mirror of
https://github.com/chylex/IntelliJ-Inspection-Lens.git
synced 2024-11-26 10:42:51 +01:00
Compare commits
No commits in common. "44f2fa5c1675bfcd2a08342ff6ef4d206b7b5711" and "c993b4f203e34e91a47383bd1097794a73b53649" have entirely different histories.
44f2fa5c16
...
c993b4f203
@ -50,7 +50,7 @@ class EditorInlayLensManager private constructor(private val editor: Editor) {
|
|||||||
|
|
||||||
private val inlays = mutableMapOf<RangeHighlighter, Inlay<LensRenderer>>()
|
private val inlays = mutableMapOf<RangeHighlighter, Inlay<LensRenderer>>()
|
||||||
|
|
||||||
private fun show(highlighterWithInfo: HighlighterWithInfo) {
|
fun show(highlighterWithInfo: HighlighterWithInfo) {
|
||||||
val (highlighter, info) = highlighterWithInfo
|
val (highlighter, info) = highlighterWithInfo
|
||||||
val currentInlay = inlays[highlighter]
|
val currentInlay = inlays[highlighter]
|
||||||
if (currentInlay != null && currentInlay.isValid) {
|
if (currentInlay != null && currentInlay.isValid) {
|
||||||
@ -73,14 +73,10 @@ class EditorInlayLensManager private constructor(private val editor: Editor) {
|
|||||||
executeInInlayBatchMode(highlightersWithInfo.size) { highlightersWithInfo.forEach(::show) }
|
executeInInlayBatchMode(highlightersWithInfo.size) { highlightersWithInfo.forEach(::show) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hide(highlighter: RangeHighlighter) {
|
fun hide(highlighter: RangeHighlighter) {
|
||||||
inlays.remove(highlighter)?.dispose()
|
inlays.remove(highlighter)?.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hideAll(highlighters: Collection<RangeHighlighter>) {
|
|
||||||
executeInInlayBatchMode(highlighters.size) { highlighters.forEach(::hide) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun hideAll() {
|
fun hideAll() {
|
||||||
executeInInlayBatchMode(inlays.size) { inlays.values.forEach(Inlay<*>::dispose) }
|
executeInInlayBatchMode(inlays.size) { inlays.values.forEach(Inlay<*>::dispose) }
|
||||||
inlays.clear()
|
inlays.clear()
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package com.chylex.intellij.inspectionlens.editor
|
package com.chylex.intellij.inspectionlens.editor
|
||||||
|
|
||||||
import com.chylex.intellij.inspectionlens.InspectionLensPluginDisposableService
|
import com.chylex.intellij.inspectionlens.InspectionLensPluginDisposableService
|
||||||
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.application.ApplicationManager
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
@ -22,9 +21,6 @@ import com.jetbrains.rd.util.lifetime.intersect
|
|||||||
class LensMarkupModelListener private constructor(editor: Editor) : MarkupModelListener {
|
class LensMarkupModelListener private constructor(editor: Editor) : MarkupModelListener {
|
||||||
private val lens = EditorInlayLensManager.getOrCreate(editor)
|
private val lens = EditorInlayLensManager.getOrCreate(editor)
|
||||||
|
|
||||||
private val showOnDispatchThread = DebouncingInvokeOnDispatchThread(lens::showAll)
|
|
||||||
private val hideOnDispatchThread = DebouncingInvokeOnDispatchThread(lens::hideAll)
|
|
||||||
|
|
||||||
override fun afterAdded(highlighter: RangeHighlighterEx) {
|
override fun afterAdded(highlighter: RangeHighlighterEx) {
|
||||||
showIfValid(highlighter)
|
showIfValid(highlighter)
|
||||||
}
|
}
|
||||||
@ -34,19 +30,35 @@ class LensMarkupModelListener private constructor(editor: Editor) : MarkupModelL
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun beforeRemoved(highlighter: RangeHighlighterEx) {
|
override fun beforeRemoved(highlighter: RangeHighlighterEx) {
|
||||||
if (getFilteredHighlightInfo(highlighter) != null) {
|
lens.hide(highlighter)
|
||||||
hideOnDispatchThread.enqueue(highlighter)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showIfValid(highlighter: RangeHighlighter) {
|
private fun showIfValid(highlighter: RangeHighlighter) {
|
||||||
runWithHighlighterIfValid(highlighter, showOnDispatchThread::enqueue, ::showAsynchronously)
|
runWithHighlighterIfValid(highlighter, lens::show, ::showAsynchronously)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showAllValid(highlighters: Array<RangeHighlighter>) {
|
||||||
|
val immediateHighlighters = mutableListOf<HighlighterWithInfo>()
|
||||||
|
|
||||||
|
for (highlighter in highlighters) {
|
||||||
|
runWithHighlighterIfValid(highlighter, immediateHighlighters::add, ::showAsynchronously)
|
||||||
|
}
|
||||||
|
|
||||||
|
lens.showAll(immediateHighlighters)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
val application = ApplicationManager.getApplication()
|
||||||
|
if (application.isDispatchThread) {
|
||||||
|
lens.show(highlighterWithInfo)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
application.invokeLater {
|
||||||
|
lens.show(highlighterWithInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,12 +66,15 @@ class LensMarkupModelListener private constructor(editor: Editor) : MarkupModelL
|
|||||||
companion object {
|
companion object {
|
||||||
private val MINIMUM_SEVERITY = HighlightSeverity.TEXT_ATTRIBUTES.myVal + 1
|
private val MINIMUM_SEVERITY = HighlightSeverity.TEXT_ATTRIBUTES.myVal + 1
|
||||||
|
|
||||||
private fun getFilteredHighlightInfo(highlighter: RangeHighlighter): HighlightInfo? {
|
private fun getHighlightInfoIfValid(highlighter: RangeHighlighter): HighlightInfo? {
|
||||||
return HighlightInfo.fromRangeHighlighter(highlighter)?.takeIf { it.severity.myVal >= MINIMUM_SEVERITY }
|
return if (highlighter.isValid)
|
||||||
|
HighlightInfo.fromRangeHighlighter(highlighter)?.takeIf { it.severity.myVal >= MINIMUM_SEVERITY }
|
||||||
|
else
|
||||||
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun runWithHighlighterIfValid(highlighter: RangeHighlighter, actionForImmediate: (HighlighterWithInfo) -> Unit, actionForAsync: (HighlighterWithInfo.Async) -> Unit) {
|
private inline fun runWithHighlighterIfValid(highlighter: RangeHighlighter, actionForImmediate: (HighlighterWithInfo) -> Unit, actionForAsync: (HighlighterWithInfo.Async) -> Unit) {
|
||||||
val info = highlighter.takeIf { it.isValid }?.let(::getFilteredHighlightInfo)
|
val info = getHighlightInfoIfValid(highlighter)
|
||||||
if (info != null) {
|
if (info != null) {
|
||||||
processHighlighterWithInfo(HighlighterWithInfo.from(highlighter, info), actionForImmediate, actionForAsync)
|
processHighlighterWithInfo(HighlighterWithInfo.from(highlighter, info), actionForImmediate, actionForAsync)
|
||||||
}
|
}
|
||||||
@ -88,10 +103,7 @@ class LensMarkupModelListener private constructor(editor: Editor) : MarkupModelL
|
|||||||
|
|
||||||
val listener = LensMarkupModelListener(editor)
|
val listener = LensMarkupModelListener(editor)
|
||||||
markupModel.addMarkupModelListener(pluginLifetime.intersect(editorLifetime).createNestedDisposable(), listener)
|
markupModel.addMarkupModelListener(pluginLifetime.intersect(editorLifetime).createNestedDisposable(), listener)
|
||||||
|
listener.showAllValid(markupModel.allHighlighters)
|
||||||
for (highlighter in markupModel.allHighlighters) {
|
|
||||||
listener.showIfValid(highlighter)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import com.intellij.openapi.editor.Editor
|
|||||||
import com.intellij.openapi.editor.Inlay
|
import com.intellij.openapi.editor.Inlay
|
||||||
import com.intellij.openapi.editor.markup.TextAttributes
|
import com.intellij.openapi.editor.markup.TextAttributes
|
||||||
import com.intellij.openapi.util.text.StringUtil
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
|
import java.awt.Font
|
||||||
import java.awt.Graphics
|
import java.awt.Graphics
|
||||||
import java.awt.Rectangle
|
import java.awt.Rectangle
|
||||||
|
|
||||||
@ -30,7 +31,7 @@ class LensRenderer(info: HighlightInfo) : HintRenderer(null) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getTextAttributes(editor: Editor): TextAttributes {
|
override fun getTextAttributes(editor: Editor): TextAttributes {
|
||||||
return severity.colorAttributes
|
return ATTRIBUTES_SINGLETON.also { it.foregroundColor = severity.color }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun useEditorFont(): Boolean {
|
override fun useEditorFont(): Boolean {
|
||||||
@ -38,6 +39,8 @@ class LensRenderer(info: HighlightInfo) : HintRenderer(null) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
|
private val ATTRIBUTES_SINGLETON = TextAttributes(null, null, null, null, Font.ITALIC)
|
||||||
|
|
||||||
private fun getValidDescriptionText(text: String?): String {
|
private fun getValidDescriptionText(text: String?): String {
|
||||||
return if (text.isNullOrBlank()) " " else addMissingPeriod(convertHtmlToText(text))
|
return if (text.isNullOrBlank()) " " else addMissingPeriod(convertHtmlToText(text))
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import com.intellij.lang.annotation.HighlightSeverity
|
|||||||
import com.intellij.ui.ColorUtil
|
import com.intellij.ui.ColorUtil
|
||||||
import com.intellij.ui.JBColor
|
import com.intellij.ui.JBColor
|
||||||
import java.awt.Color
|
import java.awt.Color
|
||||||
import java.awt.Font
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines properties of inspection lenses based on severity.
|
* Determines properties of inspection lenses based on severity.
|
||||||
@ -17,14 +16,12 @@ enum class LensSeverity(baseColor: Color, lightThemeDarkening: Int, darkThemeBri
|
|||||||
SERVER_PROBLEM (Color(176, 97, 0), lightThemeDarkening = 4, darkThemeBrightening = 2),
|
SERVER_PROBLEM (Color(176, 97, 0), lightThemeDarkening = 4, darkThemeBrightening = 2),
|
||||||
OTHER (Color(128, 128, 128), lightThemeDarkening = 1, darkThemeBrightening = 2);
|
OTHER (Color(128, 128, 128), lightThemeDarkening = 1, darkThemeBrightening = 2);
|
||||||
|
|
||||||
val colorAttributes: LensSeverityTextAttributes
|
val color: JBColor
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val lightThemeColor = ColorUtil.saturate(ColorUtil.darker(baseColor, lightThemeDarkening), 1)
|
val lightThemeColor = ColorUtil.saturate(ColorUtil.darker(baseColor, lightThemeDarkening), 1)
|
||||||
val darkThemeColor = ColorUtil.desaturate(ColorUtil.brighter(baseColor, darkThemeBrightening), 2)
|
val darkThemeColor = ColorUtil.desaturate(ColorUtil.brighter(baseColor, darkThemeBrightening), 2)
|
||||||
|
color = JBColor(lightThemeColor, darkThemeColor)
|
||||||
val textColor = JBColor(lightThemeColor, darkThemeColor)
|
|
||||||
colorAttributes = LensSeverityTextAttributes(foregroundColor = textColor, fontStyle = Font.ITALIC)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
package com.chylex.intellij.inspectionlens.editor
|
|
||||||
|
|
||||||
import com.intellij.openapi.editor.markup.UnmodifiableTextAttributes
|
|
||||||
import com.intellij.ui.JBColor
|
|
||||||
import java.awt.Font
|
|
||||||
|
|
||||||
class LensSeverityTextAttributes(private val foregroundColor: JBColor, private val fontStyle: Int = Font.PLAIN) : UnmodifiableTextAttributes() {
|
|
||||||
override fun getForegroundColor(): JBColor {
|
|
||||||
return foregroundColor
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getFontType(): Int {
|
|
||||||
return fontStyle
|
|
||||||
}
|
|
||||||
}
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user