processor should return false if terminated by ProcessCanceledException
[fedora-idea.git] / platform / lang-impl / src / com / intellij / codeInsight / daemon / impl / LocalInspectionsPass.java
blobc6ed79d3d02887db3eff5c47930003385d6a70ba
1 /*
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.
17 package com.intellij.codeInsight.daemon.impl;
19 import com.intellij.codeHighlighting.Pass;
20 import com.intellij.codeInsight.daemon.DaemonBundle;
21 import com.intellij.codeInsight.daemon.HighlightDisplayKey;
22 import com.intellij.codeInsight.daemon.impl.analysis.HighlightLevelUtil;
23 import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
24 import com.intellij.codeInsight.intention.EmptyIntentionAction;
25 import com.intellij.codeInspection.*;
26 import com.intellij.codeInspection.ex.*;
27 import com.intellij.concurrency.JobUtil;
28 import com.intellij.injected.editor.DocumentWindow;
29 import com.intellij.lang.Language;
30 import com.intellij.lang.annotation.HighlightSeverity;
31 import com.intellij.lang.injection.InjectedLanguageManager;
32 import com.intellij.openapi.actionSystem.IdeActions;
33 import com.intellij.openapi.application.ApplicationManager;
34 import com.intellij.openapi.diagnostic.Logger;
35 import com.intellij.openapi.editor.Document;
36 import com.intellij.openapi.editor.colors.CodeInsightColors;
37 import com.intellij.openapi.editor.colors.TextAttributesKey;
38 import com.intellij.openapi.keymap.Keymap;
39 import com.intellij.openapi.keymap.KeymapManager;
40 import com.intellij.openapi.keymap.KeymapUtil;
41 import com.intellij.openapi.progress.ProcessCanceledException;
42 import com.intellij.openapi.progress.ProgressIndicator;
43 import com.intellij.openapi.progress.ProgressManager;
44 import com.intellij.openapi.project.DumbAware;
45 import com.intellij.openapi.project.DumbService;
46 import com.intellij.openapi.util.IconLoader;
47 import com.intellij.openapi.util.TextRange;
48 import com.intellij.openapi.util.text.StringUtil;
49 import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
50 import com.intellij.psi.*;
51 import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
52 import com.intellij.util.Processor;
53 import com.intellij.util.SmartList;
54 import com.intellij.util.containers.ContainerUtil;
55 import com.intellij.xml.util.XmlStringUtil;
56 import gnu.trove.THashMap;
57 import gnu.trove.THashSet;
58 import org.jetbrains.annotations.NonNls;
59 import org.jetbrains.annotations.NotNull;
60 import org.jetbrains.annotations.Nullable;
62 import javax.swing.*;
63 import java.util.*;
65 /**
66 * @author max
68 public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass implements DumbAware {
69 private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.LocalInspectionsPass");
70 private final int myStartOffset;
71 private final int myEndOffset;
72 @NotNull private List<ProblemDescriptor> myDescriptors = Collections.emptyList();
73 @NotNull private List<HighlightInfoType> myLevels = Collections.emptyList();
74 @NotNull private List<LocalInspectionTool> myTools = Collections.emptyList();
75 @NotNull private List<InjectedPsiInspectionResult> myInjectedPsiInspectionResults = Collections.emptyList();
76 static final String PRESENTABLE_NAME = DaemonBundle.message("pass.inspection");
77 private volatile List<HighlightInfo> myInfos = Collections.emptyList();
78 static final Icon IN_PROGRESS_ICON = IconLoader.getIcon("/general/inspectionInProgress.png");
79 private final String myShortcutText;
80 private final SeverityRegistrar mySeverityRegistrar;
82 public LocalInspectionsPass(@NotNull PsiFile file, @Nullable Document document, int startOffset, int endOffset) {
83 super(file.getProject(), document, IN_PROGRESS_ICON, PRESENTABLE_NAME, file, true);
84 myStartOffset = startOffset;
85 myEndOffset = endOffset;
86 setId(Pass.LOCAL_INSPECTIONS);
88 final KeymapManager keymapManager = KeymapManager.getInstance();
89 if (keymapManager != null) {
90 final Keymap keymap = keymapManager.getActiveKeymap();
91 myShortcutText = keymap == null ? "" : "(" + KeymapUtil.getShortcutsText(keymap.getShortcuts(IdeActions.ACTION_SHOW_ERROR_DESCRIPTION)) + ")";
93 else {
94 myShortcutText = "";
96 mySeverityRegistrar = SeverityRegistrar.getInstance(myProject);
99 protected void collectInformationWithProgress(final ProgressIndicator progress) {
100 myDescriptors = new ArrayList<ProblemDescriptor>();
101 myLevels = new ArrayList<HighlightInfoType>();
102 myTools = new ArrayList<LocalInspectionTool>();
103 long startTime = System.nanoTime();
104 inspectRoot();
105 long endTime = System.nanoTime();
106 if (LOG.isDebugEnabled()) {
107 LOG.debug("Inspections for " + myFile.getName() + " completed in " + (endTime - startTime) / 1000000 + " ms");
111 private void inspectRoot() {
112 if (!HighlightLevelUtil.shouldInspect(myFile)) return;
113 final InspectionManagerEx iManager = (InspectionManagerEx)InspectionManager.getInstance(myProject);
114 final InspectionProfileWrapper profile = InspectionProjectProfileManager.getInstance(myProject).getProfileWrapper();
115 final List<LocalInspectionTool> tools = DumbService.getInstance(myProject).filterByDumbAwareness(getInspectionTools(profile));
117 inspect(tools, iManager, true, true);
120 public void doInspectInBatch(final InspectionManagerEx iManager, InspectionProfileEntry[] toolWrappers, boolean ignoreSuppressed) {
121 myDescriptors = new ArrayList<ProblemDescriptor>();
122 myLevels = new ArrayList<HighlightInfoType>();
123 myTools = new ArrayList<LocalInspectionTool>();
125 Map<LocalInspectionTool, LocalInspectionToolWrapper> tool2Wrapper = new THashMap<LocalInspectionTool, LocalInspectionToolWrapper>(toolWrappers.length);
126 for (InspectionProfileEntry toolWrapper : toolWrappers) {
127 tool2Wrapper.put(((LocalInspectionToolWrapper)toolWrapper).getTool(), (LocalInspectionToolWrapper)toolWrapper);
129 List<LocalInspectionTool> tools = new ArrayList<LocalInspectionTool>(tool2Wrapper.keySet());
130 inspect(tools, iManager, false, ignoreSuppressed);
131 addDescriptorsFromInjectedResults(tool2Wrapper, iManager);
132 for (int i = 0; i < myTools.size(); i++) {
133 final LocalInspectionTool tool = myTools.get(i);
134 ProblemDescriptor descriptor = myDescriptors.get(i);
135 LocalInspectionToolWrapper toolWrapper = tool2Wrapper.get(tool);
137 toolWrapper.addProblemDescriptors(Collections.singletonList(descriptor), true);
141 private void addDescriptorsFromInjectedResults(Map<LocalInspectionTool, LocalInspectionToolWrapper> tool2Wrapper,
142 InspectionManagerEx iManager) {
143 Set<TextRange> emptyActionRegistered = new THashSet<TextRange>();
144 InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile();
145 InjectedLanguageManager ilManager = InjectedLanguageManager.getInstance(myProject);
146 PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject);
147 //noinspection ForLoopReplaceableByForEach
148 for (int i = 0; i < myInjectedPsiInspectionResults.size(); i++) {
149 InjectedPsiInspectionResult result = myInjectedPsiInspectionResults.get(i);
150 LocalInspectionTool tool = result.tool;
151 HighlightSeverity severity = inspectionProfile.getErrorLevel(HighlightDisplayKey.find(tool.getShortName()), myFile).getSeverity();
153 PsiElement injectedPsi = result.injectedPsi;
154 DocumentWindow documentRange = (DocumentWindow)documentManager.getDocument((PsiFile)injectedPsi);
155 if (documentRange == null) continue;
156 //noinspection ForLoopReplaceableByForEach
157 for (int j = 0; j < result.foundProblems.size(); j++) {
158 ProblemDescriptor descriptor = result.foundProblems.get(j);
159 PsiElement psiElement = descriptor.getPsiElement();
160 if (InspectionManagerEx.inspectionResultSuppressed(psiElement, tool)) continue;
161 HighlightInfoType level = highlightTypeFromDescriptor(descriptor, severity);
162 HighlightInfo info = createHighlightInfo(descriptor, tool, level,emptyActionRegistered);
163 if (info == null) continue;
164 List<TextRange> editables = ilManager.intersectWithAllEditableFragments((PsiFile)injectedPsi, new TextRange(info.startOffset, info.endOffset));
165 for (TextRange editable : editables) {
166 TextRange hostRange = documentRange.injectedToHost(editable);
167 QuickFix[] fixes = descriptor.getFixes();
168 LocalQuickFix[] localFixes = null;
169 if (fixes != null) {
170 localFixes = new LocalQuickFix[fixes.length];
171 for (int k = 0; k < fixes.length; k++) {
172 QuickFix fix = fixes[k];
173 localFixes[k] = (LocalQuickFix)fix;
176 ProblemDescriptor patchedDescriptor = iManager.createProblemDescriptor(myFile, hostRange, descriptor.getDescriptionTemplate(),
177 descriptor.getHighlightType(),
178 localFixes);
179 LocalInspectionToolWrapper toolWrapper = tool2Wrapper.get(tool);
180 toolWrapper.addProblemDescriptors(Collections.singletonList(patchedDescriptor), true);
186 private void inspect(final List<LocalInspectionTool> tools, final InspectionManagerEx iManager, final boolean isOnTheFly, final boolean ignoreSuppressed) {
187 if (tools.isEmpty()) return;
188 final PsiElement[] elements = getElementsIntersectingRange(myFile, myStartOffset, myEndOffset);
190 setProgressLimit(1L * tools.size() * elements.length);
191 final LocalInspectionToolSession session = new LocalInspectionToolSession(myFile, myStartOffset, myEndOffset);
193 JobUtil.invokeConcurrentlyUnderMyProgress(tools, new Processor<LocalInspectionTool>() {
194 public boolean process(final LocalInspectionTool tool) {
195 final ProgressManager progressManager = ProgressManager.getInstance();
196 try {
197 progressManager.checkCanceled();
199 ApplicationManager.getApplication().assertReadAccessAllowed();
201 ProblemsHolder holder = new ProblemsHolder(iManager, myFile);
202 progressManager.checkCanceled();
203 PsiElementVisitor elementVisitor = tool.buildVisitor(holder, isOnTheFly);
204 //noinspection ConstantConditions
205 if(elementVisitor == null) {
206 LOG.error("Tool " + tool + " must not return null from the buildVisitor() method");
208 tool.inspectionStarted(session);
209 for (PsiElement element : elements) {
210 progressManager.checkCanceled();
211 element.accept(elementVisitor);
213 tool.inspectionFinished(session);
214 advanceProgress(elements.length);
216 if (holder.hasResults()) {
217 appendDescriptors(holder.getResults(), tool, ignoreSuppressed);
219 return true;
221 catch (ProcessCanceledException e) {
222 return false;
225 }, "Inspection tools");
227 inspectInjectedPsi(elements, tools);
229 myInfos = new ArrayList<HighlightInfo>(myDescriptors.size());
230 addHighlightsFromDescriptors(myInfos);
231 addHighlightsFromInjectedPsiProblems(myInfos);
234 void inspectInjectedPsi(final PsiElement[] elements, final List<LocalInspectionTool> tools) {
235 myInjectedPsiInspectionResults = ContainerUtil.createEmptyCOWList();
236 final Set<PsiFile> injected = new THashSet<PsiFile>();
237 for (PsiElement element : elements) {
238 InjectedLanguageUtil.enumerate(element, myFile, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
239 public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
240 injected.add(injectedPsi);
242 }, false);
244 JobUtil.invokeConcurrentlyUnderMyProgress(injected, new Processor<PsiFile>() {
245 public boolean process(final PsiFile injectedPsi) {
246 inspectInjectedPsi(injectedPsi, myInjectedPsiInspectionResults, tools);
247 return true;
249 }, "Inspect injected fragments");
252 public Collection<HighlightInfo> getHighlights() {
253 ArrayList<HighlightInfo> highlights = new ArrayList<HighlightInfo>(myDescriptors.size());
254 addHighlightsFromDescriptors(highlights);
255 addHighlightsFromInjectedPsiProblems(highlights);
256 return highlights;
259 private static HighlightInfo highlightInfoFromDescriptor(final ProblemDescriptor problemDescriptor,
260 final HighlightInfoType highlightInfoType,
261 final String message,
262 final String toolTip) {
263 TextRange textRange = ((ProblemDescriptorImpl)problemDescriptor).getTextRange();
264 PsiElement element = problemDescriptor.getPsiElement();
265 boolean isFileLevel = element instanceof PsiFile && textRange.equals(element.getTextRange());
266 HighlightInfo highlightInfo = new HighlightInfo(null, highlightInfoType, textRange.getStartOffset(), textRange.getEndOffset(), message,
267 toolTip, highlightInfoType.getSeverity(element), problemDescriptor.isAfterEndOfLine(), null,
268 isFileLevel);
270 return highlightInfo;
273 private synchronized void appendDescriptors(List<ProblemDescriptor> problemDescriptors, LocalInspectionTool tool, boolean ignoreSuppressed) {
274 if (problemDescriptors == null) return;
275 InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile();
276 final HighlightSeverity severity = inspectionProfile.getErrorLevel(HighlightDisplayKey.find(tool.getShortName()), myFile).getSeverity();
277 ProgressManager progressManager = ProgressManager.getInstance();
278 for (ProblemDescriptor problemDescriptor : problemDescriptors) {
279 progressManager.checkCanceled();
280 if (!(ignoreSuppressed && InspectionManagerEx.inspectionResultSuppressed(problemDescriptor.getPsiElement(), tool))) {
281 myDescriptors.add(problemDescriptor);
282 HighlightInfoType type = highlightTypeFromDescriptor(problemDescriptor, severity);
283 myLevels.add(type);
284 myTools.add(tool);
289 @NotNull
290 private HighlightInfoType highlightTypeFromDescriptor(final ProblemDescriptor problemDescriptor, final HighlightSeverity severity) {
291 final ProblemHighlightType highlightType = problemDescriptor.getHighlightType();
292 switch (highlightType) {
293 case GENERIC_ERROR_OR_WARNING:
294 return mySeverityRegistrar.getHighlightInfoTypeBySeverity(severity);
295 case LIKE_DEPRECATED:
296 return new HighlightInfoType.HighlightInfoTypeImpl(severity, HighlightInfoType.DEPRECATED.getAttributesKey());
297 case LIKE_UNKNOWN_SYMBOL:
298 if (severity == HighlightSeverity.ERROR) {
299 return new HighlightInfoType.HighlightInfoTypeImpl(severity, HighlightInfoType.WRONG_REF.getAttributesKey());
301 else if (severity == HighlightSeverity.WARNING) {
302 return new HighlightInfoType.HighlightInfoTypeImpl(severity, CodeInsightColors.INFO_ATTRIBUTES);
304 else {
305 return mySeverityRegistrar.getHighlightInfoTypeBySeverity(severity);
307 case LIKE_UNUSED_SYMBOL:
308 return new HighlightInfoType.HighlightInfoTypeImpl(severity, HighlightInfoType.UNUSED_SYMBOL.getAttributesKey());
309 case INFO:
310 return HighlightInfoType.INFO;
311 case ERROR:
312 return HighlightInfoType.WRONG_REF;
313 case GENERIC_ERROR:
314 return HighlightInfoType.ERROR;
315 case INFORMATION:
316 final TextAttributesKey attributes = ((ProblemDescriptorImpl)problemDescriptor).getEnforcedTextAttributes();
317 if (attributes != null) {
318 return new HighlightInfoType.HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, attributes);
320 return HighlightInfoType.INFORMATION;
322 throw new RuntimeException("Cannot map " + highlightType);
325 protected void applyInformationWithProgress() {
326 UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, myStartOffset, myEndOffset, myInfos, getId());
329 private void addHighlightsFromDescriptors(final List<HighlightInfo> toInfos) {
330 Set<TextRange> emptyActionRegistered = new THashSet<TextRange>();
331 for (int i = 0; i < myDescriptors.size(); i++) {
332 ProblemDescriptor descriptor = myDescriptors.get(i);
333 LocalInspectionTool tool = myTools.get(i);
334 final HighlightInfoType level = myLevels.get(i);
335 HighlightInfo highlightInfo = createHighlightInfo(descriptor, tool, level, emptyActionRegistered);
336 if (highlightInfo != null) {
337 toInfos.add(highlightInfo);
342 private void addHighlightsFromInjectedPsiProblems(final List<HighlightInfo> infos) {
343 Set<TextRange> emptyActionRegistered = new THashSet<TextRange>();
344 InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile();
345 PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject);
346 InjectedLanguageManager ilManager = InjectedLanguageManager.getInstance(myProject);
347 for (InjectedPsiInspectionResult result : myInjectedPsiInspectionResults) {
348 LocalInspectionTool tool = result.tool;
349 HighlightSeverity severity = inspectionProfile.getErrorLevel(HighlightDisplayKey.find(tool.getShortName()), myFile).getSeverity();
351 PsiElement injectedPsi = result.injectedPsi;
352 DocumentWindow documentRange = (DocumentWindow)documentManager.getDocument((PsiFile)injectedPsi);
353 if (documentRange == null) continue;
354 //noinspection ForLoopReplaceableByForEach
355 for (int j = 0; j < result.foundProblems.size(); j++) {
356 ProblemDescriptor descriptor = result.foundProblems.get(j);
357 PsiElement psiElement = descriptor.getPsiElement();
358 if (InspectionManagerEx.inspectionResultSuppressed(psiElement, tool)) continue;
359 HighlightInfoType level = highlightTypeFromDescriptor(descriptor, severity);
360 HighlightInfo info = createHighlightInfo(descriptor, tool, level, emptyActionRegistered);
361 if (info == null) continue;
363 // todo we got to separate our "internal" prefixes/suffixes from user-defined ones
364 // todo in the latter case the erors should be highlighted, otherwise not
365 List<TextRange> editables =
366 ilManager.intersectWithAllEditableFragments((PsiFile)injectedPsi, new TextRange(info.startOffset, info.endOffset));
367 for (TextRange editable : editables) {
368 TextRange hostRange = documentRange.injectedToHost(editable);
369 HighlightInfo patched = HighlightInfo.createHighlightInfo(info.type, psiElement, hostRange.getStartOffset(), hostRange.getEndOffset(), info.description, info.toolTip);
370 if (patched != null) {
371 registerQuickFixes(tool, descriptor, patched, emptyActionRegistered);
372 infos.add(patched);
379 @Nullable
380 private HighlightInfo createHighlightInfo(final ProblemDescriptor descriptor, final LocalInspectionTool tool, final HighlightInfoType level,
381 final Set<TextRange> emptyActionRegistered) {
382 PsiElement psiElement = descriptor.getPsiElement();
383 if (psiElement == null) return null;
384 @NonNls String message = renderDescriptionMessage(descriptor);
386 final HighlightDisplayKey key = HighlightDisplayKey.find(tool.getShortName());
387 final InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile();
388 if (!inspectionProfile.isToolEnabled(key, myFile)) return null;
390 HighlightInfoType type = new HighlightInfoType.HighlightInfoTypeImpl(level.getSeverity(psiElement), level.getAttributesKey());
391 final String plainMessage = message.startsWith("<html>") ? StringUtil.unescapeXml(message.replaceAll("<[^>]*>", "")) : message;
392 @NonNls final String link = "<a href=\"#inspection/" + tool.getShortName() + "\"> " + DaemonBundle.message("inspection.extended.description") +
393 "</a>" + myShortcutText;
395 @NonNls String tooltip;
396 if (message.startsWith("<html>")) {
397 tooltip = message.contains("</body>") ? message.replace("</body>", link + "</body>") : message.replace("</html>", link + "</html>");
399 else {
400 tooltip = "<html><body>" + XmlStringUtil.escapeString(message) + link + "</body></html>";
402 HighlightInfo highlightInfo = highlightInfoFromDescriptor(descriptor, type, plainMessage, tooltip);
403 registerQuickFixes(tool, descriptor, highlightInfo, emptyActionRegistered);
404 return highlightInfo;
407 private static void registerQuickFixes(final LocalInspectionTool tool, final ProblemDescriptor descriptor,
408 final HighlightInfo highlightInfo, final Set<TextRange> emptyActionRegistered) {
409 final HighlightDisplayKey key = HighlightDisplayKey.find(tool.getShortName());
410 boolean needEmptyAction = true;
411 final QuickFix[] fixes = descriptor.getFixes();
412 if (fixes != null && fixes.length > 0) {
413 for (int k = 0; k < fixes.length; k++) {
414 if (fixes[k] != null) { // prevent null fixes from var args
415 QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixWrapper.wrap(descriptor, k), key);
416 needEmptyAction = false;
420 HintAction hintAction = ((ProblemDescriptorImpl)descriptor).getHintAction();
421 if (hintAction != null) {
422 QuickFixAction.registerQuickFixAction(highlightInfo, hintAction, key);
423 needEmptyAction = false;
425 if (((ProblemDescriptorImpl)descriptor).getEnforcedTextAttributes() != null) {
426 needEmptyAction = false;
428 if (needEmptyAction && emptyActionRegistered.add(new TextRange(highlightInfo.fixStartOffset, highlightInfo.fixEndOffset))) {
429 EmptyIntentionAction emptyIntentionAction = new EmptyIntentionAction(tool.getDisplayName());
430 QuickFixAction.registerQuickFixAction(highlightInfo, emptyIntentionAction, key);
434 private static String renderDescriptionMessage(ProblemDescriptor descriptor) {
435 PsiElement psiElement = descriptor.getPsiElement();
436 String message = descriptor.getDescriptionTemplate();
438 // no message. Should not be the case if inspection correctly implemented.
439 // noinspection ConstantConditions
440 if (message == null) return "";
442 message = StringUtil.replace(message, "<code>", "'");
443 message = StringUtil.replace(message, "</code>", "'");
444 //message = message.replaceAll("<[^>]*>", "");
445 String text = psiElement == null ? "" : psiElement.getText();
446 message = StringUtil.replace(message, "#loc", "");
447 message = StringUtil.replace(message, "#ref", text);
449 message = StringUtil.unescapeXml(message).trim();
450 return message;
453 public static PsiElement[] getElementsIntersectingRange(PsiFile file, final int startOffset, final int endOffset) {
454 final FileViewProvider viewProvider = file.getViewProvider();
455 final Set<PsiElement> result = new LinkedHashSet<PsiElement>();
456 for (Language language : viewProvider.getLanguages()) {
457 final PsiFile psiRoot = viewProvider.getPsi(language);
458 if (HighlightLevelUtil.shouldInspect(psiRoot)) {
459 result.addAll(CollectHighlightsUtil.getElementsInRange(psiRoot, startOffset, endOffset, true));
462 return result.toArray(new PsiElement[result.size()]);
465 List<LocalInspectionTool> getInspectionTools(InspectionProfileWrapper profile) {
466 return profile.getHighlightingLocalInspectionTools(myFile);
469 private static void inspectInjectedPsi(PsiFile injectedPsi, List<InjectedPsiInspectionResult> result, List<LocalInspectionTool> tools) {
470 InspectionManager inspectionManager = InspectionManager.getInstance(injectedPsi.getProject());
471 final ProblemsHolder problemsHolder = new ProblemsHolder(inspectionManager, injectedPsi);
472 final PsiElement host = injectedPsi.getContext();
473 for (LocalInspectionTool tool : tools) {
474 if (host != null && InspectionManagerEx.inspectionResultSuppressed(host, tool)) {
475 continue;
477 final PsiElementVisitor visitor = tool.buildVisitor(problemsHolder, true);
478 assert !(visitor instanceof PsiRecursiveElementVisitor) : "The visitor returned from LocalInspectionTool.buildVisitor() must not be recursive. "+tool;
479 injectedPsi.accept(new PsiRecursiveElementWalkingVisitor() {
480 @Override public void visitElement(PsiElement element) {
481 element.accept(visitor);
482 super.visitElement(element);
485 List<ProblemDescriptor> problems = problemsHolder.getResults();
486 if (problems != null && !problems.isEmpty()) {
487 InjectedPsiInspectionResult res = new InjectedPsiInspectionResult(tool, injectedPsi, new SmartList<ProblemDescriptor>(problems));
488 result.add(res);
493 public List<HighlightInfo> getInfos() {
494 return myInfos;
497 private static class InjectedPsiInspectionResult {
498 public final LocalInspectionTool tool;
499 public final PsiElement injectedPsi;
500 public final List<ProblemDescriptor> foundProblems;
502 private InjectedPsiInspectionResult(final LocalInspectionTool tool, final PsiElement injectedPsi, final List<ProblemDescriptor> foundProblems) {
503 this.tool = tool;
504 this.injectedPsi = injectedPsi;
505 this.foundProblems = foundProblems;