diff --git a/RegExpSupport/src/org/intellij/lang/regexp/validation/RegExpAnnotator.java b/RegExpSupport/src/org/intellij/lang/regexp/validation/RegExpAnnotator.java index 0d66b153b9d4..52307d1cd58d 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/validation/RegExpAnnotator.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/validation/RegExpAnnotator.java @@ -35,8 +35,7 @@ import org.jetbrains.annotations.Nullable; public final class RegExpAnnotator extends RegExpElementVisitor implements Annotator { private AnnotationHolder myHolder; - // made this synchronized after running into the assertion below a couple of times. - public synchronized void annotate(PsiElement psiElement, AnnotationHolder holder) { + public void annotate(PsiElement psiElement, AnnotationHolder holder) { assert myHolder == null : "unsupported concurrent annotator invocation"; try { myHolder = holder; diff --git a/platform/lang-api/src/com/intellij/lang/annotation/Annotator.java b/platform/lang-api/src/com/intellij/lang/annotation/Annotator.java index 663559243632..555e9f6839e7 100644 --- a/platform/lang-api/src/com/intellij/lang/annotation/Annotator.java +++ b/platform/lang-api/src/com/intellij/lang/annotation/Annotator.java @@ -16,6 +16,7 @@ package com.intellij.lang.annotation; import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; import java.util.Collections; import java.util.List; @@ -35,5 +36,5 @@ public interface Annotator { * @param psiElement the element to annotate. * @param holder the container which receives annotations created by the plugin. */ - void annotate(PsiElement psiElement, AnnotationHolder holder); + void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder holder); } 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 b9e7e417a2dc..f60fd8820724 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 @@ -299,11 +299,25 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP final AnnotationHolderImpl annotationHolder, final HighlightErrorFilter[] errorFilters, final InjectedLanguageManager injectedLanguageManager) { + Language injectedLanguage = injectedPsi.getLanguage(); + runAnnotatorsForInjected(injectedPsi, annotationHolder, errorFilters, injectedLanguageManager, injectedLanguage); + highlightInjectedSyntax(injectedLanguage, injectedPsi, annotationHolder); + } + + private static final PerThreadMap cachedAnnotators = new PerThreadMap() { + @NotNull + @Override + public Collection initialValue(@NotNull Language key) { + return LanguageAnnotators.INSTANCE.allForLanguage(key); + } + }; + private static void runAnnotatorsForInjected(final PsiFile injectedPsi, final AnnotationHolderImpl annotationHolder, + final HighlightErrorFilter[] errorFilters, final InjectedLanguageManager injectedLanguageManager, + Language injectedLanguage) { final DocumentWindow documentRange = ((VirtualFileWindow)injectedPsi.getViewProvider().getVirtualFile()).getDocumentWindow(); assert documentRange != null; assert documentRange.getText().equals(injectedPsi.getText()); - Language injectedLanguage = injectedPsi.getLanguage(); - final List annotators = LanguageAnnotators.INSTANCE.allForLanguage(injectedLanguage); + final List annotators = cachedAnnotators.get(injectedLanguage); final AnnotationHolderImpl fixingOffsetsHolder = new AnnotationHolderImpl() { public boolean add(final Annotation annotation) { return true; // we are going to hand off the annotation to the annotationHolder anyway @@ -356,7 +370,6 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP }; injectedPsi.accept(visitor); - highlightInjectedSyntax(injectedLanguage, injectedPsi, annotationHolder); } private static void highlightInjectedSyntax(final Language injectedLanguage, @@ -467,7 +480,6 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP final HighlightInfoHolder holder = createInfoHolder(); holder.setWritable(true); - final ProgressManager progressManager = ProgressManager.getInstance(); setProgressLimit((long)elements.size() * visitorArray.length); final int chunkSize = Math.max(1, elements.size() / 100); // one percent precision is enough diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/analysis/DefaultHighlightVisitor.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/analysis/DefaultHighlightVisitor.java index 0226623aeb48..8fb3d0fbc248 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/analysis/DefaultHighlightVisitor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/analysis/DefaultHighlightVisitor.java @@ -117,7 +117,7 @@ public class DefaultHighlightVisitor extends PsiElementVisitor implements Highli public static HighlightInfo createErrorElementInfo(final PsiErrorElement element) { TextRange range = element.getTextRange(); - if (range.getLength() > 0) { + if (!range.isEmpty()) { final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, range, element.getErrorDescription()); for(ErrorQuickFixProvider provider: Extensions.getExtensions(ErrorQuickFixProvider.EP_NAME)) { provider.registerErrorQuickFix(element, highlightInfo); @@ -132,10 +132,7 @@ public class DefaultHighlightVisitor extends PsiElementVisitor implements Highli String text = elementAtOffset == null ? null : elementAtOffset.getText(); HighlightInfo info; if (offset < fileLength && text != null && !StringUtil.startsWithChar(text, '\n') && !StringUtil.startsWithChar(text, '\r')) { - int start = offset; - int end = offset + 1; - info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, start, end, element.getErrorDescription()); - info.navigationShift = offset - start; + info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, offset, offset + 1, element.getErrorDescription()); } else { int start; diff --git a/platform/lang-impl/src/com/intellij/codeInspection/AnnotatorBasedInspection.java b/platform/lang-impl/src/com/intellij/codeInspection/AnnotatorBasedInspection.java index defa69ed4422..b1381e7e0092 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/AnnotatorBasedInspection.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/AnnotatorBasedInspection.java @@ -60,7 +60,7 @@ public class AnnotatorBasedInspection extends GlobalInspectionTool { @NotNull @Override public String getGroupDisplayName() { - return "General"; + return GENERAL_GROUP_NAME; } @Nls @@ -76,12 +76,14 @@ public class AnnotatorBasedInspection extends GlobalInspectionTool { return "Annotator"; } - private static class MyPsiRecursiveElementVisitor extends PsiRecursiveElementVisitor implements PsiLanguageInjectionHost.InjectedPsiVisitor { - private AnnotationHolder myHolder; + private static class MyPsiRecursiveElementVisitor extends PsiRecursiveElementVisitor + implements PsiLanguageInjectionHost.InjectedPsiVisitor { + private final AnnotationHolder myHolder; private List annotators; private PsiFile myFile; - public MyPsiRecursiveElementVisitor(final InspectionManager manager, final GlobalInspectionContext globalContext, + public MyPsiRecursiveElementVisitor(final InspectionManager manager, + final GlobalInspectionContext globalContext, final ProblemDescriptionsProcessor problemDescriptionsProcessor) { myHolder = new AnnotationHolderImpl() { @Override @@ -104,9 +106,13 @@ public class AnnotatorBasedInspection extends GlobalInspectionTool { return createProblem(elt, message, ProblemHighlightType.INFORMATION, HighlightSeverity.INFORMATION, null); } - private Annotation createProblem(PsiElement elt, String message, ProblemHighlightType problemHighlightType, - HighlightSeverity severity, TextRange range) { - GlobalInspectionUtil.createProblem(elt, message, problemHighlightType, range, manager, problemDescriptionsProcessor, globalContext); + private Annotation createProblem(PsiElement elt, + String message, + ProblemHighlightType problemHighlightType, + HighlightSeverity severity, + TextRange range) { + GlobalInspectionUtil + .createProblem(elt, message, problemHighlightType, range, manager, problemDescriptionsProcessor, globalContext); return super.createAnnotation(elt.getTextRange(), severity, message); } @@ -133,15 +139,8 @@ public class AnnotatorBasedInspection extends GlobalInspectionTool { @Override protected Annotation createAnnotation(TextRange range, HighlightSeverity severity, String message) { if (severity != HighlightSeverity.INFORMATION) { - GlobalInspectionUtil.createProblem( - myFile, - message, - HighlightInfo.convertSeverityToProblemHighlight(severity), - range, - manager, - problemDescriptionsProcessor, - globalContext - ); + GlobalInspectionUtil.createProblem(myFile, message, HighlightInfo.convertSeverityToProblemHighlight(severity), range, manager, + problemDescriptionsProcessor, globalContext); } return super.createAnnotation(range, severity, message); } @@ -158,12 +157,9 @@ public class AnnotatorBasedInspection extends GlobalInspectionTool { public void visitElement(PsiElement element) { super.visitElement(element); - List annotators = this.annotators != null ? - this.annotators:LanguageAnnotators.INSTANCE.allForLanguage(element.getLanguage()); - if (!annotators.isEmpty()) { - for(Annotator annotator:annotators) { - annotator.annotate(element, myHolder); - } + List elemAnnos = annotators != null ? annotators : LanguageAnnotators.INSTANCE.allForLanguage(element.getLanguage()); + for (Annotator annotator : elemAnnos) { + annotator.annotate(element, myHolder); } if (element instanceof PsiLanguageInjectionHost) { ((PsiLanguageInjectionHost)element).processInjectedPsi(this); @@ -174,7 +170,8 @@ public class AnnotatorBasedInspection extends GlobalInspectionTool { try { annotators = LanguageAnnotators.INSTANCE.allForLanguage(injectedPsi.getLanguage()); injectedPsi.acceptChildren(this); - } finally { + } + finally { annotators = null; } }