From db35ecd64b390ed8d40a90cd0538f563682b09b0 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Tue, 9 Jun 2020 01:04:05 +0300 Subject: [PATCH] IDEA-238791/IDEA-241748: use RangeHighlighterEx instead of HighlightInfo to create HighlightingProblem GitOrigin-RevId: 7df56318c4e772c9215fce4a18bb728289185f6f --- .../toolWindow/HighlightingFileRoot.kt | 10 ++++++--- .../toolWindow/HighlightingPanel.kt | 6 ++--- .../toolWindow/HighlightingProblem.kt | 22 +++++++++++-------- .../toolWindow/HighlightingWatcher.kt | 20 ++++++++++++----- .../problemsView/toolWindow/ProblemsView.java | 6 ++--- .../analysis/problemsView/toolWindow/Root.kt | 6 +++++ .../daemon/impl/GotoNextErrorHandler.java | 6 +++-- 7 files changed, 51 insertions(+), 25 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/HighlightingFileRoot.kt b/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/HighlightingFileRoot.kt index c97556da3dcd..dad2189c651f 100644 --- a/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/HighlightingFileRoot.kt +++ b/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/HighlightingFileRoot.kt @@ -1,8 +1,8 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.analysis.problemsView.toolWindow -import com.intellij.codeInsight.daemon.impl.HighlightInfo import com.intellij.lang.annotation.HighlightSeverity.INFORMATION +import com.intellij.openapi.editor.ex.RangeHighlighterEx import com.intellij.openapi.util.Disposer import com.intellij.openapi.vfs.VirtualFile @@ -23,8 +23,8 @@ internal class HighlightingFileRoot(panel: ProblemsViewPanel, val file: VirtualF return synchronized(problems) { problems.getProblemNodes() } } - fun findProblemNode(info: HighlightInfo?): ProblemNode? { - val problem = watcher.getProblem(info) ?: return null + fun findProblemNode(highlighter: RangeHighlighterEx): ProblemNode? { + val problem = watcher.findProblem(highlighter) ?: return null return synchronized(problems) { problems.findProblemNode(problem) } } @@ -42,6 +42,10 @@ internal class HighlightingFileRoot(panel: ProblemsViewPanel, val file: VirtualF structureChanged() } + override fun updateProblem(file: VirtualFile, problem: Problem) { + synchronized(problems) { problems.findProblemNode(problem) }?.let { structureChanged() } + } + override fun updateProblems(file: VirtualFile, collection: Collection) { synchronized(problems) { problems.update(collection) } structureChanged() diff --git a/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/HighlightingPanel.kt b/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/HighlightingPanel.kt index d71d6a7d3f9f..c92b94fc158e 100644 --- a/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/HighlightingPanel.kt +++ b/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/HighlightingPanel.kt @@ -1,11 +1,11 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.analysis.problemsView.toolWindow -import com.intellij.codeInsight.daemon.impl.HighlightInfo import com.intellij.codeInsight.daemon.impl.SeverityRegistrar.getSeverityRegistrar import com.intellij.ide.TreeExpander import com.intellij.lang.annotation.HighlightSeverity import com.intellij.openapi.actionSystem.ToggleOptionAction.Option +import com.intellij.openapi.editor.ex.RangeHighlighterEx import com.intellij.openapi.fileEditor.* import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile @@ -30,9 +30,9 @@ internal class HighlightingPanel(project: Project, state: ProblemsViewState) if (selected) updateCurrentFile() } - fun selectHighlightInfo(info: HighlightInfo) { + fun selectHighlighter(highlighter: RangeHighlighterEx) { val root = treeModel.root as? HighlightingFileRoot - root?.findProblemNode(info)?.let { select(it) } + root?.findProblemNode(highlighter)?.let { select(it) } } override fun fileOpened(manager: FileEditorManager, file: VirtualFile) = updateCurrentFile() diff --git a/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/HighlightingProblem.kt b/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/HighlightingProblem.kt index 07d2c721afeb..194989a9116e 100644 --- a/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/HighlightingProblem.kt +++ b/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/HighlightingProblem.kt @@ -12,40 +12,44 @@ import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.RangeMarker +import com.intellij.openapi.editor.ex.RangeHighlighterEx import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiFile import javax.swing.Icon -internal class HighlightingProblem(val info: HighlightInfo) : Problem { +internal class HighlightingProblem(private val highlighter: RangeHighlighterEx) : Problem { private fun getIcon(level: HighlightDisplayLevel) = if (severity >= level.severity.myVal) level.icon else null + private val info: HighlightInfo? + get() = HighlightInfo.fromRangeHighlighter(highlighter) + override val icon: Icon - get() = HighlightDisplayLevel.find(info.severity)?.icon + get() = HighlightDisplayLevel.find(info?.severity)?.icon ?: getIcon(HighlightDisplayLevel.ERROR) ?: getIcon(HighlightDisplayLevel.WARNING) ?: HighlightDisplayLevel.WEAK_WARNING.icon override val description: String - get() = info.description + get() = info?.description ?: "Invalid" override val severity: Int - get() = info.severity.myVal + get() = info?.severity?.myVal ?: -1 override val offset: Int - get() = info.actualStartOffset + get() = info?.actualStartOffset ?: -1 - override fun hashCode() = info.hashCode() + override fun hashCode() = highlighter.hashCode() - override fun equals(other: Any?) = other is HighlightingProblem && other.info == info + override fun equals(other: Any?) = other is HighlightingProblem && other.highlighter == highlighter override fun hasQuickFixActions(): Boolean { - val markers = info.quickFixActionMarkers ?: return false + val markers = info?.quickFixActionMarkers ?: return false return markers.any { it.second.isValid } } override fun getQuickFixActions(): Collection { - val markers = info.quickFixActionMarkers ?: return emptyList() + val markers = info?.quickFixActionMarkers ?: return emptyList() return markers.filter { it.second.isValid }.map { QuickFixAction(it.first.action, it.second) } } } diff --git a/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/HighlightingWatcher.kt b/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/HighlightingWatcher.kt index 88a25cd8342e..3179a7139b0a 100644 --- a/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/HighlightingWatcher.kt +++ b/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/HighlightingWatcher.kt @@ -17,6 +17,7 @@ internal class HighlightingWatcher( private val level: Int = ERROR.myVal) : MarkupModelListener, Disposable { + private val problems = mutableMapOf() private var reference: WeakReference? = null init { @@ -33,6 +34,10 @@ internal class HighlightingWatcher( getProblem(highlighter)?.let { root.removeProblem(file, it) } } + override fun attributesChanged(highlighter: RangeHighlighterEx, renderersChanged: Boolean, fontStyleOrColorChanged: Boolean) { + findProblem(highlighter)?.let { root.updateProblem(file, it) } + } + fun update() { val model = reference?.get() ?: getMarkupModel() ?: return val problems = mutableSetOf() @@ -43,13 +48,18 @@ internal class HighlightingWatcher( root.updateProblems(file, problems) } - fun getProblem(info: HighlightInfo?): Problem? { - return if (null == info?.description || info.severity.myVal < level) null else HighlightingProblem(info) + fun findProblem(highlighter: RangeHighlighterEx) = synchronized(problems) { problems[highlighter] } + + private fun getProblem(highlighter: RangeHighlighterEx) = when { + !isValid(highlighter) -> null + else -> synchronized(problems) { + problems.computeIfAbsent(highlighter) { HighlightingProblem(highlighter) } + } } - private fun getProblem(highlighter: RangeHighlighterEx): Problem? { - val info = highlighter.errorStripeTooltip as? HighlightInfo ?: return null - return getProblem(info) + private fun isValid(highlighter: RangeHighlighterEx): Boolean { + val info = highlighter.errorStripeTooltip as? HighlightInfo ?: return false + return info.description != null && info.severity.myVal >= level } private fun getMarkupModel(): MarkupModelEx? { diff --git a/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/ProblemsView.java b/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/ProblemsView.java index d086c2edfb1a..9a33a43eb598 100644 --- a/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/ProblemsView.java +++ b/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/ProblemsView.java @@ -1,10 +1,10 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.analysis.problemsView.toolWindow; -import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.application.Experiments; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.ex.RangeHighlighterEx; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; @@ -42,9 +42,9 @@ public final class ProblemsView implements DumbAware, ToolWindowFactory { window.activate(null, true); } - public static void selectHighlightInfoIfVisible(@NotNull Project project, @NotNull HighlightInfo info) { + public static void selectHighlighterIfVisible(@NotNull Project project, @NotNull RangeHighlighterEx highlighter) { HighlightingPanel panel = get(HighlightingPanel.class, getSelectedContent(project)); - if (panel != null && panel.isShowing()) panel.selectHighlightInfo(info); + if (panel != null && panel.isShowing()) panel.selectHighlighter(highlighter); } static @Nullable Document getDocument(@Nullable Project project, @NotNull VirtualFile file) { diff --git a/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/Root.kt b/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/Root.kt index 47dd17eda285..07308451ba22 100644 --- a/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/Root.kt +++ b/platform/lang-impl/src/com/intellij/analysis/problemsView/toolWindow/Root.kt @@ -44,6 +44,12 @@ internal open class Root(val panel: ProblemsViewPanel) : Node(panel.project), Di synchronized(allProblems) { remove(file, problem) }?.let { structureChanged(it) } } + open fun updateProblem(file: VirtualFile, problem: Problem) { + val node = synchronized(allProblems) { allProblems[file]?.findProblemNode(problem) } ?: return + node.update() + structureChanged(node) + } + open fun removeProblems(file: VirtualFile) { synchronized(allProblems) { removeAll(file) }?.let { structureChanged(it) } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GotoNextErrorHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GotoNextErrorHandler.java index 605ad07d40c2..85e3b95a3bf9 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GotoNextErrorHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GotoNextErrorHandler.java @@ -9,6 +9,7 @@ import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInspection.InspectionsBundle; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.editor.*; +import com.intellij.openapi.editor.ex.RangeHighlighterEx; import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.registry.Registry; @@ -16,7 +17,7 @@ import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import static com.intellij.analysis.problemsView.toolWindow.ProblemsView.selectHighlightInfoIfVisible; +import static com.intellij.analysis.problemsView.toolWindow.ProblemsView.selectHighlighterIfVisible; public class GotoNextErrorHandler implements CodeInsightActionHandler { private final boolean myGoForward; @@ -140,7 +141,8 @@ public class GotoNextErrorHandler implements CodeInsightActionHandler { ); IdeDocumentHistory.getInstance(project).includeCurrentCommandAsNavigation(); - selectHighlightInfoIfVisible(project, info); + RangeHighlighterEx highlighter = info.getHighlighter(); + if (highlighter != null) selectHighlighterIfVisible(project, highlighter); } private static int getNavigationPositionFor(HighlightInfo info, Document document) {