inspection view: show inspection's group nodes IDEA-180726

This commit is contained in:
Dmitry Batkovich
2017-10-27 16:35:42 +03:00
parent 8aa559bcc8
commit f9f3b90811
4 changed files with 79 additions and 66 deletions
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2015 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInspection.ui;
@@ -22,22 +8,14 @@ import org.jetbrains.annotations.NotNull;
* @author max
*/
public class InspectionGroupNode extends InspectionTreeNode {
@NotNull private final String[] myGroupPath;
InspectionGroupNode(@NotNull String groupTitle, @NotNull String[] groupPath) {
super(groupTitle);
myGroupPath = groupPath;
InspectionGroupNode(@NotNull String subGroup) {
super(subGroup);
}
String getGroupTitle() {
String getSubGroup() {
return (String) getUserObject();
}
@NotNull
public String[] getGroupPath() {
return myGroupPath;
}
@Override
public boolean appearsBold() {
return true;
@@ -47,12 +47,10 @@ import com.intellij.profile.codeInspection.ProjectInspectionProfileManager;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.ui.*;
import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.EditSourceOnDoubleClickHandler;
import com.intellij.util.ObjectUtils;
import com.intellij.util.OpenSourceUtil;
import com.intellij.util.concurrency.AppExecutorUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
@@ -73,7 +71,6 @@ import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.*;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
public class InspectionResultsView extends JPanel implements Disposable, DataProvider, OccurenceNavigator {
@@ -618,9 +615,7 @@ public class InspectionResultsView extends JPanel implements Disposable, DataPro
HighlightDisplayLevel errorLevel,
boolean groupedBySeverity,
boolean isSingleInspectionRun) {
String groupName =
toolWrapper.getGroupDisplayName().isEmpty() ? InspectionProfileEntry.GENERAL_GROUP_NAME : toolWrapper.getGroupDisplayName();
InspectionTreeNode parentNode = myTree.getToolParentNode(groupName, toolWrapper.getGroupPath(), errorLevel, groupedBySeverity, isSingleInspectionRun);
InspectionTreeNode parentNode = myTree.getToolParentNode(toolWrapper, errorLevel, groupedBySeverity, isSingleInspectionRun);
InspectionNode toolNode = new InspectionNode(toolWrapper, myInspectionProfile);
boolean showStructure = myGlobalInspectionContext.getUIOptions().SHOW_STRUCTURE;
toolNode = myProvider.appendToolNodeContent(myGlobalInspectionContext, toolNode, parentNode, showStructure, groupedBySeverity);
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2009 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInspection.ui;
@@ -54,7 +40,7 @@ public class InspectionResultsViewComparator implements Comparator<InspectionTre
if (node2 instanceof InspectionSeverityGroupNode) return 1;
if (node1 instanceof InspectionGroupNode && node2 instanceof InspectionGroupNode) {
return ((InspectionGroupNode)node1).getGroupTitle().compareToIgnoreCase(((InspectionGroupNode)node2).getGroupTitle());
return ((InspectionGroupNode)node1).getSubGroup().compareTo(((InspectionGroupNode)node2).getSubGroup());
}
if (node1 instanceof InspectionGroupNode) return -1;
if (node2 instanceof InspectionGroupNode) return 1;
@@ -8,6 +8,7 @@ import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ex.GlobalInspectionContextImpl;
import com.intellij.codeInspection.ex.InspectionToolWrapper;
import com.intellij.codeInspection.reference.RefEntity;
import com.intellij.concurrency.ConcurrentCollectionFactory;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
@@ -23,6 +24,7 @@ import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -41,7 +43,7 @@ public class InspectionTree extends Tree {
@NotNull private final GlobalInspectionContextImpl myContext;
@NotNull private final ConcurrentMap<HighlightDisplayLevel, InspectionSeverityGroupNode> mySeverityGroupNodes = ContainerUtil.newConcurrentMap();
@NotNull private final ConcurrentMap<HighlightDisplayLevel, ConcurrentMap<String, InspectionGroupNode>> myGroups = ContainerUtil.newConcurrentMap();
@NotNull private final ConcurrentMap<HighlightDisplayLevel, ConcurrentMap<String[], InspectionGroupNode>> myGroups = ContainerUtil.newConcurrentMap();
@NotNull private InspectionTreeState myState = new InspectionTreeState();
private boolean myQueueUpdate;
@@ -97,7 +99,7 @@ public class InspectionTree extends Tree {
final TreePath commonPath = TreeUtil.findCommonPath(paths);
for (Object n : commonPath.getPath()) {
if (n instanceof InspectionGroupNode) {
return ((InspectionGroupNode)n).getGroupPath();
return getGroupPath((InspectionGroupNode)n);
}
}
return null;
@@ -275,40 +277,48 @@ public class InspectionTree extends Tree {
}
@NotNull
InspectionTreeNode getToolParentNode(@NotNull String groupName,
@NotNull String[] groupPath,
HighlightDisplayLevel errorLevel,
boolean groupedBySeverity,
boolean isSingleInspectionRun) {
InspectionTreeNode getToolParentNode(@NotNull InspectionToolWrapper toolWrapper,
HighlightDisplayLevel errorLevel,
boolean groupedBySeverity,
boolean isSingleInspectionRun) {
//synchronize
if (!groupedBySeverity && isSingleInspectionRun) {
return getRoot();
}
if (groupName.isEmpty()) {
String[] groupPath = toolWrapper.getGroupPath();
if (groupPath.length == 0) {
LOG.error("groupPath is empty for tool: " + toolWrapper.getShortName() + ", class: " + toolWrapper.getTool().getClass());
return getRelativeRootNode(groupedBySeverity, errorLevel);
}
ConcurrentMap<String, InspectionGroupNode> map = myGroups.get(errorLevel);
ConcurrentMap<String[], InspectionGroupNode> map = myGroups.get(errorLevel);
if (map == null) {
map = ConcurrencyUtil.cacheOrGet(myGroups, errorLevel, ContainerUtil.newConcurrentMap());
map = ConcurrencyUtil.cacheOrGet(myGroups, errorLevel, ConcurrentCollectionFactory.createMap(new TObjectHashingStrategy<String[]>() {
@Override
public int computeHashCode(String[] object) {
return Arrays.hashCode(object);
}
@Override
public boolean equals(String[] o1, String[] o2) {
return Arrays.equals(o1, o2);
}
}));
}
InspectionGroupNode group;
if (groupedBySeverity) {
group = map.get(groupName);
group = map.get(groupPath);
}
else {
group = null;
for (Map<String, InspectionGroupNode> groupMap : myGroups.values()) {
if ((group = groupMap.get(groupName)) != null) break;
for (Map<String[], InspectionGroupNode> groupMap : myGroups.values()) {
if ((group = groupMap.get(groupPath)) != null) break;
}
}
if (group == null) {
if (isSingleInspectionRun) {
return getRelativeRootNode(true, errorLevel);
}
group = ConcurrencyUtil.cacheOrGet(map, groupName, new InspectionGroupNode(groupName, groupPath));
InspectionResultsView view = myContext.getView();
if (view != null && !view.isDisposed()) {
getRelativeRootNode(groupedBySeverity, errorLevel).insertByOrder(group, false);
}
group = map.computeIfAbsent(groupPath, this::insertGroupNode);
}
return group;
}
@@ -433,6 +443,38 @@ public class InspectionTree extends Tree {
return myContext;
}
private InspectionGroupNode insertGroupNode(@NotNull String[] groupPath) {
InspectionTreeNode currentNode = getRoot();
for (int groupIdx = 0; groupIdx < groupPath.length; groupIdx++) {
String subGroup = groupPath[groupIdx];
InspectionTreeNode next = null;
for (int i = 0; i < currentNode.getChildCount(); i++) {
TreeNode child = currentNode.getChildAt(i);
if (child instanceof InspectionGroupNode && ((InspectionGroupNode)child).getSubGroup().equals(subGroup)) {
next = (InspectionTreeNode)child;
break;
}
}
if (next == null) {
for (int i = groupIdx; i < groupPath.length; i++) {
InspectionResultsView view = getContext().getView();
if (view != null && !view.isDisposed()) {
currentNode = currentNode.insertByOrder(new InspectionGroupNode(groupPath[i]), false);
}
}
break;
}
else {
currentNode = next;
}
}
return (InspectionGroupNode)currentNode;
}
private static void collectReadOnlyFiles(@NotNull Collection<CommonProblemDescriptor> descriptors, @NotNull Set<VirtualFile> readOnlySink) {
for (CommonProblemDescriptor descriptor : descriptors) {
collectReadOnlyFiles(descriptor, readOnlySink);
@@ -447,4 +489,16 @@ public class InspectionTree extends Tree {
}
}
}
@NotNull
private static String[] getGroupPath(@NotNull InspectionGroupNode node) {
List<String> path = new ArrayList<>(2);
while (true) {
TreeNode parent = node.getParent();
if (!(parent instanceof InspectionGroupNode)) break;
node = (InspectionGroupNode)parent;
path.add(node.getSubGroup());
}
return ArrayUtil.toStringArray(path);
}
}