mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-08 15:09:39 +07:00
inspection tool window: do not update tree in EDT (offline inspection view freeze). not polished
This commit is contained in:
@@ -54,7 +54,7 @@ public class OfflineIRVTest extends TestSourceBasedTestCase {
|
||||
private LocalInspectionToolWrapper myToolWrapper;
|
||||
|
||||
private static String varMessage(String name) {
|
||||
return InspectionsBundle.message("inspection.unused.assignment.problem.descriptor1", "<code>"+name+"</code>") + ".";
|
||||
return InspectionsBundle.message("inspection.unused.assignment.problem.descriptor1", "'" + name + "'");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -146,7 +146,7 @@ public class OfflineIRVTest extends TestSourceBasedTestCase {
|
||||
+ " -f()\n"
|
||||
+ " -D\n"
|
||||
+ " -b()\n"
|
||||
+ " " + InspectionsBundle.message("inspection.unused.assignment.problem.descriptor1", "'" + "r" + "'") + "\n"
|
||||
+ " " + varMessage("r") + "\n"
|
||||
+ " -anonymous (java.lang.Runnable)\n"
|
||||
+ " -run()\n"
|
||||
+ " " + varMessage("i") + "\n"
|
||||
|
||||
@@ -23,9 +23,12 @@ package com.intellij.codeInspection.offline;
|
||||
import com.intellij.codeInspection.reference.RefElement;
|
||||
import com.intellij.codeInspection.reference.RefManager;
|
||||
import com.intellij.codeInspection.reference.RefEntity;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -112,7 +115,7 @@ public class OfflineProblemDescriptor {
|
||||
if (refElement instanceof RefElement) {
|
||||
final PsiElement element = ((RefElement)refElement).getElement();
|
||||
if (element != null && element.isValid()) {
|
||||
PsiDocumentManager.getInstance(element.getProject()).commitAllDocuments();
|
||||
UIUtil.invokeLaterIfNeeded(() -> PsiDocumentManager.getInstance(element.getProject()).commitAllDocuments());
|
||||
}
|
||||
}
|
||||
return refElement;
|
||||
@@ -178,6 +181,10 @@ public class OfflineProblemDescriptor {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myDescription;
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
return myFQName;
|
||||
} else {
|
||||
return myDescription;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,7 +225,9 @@ public class ViewOfflineResultsAction extends AnAction {
|
||||
final InspectionResultsView view = new InspectionResultsView(context,
|
||||
new OfflineInspectionRVContentProvider(resMap, project));
|
||||
((RefManagerImpl)context.getRefManager()).startOfflineView();
|
||||
view.update();
|
||||
ApplicationManager.getApplication().executeOnPooledThread(() -> {
|
||||
ApplicationManager.getApplication().runReadAction((Runnable)view::buildTree);
|
||||
});
|
||||
TreeUtil.selectFirstNode(view.getTree());
|
||||
context.addView(view, title);
|
||||
return view;
|
||||
|
||||
@@ -125,6 +125,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
|
||||
});
|
||||
|
||||
myView = view;
|
||||
myView.getTree().setPaintBusy(true);
|
||||
myContent = ContentFactory.SERVICE.getInstance().createContent(view, title, false);
|
||||
|
||||
myContent.setDisposer(myView);
|
||||
@@ -353,6 +354,9 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
|
||||
else if (view != null) {
|
||||
addView(view);
|
||||
}
|
||||
if (myView != null) {
|
||||
myView.getTree().setPaintBusy(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
package com.intellij.codeInspection.ex;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.intellij.codeInspection.CommonProblemDescriptor;
|
||||
import com.intellij.codeInspection.QuickFix;
|
||||
import com.intellij.codeInspection.reference.RefEntity;
|
||||
@@ -31,6 +32,7 @@ import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -40,6 +42,7 @@ import javax.swing.tree.MutableTreeNode;
|
||||
import javax.swing.tree.TreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public abstract class InspectionRVContentProvider {
|
||||
private static final Logger LOG = Logger.getInstance("#" + InspectionRVContentProvider.class.getName());
|
||||
@@ -121,22 +124,23 @@ public abstract class InspectionRVContentProvider {
|
||||
protected abstract void appendDescriptor(@NotNull GlobalInspectionContextImpl context,
|
||||
@NotNull InspectionToolWrapper toolWrapper,
|
||||
@NotNull UserObjectContainer container,
|
||||
@NotNull InspectionPackageNode pNode,
|
||||
@NotNull InspectionTreeNode pNode,
|
||||
final boolean canPackageRepeat);
|
||||
|
||||
public boolean isContentLoaded() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected <T> List<InspectionTreeNode> buildTree(@NotNull GlobalInspectionContextImpl context,
|
||||
@NotNull Map<String, Set<T>> packageContents,
|
||||
final boolean canPackageRepeat,
|
||||
@NotNull InspectionToolWrapper toolWrapper,
|
||||
@NotNull Function<T, UserObjectContainer<T>> computeContainer,
|
||||
final boolean showStructure) {
|
||||
final List<InspectionTreeNode> content = new ArrayList<InspectionTreeNode>();
|
||||
protected <T> void buildTree(@NotNull GlobalInspectionContextImpl context,
|
||||
@NotNull Map<String, Set<T>> packageContents,
|
||||
final boolean canPackageRepeat,
|
||||
@NotNull InspectionToolWrapper toolWrapper,
|
||||
@NotNull Function<T, UserObjectContainer<T>> computeContainer,
|
||||
final boolean showStructure,
|
||||
final Consumer<InspectionTreeNode> createdNodesConsumer) {
|
||||
final Map<String, Map<String, InspectionPackageNode>> module2PackageMap = new HashMap<String, Map<String, InspectionPackageNode>>();
|
||||
boolean supportStructure = showStructure;
|
||||
final MultiMap<InspectionPackageNode, UserObjectContainer<T>> packageDescriptors = new MultiMap<>();
|
||||
for (String packageName : packageContents.keySet()) {
|
||||
final Set<T> elements = packageContents.get(packageName);
|
||||
for (T userObject : elements) {
|
||||
@@ -153,50 +157,64 @@ public abstract class InspectionRVContentProvider {
|
||||
pNode = new InspectionPackageNode(packageName);
|
||||
packageNodes.put(packageName, pNode);
|
||||
}
|
||||
appendDescriptor(context, toolWrapper, container, pNode, canPackageRepeat);
|
||||
|
||||
packageDescriptors.putValue(pNode, container);
|
||||
}
|
||||
}
|
||||
|
||||
if (supportStructure) {
|
||||
final HashMap<String, InspectionModuleNode> moduleNodes = new HashMap<String, InspectionModuleNode>();
|
||||
for (final String moduleName : module2PackageMap.keySet()) {
|
||||
final Map<String, InspectionPackageNode> packageNodes = module2PackageMap.get(moduleName);
|
||||
for (InspectionPackageNode packageNode : packageNodes.values()) {
|
||||
if (packageNode.getChildCount() > 0) {
|
||||
InspectionModuleNode moduleNode = moduleNodes.get(moduleName);
|
||||
if (moduleNode == null) {
|
||||
if (moduleName != null) {
|
||||
final Module module = ModuleManager.getInstance(myProject).findModuleByName(moduleName);
|
||||
if (module != null) {
|
||||
moduleNode = new InspectionModuleNode(module);
|
||||
moduleNodes.put(moduleName, moduleNode);
|
||||
}
|
||||
else { //module content was removed ?
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
content.addAll(packageNodes.values());
|
||||
break;
|
||||
InspectionModuleNode moduleNode = moduleNodes.get(moduleName);
|
||||
|
||||
if (moduleNode == null) {
|
||||
if (moduleName != null) {
|
||||
final Module module = ModuleManager.getInstance(myProject).findModuleByName(moduleName);
|
||||
if (module != null) {
|
||||
moduleNode = new InspectionModuleNode(module);
|
||||
moduleNodes.put(moduleName, moduleNode);
|
||||
}
|
||||
else { //module content was removed ?
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (InspectionPackageNode packageNode : packageNodes.values()) {
|
||||
createdNodesConsumer.accept(packageNode);
|
||||
for (UserObjectContainer<T> container : packageDescriptors.get(packageNode)) {
|
||||
appendDescriptor(context, toolWrapper, container, packageNode, canPackageRepeat);
|
||||
}
|
||||
}
|
||||
if (packageNode.getPackageName() != null) {
|
||||
moduleNode.add(packageNode);
|
||||
} else {
|
||||
for(int i = packageNode.getChildCount() - 1; i >= 0; i--) {
|
||||
moduleNode.add((MutableTreeNode)packageNode.getChildAt(i));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
createdNodesConsumer.accept(moduleNode);
|
||||
for (InspectionPackageNode packageNode : packageNodes.values()) {
|
||||
if (packageNode.getPackageName() != null) {
|
||||
moduleNode.add(packageNode);
|
||||
for (UserObjectContainer<T> container : packageDescriptors.get(packageNode)) {
|
||||
appendDescriptor(context, toolWrapper, container, packageNode, canPackageRepeat);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (UserObjectContainer<T> container : packageDescriptors.get(packageNode)) {
|
||||
appendDescriptor(context, toolWrapper, container, moduleNode, canPackageRepeat);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
content.addAll(moduleNodes.values());
|
||||
}
|
||||
else {
|
||||
for (Map<String, InspectionPackageNode> packageNodes : module2PackageMap.values()) {
|
||||
for (InspectionPackageNode pNode : packageNodes.values()) {
|
||||
for (UserObjectContainer<T> container : packageDescriptors.get(pNode)) {
|
||||
appendDescriptor(context, toolWrapper, container, pNode, canPackageRepeat);
|
||||
}
|
||||
for (int i = 0; i < pNode.getChildCount(); i++) {
|
||||
final TreeNode childNode = pNode.getChildAt(i);
|
||||
if (childNode instanceof ProblemDescriptionNode) {
|
||||
content.add(pNode);
|
||||
createdNodesConsumer.accept(pNode);
|
||||
break;
|
||||
}
|
||||
LOG.assertTrue(childNode instanceof RefElementNode, childNode.getClass().getName());
|
||||
@@ -216,7 +234,7 @@ public abstract class InspectionRVContentProvider {
|
||||
parentNodes.add((RefElementNode)grandChildNode);
|
||||
}
|
||||
if (!hasElementNodeUnder) {
|
||||
content.add(elementNode);
|
||||
createdNodesConsumer.accept(elementNode);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -237,12 +255,13 @@ public abstract class InspectionRVContentProvider {
|
||||
parentNode.add(node);
|
||||
}
|
||||
}
|
||||
content.addAll(parentNodes);
|
||||
for (RefElementNode node : parentNodes) {
|
||||
createdNodesConsumer.accept(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -333,19 +352,11 @@ public abstract class InspectionRVContentProvider {
|
||||
}
|
||||
|
||||
protected static void add(@Nullable final DefaultTreeModel model, final InspectionTreeNode child, final InspectionTreeNode parent) {
|
||||
if (model == null) {
|
||||
insertByIndex(child, parent);
|
||||
}
|
||||
else {
|
||||
if (parent.getIndex(child) < 0) {
|
||||
model.insertNodeInto(child, parent, child.getParent() == parent ? parent.getChildCount() - 1 : parent.getChildCount());
|
||||
}
|
||||
}
|
||||
insertByIndex(child, parent);
|
||||
}
|
||||
|
||||
private static void insertByIndex(InspectionTreeNode child, InspectionTreeNode parent) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
parent.add(child);
|
||||
public static void insertByIndex(InspectionTreeNode child, InspectionTreeNode parent) {
|
||||
if (parent.getIndex(child) != -1) {
|
||||
return;
|
||||
}
|
||||
final int i = TreeUtil.indexedBinarySearch(parent, child, InspectionResultsViewComparator.getInstance());
|
||||
|
||||
@@ -95,7 +95,6 @@ public class InspectionRVContentProviderImpl extends InspectionRVContentProvider
|
||||
@NotNull final Map<String, Set<RefEntity>> contents,
|
||||
@NotNull final Map<RefEntity, CommonProblemDescriptor[]> problems,
|
||||
DefaultTreeModel model) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
final InspectionToolWrapper toolWrapper = toolNode.getToolWrapper();
|
||||
|
||||
Function<RefEntity, UserObjectContainer<RefEntity>> computeContainer = new Function<RefEntity, UserObjectContainer<RefEntity>>() {
|
||||
@@ -114,11 +113,9 @@ public class InspectionRVContentProviderImpl extends InspectionRVContentProvider
|
||||
}
|
||||
entities.addAll(moduleProblems);
|
||||
}
|
||||
List<InspectionTreeNode> list = buildTree(context, contents, false, toolWrapper, computeContainer, showStructure);
|
||||
|
||||
for (InspectionTreeNode node : list) {
|
||||
buildTree(context, contents, false, toolWrapper, computeContainer, showStructure, node -> {
|
||||
merge(model, node, toolNode, true);
|
||||
}
|
||||
});
|
||||
|
||||
if (presentation.isOldProblemsIncluded()) {
|
||||
final Map<RefEntity, CommonProblemDescriptor[]> oldProblems = presentation.getOldProblemElements();
|
||||
@@ -129,11 +126,9 @@ public class InspectionRVContentProviderImpl extends InspectionRVContentProvider
|
||||
}
|
||||
};
|
||||
|
||||
list = buildTree(context, presentation.getOldContent(), true, toolWrapper, computeContainer, showStructure);
|
||||
|
||||
for (InspectionTreeNode node : list) {
|
||||
buildTree(context, presentation.getOldContent(), true, toolWrapper, computeContainer, showStructure, node -> {
|
||||
merge(model, node, toolNode, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
merge(model, toolNode, parentNode, false);
|
||||
}
|
||||
@@ -142,7 +137,7 @@ public class InspectionRVContentProviderImpl extends InspectionRVContentProvider
|
||||
protected void appendDescriptor(@NotNull GlobalInspectionContextImpl context,
|
||||
@NotNull final InspectionToolWrapper toolWrapper,
|
||||
@NotNull final UserObjectContainer container,
|
||||
@NotNull final InspectionPackageNode pNode,
|
||||
@NotNull final InspectionTreeNode pNode,
|
||||
final boolean canPackageRepeat) {
|
||||
final RefElementContainer refElementDescriptor = (RefElementContainer)container;
|
||||
final RefEntity refElement = refElementDescriptor.getUserObject();
|
||||
@@ -163,8 +158,8 @@ public class InspectionRVContentProviderImpl extends InspectionRVContentProvider
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (canPackageRepeat) {
|
||||
final Set<RefEntity> currentElements = presentation.getContent().get(pNode.getPackageName());
|
||||
if (canPackageRepeat && pNode instanceof InspectionPackageNode) {
|
||||
final Set<RefEntity> currentElements = presentation.getContent().get(((InspectionPackageNode) pNode).getPackageName());
|
||||
if (currentElements != null) {
|
||||
final Set<RefEntity> currentEntities = new HashSet<RefEntity>(currentElements);
|
||||
if (RefUtil.contains(refElement, currentEntities)) return;
|
||||
|
||||
@@ -125,11 +125,8 @@ public class OfflineInspectionRVContentProvider extends InspectionRVContentProvi
|
||||
return new OfflineProblemDescriptorContainer(descriptor);
|
||||
}
|
||||
};
|
||||
final List<InspectionTreeNode> list = buildTree(context, filteredContent, false, toolWrapper, computeContainer, showStructure);
|
||||
for (InspectionTreeNode node : list) {
|
||||
toolNode.add(node);
|
||||
}
|
||||
parentNode.add(toolNode);
|
||||
buildTree(context, filteredContent, false, toolWrapper, computeContainer, showStructure, toolNode::add);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,13 +172,15 @@ public class OfflineInspectionRVContentProvider extends InspectionRVContentProvi
|
||||
protected void appendDescriptor(@NotNull GlobalInspectionContextImpl context,
|
||||
@NotNull final InspectionToolWrapper toolWrapper,
|
||||
@NotNull final UserObjectContainer container,
|
||||
@NotNull final InspectionPackageNode packageNode,
|
||||
@NotNull final InspectionTreeNode packageNode,
|
||||
final boolean canPackageRepeat) {
|
||||
InspectionToolPresentation presentation = context.getPresentation(toolWrapper);
|
||||
final RefElementNode elemNode = addNodeToParent(container, presentation, packageNode);
|
||||
if (toolWrapper instanceof LocalInspectionToolWrapper) {
|
||||
elemNode.add(new OfflineProblemDescriptorNode(((OfflineProblemDescriptorContainer)container).getUserObject(),
|
||||
(LocalInspectionToolWrapper)toolWrapper, presentation));
|
||||
final OfflineProblemDescriptorNode child =
|
||||
OfflineProblemDescriptorNode.create(((OfflineProblemDescriptorContainer)container).getUserObject(),
|
||||
(LocalInspectionToolWrapper)toolWrapper, presentation);
|
||||
insertByIndex(child, elemNode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,10 +47,33 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class OfflineProblemDescriptorNode extends ProblemDescriptionNode {
|
||||
OfflineProblemDescriptorNode(@NotNull OfflineProblemDescriptor descriptor,
|
||||
OfflineProblemDescriptorNode(RefEntity refEntity,
|
||||
CommonProblemDescriptor descriptor,
|
||||
@NotNull LocalInspectionToolWrapper toolWrapper,
|
||||
@NotNull InspectionToolPresentation presentation) {
|
||||
super(descriptor, toolWrapper, presentation);
|
||||
@NotNull InspectionToolPresentation presentation,
|
||||
OfflineProblemDescriptor offlineDescriptor) {
|
||||
super(refEntity, descriptor, toolWrapper, presentation);
|
||||
if (descriptor == null) {
|
||||
setUserObject(offlineDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
static OfflineProblemDescriptorNode create(@NotNull OfflineProblemDescriptor offlineDescriptor,
|
||||
@NotNull LocalInspectionToolWrapper toolWrapper,
|
||||
@NotNull InspectionToolPresentation presentation) {
|
||||
final RefEntity refElement = createRefElement(offlineDescriptor, presentation);
|
||||
final CommonProblemDescriptor descriptor = createDescriptor(refElement, offlineDescriptor, toolWrapper, presentation);
|
||||
return new OfflineProblemDescriptorNode(refElement, descriptor, toolWrapper, presentation, offlineDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileStatus getNodeStatus() {
|
||||
return FileStatus.NOT_CHANGED;
|
||||
}
|
||||
|
||||
private static PsiElement[] getElementsIntersectingRange(PsiFile file, final int startOffset, final int endOffset) {
|
||||
@@ -65,77 +88,49 @@ public class OfflineProblemDescriptorNode extends ProblemDescriptionNode {
|
||||
return PsiUtilCore.toPsiElementArray(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public RefEntity getElement() {
|
||||
if (userObject instanceof CommonProblemDescriptor) {
|
||||
return myElement;
|
||||
}
|
||||
if (userObject == null) {
|
||||
return null;
|
||||
}
|
||||
myElement = ((OfflineProblemDescriptor)userObject).getRefElement(myPresentation.getContext().getRefManager());
|
||||
return myElement;
|
||||
private static RefEntity createRefElement(OfflineProblemDescriptor descriptor, InspectionToolPresentation presentation) {
|
||||
return descriptor.getRefElement(presentation.getContext().getRefManager());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public CommonProblemDescriptor getDescriptor() {
|
||||
if (userObject == null) return null;
|
||||
if (userObject instanceof CommonProblemDescriptor) {
|
||||
return (CommonProblemDescriptor)userObject;
|
||||
}
|
||||
private static CommonProblemDescriptor createDescriptor(@Nullable RefEntity element,
|
||||
@NotNull OfflineProblemDescriptor offlineDescriptor,
|
||||
@NotNull LocalInspectionToolWrapper toolWrapper,
|
||||
@NotNull InspectionToolPresentation presentation) {
|
||||
|
||||
final InspectionManager inspectionManager = InspectionManager.getInstance(myPresentation.getContext().getProject());
|
||||
final OfflineProblemDescriptor offlineProblemDescriptor = (OfflineProblemDescriptor)userObject;
|
||||
final RefEntity element = getElement();
|
||||
if (myToolWrapper instanceof LocalInspectionToolWrapper) {
|
||||
if (element instanceof RefElement) {
|
||||
final PsiElement psiElement = ((RefElement)element).getElement();
|
||||
if (psiElement != null) {
|
||||
ProblemDescriptor descriptor = ProgressManager.getInstance().runProcess(new Computable<ProblemDescriptor>() {
|
||||
@Override
|
||||
public ProblemDescriptor compute() {
|
||||
return runLocalTool(psiElement, inspectionManager, offlineProblemDescriptor);
|
||||
}
|
||||
}, new DaemonProgressIndicator());
|
||||
if (descriptor != null) return descriptor;
|
||||
}
|
||||
final InspectionManager inspectionManager = InspectionManager.getInstance(presentation.getContext().getProject());
|
||||
final OfflineProblemDescriptor offlineProblemDescriptor = offlineDescriptor;
|
||||
if (element instanceof RefElement) {
|
||||
final PsiElement psiElement = ((RefElement)element).getElement();
|
||||
if (psiElement != null) {
|
||||
ProblemDescriptor descriptor = ProgressManager.getInstance().runProcess(new Computable<ProblemDescriptor>() {
|
||||
@Override
|
||||
public ProblemDescriptor compute() {
|
||||
return runLocalTool(psiElement, inspectionManager, offlineProblemDescriptor, toolWrapper);
|
||||
}
|
||||
}, new DaemonProgressIndicator());
|
||||
if (descriptor != null) return descriptor;
|
||||
}
|
||||
setUserObject(null);
|
||||
return null;
|
||||
}
|
||||
final List<String> hints = offlineProblemDescriptor.getHints();
|
||||
if (element instanceof RefElement) {
|
||||
final PsiElement psiElement = ((RefElement)element).getElement();
|
||||
if (psiElement == null) return null;
|
||||
ProblemDescriptor descriptor = inspectionManager.createProblemDescriptor(psiElement, offlineProblemDescriptor.getDescription(),
|
||||
(LocalQuickFix)null,
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false);
|
||||
final LocalQuickFix[] quickFixes = getFixes(descriptor, hints);
|
||||
if (quickFixes != null) {
|
||||
descriptor = inspectionManager.createProblemDescriptor(psiElement, offlineProblemDescriptor.getDescription(), false, quickFixes,
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
|
||||
}
|
||||
setUserObject(descriptor);
|
||||
return descriptor;
|
||||
}
|
||||
CommonProblemDescriptor descriptor =
|
||||
inspectionManager.createProblemDescriptor(offlineProblemDescriptor.getDescription(), (QuickFix)null);
|
||||
final QuickFix[] quickFixes = getFixes(descriptor, hints);
|
||||
final QuickFix[] quickFixes = getFixes(descriptor, hints, presentation);
|
||||
if (quickFixes != null) {
|
||||
descriptor = inspectionManager.createProblemDescriptor(offlineProblemDescriptor.getDescription(), quickFixes);
|
||||
}
|
||||
setUserObject(descriptor);
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
private ProblemDescriptor runLocalTool(@NotNull PsiElement psiElement,
|
||||
@NotNull InspectionManager inspectionManager,
|
||||
@NotNull OfflineProblemDescriptor offlineProblemDescriptor) {
|
||||
private static ProblemDescriptor runLocalTool(@NotNull PsiElement psiElement,
|
||||
@NotNull InspectionManager inspectionManager,
|
||||
@NotNull OfflineProblemDescriptor offlineProblemDescriptor,
|
||||
@NotNull LocalInspectionToolWrapper toolWrapper) {
|
||||
PsiFile containingFile = psiElement.getContainingFile();
|
||||
final ProblemsHolder holder = new ProblemsHolder(inspectionManager, containingFile, false);
|
||||
final LocalInspectionTool localTool = ((LocalInspectionToolWrapper)myToolWrapper).getTool();
|
||||
final LocalInspectionTool localTool = toolWrapper.getTool();
|
||||
final int startOffset = psiElement.getTextRange().getStartOffset();
|
||||
final int endOffset = psiElement.getTextRange().getEndOffset();
|
||||
LocalInspectionToolSession session = new LocalInspectionToolSession(containingFile, startOffset, endOffset);
|
||||
@@ -154,7 +149,6 @@ public class OfflineProblemDescriptorNode extends ProblemDescriptionNode {
|
||||
final PsiNamedElement member = localTool.getProblemElement(descriptor.getPsiElement());
|
||||
if (psiElement instanceof PsiFile || member != null && member.equals(psiElement)) {
|
||||
if (curIdx == idx) {
|
||||
setUserObject(descriptor);
|
||||
return descriptor;
|
||||
}
|
||||
curIdx++;
|
||||
@@ -166,40 +160,24 @@ public class OfflineProblemDescriptorNode extends ProblemDescriptionNode {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private LocalQuickFix[] getFixes(@NotNull CommonProblemDescriptor descriptor, List<String> hints) {
|
||||
private static LocalQuickFix[] getFixes(@NotNull CommonProblemDescriptor descriptor, List<String> hints, InspectionToolPresentation presentation) {
|
||||
final List<LocalQuickFix> fixes = new ArrayList<LocalQuickFix>(hints == null ? 1 : hints.size());
|
||||
if (hints == null) {
|
||||
addFix(descriptor, fixes, null);
|
||||
addFix(descriptor, fixes, null, presentation);
|
||||
}
|
||||
else {
|
||||
for (String hint : hints) {
|
||||
addFix(descriptor, fixes, hint);
|
||||
addFix(descriptor, fixes, hint, presentation);
|
||||
}
|
||||
}
|
||||
return fixes.isEmpty() ? null : fixes.toArray(new LocalQuickFix[fixes.size()]);
|
||||
}
|
||||
|
||||
private void addFix(@NotNull CommonProblemDescriptor descriptor, final List<LocalQuickFix> fixes, String hint) {
|
||||
final IntentionAction intentionAction = myPresentation.findQuickFixes(descriptor, hint);
|
||||
private static void addFix(@NotNull CommonProblemDescriptor descriptor, final List<LocalQuickFix> fixes, String hint, InspectionToolPresentation presentation) {
|
||||
final IntentionAction intentionAction = presentation.findQuickFixes(descriptor, hint);
|
||||
if (intentionAction instanceof QuickFixWrapper) {
|
||||
fixes.add(((QuickFixWrapper)intentionAction).getFix());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileStatus getNodeStatus() {
|
||||
return FileStatus.NOT_CHANGED;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (userObject instanceof OfflineProblemDescriptor) {
|
||||
return ((OfflineProblemDescriptor)userObject).getDescription();
|
||||
}
|
||||
return super.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,27 +28,17 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class OfflineRefElementNode extends RefElementNode {
|
||||
private final RefEntity myElement;
|
||||
|
||||
public OfflineRefElementNode(@NotNull OfflineProblemDescriptor descriptor, @NotNull InspectionToolPresentation presentation) {
|
||||
super(descriptor, presentation);
|
||||
myElement = descriptor.getRefElement(presentation.getContext().getRefManager());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public RefEntity getElement() {
|
||||
if (userObject instanceof RefEntity) {
|
||||
return (RefEntity)userObject;
|
||||
}
|
||||
if (userObject == null) return null;
|
||||
final RefEntity refElement = ((OfflineProblemDescriptor)userObject).getRefElement(myToolPresentation.getContext().getRefManager());
|
||||
setUserObject(refElement);
|
||||
return refElement;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public OfflineProblemDescriptor getDescriptor() {
|
||||
if (userObject instanceof OfflineProblemDescriptor) {
|
||||
return (OfflineProblemDescriptor)userObject;
|
||||
}
|
||||
return null;
|
||||
setUserObject(myElement);
|
||||
return myElement;
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import com.intellij.codeInspection.*;
|
||||
import com.intellij.codeInspection.ex.*;
|
||||
import com.intellij.codeInspection.reference.*;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.PathMacroManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
@@ -78,8 +79,6 @@ public class DefaultInspectionToolPresentation implements ProblemDescriptionsPro
|
||||
protected static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.DescriptorProviderInspection");
|
||||
private boolean isDisposed;
|
||||
|
||||
private final Object myToolLock = new Object();
|
||||
|
||||
public DefaultInspectionToolPresentation(@NotNull InspectionToolWrapper toolWrapper, @NotNull GlobalInspectionContextImpl context) {
|
||||
myToolWrapper = toolWrapper;
|
||||
myContext = context;
|
||||
@@ -237,33 +236,33 @@ public class DefaultInspectionToolPresentation implements ProblemDescriptionsPro
|
||||
context.addView(view);
|
||||
}
|
||||
if (!isDisposed()) {
|
||||
final InspectionNode toolNode;
|
||||
synchronized (myToolLock) {
|
||||
if (myToolNode == null) {
|
||||
final HighlightSeverity currentSeverity = getSeverity((RefElement)refElement);
|
||||
toolNode = view.addTool(myToolWrapper, HighlightDisplayLevel.find(currentSeverity), context.getUIOptions().GROUP_BY_SEVERITY);
|
||||
}
|
||||
else {
|
||||
toolNode = myToolNode;
|
||||
if (toolNode.isTooBigForOnlineRefresh()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
final Map<RefEntity, CommonProblemDescriptor[]> problems = new HashMap<RefEntity, CommonProblemDescriptor[]>();
|
||||
problems.put(refElement, descriptors);
|
||||
final Map<String, Set<RefEntity>> contents = new HashMap<String, Set<RefEntity>>();
|
||||
final String groupName = refElement.getRefManager().getGroupName((RefElement)refElement);
|
||||
Set<RefEntity> content = contents.get(groupName);
|
||||
if (content == null) {
|
||||
content = new HashSet<RefEntity>();
|
||||
contents.put(groupName, content);
|
||||
}
|
||||
content.add(refElement);
|
||||
final InspectionResultsView finalView = view;
|
||||
ApplicationManager.getApplication().executeOnPooledThread(() -> {
|
||||
ApplicationManager.getApplication().runReadAction(() -> {
|
||||
synchronized (finalView.getTreeWriteLock()) {
|
||||
final InspectionNode toolNode;
|
||||
toolNode = myToolNode == null ?
|
||||
finalView.addTool(myToolWrapper, HighlightDisplayLevel.find(getSeverity((RefElement)refElement)),
|
||||
context.getUIOptions().GROUP_BY_SEVERITY) : myToolNode;
|
||||
|
||||
view.getProvider().appendToolNodeContent(context, toolNode,
|
||||
(InspectionTreeNode)toolNode.getParent(), context.getUIOptions().SHOW_STRUCTURE,
|
||||
contents, problems, (DefaultTreeModel)view.getTree().getModel());
|
||||
final Map<RefEntity, CommonProblemDescriptor[]> problems = new HashMap<RefEntity, CommonProblemDescriptor[]>();
|
||||
problems.put(refElement, descriptors);
|
||||
final Map<String, Set<RefEntity>> contents = new HashMap<String, Set<RefEntity>>();
|
||||
final String groupName = refElement.getRefManager().getGroupName((RefElement)refElement);
|
||||
Set<RefEntity> content = contents.get(groupName);
|
||||
if (content == null) {
|
||||
content = new HashSet<RefEntity>();
|
||||
contents.put(groupName, content);
|
||||
}
|
||||
content.add(refElement);
|
||||
|
||||
finalView.getProvider().appendToolNodeContent(context, toolNode,
|
||||
(InspectionTreeNode)toolNode.getParent(), context.getUIOptions().SHOW_STRUCTURE,
|
||||
contents, problems, (DefaultTreeModel)finalView.getTree().getModel());
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -303,11 +302,8 @@ public class DefaultInspectionToolPresentation implements ProblemDescriptionsPro
|
||||
return Arrays.copyOfRange(out, 0, o);
|
||||
}
|
||||
|
||||
|
||||
public void setToolNode(InspectionNode toolNode) {
|
||||
synchronized (myToolLock) {
|
||||
myToolNode = toolNode;
|
||||
}
|
||||
myToolNode = toolNode;
|
||||
}
|
||||
|
||||
protected boolean isDisposed() {
|
||||
|
||||
@@ -25,7 +25,7 @@ import javax.swing.*;
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
class InspectionGroupNode extends InspectionTreeNode {
|
||||
public class InspectionGroupNode extends InspectionTreeNode {
|
||||
private static final Icon EMPTY = new EmptyIcon(0, IconUtil.getEmptyIcon(false).getIconHeight());
|
||||
|
||||
InspectionGroupNode(@NotNull String groupTitle) {
|
||||
|
||||
@@ -29,7 +29,7 @@ import javax.swing.*;
|
||||
*/
|
||||
public class InspectionNode extends InspectionTreeNode {
|
||||
public static final Icon TOOL = LayeredIcon.create(AllIcons.Toolwindows.ToolWindowInspection, IconUtil.getEmptyIcon(false));
|
||||
private boolean myTooBigForOnlineRefresh = false;
|
||||
private volatile boolean myUpdatingNow;
|
||||
|
||||
public InspectionNode(@NotNull InspectionToolWrapper toolWrapper) {
|
||||
super(toolWrapper);
|
||||
@@ -49,10 +49,4 @@ public class InspectionNode extends InspectionTreeNode {
|
||||
return TOOL;
|
||||
}
|
||||
|
||||
public boolean isTooBigForOnlineRefresh() {
|
||||
if (!myTooBigForOnlineRefresh) {
|
||||
myTooBigForOnlineRefresh = getProblemCount() > 1000;
|
||||
}
|
||||
return myTooBigForOnlineRefresh;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,23 +50,26 @@ import com.intellij.openapi.wm.ToolWindowId;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.intellij.pom.Navigatable;
|
||||
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usages.impl.UsagePreviewPanel;
|
||||
import com.intellij.util.ConcurrencyUtil;
|
||||
import com.intellij.util.EditSourceOnDoubleClickHandler;
|
||||
import com.intellij.util.OpenSourceUtil;
|
||||
import com.intellij.util.containers.*;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.MutableTreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
@@ -76,10 +79,11 @@ import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.*;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import static com.intellij.codeInspection.ex.InspectionRVContentProvider.insertByIndex;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
@@ -112,6 +116,8 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
|
||||
private AnAction myExcludeAction;
|
||||
private Editor myPreviewEditor;
|
||||
|
||||
private final Object myTreeWriteLock = new Object();
|
||||
|
||||
public InspectionResultsView(@NotNull GlobalInspectionContextImpl globalInspectionContext,
|
||||
@NotNull InspectionRVContentProvider provider) {
|
||||
setLayout(new BorderLayout());
|
||||
@@ -144,10 +150,14 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
|
||||
|
||||
|
||||
private void initTreeListeners() {
|
||||
myTree.getSelectionModel().addTreeSelectionListener(e -> {
|
||||
syncRightPanel();
|
||||
if (isAutoScrollMode()) {
|
||||
OpenSourceUtil.openSourcesFrom(DataManager.getInstance().getDataContext(InspectionResultsView.this), false);
|
||||
myTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
if (myTree.isUnderQueueUpdate()) return;
|
||||
syncRightPanel();
|
||||
if (isAutoScrollMode()) {
|
||||
OpenSourceUtil.openSourcesFrom(DataManager.getInstance().getDataContext(InspectionResultsView.this), false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -509,8 +519,9 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
|
||||
myProvider.appendToolNodeContent(myGlobalInspectionContext, toolNode, parentNode, showStructure);
|
||||
InspectionToolPresentation presentation = myGlobalInspectionContext.getPresentation(toolWrapper);
|
||||
toolNode = presentation.createToolNode(myGlobalInspectionContext, toolNode, myProvider, parentNode, showStructure);
|
||||
((DefaultInspectionToolPresentation)presentation).setToolNode(toolNode);
|
||||
|
||||
synchronized (myTreeWriteLock) {
|
||||
((DefaultInspectionToolPresentation)presentation).setToolNode(toolNode);
|
||||
}
|
||||
registerActionShortcuts(presentation);
|
||||
return toolNode;
|
||||
}
|
||||
@@ -553,24 +564,31 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
|
||||
return resultsFound;
|
||||
}
|
||||
|
||||
private boolean buildTree() {
|
||||
InspectionProfile profile = myInspectionProfile;
|
||||
boolean isGroupedBySeverity = myGlobalInspectionContext.getUIOptions().GROUP_BY_SEVERITY;
|
||||
myGroups.clear();
|
||||
final Map<String, Tools> tools = myGlobalInspectionContext.getTools();
|
||||
boolean resultsFound = false;
|
||||
for (Tools currentTools : tools.values()) {
|
||||
InspectionToolWrapper defaultToolWrapper = currentTools.getDefaultState().getTool();
|
||||
final HighlightDisplayKey key = HighlightDisplayKey.find(defaultToolWrapper.getShortName());
|
||||
for (ScopeToolState state : myProvider.getTools(currentTools)) {
|
||||
InspectionToolWrapper toolWrapper = state.getTool();
|
||||
if (myProvider.checkReportedProblems(myGlobalInspectionContext, toolWrapper)) {
|
||||
addTool(toolWrapper, ((InspectionProfileImpl)profile).getErrorLevel(key, state.getScope(myProject), myProject), isGroupedBySeverity);
|
||||
resultsFound = true;
|
||||
public Object getTreeWriteLock() {
|
||||
return myTreeWriteLock;
|
||||
}
|
||||
|
||||
public boolean buildTree() {
|
||||
synchronized (myTreeWriteLock) {
|
||||
InspectionProfile profile = myInspectionProfile;
|
||||
boolean isGroupedBySeverity = myGlobalInspectionContext.getUIOptions().GROUP_BY_SEVERITY;
|
||||
myGroups.clear();
|
||||
final Map<String, Tools> tools = myGlobalInspectionContext.getTools();
|
||||
boolean resultsFound = false;
|
||||
for (Tools currentTools : tools.values()) {
|
||||
InspectionToolWrapper defaultToolWrapper = currentTools.getDefaultState().getTool();
|
||||
final HighlightDisplayKey key = HighlightDisplayKey.find(defaultToolWrapper.getShortName());
|
||||
for (ScopeToolState state : myProvider.getTools(currentTools)) {
|
||||
InspectionToolWrapper toolWrapper = state.getTool();
|
||||
if (myProvider.checkReportedProblems(myGlobalInspectionContext, toolWrapper)) {
|
||||
addTool(toolWrapper, ((InspectionProfileImpl)profile).getErrorLevel(key, state.getScope(myProject), myProject),
|
||||
isGroupedBySeverity);
|
||||
resultsFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return resultsFound;
|
||||
}
|
||||
return resultsFound;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -594,7 +612,9 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
|
||||
}
|
||||
if (group == null) {
|
||||
group = ConcurrencyUtil.cacheOrGet(map, groupName, new InspectionGroupNode(groupName));
|
||||
addChildNodeInEDT(getRelativeRootNode(groupedBySeverity, errorLevel), group);
|
||||
if (!myDisposed) {
|
||||
insertByIndex(group, getRelativeRootNode(groupedBySeverity, errorLevel));
|
||||
}
|
||||
}
|
||||
return group;
|
||||
}
|
||||
@@ -608,7 +628,7 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
|
||||
severityGroupNode = ConcurrencyUtil.cacheOrGet(mySeverityGroupNodes, level, newNode);
|
||||
if (severityGroupNode == newNode) {
|
||||
InspectionTreeNode root = myTree.getRoot();
|
||||
addChildNodeInEDT(root, severityGroupNode);
|
||||
insertByIndex(root, severityGroupNode);
|
||||
}
|
||||
}
|
||||
return severityGroupNode;
|
||||
@@ -616,18 +636,6 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
|
||||
return myTree.getRoot();
|
||||
}
|
||||
|
||||
private void addChildNodeInEDT(@NotNull final DefaultMutableTreeNode root, @NotNull final MutableTreeNode severityGroupNode) {
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!myDisposed) {
|
||||
root.add(severityGroupNode);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private OccurenceNavigator getOccurenceNavigator() {
|
||||
return myOccurenceNavigator;
|
||||
}
|
||||
|
||||
@@ -22,8 +22,10 @@ import com.intellij.openapi.application.ex.ApplicationInfoEx;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.util.PlatformUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.MutableTreeNode;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
@@ -34,9 +36,10 @@ public class InspectionRootNode extends InspectionTreeNode {
|
||||
: IconLoader.getIcon(ApplicationInfoEx.getInstanceEx().getSmallIconUrl());
|
||||
private final Project myProject;
|
||||
|
||||
public InspectionRootNode(Project project) {
|
||||
public InspectionRootNode(Project project, @NotNull InspectionTreeUpdater updater) {
|
||||
super(project);
|
||||
myProject = project;
|
||||
myUpdater = updater;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
@@ -52,4 +55,9 @@ public class InspectionRootNode extends InspectionTreeNode {
|
||||
public Icon getIcon(boolean expanded) {
|
||||
return APP_ICON;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(MutableTreeNode newChild) {
|
||||
super.add(newChild);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,15 +40,13 @@ import com.intellij.ui.treeStructure.Tree;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.tree.TreeModelAdapter;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.TreeExpansionEvent;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.event.TreeWillExpandListener;
|
||||
import javax.swing.event.*;
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
import javax.swing.tree.ExpandVetoException;
|
||||
import javax.swing.tree.TreeNode;
|
||||
@@ -59,9 +57,10 @@ public class InspectionTree extends Tree {
|
||||
private final HashSet<Object> myExpandedUserObjects;
|
||||
@NotNull private final GlobalInspectionContextImpl myContext;
|
||||
private SelectionPath mySelectionPath;
|
||||
private boolean myQueueUpdate;
|
||||
|
||||
public InspectionTree(@NotNull Project project, @NotNull GlobalInspectionContextImpl context) {
|
||||
super(new InspectionRootNode(project));
|
||||
setModel(new DefaultTreeModel(new InspectionRootNode(project, new InspectionTreeUpdater(this))));
|
||||
myContext = context;
|
||||
|
||||
setCellRenderer(new CellRenderer());
|
||||
@@ -91,6 +90,14 @@ public class InspectionTree extends Tree {
|
||||
});
|
||||
}
|
||||
|
||||
public void setQueueUpdate(boolean queueUpdate) {
|
||||
myQueueUpdate = queueUpdate;
|
||||
}
|
||||
|
||||
public boolean isUnderQueueUpdate() {
|
||||
return myQueueUpdate;
|
||||
}
|
||||
|
||||
public void removeAllNodes() {
|
||||
getRoot().removeAllChildren();
|
||||
nodeStructureChanged(getRoot());
|
||||
@@ -297,9 +304,9 @@ public class InspectionTree extends Tree {
|
||||
}
|
||||
}
|
||||
|
||||
private void restoreExpansionStatus(InspectionTreeNode node) {
|
||||
public void restoreExpansionStatus(InspectionTreeNode node) {
|
||||
if (myExpandedUserObjects.contains(node.getUserObject())) {
|
||||
sortChildren(node);
|
||||
//sortChildren(node);
|
||||
TreeNode[] pathToNode = node.getPath();
|
||||
expandPath(new TreePath(pathToNode));
|
||||
Enumeration children = node.children();
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.MutableTreeNode;
|
||||
import java.util.Enumeration;
|
||||
|
||||
/**
|
||||
@@ -28,6 +29,7 @@ import java.util.Enumeration;
|
||||
*/
|
||||
public abstract class InspectionTreeNode extends DefaultMutableTreeNode {
|
||||
private boolean myResolved;
|
||||
protected volatile InspectionTreeUpdater myUpdater;
|
||||
protected InspectionTreeNode(Object userObject) {
|
||||
super(userObject);
|
||||
}
|
||||
@@ -78,4 +80,33 @@ public abstract class InspectionTreeNode extends DefaultMutableTreeNode {
|
||||
child.amnesty();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(MutableTreeNode newChild) {
|
||||
super.add(newChild);
|
||||
if (myUpdater != null) {
|
||||
((InspectionTreeNode)newChild).propagateUpdater(myUpdater);
|
||||
myUpdater.update();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(MutableTreeNode newChild, int childIndex) {
|
||||
super.insert(newChild, childIndex);
|
||||
if (myUpdater != null) {
|
||||
((InspectionTreeNode)newChild).propagateUpdater(myUpdater);
|
||||
myUpdater.update();
|
||||
}
|
||||
}
|
||||
|
||||
private void propagateUpdater(InspectionTreeUpdater updater) {
|
||||
if (myUpdater != null) return;
|
||||
myUpdater = updater;
|
||||
Enumeration enumeration = children();
|
||||
while (enumeration.hasMoreElements()) {
|
||||
InspectionTreeNode child = (InspectionTreeNode)enumeration.nextElement();
|
||||
child.propagateUpdater(updater);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.codeInspection.ui;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.util.ui.update.MergingUpdateQueue;
|
||||
import com.intellij.util.ui.update.Update;
|
||||
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class InspectionTreeUpdater {
|
||||
private final InspectionTree myTree;
|
||||
private final MergingUpdateQueue myUpdateQueue;
|
||||
|
||||
public InspectionTreeUpdater(InspectionTree tree) {
|
||||
myTree = tree;
|
||||
myUpdateQueue = new MergingUpdateQueue("InspectionView", 100, true, tree);
|
||||
}
|
||||
|
||||
public void update() {
|
||||
if (ApplicationManager.getApplication().isDispatchThread()) {
|
||||
return;
|
||||
}
|
||||
myUpdateQueue.queue(new Update("TreeRepaint") {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
myTree.setQueueUpdate(true);
|
||||
((DefaultTreeModel)myTree.getModel()).reload();
|
||||
myTree.revalidate();
|
||||
myTree.repaint();
|
||||
myTree.restoreExpansionAndSelection();
|
||||
} finally {
|
||||
myTree.setQueueUpdate(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canEat(Update update) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -38,32 +38,18 @@ import static com.intellij.codeInspection.ProblemDescriptorUtil.TRIM_AT_TREE_END
|
||||
public class ProblemDescriptionNode extends InspectionTreeNode {
|
||||
protected RefEntity myElement;
|
||||
private final CommonProblemDescriptor myDescriptor;
|
||||
protected final InspectionToolWrapper myToolWrapper;
|
||||
protected final InspectionToolWrapper toolWrapper;
|
||||
@NotNull
|
||||
protected final InspectionToolPresentation myPresentation;
|
||||
|
||||
public ProblemDescriptionNode(@NotNull Object userObject,
|
||||
@NotNull InspectionToolWrapper toolWrapper,
|
||||
@NotNull InspectionToolPresentation presentation) {
|
||||
this(userObject, null, null, toolWrapper, presentation);
|
||||
}
|
||||
|
||||
public ProblemDescriptionNode(@NotNull RefEntity element,
|
||||
@NotNull CommonProblemDescriptor descriptor,
|
||||
@NotNull InspectionToolWrapper toolWrapper,
|
||||
@NotNull InspectionToolPresentation presentation) {
|
||||
this(descriptor, element, descriptor, toolWrapper, presentation);
|
||||
}
|
||||
|
||||
private ProblemDescriptionNode(@NotNull Object userObject,
|
||||
RefEntity element,
|
||||
public ProblemDescriptionNode(RefEntity element,
|
||||
CommonProblemDescriptor descriptor,
|
||||
@NotNull InspectionToolWrapper toolWrapper,
|
||||
@NotNull InspectionToolPresentation presentation) {
|
||||
super(userObject);
|
||||
super(descriptor);
|
||||
myElement = element;
|
||||
myDescriptor = descriptor;
|
||||
myToolWrapper = toolWrapper;
|
||||
this.toolWrapper = toolWrapper;
|
||||
myPresentation = presentation;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ public class RefElementNode extends InspectionTreeNode {
|
||||
}
|
||||
});
|
||||
|
||||
public RefElementNode(@NotNull Object userObject, @NotNull InspectionToolPresentation presentation) {
|
||||
public RefElementNode(@Nullable Object userObject, @NotNull InspectionToolPresentation presentation) {
|
||||
super(userObject);
|
||||
myToolPresentation = presentation;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user