From cfe8a8159eb120cd4e440ae1e96c1fae60ce065b Mon Sep 17 00:00:00 2001 From: Sergei Tachenov Date: Mon, 28 Jul 2025 15:40:15 +0300 Subject: [PATCH] [terminal] IJPL-178962 Hyperlinks: get rid of lists of events where not needed The whole List thing exists only on the higher level, and not even used for anything practical at the moment. Let's not propagate this approach to lower level stuff unless needed. This might be reverted if we actually start to process EDT events in bulks on the frontend side, then we can send several events at once. GitOrigin-RevId: 949dac5fb986be0a78c1a6afdd3008d984623f9f --- .../intellij/terminal/backend/StateAwareTerminalSession.kt | 7 ++++++- .../backend/hyperlinks/BackendTerminalHyperlinkFacade.kt | 2 +- .../hyperlinks/BackendTerminalHyperlinkHighlighter.kt | 6 +++--- .../backend/BackendTerminalHyperlinkHighlighterTest.kt | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/plugins/terminal/backend/src/com/intellij/terminal/backend/StateAwareTerminalSession.kt b/plugins/terminal/backend/src/com/intellij/terminal/backend/StateAwareTerminalSession.kt index 11ea5d961fee..856f94c4ea05 100644 --- a/plugins/terminal/backend/src/com/intellij/terminal/backend/StateAwareTerminalSession.kt +++ b/plugins/terminal/backend/src/com/intellij/terminal/backend/StateAwareTerminalSession.kt @@ -14,6 +14,7 @@ import kotlinx.coroutines.* import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.SendChannel import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.merge import org.jetbrains.plugins.terminal.block.reworked.* import org.jetbrains.plugins.terminal.block.reworked.hyperlinks.isSplitHyperlinksSupportEnabled @@ -92,7 +93,11 @@ internal class StateAwareTerminalSession( coroutineScope.launch(CoroutineName("StateAwareTerminalSession: models updating")) { val originalOutputFlow = if (outputHyperlinkFacade != null && alternateBufferHyperlinkFacade != null) { - merge(delegate.getOutputFlow(), outputHyperlinkFacade.resultFlow, alternateBufferHyperlinkFacade.resultFlow) + merge( + delegate.getOutputFlow(), + outputHyperlinkFacade.resultFlow.map { listOf(it) }, + alternateBufferHyperlinkFacade.resultFlow.map { listOf(it) }, + ) } else { delegate.getOutputFlow() diff --git a/plugins/terminal/backend/src/com/intellij/terminal/backend/hyperlinks/BackendTerminalHyperlinkFacade.kt b/plugins/terminal/backend/src/com/intellij/terminal/backend/hyperlinks/BackendTerminalHyperlinkFacade.kt index 724fe1aec1e7..0feedc591920 100644 --- a/plugins/terminal/backend/src/com/intellij/terminal/backend/hyperlinks/BackendTerminalHyperlinkFacade.kt +++ b/plugins/terminal/backend/src/com/intellij/terminal/backend/hyperlinks/BackendTerminalHyperlinkFacade.kt @@ -25,7 +25,7 @@ internal class BackendTerminalHyperlinkFacade( private val highlighter = BackendTerminalHyperlinkHighlighter(project, coroutineScope, outputModel, isInAlternateBuffer) private val model = TerminalHyperlinksModel(if (isInAlternateBuffer) "Backend AltBuf" else "Backend Output", outputModel) - val resultFlow: Flow> get() = highlighter.resultFlow + val resultFlow: Flow get() = highlighter.resultFlow fun updateModelState(event: TerminalHyperlinksChangedEvent): Boolean { if (event.documentModificationStamp < outputModel.document.modificationStamp) return false diff --git a/plugins/terminal/backend/src/com/intellij/terminal/backend/hyperlinks/BackendTerminalHyperlinkHighlighter.kt b/plugins/terminal/backend/src/com/intellij/terminal/backend/hyperlinks/BackendTerminalHyperlinkHighlighter.kt index 5325a1030214..a66d16d6fcff 100644 --- a/plugins/terminal/backend/src/com/intellij/terminal/backend/hyperlinks/BackendTerminalHyperlinkHighlighter.kt +++ b/plugins/terminal/backend/src/com/intellij/terminal/backend/hyperlinks/BackendTerminalHyperlinkHighlighter.kt @@ -45,7 +45,7 @@ internal class BackendTerminalHyperlinkHighlighter( private val highlightTask = MutableStateFlow(highlightAllTask()) private val filterWrapper = CompositeFilterWrapper(project, coroutineScope) - val resultFlow: Flow> + val resultFlow: Flow get() = channelFlow { val channel = this // asynchronous because we don't want to block the main event processing coroutine @@ -116,7 +116,7 @@ internal class BackendTerminalHyperlinkHighlighter( private val outputModel: FrozenTerminalOutputModel, val startOffset: TerminalOffset, ) { - suspend fun run(filter: CompositeFilter, channel: SendChannel>) { + suspend fun run(filter: CompositeFilter, channel: SendChannel) { val document = outputModel.document val firstID = hyperlinkId.get() + 1 var firstOffset: TerminalOffset? = null @@ -148,7 +148,7 @@ internal class BackendTerminalHyperlinkHighlighter( require(!(firstBatch && lastBatch)) if (results.isNotEmpty() || firstBatch || lastBatch) { val event = createEvent(results, firstBatch) - channel.send(listOf(event)) + channel.send(event) logEvent(event) } } diff --git a/plugins/terminal/backend/testSrc/com/intellij/terminal/backend/BackendTerminalHyperlinkHighlighterTest.kt b/plugins/terminal/backend/testSrc/com/intellij/terminal/backend/BackendTerminalHyperlinkHighlighterTest.kt index 89064faa59d7..133a6f276f08 100644 --- a/plugins/terminal/backend/testSrc/com/intellij/terminal/backend/BackendTerminalHyperlinkHighlighterTest.kt +++ b/plugins/terminal/backend/testSrc/com/intellij/terminal/backend/BackendTerminalHyperlinkHighlighterTest.kt @@ -315,7 +315,7 @@ internal class BackendTerminalHyperlinkHighlighterTest : BasePlatformTestCase() // do what StateAwareTerminalSession does, but with less infrastructure around val eventJob = launch(CoroutineName("BackendTerminalHyperlinkHighlighterTest event processing"), start = UNDISPATCHED) { - merge(updateEvents, backendFacade.resultFlow).collect { events -> + merge(updateEvents, backendFacade.resultFlow.map { listOf(it) }).collect { events -> events.forEach { event -> when (event) { is TerminalContentUpdatedEvent -> {