mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-CR-64585: IDEA-245071: implement DaemonCodeAnalyzerImpl#serializeCodeInsightPasses()
GitOrigin-RevId: 077ab6dc38924188f1017543763611915160f7ca
This commit is contained in:
committed by
intellij-monorepo-bot
parent
9f338cae80
commit
fe2da78da7
+91
-36
@@ -2122,7 +2122,7 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase {
|
||||
}
|
||||
|
||||
public void testAddRemoveHighlighterRaceInIncorrectAnnotatorsWhichUseFileRecursiveVisit() {
|
||||
useAnnotatorsIn(JavaFileType.INSTANCE.getLanguage(), new MyRecordingAnnotator[]{new MyIncorrectlyRecursiveAnnotator()}, () -> {
|
||||
useAnnotatorsIn(JavaFileType.INSTANCE.getLanguage(), new MyIncorrectlyRecursiveAnnotator(), () -> {
|
||||
@Language("JAVA")
|
||||
String text1 = "class X {\n" +
|
||||
" int foo(Object param) {\n" +
|
||||
@@ -2148,28 +2148,59 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase {
|
||||
public static void useAnnotatorsIn(@NotNull com.intellij.lang.Language language,
|
||||
MyRecordingAnnotator @NotNull [] annotators,
|
||||
@NotNull Runnable runnable) {
|
||||
useAnnotatorsIn(Collections.singletonMap(language, annotators), runnable);
|
||||
}
|
||||
|
||||
public static void useAnnotatorsIn(@NotNull com.intellij.lang.Language language,
|
||||
@NotNull MyRecordingAnnotator annotator,
|
||||
@NotNull Runnable runnable) {
|
||||
useAnnotatorsIn(Collections.singletonMap(language, new MyRecordingAnnotator[]{annotator}), runnable);
|
||||
}
|
||||
|
||||
public static void useAnnotatorsIn(@NotNull Map<com.intellij.lang.Language, MyRecordingAnnotator @NotNull []> annotatorsByLanguage,
|
||||
@NotNull Runnable runnable) {
|
||||
MyRecordingAnnotator.clearAll();
|
||||
for (Annotator annotator : annotators) {
|
||||
LanguageAnnotators.INSTANCE.addExplicitExtension(language, annotator);
|
||||
}
|
||||
try {
|
||||
List<Annotator> list = LanguageAnnotators.INSTANCE.allForLanguage(language);
|
||||
assertTrue(list.toString(), list.containsAll(Arrays.asList(annotators)));
|
||||
runnable.run();
|
||||
for (MyRecordingAnnotator annotator : annotators) {
|
||||
assertTrue(annotator +" must have done something but didn't", annotator.didIDoIt());
|
||||
}
|
||||
}
|
||||
finally {
|
||||
for (int i = annotators.length - 1; i >= 0; i--) {
|
||||
Annotator annotator = annotators[i];
|
||||
LanguageAnnotators.INSTANCE.removeExplicitExtension(language, annotator);
|
||||
for (Map.Entry<com.intellij.lang.Language, MyRecordingAnnotator[]> entry : annotatorsByLanguage.entrySet()) {
|
||||
com.intellij.lang.Language language = entry.getKey();
|
||||
MyRecordingAnnotator[] annotators = entry.getValue();
|
||||
for (Annotator annotator : annotators) {
|
||||
LanguageAnnotators.INSTANCE.addExplicitExtension(language, annotator);
|
||||
}
|
||||
}
|
||||
|
||||
List<Annotator> list = LanguageAnnotators.INSTANCE.allForLanguage(language);
|
||||
for (Annotator annotator : annotators) {
|
||||
assertFalse(list.toString(), list.contains(annotator));
|
||||
try {
|
||||
for (Map.Entry<com.intellij.lang.Language, MyRecordingAnnotator[]> entry : annotatorsByLanguage.entrySet()) {
|
||||
com.intellij.lang.Language language = entry.getKey();
|
||||
MyRecordingAnnotator[] annotators = entry.getValue();
|
||||
List<Annotator> list = LanguageAnnotators.INSTANCE.allForLanguage(language);
|
||||
assertTrue(list.toString(), list.containsAll(Arrays.asList(annotators)));
|
||||
}
|
||||
runnable.run();
|
||||
for (Map.Entry<com.intellij.lang.Language, MyRecordingAnnotator[]> entry : annotatorsByLanguage.entrySet()) {
|
||||
MyRecordingAnnotator[] annotators = entry.getValue();
|
||||
for (MyRecordingAnnotator annotator : annotators) {
|
||||
assertTrue(annotator + " must have done something but didn't", annotator.didIDoIt());
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
for (Map.Entry<com.intellij.lang.Language, MyRecordingAnnotator[]> entry : annotatorsByLanguage.entrySet()) {
|
||||
com.intellij.lang.Language language = entry.getKey();
|
||||
MyRecordingAnnotator[] annotators = entry.getValue();
|
||||
for (int i = annotators.length - 1; i >= 0; i--) {
|
||||
Annotator annotator = annotators[i];
|
||||
LanguageAnnotators.INSTANCE.removeExplicitExtension(language, annotator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<com.intellij.lang.Language, MyRecordingAnnotator[]> entry : annotatorsByLanguage.entrySet()) {
|
||||
com.intellij.lang.Language language = entry.getKey();
|
||||
MyRecordingAnnotator[] annotators = entry.getValue();
|
||||
List<Annotator> list = LanguageAnnotators.INSTANCE.allForLanguage(language);
|
||||
for (Annotator annotator : annotators) {
|
||||
assertFalse(list.toString(), list.contains(annotator));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2509,38 +2540,49 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase {
|
||||
|
||||
public void testAddAnnotationViaBuilderEntailsCreatingCorrespondingRangeHighlighterImmediately() {
|
||||
if (!ensureEnoughParallelism()) return;
|
||||
useAnnotatorsIn(JavaFileType.INSTANCE.getLanguage(), new MyRecordingAnnotator[]{new MyNewBuilderAnnotator(), }, this::checkSwearingAnnotationIsVisibleImmediately);
|
||||
useAnnotatorsIn(JavaFileType.INSTANCE.getLanguage(), new MyNewBuilderAnnotator(), this::checkSwearingAnnotationIsVisibleImmediately);
|
||||
}
|
||||
|
||||
private static final AtomicBoolean annotated = new AtomicBoolean();
|
||||
private static final AtomicBoolean injectedAnnotated = new AtomicBoolean();
|
||||
private static final AtomicBoolean inspected = new AtomicBoolean();
|
||||
|
||||
public static class MySlowAnnotator extends MyRecordingAnnotator {
|
||||
|
||||
@Override
|
||||
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
|
||||
if (element instanceof PsiFile) {
|
||||
assertFalse("For this moment file has not to process injected fragments", injectedAnnotated.get());
|
||||
assertFalse("For this moment file has not to run inspections", inspected.get());
|
||||
annotated.set(true);
|
||||
iDidIt();
|
||||
}
|
||||
assertFalse(inspected.get());
|
||||
}
|
||||
}
|
||||
public void test_RunInspectionsAfterCompletionOfGeneralHighlightPass_SecretSettingDoesWork() {
|
||||
|
||||
public static class MyInjectedSlowAnnotator extends MyRecordingAnnotator {
|
||||
|
||||
@Override
|
||||
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
|
||||
assertTrue("File already has to be annotated", annotated.get());
|
||||
injectedAnnotated.set(true);
|
||||
iDidIt();
|
||||
}
|
||||
}
|
||||
|
||||
public void test_SerializeCodeInsightPasses_SecretSettingDoesWork() {
|
||||
if (!ensureEnoughParallelism()) return;
|
||||
|
||||
TextEditorHighlightingPassRegistrarImpl registrar =
|
||||
(TextEditorHighlightingPassRegistrarImpl)TextEditorHighlightingPassRegistrar.getInstance(myProject);
|
||||
assertFalse("Somebody (rogue plugin?) has left the dangerous setting on", registrar.isRunInspectionsAfterCompletionOfGeneralHighlightPass());
|
||||
assertFalse("Somebody (rogue plugin?) has left the dangerous setting on", registrar.isSerializeCodeInsightPasses());
|
||||
|
||||
registerInspection(new LocalInspectionTool() {
|
||||
@Override
|
||||
public @NotNull String getID() {
|
||||
return getTestName(false)+"MySlowInspectionTool";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProblemDescriptor @Nullable [] checkFile(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) {
|
||||
inspected.set(true);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
|
||||
boolean isOnTheFly,
|
||||
@@ -2548,21 +2590,34 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase {
|
||||
return new PsiElementVisitor() {
|
||||
@Override
|
||||
public void visitElement(@NotNull PsiElement element) {
|
||||
assertTrue(annotated.get());
|
||||
assertTrue("File has to be already annotated", annotated.get());
|
||||
inspected.set(true);
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
try {
|
||||
myDaemonCodeAnalyzer.runLocalInspectionPassAfterCompletionOfGeneralHighlightPass(true);
|
||||
myDaemonCodeAnalyzer.serializeCodeInsightPasses(true);
|
||||
|
||||
Map<com.intellij.lang.Language, MyRecordingAnnotator @NotNull []> annotatorsByLanguage = new HashMap<>();
|
||||
annotatorsByLanguage.put(JavaLanguage.INSTANCE, new MyRecordingAnnotator[]{new MySlowAnnotator()});
|
||||
annotatorsByLanguage.put(XMLLanguage.INSTANCE, new MyRecordingAnnotator[]{new MyInjectedSlowAnnotator()});
|
||||
|
||||
useAnnotatorsIn(annotatorsByLanguage, () -> {
|
||||
configureByText(JavaFileType.INSTANCE,
|
||||
"class X{\n" +
|
||||
"// language=XML\n" +
|
||||
"String ql = \"<value>1</value>\";" +
|
||||
"\n}");
|
||||
|
||||
useAnnotatorsIn(JavaFileType.INSTANCE.getLanguage(), new MyRecordingAnnotator[]{new MySlowAnnotator(), }, () -> {
|
||||
configureByText(JavaFileType.INSTANCE, "class X{}");
|
||||
doHighlighting();
|
||||
assertTrue("File already has to be java annotated", annotated.get());
|
||||
assertTrue("File already has to annotate xml injection", injectedAnnotated.get());
|
||||
assertTrue("File already has to run inspections", inspected.get());
|
||||
});
|
||||
}
|
||||
finally {
|
||||
myDaemonCodeAnalyzer.runLocalInspectionPassAfterCompletionOfGeneralHighlightPass(false);
|
||||
myDaemonCodeAnalyzer.serializeCodeInsightPasses(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2575,7 +2630,7 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase {
|
||||
public void testTypingMustRescheduleDaemonBackByReparseDelayMillis() {
|
||||
EmptyAnnotator emptyAnnotator = new EmptyAnnotator();
|
||||
executeWithReparseDelay(2000, () ->
|
||||
useAnnotatorsIn(JavaLanguage.INSTANCE, new MyRecordingAnnotator[]{emptyAnnotator}, () -> {
|
||||
useAnnotatorsIn(JavaLanguage.INSTANCE, emptyAnnotator, () -> {
|
||||
@Language("JAVA")
|
||||
String text = "class X {\n}";
|
||||
configureByText(JavaFileType.INSTANCE, text);
|
||||
@@ -2606,7 +2661,7 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase {
|
||||
}
|
||||
|
||||
public void testDaemonDoesReportTheFirstProducedAnnotation() {
|
||||
useAnnotatorsIn(JavaFileType.INSTANCE.getLanguage(), new MyRecordingAnnotator[]{new MyInfoAnnotator()}, () -> checkFirstAnnotation());
|
||||
useAnnotatorsIn(JavaFileType.INSTANCE.getLanguage(), new MyInfoAnnotator(), () -> checkFirstAnnotation());
|
||||
}
|
||||
|
||||
private void checkFirstAnnotation() {
|
||||
|
||||
+5
-5
@@ -38,7 +38,7 @@ public final class TextEditorHighlightingPassRegistrarImpl extends TextEditorHig
|
||||
private final AtomicInteger nextAvailableId = new AtomicInteger();
|
||||
private boolean checkedForCycles;
|
||||
private final Project myProject;
|
||||
private boolean runInspectionsAfterCompletionOfGeneralHighlightPass;
|
||||
private boolean serializeCodeInsightPasses;
|
||||
|
||||
public TextEditorHighlightingPassRegistrarImpl(@NotNull Project project) {
|
||||
myProject = project;
|
||||
@@ -76,14 +76,14 @@ public final class TextEditorHighlightingPassRegistrarImpl extends TextEditorHig
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
void runInspectionsAfterCompletionOfGeneralHighlightPass(boolean flag) {
|
||||
runInspectionsAfterCompletionOfGeneralHighlightPass = flag;
|
||||
void serializeCodeInsightPasses(boolean flag) {
|
||||
serializeCodeInsightPasses = flag;
|
||||
reRegisterFactories();
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
boolean isRunInspectionsAfterCompletionOfGeneralHighlightPass() {
|
||||
return runInspectionsAfterCompletionOfGeneralHighlightPass;
|
||||
boolean isSerializeCodeInsightPasses() {
|
||||
return serializeCodeInsightPasses;
|
||||
}
|
||||
|
||||
private static final class PassConfig {
|
||||
|
||||
+20
-2
@@ -982,20 +982,38 @@ public final class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzerEx implement
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link DaemonCodeAnalyzerImpl#serializeCodeInsightPasses(boolean)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
@ApiStatus.Internal
|
||||
public void runLocalInspectionPassAfterCompletionOfGeneralHighlightPass(boolean flag) {
|
||||
serializeCodeInsightPasses(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* This API is made {@code Internal} intentionally as it could lead to unpredictable highlighting performance behaviour.
|
||||
*
|
||||
* @param flag if {@code true}: enables code insight passes serialization:
|
||||
* Injected fragments {@link InjectedGeneralHighlightingPass} highlighting and Inspections run after
|
||||
* completion of Syntax analysis {@link GeneralHighlightingPass}.
|
||||
* if {@code false} (default behaviour) code insight passes are running in parallel
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public void serializeCodeInsightPasses(boolean flag) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
setUpdateByTimerEnabled(false);
|
||||
try {
|
||||
cancelUpdateProgress(false, "runLocalInspectionPassAfterCompletionOfGeneralHighlightPass");
|
||||
cancelUpdateProgress(false, "serializeCodeInsightPasses");
|
||||
myPassExecutorService.cancelAll(true);
|
||||
|
||||
TextEditorHighlightingPassRegistrarImpl registrar =
|
||||
(TextEditorHighlightingPassRegistrarImpl)TextEditorHighlightingPassRegistrar.getInstance(myProject);
|
||||
registrar.runInspectionsAfterCompletionOfGeneralHighlightPass(flag);
|
||||
registrar.serializeCodeInsightPasses(flag);
|
||||
}
|
||||
finally {
|
||||
setUpdateByTimerEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-1
@@ -7,13 +7,18 @@ import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.ProperTextRange;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class InjectedGeneralHighlightingPassFactory implements MainHighlightingPassFactory, TextEditorHighlightingPassFactoryRegistrar {
|
||||
@Override
|
||||
public void registerHighlightingPassFactory(@NotNull TextEditorHighlightingPassRegistrar registrar, @NotNull Project project) {
|
||||
registrar.registerTextEditorHighlightingPass(this, null, new int[]{Pass.UPDATE_ALL}, false, -1);
|
||||
boolean serialized = Registry.is("editor.injected.highlighting.serialization.allowed") &&
|
||||
((TextEditorHighlightingPassRegistrarImpl)registrar).isSerializeCodeInsightPasses();
|
||||
int[] ghl = {Pass.UPDATE_ALL};
|
||||
registrar.registerTextEditorHighlightingPass(this, serialized ? ghl : null,
|
||||
serialized ? null : ghl, false, -1);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+5
-5
@@ -18,11 +18,11 @@ public final class LocalInspectionsPassFactory implements MainHighlightingPassFa
|
||||
|
||||
@Override
|
||||
public void registerHighlightingPassFactory(@NotNull TextEditorHighlightingPassRegistrar registrar, @NotNull Project project) {
|
||||
int[] GHP = {Pass.UPDATE_ALL};
|
||||
boolean runInspectionsAfterCompletionOfGeneralHighlightPass =
|
||||
((TextEditorHighlightingPassRegistrarImpl)registrar).isRunInspectionsAfterCompletionOfGeneralHighlightPass();
|
||||
registrar.registerTextEditorHighlightingPass(this, runInspectionsAfterCompletionOfGeneralHighlightPass ? GHP : null,
|
||||
runInspectionsAfterCompletionOfGeneralHighlightPass ? null : GHP, true, Pass.LOCAL_INSPECTIONS);
|
||||
int[] ghp = {Pass.UPDATE_ALL};
|
||||
boolean serializeCodeInsightPasses =
|
||||
((TextEditorHighlightingPassRegistrarImpl)registrar).isSerializeCodeInsightPasses();
|
||||
registrar.registerTextEditorHighlightingPass(this, serializeCodeInsightPasses ? ghp : null,
|
||||
serializeCodeInsightPasses ? null : ghp, true, Pass.LOCAL_INSPECTIONS);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -937,6 +937,9 @@ ide.progress.indeterminate.by.default=true
|
||||
editor.injected.highlighting.enabled=true
|
||||
editor.injected.highlighting.enabled.description=Disables injected fragments highlighting (requires project reopening)
|
||||
|
||||
editor.injected.highlighting.serialization.allowed=true
|
||||
editor.injected.highlighting.serialization.allowed.description=Allow injected fragments highlighting after syntax highlighting (requires project reopening)
|
||||
|
||||
# CPP-8395 Registry setting run.processes.with.pty not saved
|
||||
# Upper-case FALSE makes an option explicitly turned off distinct from the default value
|
||||
run.processes.with.pty=FALSE
|
||||
|
||||
Reference in New Issue
Block a user