2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 package com.intellij.codeInspection.offlineViewer;
23 import com.intellij.codeInspection.CommonProblemDescriptor;
24 import com.intellij.codeInspection.ex.*;
25 import com.intellij.codeInspection.offline.OfflineProblemDescriptor;
26 import com.intellij.codeInspection.reference.RefElement;
27 import com.intellij.codeInspection.reference.RefEntity;
28 import com.intellij.codeInspection.reference.SmartRefElementPointer;
29 import com.intellij.codeInspection.ui.*;
30 import com.intellij.openapi.project.Project;
31 import com.intellij.openapi.util.Comparing;
32 import com.intellij.util.Function;
33 import com.intellij.util.containers.HashSet;
34 import com.intellij.util.ui.tree.TreeUtil;
35 import org.jetbrains.annotations.NotNull;
36 import org.jetbrains.annotations.Nullable;
38 import javax.swing.tree.TreeNode;
39 import javax.swing.tree.TreePath;
42 public class OfflineInspectionRVContentProvider extends InspectionRVContentProvider {
43 private final Map<String, Map<String, Set<OfflineProblemDescriptor>>> myContent;
45 public OfflineInspectionRVContentProvider(@NotNull Map<String, Map<String, Set<OfflineProblemDescriptor>>> content,
46 @NotNull Project project) {
52 public boolean checkReportedProblems(@NotNull GlobalInspectionContextImpl context,
53 @NotNull final InspectionToolWrapper toolWrapper) {
54 final Map<String, Set<OfflineProblemDescriptor>> content = getFilteredContent(context, toolWrapper);
55 return content != null && !content.values().isEmpty();
59 public Iterable<? extends ScopeToolState> getTools(Tools tools) {
60 return Collections.singletonList(tools.getDefaultState());
65 public QuickFixAction[] getQuickFixes(@NotNull final InspectionToolWrapper toolWrapper, @NotNull final InspectionTree tree) {
66 final TreePath[] treePaths = tree.getSelectionPaths();
67 if (treePaths == null) return QuickFixAction.EMPTY;
68 final List<RefEntity> selectedElements = new ArrayList<RefEntity>();
69 final Map<RefEntity, CommonProblemDescriptor[]> actions = new HashMap<>();
70 for (TreePath selectionPath : treePaths) {
71 TreeUtil.traverseDepth((TreeNode)selectionPath.getLastPathComponent(), node -> {
72 if (!((InspectionTreeNode)node).isValid()) return true;
73 if (node instanceof OfflineProblemDescriptorNode) {
74 if (((OfflineProblemDescriptorNode)node).isQuickFixAppliedFromView()) return true;
75 final OfflineProblemDescriptorNode descriptorNode = (OfflineProblemDescriptorNode)node;
76 final RefEntity element = descriptorNode.getElement();
77 selectedElements.add(element);
78 CommonProblemDescriptor[] descriptors = actions.get(element);
79 final CommonProblemDescriptor descriptor = descriptorNode.getDescriptor();
80 final CommonProblemDescriptor[] descriptorAsArray = descriptor == null ? CommonProblemDescriptor.EMPTY_ARRAY
81 : new CommonProblemDescriptor[]{descriptor};
82 actions.put(element, descriptors == null ?
84 DefaultInspectionToolPresentation.mergeDescriptors(descriptors, descriptorAsArray));
86 else if (node instanceof RefElementNode) {
87 selectedElements.add(((RefElementNode)node).getElement());
93 if (selectedElements.isEmpty()) return null;
95 final RefEntity[] selectedRefElements = selectedElements.toArray(new RefEntity[selectedElements.size()]);
97 GlobalInspectionContextImpl context = tree.getContext();
98 InspectionToolPresentation presentation = context.getPresentation(toolWrapper);
99 return presentation.extractActiveFixes(selectedRefElements, actions, tree.getSelectedDescriptors());
103 public boolean isContentLoaded() {
108 public void appendToolNodeContent(@NotNull GlobalInspectionContextImpl context,
109 @NotNull final InspectionNode toolNode,
110 @NotNull final InspectionTreeNode parentNode,
111 final boolean showStructure,
112 @NotNull final Map<String, Set<RefEntity>> contents,
113 @NotNull final Map<RefEntity, CommonProblemDescriptor[]> problems) {
114 InspectionToolWrapper toolWrapper = toolNode.getToolWrapper();
115 final Map<String, Set<OfflineProblemDescriptor>> filteredContent = getFilteredContent(context, toolWrapper);
116 if (filteredContent != null && !filteredContent.values().isEmpty()) {
117 final Function<OfflineProblemDescriptor, UserObjectContainer<OfflineProblemDescriptor>> computeContainer =
118 descriptor -> new OfflineProblemDescriptorContainer(descriptor);
119 parentNode.add(toolNode);
120 buildTree(context, filteredContent, false, toolWrapper, computeContainer, showStructure, toolNode::add);
125 @SuppressWarnings({"UnusedAssignment"})
126 private Map<String, Set<OfflineProblemDescriptor>> getFilteredContent(@NotNull GlobalInspectionContextImpl context,
127 @NotNull InspectionToolWrapper toolWrapper) {
128 Map<String, Set<OfflineProblemDescriptor>> content = myContent.get(toolWrapper.getShortName());
129 if (content == null) return null;
130 if (context.getUIOptions().FILTER_RESOLVED_ITEMS) {
131 final Map<String, Set<OfflineProblemDescriptor>> current = new HashMap<String, Set<OfflineProblemDescriptor>>(content);
132 content = null; //GC it
133 InspectionToolPresentation presentation = context.getPresentation(toolWrapper);
134 for (RefEntity refEntity : presentation.getIgnoredRefElements()) {
135 if (refEntity instanceof RefElement) {
136 excludeProblem(refEntity.getExternalName(), current);
144 private static void excludeProblem(final String externalName, final Map<String, Set<OfflineProblemDescriptor>> content) {
145 for (Iterator<String> iter = content.keySet().iterator(); iter.hasNext();) {
146 final String packageName = iter.next();
147 final Set<OfflineProblemDescriptor> excluded = new HashSet<OfflineProblemDescriptor>(content.get(packageName));
148 for (Iterator<OfflineProblemDescriptor> it = excluded.iterator(); it.hasNext();) {
149 final OfflineProblemDescriptor ex = it.next();
150 if (Comparing.strEqual(ex.getFQName(), externalName)) {
154 if (excluded.isEmpty()) {
157 content.put(packageName, excluded);
163 protected void appendDescriptor(@NotNull GlobalInspectionContextImpl context,
164 @NotNull final InspectionToolWrapper toolWrapper,
165 @NotNull final UserObjectContainer container,
166 @NotNull final InspectionTreeNode packageNode,
167 final boolean canPackageRepeat) {
168 InspectionToolPresentation presentation = context.getPresentation(toolWrapper);
169 final RefElementNode elemNode = addNodeToParent(container, presentation, packageNode);
170 if (toolWrapper instanceof LocalInspectionToolWrapper) {
171 final OfflineProblemDescriptorNode child =
172 OfflineProblemDescriptorNode.create(((OfflineProblemDescriptorContainer)container).getUserObject(),
173 (LocalInspectionToolWrapper)toolWrapper, presentation);
174 elemNode.insertByOrder(child, true);
179 private static class OfflineProblemDescriptorContainer implements UserObjectContainer<OfflineProblemDescriptor> {
181 private final OfflineProblemDescriptor myDescriptor;
183 public OfflineProblemDescriptorContainer(@NotNull OfflineProblemDescriptor descriptor) {
184 myDescriptor = descriptor;
189 public OfflineProblemDescriptorContainer getOwner() {
190 final OfflineProblemDescriptor descriptor = myDescriptor.getOwner();
191 if (descriptor != null) {
192 final OfflineProblemDescriptorContainer container = new OfflineProblemDescriptorContainer(descriptor);
193 return container.supportStructure() ? container : null;
200 public RefElementNode createNode(@NotNull InspectionToolPresentation presentation) {
201 return new OfflineRefElementNode(myDescriptor, presentation);
206 public OfflineProblemDescriptor getUserObject() {
211 public String getModule() {
212 return myDescriptor.getModuleName();
216 public boolean areEqual(final OfflineProblemDescriptor o1, final OfflineProblemDescriptor o2) {
217 if (o1 == null || o2 == null) {
221 if (!Comparing.strEqual(o1.getFQName(), o2.getFQName())) return false;
222 if (!Comparing.strEqual(o1.getType(), o2.getType())) return false;
228 public boolean supportStructure() {
229 return !Comparing.strEqual(myDescriptor.getType(), SmartRefElementPointer.MODULE) &&
230 !Comparing.strEqual(myDescriptor.getType(), "package") &&
231 !Comparing.strEqual(myDescriptor.getType(), SmartRefElementPointer.PROJECT);