mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Problems View refactoring - async highlighters support
GitOrigin-RevId: 3283032cd02cc3aa18129c521c79108787d0ecfd
This commit is contained in:
committed by
intellij-monorepo-bot
parent
77ef50b99e
commit
9c3ab2e377
+7
@@ -0,0 +1,7 @@
|
||||
package com.intellij.codeInsight.daemon.impl
|
||||
|
||||
import org.jetbrains.concurrency.Promise
|
||||
|
||||
interface AsyncDescriptionSupplier {
|
||||
fun requestDescription() : Promise<String>
|
||||
}
|
||||
+5
-8
@@ -2,7 +2,6 @@
|
||||
package com.intellij.analysis.problemsView.toolWindow
|
||||
|
||||
import com.intellij.analysis.problemsView.Problem
|
||||
import com.intellij.analysis.problemsView.ProblemsListener
|
||||
import com.intellij.analysis.problemsView.ProblemsProvider
|
||||
import com.intellij.lang.annotation.HighlightSeverity
|
||||
import com.intellij.openapi.editor.ex.RangeHighlighterEx
|
||||
@@ -10,16 +9,16 @@ import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
|
||||
open class HighlightingFileRoot(panel: ProblemsViewPanel, val file: VirtualFile) : Root(panel) {
|
||||
internal class HighlightingFileRoot(panel: ProblemsViewPanel, val file: VirtualFile) : Root(panel) {
|
||||
|
||||
private val problems = mutableSetOf<HighlightingProblem>()
|
||||
private val filter = ProblemFilter(panel.state)
|
||||
|
||||
protected val provider = object : ProblemsProvider {
|
||||
private val provider = object : ProblemsProvider {
|
||||
override val project = panel.project
|
||||
}
|
||||
|
||||
protected open val watcher = createWatcher(provider, this, file, HighlightSeverity.INFORMATION.myVal + 1)
|
||||
private val watcher = createWatcher(provider, file)
|
||||
|
||||
init {
|
||||
Disposer.register(this, provider)
|
||||
@@ -45,10 +44,8 @@ open class HighlightingFileRoot(panel: ProblemsViewPanel, val file: VirtualFile)
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
protected open fun createWatcher(provider: ProblemsProvider,
|
||||
listener: ProblemsListener,
|
||||
file: VirtualFile,
|
||||
level: Int): HighlightingWatcher =
|
||||
private fun createWatcher(provider: ProblemsProvider,
|
||||
file: VirtualFile): HighlightingWatcher =
|
||||
HighlightingWatcher(provider, this, file, HighlightSeverity.INFORMATION.myVal + 1)
|
||||
|
||||
override fun getOtherProblemCount() = 0
|
||||
|
||||
+3
-3
@@ -22,7 +22,7 @@ import com.intellij.util.ui.tree.TreeUtil
|
||||
import org.jetbrains.annotations.Nls
|
||||
import javax.swing.Icon
|
||||
|
||||
open class HighlightingPanel(project: Project, state: ProblemsViewState)
|
||||
class HighlightingPanel(project: Project, state: ProblemsViewState)
|
||||
: ProblemsViewPanel(project, ID, state, ProblemsViewBundle.messagePointer("problems.view.highlighting")),
|
||||
FileEditorManagerListener, PowerSaveMode.Listener {
|
||||
|
||||
@@ -88,7 +88,7 @@ open class HighlightingPanel(project: Project, state: ProblemsViewState)
|
||||
currentFile = ClientId.withClientId(myClientId) { findCurrentFile() }
|
||||
}
|
||||
|
||||
val currentRoot
|
||||
internal val currentRoot
|
||||
get() = treeModel.root as? HighlightingFileRoot
|
||||
|
||||
var currentFile
|
||||
@@ -106,7 +106,7 @@ open class HighlightingPanel(project: Project, state: ProblemsViewState)
|
||||
powerSaveStateChanged()
|
||||
}
|
||||
|
||||
protected open fun getRoot(file: VirtualFile): HighlightingFileRoot = HighlightingFileRoot(this, file)
|
||||
internal fun getRoot(file: VirtualFile): HighlightingFileRoot = HighlightingFileRoot(this, file)
|
||||
|
||||
fun selectHighlighter(highlighter: RangeHighlighterEx) {
|
||||
val problem = currentRoot?.findProblem(highlighter) ?: return
|
||||
|
||||
+40
-9
@@ -1,39 +1,69 @@
|
||||
// Copyright 2000-2021 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.CommonBundle
|
||||
import com.intellij.analysis.problemsView.FileProblem
|
||||
import com.intellij.analysis.problemsView.ProblemsProvider
|
||||
import com.intellij.codeHighlighting.HighlightDisplayLevel
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey
|
||||
import com.intellij.codeInsight.daemon.impl.AsyncDescriptionSupplier
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.editor.ex.RangeHighlighterEx
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.ui.AnimatedIcon
|
||||
import com.intellij.xml.util.XmlStringUtil.escapeString
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import javax.swing.Icon
|
||||
|
||||
open class HighlightingProblem(
|
||||
internal class HighlightingProblem(
|
||||
override val provider: ProblemsProvider,
|
||||
override val file: VirtualFile,
|
||||
private val highlighter: RangeHighlighterEx
|
||||
val highlighter: RangeHighlighterEx
|
||||
) : FileProblem {
|
||||
|
||||
private fun getIcon(level: HighlightDisplayLevel) = if (severity >= level.severity.myVal) level.icon else null
|
||||
private fun getIcon(level: HighlightDisplayLevel): Icon? = when {
|
||||
text.isEmpty() || asyncDescriptionRequested.get() -> AnimatedIcon.Default.INSTANCE
|
||||
severity >= level.severity.myVal -> level.icon
|
||||
else -> null
|
||||
}
|
||||
|
||||
open val info: HighlightInfo?
|
||||
private var asyncDescriptionRequested = AtomicBoolean(false)
|
||||
private var loading = AtomicBoolean(false)
|
||||
|
||||
val info: HighlightInfo?
|
||||
get() {
|
||||
return HighlightInfo.fromRangeHighlighter(highlighter)
|
||||
val info = HighlightInfo.fromRangeHighlighter(highlighter)
|
||||
if (info is AsyncDescriptionSupplier) {
|
||||
requestAsyncDescription(info)
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
private fun requestAsyncDescription(info: AsyncDescriptionSupplier) {
|
||||
if (!asyncDescriptionRequested.compareAndSet(false, true)) return
|
||||
loading.set(true)
|
||||
|
||||
info.requestDescription().onSuccess {
|
||||
// we do that to avoid Concurrent modification exception
|
||||
ApplicationManager.getApplication().invokeLater {
|
||||
val panel = ProblemsView.getSelectedPanel(provider.project) as? HighlightingPanel
|
||||
panel?.currentRoot?.problemUpdated(this)
|
||||
loading.set(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override val icon: Icon
|
||||
get() = HighlightDisplayLevel.find(info?.severity)?.icon
|
||||
?: getIcon(HighlightDisplayLevel.ERROR)
|
||||
?: getIcon(HighlightDisplayLevel.WARNING)
|
||||
?: HighlightDisplayLevel.WEAK_WARNING.icon
|
||||
?: getIcon(HighlightDisplayLevel.ERROR)
|
||||
?: getIcon(HighlightDisplayLevel.WARNING)
|
||||
?: HighlightDisplayLevel.WEAK_WARNING.icon
|
||||
|
||||
override val text: String
|
||||
get() {
|
||||
val text = info?.description ?: return "Invalid"
|
||||
val text = info?.description ?: return CommonBundle.getLoadingTreeNodeText()
|
||||
val pos = text.indexOfFirst { StringUtil.isLineBreak(it) }
|
||||
return if (pos < 0 || text.startsWith("<html>", ignoreCase = true)) text
|
||||
else text.substring(0, pos) + StringUtil.ELLIPSIS
|
||||
@@ -48,6 +78,7 @@ open class HighlightingProblem(
|
||||
override val description: String?
|
||||
get() {
|
||||
val text = info?.description ?: return null
|
||||
if (text.isEmpty()) return null
|
||||
val pos = text.indexOfFirst { StringUtil.isLineBreak(it) }
|
||||
return if (pos < 0 || text.startsWith("<html>", ignoreCase = true)) null
|
||||
else "<html>" + StringUtil.join(StringUtil.splitByLines(escapeString(text)), "<br/>")
|
||||
|
||||
+6
-6
@@ -14,14 +14,14 @@ import com.intellij.openapi.editor.impl.event.MarkupModelListener
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
open class HighlightingWatcher(
|
||||
protected val provider: ProblemsProvider,
|
||||
protected val listener: ProblemsListener,
|
||||
protected val file: VirtualFile,
|
||||
internal class HighlightingWatcher(
|
||||
private val provider: ProblemsProvider,
|
||||
private val listener: ProblemsListener,
|
||||
private val file: VirtualFile,
|
||||
private val level: Int)
|
||||
: MarkupModelListener, Disposable {
|
||||
|
||||
protected val problems = mutableMapOf<RangeHighlighterEx, Problem>()
|
||||
private val problems = mutableMapOf<RangeHighlighterEx, Problem>()
|
||||
private var reference: WeakReference<MarkupModelEx>? = null
|
||||
|
||||
init {
|
||||
@@ -62,7 +62,7 @@ open class HighlightingWatcher(
|
||||
|
||||
fun findProblem(highlighter: RangeHighlighterEx) = synchronized(problems) { problems[highlighter] }
|
||||
|
||||
protected open fun getHighlightingProblem(highlighter: RangeHighlighterEx): HighlightingProblem
|
||||
private fun getHighlightingProblem(highlighter: RangeHighlighterEx): HighlightingProblem
|
||||
= HighlightingProblem(provider, file, highlighter)
|
||||
|
||||
private fun getProblem(highlighter: RangeHighlighterEx) = when {
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ open class ProblemsViewState : BaseState() {
|
||||
var sortByName by property(false)
|
||||
|
||||
@get:XCollection(style = XCollection.Style.v2)
|
||||
val hideBySeverity: MutableSet<Int> by property(Collections.newSetFromMap(ConcurrentHashMap()), { it.isEmpty() })
|
||||
val hideBySeverity: MutableSet<Int> by property(Collections.newSetFromMap(ConcurrentHashMap())) { it.isEmpty() }
|
||||
}
|
||||
|
||||
@State(name = "ProblemsViewState", storages = [(Storage(value = StoragePathMacros.WORKSPACE_FILE))])
|
||||
|
||||
Reference in New Issue
Block a user