mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[UI, Find Usages] IJPL-162332 Cache canNavigate for usages
Let's try to cache the values to implement canNavigate so it can be safely invoked on the EDT. This should fix the slow ops in next / prev occurrence. There's a risk of performance regressions, though, because now this value will be precomputed for all nodes, and there can easily be thousands of them. GitOrigin-RevId: 068f3f99c600024aea1aab9b5eba7e140ca951e3
This commit is contained in:
committed by
intellij-monorepo-bot
parent
8a585321a9
commit
4b442cc6c9
@@ -5,7 +5,7 @@ c:com.intellij.usages.impl.GroupNode
|
||||
- com.intellij.pom.Navigatable
|
||||
- java.lang.Comparable
|
||||
- javax.swing.tree.DefaultMutableTreeNode
|
||||
- canNavigate():Z
|
||||
- p:canDataNavigate(Z):Z
|
||||
- canNavigateToSource():Z
|
||||
- compareTo(com.intellij.usages.impl.GroupNode):I
|
||||
- getGroup():com.intellij.usages.UsageGroup
|
||||
@@ -52,7 +52,7 @@ c:com.intellij.usages.impl.UsageNode
|
||||
- java.lang.Comparable
|
||||
- javax.swing.tree.DefaultMutableTreeNode
|
||||
- <init>(com.intellij.usages.Usage):V
|
||||
- canNavigate():Z
|
||||
- p:canDataNavigate(Z):Z
|
||||
- canNavigateToSource():Z
|
||||
- compareTo(com.intellij.usages.impl.UsageNode):I
|
||||
- p:getNodeText():java.lang.String
|
||||
|
||||
@@ -342,7 +342,7 @@ public class GroupNode extends Node implements Navigatable, Comparable<GroupNode
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canNavigate() {
|
||||
protected boolean canDataNavigate(boolean isDataValid) {
|
||||
return getGroup() != null && getGroup().canNavigate();
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ public abstract class Node extends DefaultMutableTreeNode {
|
||||
static final byte EXCLUDED_MASK = 1 << 3;
|
||||
private static final byte UPDATED_MASK = 1 << 4;
|
||||
private static final byte FORCE_UPDATE_REQUESTED_MASK = 1 << 5;
|
||||
private static final byte CACHED_CAN_NAVIGATE = 1 << 6;
|
||||
|
||||
@MagicConstant(intValues = {
|
||||
CACHED_INVALID_MASK,
|
||||
@@ -35,6 +36,7 @@ public abstract class Node extends DefaultMutableTreeNode {
|
||||
EXCLUDED_MASK,
|
||||
UPDATED_MASK,
|
||||
FORCE_UPDATE_REQUESTED_MASK,
|
||||
CACHED_CAN_NAVIGATE,
|
||||
})
|
||||
private @interface FlagConstant {
|
||||
}
|
||||
@@ -61,6 +63,8 @@ public abstract class Node extends DefaultMutableTreeNode {
|
||||
|
||||
protected abstract boolean isDataExcluded();
|
||||
|
||||
protected abstract boolean canDataNavigate(boolean isDataValid);
|
||||
|
||||
@ApiStatus.Internal
|
||||
public @Nullable UsageNodePresentation getCachedPresentation() {
|
||||
return null;
|
||||
@@ -74,6 +78,10 @@ public abstract class Node extends DefaultMutableTreeNode {
|
||||
return !isFlagSet(CACHED_INVALID_MASK);
|
||||
}
|
||||
|
||||
public final boolean canNavigate() {
|
||||
return isFlagSet(CACHED_CAN_NAVIGATE);
|
||||
}
|
||||
|
||||
final boolean isReadOnly() {
|
||||
boolean result;
|
||||
boolean computed = isFlagSet(READ_ONLY_COMPUTED_MASK);
|
||||
@@ -98,24 +106,30 @@ public abstract class Node extends DefaultMutableTreeNode {
|
||||
ApplicationManager.getApplication().assertIsNonDispatchThread();
|
||||
boolean isDataValid = isDataValid();
|
||||
boolean isReadOnly = isDataReadOnly();
|
||||
// pass isDataValid here to avoid recomputing it inside
|
||||
boolean canNavigate = canDataNavigate(isDataValid);
|
||||
String text = getNodeText();
|
||||
updateCachedPresentation();
|
||||
doUpdate(isDataValid, isReadOnly, text, edtFireTreeNodesChangedQueue);
|
||||
doUpdate(isDataValid, isReadOnly, canNavigate, text, edtFireTreeNodesChangedQueue);
|
||||
}
|
||||
|
||||
private synchronized void doUpdate(boolean isDataValid,
|
||||
boolean isReadOnly,
|
||||
boolean canNavigate,
|
||||
@NotNull String text,
|
||||
@NotNull Consumer<? super Node> edtFireTreeNodesChangedQueue) {
|
||||
boolean cachedValid = isValid();
|
||||
boolean cachedReadOnly = isFlagSet(CACHED_READ_ONLY_MASK);
|
||||
boolean cachedCanNavigate = canNavigate();
|
||||
|
||||
if (isDataValid != cachedValid ||
|
||||
isReadOnly != cachedReadOnly ||
|
||||
myCachedTextHash != text.hashCode() ||
|
||||
canNavigate != cachedCanNavigate ||
|
||||
isFlagSet(FORCE_UPDATE_REQUESTED_MASK)) {
|
||||
setFlag(CACHED_INVALID_MASK, !isDataValid);
|
||||
setFlag(CACHED_READ_ONLY_MASK, isReadOnly);
|
||||
setFlag(CACHED_CAN_NAVIGATE, canNavigate);
|
||||
setFlag(FORCE_UPDATE_REQUESTED_MASK, false);
|
||||
|
||||
myCachedTextHash = text.hashCode();
|
||||
|
||||
@@ -39,8 +39,8 @@ public class UsageNode extends Node implements Comparable<UsageNode>, Navigatabl
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canNavigate() {
|
||||
return getUsage().isValid() && getUsage().canNavigate();
|
||||
protected boolean canDataNavigate(boolean isDataValid) {
|
||||
return isDataValid && getUsage().canNavigate();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,6 +25,11 @@ class UsageTargetNode extends Node {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canDataNavigate(boolean isDataValid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull String getNodeText() {
|
||||
return ObjectUtils.notNull(getTarget().getPresentation().getPresentableText(), "");
|
||||
|
||||
@@ -1902,8 +1902,11 @@ public class UsageViewImpl implements UsageViewEx {
|
||||
}
|
||||
|
||||
private @Nullable Navigatable getNavigatableForNode(@NotNull DefaultMutableTreeNode node, boolean allowRequestFocus) {
|
||||
Object userObject = node.getUserObject();
|
||||
if (userObject instanceof Navigatable navigatable) {
|
||||
Object maybeNavigatable = node;
|
||||
if (!(maybeNavigatable instanceof Navigatable)) {
|
||||
maybeNavigatable = node.getUserObject();
|
||||
}
|
||||
if (maybeNavigatable instanceof Navigatable navigatable) {
|
||||
return navigatable.canNavigate() ? new Navigatable() {
|
||||
@Override
|
||||
public void navigate(boolean requestFocus) {
|
||||
@@ -1939,9 +1942,7 @@ public class UsageViewImpl implements UsageViewEx {
|
||||
protected Navigatable createDescriptorForNode(@NotNull DefaultMutableTreeNode node) {
|
||||
if (node.getChildCount() > 0) return null;
|
||||
if (node instanceof Node n && n.isExcluded()) return null;
|
||||
try (AccessToken ignore = SlowOperations.knownIssue("IJPL-162332")) {
|
||||
return getNavigatableForNode(node, !myPresentation.isReplaceMode());
|
||||
}
|
||||
return getNavigatableForNode(node, !myPresentation.isReplaceMode());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -53,6 +53,11 @@ final class UsageViewTreeModelBuilder extends DefaultTreeModel {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canDataNavigate(boolean isDataValid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull String getNodeText() {
|
||||
return getUserObject().toString();
|
||||
|
||||
Reference in New Issue
Block a user