Inspections #ref ancor should honor range if present.
[fedora-idea.git] / platform / lang-impl / src / com / intellij / codeInsight / daemon / impl / LocalInspectionsPass.java
bloba943ec93fe9779afdc188e92a9382032a70eef89
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.codeInspection.ui.ProblemDescriptionNode;
28 import com.intellij.concurrency.JobUtil;
29 import com.intellij.injected.editor.DocumentWindow;
30 import com.intellij.lang.Language;
31 import com.intellij.lang.annotation.HighlightSeverity;
32 import com.intellij.lang.injection.InjectedLanguageManager;
33 import com.intellij.openapi.actionSystem.IdeActions;
34 import com.intellij.openapi.application.ApplicationManager;
35 import com.intellij.openapi.diagnostic.Logger;
36 import com.intellij.openapi.editor.Document;
37 import com.intellij.openapi.editor.colors.CodeInsightColors;
38 import com.intellij.openapi.editor.colors.TextAttributesKey;
39 import com.intellij.openapi.keymap.Keymap;
40 import com.intellij.openapi.keymap.KeymapManager;
41 import com.intellij.openapi.keymap.KeymapUtil;
42 import com.intellij.openapi.progress.ProgressIndicator;
43 import com.intellij.openapi.progress.ProgressManager;
44 import com.intellij.openapi.progress.util.ProgressWrapper;
45 import com.intellij.openapi.project.DumbAware;
46 import com.intellij.openapi.project.DumbService;
47 import com.intellij.openapi.util.IconLoader;
48 import com.intellij.openapi.util.TextRange;
49 import com.intellij.openapi.util.text.StringUtil;
50 import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
51 import com.intellij.psi.*;
52 import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
53 import com.intellij.util.Processor;
54 import com.intellij.util.SmartList;
55 import com.intellij.util.containers.ContainerUtil;
56 import com.intellij.xml.util.XmlStringUtil;
57 import gnu.trove.THashMap;
58 import gnu.trove.THashSet;
59 import org.jetbrains.annotations.NonNls;
60 import org.jetbrains.annotations.NotNull;
61 import org.jetbrains.annotations.Nullable;
63 import javax.swing.*;
64 import java.util.*;
66 /**
67 * @author max
69 public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass implements DumbAware {
70 private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.LocalInspectionsPass");
71 private final int myStartOffset;
72 private final int myEndOffset;
73 @NotNull private List<ProblemDescriptor> myDescriptors = Collections.emptyList();
74 @NotNull private List<HighlightInfoType> myLevels = Collections.emptyList();
75 @NotNull private List<LocalInspectionTool> myTools = Collections.emptyList();
76 @NotNull private List<InjectedPsiInspectionResult> myInjectedPsiInspectionResults = Collections.emptyList();
77 static final String PRESENTABLE_NAME = DaemonBundle.message("pass.inspection");
78 private volatile List<HighlightInfo> myInfos = Collections.emptyList();
79 static final Icon IN_PROGRESS_ICON = IconLoader.getIcon("/general/inspectionInProgress.png");
80 private final String myShortcutText;
81 private final SeverityRegistrar mySeverityRegistrar;
83 public LocalInspectionsPass(@NotNull PsiFile file, @Nullable Document document, int startOffset, int endOffset) {
84 super(file.getProject(), document, IN_PROGRESS_ICON, PRESENTABLE_NAME, file, true);
85 myStartOffset = startOffset;
86 myEndOffset = endOffset;
87 setId(Pass.LOCAL_INSPECTIONS);
89 final KeymapManager keymapManager = KeymapManager.getInstance();
90 if (keymapManager != null) {
91 final Keymap keymap = keymapManager.getActiveKeymap();
92 myShortcutText = keymap == null ? "" : "(" + KeymapUtil.getShortcutsText(keymap.getShortcuts(IdeActions.ACTION_SHOW_ERROR_DESCRIPTION)) + ")";
94 else {
95 myShortcutText = "";
97 mySeverityRegistrar = SeverityRegistrar.getInstance(myProject);
100 protected void collectInformationWithProgress(final ProgressIndicator progress) {
101 myDescriptors = new ArrayList<ProblemDescriptor>();
102 myLevels = new ArrayList<HighlightInfoType>();
103 myTools = new ArrayList<LocalInspectionTool>();
104 long startTime = System.nanoTime();
105 inspectRoot();
106 long endTime = System.nanoTime();
107 if (LOG.isDebugEnabled()) {
108 LOG.debug("Inspections for " + myFile.getName() + " completed in " + (endTime - startTime) / 1000000 + " ms");
112 private void inspectRoot() {
113 if (!HighlightLevelUtil.shouldInspect(myFile)) return;
114 final InspectionManagerEx iManager = (InspectionManagerEx)InspectionManager.getInstance(myProject);
115 final InspectionProfileWrapper profile = InspectionProjectProfileManager.getInstance(myProject).getProfileWrapper();
116 final List<LocalInspectionTool> tools = DumbService.getInstance(myProject).filterByDumbAwareness(getInspectionTools(profile));
118 inspect(tools, iManager, true, true);
121 public void doInspectInBatch(final InspectionManagerEx iManager, InspectionProfileEntry[] toolWrappers, boolean ignoreSuppressed) {
122 myDescriptors = new ArrayList<ProblemDescriptor>();
123 myLevels = new ArrayList<HighlightInfoType>();
124 myTools = new ArrayList<LocalInspectionTool>();
126 Map<LocalInspectionTool, LocalInspectionToolWrapper> tool2Wrapper = new THashMap<LocalInspectionTool, LocalInspectionToolWrapper>(toolWrappers.length);
127 for (InspectionProfileEntry toolWrapper : toolWrappers) {
128 tool2Wrapper.put(((LocalInspectionToolWrapper)toolWrapper).getTool(), (LocalInspectionToolWrapper)toolWrapper);
130 List<LocalInspectionTool> tools = new ArrayList<LocalInspectionTool>(tool2Wrapper.keySet());
131 inspect(tools, iManager, false, ignoreSuppressed);
132 addDescriptorsFromInjectedResults(tool2Wrapper, iManager);
133 for (int i = 0; i < myTools.size(); i++) {
134 final LocalInspectionTool tool = myTools.get(i);
135 ProblemDescriptor descriptor = myDescriptors.get(i);
136 LocalInspectionToolWrapper toolWrapper = tool2Wrapper.get(tool);
138 toolWrapper.addProblemDescriptors(Collections.singletonList(descriptor), true);
142 private void addDescriptorsFromInjectedResults(Map<LocalInspectionTool, LocalInspectionToolWrapper> tool2Wrapper,
143 InspectionManagerEx iManager) {
144 Set<TextRange> emptyActionRegistered = new THashSet<TextRange>();
145 InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile();
146 InjectedLanguageManager ilManager = InjectedLanguageManager.getInstance(myProject);
147 PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject);
148 //noinspection ForLoopReplaceableByForEach
149 for (int i = 0; i < myInjectedPsiInspectionResults.size(); i++) {
150 InjectedPsiInspectionResult result = myInjectedPsiInspectionResults.get(i);
151 LocalInspectionTool tool = result.tool;
152 HighlightSeverity severity = inspectionProfile.getErrorLevel(HighlightDisplayKey.find(tool.getShortName()), myFile).getSeverity();
154 PsiElement injectedPsi = result.injectedPsi;
155 DocumentWindow documentRange = (DocumentWindow)documentManager.getDocument((PsiFile)injectedPsi);
156 if (documentRange == null) continue;
157 //noinspection ForLoopReplaceableByForEach
158 for (int j = 0; j < result.foundProblems.size(); j++) {
159 ProblemDescriptor descriptor = result.foundProblems.get(j);
160 PsiElement psiElement = descriptor.getPsiElement();
161 if (InspectionManagerEx.inspectionResultSuppressed(psiElement, tool)) continue;
162 HighlightInfoType level = highlightTypeFromDescriptor(descriptor, severity);
163 HighlightInfo info = createHighlightInfo(descriptor, tool, level,emptyActionRegistered);
164 if (info == null) continue;
165 List<TextRange> editables = ilManager.intersectWithAllEditableFragments((PsiFile)injectedPsi, new TextRange(info.startOffset, info.endOffset));
166 for (TextRange editable : editables) {
167 TextRange hostRange = documentRange.injectedToHost(editable);
168 QuickFix[] fixes = descriptor.getFixes();
169 LocalQuickFix[] localFixes = null;
170 if (fixes != null) {
171 localFixes = new LocalQuickFix[fixes.length];
172 for (int k = 0; k < fixes.length; k++) {
173 QuickFix fix = fixes[k];
174 localFixes[k] = (LocalQuickFix)fix;
177 ProblemDescriptor patchedDescriptor = iManager.createProblemDescriptor(myFile, hostRange, descriptor.getDescriptionTemplate(),
178 descriptor.getHighlightType(),
179 localFixes);
180 LocalInspectionToolWrapper toolWrapper = tool2Wrapper.get(tool);
181 toolWrapper.addProblemDescriptors(Collections.singletonList(patchedDescriptor), true);
187 private void inspect(final List<LocalInspectionTool> tools, final InspectionManagerEx iManager, final boolean isOnTheFly, final boolean ignoreSuppressed) {
188 if (tools.isEmpty()) return;
189 final PsiElement[] elements = getElementsIntersectingRange(myFile, myStartOffset, myEndOffset);
191 setProgressLimit(1L * tools.size() * elements.length);
192 final LocalInspectionToolSession session = new LocalInspectionToolSession(myFile, myStartOffset, myEndOffset);
193 final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
194 LOG.assertTrue(indicator != null);
196 JobUtil.invokeConcurrentlyUnderMyProgress(tools, new Processor<LocalInspectionTool>() {
197 public boolean process(final LocalInspectionTool tool) {
198 final ProgressManager progressManager = ProgressManager.getInstance();
199 ProgressManager.checkCanceled();
200 ProgressIndicator localIndicator = progressManager.getProgressIndicator();
202 ProgressIndicator original = ((ProgressWrapper)localIndicator).getOriginalProgressIndicator();
203 LOG.assertTrue(original == indicator, original);
205 ApplicationManager.getApplication().assertReadAccessAllowed();
207 ProblemsHolder holder = new ProblemsHolder(iManager, myFile);
208 PsiElementVisitor elementVisitor = tool.buildVisitor(holder, isOnTheFly);
209 //noinspection ConstantConditions
210 if(elementVisitor == null) {
211 LOG.error("Tool " + tool + " must not return null from the buildVisitor() method");
213 tool.inspectionStarted(session);
214 for (PsiElement element : elements) {
215 ProgressManager.checkCanceled();
216 element.accept(elementVisitor);
218 tool.inspectionFinished(session);
219 advanceProgress(elements.length);
221 if (holder.hasResults()) {
222 appendDescriptors(holder.getResults(), tool, ignoreSuppressed);
224 return true;
226 }, "Inspection tools");
227 ProgressManager.checkCanceled();
229 inspectInjectedPsi(elements, tools);
231 myInfos = new ArrayList<HighlightInfo>(myDescriptors.size());
232 addHighlightsFromDescriptors(myInfos);
233 addHighlightsFromInjectedPsiProblems(myInfos);
236 void inspectInjectedPsi(final PsiElement[] elements, final List<LocalInspectionTool> tools) {
237 myInjectedPsiInspectionResults = ContainerUtil.createEmptyCOWList();
238 final Set<PsiFile> injected = new THashSet<PsiFile>();
239 for (PsiElement element : elements) {
240 InjectedLanguageUtil.enumerate(element, myFile, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
241 public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
242 injected.add(injectedPsi);
244 }, false);
246 JobUtil.invokeConcurrentlyUnderMyProgress(injected, new Processor<PsiFile>() {
247 public boolean process(final PsiFile injectedPsi) {
248 inspectInjectedPsi(injectedPsi, myInjectedPsiInspectionResults, tools);
249 return true;
251 }, "Inspect injected fragments");
254 public Collection<HighlightInfo> getHighlights() {
255 ArrayList<HighlightInfo> highlights = new ArrayList<HighlightInfo>(myDescriptors.size());
256 addHighlightsFromDescriptors(highlights);
257 addHighlightsFromInjectedPsiProblems(highlights);
258 return highlights;
261 private static HighlightInfo highlightInfoFromDescriptor(final ProblemDescriptor problemDescriptor,
262 final HighlightInfoType highlightInfoType,
263 final String message,
264 final String toolTip) {
265 TextRange textRange = ((ProblemDescriptorImpl)problemDescriptor).getTextRange();
266 PsiElement element = problemDescriptor.getPsiElement();
267 boolean isFileLevel = element instanceof PsiFile && textRange.equals(element.getTextRange());
268 HighlightInfo highlightInfo = new HighlightInfo(null, highlightInfoType, textRange.getStartOffset(), textRange.getEndOffset(), message,
269 toolTip, highlightInfoType.getSeverity(element), problemDescriptor.isAfterEndOfLine(), null,
270 isFileLevel);
272 return highlightInfo;
275 private synchronized void appendDescriptors(List<ProblemDescriptor> problemDescriptors, LocalInspectionTool tool, boolean ignoreSuppressed) {
276 if (problemDescriptors == null) return;
277 InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile();
278 final HighlightSeverity severity = inspectionProfile.getErrorLevel(HighlightDisplayKey.find(tool.getShortName()), myFile).getSeverity();
279 for (ProblemDescriptor problemDescriptor : problemDescriptors) {
280 ProgressManager.checkCanceled();
281 if (!(ignoreSuppressed && InspectionManagerEx.inspectionResultSuppressed(problemDescriptor.getPsiElement(), tool))) {
282 myDescriptors.add(problemDescriptor);
283 HighlightInfoType type = highlightTypeFromDescriptor(problemDescriptor, severity);
284 myLevels.add(type);
285 myTools.add(tool);
290 @NotNull
291 private HighlightInfoType highlightTypeFromDescriptor(final ProblemDescriptor problemDescriptor, final HighlightSeverity severity) {
292 final ProblemHighlightType highlightType = problemDescriptor.getHighlightType();
293 switch (highlightType) {
294 case GENERIC_ERROR_OR_WARNING:
295 return mySeverityRegistrar.getHighlightInfoTypeBySeverity(severity);
296 case LIKE_DEPRECATED:
297 return new HighlightInfoType.HighlightInfoTypeImpl(severity, HighlightInfoType.DEPRECATED.getAttributesKey());
298 case LIKE_UNKNOWN_SYMBOL:
299 if (severity == HighlightSeverity.ERROR) {
300 return new HighlightInfoType.HighlightInfoTypeImpl(severity, HighlightInfoType.WRONG_REF.getAttributesKey());
302 else if (severity == HighlightSeverity.WARNING) {
303 return new HighlightInfoType.HighlightInfoTypeImpl(severity, CodeInsightColors.INFO_ATTRIBUTES);
305 else {
306 return mySeverityRegistrar.getHighlightInfoTypeBySeverity(severity);
308 case LIKE_UNUSED_SYMBOL:
309 return new HighlightInfoType.HighlightInfoTypeImpl(severity, HighlightInfoType.UNUSED_SYMBOL.getAttributesKey());
310 case INFO:
311 return HighlightInfoType.INFO;
312 case ERROR:
313 return HighlightInfoType.WRONG_REF;
314 case GENERIC_ERROR:
315 return HighlightInfoType.ERROR;
316 case INFORMATION:
317 final TextAttributesKey attributes = ((ProblemDescriptorImpl)problemDescriptor).getEnforcedTextAttributes();
318 if (attributes != null) {
319 return new HighlightInfoType.HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, attributes);
321 return HighlightInfoType.INFORMATION;
323 throw new RuntimeException("Cannot map " + highlightType);
326 protected void applyInformationWithProgress() {
327 UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, myStartOffset, myEndOffset, myInfos, getId());
330 private void addHighlightsFromDescriptors(final List<HighlightInfo> toInfos) {
331 Set<TextRange> emptyActionRegistered = new THashSet<TextRange>();
332 for (int i = 0; i < myDescriptors.size(); i++) {
333 ProblemDescriptor descriptor = myDescriptors.get(i);
334 LocalInspectionTool tool = myTools.get(i);
335 final HighlightInfoType level = myLevels.get(i);
336 HighlightInfo highlightInfo = createHighlightInfo(descriptor, tool, level, emptyActionRegistered);
337 if (highlightInfo != null) {
338 toInfos.add(highlightInfo);
343 private void addHighlightsFromInjectedPsiProblems(final List<HighlightInfo> infos) {
344 Set<TextRange> emptyActionRegistered = new THashSet<TextRange>();
345 InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile();
346 PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject);
347 InjectedLanguageManager ilManager = InjectedLanguageManager.getInstance(myProject);
348 for (InjectedPsiInspectionResult result : myInjectedPsiInspectionResults) {
349 LocalInspectionTool tool = result.tool;
350 HighlightSeverity severity = inspectionProfile.getErrorLevel(HighlightDisplayKey.find(tool.getShortName()), myFile).getSeverity();
352 PsiElement injectedPsi = result.injectedPsi;
353 DocumentWindow documentRange = (DocumentWindow)documentManager.getDocument((PsiFile)injectedPsi);
354 if (documentRange == null) continue;
355 //noinspection ForLoopReplaceableByForEach
356 for (int j = 0; j < result.foundProblems.size(); j++) {
357 ProblemDescriptor descriptor = result.foundProblems.get(j);
358 PsiElement psiElement = descriptor.getPsiElement();
359 if (InspectionManagerEx.inspectionResultSuppressed(psiElement, tool)) continue;
360 HighlightInfoType level = highlightTypeFromDescriptor(descriptor, severity);
361 HighlightInfo info = createHighlightInfo(descriptor, tool, level, emptyActionRegistered);
362 if (info == null) continue;
364 // todo we got to separate our "internal" prefixes/suffixes from user-defined ones
365 // todo in the latter case the erors should be highlighted, otherwise not
366 List<TextRange> editables =
367 ilManager.intersectWithAllEditableFragments((PsiFile)injectedPsi, new TextRange(info.startOffset, info.endOffset));
368 for (TextRange editable : editables) {
369 TextRange hostRange = documentRange.injectedToHost(editable);
370 HighlightInfo patched = HighlightInfo.createHighlightInfo(info.type, psiElement, hostRange.getStartOffset(), hostRange.getEndOffset(), info.description, info.toolTip);
371 if (patched != null) {
372 registerQuickFixes(tool, descriptor, patched, emptyActionRegistered);
373 infos.add(patched);
380 @Nullable
381 private HighlightInfo createHighlightInfo(final ProblemDescriptor descriptor, final LocalInspectionTool tool, final HighlightInfoType level,
382 final Set<TextRange> emptyActionRegistered) {
383 PsiElement psiElement = descriptor.getPsiElement();
384 if (psiElement == null) return null;
385 @NonNls String message = renderDescriptionMessage(descriptor);
387 final HighlightDisplayKey key = HighlightDisplayKey.find(tool.getShortName());
388 final InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile();
389 if (!inspectionProfile.isToolEnabled(key, myFile)) return null;
391 HighlightInfoType type = new HighlightInfoType.HighlightInfoTypeImpl(level.getSeverity(psiElement), level.getAttributesKey());
392 final String plainMessage = message.startsWith("<html>") ? StringUtil.unescapeXml(message.replaceAll("<[^>]*>", "")) : message;
393 @NonNls final String link = "<a href=\"#inspection/" + tool.getShortName() + "\"> " + DaemonBundle.message("inspection.extended.description") +
394 "</a>" + myShortcutText;
396 @NonNls String tooltip = null;
397 if (descriptor.showTooltip()) {
398 if (message.startsWith("<html>")) {
399 tooltip = message.contains("</body>") ? message.replace("</body>", link + "</body>") : message.replace("</html>", link + "</html>");
401 else {
402 tooltip = "<html><body>" + XmlStringUtil.escapeString(message) + link + "</body></html>";
405 HighlightInfo highlightInfo = highlightInfoFromDescriptor(descriptor, type, plainMessage, tooltip);
406 registerQuickFixes(tool, descriptor, highlightInfo, emptyActionRegistered);
407 return highlightInfo;
410 private static void registerQuickFixes(final LocalInspectionTool tool, final ProblemDescriptor descriptor,
411 final HighlightInfo highlightInfo, final Set<TextRange> emptyActionRegistered) {
412 final HighlightDisplayKey key = HighlightDisplayKey.find(tool.getShortName());
413 boolean needEmptyAction = true;
414 final QuickFix[] fixes = descriptor.getFixes();
415 if (fixes != null && fixes.length > 0) {
416 for (int k = 0; k < fixes.length; k++) {
417 if (fixes[k] != null) { // prevent null fixes from var args
418 QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixWrapper.wrap(descriptor, k), key);
419 needEmptyAction = false;
423 HintAction hintAction = ((ProblemDescriptorImpl)descriptor).getHintAction();
424 if (hintAction != null) {
425 QuickFixAction.registerQuickFixAction(highlightInfo, hintAction, key);
426 needEmptyAction = false;
428 if (((ProblemDescriptorImpl)descriptor).getEnforcedTextAttributes() != null) {
429 needEmptyAction = false;
431 if (needEmptyAction && emptyActionRegistered.add(new TextRange(highlightInfo.fixStartOffset, highlightInfo.fixEndOffset))) {
432 EmptyIntentionAction emptyIntentionAction = new EmptyIntentionAction(tool.getDisplayName());
433 QuickFixAction.registerQuickFixAction(highlightInfo, emptyIntentionAction, key);
437 private static String renderDescriptionMessage(ProblemDescriptor descriptor) {
438 PsiElement psiElement = descriptor.getPsiElement();
439 String message = descriptor.getDescriptionTemplate();
441 // no message. Should not be the case if inspection correctly implemented.
442 // noinspection ConstantConditions
443 if (message == null) return "";
445 message = StringUtil.replace(message, "<code>", "'");
446 message = StringUtil.replace(message, "</code>", "'");
447 //message = message.replaceAll("<[^>]*>", "");
448 String ref = ProblemDescriptionNode.extractHighlightedText(descriptor, psiElement);
449 message = StringUtil.replace(message, "#loc", "");
450 message = StringUtil.replace(message, "#ref", ref);
452 message = StringUtil.unescapeXml(message).trim();
453 return message;
456 public static PsiElement[] getElementsIntersectingRange(PsiFile file, final int startOffset, final int endOffset) {
457 final FileViewProvider viewProvider = file.getViewProvider();
458 final Set<PsiElement> result = new LinkedHashSet<PsiElement>();
459 for (Language language : viewProvider.getLanguages()) {
460 final PsiFile psiRoot = viewProvider.getPsi(language);
461 if (HighlightLevelUtil.shouldInspect(psiRoot)) {
462 result.addAll(CollectHighlightsUtil.getElementsInRange(psiRoot, startOffset, endOffset, true));
465 return result.toArray(new PsiElement[result.size()]);
468 List<LocalInspectionTool> getInspectionTools(InspectionProfileWrapper profile) {
469 return profile.getHighlightingLocalInspectionTools(myFile);
472 private static void inspectInjectedPsi(PsiFile injectedPsi, List<InjectedPsiInspectionResult> result, List<LocalInspectionTool> tools) {
473 InspectionManager inspectionManager = InspectionManager.getInstance(injectedPsi.getProject());
474 final ProblemsHolder problemsHolder = new ProblemsHolder(inspectionManager, injectedPsi);
475 final PsiElement host = injectedPsi.getContext();
477 final PsiElement[] elements = getElementsIntersectingRange(injectedPsi, 0, injectedPsi.getTextLength());
478 if (elements.length != 0) {
479 for (LocalInspectionTool tool : tools) {
480 if (host != null && InspectionManagerEx.inspectionResultSuppressed(host, tool)) {
481 continue;
483 final PsiElementVisitor visitor = tool.buildVisitor(problemsHolder, true);
484 assert !(visitor instanceof PsiRecursiveElementVisitor) : "The visitor returned from LocalInspectionTool.buildVisitor() must not be recursive. "+tool;
485 for (PsiElement element : elements) {
486 element.accept(visitor);
488 List<ProblemDescriptor> problems = problemsHolder.getResults();
489 if (problems != null && !problems.isEmpty()) {
490 InjectedPsiInspectionResult res = new InjectedPsiInspectionResult(tool, injectedPsi, new SmartList<ProblemDescriptor>(problems));
491 result.add(res);
497 public List<HighlightInfo> getInfos() {
498 return myInfos;
501 private static class InjectedPsiInspectionResult {
502 public final LocalInspectionTool tool;
503 public final PsiElement injectedPsi;
504 public final List<ProblemDescriptor> foundProblems;
506 private InjectedPsiInspectionResult(final LocalInspectionTool tool, final PsiElement injectedPsi, final List<ProblemDescriptor> foundProblems) {
507 this.tool = tool;
508 this.injectedPsi = injectedPsi;
509 this.foundProblems = foundProblems;