diff --git a/plugins/terminal/backend/src/com/intellij/terminal/backend/TerminalSessionStart.kt b/plugins/terminal/backend/src/com/intellij/terminal/backend/TerminalSessionStart.kt index 9c80b394fe74..35b4420da4d2 100644 --- a/plugins/terminal/backend/src/com/intellij/terminal/backend/TerminalSessionStart.kt +++ b/plugins/terminal/backend/src/com/intellij/terminal/backend/TerminalSessionStart.kt @@ -6,6 +6,7 @@ import com.intellij.openapi.project.Project import com.intellij.platform.util.coroutines.childScope import com.intellij.terminal.JBTerminalSystemSettingsProviderBase import com.intellij.terminal.TerminalExecutorServiceManagerImpl +import com.intellij.terminal.backend.fus.enableFus import com.intellij.terminal.session.TerminalSession import com.intellij.terminal.session.TerminalSessionTerminatedEvent import com.intellij.util.AwaitCancellationAndInvoke @@ -24,7 +25,6 @@ import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.launch import org.jetbrains.plugins.terminal.FusAwareTtyBasedDataStream import org.jetbrains.plugins.terminal.LocalBlockTerminalRunner -import org.jetbrains.plugins.terminal.LocalTerminalTtyConnector import org.jetbrains.plugins.terminal.ShellStartupOptions import org.jetbrains.plugins.terminal.fus.BackendOutputActivity import org.jetbrains.plugins.terminal.util.STOP_EMULATOR_TIMEOUT @@ -55,9 +55,9 @@ internal fun createTerminalSession( coroutineScope: CoroutineScope, fusActivity: BackendOutputActivity, ): TerminalSession { - ttyConnector.startStatisticsReporting(fusActivity) + val connector = enableFus(ttyConnector, fusActivity) val maxHistoryLinesCount = AdvancedSettings.getInt("terminal.buffer.max.lines.count") - val services: JediTermServices = createJediTermServices(ttyConnector, fusActivity, initialSize, maxHistoryLinesCount, settings) + val services: JediTermServices = createJediTermServices(connector, fusActivity, initialSize, maxHistoryLinesCount, settings) val outputScope = coroutineScope.childScope("Terminal output forwarding") val shellIntegrationController = TerminalShellIntegrationController(services.controller) @@ -100,7 +100,7 @@ internal fun createTerminalSession( } private fun createJediTermServices( - connector: LocalTerminalTtyConnector, + connector: TtyConnector, fusActivity: BackendOutputActivity, termSize: TermSize, maxHistoryLinesCount: Int, diff --git a/plugins/terminal/backend/src/com/intellij/terminal/backend/fus/BackendLatencyServiceImpl.kt b/plugins/terminal/backend/src/com/intellij/terminal/backend/fus/BackendLatencyServiceImpl.kt index 3f63463f0dfa..05c3258a6a16 100644 --- a/plugins/terminal/backend/src/com/intellij/terminal/backend/fus/BackendLatencyServiceImpl.kt +++ b/plugins/terminal/backend/src/com/intellij/terminal/backend/fus/BackendLatencyServiceImpl.kt @@ -4,8 +4,11 @@ import com.intellij.openapi.diagnostic.logger import com.intellij.platform.rpc.UID import com.intellij.terminal.session.TerminalContentUpdatedEvent import com.intellij.terminal.session.TerminalWriteBytesEvent +import com.jediterm.core.util.TermSize +import com.jediterm.terminal.TtyConnector import fleet.multiplatform.shims.ConcurrentHashMap import org.jetbrains.plugins.terminal.fus.BackendLatencyService +import org.jetbrains.plugins.terminal.fus.BackendLatencyService.Companion.getInstance import org.jetbrains.plugins.terminal.fus.BackendOutputActivity import org.jetbrains.plugins.terminal.fus.BackendTypingActivity import org.jetbrains.plugins.terminal.fus.ReworkedTerminalUsageCollector @@ -32,6 +35,9 @@ internal class BackendLatencyServiceImpl : BackendLatencyService { } } +internal fun enableFus(ttyConnector: TtyConnector, fusActivity: BackendOutputActivity): TtyConnector = + FusAwareTtyConnector(ttyConnector, fusActivity) + private val backendTypingActivityByByteArray = ConcurrentHashMap() private class BackendTypingActivityImpl(override val id: Int, private val bytes: ByteArray) : BackendTypingActivity { @@ -285,6 +291,43 @@ private class BackendOutputActivityImpl : BackendOutputActivity { } } +private class FusAwareTtyConnector(private val original: TtyConnector, private val outputActivity: BackendOutputActivity) : TtyConnector { + override fun read(buf: CharArray, offset: Int, length: Int): Int = original.read(buf, offset, length).also { charsRead -> + outputActivity.charsRead(charsRead) + } + + override fun write(bytes: ByteArray) { + val typingActivity = getInstance().getBackendTypingActivityOrNull(bytes) + try { + original.write(bytes) + typingActivity?.reportDuration() + } + finally { + typingActivity?.finishBytesProcessing() + } + } + + override fun write(string: String) { + original.write(string) + } + + override fun isConnected(): Boolean = original.isConnected + + override fun waitFor(): Int = original.waitFor() + + override fun ready(): Boolean = original.ready() + + override fun getName(): String? = original.name + + override fun close() { + original.close() + } + + override fun resize(termSize: TermSize) { + original.resize(termSize) + } +} + // used to track individual instances of data classes private class IdentityWrapper(private val instance: T) { override fun equals(other: Any?): Boolean = instance === (other as? IdentityWrapper)?.instance diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/FusAwareTtyBasedDataStream.kt b/plugins/terminal/src/org/jetbrains/plugins/terminal/FusAwareTtyBasedDataStream.kt index 3c2a4e89eabe..495f3df86904 100644 --- a/plugins/terminal/src/org/jetbrains/plugins/terminal/FusAwareTtyBasedDataStream.kt +++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/FusAwareTtyBasedDataStream.kt @@ -2,12 +2,13 @@ package org.jetbrains.plugins.terminal import com.jediterm.terminal.TtyBasedArrayDataStream +import com.jediterm.terminal.TtyConnector import org.jetbrains.annotations.ApiStatus import org.jetbrains.plugins.terminal.fus.BackendOutputActivity @ApiStatus.Internal class FusAwareTtyBasedDataStream( - connector: LocalTerminalTtyConnector, + connector: TtyConnector, private val fusActivity: BackendOutputActivity, ) : TtyBasedArrayDataStream(connector) { diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalTtyConnector.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalTtyConnector.java index e856e8f65b40..eabec7ce2806 100644 --- a/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalTtyConnector.java +++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalTtyConnector.java @@ -9,11 +9,7 @@ import com.pty4j.PtyProcess; import com.pty4j.unix.UnixPtyProcess; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.terminal.fus.BackendLatencyService; -import org.jetbrains.plugins.terminal.fus.BackendOutputActivity; -import java.io.IOException; import java.nio.charset.Charset; import java.util.concurrent.TimeUnit; @@ -21,42 +17,12 @@ import java.util.concurrent.TimeUnit; public class LocalTerminalTtyConnector extends PtyProcessTtyConnector { private static final Logger LOG = Logger.getInstance(LocalTerminalTtyConnector.class); private final @NotNull PtyProcess myProcess; - private @Nullable BackendOutputActivity fusActivity; LocalTerminalTtyConnector(@NotNull PtyProcess process, @NotNull Charset charset) { super(process, charset); myProcess = process; } - public void startStatisticsReporting(@NotNull BackendOutputActivity fusActivity) { - this.fusActivity = fusActivity; - } - - @Override - public int read(char[] buf, int offset, int length) throws IOException { - var fusActivity = this.fusActivity; - var charsRead = super.read(buf, offset, length); - if (fusActivity == null) return charsRead; - fusActivity.charsRead(charsRead); - return charsRead; - } - - @Override - public void write(byte[] bytes) throws IOException { - var fusActivity = BackendLatencyService.getInstance().getBackendTypingActivityOrNull(bytes); - try { - super.write(bytes); - if (fusActivity != null) { - fusActivity.reportDuration(); - } - } - finally { - if (fusActivity != null) { - fusActivity.finishBytesProcessing(); - } - } - } - @Override public void close() { if (myProcess instanceof UnixPtyProcess) {