[terminal] IJPL-252272 Refactor: use builder approach for specifying options of EditorTextDecorationApplier

(cherry picked from commit e931d2c07c7a1d11a0007a849ab7a6339e469269)

IJ-CR-217674

GitOrigin-RevId: 5681e297c269cf48e6fc22cd45a3c703e0791dcb
This commit is contained in:
Konstantin Hudyakov
2026-08-10 18:43:20 +00:00
committed by intellij-monorepo-bot
parent 98c886c35d
commit d9ce27b35a
4 changed files with 44 additions and 17 deletions
@@ -4,6 +4,9 @@
- a:addDecorations(java.util.Collection):V
- a:getHoveredHyperlink():com.intellij.execution.impl.HyperlinkDecoration
- a:removeDecorations(java.util.Collection):V
*:com.intellij.execution.impl.EditorTextDecorationApplierBuilder
- a:getConsumeOnlyOnCtrlClick():Z
- a:setConsumeOnlyOnCtrlClick(Z):V
*f:com.intellij.execution.impl.EditorTextDecorationApplierKt
- *sf:buildHighlighting(com.intellij.execution.impl.EditorTextDecorationId,I,I,com.intellij.openapi.editor.markup.TextAttributes,kotlin.jvm.functions.Function1):com.intellij.execution.impl.HighlightingDecoration
- *bs:buildHighlighting$default(com.intellij.execution.impl.EditorTextDecorationId,I,I,com.intellij.openapi.editor.markup.TextAttributes,kotlin.jvm.functions.Function1,I,java.lang.Object):com.intellij.execution.impl.HighlightingDecoration
@@ -11,8 +14,8 @@
- *bs:buildHyperlink$default(com.intellij.execution.impl.EditorTextDecorationId,I,I,kotlin.jvm.functions.Function1,kotlin.jvm.functions.Function1,I,java.lang.Object):com.intellij.execution.impl.HyperlinkDecoration
- *sf:buildInlay(com.intellij.execution.impl.EditorTextDecorationId,I,com.intellij.execution.impl.InlayProvider,kotlin.jvm.functions.Function1):com.intellij.execution.impl.InlayDecoration
- *bs:buildInlay$default(com.intellij.execution.impl.EditorTextDecorationId,I,com.intellij.execution.impl.InlayProvider,kotlin.jvm.functions.Function1,I,java.lang.Object):com.intellij.execution.impl.InlayDecoration
- *sf:createEditorTextDecorationApplier(com.intellij.openapi.editor.ex.EditorEx,com.intellij.openapi.Disposable,Z):com.intellij.execution.impl.EditorTextDecorationApplier
- *bs:createEditorTextDecorationApplier$default(com.intellij.openapi.editor.ex.EditorEx,com.intellij.openapi.Disposable,Z,I,java.lang.Object):com.intellij.execution.impl.EditorTextDecorationApplier
- *sf:createEditorTextDecorationApplier(com.intellij.openapi.editor.ex.EditorEx,com.intellij.openapi.Disposable,kotlin.jvm.functions.Function1):com.intellij.execution.impl.EditorTextDecorationApplier
- *bs:createEditorTextDecorationApplier$default(com.intellij.openapi.editor.ex.EditorEx,com.intellij.openapi.Disposable,kotlin.jvm.functions.Function1,I,java.lang.Object):com.intellij.execution.impl.EditorTextDecorationApplier
- *sf:createTextDecorationId(J):com.intellij.execution.impl.EditorTextDecorationId
*:com.intellij.execution.impl.EditorTextDecorationId
- java.lang.Comparable
@@ -60,19 +60,43 @@ sealed interface EditorTextDecorationApplier {
* Creates a new decoration applier for the given editor.
*
* A parent disposable ensures that the applier unsubscribes from the editor listeners.
*
* @param consumeOnlyOnCtrlClick if `true`, a hyperlink click only consumes the mouse
* event when the modifier key (Cmd on macOS, Ctrl elsewhere) is pressed.
* Plain click on a visible link won't consume the mouse event and it will reach other listeners.
* Defaults to `false` - consume the mouse event it was somehow handled (either open the link or show the hint).
*/
@ApiStatus.Experimental
fun createEditorTextDecorationApplier(
editor: EditorEx,
parentDisposable: Disposable,
consumeOnlyOnCtrlClick: Boolean = false,
): EditorTextDecorationApplier =
EditorTextDecorationApplierImpl(editor, parentDisposable, consumeOnlyOnCtrlClick)
builder: (EditorTextDecorationApplierBuilder.() -> Unit)? = null,
): EditorTextDecorationApplier = EditorTextDecorationApplierBuilderImpl(editor, parentDisposable).run {
builder?.invoke(this)
build()
}
/**
* A builder to set optional attributes of an [EditorTextDecorationApplier] being created.
*
* An instance of a builder is passed to the function passed to [createEditorTextDecorationApplier] as the last parameter.
*/
@ApiStatus.Experimental
sealed interface EditorTextDecorationApplierBuilder {
/**
* If `true`, a hyperlink click only consumes the mouse
* event when the modifier key (Cmd on macOS, Ctrl elsewhere) is pressed.
* Plain click on a visible link won't consume the mouse event and it will reach other listeners.
* Defaults to `false` - consume the mouse event if it was somehow handled (either open the link or show the hint).
*/
var consumeOnlyOnCtrlClick: Boolean
}
private class EditorTextDecorationApplierBuilderImpl(
private val editor: EditorEx,
private val parentDisposable: Disposable,
) : EditorTextDecorationApplierBuilder {
override var consumeOnlyOnCtrlClick: Boolean = false
fun build(): EditorTextDecorationApplier {
return EditorTextDecorationApplierImpl(editor, parentDisposable, consumeOnlyOnCtrlClick)
}
}
/** The base interface for editor decorations. */
@ApiStatus.Experimental
@@ -260,9 +260,9 @@ class TerminalViewImpl(
// Should be created before "configureOutputEditor" is called where mouse reporting is configured (TerminalMouseEventsHandlerImpl).
// To make mouse events first handled by hyperlinks logic and only then reported to the process.
val alternateBufferDecorationApplier = createEditorTextDecorationApplier(
alternateBufferEditor, coroutineScope.asDisposable(), consumeOnlyOnCtrlClick = true,
)
val alternateBufferDecorationApplier = createEditorTextDecorationApplier(alternateBufferEditor, coroutineScope.asDisposable()) {
consumeOnlyOnCtrlClick = true
}
configureOutputEditor(
project,
editor = alternateBufferEditor,
@@ -315,9 +315,9 @@ class TerminalViewImpl(
// Should be created before "configureOutputEditor" is called where mouse reporting is configured (TerminalMouseEventsHandlerImpl).
// To make mouse events first handled by hyperlinks logic and only then reported to the process.
outputEditorDecorationApplier = createEditorTextDecorationApplier(
outputEditor, coroutineScope.asDisposable(), consumeOnlyOnCtrlClick = true,
)
outputEditorDecorationApplier = createEditorTextDecorationApplier(outputEditor, coroutineScope.asDisposable()) {
consumeOnlyOnCtrlClick = true
}
configureOutputEditor(
project,
editor = outputEditor,
@@ -649,7 +649,7 @@ internal class TerminalHyperlinksProcessingTest : BasePlatformTestCase() {
private val hyperlinkFacade = installHyperlinksProcessing(
project = project,
outputModel = outputModel,
decorationApplier = createEditorTextDecorationApplier(editor, coroutineScope.asDisposable(), consumeOnlyOnCtrlClick = true),
decorationApplier = createEditorTextDecorationApplier(editor, coroutineScope.asDisposable()) { consumeOnlyOnCtrlClick = true },
sessionModel = createSessionModel(),
eelDescriptor = LocalEelDescriptor,
coroutineScope = coroutineScope.childScope("HyperlinksProcessing")