mirror of
https://github.com/chylex/IntelliJ-Inspection-Lens.git
synced 2025-06-03 08:34:07 +02:00
Rewrite inlay hint priority calculation to use position in line instead of the whole document
This commit is contained in:
parent
0aff0f49ae
commit
ca4fb0484a
src
main/kotlin/com/chylex/intellij/inspectionlens
test/kotlin/com/chylex/intellij/inspectionlens
@ -1,6 +1,5 @@
|
|||||||
package com.chylex.intellij.inspectionlens
|
package com.chylex.intellij.inspectionlens
|
||||||
|
|
||||||
import com.chylex.intellij.inspectionlens.EditorInlayLensManager.Companion.MAXIMUM_SEVERITY
|
|
||||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo
|
import com.intellij.codeInsight.daemon.impl.HighlightInfo
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.editor.Inlay
|
import com.intellij.openapi.editor.Inlay
|
||||||
@ -17,10 +16,10 @@ class EditorInlayLensManager private constructor(private val editor: Editor) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Highest allowed severity for the purposes of sorting multiple highlights at the same offset.
|
* Highest allowed severity for the purposes of sorting multiple highlights at the same offset.
|
||||||
* A [MAXIMUM_SEVERITY] of 500 allows for 8 589 933 positions in the document before sorting breaks down.
|
|
||||||
* The value is a little higher than the highest [com.intellij.lang.annotation.HighlightSeverity], in case severities with higher values are introduced in the future.
|
* The value is a little higher than the highest [com.intellij.lang.annotation.HighlightSeverity], in case severities with higher values are introduced in the future.
|
||||||
*/
|
*/
|
||||||
private const val MAXIMUM_SEVERITY = 500
|
private const val MAXIMUM_SEVERITY = 500
|
||||||
|
private const val MAXIMUM_POSITION = ((Int.MAX_VALUE / MAXIMUM_SEVERITY) * 2) - 1
|
||||||
|
|
||||||
fun getOrCreate(editor: Editor): EditorInlayLensManager {
|
fun getOrCreate(editor: Editor): EditorInlayLensManager {
|
||||||
return editor.getUserData(KEY) ?: EditorInlayLensManager(editor).also { editor.putUserData(KEY, it) }
|
return editor.getUserData(KEY) ?: EditorInlayLensManager(editor).also { editor.putUserData(KEY, it) }
|
||||||
@ -39,18 +38,14 @@ class EditorInlayLensManager private constructor(private val editor: Editor) {
|
|||||||
return info.actualEndOffset - 1
|
return info.actualEndOffset - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun getInlayHintPriority(offset: Int, severity: Int): Int {
|
internal fun getInlayHintPriority(position: Int, severity: Int): Int {
|
||||||
// Sorts highlights first by offset in the document, then by severity.
|
// Sorts highlights first by position on the line, then by severity.
|
||||||
val positionBucket = offset.coerceAtLeast(0) * MAXIMUM_SEVERITY.toLong()
|
val positionBucket = position.coerceIn(0, MAXIMUM_POSITION) * MAXIMUM_SEVERITY
|
||||||
val positionFactor = (Int.MAX_VALUE - MAXIMUM_SEVERITY - positionBucket).coerceAtLeast(Int.MIN_VALUE + 1L).toInt()
|
// The multiplication can overflow, but subtracting overflowed result from Int.MAX_VALUE does not break continuity.
|
||||||
val severityFactor = severity.coerceIn(0, MAXIMUM_SEVERITY)
|
val positionFactor = Integer.MAX_VALUE - positionBucket
|
||||||
// The result is between (Int.MIN_VALUE + 1)..Int.MAX_VALUE, allowing for negation without overflow.
|
val severityFactor = severity.coerceIn(0, MAXIMUM_SEVERITY) - MAXIMUM_SEVERITY
|
||||||
return positionFactor + severityFactor
|
return positionFactor + severityFactor
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getInlayHintPriority(info: HighlightInfo): Int {
|
|
||||||
return getInlayHintPriority(info.actualEndOffset, info.severity.myVal)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val inlays = mutableMapOf<RangeHighlighter, Inlay<LensRenderer>>()
|
private val inlays = mutableMapOf<RangeHighlighter, Inlay<LensRenderer>>()
|
||||||
@ -87,6 +82,17 @@ class EditorInlayLensManager private constructor(private val editor: Editor) {
|
|||||||
inlays.clear()
|
inlays.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getInlayHintPriority(info: HighlightInfo): Int {
|
||||||
|
val startOffset = info.actualStartOffset
|
||||||
|
val positionOnLine = startOffset - getLineStartOffset(startOffset)
|
||||||
|
return getInlayHintPriority(positionOnLine, info.severity.myVal)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getLineStartOffset(offset: Int): Int {
|
||||||
|
val position = editor.offsetToLogicalPosition(offset)
|
||||||
|
return editor.document.getLineStartOffset(position.line)
|
||||||
|
}
|
||||||
|
|
||||||
private fun executeInInlayBatchMode(operations: Int, block: () -> Unit) {
|
private fun executeInInlayBatchMode(operations: Int, block: () -> Unit) {
|
||||||
editor.inlayModel.execute(operations > 1000, block)
|
editor.inlayModel.execute(operations > 1000, block)
|
||||||
}
|
}
|
||||||
|
@ -10,16 +10,16 @@ import org.junit.jupiter.params.provider.ValueSource
|
|||||||
class EditorInlayLensManagerTest {
|
class EditorInlayLensManagerTest {
|
||||||
@Nested
|
@Nested
|
||||||
inner class Priority {
|
inner class Priority {
|
||||||
@ParameterizedTest(name = "offsetAndSeverity = {0}")
|
@ParameterizedTest(name = "positionAndSeverity = {0}")
|
||||||
@ValueSource(ints = [0, -1, Int.MIN_VALUE])
|
@ValueSource(ints = [0, -1, Int.MIN_VALUE])
|
||||||
fun minimumOffset(offsetAndSeverity: Int) {
|
fun minimumOffset(positionAndSeverity: Int) {
|
||||||
assertEquals(Int.MAX_VALUE, EditorInlayLensManager.getInlayHintPriority(offsetAndSeverity, Int.MAX_VALUE))
|
assertEquals(Int.MAX_VALUE, EditorInlayLensManager.getInlayHintPriority(positionAndSeverity, Int.MAX_VALUE))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest(name = "offset = {0}")
|
@ParameterizedTest(name = "position = {0}")
|
||||||
@ValueSource(ints = [8_589_934, Int.MAX_VALUE])
|
@ValueSource(ints = [8_589_933, Int.MAX_VALUE])
|
||||||
fun maximumOffset(offset: Int) {
|
fun maximumOffset(position: Int) {
|
||||||
assertEquals(Int.MIN_VALUE + 1, EditorInlayLensManager.getInlayHintPriority(offset, Int.MIN_VALUE))
|
assertEquals(Int.MIN_VALUE + 295, EditorInlayLensManager.getInlayHintPriority(position, Int.MIN_VALUE))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest(name = "severity = {0}")
|
@ParameterizedTest(name = "severity = {0}")
|
||||||
@ -34,17 +34,23 @@ class EditorInlayLensManagerTest {
|
|||||||
assertEquals(Int.MAX_VALUE - 1000 + severity, EditorInlayLensManager.getInlayHintPriority(1, severity))
|
assertEquals(Int.MAX_VALUE - 1000 + severity, EditorInlayLensManager.getInlayHintPriority(1, severity))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest(name = "severity = {0}")
|
||||||
|
@ValueSource(ints = [0, 1, 250, 499, 500])
|
||||||
|
fun middlePriorityBucket(severity: Int) {
|
||||||
|
assertEquals(-353 + severity, EditorInlayLensManager.getInlayHintPriority(4294967, severity))
|
||||||
|
}
|
||||||
|
|
||||||
@ParameterizedTest(name = "severity = {0}")
|
@ParameterizedTest(name = "severity = {0}")
|
||||||
@ValueSource(ints = [0, 1, 250, 499, 500])
|
@ValueSource(ints = [0, 1, 250, 499, 500])
|
||||||
fun penultimatePriorityBucket(severity: Int) {
|
fun penultimatePriorityBucket(severity: Int) {
|
||||||
assertEquals(Int.MIN_VALUE + 295 + severity, EditorInlayLensManager.getInlayHintPriority(8_589_933, severity))
|
assertEquals(Int.MIN_VALUE + 295 + 500 + severity, EditorInlayLensManager.getInlayHintPriority(8_589_932, severity))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If any of these change, re-evaluate [EditorInlayLensManager.MAXIMUM_SEVERITY] and the priority calculations.
|
* If any of these change, re-evaluate [EditorInlayLensManager.MAXIMUM_SEVERITY] and the priority calculations.
|
||||||
*/
|
*/
|
||||||
@Nested
|
@Nested
|
||||||
inner class IdeaAssumptions {
|
inner class IdeaHighlightSeverityAssumptions {
|
||||||
@Test
|
@Test
|
||||||
fun smallestSeverityHasNotChanged() {
|
fun smallestSeverityHasNotChanged() {
|
||||||
assertEquals(10, HighlightSeverity.DEFAULT_SEVERITIES.minOf(HighlightSeverity::myVal))
|
assertEquals(10, HighlightSeverity.DEFAULT_SEVERITIES.minOf(HighlightSeverity::myVal))
|
||||||
|
Loading…
Reference in New Issue
Block a user