mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
more responsive find usages: group usages outside EDT
This commit is contained in:
+7
-1
@@ -22,6 +22,7 @@ import com.intellij.testFramework.LightPlatformTestCase;
|
||||
import com.intellij.usages.*;
|
||||
import com.intellij.usages.rules.UsageFilteringRule;
|
||||
import com.intellij.usages.rules.UsageGroupingRule;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -90,7 +91,12 @@ public class UsageNodeTreeBuilderTest extends LightPlatformTestCase {
|
||||
model.setRoot(rootNode);
|
||||
UsageNodeTreeBuilder usageNodeTreeBuilder = new UsageNodeTreeBuilder(UsageTarget.EMPTY_ARRAY, rules, UsageFilteringRule.EMPTY_ARRAY, rootNode);
|
||||
for (Usage usage : usages) {
|
||||
usageNodeTreeBuilder.appendUsage(usage);
|
||||
usageNodeTreeBuilder.appendUsage(usage, new Consumer<Runnable>() {
|
||||
@Override
|
||||
public void consume(Runnable runnable) {
|
||||
runnable.run();
|
||||
}
|
||||
});
|
||||
UIUtil.dispatchAllInvocationEvents();
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import com.intellij.usages.UsageGroup;
|
||||
import com.intellij.usages.UsageView;
|
||||
import com.intellij.usages.UsageViewSettings;
|
||||
import com.intellij.usages.rules.MergeableUsage;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -62,22 +62,22 @@ public class GroupNode extends Node implements Navigatable, Comparable<GroupNode
|
||||
return children == null ? result : result + children.toString();
|
||||
}
|
||||
|
||||
public GroupNode addGroup(@NotNull UsageGroup group, int ruleIndex) {
|
||||
public GroupNode addGroup(@NotNull UsageGroup group, int ruleIndex, Consumer<Runnable> edtQueue) {
|
||||
synchronized (lock) {
|
||||
GroupNode node = mySubgroupNodes.get(group);
|
||||
if (node == null) {
|
||||
final GroupNode node1 = node = new GroupNode(group, ruleIndex, getBuilder());
|
||||
mySubgroupNodes.put(group, node);
|
||||
|
||||
addNode(node1);
|
||||
addNode(node1, edtQueue);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
void addNode(@NotNull final DefaultMutableTreeNode node) {
|
||||
void addNode(@NotNull final DefaultMutableTreeNode node, @NotNull Consumer<Runnable> edtQueue) {
|
||||
if (!getBuilder().isDetachedMode()) {
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
edtQueue.consume(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myTreeModel.insertNodeInto(node, GroupNode.this, getNodeInsertionIndex(node));
|
||||
@@ -102,7 +102,7 @@ public class GroupNode extends Node implements Navigatable, Comparable<GroupNode
|
||||
myTreeModel.reload(this);
|
||||
}
|
||||
|
||||
private UsageNode tryMerge(@NotNull Usage usage) {
|
||||
@Nullable UsageNode tryMerge(@NotNull Usage usage) {
|
||||
if (!(usage instanceof MergeableUsage)) return null;
|
||||
MergeableUsage mergeableUsage = (MergeableUsage)usage;
|
||||
for (UsageNode node : myUsageNodes) {
|
||||
@@ -154,7 +154,7 @@ public class GroupNode extends Node implements Navigatable, Comparable<GroupNode
|
||||
myTreeModel.nodeChanged(this);
|
||||
}
|
||||
|
||||
public UsageNode addUsage(@NotNull Usage usage) {
|
||||
public UsageNode addUsage(@NotNull Usage usage, Consumer<Runnable> edtQueue) {
|
||||
final UsageNode node;
|
||||
synchronized (lock) {
|
||||
if (UsageViewSettings.getInstance().isFilterDuplicatedLine()) {
|
||||
@@ -168,7 +168,7 @@ public class GroupNode extends Node implements Navigatable, Comparable<GroupNode
|
||||
}
|
||||
|
||||
if (!getBuilder().isDetachedMode()) {
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
edtQueue.consume(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myTreeModel.insertNodeInto(node, GroupNode.this, getNodeIndex(node));
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.usages.rules.UsageFilteringRule;
|
||||
import com.intellij.usages.rules.UsageFilteringRuleEx;
|
||||
import com.intellij.usages.rules.UsageGroupingRule;
|
||||
import com.intellij.usages.rules.UsageGroupingRuleEx;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -69,7 +70,7 @@ class UsageNodeTreeBuilder {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
UsageNode appendUsage(@NotNull Usage usage) {
|
||||
UsageNode appendUsage(@NotNull Usage usage, Consumer<Runnable> edtQueue) {
|
||||
if (!isVisible(usage)) return null;
|
||||
|
||||
GroupNode lastGroupNode = myRoot;
|
||||
@@ -83,10 +84,10 @@ class UsageNodeTreeBuilder {
|
||||
group = rule.groupUsage(usage);
|
||||
}
|
||||
if (group != null) {
|
||||
lastGroupNode = lastGroupNode.addGroup(group, i);
|
||||
lastGroupNode = lastGroupNode.addGroup(group, i, edtQueue);
|
||||
}
|
||||
}
|
||||
|
||||
return lastGroupNode.addUsage(usage);
|
||||
return lastGroupNode.addUsage(usage, edtQueue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ import com.intellij.openapi.ui.SimpleToolWindowPanel;
|
||||
import com.intellij.openapi.ui.Splitter;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.vfs.ReadonlyStatusHandler;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.Navigatable;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
@@ -47,6 +47,7 @@ import com.intellij.usageView.UsageViewManager;
|
||||
import com.intellij.usages.*;
|
||||
import com.intellij.usages.rules.*;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.EditSourceOnDoubleClickHandler;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -237,10 +238,10 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra
|
||||
}
|
||||
});
|
||||
}
|
||||
myTransferToEDTQueue = new TransferToEDTQueue<Usage>("Insert usages", new Processor<Usage>() {
|
||||
myTransferToEDTQueue = new TransferToEDTQueue<Runnable>("Insert usages", new Processor<Runnable>() {
|
||||
@Override
|
||||
public boolean process(Usage usage) {
|
||||
appendUsage(usage);
|
||||
public boolean process(Runnable runnable) {
|
||||
runnable.run();
|
||||
return true;
|
||||
}
|
||||
}, new Condition<Object>() {
|
||||
@@ -672,7 +673,7 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra
|
||||
if (usageCount > UsageLimitUtil.USAGES_LIMIT && tooManyUsages.get() == 0 && tooManyUsages.compareAndSet(0, 1)) {
|
||||
((UsageViewManagerImpl)usageViewManager).showTooManyUsagesWarning(indicator, waitWhileUserClick, usageCountWithoutDefinition.get());
|
||||
}
|
||||
appendUsageLater(usage);
|
||||
appendUsage(usage);
|
||||
}
|
||||
ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
|
||||
return indicator == null || !indicator.isCanceled();
|
||||
@@ -699,10 +700,7 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra
|
||||
}
|
||||
}
|
||||
|
||||
private final TransferToEDTQueue<Usage> myTransferToEDTQueue;
|
||||
public void appendUsageLater(@NotNull Usage usage) {
|
||||
myTransferToEDTQueue.offer(usage);
|
||||
}
|
||||
private final TransferToEDTQueue<Runnable> myTransferToEDTQueue;
|
||||
public void drainQueuedUsageNodes() {
|
||||
assert !ApplicationManager.getApplication().isDispatchThread() : Thread.currentThread();
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@@ -718,6 +716,7 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra
|
||||
doAppendUsage(usage);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public UsageNode doAppendUsage(@NotNull Usage usage) {
|
||||
// invoke in ReadAction to be be sure that usages are not invalidated while the tree is being built
|
||||
ApplicationManager.getApplication().assertReadAccessAllowed();
|
||||
@@ -725,7 +724,12 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra
|
||||
// because the view is built incrementally, the usage may be already invalid, so need to filter such cases
|
||||
return null;
|
||||
}
|
||||
UsageNode node = myBuilder.appendUsage(usage);
|
||||
UsageNode node = myBuilder.appendUsage(usage, new Consumer<Runnable>() {
|
||||
@Override
|
||||
public void consume(Runnable runnable) {
|
||||
myTransferToEDTQueue.offer(runnable);
|
||||
}
|
||||
});
|
||||
myUsageNodes.put(usage, node == null ? NULL_NODE : node);
|
||||
return node;
|
||||
}
|
||||
@@ -934,7 +938,7 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra
|
||||
final Set<VirtualFile> readOnlyUsages = getReadOnlyUsagesFiles();
|
||||
|
||||
return readOnlyUsages.isEmpty() ||
|
||||
!ReadonlyStatusHandler.getInstance(myProject).ensureFilesWritable(VfsUtil.toVirtualFileArray(readOnlyUsages)).hasReadonlyFiles();
|
||||
!ReadonlyStatusHandler.getInstance(myProject).ensureFilesWritable(VfsUtilCore.toVirtualFileArray(readOnlyUsages)).hasReadonlyFiles();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -282,7 +282,7 @@ public class UsageViewManagerImpl extends UsageViewManager {
|
||||
openView(usageView);
|
||||
Usage firstUsage = myFirstUsage.get();
|
||||
if (firstUsage != null) {
|
||||
usageView.appendUsageLater(firstUsage);
|
||||
usageView.appendUsage(firstUsage);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -308,8 +308,10 @@ public class UsageViewManagerImpl extends UsageViewManager {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
//long start = System.currentTimeMillis();
|
||||
searchUsages();
|
||||
endSearchForUsages();
|
||||
//System.out.println("Usage search took " + (System.currentTimeMillis() - start));
|
||||
}
|
||||
|
||||
private void searchUsages() {
|
||||
@@ -342,7 +344,7 @@ public class UsageViewManagerImpl extends UsageViewManager {
|
||||
}
|
||||
UsageViewImpl usageView = getUsageView();
|
||||
if (usageView != null) {
|
||||
usageView.appendUsageLater(usage);
|
||||
usageView.appendUsage(usage);
|
||||
}
|
||||
}
|
||||
return indicator == null || !indicator.isCanceled();
|
||||
|
||||
@@ -17,6 +17,8 @@ package com.intellij.usages.impl;
|
||||
|
||||
import com.intellij.usages.UsageTarget;
|
||||
import com.intellij.usages.UsageViewPresentation;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
@@ -66,7 +68,12 @@ public class UsageViewTreeModelBuilder extends DefaultTreeModel {
|
||||
myTargetsNode.add(targetNode);
|
||||
myTargetNodes[i] = targetNode;
|
||||
}
|
||||
myRootNode.addNode(myTargetsNode);
|
||||
myRootNode.addNode(myTargetsNode, new Consumer<Runnable>() {
|
||||
@Override
|
||||
public void consume(Runnable runnable) {
|
||||
UIUtil.invokeLaterIfNeeded(runnable);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public UsageNode getFirstUsageNode() {
|
||||
|
||||
Reference in New Issue
Block a user