/platform/lang-impl/src/com/intellij/codeInspection/ex/LocalInspectionToolWrapper.java

https://bitbucket.org/nbargnesi/idea · Java · 233 lines · 182 code · 32 blank · 19 comment · 39 complexity · 4ae06710bcec4a0d98c51cde85a8adf7 MD5 · raw file

  1. /*
  2. * Copyright 2000-2009 JetBrains s.r.o.
  3. *
  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
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  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.
  15. */
  16. package com.intellij.codeInspection.ex;
  17. import com.intellij.analysis.AnalysisScope;
  18. import com.intellij.codeHighlighting.HighlightDisplayLevel;
  19. import com.intellij.codeInspection.*;
  20. import com.intellij.codeInspection.reference.RefElement;
  21. import com.intellij.codeInspection.reference.RefEntity;
  22. import com.intellij.codeInspection.reference.RefManagerImpl;
  23. import com.intellij.codeInspection.ui.InspectionResultsView;
  24. import com.intellij.codeInspection.ui.InspectionTreeNode;
  25. import com.intellij.lang.annotation.HighlightSeverity;
  26. import com.intellij.openapi.application.ApplicationManager;
  27. import com.intellij.openapi.diagnostic.Logger;
  28. import com.intellij.openapi.extensions.Extensions;
  29. import com.intellij.openapi.util.NotNullLazyValue;
  30. import com.intellij.psi.*;
  31. import com.intellij.util.TripleFunction;
  32. import com.intellij.util.containers.HashSet;
  33. import com.intellij.util.ui.UIUtil;
  34. import org.jetbrains.annotations.NotNull;
  35. import org.jetbrains.annotations.Nullable;
  36. import org.jetbrains.annotations.TestOnly;
  37. import javax.swing.tree.DefaultTreeModel;
  38. import java.util.*;
  39. /**
  40. * @author max
  41. */
  42. public class LocalInspectionToolWrapper extends InspectionToolWrapper<LocalInspectionTool, LocalInspectionEP> {
  43. private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.LocalInspectionToolWrapper");
  44. /** This should be used in tests primarily */
  45. public LocalInspectionToolWrapper(@NotNull LocalInspectionTool tool) {
  46. super(tool, ourEPMap.getValue().get(tool.getShortName()));
  47. }
  48. public LocalInspectionToolWrapper(LocalInspectionEP ep) {
  49. super(ep);
  50. }
  51. @TestOnly
  52. public LocalInspectionToolWrapper(@Nullable LocalInspectionTool tool, @Nullable LocalInspectionEP ep) {
  53. super(tool, ep);
  54. }
  55. private LocalInspectionToolWrapper(LocalInspectionToolWrapper other) {
  56. super(other);
  57. }
  58. @Override
  59. public LocalInspectionToolWrapper createCopy() {
  60. return new LocalInspectionToolWrapper(this);
  61. }
  62. public void processFile(PsiFile file, final boolean filterSuppressed, final InspectionManager manager) {
  63. processFile(file, filterSuppressed, manager, false);
  64. }
  65. public void processFile(final PsiFile file, final boolean filterSuppressed, final InspectionManager manager, final boolean isOnTheFly) {
  66. final ProblemsHolder holder = new ProblemsHolder(manager, file, isOnTheFly);
  67. LocalInspectionToolSession session = new LocalInspectionToolSession(file, 0, file.getTextLength());
  68. final PsiElementVisitor customVisitor = getTool().buildVisitor(holder, isOnTheFly, session);
  69. LOG.assertTrue(!(customVisitor instanceof PsiRecursiveElementVisitor), "The visitor returned from LocalInspectionTool.buildVisitor() must not be recursive");
  70. getTool().inspectionStarted(session, isOnTheFly);
  71. file.accept(new PsiRecursiveElementWalkingVisitor() {
  72. @Override public void visitElement(PsiElement element) {
  73. element.accept(customVisitor);
  74. super.visitElement(element);
  75. }
  76. });
  77. getTool().inspectionFinished(session, holder);
  78. addProblemDescriptors(holder.getResults(), filterSuppressed);
  79. }
  80. @NotNull
  81. public JobDescriptor[] getJobDescriptors(GlobalInspectionContext context) {
  82. return ((GlobalInspectionContextImpl)context).LOCAL_ANALYSIS_ARRAY;
  83. }
  84. public void addProblemDescriptors(List<ProblemDescriptor> descriptors, final boolean filterSuppressed) {
  85. final GlobalInspectionContextImpl context = getContext();
  86. if (context != null) { //can be already closed
  87. addProblemDescriptors(descriptors, filterSuppressed, context, getTool(), CONVERT, this);
  88. }
  89. }
  90. private static final TripleFunction<LocalInspectionTool, PsiElement, GlobalInspectionContext,RefElement> CONVERT = new TripleFunction<LocalInspectionTool, PsiElement, GlobalInspectionContext,RefElement>() {
  91. @Override
  92. public RefElement fun(LocalInspectionTool tool, PsiElement elt, GlobalInspectionContext context) {
  93. final PsiNamedElement problemElement = tool.getProblemElement(elt);
  94. RefElement refElement = context.getRefManager().getReference(problemElement);
  95. if (refElement == null && problemElement != null) { // no need to lose collected results
  96. refElement = GlobalInspectionUtil.retrieveRefElement(elt, context);
  97. }
  98. return refElement;
  99. }
  100. };
  101. @Override
  102. protected void addProblemElement(RefEntity refElement, boolean filterSuppressed, CommonProblemDescriptor... descriptions) {
  103. super.addProblemElement(refElement, filterSuppressed, descriptions);
  104. final InspectionResultsView view = getContext().getView();
  105. if (view != null && refElement instanceof RefElement) {
  106. if (myToolNode == null) {
  107. final HighlightSeverity currentSeverity = getCurrentSeverity((RefElement)refElement);
  108. view.addTool(this, HighlightDisplayLevel.find(currentSeverity), getContext().getUIOptions().GROUP_BY_SEVERITY);
  109. } else if (myToolNode.getProblemCount() > 1000) {
  110. return;
  111. }
  112. final HashMap<RefEntity, CommonProblemDescriptor[]> problems = new HashMap<RefEntity, CommonProblemDescriptor[]>();
  113. problems.put(refElement, descriptions);
  114. final HashMap<String, Set<RefEntity>> contents = new HashMap<String, Set<RefEntity>>();
  115. final String groupName = refElement.getRefManager().getGroupName((RefElement)refElement);
  116. Set<RefEntity> content = contents.get(groupName);
  117. if (content == null) {
  118. content = new HashSet<RefEntity>();
  119. contents.put(groupName, content);
  120. }
  121. content.add(refElement);
  122. UIUtil.invokeLaterIfNeeded(new Runnable() {
  123. public void run() {
  124. final GlobalInspectionContextImpl context = getContext();
  125. if (context != null) {
  126. view.getProvider().appendToolNodeContent(myToolNode,
  127. (InspectionTreeNode)myToolNode.getParent(), context.getUIOptions().SHOW_STRUCTURE,
  128. contents, problems, (DefaultTreeModel)view.getTree().getModel());
  129. context.addView(view);
  130. }
  131. }
  132. });
  133. }
  134. }
  135. public static void addProblemDescriptors(List<ProblemDescriptor> descriptors,
  136. boolean filterSuppressed,
  137. @NotNull GlobalInspectionContextImpl context,
  138. LocalInspectionTool tool,
  139. @NotNull TripleFunction<LocalInspectionTool, PsiElement, GlobalInspectionContext, RefElement> getProblemElementFunction,
  140. @NotNull DescriptorProviderInspection dpi) {
  141. if (descriptors == null || descriptors.isEmpty()) return;
  142. Map<RefElement, List<ProblemDescriptor>> problems = new HashMap<RefElement, List<ProblemDescriptor>>();
  143. final RefManagerImpl refManager = (RefManagerImpl)context.getRefManager();
  144. for (ProblemDescriptor descriptor : descriptors) {
  145. final PsiElement elt = descriptor.getPsiElement();
  146. if (elt == null) continue;
  147. if (filterSuppressed) {
  148. if (refManager.isDeclarationsFound()
  149. && (context.isSuppressed(elt, tool.getID()) || tool.getAlternativeID() != null && context.isSuppressed(elt, tool.getAlternativeID()))) {
  150. continue;
  151. }
  152. if (InspectionManagerEx.inspectionResultSuppressed(elt, tool)) continue;
  153. }
  154. RefElement refElement = getProblemElementFunction.fun(tool, elt, context);
  155. List<ProblemDescriptor> elementProblems = problems.get(refElement);
  156. if (elementProblems == null) {
  157. elementProblems = new ArrayList<ProblemDescriptor>();
  158. problems.put(refElement, elementProblems);
  159. }
  160. elementProblems.add(descriptor);
  161. }
  162. for (Map.Entry<RefElement, List<ProblemDescriptor>> entry : problems.entrySet()) {
  163. final List<ProblemDescriptor> problemDescriptors = entry.getValue();
  164. dpi.addProblemElement(entry.getKey(),
  165. filterSuppressed,
  166. problemDescriptors.toArray(new CommonProblemDescriptor[problemDescriptors.size()]));
  167. }
  168. }
  169. public void runInspection(@NotNull AnalysisScope scope, @NotNull final InspectionManager manager) {
  170. LOG.assertTrue(ApplicationManager.getApplication().isUnitTestMode());
  171. scope.accept(new PsiRecursiveElementVisitor() {
  172. @Override public void visitFile(PsiFile file) {
  173. processFile(file, true, manager);
  174. }
  175. });
  176. }
  177. public boolean isUnfair() {
  178. return myEP == null ? getTool() instanceof UnfairLocalInspectionTool : myEP.unfair;
  179. }
  180. public String getID() {
  181. return myEP == null ? getTool().getID() : myEP.id == null ? myEP.getShortName() : myEP.id;
  182. }
  183. @Nullable
  184. public String getAlternativeID() {
  185. return myEP == null ? getTool().getAlternativeID() : myEP.alternativeId;
  186. }
  187. public boolean runForWholeFile() {
  188. return myEP == null ? getTool().runForWholeFile() : myEP.runForWholeFile;
  189. }
  190. private final static NotNullLazyValue<Map<String, LocalInspectionEP>> ourEPMap = new NotNullLazyValue<Map<String, LocalInspectionEP>>() {
  191. @NotNull
  192. @Override
  193. protected Map<String, LocalInspectionEP> compute() {
  194. HashMap<String, LocalInspectionEP> map = new HashMap<String, LocalInspectionEP>();
  195. for (LocalInspectionEP ep : Extensions.getExtensions(LocalInspectionEP.LOCAL_INSPECTION)) {
  196. map.put(ep.getShortName(), ep);
  197. }
  198. return map;
  199. }
  200. };
  201. }