mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-08 15:09:39 +07:00
prevent AnnotationHolderImpl from extension, make AnnotationSessionImpl.computeWithSession() the only available mechanism to obtain anno holder
GitOrigin-RevId: 5565124fe4655c87730d3978b92672ed0eea4f90
This commit is contained in:
committed by
intellij-monorepo-bot
parent
7714170a67
commit
7a16a7a4c0
@@ -5,7 +5,7 @@ import com.intellij.codeHighlighting.HighlightDisplayLevel;
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.codeInsight.daemon.impl.AnnotationHolderImpl;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.AnnotationSessionImpl;
|
||||
import com.intellij.codeInsight.daemon.impl.AnnotationSessionImpl;
|
||||
import com.intellij.codeInspection.*;
|
||||
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
|
||||
import com.intellij.codeInspection.ex.Tools;
|
||||
@@ -329,11 +329,11 @@ public class InspectionValidatorWrapper implements Validator {
|
||||
|
||||
private Map<ProblemDescriptor, HighlightDisplayLevel> runXmlFileSchemaValidation(@NotNull XmlFile xmlFile) {
|
||||
Map<ProblemDescriptor, HighlightDisplayLevel> problemsMap = new LinkedHashMap<>();
|
||||
return AnnotationSessionImpl.computeWithSession(xmlFile, false, holder -> {
|
||||
List<ExternalAnnotator<?,?>> annotators = ExternalLanguageAnnotators.allForFile(XMLLanguage.INSTANCE, xmlFile);
|
||||
for (ExternalAnnotator<?, ?> annotator : annotators) {
|
||||
processAnnotator(xmlFile, holder, annotator);
|
||||
for (Annotation annotation : holder) {
|
||||
List<ExternalAnnotator<?, ?>> annotators = ExternalLanguageAnnotators.allForFile(XMLLanguage.INSTANCE, xmlFile);
|
||||
for (ExternalAnnotator<?, ?> annotator : annotators) {
|
||||
AnnotationSessionImpl.computeWithSession(xmlFile, false, annotator, annotationHolder -> {
|
||||
processAnnotator(xmlFile, ((AnnotationHolderImpl)annotationHolder), annotator);
|
||||
for (Annotation annotation : ((AnnotationHolderImpl)annotationHolder)) {
|
||||
HighlightInfo info = HighlightInfo.fromAnnotation(annotator, annotation);
|
||||
if (info.getSeverity() == HighlightSeverity.INFORMATION) continue;
|
||||
|
||||
@@ -342,17 +342,19 @@ public class InspectionValidatorWrapper implements Validator {
|
||||
if (startElement == null || endElement == null) continue;
|
||||
|
||||
ProblemDescriptor descriptor =
|
||||
myInspectionManager.createProblemDescriptor(startElement, endElement, info.getDescription(), ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
||||
myInspectionManager.createProblemDescriptor(startElement, endElement, info.getDescription(),
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
||||
false);
|
||||
HighlightDisplayLevel level = info.getSeverity() == HighlightSeverity.ERROR? HighlightDisplayLevel.ERROR: HighlightDisplayLevel.WARNING;
|
||||
HighlightDisplayLevel level =
|
||||
info.getSeverity() == HighlightSeverity.ERROR ? HighlightDisplayLevel.ERROR : HighlightDisplayLevel.WARNING;
|
||||
problemsMap.put(descriptor, level);
|
||||
}
|
||||
}
|
||||
holder.assertAllAnnotationsCreated();
|
||||
|
||||
if (!holder.hasAnnotations()) return Collections.emptyMap();
|
||||
return problemsMap;
|
||||
});
|
||||
((AnnotationHolderImpl)annotationHolder).assertAllAnnotationsCreated();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
if (problemsMap.isEmpty()) return Collections.emptyMap();
|
||||
return problemsMap;
|
||||
}
|
||||
|
||||
private static <X, Y> void processAnnotator(@NotNull XmlFile xmlFile, AnnotationHolderImpl holder, ExternalAnnotator<X, Y> annotator) {
|
||||
@@ -360,7 +362,7 @@ public class InspectionValidatorWrapper implements Validator {
|
||||
if (initial != null) {
|
||||
Y result = annotator.doAnnotate(initial);
|
||||
if (result != null) {
|
||||
holder.applyExternalAnnotatorWithContext(xmlFile, annotator, result);
|
||||
holder.applyExternalAnnotatorWithContext(xmlFile, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.ReflectionUtilRt;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.xml.util.XmlStringUtil;
|
||||
@@ -21,21 +20,20 @@ import org.jetbrains.annotations.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* Use {@link AnnotationHolder} instead. The members of this class can suddenly change or disappear.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@ApiStatus.NonExtendable
|
||||
sealed public class AnnotationHolderImpl extends SmartList<@NotNull Annotation> implements AnnotationHolder
|
||||
permits AnnotatorRunner.AnnotatorSpecificHolder {
|
||||
final public class AnnotationHolderImpl extends SmartList<@NotNull Annotation> implements AnnotationHolder {
|
||||
private static final Logger LOG = Logger.getInstance(AnnotationHolderImpl.class);
|
||||
private final AnnotationSession myAnnotationSession;
|
||||
|
||||
private final boolean myBatchMode;
|
||||
private Annotator myCurrentAnnotator;
|
||||
private ExternalAnnotator<?, ?> myExternalAnnotator;
|
||||
|
||||
private final AtomicReference<PsiElement> myCurrentElement = new AtomicReference<>();
|
||||
private final @NotNull Object/*Annotator|ExternalAnnotator*/ myAnnotator;
|
||||
/**
|
||||
* @deprecated Do not instantiate the AnnotationHolderImpl directly, please use the one provided via {@link Annotator#annotate(PsiElement, AnnotationHolder)} instead
|
||||
*/
|
||||
@@ -44,6 +42,17 @@ sealed public class AnnotationHolderImpl extends SmartList<@NotNull Annotation>
|
||||
public AnnotationHolderImpl(@NotNull AnnotationSession session, boolean batchMode) {
|
||||
myAnnotationSession = session;
|
||||
myBatchMode = batchMode;
|
||||
myAnnotator = (Annotator)(element, holder) -> {};
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
AnnotationHolderImpl(@NotNull Object/*Annotator|ExternalAnnotator*/ annotator, @NotNull AnnotationSession session, boolean batchMode) {
|
||||
myAnnotator = annotator;
|
||||
myAnnotationSession = session;
|
||||
myBatchMode = batchMode;
|
||||
if (!(annotator instanceof Annotator) && !(annotator instanceof ExternalAnnotator<?,?>)) {
|
||||
throw new IllegalArgumentException("annotator must be instanceof Annotator|ExternalAnnotator but got "+annotator.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -197,34 +206,39 @@ sealed public class AnnotationHolderImpl extends SmartList<@NotNull Annotation>
|
||||
|
||||
@Override
|
||||
public @NotNull AnnotationBuilder newAnnotation(@NotNull HighlightSeverity severity, @NotNull @Nls String message) {
|
||||
return createBuilder(severity, message, myCurrentElement, ObjectUtils.chooseNotNull(myCurrentAnnotator, myExternalAnnotator));
|
||||
return createBuilder(severity, message);
|
||||
}
|
||||
@Override
|
||||
public @NotNull AnnotationBuilder newSilentAnnotation(@NotNull HighlightSeverity severity) {
|
||||
return createBuilder(severity, null, myCurrentElement, ObjectUtils.chooseNotNull(myCurrentAnnotator, myExternalAnnotator));
|
||||
return createBuilder(severity, null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected B createBuilder(@NotNull HighlightSeverity severity, @Nls String message, PsiElement currentElement, Object currentAnnotator) {
|
||||
return new B(this, severity, message, currentElement, currentAnnotator);
|
||||
private B createBuilder(@NotNull HighlightSeverity severity, @Nls String message) {
|
||||
return new B(this, severity, message, myCurrentElement.get(), myAnnotator);
|
||||
}
|
||||
|
||||
private PsiElement myCurrentElement;
|
||||
@ApiStatus.Internal
|
||||
public void runAnnotatorWithContext(@NotNull PsiElement element, @NotNull Annotator annotator) {
|
||||
myCurrentAnnotator = annotator;
|
||||
myCurrentElement = element;
|
||||
annotator.annotate(element, this);
|
||||
myCurrentElement = null;
|
||||
myCurrentAnnotator = null;
|
||||
public void runAnnotatorWithContext(@NotNull PsiElement element) {
|
||||
myCurrentElement.set(element);
|
||||
((Annotator)myAnnotator).annotate(element, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* use {@link #runAnnotatorWithContext(PsiElement)}
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public <R> void applyExternalAnnotatorWithContext(@NotNull PsiFile file, @NotNull ExternalAnnotator<?,R> annotator, R result) {
|
||||
myExternalAnnotator = annotator;
|
||||
myCurrentElement = file;
|
||||
annotator.apply(file, result, this);
|
||||
myCurrentElement = null;
|
||||
myExternalAnnotator = null;
|
||||
@Deprecated(forRemoval = true)
|
||||
public void runAnnotatorWithContext(PsiElement element, Annotator annotator) {
|
||||
myCurrentElement.set(element);
|
||||
annotator.annotate(element, this);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public <R> void applyExternalAnnotatorWithContext(@NotNull PsiFile file, R result) {
|
||||
myCurrentElement.set(file);
|
||||
//noinspection unchecked
|
||||
((ExternalAnnotator<?,R>)myAnnotator).apply(file, result, this);
|
||||
}
|
||||
|
||||
// to assert each AnnotationBuilder did call .create() in the end
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.daemon.impl;
|
||||
|
||||
import com.intellij.lang.annotation.*;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.UserDataHolder;
|
||||
import com.intellij.openapi.util.UserDataHolderBase;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public final class AnnotationSessionImpl extends AnnotationSession {
|
||||
private final UserDataHolder myDataHolder = new UserDataHolderBase();
|
||||
private volatile TextRange myPriorityRange;
|
||||
private volatile HighlightSeverity myMinimumSeverity;
|
||||
|
||||
private AnnotationSessionImpl(@NotNull PsiFile file) {
|
||||
super(file);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
@NotNull
|
||||
public static AnnotationSession create(@NotNull PsiFile file) {
|
||||
return new AnnotationSessionImpl(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return text range (inside the {@link #getFile()}) for which annotators should be calculated sooner than for the remaining range in the file.
|
||||
* Usually this priority range corresponds to the range visible on screen.
|
||||
*/
|
||||
public @NotNull TextRange getPriorityRange() {
|
||||
return Objects.requireNonNullElseGet(myPriorityRange, ()->getFile().getTextRange());
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
void setVR(@NotNull TextRange range) {
|
||||
myPriorityRange = range;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> @Nullable T getUserData(@NotNull Key<T> key) {
|
||||
return myDataHolder.getUserData(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void putUserData(@NotNull Key<T> key, @Nullable T value) {
|
||||
myDataHolder.putUserData(key, value);
|
||||
}
|
||||
|
||||
void setMinimumSeverity(@Nullable HighlightSeverity severity) {
|
||||
myMinimumSeverity = severity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HighlightSeverity getMinimumSeverity() {
|
||||
return myMinimumSeverity;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static <T> T computeWithSession(@NotNull PsiFile psiFile, boolean batchMode, @NotNull Annotator annotator, @NotNull Function<? super AnnotationHolder, T> runnable) {
|
||||
return computeWithSession(batchMode, annotator, new AnnotationSessionImpl(psiFile), runnable);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static <T> T computeWithSession(@NotNull PsiFile psiFile, boolean batchMode, @NotNull ExternalAnnotator<?,?> annotator, @NotNull Function<? super AnnotationHolder, T> runnable) {
|
||||
return computeWithSession(batchMode, annotator, new AnnotationSessionImpl(psiFile), runnable);
|
||||
}
|
||||
|
||||
static <T> T computeWithSession(boolean batchMode,
|
||||
@NotNull Object annotator,
|
||||
@NotNull AnnotationSessionImpl session,
|
||||
@NotNull Function<? super AnnotationHolderImpl, T> runnable) {
|
||||
AnnotationHolderImpl holder = new AnnotationHolderImpl(annotator, session, batchMode);
|
||||
return runnable.apply(holder);
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,7 @@ import com.intellij.injected.editor.DocumentWindow;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.LanguageAnnotators;
|
||||
import com.intellij.lang.annotation.Annotation;
|
||||
import com.intellij.lang.annotation.AnnotationSession;
|
||||
import com.intellij.lang.annotation.Annotator;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx;
|
||||
@@ -30,11 +28,9 @@ import com.intellij.util.ReflectionUtil;
|
||||
import com.intellij.util.containers.CollectionFactory;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashingStrategy;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -127,25 +123,6 @@ final class AnnotatorRunner {
|
||||
}
|
||||
}
|
||||
|
||||
static final class AnnotatorSpecificHolder extends AnnotationHolderImpl {
|
||||
private final @NotNull Annotator myAnnotator;
|
||||
private final @NotNull AtomicReference<? extends PsiElement> myCurrentElement;
|
||||
|
||||
AnnotatorSpecificHolder(@NotNull Annotator annotator,
|
||||
@NotNull AtomicReference<? extends PsiElement> currentElement,
|
||||
@NotNull AnnotationSession annotationSession,
|
||||
boolean batchMode) {
|
||||
super(annotationSession, batchMode);
|
||||
myAnnotator = annotator;
|
||||
myCurrentElement = currentElement;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull B createBuilder(@NotNull HighlightSeverity severity, @Nls String message, PsiElement __, Object ___) {
|
||||
return super.createBuilder(severity, message, myCurrentElement.get(), myAnnotator);
|
||||
}
|
||||
}
|
||||
|
||||
private void runAnnotator(@NotNull Annotator annotator,
|
||||
@NotNull List<? extends PsiElement> insideThenOutside,
|
||||
@NotNull Map<Annotator, Set<Language>> supportedLanguages, @NotNull HighlightInfoUpdater highlightInfoUpdater) {
|
||||
@@ -153,48 +130,46 @@ final class AnnotatorRunner {
|
||||
if (supported.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
AtomicReference<PsiElement> currentElement = new AtomicReference<>();
|
||||
// create AnnotationHolderImpl for each Annotator to make it immutable thread-safe converter to the corresponding HighlightInfo
|
||||
AnnotationHolderImpl annotationHolder = new AnnotatorSpecificHolder(annotator, currentElement,
|
||||
AnnotatorRunner.this.myHighlightInfoHolder.getAnnotationSession(),
|
||||
AnnotatorRunner.this.myBatchMode);
|
||||
HighlightersRecycler emptyElementRecycler = new HighlightersRecycler(); // no need to call incinerate/release because it's always empty
|
||||
for (PsiElement element : insideThenOutside) {
|
||||
if (!supported.contains(element.getLanguage())) {
|
||||
continue;
|
||||
}
|
||||
if (myDumb && !DumbService.isDumbAware(annotator)) {
|
||||
continue;
|
||||
}
|
||||
ProgressManager.checkCanceled();
|
||||
currentElement.set(element);
|
||||
int sizeBefore = annotationHolder.size();
|
||||
annotator.annotate(element, annotationHolder);
|
||||
int sizeAfter = annotationHolder.size();
|
||||
|
||||
List<HighlightInfo> newInfos;
|
||||
if (sizeBefore == sizeAfter) {
|
||||
newInfos = List.of();
|
||||
}
|
||||
else {
|
||||
newInfos = new ArrayList<>(sizeAfter - sizeBefore);
|
||||
for (int i = sizeBefore; i < sizeAfter; i++) {
|
||||
Annotation annotation = annotationHolder.get(i);
|
||||
HighlightInfo info = HighlightInfo.fromAnnotation(annotator.getClass(), annotation, myBatchMode);
|
||||
info.setGroup(-1); // prevent DefaultHighlightProcessor from removing this info, we want to control it ourselves via `psiElementVisited` below
|
||||
addConvertedToHostInfo(info, newInfos);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("runAnnotator annotation="+annotation+" -> "+newInfos);
|
||||
}
|
||||
myAnnotatorStatisticsCollector.reportAnnotationProduced(annotator, annotation);
|
||||
AnnotationSessionImpl.computeWithSession(myBatchMode, annotator, (AnnotationSessionImpl)myHighlightInfoHolder.getAnnotationSession(), annotationHolder -> {
|
||||
HighlightersRecycler emptyElementRecycler = new HighlightersRecycler(); // no need to call incinerate/release because it's always empty
|
||||
for (PsiElement element : insideThenOutside) {
|
||||
if (!supported.contains(element.getLanguage())) {
|
||||
continue;
|
||||
}
|
||||
results.addAll(newInfos);
|
||||
if (myDumb && !DumbService.isDumbAware(annotator)) {
|
||||
continue;
|
||||
}
|
||||
ProgressManager.checkCanceled();
|
||||
int sizeBefore = annotationHolder.size();
|
||||
annotationHolder.runAnnotatorWithContext(element);
|
||||
int sizeAfter = annotationHolder.size();
|
||||
|
||||
List<HighlightInfo> newInfos;
|
||||
if (sizeBefore == sizeAfter) {
|
||||
newInfos = List.of();
|
||||
}
|
||||
else {
|
||||
newInfos = new ArrayList<>(sizeAfter - sizeBefore);
|
||||
for (int i = sizeBefore; i < sizeAfter; i++) {
|
||||
Annotation annotation = annotationHolder.get(i);
|
||||
HighlightInfo info = HighlightInfo.fromAnnotation(annotator.getClass(), annotation, myBatchMode);
|
||||
info.setGroup(-1); // prevent DefaultHighlightProcessor from removing this info, we want to control it ourselves via `psiElementVisited` below
|
||||
addConvertedToHostInfo(info, newInfos);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("runAnnotator annotation="+annotation+" -> "+newInfos);
|
||||
}
|
||||
myAnnotatorStatisticsCollector.reportAnnotationProduced(annotator, annotation);
|
||||
}
|
||||
results.addAll(newInfos);
|
||||
}
|
||||
Document hostDocument = myPsiFile.getFileDocument();
|
||||
if (hostDocument instanceof DocumentWindow w) hostDocument = w.getDelegate();
|
||||
highlightInfoUpdater.psiElementVisited(annotator.getClass(), element, newInfos, hostDocument, myPsiFile, myProject,
|
||||
emptyElementRecycler, myHighlightingSession);
|
||||
}
|
||||
Document hostDocument = myPsiFile.getFileDocument();
|
||||
if (hostDocument instanceof DocumentWindow w) hostDocument = w.getDelegate();
|
||||
highlightInfoUpdater.psiElementVisited(annotator.getClass(), element, newInfos, hostDocument, myPsiFile, myProject,
|
||||
emptyElementRecycler, myHighlightingSession);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
private static void addPatchedInfos(@NotNull HighlightInfo info,
|
||||
|
||||
@@ -6,7 +6,6 @@ import com.intellij.codeHighlighting.Pass;
|
||||
import com.intellij.codeHighlighting.RainbowHighlighter;
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
import com.intellij.codeInsight.daemon.RainbowVisitor;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.AnnotationSessionImpl;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightInfoHolder;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightingLevelManager;
|
||||
import com.intellij.codeInsight.highlighting.PassRunningAssert;
|
||||
|
||||
@@ -1,66 +1,24 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.daemon.impl.analysis;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.AnnotationHolderImpl;
|
||||
import com.intellij.lang.annotation.AnnotationSession;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.UserDataHolder;
|
||||
import com.intellij.openapi.util.UserDataHolderBase;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Do not use, for binary compatibility only
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
@ApiStatus.Internal
|
||||
public final class AnnotationSessionImpl extends AnnotationSession {
|
||||
private final UserDataHolder myDataHolder = new UserDataHolderBase();
|
||||
private volatile TextRange myPriorityRange;
|
||||
private volatile HighlightSeverity myMinimumSeverity;
|
||||
|
||||
public class AnnotationSessionImpl {
|
||||
@ApiStatus.Internal
|
||||
AnnotationSessionImpl(@NotNull PsiFile file) {
|
||||
super(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return text range (inside the {@link #getFile()}) for which annotators should be calculated sooner than for the remaining range in the file.
|
||||
* Usually this priority range corresponds to the range visible on screen.
|
||||
*/
|
||||
public @NotNull TextRange getPriorityRange() {
|
||||
return Objects.requireNonNullElseGet(myPriorityRange, ()->getFile().getTextRange());
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public void setVR(@NotNull TextRange range) {
|
||||
myPriorityRange = range;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> @Nullable T getUserData(@NotNull Key<T> key) {
|
||||
return myDataHolder.getUserData(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void putUserData(@NotNull Key<T> key, @Nullable T value) {
|
||||
myDataHolder.putUserData(key, value);
|
||||
}
|
||||
|
||||
public void setMinimumSeverity(@Nullable HighlightSeverity severity) {
|
||||
myMinimumSeverity = severity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HighlightSeverity getMinimumSeverity() {
|
||||
return myMinimumSeverity;
|
||||
}
|
||||
|
||||
public static <T> T computeWithSession(@NotNull PsiFile psiFile, boolean batchMode, @NotNull Function<? super AnnotationHolderImpl, T> runnable) {
|
||||
AnnotationHolderImpl holder = new AnnotationHolderImpl(new AnnotationSessionImpl(psiFile), batchMode);
|
||||
AnnotationSession session = com.intellij.codeInsight.daemon.impl.AnnotationSessionImpl.create(psiFile);
|
||||
AnnotationHolderImpl holder = new AnnotationHolderImpl(session, batchMode);
|
||||
return runnable.apply(holder);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.daemon.impl.analysis;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.AnnotationSessionImpl;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfoFilter;
|
||||
import com.intellij.lang.annotation.AnnotationSession;
|
||||
@@ -23,7 +24,7 @@ public class HighlightInfoHolder {
|
||||
|
||||
public HighlightInfoHolder(@NotNull PsiFile contextFile, @NotNull HighlightInfoFilter @NotNull ... filters) {
|
||||
myContextFile = contextFile;
|
||||
myAnnotationSession = new AnnotationSessionImpl(contextFile);
|
||||
myAnnotationSession = AnnotationSessionImpl.create(contextFile);
|
||||
myFilters = filters;
|
||||
myInfos = new ArrayList<>(Math.max(10, contextFile.getTextLength() / 800)); // extrapolated from the most error-packed AbstractTreeUI
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.AnnotationSessionImpl;
|
||||
import com.intellij.codeInsight.daemon.impl.AnnotationHolderImpl;
|
||||
import com.intellij.codeInsight.daemon.impl.AnnotationSessionImpl;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.lang.annotation.Annotation;
|
||||
import com.intellij.lang.annotation.ExternalAnnotator;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -10,6 +12,8 @@ import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ExternalAnnotatorInspectionVisitor extends PsiElementVisitor {
|
||||
private static final Logger LOG = Logger.getInstance(ExternalAnnotatorInspectionVisitor.class);
|
||||
|
||||
@@ -44,10 +48,10 @@ public class ExternalAnnotatorInspectionVisitor extends PsiElementVisitor {
|
||||
if (annotationResult == null) {
|
||||
return ProblemDescriptor.EMPTY_ARRAY;
|
||||
}
|
||||
return ReadAction.compute(() -> AnnotationSessionImpl.computeWithSession(file, true, annotationHolder -> {
|
||||
annotationHolder.applyExternalAnnotatorWithContext(file, annotator, annotationResult);
|
||||
annotationHolder.assertAllAnnotationsCreated();
|
||||
return ProblemDescriptorUtil.convertToProblemDescriptors(annotationHolder, file);
|
||||
return ReadAction.compute(() -> AnnotationSessionImpl.computeWithSession(file, true, annotator, annotationHolder -> {
|
||||
((AnnotationHolderImpl)annotationHolder).applyExternalAnnotatorWithContext(file, annotationResult);
|
||||
((AnnotationHolderImpl)annotationHolder).assertAllAnnotationsCreated();
|
||||
return ProblemDescriptorUtil.convertToProblemDescriptors((List<? extends Annotation>)annotationHolder, file);
|
||||
}));
|
||||
}
|
||||
return ProblemDescriptor.EMPTY_ARRAY;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
package com.intellij.codeInsight.daemon.impl;
|
||||
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.AnnotationSessionImpl;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightingLevelManager;
|
||||
import com.intellij.codeInspection.InspectionProfile;
|
||||
import com.intellij.codeInspection.ex.InspectionProfileImpl;
|
||||
@@ -54,6 +53,7 @@ public final class ExternalToolPass extends ProgressableTextEditorHighlightingPa
|
||||
final @NotNull PsiFile psiRoot;
|
||||
final @NotNull K collectedInfo;
|
||||
volatile V annotationResult;
|
||||
volatile AnnotationHolderImpl annotationHolder;
|
||||
|
||||
MyData(@NotNull ExternalAnnotator<K,V> annotator, @NotNull PsiFile psiRoot, @NotNull K collectedInfo) {
|
||||
this.annotator = annotator;
|
||||
@@ -142,39 +142,36 @@ public final class ExternalToolPass extends ProgressableTextEditorHighlightingPa
|
||||
}
|
||||
|
||||
long modificationStampBefore = myDocument.getModificationStamp();
|
||||
AnnotationSessionImpl.computeWithSession(myFile, false, annotationHolder -> {
|
||||
Update update = new Update(myFile) {
|
||||
@Override
|
||||
public void setRejected() {
|
||||
super.setRejected();
|
||||
if (!myProject.isDisposed()) { // Project close in EDT might call MergeUpdateQueue.dispose which calls setRejected in EDT
|
||||
doFinish(convertToHighlights(annotationHolder));
|
||||
}
|
||||
Update update = new Update(myFile) {
|
||||
@Override
|
||||
public void setRejected() {
|
||||
super.setRejected();
|
||||
if (!myProject.isDisposed()) { // Project close in EDT might call MergeUpdateQueue.dispose which calls setRejected in EDT
|
||||
doFinish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (documentChanged(modificationStampBefore) || myProject.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
// have to instantiate new indicator because the old one (progress) might have already been canceled
|
||||
DaemonProgressIndicator indicator = new DaemonProgressIndicator();
|
||||
BackgroundTaskUtil.runUnderDisposeAwareIndicator(myProject, () -> {
|
||||
// run annotators outside the read action because they could start OSProcessHandler
|
||||
runChangeAware(myDocument, () -> doAnnotate());
|
||||
ReadAction.run(() -> {
|
||||
ProgressManager.checkCanceled();
|
||||
if (!documentChanged(modificationStampBefore)) {
|
||||
doApply(annotationHolder);
|
||||
doFinish(convertToHighlights(annotationHolder));
|
||||
}
|
||||
});
|
||||
}, indicator);
|
||||
@Override
|
||||
public void run() {
|
||||
if (documentChanged(modificationStampBefore) || myProject.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
};
|
||||
ExternalAnnotatorManager.getInstance().queue(update);
|
||||
return null;
|
||||
});
|
||||
// have to instantiate new indicator because the old one (progress) might have already been canceled
|
||||
DaemonProgressIndicator indicator = new DaemonProgressIndicator();
|
||||
BackgroundTaskUtil.runUnderDisposeAwareIndicator(myProject, () -> {
|
||||
// run annotators outside the read action because they could start OSProcessHandler
|
||||
runChangeAware(myDocument, () -> doAnnotate());
|
||||
ReadAction.run(() -> {
|
||||
ProgressManager.checkCanceled();
|
||||
if (!documentChanged(modificationStampBefore)) {
|
||||
doApply();
|
||||
doFinish();
|
||||
}
|
||||
});
|
||||
}, indicator);
|
||||
}
|
||||
};
|
||||
ExternalAnnotatorManager.getInstance().queue(update);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -206,24 +203,27 @@ public final class ExternalToolPass extends ProgressableTextEditorHighlightingPa
|
||||
|
||||
private static <K, V> void doAnnotate(@NotNull MyData<K, V> data) {
|
||||
try {
|
||||
data.annotationResult = data.annotator.doAnnotate(data.collectedInfo);
|
||||
AnnotationSessionImpl.computeWithSession(data.psiRoot, false, data.annotator, annotationHolder -> {
|
||||
data.annotationHolder = (AnnotationHolderImpl)annotationHolder;
|
||||
data.annotationResult = data.annotator.doAnnotate(data.collectedInfo);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
catch (Throwable t) {
|
||||
processError(t, data.annotator, data.psiRoot);
|
||||
}
|
||||
}
|
||||
|
||||
private void doApply(@NotNull AnnotationHolderImpl annotationHolder) {
|
||||
private void doApply() {
|
||||
for (MyData<?,?> data : myAnnotationData) {
|
||||
doApply(data, annotationHolder);
|
||||
doApply(data);
|
||||
}
|
||||
annotationHolder.assertAllAnnotationsCreated();
|
||||
}
|
||||
|
||||
private static <K, V> void doApply(@NotNull MyData<K, V> data, @NotNull AnnotationHolderImpl annotationHolder) {
|
||||
private static <K, V> void doApply(@NotNull MyData<K, V> data) {
|
||||
if (data.annotationResult != null && data.psiRoot.isValid()) {
|
||||
try {
|
||||
annotationHolder.applyExternalAnnotatorWithContext(data.psiRoot, data.annotator, data.annotationResult);
|
||||
data.annotationHolder.applyExternalAnnotatorWithContext(data.psiRoot, data.annotationResult);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
processError(t, data.annotator, data.psiRoot);
|
||||
@@ -231,11 +231,11 @@ public final class ExternalToolPass extends ProgressableTextEditorHighlightingPa
|
||||
}
|
||||
}
|
||||
|
||||
private static @NotNull List<HighlightInfo> convertToHighlights(@NotNull AnnotationHolderImpl holder) {
|
||||
return ContainerUtil.map(holder, annotation -> HighlightInfo.fromAnnotation(annotation));
|
||||
}
|
||||
|
||||
private void doFinish(@NotNull List<? extends HighlightInfo> highlights) {
|
||||
private void doFinish() {
|
||||
List<HighlightInfo> highlights = myAnnotationData.stream()
|
||||
.flatMap(data ->
|
||||
ContainerUtil.notNullize(data.annotationHolder).stream().map(annotation -> HighlightInfo.fromAnnotation(data.annotator, annotation)))
|
||||
.toList();
|
||||
MarkupModelEx markupModel = (MarkupModelEx)DocumentMarkupModel.forDocument(myDocument, myProject, true);
|
||||
// use the method which doesn't retrieve a HighlightingSession from the indicator, because we likely destroyed the one already
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersInRange(myRestrictRange, highlights, markupModel, getId(), myHighlightingSession);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package com.intellij.testFramework.fixtures;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.*;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.AnnotationSessionImpl;
|
||||
import com.intellij.codeInsight.daemon.impl.AnnotationSessionImpl;
|
||||
import com.intellij.codeInsight.editorActions.smartEnter.SmartEnterProcessor;
|
||||
import com.intellij.codeInsight.editorActions.smartEnter.SmartEnterProcessors;
|
||||
import com.intellij.codeInsight.generation.surroundWith.SurroundWithHandler;
|
||||
@@ -322,10 +322,10 @@ public final class CodeInsightTestUtil {
|
||||
@NotNull Consumer<? super Out> resultChecker) {
|
||||
Out result = annotator.doAnnotate(in);
|
||||
resultChecker.accept(result);
|
||||
return AnnotationSessionImpl.computeWithSession(psiFile, false, annotationHolder -> {
|
||||
ApplicationManager.getApplication().runReadAction(() -> annotationHolder.applyExternalAnnotatorWithContext(psiFile, annotator, result));
|
||||
annotationHolder.assertAllAnnotationsCreated();
|
||||
return List.copyOf(annotationHolder);
|
||||
return AnnotationSessionImpl.computeWithSession(psiFile, false, annotator, annotationHolder -> {
|
||||
ApplicationManager.getApplication().runReadAction(() -> ((AnnotationHolderImpl)annotationHolder).applyExternalAnnotatorWithContext(psiFile, result));
|
||||
((AnnotationHolderImpl)annotationHolder).assertAllAnnotationsCreated();
|
||||
return List.copyOf(((AnnotationHolderImpl)annotationHolder));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -335,12 +335,12 @@ public final class CodeInsightTestUtil {
|
||||
@NotNull
|
||||
public static List<Annotation> testAnnotator(@NotNull Annotator annotator, @NotNull PsiElement @NotNull... elements) {
|
||||
PsiFile psiFile = elements[0].getContainingFile();
|
||||
return AnnotationSessionImpl.computeWithSession(psiFile, false, annotationHolder -> {
|
||||
return AnnotationSessionImpl.computeWithSession(psiFile, false, annotator, annotationHolder -> {
|
||||
for (PsiElement element : elements) {
|
||||
annotationHolder.runAnnotatorWithContext(element, annotator);
|
||||
((AnnotationHolderImpl)annotationHolder).runAnnotatorWithContext(element);
|
||||
}
|
||||
annotationHolder.assertAllAnnotationsCreated();
|
||||
return List.copyOf(annotationHolder);
|
||||
((AnnotationHolderImpl)annotationHolder).assertAllAnnotationsCreated();
|
||||
return List.copyOf(((AnnotationHolderImpl)annotationHolder));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -15,10 +15,11 @@
|
||||
*/
|
||||
package org.intellij.plugins.xpathView.util;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.AnnotationHolderImpl;
|
||||
import com.intellij.codeInsight.daemon.impl.AnnotationSessionImpl;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.LanguageAnnotators;
|
||||
import com.intellij.lang.annotation.Annotation;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.AnnotationSessionImpl;
|
||||
import com.intellij.lang.annotation.Annotator;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -28,6 +29,8 @@ import com.intellij.psi.xml.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public final class MyPsiUtil {
|
||||
private static final Logger LOG = Logger.getInstance(MyPsiUtil.class);
|
||||
|
||||
@@ -155,9 +158,9 @@ public final class MyPsiUtil {
|
||||
file.accept(new PsiRecursiveElementVisitor() {
|
||||
@Override
|
||||
public void visitElement(@NotNull PsiElement element) {
|
||||
AnnotationSessionImpl.computeWithSession(file, false, holder -> {
|
||||
holder.runAnnotatorWithContext(element, annotator);
|
||||
for (Annotation annotation : holder) {
|
||||
AnnotationSessionImpl.computeWithSession(file, false, annotator, annotationHolder -> {
|
||||
((AnnotationHolderImpl)annotationHolder).runAnnotatorWithContext(element);
|
||||
for (Annotation annotation : (List<Annotation>)annotationHolder) {
|
||||
if (annotation.getSeverity() == HighlightSeverity.ERROR) {
|
||||
error[0] = annotation.getMessage();
|
||||
break;
|
||||
|
||||
@@ -2,17 +2,20 @@
|
||||
package com.intellij.util.xml.highlighting;
|
||||
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.AnnotationSessionImpl;
|
||||
import com.intellij.codeInsight.daemon.impl.AnnotationSessionImpl;
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.codeInspection.InspectionProfile;
|
||||
import com.intellij.codeInspection.InspectionProfileEntry;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.ex.InspectionToolWrapper;
|
||||
import com.intellij.lang.annotation.AnnotationHolder;
|
||||
import com.intellij.lang.annotation.Annotator;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.profile.ProfileChangeAdapter;
|
||||
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.impl.source.xml.XmlFileImpl;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.psi.xml.XmlFile;
|
||||
@@ -196,7 +199,7 @@ public class DomElementAnnotationsManagerImpl extends DomElementAnnotationsManag
|
||||
return problemHolder.getAllProblems(inspection);
|
||||
}
|
||||
|
||||
return AnnotationSessionImpl.computeWithSession(domFileElement.getFile(), false, annotationHolder -> {
|
||||
return AnnotationSessionImpl.computeWithSession(domFileElement.getFile(), false, MyDomElementFakeAnnotator.INSTANCE, annotationHolder -> {
|
||||
DomElementAnnotationHolder holder = new DomElementAnnotationHolderImpl(onTheFly, domFileElement, annotationHolder);
|
||||
inspection.checkFileElement(domFileElement, holder);
|
||||
//noinspection unchecked
|
||||
@@ -204,6 +207,14 @@ public class DomElementAnnotationsManagerImpl extends DomElementAnnotationsManag
|
||||
});
|
||||
}
|
||||
|
||||
private static class MyDomElementFakeAnnotator implements Annotator {
|
||||
private static final MyDomElementFakeAnnotator INSTANCE = new MyDomElementFakeAnnotator();
|
||||
@Override
|
||||
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public List<DomElementsInspection<?>> getSuitableDomInspections(final DomFileElement<?> fileElement, boolean enabledOnly) {
|
||||
Class<?> rootType = fileElement.getRootElementClass();
|
||||
final InspectionProfile profile = getInspectionProfile(fileElement);
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
package com.intellij.util.xml;
|
||||
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.codeInsight.daemon.impl.AnnotationSessionImpl;
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.codeInspection.InspectionProfile;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.AnnotationSessionImpl;
|
||||
import com.intellij.lang.annotation.Annotator;
|
||||
import com.intellij.mock.MockInspectionProfile;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiFile;
|
||||
@@ -21,6 +22,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
public class DomHighlightingLiteTest extends DomTestCase {
|
||||
@@ -118,7 +120,8 @@ public class DomHighlightingLiteTest extends DomTestCase {
|
||||
}
|
||||
|
||||
private DomElementAnnotationHolderImpl createHolder() {
|
||||
return AnnotationSessionImpl.computeWithSession(myElement.getFile(), false, holder -> new DomElementAnnotationHolderImpl(true, myElement, holder));
|
||||
Annotator annotator = (element, holder) -> {};
|
||||
return AnnotationSessionImpl.computeWithSession(myElement.getFile(), false, annotator, holder -> new DomElementAnnotationHolderImpl(true, myElement, holder));
|
||||
}
|
||||
|
||||
private static DomElementsProblemsHolderImpl assertNotEmptyHolder(final DomElementsProblemsHolder holder1) {
|
||||
@@ -168,7 +171,7 @@ public class DomHighlightingLiteTest extends DomTestCase {
|
||||
}
|
||||
};
|
||||
final StringBuilder s = new StringBuilder();
|
||||
AnnotationSessionImpl.computeWithSession(myElement.getFile(), false, toFill -> {
|
||||
AnnotationSessionImpl.computeWithSession(myElement.getFile(), false, annotator, annotationHolder -> {
|
||||
final MyDomElementsInspection inspection = new MyDomElementsInspection() {
|
||||
|
||||
@Override
|
||||
@@ -176,15 +179,15 @@ public class DomHighlightingLiteTest extends DomTestCase {
|
||||
s.append("visited");
|
||||
}
|
||||
};
|
||||
annotator.runInspection(inspection, myElement, toFill);
|
||||
annotator.runInspection(inspection, myElement, annotationHolder);
|
||||
assertEquals("visited", s.toString());
|
||||
final DomElementsProblemsHolderImpl holder = assertNotEmptyHolder(myAnnotationsManager.getProblemHolder(myElement));
|
||||
assertEmpty(toFill);
|
||||
assertEmpty((Collection<?>)annotationHolder);
|
||||
|
||||
annotator.runInspection(inspection, myElement, toFill);
|
||||
annotator.runInspection(inspection, myElement, annotationHolder);
|
||||
assertEquals("visited", s.toString());
|
||||
assertSame(holder, assertNotEmptyHolder(myAnnotationsManager.getProblemHolder(myElement)));
|
||||
assertEmpty(toFill);
|
||||
assertEmpty((Collection<?>)annotationHolder);
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user