ComponentWithBrowseButton - optional remove listener on hide
[fedora-idea.git] / platform / lang-impl / src / com / intellij / codeInsight / daemon / impl / LocalInspectionsPass.java
blobc74efd2d06b18b425cb7a5d039b528c58a5ebd6f
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(), true, 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);
192 final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
193 LOG.assertTrue(indicator != null);
195 JobUtil.invokeConcurrentlyUnderMyProgress(tools, new Processor<LocalInspectionTool>() {
196 public boolean process(final LocalInspectionTool tool) {
197 final ProgressManager progressManager = ProgressManager.getInstance();
198 ProgressManager.checkCanceled();
199 ProgressIndicator localIndicator = progressManager.getProgressIndicator();
201 ProgressIndicator original = ((ProgressWrapper)localIndicator).getOriginalProgressIndicator();
202 LOG.assertTrue(original == indicator, original);
204 ApplicationManager.getApplication().assertReadAccessAllowed();
206 ProblemsHolder holder = new ProblemsHolder(iManager, myFile, isOnTheFly);
207 PsiElementVisitor elementVisitor = tool.buildVisitor(holder, isOnTheFly);
208 //noinspection ConstantConditions
209 if(elementVisitor == null) {
210 LOG.error("Tool " + tool + " must not return null from the buildVisitor() method");
212 tool.inspectionStarted(session);
213 for (PsiElement element : elements) {
214 ProgressManager.checkCanceled();
215 element.accept(elementVisitor);
217 tool.inspectionFinished(session);
218 advanceProgress(elements.length);
220 if (holder.hasResults()) {
221 appendDescriptors(holder.getResults(), tool, ignoreSuppressed);
223 return true;
225 }, "Inspection tools");
226 ProgressManager.checkCanceled();
228 inspectInjectedPsi(elements, tools);
230 myInfos = new ArrayList<HighlightInfo>(myDescriptors.size());
231 addHighlightsFromDescriptors(myInfos);
232 addHighlightsFromInjectedPsiProblems(myInfos);
235 void inspectInjectedPsi(final PsiElement[] elements, final List<LocalInspectionTool> tools) {
236 myInjectedPsiInspectionResults = ContainerUtil.createEmptyCOWList();
237 final Set<PsiFile> injected = new THashSet<PsiFile>();
238 for (PsiElement element : elements) {
239 InjectedLanguageUtil.enumerate(element, myFile, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
240 public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
241 injected.add(injectedPsi);
243 }, false);
245 JobUtil.invokeConcurrentlyUnderMyProgress(injected, new Processor<PsiFile>() {
246 public boolean process(final PsiFile injectedPsi) {
247 inspectInjectedPsi(injectedPsi, myInjectedPsiInspectionResults, tools);
248 return true;
250 }, "Inspect injected fragments");
253 public Collection<HighlightInfo> getHighlights() {
254 ArrayList<HighlightInfo> highlights = new ArrayList<HighlightInfo>(myDescriptors.size());
255 addHighlightsFromDescriptors(highlights);
256 addHighlightsFromInjectedPsiProblems(highlights);
257 return highlights;
260 private static HighlightInfo highlightInfoFromDescriptor(final ProblemDescriptor problemDescriptor,
261 final HighlightInfoType highlightInfoType,
262 final String message,
263 final String toolTip) {
264 TextRange textRange = ((ProblemDescriptorImpl)problemDescriptor).getTextRange();
265 PsiElement element = problemDescriptor.getPsiElement();
266 boolean isFileLevel = element instanceof PsiFile && textRange.equals(element.getTextRange());
267 HighlightInfo highlightInfo = new HighlightInfo(null, highlightInfoType, textRange.getStartOffset(), textRange.getEndOffset(), message,
268 toolTip, highlightInfoType.getSeverity(element), problemDescriptor.isAfterEndOfLine(), null,
269 isFileLevel);
271 return highlightInfo;
274 private synchronized void appendDescriptors(List<ProblemDescriptor> problemDescriptors, LocalInspectionTool tool, boolean ignoreSuppressed) {
275 if (problemDescriptors == null) return;
276 InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile();
277 final HighlightSeverity severity = inspectionProfile.getErrorLevel(HighlightDisplayKey.find(tool.getShortName()), myFile).getSeverity();
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 = null;
396 if (descriptor.showTooltip()) {
397 if (message.startsWith("<html>")) {
398 tooltip = message.contains("</body>") ? message.replace("</body>", link + "</body>") : message.replace("</html>", link + "</html>");
400 else {
401 tooltip = "<html><body>" + XmlStringUtil.escapeString(message) + link + "</body></html>";
404 HighlightInfo highlightInfo = highlightInfoFromDescriptor(descriptor, type, plainMessage, tooltip);
405 registerQuickFixes(tool, descriptor, highlightInfo, emptyActionRegistered);
406 return highlightInfo;
409 private static void registerQuickFixes(final LocalInspectionTool tool, final ProblemDescriptor descriptor,
410 final HighlightInfo highlightInfo, final Set<TextRange> emptyActionRegistered) {
411 final HighlightDisplayKey key = HighlightDisplayKey.find(tool.getShortName());
412 boolean needEmptyAction = true;
413 final QuickFix[] fixes = descriptor.getFixes();
414 if (fixes != null && fixes.length > 0) {
415 for (int k = 0; k < fixes.length; k++) {
416 if (fixes[k] != null) { // prevent null fixes from var args
417 QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixWrapper.wrap(descriptor, k), key);
418 needEmptyAction = false;
422 HintAction hintAction = ((ProblemDescriptorImpl)descriptor).getHintAction();
423 if (hintAction != null) {
424 QuickFixAction.registerQuickFixAction(highlightInfo, hintAction, key);
425 needEmptyAction = false;
427 if (((ProblemDescriptorImpl)descriptor).getEnforcedTextAttributes() != null) {
428 needEmptyAction = false;
430 if (needEmptyAction && emptyActionRegistered.add(new TextRange(highlightInfo.fixStartOffset, highlightInfo.fixEndOffset))) {
431 EmptyIntentionAction emptyIntentionAction = new EmptyIntentionAction(tool.getDisplayName());
432 QuickFixAction.registerQuickFixAction(highlightInfo, emptyIntentionAction, key);
436 private static String renderDescriptionMessage(ProblemDescriptor descriptor) {
437 PsiElement psiElement = descriptor.getPsiElement();
438 String message = descriptor.getDescriptionTemplate();
440 // no message. Should not be the case if inspection correctly implemented.
441 // noinspection ConstantConditions
442 if (message == null) return "";
444 message = StringUtil.replace(message, "<code>", "'");
445 message = StringUtil.replace(message, "</code>", "'");
446 //message = message.replaceAll("<[^>]*>", "");
447 String ref = ProblemDescriptionNode.extractHighlightedText(descriptor, psiElement);
448 message = StringUtil.replace(message, "#loc", "");
449 message = StringUtil.replace(message, "#ref", ref);
451 message = StringUtil.unescapeXml(message).trim();
452 return message;
455 public static PsiElement[] getElementsIntersectingRange(PsiFile file, final int startOffset, final int endOffset) {
456 final FileViewProvider viewProvider = file.getViewProvider();
457 final Set<PsiElement> result = new LinkedHashSet<PsiElement>();
458 for (Language language : viewProvider.getLanguages()) {
459 final PsiFile psiRoot = viewProvider.getPsi(language);
460 if (HighlightLevelUtil.shouldInspect(psiRoot)) {
461 result.addAll(CollectHighlightsUtil.getElementsInRange(psiRoot, startOffset, endOffset, true));
464 return result.toArray(new PsiElement[result.size()]);
467 List<LocalInspectionTool> getInspectionTools(InspectionProfileWrapper profile) {
468 return profile.getHighlightingLocalInspectionTools(myFile);
471 private static void inspectInjectedPsi(PsiFile injectedPsi, List<InjectedPsiInspectionResult> result, List<LocalInspectionTool> tools) {
472 InspectionManager inspectionManager = InspectionManager.getInstance(injectedPsi.getProject());
473 final ProblemsHolder problemsHolder = new ProblemsHolder(inspectionManager, injectedPsi, true);
474 final PsiElement host = injectedPsi.getContext();
476 final PsiElement[] elements = getElementsIntersectingRange(injectedPsi, 0, injectedPsi.getTextLength());
477 if (elements.length != 0) {
478 for (LocalInspectionTool tool : tools) {
479 if (host != null && InspectionManagerEx.inspectionResultSuppressed(host, tool)) {
480 continue;
482 final PsiElementVisitor visitor = tool.buildVisitor(problemsHolder, true);
483 assert !(visitor instanceof PsiRecursiveElementVisitor) : "The visitor returned from LocalInspectionTool.buildVisitor() must not be recursive. "+tool;
484 for (PsiElement element : elements) {
485 element.accept(visitor);
487 List<ProblemDescriptor> problems = problemsHolder.getResults();
488 if (problems != null && !problems.isEmpty()) {
489 InjectedPsiInspectionResult res = new InjectedPsiInspectionResult(tool, injectedPsi, new SmartList<ProblemDescriptor>(problems));
490 result.add(res);
496 public List<HighlightInfo> getInfos() {
497 return myInfos;
500 private static class InjectedPsiInspectionResult {
501 public final LocalInspectionTool tool;
502 public final PsiElement injectedPsi;
503 public final List<ProblemDescriptor> foundProblems;
505 private InjectedPsiInspectionResult(final LocalInspectionTool tool, final PsiElement injectedPsi, final List<ProblemDescriptor> foundProblems) {
506 this.tool = tool;
507 this.injectedPsi = injectedPsi;
508 this.foundProblems = foundProblems;