diff --git a/.idea/modules.xml b/.idea/modules.xml index 18f0a957bb5d..446556c1582b 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -10,6 +10,8 @@ + + diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index a806b2ba5ba9..c3d4806d3f6e 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -289,7 +289,7 @@ public def layoutCommunityPlugins(String home) { } fileset(dir: "$home/plugins/gradle/lib") { include(name: "*.jar") } } - + layoutPlugin("git4idea") { jar("git4idea-rt.jar") { module("git4idea-rt") @@ -701,6 +701,8 @@ def layout_core_upsource(String home, String target) { module("java-indexing-impl") module("platform-resources") module("platform-resources-en") + module("analysis-api") + module("analysis-impl") } jar("annotations.jar") { diff --git a/build/scripts/utils.gant b/build/scripts/utils.gant index 19530671f1f1..f74f8a9b4ae0 100644 --- a/build/scripts/utils.gant +++ b/build/scripts/utils.gant @@ -181,7 +181,7 @@ def debugPort = System.getProperty("debug.port") ?: 5555 if (suspendUntilDebuggerConnect == 'y') { println """\ ------------->----------- This process is suspended until remote debugger connects to the port $debugPort ----<---- --------------------------------------------^------^------^------^------^------^------^----------------------- +-------------------------------------------^------^------^------^------^------^------^----------------------- """ } @@ -250,6 +250,7 @@ binding.setVariable("platformApiModules", [ "platform-api", "lvcs-api", "lang-api", + "analysis-api", "vcs-api", "usageView", "xdebugger-api", @@ -267,6 +268,7 @@ binding.setVariable("platformImplementationModules", [ "platform-impl", "vcs-impl", "lang-impl", + "analysis-impl", "testRunner", "smRunner", "xdebugger-impl", diff --git a/platform/analysis-api/analysis-api.iml b/platform/analysis-api/analysis-api.iml new file mode 100644 index 000000000000..177ad6224f2a --- /dev/null +++ b/platform/analysis-api/analysis-api.iml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/platform/platform-api/src/com/intellij/codeHighlighting/HighlightDisplayLevel.java b/platform/analysis-api/src/com/intellij/codeHighlighting/HighlightDisplayLevel.java similarity index 83% rename from platform/platform-api/src/com/intellij/codeHighlighting/HighlightDisplayLevel.java rename to platform/analysis-api/src/com/intellij/codeHighlighting/HighlightDisplayLevel.java index 9e21988cb552..34133f67d6de 100644 --- a/platform/platform-api/src/com/intellij/codeHighlighting/HighlightDisplayLevel.java +++ b/platform/analysis-api/src/com/intellij/codeHighlighting/HighlightDisplayLevel.java @@ -16,7 +16,10 @@ package com.intellij.codeHighlighting; import com.intellij.lang.annotation.HighlightSeverity; -import com.intellij.openapi.editor.colors.*; +import com.intellij.openapi.editor.colors.CodeInsightColors; +import com.intellij.openapi.editor.colors.TextAttributesKey; +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.util.Comparing; import com.intellij.util.ImageLoader; import com.intellij.util.containers.HashMap; @@ -106,17 +109,27 @@ public class HighlightDisplayLevel { @NotNull private static Icon createIconByMask(@NotNull TextAttributesKey key) { - final EditorColorsManager manager = EditorColorsManager.getInstance(); - if (manager != null) { - final EditorColorsScheme globalScheme = manager.getGlobalScheme(); - return createIconByMask(globalScheme.getAttributes(key).getErrorStripeColor()); - } - + Icon icon = createIconByMaskFromExtensions(key); + if (icon != null) return icon; return createIconByMask(key.getDefaultAttributes().getErrorStripeColor()); } + public interface IconCreator { + ExtensionPointName EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.codeHighlighting.iconCreator"); + + Icon createIcon(@NotNull TextAttributesKey key); + } + + public static Icon createIconByMaskFromExtensions(@NotNull TextAttributesKey key) { + for (IconCreator creator : Extensions.getExtensions(IconCreator.EXTENSION_POINT_NAME)) { + Icon icon = creator.createIcon(key); + if (icon != null) return icon; + } + return null; + } + @NotNull - public static Icon createIconByMask(@NotNull final Color renderColor) { + public static Icon createIconByMask(final Color renderColor) { return new Icon() { @Override public void paintIcon(Component c, Graphics g, int x, int y) { diff --git a/platform/lang-api/src/com/intellij/codeInsight/daemon/EmptyResolveMessageProvider.java b/platform/analysis-api/src/com/intellij/codeInsight/daemon/EmptyResolveMessageProvider.java similarity index 100% rename from platform/lang-api/src/com/intellij/codeInsight/daemon/EmptyResolveMessageProvider.java rename to platform/analysis-api/src/com/intellij/codeInsight/daemon/EmptyResolveMessageProvider.java diff --git a/java/openapi/src/com/intellij/codeInsight/daemon/GroupNames.java b/platform/analysis-api/src/com/intellij/codeInsight/daemon/GroupNames.java similarity index 100% rename from java/openapi/src/com/intellij/codeInsight/daemon/GroupNames.java rename to platform/analysis-api/src/com/intellij/codeInsight/daemon/GroupNames.java diff --git a/platform/lang-api/src/com/intellij/codeInsight/daemon/HighlightDisplayKey.java b/platform/analysis-api/src/com/intellij/codeInsight/daemon/HighlightDisplayKey.java similarity index 100% rename from platform/lang-api/src/com/intellij/codeInsight/daemon/HighlightDisplayKey.java rename to platform/analysis-api/src/com/intellij/codeInsight/daemon/HighlightDisplayKey.java diff --git a/platform/lang-api/src/com/intellij/codeInspection/CommonProblemDescriptor.java b/platform/analysis-api/src/com/intellij/codeInspection/CommonProblemDescriptor.java similarity index 100% rename from platform/lang-api/src/com/intellij/codeInspection/CommonProblemDescriptor.java rename to platform/analysis-api/src/com/intellij/codeInspection/CommonProblemDescriptor.java diff --git a/platform/lang-api/src/com/intellij/codeInspection/InspectionManager.java b/platform/analysis-api/src/com/intellij/codeInspection/InspectionManager.java similarity index 87% rename from platform/lang-api/src/com/intellij/codeInspection/InspectionManager.java rename to platform/analysis-api/src/com/intellij/codeInspection/InspectionManager.java index 19d55fefe055..2d5b03b07de3 100644 --- a/platform/lang-api/src/com/intellij/codeInspection/InspectionManager.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/InspectionManager.java @@ -84,14 +84,6 @@ public abstract class InspectionManager { boolean onTheFly, LocalQuickFix... fixes); - @NotNull - public abstract ProblemDescriptor createProblemDescriptor(@NotNull final PsiElement psiElement, - @NotNull final String descriptionTemplate, - @NotNull ProblemHighlightType highlightType, - @Nullable final HintAction hintAction, - boolean onTheFly, - LocalQuickFix... fixes); - @NotNull public abstract ProblemDescriptor createProblemDescriptor(@NotNull final PsiElement psiElement, @NotNull final String descriptionTemplate, @@ -153,17 +145,6 @@ public abstract class InspectionManager { @NotNull ProblemHighlightType highlightType, final LocalQuickFix... fixes); - @Deprecated - @NotNull - /** - * use {@link #createProblemDescriptor(PsiElement, String, ProblemHighlightType, HintAction, boolean, LocalQuickFix...)} instead - */ - public abstract ProblemDescriptor createProblemDescriptor(@NotNull final PsiElement psiElement, - @NotNull final String descriptionTemplate, - @NotNull ProblemHighlightType highlightType, - @Nullable final HintAction hintAction, - final LocalQuickFix... fixes); - @Deprecated @NotNull /** diff --git a/platform/lang-api/src/com/intellij/codeInspection/InspectionProfileEntry.java b/platform/analysis-api/src/com/intellij/codeInspection/InspectionProfileEntry.java similarity index 91% rename from platform/lang-api/src/com/intellij/codeInspection/InspectionProfileEntry.java rename to platform/analysis-api/src/com/intellij/codeInspection/InspectionProfileEntry.java index 5d501b22c147..4e9e817178c5 100644 --- a/platform/lang-api/src/com/intellij/codeInspection/InspectionProfileEntry.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/InspectionProfileEntry.java @@ -28,7 +28,10 @@ import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters; import com.intellij.util.xmlb.XmlSerializationException; import com.intellij.util.xmlb.XmlSerializer; import org.jdom.Element; -import org.jetbrains.annotations.*; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.io.BufferedReader; @@ -61,9 +64,9 @@ public abstract class InspectionProfileEntry { protected volatile DefaultNameProvider myNameProvider = null; /** - * @see InspectionEP#groupDisplayName - * @see InspectionEP#groupKey - * @see InspectionEP#groupBundle + * @see com.intellij.codeInspection.InspectionEP#groupDisplayName + * @see com.intellij.codeInspection.InspectionEP#groupKey + * @see com.intellij.codeInspection.InspectionEP#groupBundle */ @Nls @NotNull @@ -79,7 +82,7 @@ public abstract class InspectionProfileEntry { } /** - * @see InspectionEP#groupPath + * @see com.intellij.codeInspection.InspectionEP#groupPath */ @NotNull public String[] getGroupPath() { @@ -91,9 +94,9 @@ public abstract class InspectionProfileEntry { } /** - * @see InspectionEP#displayName - * @see InspectionEP#key - * @see InspectionEP#bundle + * @see com.intellij.codeInspection.InspectionEP#displayName + * @see com.intellij.codeInspection.InspectionEP#key + * @see com.intellij.codeInspection.InspectionEP#bundle */ @Nls @NotNull @@ -111,7 +114,7 @@ public abstract class InspectionProfileEntry { /** * DO NOT OVERRIDE this method. * - * @see InspectionEP#shortName + * @see com.intellij.codeInspection.InspectionEP#shortName */ @NonNls @NotNull @@ -133,7 +136,7 @@ public abstract class InspectionProfileEntry { /** * DO NOT OVERRIDE this method. * - * @see InspectionEP#level + * @see com.intellij.codeInspection.InspectionEP#level */ @NotNull public HighlightDisplayLevel getDefaultLevel() { @@ -143,7 +146,7 @@ public abstract class InspectionProfileEntry { /** * DO NOT OVERRIDE this method. * - * @see InspectionEP#enabledByDefault + * @see com.intellij.codeInspection.InspectionEP#enabledByDefault */ public boolean isEnabledByDefault() { return false; @@ -260,7 +263,7 @@ public abstract class InspectionProfileEntry { * Initialize inspection with project. Is called on project opened for all profiles as well as on profile creation. * * @param project to be associated with this entry - * @deprecated this won't work for inspections configured via {@link InspectionEP} + * @deprecated this won't work for inspections configured via {@link com.intellij.codeInspection.InspectionEP} */ public void projectOpened(Project project) { } @@ -269,7 +272,7 @@ public abstract class InspectionProfileEntry { * Cleanup inspection settings corresponding to the project. Is called on project closed for all profiles as well as on profile deletion. * * @param project to be disassociated from this entry - * @deprecated this won't work for inspections configured via {@link InspectionEP} + * @deprecated this won't work for inspections configured via {@link com.intellij.codeInspection.InspectionEP} */ public void projectClosed(Project project) { } diff --git a/platform/lang-api/src/com/intellij/codeInspection/InspectionsBundle.java b/platform/analysis-api/src/com/intellij/codeInspection/InspectionsBundle.java similarity index 100% rename from platform/lang-api/src/com/intellij/codeInspection/InspectionsBundle.java rename to platform/analysis-api/src/com/intellij/codeInspection/InspectionsBundle.java diff --git a/platform/lang-api/src/com/intellij/codeInspection/LocalInspectionTool.java b/platform/analysis-api/src/com/intellij/codeInspection/LocalInspectionTool.java similarity index 98% rename from platform/lang-api/src/com/intellij/codeInspection/LocalInspectionTool.java rename to platform/analysis-api/src/com/intellij/codeInspection/LocalInspectionTool.java index 4621faa8b70a..ef85342bfb84 100644 --- a/platform/lang-api/src/com/intellij/codeInspection/LocalInspectionTool.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/LocalInspectionTool.java @@ -35,8 +35,11 @@ public abstract class LocalInspectionTool extends InspectionProfileEntry { private static final Logger LOG = Logger.getInstance("#" + LocalInspectionTool.class.getName()); interface LocalDefaultNameProvider extends DefaultNameProvider { - @Nullable String getDefaultID(); - @Nullable String getDefaultAlternativeID(); + @Nullable + String getDefaultID(); + + @Nullable + String getDefaultAlternativeID(); } /** diff --git a/platform/lang-api/src/com/intellij/codeInspection/LocalInspectionToolSession.java b/platform/analysis-api/src/com/intellij/codeInspection/LocalInspectionToolSession.java similarity index 99% rename from platform/lang-api/src/com/intellij/codeInspection/LocalInspectionToolSession.java rename to platform/analysis-api/src/com/intellij/codeInspection/LocalInspectionToolSession.java index 50ab0b92e180..066e5c735127 100644 --- a/platform/lang-api/src/com/intellij/codeInspection/LocalInspectionToolSession.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/LocalInspectionToolSession.java @@ -47,4 +47,4 @@ public class LocalInspectionToolSession extends UserDataHolderBase { public int getEndOffset() { return myEndOffset; } -} \ No newline at end of file +} diff --git a/platform/lang-api/src/com/intellij/codeInspection/LocalQuickFix.java b/platform/analysis-api/src/com/intellij/codeInspection/LocalQuickFix.java similarity index 100% rename from platform/lang-api/src/com/intellij/codeInspection/LocalQuickFix.java rename to platform/analysis-api/src/com/intellij/codeInspection/LocalQuickFix.java diff --git a/platform/lang-api/src/com/intellij/codeInspection/LocalQuickFixBase.java b/platform/analysis-api/src/com/intellij/codeInspection/LocalQuickFixBase.java similarity index 100% rename from platform/lang-api/src/com/intellij/codeInspection/LocalQuickFixBase.java rename to platform/analysis-api/src/com/intellij/codeInspection/LocalQuickFixBase.java diff --git a/platform/lang-api/src/com/intellij/codeInspection/LocalQuickFixProvider.java b/platform/analysis-api/src/com/intellij/codeInspection/LocalQuickFixProvider.java similarity index 95% rename from platform/lang-api/src/com/intellij/codeInspection/LocalQuickFixProvider.java rename to platform/analysis-api/src/com/intellij/codeInspection/LocalQuickFixProvider.java index 4278e573808b..28176a396f1b 100644 --- a/platform/lang-api/src/com/intellij/codeInspection/LocalQuickFixProvider.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/LocalQuickFixProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2013 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,4 +26,4 @@ import org.jetbrains.annotations.Nullable; public interface LocalQuickFixProvider { @Nullable LocalQuickFix[] getQuickFixes(); -} \ No newline at end of file +} diff --git a/platform/lang-api/src/com/intellij/codeInspection/ProblemDescriptor.java b/platform/analysis-api/src/com/intellij/codeInspection/ProblemDescriptor.java similarity index 100% rename from platform/lang-api/src/com/intellij/codeInspection/ProblemDescriptor.java rename to platform/analysis-api/src/com/intellij/codeInspection/ProblemDescriptor.java diff --git a/platform/lang-api/src/com/intellij/codeInspection/ProblemHighlightType.java b/platform/analysis-api/src/com/intellij/codeInspection/ProblemHighlightType.java similarity index 100% rename from platform/lang-api/src/com/intellij/codeInspection/ProblemHighlightType.java rename to platform/analysis-api/src/com/intellij/codeInspection/ProblemHighlightType.java diff --git a/platform/lang-api/src/com/intellij/codeInspection/ProblemsHolder.java b/platform/analysis-api/src/com/intellij/codeInspection/ProblemsHolder.java similarity index 100% rename from platform/lang-api/src/com/intellij/codeInspection/ProblemsHolder.java rename to platform/analysis-api/src/com/intellij/codeInspection/ProblemsHolder.java diff --git a/platform/lang-api/src/com/intellij/codeInspection/QuickFix.java b/platform/analysis-api/src/com/intellij/codeInspection/QuickFix.java similarity index 100% rename from platform/lang-api/src/com/intellij/codeInspection/QuickFix.java rename to platform/analysis-api/src/com/intellij/codeInspection/QuickFix.java diff --git a/platform/platform-api/src/com/intellij/lang/annotation/HighlightSeverity.java b/platform/analysis-api/src/com/intellij/lang/annotation/HighlightSeverity.java similarity index 96% rename from platform/platform-api/src/com/intellij/lang/annotation/HighlightSeverity.java rename to platform/analysis-api/src/com/intellij/lang/annotation/HighlightSeverity.java index 3553925ff9a3..7e6ea0f3b5b4 100644 --- a/platform/platform-api/src/com/intellij/lang/annotation/HighlightSeverity.java +++ b/platform/analysis-api/src/com/intellij/lang/annotation/HighlightSeverity.java @@ -21,6 +21,7 @@ import com.intellij.openapi.util.JDOMExternalizable; import com.intellij.openapi.util.WriteExternalException; import org.jdom.Element; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; /** * Defines a highlighting severity level for an annotation. @@ -93,7 +94,7 @@ public class HighlightSeverity implements Comparable, JDOMExt } @Override - public int compareTo(final HighlightSeverity highlightSeverity) { + public int compareTo(@NotNull final HighlightSeverity highlightSeverity) { return myVal - highlightSeverity.myVal; } diff --git a/platform/analysis-impl/analysis-impl.iml b/platform/analysis-impl/analysis-impl.iml new file mode 100644 index 000000000000..ad33ccfa85f0 --- /dev/null +++ b/platform/analysis-impl/analysis-impl.iml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/Divider.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/Divider.java similarity index 95% rename from platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/Divider.java rename to platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/Divider.java index 401aab96e5df..e4425e1c247b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/Divider.java +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/Divider.java @@ -15,7 +15,6 @@ */ package com.intellij.codeInsight.daemon.impl; -import com.intellij.codeInsight.daemon.impl.analysis.HighlightLevelUtil; import com.intellij.lang.Language; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.progress.ProgressManager; @@ -43,12 +42,12 @@ public class Divider { @NotNull TextRange range, @NotNull List inside, @NotNull List outside, - @NotNull HighlightLevelUtil.AnalysisLevel level, - boolean includeParents) { + boolean includeParents, + @NotNull Condition filter) { final FileViewProvider viewProvider = file.getViewProvider(); for (Language language : viewProvider.getLanguages()) { final PsiFile psiRoot = viewProvider.getPsi(language); - if (HighlightLevelUtil.shouldAnalyse(psiRoot, level)) { + if (filter.value(psiRoot)) { divideInsideAndOutside(psiRoot, startOffset, endOffset, range, inside, outside, includeParents); } } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/CommonProblemDescriptorImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/CommonProblemDescriptorImpl.java similarity index 100% rename from platform/lang-impl/src/com/intellij/codeInspection/CommonProblemDescriptorImpl.java rename to platform/analysis-impl/src/com/intellij/codeInspection/CommonProblemDescriptorImpl.java diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/InspectionEngine.java b/platform/analysis-impl/src/com/intellij/codeInspection/InspectionEngine.java new file mode 100644 index 000000000000..e78fe4ea2406 --- /dev/null +++ b/platform/analysis-impl/src/com/intellij/codeInspection/InspectionEngine.java @@ -0,0 +1,103 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInspection; + +import com.intellij.codeInsight.daemon.impl.Divider; +import com.intellij.concurrency.JobLauncher; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import com.intellij.util.Processor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +public class InspectionEngine { + private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.InspectionEngine"); + + @NotNull + public static PsiElementVisitor createVisitorAndAcceptElements(@NotNull LocalInspectionTool tool, + @NotNull ProblemsHolder holder, + boolean isOnTheFly, + @NotNull LocalInspectionToolSession session, + @NotNull List elements, + @Nullable Collection languages) { + PsiElementVisitor visitor = tool.buildVisitor(holder, isOnTheFly, session); + //noinspection ConstantConditions + if(visitor == null) { + LOG.error("Tool " + tool + " must not return null from the buildVisitor() method"); + } + assert !(visitor instanceof PsiRecursiveElementVisitor || visitor instanceof PsiRecursiveElementWalkingVisitor) + : "The visitor returned from LocalInspectionTool.buildVisitor() must not be recursive. "+tool; + + tool.inspectionStarted(session, isOnTheFly); + acceptElements(elements, visitor, languages); + return visitor; + } + + public static void acceptElements(@NotNull List elements, + @NotNull PsiElementVisitor elementVisitor, + @Nullable Collection languages) { + //noinspection ForLoopReplaceableByForEach + for (int i = 0, elementsSize = elements.size(); i < elementsSize; i++) { + PsiElement element = elements.get(i); + if (languages == null || languages.contains(element.getLanguage().getID())) { + element.accept(elementVisitor); + } + ProgressManager.checkCanceled(); + } + } + + public List inspect(@NotNull final List tools, + @NotNull final PsiFile file, + @NotNull final InspectionManager iManager, + final boolean isOnTheFly, + boolean failFastOnAcquireReadAction, + @NotNull final ProgressIndicator indicator) { + if (tools.isEmpty()) return Collections.emptyList(); + final List resultDescriptors = Collections.synchronizedList(new ArrayList()); + final List elements = new ArrayList(); + + TextRange range = file.getTextRange(); + final LocalInspectionToolSession session = new LocalInspectionToolSession(file, range.getStartOffset(), range.getEndOffset()); + Divider.divideInsideAndOutside(file, range.getStartOffset(), range.getEndOffset(), range, elements, Collections.emptyList(), true, Condition.TRUE); + + boolean result = JobLauncher.getInstance().invokeConcurrentlyUnderProgress(tools, indicator, failFastOnAcquireReadAction, new Processor() { + @Override + public boolean process(LocalInspectionTool tool) { + ProblemsHolder holder = new ProblemsHolder(iManager, file, isOnTheFly); + createVisitorAndAcceptElements(tool, holder, isOnTheFly, session, elements, null); + + tool.inspectionFinished(session, holder); + + if (holder.hasResults()) { + resultDescriptors.addAll(holder.getResults()); + } + + return true; + } + }); + + return resultDescriptors; + } +} diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/InspectionManagerBase.java b/platform/analysis-impl/src/com/intellij/codeInspection/InspectionManagerBase.java new file mode 100644 index 000000000000..526a1f8dbfc6 --- /dev/null +++ b/platform/analysis-impl/src/com/intellij/codeInspection/InspectionManagerBase.java @@ -0,0 +1,172 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInspection; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + +public class InspectionManagerBase extends InspectionManager { + private final Project myProject; + + public InspectionManagerBase(Project project) { + myProject = project; + } + + @Override + @NotNull + public Project getProject() { + return myProject; + } + + @Override + @NotNull + public CommonProblemDescriptor createProblemDescriptor(@NotNull String descriptionTemplate, QuickFix... fixes) { + return new CommonProblemDescriptorImpl(fixes, descriptionTemplate); + } + + @Override + @NotNull + public ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, + @NotNull String descriptionTemplate, + LocalQuickFix fix, + @NotNull ProblemHighlightType highlightType, + boolean onTheFly) { + LocalQuickFix[] quickFixes = fix != null ? new LocalQuickFix[]{fix} : null; + return createProblemDescriptor(psiElement, descriptionTemplate, onTheFly, quickFixes, highlightType); + } + + @Override + @NotNull + public ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, + @NotNull String descriptionTemplate, + boolean onTheFly, + LocalQuickFix[] fixes, + @NotNull ProblemHighlightType highlightType) { + return createProblemDescriptor(psiElement, descriptionTemplate, fixes, highlightType, onTheFly, false); + } + + @Override + @NotNull + public ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, + @NotNull String descriptionTemplate, + LocalQuickFix[] fixes, + @NotNull ProblemHighlightType highlightType, + boolean onTheFly, + boolean isAfterEndOfLine) { + return new ProblemDescriptorBase(psiElement, psiElement, descriptionTemplate, fixes, highlightType, isAfterEndOfLine, null, true, onTheFly); + } + + @Override + @NotNull + public ProblemDescriptor createProblemDescriptor(@NotNull PsiElement startElement, + @NotNull PsiElement endElement, + @NotNull String descriptionTemplate, + @NotNull ProblemHighlightType highlightType, + boolean onTheFly, + LocalQuickFix... fixes) { + return new ProblemDescriptorBase(startElement, endElement, descriptionTemplate, fixes, highlightType, false, null, true, onTheFly); + } + + @NotNull + @Override + public ProblemDescriptor createProblemDescriptor(@NotNull final PsiElement psiElement, + final TextRange rangeInElement, + @NotNull final String descriptionTemplate, + @NotNull final ProblemHighlightType highlightType, + boolean onTheFly, + final LocalQuickFix... fixes) { + return new ProblemDescriptorBase(psiElement, psiElement, descriptionTemplate, fixes, highlightType, false, rangeInElement, true, onTheFly); + } + + @NotNull + @Override + public ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, + @NotNull String descriptionTemplate, + boolean showTooltip, + @NotNull ProblemHighlightType highlightType, + boolean onTheFly, + LocalQuickFix... fixes) { + return new ProblemDescriptorBase(psiElement, psiElement, descriptionTemplate, fixes, highlightType, false, null, showTooltip, onTheFly); + } + + @Override + @Deprecated + @NotNull + public ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, + @NotNull String descriptionTemplate, + LocalQuickFix fix, + @NotNull ProblemHighlightType highlightType) { + LocalQuickFix[] quickFixes = fix != null ? new LocalQuickFix[]{fix} : null; + return createProblemDescriptor(psiElement, descriptionTemplate, false, quickFixes, highlightType); + } + + @Override + @Deprecated + @NotNull + public ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, + @NotNull String descriptionTemplate, + LocalQuickFix[] fixes, + @NotNull ProblemHighlightType highlightType) { + return createProblemDescriptor(psiElement, descriptionTemplate, fixes, highlightType, false, false); + } + + @Override + @Deprecated + @NotNull + public ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, + @NotNull String descriptionTemplate, + LocalQuickFix[] fixes, + @NotNull ProblemHighlightType highlightType, + boolean isAfterEndOfLine) { + return createProblemDescriptor(psiElement, descriptionTemplate, fixes, highlightType, true, isAfterEndOfLine); + } + + @Override + @Deprecated + @NotNull + public ProblemDescriptor createProblemDescriptor(@NotNull PsiElement startElement, + @NotNull PsiElement endElement, + @NotNull String descriptionTemplate, + @NotNull ProblemHighlightType highlightType, + LocalQuickFix... fixes) { + return createProblemDescriptor(startElement, endElement, descriptionTemplate, highlightType, true, fixes); + } + + @NotNull + @Override + @Deprecated + public ProblemDescriptor createProblemDescriptor(@NotNull final PsiElement psiElement, + final TextRange rangeInElement, + @NotNull final String descriptionTemplate, + @NotNull final ProblemHighlightType highlightType, + final LocalQuickFix... fixes) { + return createProblemDescriptor(psiElement, rangeInElement, descriptionTemplate, highlightType, true, fixes); + } + + @NotNull + @Deprecated + @Override + public ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, + @NotNull String descriptionTemplate, + boolean showTooltip, + @NotNull ProblemHighlightType highlightType, + LocalQuickFix... fixes) { + return createProblemDescriptor(psiElement, descriptionTemplate, showTooltip, highlightType, true, fixes); + } + +} diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ProblemDescriptorBase.java b/platform/analysis-impl/src/com/intellij/codeInspection/ProblemDescriptorBase.java new file mode 100644 index 000000000000..ebb5a1c6b86e --- /dev/null +++ b/platform/analysis-impl/src/com/intellij/codeInspection/ProblemDescriptorBase.java @@ -0,0 +1,208 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInspection; + +import com.intellij.lang.injection.InjectedLanguageManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.colors.TextAttributesKey; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.TextRange; +import com.intellij.pom.Navigatable; +import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class ProblemDescriptorBase extends CommonProblemDescriptorImpl implements ProblemDescriptor { + private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.ProblemDescriptorImpl"); + + @NotNull private final SmartPsiElementPointer myStartSmartPointer; + @Nullable private final SmartPsiElementPointer myEndSmartPointer; + + private final ProblemHighlightType myHighlightType; + private Navigatable myNavigatable; + private final boolean myAfterEndOfLine; + private final TextRange myTextRangeInElement; + private final boolean myShowTooltip; + private TextAttributesKey myEnforcedTextAttributes; + private int myLineNumber = -1; + private String myProblemGroup; + + public ProblemDescriptorBase(@NotNull PsiElement startElement, + @NotNull PsiElement endElement, + String descriptionTemplate, + LocalQuickFix[] fixes, + @NotNull ProblemHighlightType highlightType, + boolean isAfterEndOfLine, + @Nullable TextRange rangeInElement, + final boolean tooltip, + boolean onTheFly) { + super(fixes, descriptionTemplate); + myShowTooltip = tooltip; + PsiFile startContainingFile = startElement.getContainingFile(); + LOG.assertTrue(startContainingFile != null && startContainingFile.isValid() || startElement.isValid(), startElement); + PsiFile endContainingFile = startElement == endElement ? startContainingFile : endElement.getContainingFile(); + LOG.assertTrue(startElement == endElement || endContainingFile != null && endContainingFile.isValid() || endElement.isValid(), endElement); + assertPhysical(startElement); + if (startElement != endElement) assertPhysical(endElement); + + final TextRange startElementRange = startElement.getTextRange(); + LOG.assertTrue(startElementRange != null, startElement); + final TextRange endElementRange = endElement.getTextRange(); + LOG.assertTrue(endElementRange != null, endElement); + if (startElementRange.getStartOffset() >= endElementRange.getEndOffset()) { + if (!(startElement instanceof PsiFile && endElement instanceof PsiFile)) { + LOG.error("Empty PSI elements should not be passed to createDescriptor. Start: " + startElement + ", end: " + endElement); + } + } + + myHighlightType = highlightType; + final Project project = startContainingFile == null ? startElement.getProject() : startContainingFile.getProject(); + final SmartPointerManager manager = SmartPointerManager.getInstance(project); + myStartSmartPointer = manager.createSmartPsiElementPointer(startElement, startContainingFile); + myEndSmartPointer = startElement == endElement ? null : manager.createSmartPsiElementPointer(endElement, endContainingFile); + + myAfterEndOfLine = isAfterEndOfLine; + myTextRangeInElement = rangeInElement; + } + + protected void assertPhysical(final PsiElement element) { + if (!element.isPhysical()) { + LOG.error("Non-physical PsiElement. Physical element is required to be able to anchor the problem in the source tree: " + + element + "; file: " + element.getContainingFile()); + } + } + + @Override + public PsiElement getPsiElement() { + PsiElement startElement = getStartElement(); + if (myEndSmartPointer == null) { + return startElement; + } + PsiElement endElement = getEndElement(); + if (startElement == endElement) { + return startElement; + } + if (startElement == null || endElement == null) return null; + return PsiTreeUtil.findCommonParent(startElement, endElement); + } + + @Override + public PsiElement getStartElement() { + return myStartSmartPointer.getElement(); + } + + @Override + public PsiElement getEndElement() { + return myEndSmartPointer == null ? getStartElement() : myEndSmartPointer.getElement(); + } + + @Override + public int getLineNumber() { + if (myLineNumber == -1) { + PsiElement psiElement = getPsiElement(); + if (psiElement == null) return -1; + if (!psiElement.isValid()) return -1; + LOG.assertTrue(psiElement.isPhysical()); + InjectedLanguageManager manager = InjectedLanguageManager.getInstance(psiElement.getProject()); + PsiFile containingFile = manager.getTopLevelFile(psiElement); + Document document = PsiDocumentManager.getInstance(psiElement.getProject()).getDocument(containingFile); + if (document == null) return -1; + TextRange textRange = getTextRange(); + if (textRange == null) return -1; + textRange = manager.injectedToHost(psiElement, textRange); + myLineNumber = document.getLineNumber(textRange.getStartOffset()) + 1; + } + return myLineNumber; + } + + @NotNull + @Override + public ProblemHighlightType getHighlightType() { + return myHighlightType; + } + + @Override + public boolean isAfterEndOfLine() { + return myAfterEndOfLine; + } + + @Override + public void setTextAttributes(TextAttributesKey key) { + myEnforcedTextAttributes = key; + } + + public TextAttributesKey getEnforcedTextAttributes() { + return myEnforcedTextAttributes; + } + + public TextRange getTextRangeForNavigation() { + TextRange textRange = getTextRange(); + if (textRange == null) return null; + PsiElement element = getPsiElement(); + return InjectedLanguageManager.getInstance(element.getProject()).injectedToHost(element, textRange); + } + + public TextRange getTextRange() { + PsiElement startElement = getStartElement(); + PsiElement endElement = myEndSmartPointer == null ? startElement : getEndElement(); + if (startElement == null || endElement == null) { + return null; + } + + TextRange textRange = startElement.getTextRange(); + if (startElement == endElement) { + if (isAfterEndOfLine()) return new TextRange(textRange.getEndOffset(), textRange.getEndOffset()); + if (myTextRangeInElement != null) { + return new TextRange(textRange.getStartOffset() + myTextRangeInElement.getStartOffset(), + textRange.getStartOffset() + myTextRangeInElement.getEndOffset()); + } + return textRange; + } + return new TextRange(textRange.getStartOffset(), endElement.getTextRange().getEndOffset()); + } + + public Navigatable getNavigatable() { + return myNavigatable; + } + + public void setNavigatable(final Navigatable navigatable) { + myNavigatable = navigatable; + } + + @Override + @Nullable + public String getProblemGroup() { + return myProblemGroup; + } + + @Override + public void setProblemGroup(@Nullable String problemGroup) { + myProblemGroup = problemGroup; + } + + @Override + public boolean showTooltip() { + return myShowTooltip; + } + + @Override + public String toString() { + PsiElement element = getPsiElement(); + return ProblemDescriptorUtil.renderDescriptionMessage(this, element); + } +} diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ProblemDescriptorUtil.java b/platform/analysis-impl/src/com/intellij/codeInspection/ProblemDescriptorUtil.java new file mode 100644 index 000000000000..2f7742dd893c --- /dev/null +++ b/platform/analysis-impl/src/com/intellij/codeInspection/ProblemDescriptorUtil.java @@ -0,0 +1,79 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInspection; + +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + +public class ProblemDescriptorUtil { + public static String extractHighlightedText(@NotNull CommonProblemDescriptor descriptor, PsiElement psiElement) { + if (psiElement == null || !psiElement.isValid()) return ""; + String ref = psiElement.getText(); + if (descriptor instanceof ProblemDescriptorBase) { + TextRange textRange = ((ProblemDescriptorBase)descriptor).getTextRange(); + final TextRange elementRange = psiElement.getTextRange(); + if (textRange != null && elementRange != null) { + textRange = textRange.shiftRight(-elementRange.getStartOffset()); + if (textRange.getStartOffset() >= 0 && textRange.getEndOffset() <= elementRange.getLength()) { + ref = textRange.substring(ref); + } + } + } + ref = StringUtil.replaceChar(ref, '\n', ' ').trim(); + ref = StringUtil.first(ref, 100, true); + return ref; + } + + @NotNull + public static String renderDescriptionMessage(@NotNull CommonProblemDescriptor descriptor, PsiElement element, boolean appendLineNumber) { + String message = descriptor.getDescriptionTemplate(); + + // no message. Should not be the case if inspection correctly implemented. + // noinspection ConstantConditions + if (message == null) return ""; + + if (appendLineNumber && descriptor instanceof ProblemDescriptor && !message.contains("#ref") && message.contains("#loc")) { + final int lineNumber = ((ProblemDescriptor)descriptor).getLineNumber(); + if (lineNumber >= 0) { + message = StringUtil.replace(message, "#loc", "(" + InspectionsBundle.message("inspection.export.results.at.line") + " " + lineNumber + ")"); + } + } + message = StringUtil.replace(message, "", "'"); + message = StringUtil.replace(message, "", "'"); + message = StringUtil.replace(message, "#loc ", ""); + message = StringUtil.replace(message, " #loc", ""); + message = StringUtil.replace(message, "#loc", ""); + if (message.contains("#ref")) { + String ref = extractHighlightedText(descriptor, element); + message = StringUtil.replace(message, "#ref", ref); + } + + final int endIndex = message.indexOf("#end"); + if (endIndex > 0) { + message = message.substring(0, endIndex); + } + + message = StringUtil.unescapeXml(message).trim(); + return message; + } + + @NotNull + public static String renderDescriptionMessage(@NotNull CommonProblemDescriptor descriptor, PsiElement element) { + return renderDescriptionMessage(descriptor, element, false); + } +} diff --git a/platform/lang-api/src/com/intellij/psi/PsiRecursiveElementVisitor.java b/platform/core-api/src/com/intellij/psi/PsiRecursiveElementVisitor.java similarity index 100% rename from platform/lang-api/src/com/intellij/psi/PsiRecursiveElementVisitor.java rename to platform/core-api/src/com/intellij/psi/PsiRecursiveElementVisitor.java diff --git a/platform/lang-api/lang-api.iml b/platform/lang-api/lang-api.iml index b8ffb1cfee1c..b095734ee2d1 100644 --- a/platform/lang-api/lang-api.iml +++ b/platform/lang-api/lang-api.iml @@ -15,6 +15,7 @@ + diff --git a/platform/lang-impl/lang-impl.iml b/platform/lang-impl/lang-impl.iml index 654249b5ee81..d1580e0bc141 100644 --- a/platform/lang-impl/lang-impl.iml +++ b/platform/lang-impl/lang-impl.iml @@ -29,6 +29,7 @@ + diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java index 0564dec0c92a..fa49d34146de 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java @@ -85,6 +85,12 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP static final String PRESENTABLE_NAME = DaemonBundle.message("pass.syntax"); private static final Key HAS_ERROR_ELEMENT = Key.create("HAS_ERROR_ELEMENT"); private static final JobLauncher JobUtil = JobLauncher.getInstance(); + private static final Condition FILE_FILTER = new Condition() { + @Override + public boolean value(PsiFile file) { + return HighlightLevelUtil.shouldHighlight(file); + } + }; private final int myStartOffset; private final int myEndOffset; @@ -195,7 +201,7 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP try { final HighlightVisitor[] filteredVisitors = filterVisitors(highlightVisitors, myFile); Divider.divideInsideAndOutside(myFile, myStartOffset, myEndOffset, myPriorityRange, inside, outside, - HighlightLevelUtil.AnalysisLevel.HIGHLIGHT,false); + false, FILE_FILTER); setProgressLimit((long)(inside.size()+outside.size())); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java index a30b8d03bec0..4406095b71c8 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java @@ -24,7 +24,6 @@ import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction; import com.intellij.codeInsight.intention.EmptyIntentionAction; import com.intellij.codeInspection.*; import com.intellij.codeInspection.ex.*; -import com.intellij.codeInspection.ui.ProblemDescriptionNode; import com.intellij.concurrency.JobLauncher; import com.intellij.injected.editor.DocumentWindow; import com.intellij.lang.Language; @@ -47,6 +46,7 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbService; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.Trinity; @@ -78,6 +78,12 @@ import java.util.concurrent.ConcurrentMap; public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass implements DumbAware { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.LocalInspectionsPass"); public static final TextRange EMPTY_PRIORITY_RANGE = TextRange.EMPTY_RANGE; + private static final Condition FILE_FILTER = new Condition() { + @Override + public boolean value(PsiFile file) { + return HighlightLevelUtil.shouldInspect(file); + } + }; private final int myStartOffset; private final int myEndOffset; private final TextRange myPriorityRange; @@ -174,7 +180,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass PsiElement psiElement = descriptor.getPsiElement(); if (psiElement == null) continue; if (InspectionManagerEx.inspectionResultSuppressed(psiElement, tool.getTool())) continue; - List editables = ilManager.intersectWithAllEditableFragments(file, ((ProblemDescriptorImpl)descriptor).getTextRange()); + List editables = ilManager.intersectWithAllEditableFragments(file, ((ProblemDescriptorBase)descriptor).getTextRange()); for (TextRange editable : editables) { TextRange hostRange = documentRange.injectedToHost(editable); QuickFix[] fixes = descriptor.getFixes(); @@ -207,7 +213,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass List inside = new ArrayList(); List outside = new ArrayList(); Divider.divideInsideAndOutside(myFile, myStartOffset, myEndOffset, myPriorityRange, inside, outside, - HighlightLevelUtil.AnalysisLevel.HIGHLIGHT_AND_INSPECT,true); + true, FILE_FILTER); MultiMap tools = getToolsForElements(toolWrappers, checkDumbAwareness, inside, outside); @@ -216,7 +222,8 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass List init = visitPriorityElementsAndInit(tools, iManager, isOnTheFly, indicator, inside, session, toolWrappers, checkDumbAwareness); - visitRestElementsAndCleanup(iManager, isOnTheFly, indicator, outside, session, init, toolWrappers, checkDumbAwareness); + visitRestElementsAndCleanup(indicator, outside, session, init); + inspectInjectedPsi(outside, isOnTheFly, indicator, iManager, false, checkDumbAwareness, toolWrappers); indicator.checkCanceled(); @@ -292,6 +299,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass return map; } + @NotNull private List visitPriorityElementsAndInit(@NotNull MultiMap tools, @NotNull final InspectionManagerEx iManager, final boolean isOnTheFly, @@ -337,7 +345,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass } } }; - PsiElementVisitor visitor = createVisitorAndAcceptElements(tool, holder, isOnTheFly, session, elements, languages); + PsiElementVisitor visitor = InspectionEngine.createVisitorAndAcceptElements(tool, holder, isOnTheFly, session, elements, languages); synchronized (init) { init.add(new InspectionContext(toolWrapper, holder, visitor, languages)); @@ -351,41 +359,17 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass return true; } - @NotNull - private static PsiElementVisitor createVisitorAndAcceptElements(@NotNull LocalInspectionTool tool, - @NotNull ProblemsHolder holder, - boolean isOnTheFly, - @NotNull LocalInspectionToolSession session, - @NotNull List elements, - @Nullable Collection languages) { - PsiElementVisitor visitor = tool.buildVisitor(holder, isOnTheFly, session); - //noinspection ConstantConditions - if(visitor == null) { - LOG.error("Tool " + tool + " must not return null from the buildVisitor() method"); - } - assert !(visitor instanceof PsiRecursiveElementVisitor || visitor instanceof PsiRecursiveElementWalkingVisitor) - : "The visitor returned from LocalInspectionTool.buildVisitor() must not be recursive. "+tool; - - tool.inspectionStarted(session, isOnTheFly); - acceptElements(elements, visitor, languages); - return visitor; - } - - private void visitRestElementsAndCleanup(@NotNull final InspectionManagerEx iManager, - final boolean isOnTheFly, - @NotNull final ProgressIndicator indicator, + private void visitRestElementsAndCleanup(@NotNull final ProgressIndicator indicator, @NotNull final List elements, @NotNull final LocalInspectionToolSession session, - @NotNull List init, - @NotNull List wrappers, - boolean checkDumbAwareness) { + @NotNull List init) { Processor processor = new Processor() { @Override public boolean process(InspectionContext context) { indicator.checkCanceled(); ApplicationManager.getApplication().assertReadAccessAllowed(); - acceptElements(elements, context.visitor, context.languageIds); + InspectionEngine.acceptElements(elements, context.visitor, context.languageIds); advanceProgress(1); context.tool.getTool().inspectionFinished(session, context.holder); @@ -399,20 +383,6 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass if (!result) { throw new ProcessCanceledException(); } - inspectInjectedPsi(elements, isOnTheFly, indicator, iManager, false, checkDumbAwareness, wrappers); - } - - private static void acceptElements(@NotNull List elements, - @NotNull PsiElementVisitor elementVisitor, - @Nullable Collection languages) { - //noinspection ForLoopReplaceableByForEach - for (int i = 0, elementsSize = elements.size(); i < elementsSize; i++) { - PsiElement element = elements.get(i); - if (languages == null || languages.contains(element.getLanguage().getID())) { - element.accept(elementVisitor); - } - ProgressManager.checkCanceled(); - } } void inspectInjectedPsi(@NotNull final List elements, @@ -451,7 +421,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass @NotNull String message, String toolTip, PsiElement psiElement) { - TextRange textRange = ((ProblemDescriptorImpl)problemDescriptor).getTextRange(); + TextRange textRange = ((ProblemDescriptorBase)problemDescriptor).getTextRange(); if (textRange == null || psiElement == null) return null; boolean isFileLevel = psiElement instanceof PsiFile && textRange.equals(psiElement.getTextRange()); @@ -555,7 +525,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass case GENERIC_ERROR: return HighlightInfoType.ERROR; case INFORMATION: - final TextAttributesKey attributes = ((ProblemDescriptorImpl)problemDescriptor).getEnforcedTextAttributes(); + final TextAttributesKey attributes = ((ProblemDescriptorBase)problemDescriptor).getEnforcedTextAttributes(); if (attributes != null) { return new HighlightInfoType.HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, attributes); } @@ -647,7 +617,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass @NotNull HighlightInfoType level, @NotNull Set> emptyActionRegistered, @NotNull PsiElement element) { - @NonNls String message = ProblemDescriptionNode.renderDescriptionMessage(descriptor, element); + @NonNls String message = ProblemDescriptorUtil.renderDescriptionMessage(descriptor, element); final HighlightDisplayKey key = HighlightDisplayKey.find(tool.getShortName()); final InspectionProfile inspectionProfile = myProfileWrapper.getInspectionProfile(); @@ -697,7 +667,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass QuickFixAction.registerQuickFixAction(highlightInfo, hintAction, key); needEmptyAction = false; } - if (((ProblemDescriptorImpl)descriptor).getEnforcedTextAttributes() != null) { + if (((ProblemDescriptorBase)descriptor).getEnforcedTextAttributes() != null) { needEmptyAction = false; } if (needEmptyAction && emptyActionRegistered.add(Pair.create(new TextRange(highlightInfo.fixStartOffset, highlightInfo.fixEndOffset), tool.getShortName()))) { @@ -785,7 +755,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass LocalInspectionToolSession injSession = new LocalInspectionToolSession(injectedPsi, 0, injectedPsi.getTextLength()); Collection languages = pair.getValue(); - createVisitorAndAcceptElements(tool, holder, isOnTheFly, injSession, elements, languages); + InspectionEngine.createVisitorAndAcceptElements(tool, holder, isOnTheFly, injSession, elements, languages); tool.inspectionFinished(injSession, holder); List problems = holder.getResults(); if (!problems.isEmpty()) { diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/DescriptorComposer.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/DescriptorComposer.java index abe4ca9e7e5d..4e983b91191b 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/DescriptorComposer.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/DescriptorComposer.java @@ -16,13 +16,9 @@ package com.intellij.codeInspection.ex; -import com.intellij.codeInspection.CommonProblemDescriptor; -import com.intellij.codeInspection.InspectionsBundle; -import com.intellij.codeInspection.ProblemDescriptor; -import com.intellij.codeInspection.QuickFix; +import com.intellij.codeInspection.*; import com.intellij.codeInspection.reference.RefElement; import com.intellij.codeInspection.reference.RefEntity; -import com.intellij.codeInspection.ui.ProblemDescriptionNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileEditor.FileDocumentManager; @@ -151,7 +147,7 @@ public class DescriptorComposer extends HTMLComposerImpl { } anchor.append("\">"); - anchor.append(ProblemDescriptionNode.extractHighlightedText(description, expression).replaceAll("\\$", "\\\\\\$")); + anchor.append(ProblemDescriptorUtil.extractHighlightedText(description, expression).replaceAll("\\$", "\\\\\\$")); //noinspection HardCodedStringLiteral anchor.append(""); } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/DescriptorProviderInspection.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/DescriptorProviderInspection.java index 2914f1340600..8ef537d3460d 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/DescriptorProviderInspection.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/DescriptorProviderInspection.java @@ -20,7 +20,6 @@ import com.intellij.codeInspection.*; import com.intellij.codeInspection.reference.RefElement; import com.intellij.codeInspection.reference.RefEntity; import com.intellij.codeInspection.reference.RefModule; -import com.intellij.codeInspection.ui.ProblemDescriptionNode; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.components.PathMacroManager; import com.intellij.openapi.diagnostic.Logger; @@ -278,7 +277,8 @@ public abstract class DescriptorProviderInspection extends InspectionTool implem @NonNls final String template = description.getDescriptionTemplate(); int line = description instanceof ProblemDescriptor ? ((ProblemDescriptor)description).getLineNumber() : -1; final PsiElement psiElement = description instanceof ProblemDescriptor ? ((ProblemDescriptor)description).getPsiElement() : null; - @NonNls String problemText = StringUtil.replace(StringUtil.replace(template, "#ref", psiElement != null ? ProblemDescriptionNode.extractHighlightedText(description, psiElement): "") , " #loc ", " "); + @NonNls String problemText = StringUtil.replace(StringUtil.replace(template, "#ref", psiElement != null ? ProblemDescriptorUtil + .extractHighlightedText(description, psiElement): "") , " #loc ", " "); Element element = refEntity.getRefManager().export(refEntity, parentNode, line); if (element == null) return; diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionManagerEx.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionManagerEx.java index 11e980ef59b2..6615e3dc660e 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionManagerEx.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionManagerEx.java @@ -30,7 +30,6 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.NotNullLazyValue; -import com.intellij.openapi.util.TextRange; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowAnchor; import com.intellij.openapi.wm.ToolWindowId; @@ -49,22 +48,20 @@ import org.jetbrains.annotations.TestOnly; import java.util.HashSet; import java.util.Set; -public class InspectionManagerEx extends InspectionManager { +public class InspectionManagerEx extends InspectionManagerBase { private GlobalInspectionContextImpl myGlobalInspectionContext = null; - private final Project myProject; @NonNls private String myCurrentProfileName; private final NotNullLazyValue myContentManager; - private final Set myRunningContexts = new HashSet(); - public InspectionManagerEx(Project project) { - myProject = project; + public InspectionManagerEx(final Project project) { + super(project); if (ApplicationManager.getApplication().isHeadlessEnvironment()) { myContentManager = new NotNullLazyValue() { @NotNull @Override protected ContentManager compute() { - return ContentFactory.SERVICE.getInstance().createContentManager(new TabbedPaneContentUI(), true, myProject); + return ContentFactory.SERVICE.getInstance().createContentManager(new TabbedPaneContentUI(), true, project); } }; } @@ -73,9 +70,9 @@ public class InspectionManagerEx extends InspectionManager { @NotNull @Override protected ContentManager compute() { - ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject); + ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(project); ToolWindow toolWindow = - toolWindowManager.registerToolWindow(ToolWindowId.INSPECTION, true, ToolWindowAnchor.BOTTOM, myProject); + toolWindowManager.registerToolWindow(ToolWindowId.INSPECTION, true, ToolWindowAnchor.BOTTOM, project); ContentManager contentManager = toolWindow.getContentManager(); toolWindow.setIcon(AllIcons.Toolwindows.ToolWindowInspection); new ContentManagerWatcher(toolWindow, contentManager); @@ -85,103 +82,26 @@ public class InspectionManagerEx extends InspectionManager { } } - @Override - @NotNull - public Project getProject() { - return myProject; - } - - @Override - @NotNull - public CommonProblemDescriptor createProblemDescriptor(@NotNull String descriptionTemplate, QuickFix... fixes) { - return new CommonProblemDescriptorImpl(fixes, descriptionTemplate); - } - - @Override - @NotNull - public ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, - @NotNull String descriptionTemplate, - LocalQuickFix fix, - @NotNull ProblemHighlightType highlightType, - boolean onTheFly) { - LocalQuickFix[] quickFixes = fix != null ? new LocalQuickFix[]{fix} : null; - return createProblemDescriptor(psiElement, descriptionTemplate, onTheFly, quickFixes, highlightType); - } - - @Override - @NotNull - public ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, - @NotNull String descriptionTemplate, - boolean onTheFly, - LocalQuickFix[] fixes, - @NotNull ProblemHighlightType highlightType) { - return createProblemDescriptor(psiElement, descriptionTemplate, fixes, highlightType, onTheFly, false); - } - - @Override - @NotNull - public ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, - @NotNull String descriptionTemplate, - LocalQuickFix[] fixes, - @NotNull ProblemHighlightType highlightType, - boolean onTheFly, - boolean isAfterEndOfLine) { - return new ProblemDescriptorImpl(psiElement, psiElement, descriptionTemplate, fixes, highlightType, isAfterEndOfLine, null, onTheFly); - } - - @Override - @NotNull - public ProblemDescriptor createProblemDescriptor(@NotNull PsiElement startElement, - @NotNull PsiElement endElement, - @NotNull String descriptionTemplate, - @NotNull ProblemHighlightType highlightType, - boolean onTheFly, - LocalQuickFix... fixes) { - return new ProblemDescriptorImpl(startElement, endElement, descriptionTemplate, fixes, highlightType, false, null, onTheFly); - } @NotNull - @Override - public ProblemDescriptor createProblemDescriptor(@NotNull final PsiElement psiElement, - final TextRange rangeInElement, - @NotNull final String descriptionTemplate, - @NotNull final ProblemHighlightType highlightType, - boolean onTheFly, - final LocalQuickFix... fixes) { - return new ProblemDescriptorImpl(psiElement, psiElement, descriptionTemplate, fixes, highlightType, false, rangeInElement, onTheFly); - } - - @NotNull - @Override public ProblemDescriptor createProblemDescriptor(@NotNull final PsiElement psiElement, @NotNull final String descriptionTemplate, @NotNull final ProblemHighlightType highlightType, @Nullable final HintAction hintAction, boolean onTheFly, final LocalQuickFix... fixes) { - return new ProblemDescriptorImpl(psiElement, psiElement, descriptionTemplate, fixes, highlightType, false, null, hintAction, onTheFly); } - @NotNull - @Override - public ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, - @NotNull String descriptionTemplate, - boolean showTooltip, - @NotNull ProblemHighlightType highlightType, boolean onTheFly, LocalQuickFix... fixes) { - return new ProblemDescriptorImpl(psiElement, psiElement, descriptionTemplate, fixes, highlightType, false, null, showTooltip, null, - onTheFly); - } - public GlobalInspectionContextImpl createNewGlobalContext(boolean reuse) { if (reuse) { if (myGlobalInspectionContext == null) { - myGlobalInspectionContext = new GlobalInspectionContextImpl(myProject, myContentManager); + myGlobalInspectionContext = new GlobalInspectionContextImpl(getProject(), myContentManager); } myRunningContexts.add(myGlobalInspectionContext); return myGlobalInspectionContext; } - final GlobalInspectionContextImpl inspectionContext = new GlobalInspectionContextImpl(myProject, myContentManager); + final GlobalInspectionContextImpl inspectionContext = new GlobalInspectionContextImpl(getProject(), myContentManager); myRunningContexts.add(inspectionContext); return inspectionContext; } @@ -192,7 +112,7 @@ public class InspectionManagerEx extends InspectionManager { public String getCurrentProfile() { if (myCurrentProfileName == null) { - final InspectionProjectProfileManager profileManager = InspectionProjectProfileManager.getInstance(myProject); + final InspectionProjectProfileManager profileManager = InspectionProjectProfileManager.getInstance(getProject()); myCurrentProfileName = profileManager.getProjectProfile(); if (myCurrentProfileName == null) { myCurrentProfileName = InspectionProfileManager.getInstance().getRootProfile().getName(); @@ -241,62 +161,7 @@ public class InspectionManagerEx extends InspectionManager { return false; } - @Override - @Deprecated @NotNull - public ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, - @NotNull String descriptionTemplate, - LocalQuickFix fix, - @NotNull ProblemHighlightType highlightType) { - LocalQuickFix[] quickFixes = fix != null ? new LocalQuickFix[]{fix} : null; - return createProblemDescriptor(psiElement, descriptionTemplate, false, quickFixes, highlightType); - } - - @Override - @Deprecated - @NotNull - public ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, - @NotNull String descriptionTemplate, - LocalQuickFix[] fixes, - @NotNull ProblemHighlightType highlightType) { - return createProblemDescriptor(psiElement, descriptionTemplate, fixes, highlightType, false, false); - } - - @Override - @Deprecated - @NotNull - public ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, - @NotNull String descriptionTemplate, - LocalQuickFix[] fixes, - @NotNull ProblemHighlightType highlightType, - boolean isAfterEndOfLine) { - return new ProblemDescriptorImpl(psiElement, psiElement, descriptionTemplate, fixes, highlightType, isAfterEndOfLine, null, true); - } - - @Override - @Deprecated - @NotNull - public ProblemDescriptor createProblemDescriptor(@NotNull PsiElement startElement, - @NotNull PsiElement endElement, - @NotNull String descriptionTemplate, - @NotNull ProblemHighlightType highlightType, - LocalQuickFix... fixes) { - return new ProblemDescriptorImpl(startElement, endElement, descriptionTemplate, fixes, highlightType, false, null, true); - } - - @NotNull - @Override - @Deprecated - public ProblemDescriptor createProblemDescriptor(@NotNull final PsiElement psiElement, - final TextRange rangeInElement, - @NotNull final String descriptionTemplate, - @NotNull final ProblemHighlightType highlightType, - final LocalQuickFix... fixes) { - return new ProblemDescriptorImpl(psiElement, psiElement, descriptionTemplate, fixes, highlightType, false, rangeInElement, true); - } - - @NotNull - @Override @Deprecated public ProblemDescriptor createProblemDescriptor(@NotNull final PsiElement psiElement, @NotNull final String descriptionTemplate, @@ -307,18 +172,6 @@ public class InspectionManagerEx extends InspectionManager { return new ProblemDescriptorImpl(psiElement, psiElement, descriptionTemplate, fixes, highlightType, false, null, hintAction, true); } - @NotNull - @Deprecated - @Override - public ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, - @NotNull String descriptionTemplate, - boolean showTooltip, - @NotNull ProblemHighlightType highlightType, - LocalQuickFix... fixes) { - return new ProblemDescriptorImpl(psiElement, psiElement, descriptionTemplate, fixes, highlightType, false, null, showTooltip, null, - true); - } - @TestOnly public NotNullLazyValue getContentManager() { return myContentManager; diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/ProblemDescriptorImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/ProblemDescriptorImpl.java index 6011a97136b3..2955f369e108 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/ProblemDescriptorImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/ProblemDescriptorImpl.java @@ -17,37 +17,16 @@ package com.intellij.codeInspection.ex; import com.intellij.codeInspection.*; -import com.intellij.codeInspection.ui.ProblemDescriptionNode; -import com.intellij.lang.injection.InjectedLanguageManager; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.colors.TextAttributesKey; -import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; -import com.intellij.pom.Navigatable; -import com.intellij.psi.*; -import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** * @author max */ -public class ProblemDescriptorImpl extends CommonProblemDescriptorImpl implements ProblemDescriptor { - private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.ProblemDescriptorImpl"); - - @NotNull private final SmartPsiElementPointer myStartSmartPointer; - @Nullable private final SmartPsiElementPointer myEndSmartPointer; - - private final ProblemHighlightType myHighlightType; - private Navigatable myNavigatable; - private final boolean myAfterEndOfLine; - private final TextRange myTextRangeInElement; - private final boolean myShowTooltip; +public class ProblemDescriptorImpl extends ProblemDescriptorBase implements ProblemDescriptor { private final HintAction myHintAction; - private TextAttributesKey myEnforcedTextAttributes; - private int myLineNumber = -1; - private String myProblemGroup; public ProblemDescriptorImpl(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @@ -83,163 +62,11 @@ public class ProblemDescriptorImpl extends CommonProblemDescriptorImpl implement @Nullable HintAction hintAction, boolean onTheFly) { - super(fixes, descriptionTemplate); - myShowTooltip = tooltip; + super(startElement, endElement, descriptionTemplate, fixes, highlightType, isAfterEndOfLine, rangeInElement, tooltip, onTheFly); myHintAction = hintAction; - PsiFile startContainingFile = startElement.getContainingFile(); - LOG.assertTrue(startContainingFile != null && startContainingFile.isValid() || startElement.isValid(), startElement); - PsiFile endContainingFile = startElement == endElement ? startContainingFile : endElement.getContainingFile(); - LOG.assertTrue(startElement == endElement || endContainingFile != null && endContainingFile.isValid() || endElement.isValid(), endElement); - assertPhysical(startElement); - if (startElement != endElement) assertPhysical(endElement); - - final TextRange startElementRange = startElement.getTextRange(); - LOG.assertTrue(startElementRange != null, startElement); - final TextRange endElementRange = endElement.getTextRange(); - LOG.assertTrue(endElementRange != null, endElement); - if (startElementRange.getStartOffset() >= endElementRange.getEndOffset()) { - if (!(startElement instanceof PsiFile && endElement instanceof PsiFile)) { - LOG.error("Empty PSI elements should not be passed to createDescriptor. Start: " + startElement + ", end: " + endElement); - } - } - - myHighlightType = highlightType; - final Project project = startContainingFile == null ? startElement.getProject() : startContainingFile.getProject(); - final SmartPointerManager manager = SmartPointerManager.getInstance(project); - myStartSmartPointer = manager.createSmartPsiElementPointer(startElement, startContainingFile); - myEndSmartPointer = startElement == endElement ? null : manager.createSmartPsiElementPointer(endElement, endContainingFile); - - myAfterEndOfLine = isAfterEndOfLine; - myTextRangeInElement = rangeInElement; - } - - protected void assertPhysical(final PsiElement element) { - if (!element.isPhysical()) { - LOG.error("Non-physical PsiElement. Physical element is required to be able to anchor the problem in the source tree: " + - element + "; file: " + element.getContainingFile()); - } - } - - @Override - public PsiElement getPsiElement() { - PsiElement startElement = getStartElement(); - if (myEndSmartPointer == null) { - return startElement; - } - PsiElement endElement = getEndElement(); - if (startElement == endElement) { - return startElement; - } - if (startElement == null || endElement == null) return null; - return PsiTreeUtil.findCommonParent(startElement, endElement); - } - - @Override - public PsiElement getStartElement() { - return myStartSmartPointer.getElement(); - } - - @Override - public PsiElement getEndElement() { - return myEndSmartPointer == null ? getStartElement() : myEndSmartPointer.getElement(); - } - - @Override - public int getLineNumber() { - if (myLineNumber == -1) { - PsiElement psiElement = getPsiElement(); - if (psiElement == null) return -1; - if (!psiElement.isValid()) return -1; - LOG.assertTrue(psiElement.isPhysical()); - InjectedLanguageManager manager = InjectedLanguageManager.getInstance(psiElement.getProject()); - PsiFile containingFile = manager.getTopLevelFile(psiElement); - Document document = PsiDocumentManager.getInstance(psiElement.getProject()).getDocument(containingFile); - if (document == null) return -1; - TextRange textRange = getTextRange(); - if (textRange == null) return -1; - textRange = manager.injectedToHost(psiElement, textRange); - myLineNumber = document.getLineNumber(textRange.getStartOffset()) + 1; - } - return myLineNumber; - } - - @NotNull - @Override - public ProblemHighlightType getHighlightType() { - return myHighlightType; - } - - @Override - public boolean isAfterEndOfLine() { - return myAfterEndOfLine; - } - - @Override - public void setTextAttributes(TextAttributesKey key) { - myEnforcedTextAttributes = key; - } - - public TextAttributesKey getEnforcedTextAttributes() { - return myEnforcedTextAttributes; - } - - public TextRange getTextRangeForNavigation() { - TextRange textRange = getTextRange(); - if (textRange == null) return null; - PsiElement element = getPsiElement(); - return InjectedLanguageManager.getInstance(element.getProject()).injectedToHost(element, textRange); - } - - public TextRange getTextRange() { - PsiElement startElement = getStartElement(); - PsiElement endElement = myEndSmartPointer == null ? startElement : getEndElement(); - if (startElement == null || endElement == null) { - return null; - } - - TextRange textRange = startElement.getTextRange(); - if (startElement == endElement) { - if (isAfterEndOfLine()) return new TextRange(textRange.getEndOffset(), textRange.getEndOffset()); - if (myTextRangeInElement != null) { - return new TextRange(textRange.getStartOffset() + myTextRangeInElement.getStartOffset(), - textRange.getStartOffset() + myTextRangeInElement.getEndOffset()); - } - return textRange; - } - return new TextRange(textRange.getStartOffset(), endElement.getTextRange().getEndOffset()); - } - - public Navigatable getNavigatable() { - return myNavigatable; - } - - public void setNavigatable(final Navigatable navigatable) { - myNavigatable = navigatable; } public HintAction getHintAction() { return myHintAction; } - - @Override - @Nullable - public String getProblemGroup() { - return myProblemGroup; - } - - @Override - public void setProblemGroup(@Nullable String problemGroup) { - myProblemGroup = problemGroup; - } - - @Override - public boolean showTooltip() { - return myShowTooltip; - } - - @Override - public String toString() { - PsiElement element = getPsiElement(); - return ProblemDescriptionNode.renderDescriptionMessage(this, element); - } } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/ProblemDescriptionNode.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/ProblemDescriptionNode.java index 264ea0b0933f..db9082e26bc2 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/ProblemDescriptionNode.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/ProblemDescriptionNode.java @@ -16,20 +16,13 @@ package com.intellij.codeInspection.ui; -import com.intellij.codeInspection.CommonProblemDescriptor; -import com.intellij.codeInspection.InspectionsBundle; -import com.intellij.codeInspection.ProblemDescriptor; -import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.codeInspection.*; import com.intellij.codeInspection.ex.DescriptorProviderInspection; -import com.intellij.codeInspection.ex.ProblemDescriptorImpl; import com.intellij.codeInspection.reference.RefElement; import com.intellij.codeInspection.reference.RefEntity; import com.intellij.icons.AllIcons; -import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.FileStatus; import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -69,8 +62,8 @@ public class ProblemDescriptionNode extends InspectionTreeNode { @Override public Icon getIcon(boolean expanded) { - if (myDescriptor instanceof ProblemDescriptorImpl) { - ProblemHighlightType problemHighlightType = ((ProblemDescriptorImpl)myDescriptor).getHighlightType(); + if (myDescriptor instanceof ProblemDescriptorBase) { + ProblemHighlightType problemHighlightType = ((ProblemDescriptorBase)myDescriptor).getHighlightType(); if (problemHighlightType == ProblemHighlightType.ERROR) return AllIcons.General.Error; if (problemHighlightType == ProblemHighlightType.GENERIC_ERROR_OR_WARNING) return AllIcons.General.Warning; } @@ -122,62 +115,6 @@ public class ProblemDescriptionNode extends InspectionTreeNode { if (descriptor == null) return ""; PsiElement element = descriptor instanceof ProblemDescriptor ? ((ProblemDescriptor)descriptor).getPsiElement() : null; - return renderDescriptionMessage(descriptor, element, true)/*.replaceAll("<[^>]*>", "")*/; - } - - @NotNull - public static String renderDescriptionMessage(@NotNull CommonProblemDescriptor descriptor, PsiElement element) { - return renderDescriptionMessage(descriptor, element, false); - } - - @NotNull - public static String renderDescriptionMessage(@NotNull CommonProblemDescriptor descriptor, PsiElement element, boolean appendLineNumber) { - String message = descriptor.getDescriptionTemplate(); - - // no message. Should not be the case if inspection correctly implemented. - // noinspection ConstantConditions - if (message == null) return ""; - - if (appendLineNumber && descriptor instanceof ProblemDescriptor && !message.contains("#ref") && message.contains("#loc")) { - final int lineNumber = ((ProblemDescriptor)descriptor).getLineNumber(); - if (lineNumber >= 0) { - message = StringUtil.replace(message, "#loc", "(" + InspectionsBundle.message("inspection.export.results.at.line") + " " + lineNumber + ")"); - } - } - message = StringUtil.replace(message, "", "'"); - message = StringUtil.replace(message, "", "'"); - message = StringUtil.replace(message, "#loc ", ""); - message = StringUtil.replace(message, " #loc", ""); - message = StringUtil.replace(message, "#loc", ""); - if (message.contains("#ref")) { - String ref = extractHighlightedText(descriptor, element); - message = StringUtil.replace(message, "#ref", ref); - } - - final int endIndex = message.indexOf("#end"); - if (endIndex > 0) { - message = message.substring(0, endIndex); - } - - message = StringUtil.unescapeXml(message).trim(); - return message; - } - - public static String extractHighlightedText(@NotNull CommonProblemDescriptor descriptor, PsiElement psiElement) { - if (psiElement == null || !psiElement.isValid()) return ""; - String ref = psiElement.getText(); - if (descriptor instanceof ProblemDescriptorImpl) { - TextRange textRange = ((ProblemDescriptorImpl)descriptor).getTextRange(); - final TextRange elementRange = psiElement.getTextRange(); - if (textRange != null && elementRange != null) { - textRange = textRange.shiftRight(-elementRange.getStartOffset()); - if (textRange.getStartOffset() >= 0 && textRange.getEndOffset() <= elementRange.getLength()) { - ref = textRange.substring(ref); - } - } - } - ref = StringUtil.replaceChar(ref, '\n', ' ').trim(); - ref = StringUtil.first(ref, 100, true); - return ref; + return ProblemDescriptorUtil.renderDescriptionMessage(descriptor, element, true)/*.replaceAll("<[^>]*>", "")*/; } } diff --git a/platform/platform-api/platform-api.iml b/platform/platform-api/platform-api.iml index 93c9f0ebea70..480d221be4eb 100644 --- a/platform/platform-api/platform-api.iml +++ b/platform/platform-api/platform-api.iml @@ -31,6 +31,7 @@ + diff --git a/platform/platform-api/src/com/intellij/codeHighlighting/DefaultIconCreator.java b/platform/platform-api/src/com/intellij/codeHighlighting/DefaultIconCreator.java new file mode 100644 index 000000000000..e06f22325aa7 --- /dev/null +++ b/platform/platform-api/src/com/intellij/codeHighlighting/DefaultIconCreator.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeHighlighting; + +import com.intellij.openapi.editor.colors.EditorColorsManager; +import com.intellij.openapi.editor.colors.EditorColorsScheme; +import com.intellij.openapi.editor.colors.TextAttributesKey; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; + +public class DefaultIconCreator implements HighlightDisplayLevel.IconCreator { + @Override + public Icon createIcon(@NotNull TextAttributesKey key) { + final EditorColorsManager manager = EditorColorsManager.getInstance(); + if (manager != null) { + final EditorColorsScheme globalScheme = manager.getGlobalScheme(); + return HighlightDisplayLevel.createIconByMask(globalScheme.getAttributes(key).getErrorStripeColor()); + } + + return null; + } +} diff --git a/platform/platform-impl/platform-impl.iml b/platform/platform-impl/platform-impl.iml index edd1c9c2d2f2..085849048137 100644 --- a/platform/platform-impl/platform-impl.iml +++ b/platform/platform-impl/platform-impl.iml @@ -36,6 +36,7 @@ + diff --git a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml index 873b48d0ff6a..b56a6dd1a3fd 100644 --- a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml @@ -344,6 +344,8 @@ + diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index ecbc500deb3e..45a262c8eda2 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -790,7 +790,7 @@ - + diff --git a/spellchecker/src/com/intellij/spellchecker/quickfixes/AcceptWordAsCorrect.java b/spellchecker/src/com/intellij/spellchecker/quickfixes/AcceptWordAsCorrect.java index dd47b0c3d591..0409df133073 100644 --- a/spellchecker/src/com/intellij/spellchecker/quickfixes/AcceptWordAsCorrect.java +++ b/spellchecker/src/com/intellij/spellchecker/quickfixes/AcceptWordAsCorrect.java @@ -16,7 +16,7 @@ package com.intellij.spellchecker.quickfixes; import com.intellij.codeInspection.ProblemDescriptor; -import com.intellij.codeInspection.ui.ProblemDescriptionNode; +import com.intellij.codeInspection.ProblemDescriptorUtil; import com.intellij.openapi.actionSystem.Anchor; import com.intellij.openapi.project.Project; import com.intellij.spellchecker.SpellCheckerManager; @@ -57,7 +57,7 @@ public class AcceptWordAsCorrect implements SpellCheckerQuickFix { if (myWord != null) { spellCheckerManager.acceptWordAsCorrect(myWord, project); } else { - spellCheckerManager.acceptWordAsCorrect(ProblemDescriptionNode.extractHighlightedText(descriptor, descriptor.getPsiElement()), project); + spellCheckerManager.acceptWordAsCorrect(ProblemDescriptorUtil.extractHighlightedText(descriptor, descriptor.getPsiElement()), project); } }