From 121f917f61f1c3c6dfbee353b68a2516e982a010 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 2 Sep 2024 14:10:21 +0200 Subject: [PATCH] IJPL-161270 Semantic highlighting is still visible after disabling GitOrigin-RevId: 0af6e1899921ffaf613240ce0865d13d607d86c5 --- ...nHighlightVisitorRespondToChangesTest.java | 19 ++++++++++ .../daemon/impl/GeneralHighlightingPass.java | 6 +++ .../daemon/impl/HighlightInfoUpdaterImpl.java | 37 ++++++++----------- .../daemon/impl/DaemonCodeAnalyzerImpl.java | 4 +- .../daemon/impl/LocalInspectionsPass.java | 21 ++++++++++- 5 files changed, 61 insertions(+), 26 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/DaemonHighlightVisitorRespondToChangesTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/DaemonHighlightVisitorRespondToChangesTest.java index 4b11843b1d5e..69c39c761935 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/DaemonHighlightVisitorRespondToChangesTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/DaemonHighlightVisitorRespondToChangesTest.java @@ -1,6 +1,7 @@ // 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.codeHighlighting.RainbowHighlighter; import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; import com.intellij.codeInsight.daemon.impl.analysis.HighlightInfoHolder; @@ -580,4 +581,22 @@ public class DaemonHighlightVisitorRespondToChangesTest extends DaemonAnalyzerTe assertOneElement(ContainerUtil.filter(doHighlighting(HighlightSeverity.INFORMATION), h -> h.type.equals(HighlightInfoType.TODO))); } } + + public void testHighlightingVisitorDisabledAtSomePointEgSemanticHighlightingBeingDisabledMustRemoveAllHighlightersOfOutdatedVisitors() { + @Language("JAVA") + String text = """ + class X { + void foo(int wwwwwwwwwwwwwwwww) { + } + } + """; + configureByText(JavaFileType.INSTANCE, text); + assertEmpty(ContainerUtil.filter(doHighlighting(), info -> info.type == RainbowHighlighter.RAINBOW_ELEMENT)); + CodeInsightTestFixtureImpl.runWithRainbowEnabled(true, () -> { + myDaemonCodeAnalyzer.restart(); + assertNotEmpty(ContainerUtil.filter(doHighlighting(), info -> info.type == RainbowHighlighter.RAINBOW_ELEMENT)); + }); + myDaemonCodeAnalyzer.restart(); + assertEmpty(ContainerUtil.filter(doHighlighting(), info -> info.type == RainbowHighlighter.RAINBOW_ELEMENT)); + } } diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java index 318303378191..87934903886d 100644 --- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java @@ -40,6 +40,7 @@ import org.jetbrains.annotations.TestOnly; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.BiPredicate; import java.util.function.Consumer; import java.util.function.Predicate; @@ -180,6 +181,11 @@ sealed class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP } } } + if (myHighlightInfoUpdater instanceof HighlightInfoUpdaterImpl impl) { + List> liveVisitorClasses = ContainerUtil.map(filteredVisitors, v -> v.getClass()); + BiPredicate keepToolIdPredicate = (toolId, __) -> !HighlightInfoUpdaterImpl.isHighlightVisitorToolId(toolId) || liveVisitorClasses.contains(toolId); + impl.removeHighlightsForObsoleteTools(getHighlightingSession(), List.of(), keepToolIdPredicate); + } boolean success = collectHighlights(allInsideElements, allInsideRanges, allOutsideElements, allOutsideRanges, filteredVisitors, forceHighlightParents, (toolId, psiElement, newInfos) -> { myHighlightInfoUpdater.psiElementVisited(toolId, psiElement, newInfos, getDocument(), getFile(), myProject, getHighlightingSession(), invalidPsiRecycler); diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoUpdaterImpl.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoUpdaterImpl.java index 548e88a2ac86..78fc2161cbf0 100644 --- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoUpdaterImpl.java +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoUpdaterImpl.java @@ -56,6 +56,7 @@ import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; +import java.util.function.BiPredicate; import java.util.function.Consumer; import java.util.function.Predicate; @@ -124,7 +125,8 @@ final class HighlightInfoUpdaterImpl extends HighlightInfoUpdater implements Dis return getData(psiFile, hostDocument); } - private static @NotNull Map getData(@NotNull PsiFile psiFile, @NotNull Document hostDocument) { + @NotNull + private static Map getData(@NotNull PsiFile psiFile, @NotNull Document hostDocument) { Map> map = getOrCreateHostMap(hostDocument); Map result = map.get(psiFile); if (result == null) { @@ -133,7 +135,8 @@ final class HighlightInfoUpdaterImpl extends HighlightInfoUpdater implements Dis return result; } - private static @NotNull Map> getOrCreateHostMap(@NotNull Document hostDocument) { + @NotNull + private static Map> getOrCreateHostMap(@NotNull Document hostDocument) { Map> map = hostDocument.getUserData(VISITED_PSI_ELEMENTS); if (map == null) { map = ((UserDataHolderEx)hostDocument).putUserDataIfAbsent(VISITED_PSI_ELEMENTS, CollectionFactory.createConcurrentSoftMap((__, oldMap) -> { @@ -478,28 +481,20 @@ final class HighlightInfoUpdaterImpl extends HighlightInfoUpdater implements Dis } // remove all highlight infos from `data` generated by tools absent in 'actualToolsRun' - synchronized void removeHighlightsForObsoleteTools(@NotNull PsiFile containingFile, - @NotNull Document hostDocument, + synchronized void removeHighlightsForObsoleteTools(@NotNull HighlightingSession highlightingSession, @NotNull List injectedFragments, - @NotNull Set> actualToolsRun, - @NotNull HighlightingSession highlightingSession, - @NotNull Set inactiveSmartOnlyToolIds) { - - for (PsiFile psiFile: ContainerUtil.append(injectedFragments, containingFile)) { - getData(psiFile, hostDocument).entrySet().removeIf(entry -> { + @NotNull BiPredicate keepToolIdPredicate) { + for (PsiFile psiFile: ContainerUtil.append(injectedFragments, highlightingSession.getPsiFile())) { + Map data = getData(psiFile, highlightingSession.getDocument()); + data.entrySet().removeIf(entry -> { Object toolId = entry.getKey(); + if (UNKNOWN_ID.equals(toolId)) { + return false; + } + if (keepToolIdPredicate.test(toolId, psiFile)) { + return false; + } ToolHighlights toolHighlights = entry.getValue(); - if (UNKNOWN_ID.equals(toolId) || !isInspectionToolId(toolId)) { - return false; - } - - if (actualToolsRun.contains(Pair.create(toolId, psiFile))) { - return false; - } - if (inactiveSmartOnlyToolIds.contains(toolId)) { - // keep highlights from smart-only inspections in dumb mode - return false; - } for (List highlights : toolHighlights.elementHighlights.values()) { for (HighlightInfo info : highlights) { RangeHighlighterEx highlighter = info.highlighter; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java index b500c78ce5f1..56d65585b615 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java @@ -721,9 +721,7 @@ public final class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzerEx @Override public void settingsChanged() { - if (mySettings.isCodeHighlightingChanged(myLastSettings)) { - restart(); - } + restart(); myLastSettings = ((DaemonCodeAnalyzerSettingsImpl)mySettings).clone(); } 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 626b757ca1ad..44a2d638d26d 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 @@ -50,6 +50,7 @@ import org.jetbrains.annotations.TestOnly; import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.BiPredicate; import java.util.function.Consumer; import java.util.function.Function; @@ -165,8 +166,24 @@ final class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass } if (myHighlightInfoUpdater instanceof HighlightInfoUpdaterImpl impl) { - Set> pairs = ContainerUtil.map2Set(result.resultContexts, context -> Pair.create(context.tool().getShortName(), context.psiFile())); - impl.removeHighlightsForObsoleteTools(getFile(), getDocument(), result.injectedFragments, pairs, getHighlightingSession(), dumbToolWrapperCondition.getInactiveToolWrapperIds()); + Set> actualToolsRun = ContainerUtil.map2Set(result.resultContexts, context -> Pair.create(context.tool().getShortName(), context.psiFile())); + + Set inactiveSmartOnlyToolIds = dumbToolWrapperCondition.getInactiveToolWrapperIds(); + BiPredicate keepToolIdPredicate = (toolId, psiFile) -> { + if (!HighlightInfoUpdaterImpl.isInspectionToolId(toolId)) { + return true; + } + + if (actualToolsRun.contains(Pair.create(toolId, psiFile))) { + return true; + } + if (inactiveSmartOnlyToolIds.contains(toolId)) { + // keep highlights from smart-only inspections in dumb mode + return true; + } + return false; + }; + impl.removeHighlightsForObsoleteTools(getHighlightingSession(), result.injectedFragments, keepToolIdPredicate); impl.removeWarningsInsideErrors(result.injectedFragments, getDocument(), getHighlightingSession()); // must be the last } }