1
0
mirror of https://github.com/chylex/IntelliJ-Inspection-Lens.git synced 2024-11-25 16:42:54 +01:00

Compare commits

..

3 Commits

Author SHA1 Message Date
1c92cf000f
Release 1.3.2 2024-02-07 20:51:32 +01:00
83c179574a
Fix inspections randomly not disappearing 2024-02-07 20:33:31 +01:00
536650510d
Update IDEA to 2023.3.3 2024-02-07 06:40:15 +01:00
8 changed files with 105 additions and 60 deletions

View File

@ -4,18 +4,18 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins { plugins {
kotlin("jvm") version "1.8.0" kotlin("jvm") version "1.8.0"
id("org.jetbrains.intellij") version "1.16.0" id("org.jetbrains.intellij") version "1.17.0"
} }
group = "com.chylex.intellij.inspectionlens" group = "com.chylex.intellij.inspectionlens"
version = "1.3.1" version = "1.3.2"
repositories { repositories {
mavenCentral() mavenCentral()
} }
intellij { intellij {
version.set("233.11555.11-EAP-SNAPSHOT") version.set("2023.3.3")
updateSinceUntilBuild.set(false) updateSinceUntilBuild.set(false)
plugins.add("tanvd.grazi") plugins.add("tanvd.grazi")

View File

@ -0,0 +1,25 @@
package com.chylex.intellij.inspectionlens
import com.intellij.openapi.application.ApplicationManager
object InspectionLensRefresher {
private var needsRefresh = false
fun scheduleRefresh() {
synchronized(this) {
if (!needsRefresh) {
needsRefresh = true
ApplicationManager.getApplication().invokeLater(::refresh)
}
}
}
private fun refresh() {
synchronized(this) {
if (needsRefresh) {
needsRefresh = false
InspectionLens.refresh()
}
}
}
}

View File

@ -30,6 +30,10 @@ class EditorLensManager private constructor(private val editor: Editor) {
private fun show(highlighterWithInfo: HighlighterWithInfo) { private fun show(highlighterWithInfo: HighlighterWithInfo) {
val (highlighter, info) = highlighterWithInfo val (highlighter, info) = highlighterWithInfo
if (!highlighter.isValid) {
return
}
val existingLens = lenses[highlighter] val existingLens = lenses[highlighter]
if (existingLens != null) { if (existingLens != null) {
if (existingLens.update(info)) { if (existingLens.update(info)) {
@ -48,22 +52,10 @@ class EditorLensManager private constructor(private val editor: Editor) {
} }
} }
fun show(highlightersWithInfo: Collection<HighlighterWithInfo>) {
executeInBatchMode(highlightersWithInfo.size) {
highlightersWithInfo.forEach(::show)
}
}
private fun hide(highlighter: RangeHighlighter) { private fun hide(highlighter: RangeHighlighter) {
lenses.remove(highlighter)?.hide() lenses.remove(highlighter)?.hide()
} }
fun hide(highlighters: Collection<RangeHighlighter>) {
executeInBatchMode(highlighters.size) {
highlighters.forEach(::hide)
}
}
fun hideAll() { fun hideAll() {
executeInBatchMode(lenses.size) { executeInBatchMode(lenses.size) {
lenses.values.forEach(EditorLens::hide) lenses.values.forEach(EditorLens::hide)
@ -71,6 +63,28 @@ class EditorLensManager private constructor(private val editor: Editor) {
} }
} }
fun execute(commands: Collection<Command>) {
executeInBatchMode(commands.size) {
commands.forEach { it.apply(this) }
}
}
sealed interface Command {
fun apply(lensManager: EditorLensManager)
class Show(private val highlighter: HighlighterWithInfo) : Command {
override fun apply(lensManager: EditorLensManager) {
lensManager.show(highlighter)
}
}
class Hide(private val highlighter: RangeHighlighter) : Command {
override fun apply(lensManager: EditorLensManager) {
lensManager.hide(highlighter)
}
}
}
/** /**
* Batch mode affects both inlays and highlighters used for line colors. * Batch mode affects both inlays and highlighters used for line colors.
*/ */

View File

@ -0,0 +1,41 @@
package com.chylex.intellij.inspectionlens.editor
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.editor.markup.RangeHighlighter
class EditorLensManagerDispatcher(private val lensManager: EditorLensManager) {
private var queuedItems = mutableListOf<EditorLensManager.Command>()
private var isEnqueued = false
fun show(highlighterWithInfo: HighlighterWithInfo) {
enqueue(EditorLensManager.Command.Show(highlighterWithInfo))
}
fun hide(highlighter: RangeHighlighter) {
enqueue(EditorLensManager.Command.Hide(highlighter))
}
private fun enqueue(item: EditorLensManager.Command) {
synchronized(this) {
queuedItems.add(item)
// Enqueue even if already on dispatch thread to debounce consecutive calls.
if (!isEnqueued) {
isEnqueued = true
ApplicationManager.getApplication().invokeLater(::process)
}
}
}
private fun process() {
var itemsToProcess: List<EditorLensManager.Command>
synchronized(this) {
itemsToProcess = queuedItems
queuedItems = mutableListOf()
isEnqueued = false
}
lensManager.execute(itemsToProcess)
}
}

View File

@ -1,6 +1,5 @@
package com.chylex.intellij.inspectionlens.editor package com.chylex.intellij.inspectionlens.editor
import com.chylex.intellij.inspectionlens.utils.DebouncingInvokeOnDispatchThread
import com.intellij.codeInsight.daemon.impl.HighlightInfo import com.intellij.codeInsight.daemon.impl.HighlightInfo
import com.intellij.lang.annotation.HighlightSeverity import com.intellij.lang.annotation.HighlightSeverity
import com.intellij.openapi.Disposable import com.intellij.openapi.Disposable
@ -17,10 +16,7 @@ import com.intellij.openapi.util.Key
* Listens for inspection highlights and reports them to [EditorLensManager]. * Listens for inspection highlights and reports them to [EditorLensManager].
*/ */
internal class LensMarkupModelListener private constructor(editor: Editor) : MarkupModelListener { internal class LensMarkupModelListener private constructor(editor: Editor) : MarkupModelListener {
private val lensManager = EditorLensManager.getOrCreate(editor) private val lensManagerDispatcher = EditorLensManagerDispatcher(EditorLensManager.getOrCreate(editor))
private val showOnDispatchThread = DebouncingInvokeOnDispatchThread(lensManager::show)
private val hideOnDispatchThread = DebouncingInvokeOnDispatchThread(lensManager::hide)
override fun afterAdded(highlighter: RangeHighlighterEx) { override fun afterAdded(highlighter: RangeHighlighterEx) {
showIfValid(highlighter) showIfValid(highlighter)
@ -32,18 +28,18 @@ internal class LensMarkupModelListener private constructor(editor: Editor) : Mar
override fun beforeRemoved(highlighter: RangeHighlighterEx) { override fun beforeRemoved(highlighter: RangeHighlighterEx) {
if (getFilteredHighlightInfo(highlighter) != null) { if (getFilteredHighlightInfo(highlighter) != null) {
hideOnDispatchThread.enqueue(highlighter) lensManagerDispatcher.hide(highlighter)
} }
} }
private fun showIfValid(highlighter: RangeHighlighter) { private fun showIfValid(highlighter: RangeHighlighter) {
runWithHighlighterIfValid(highlighter, showOnDispatchThread::enqueue, ::showAsynchronously) runWithHighlighterIfValid(highlighter, lensManagerDispatcher::show, ::showAsynchronously)
} }
private fun showAsynchronously(highlighterWithInfo: HighlighterWithInfo.Async) { private fun showAsynchronously(highlighterWithInfo: HighlighterWithInfo.Async) {
highlighterWithInfo.requestDescription { highlighterWithInfo.requestDescription {
if (highlighterWithInfo.highlighter.isValid && highlighterWithInfo.hasDescription) { if (highlighterWithInfo.highlighter.isValid && highlighterWithInfo.hasDescription) {
showOnDispatchThread.enqueue(highlighterWithInfo) lensManagerDispatcher.show(highlighterWithInfo)
} }
} }
} }

View File

@ -1,7 +1,6 @@
package com.chylex.intellij.inspectionlens.editor package com.chylex.intellij.inspectionlens.editor
import com.chylex.intellij.inspectionlens.InspectionLens import com.chylex.intellij.inspectionlens.InspectionLensRefresher
import com.chylex.intellij.inspectionlens.utils.DebouncingInvokeOnDispatchThread
import com.intellij.lang.annotation.HighlightSeverity import com.intellij.lang.annotation.HighlightSeverity
import com.intellij.spellchecker.SpellCheckerSeveritiesProvider import com.intellij.spellchecker.SpellCheckerSeveritiesProvider
import com.intellij.ui.ColorUtil import com.intellij.ui.ColorUtil
@ -47,14 +46,12 @@ enum class LensSeverity(baseColor: Color, lightThemeDarkening: Int, darkThemeBri
SpellCheckerSeveritiesProvider.TYPO to TYPO, SpellCheckerSeveritiesProvider.TYPO to TYPO,
)) ))
private val refreshLater = DebouncingInvokeOnDispatchThread<Unit> { InspectionLens.refresh() }
/** /**
* Registers a mapping from a [HighlightSeverity] to a [LensSeverity], and refreshes all open editors. * Registers a mapping from a [HighlightSeverity] to a [LensSeverity], and refreshes all open editors.
*/ */
internal fun registerMapping(severity: HighlightSeverity, lensSeverity: LensSeverity) { internal fun registerMapping(severity: HighlightSeverity, lensSeverity: LensSeverity) {
if (mapping.put(severity, lensSeverity) != lensSeverity) { if (mapping.put(severity, lensSeverity) != lensSeverity) {
refreshLater.enqueue(Unit) InspectionLensRefresher.scheduleRefresh()
} }
} }

View File

@ -1,32 +0,0 @@
package com.chylex.intellij.inspectionlens.utils
import com.intellij.openapi.application.ApplicationManager
class DebouncingInvokeOnDispatchThread<T>(private val action: (List<T>) -> Unit) {
private var queuedItems = mutableListOf<T>()
private var isEnqueued = false
fun enqueue(item: T) {
synchronized(this) {
queuedItems.add(item)
// Enqueue even if already on dispatch thread to debounce consecutive calls.
if (!isEnqueued) {
isEnqueued = true
ApplicationManager.getApplication().invokeLater(::process)
}
}
}
private fun process() {
var itemsToProcess: List<T>
synchronized(this) {
itemsToProcess = queuedItems
queuedItems = mutableListOf()
isEnqueued = false
}
action(itemsToProcess)
}
}

View File

@ -17,6 +17,10 @@
]]></description> ]]></description>
<change-notes><![CDATA[ <change-notes><![CDATA[
<b>Version 1.3.2</b>
<ul>
<li>Fixed inspections randomly not disappearing.</li>
</ul>
<b>Version 1.3.1</b> <b>Version 1.3.1</b>
<ul> <ul>
<li>Updated minimum version to IntelliJ 2023.3 due to breaking API changes.</li> <li>Updated minimum version to IntelliJ 2023.3 due to breaking API changes.</li>