Skip to content

Commit 72f575f

Browse files
InfiniteRainintellij-monorepo-bot
authored andcommitted
PY-85090
[pycharm] PY-85090 Improve close detection for LoggingProcess [pycharm] PY-85090 Address feedback [pycharm] PY-85090 Add empty screen when contexts are selected [pycharm] PY-85090 Change expand/collapse all logic [pycharm] PY-85090 Improve collapse all/expand all logic [pycharm] PY-85090 Add bulk read override Merge-request: IJ-MR-179958 Merged-by: David Lysenko <[email protected]> GitOrigin-RevId: 00b7b0dd121eeebcb5920514ca8a535520f71160
1 parent 6287d2f commit 72f575f

4 files changed

Lines changed: 56 additions & 24 deletions

File tree

python/python-exec-service/src/com/intellij/python/community/execService/impl/logging.kt

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import com.intellij.openapi.components.Service
77
import com.intellij.openapi.components.service
88
import com.intellij.util.io.awaitExit
99
import com.intellij.util.io.readLineAsync
10+
import com.intellij.util.io.toByteArray
1011
import com.jetbrains.python.TraceContext
1112
import com.jetbrains.python.errorProcessing.Exe
1213
import kotlinx.coroutines.CoroutineScope
@@ -24,7 +25,9 @@ import java.io.IOException
2425
import java.io.InputStream
2526
import java.io.InputStreamReader
2627
import java.io.OutputStream
28+
import java.nio.ByteBuffer
2729
import java.util.concurrent.TimeUnit
30+
import java.util.concurrent.atomic.AtomicBoolean
2831
import java.util.concurrent.atomic.AtomicInteger
2932
import kotlin.time.Clock
3033
import kotlin.time.Instant
@@ -196,24 +199,17 @@ private class LoggingInputStream(
196199
) : InputStream() {
197200
private val bytes = ByteStreams.newDataOutput()
198201
private var tail = 0
202+
private var closed = AtomicBoolean(false)
199203

200204
val byteArray
201205
get() = bytes.toByteArray()
202206

203207
override fun read(): Int {
204-
val byte = try {
205-
backingInputStream.read()
208+
if (closed.get()) {
209+
return -1
206210
}
207-
catch (e: IOException) {
208-
// ugly hack; but the Process' `.destroy` methods abruptly close
209-
// the stream, making all pending readers throw an exception.
210-
// we can handle this case as legal here
211-
if (e.message == "Stream closed") {
212-
return -1
213-
}
214211

215-
throw e
216-
}
212+
val byte = backingInputStream.read()
217213

218214
if (tail < LoggingLimits.MAX_OUTPUT_SIZE && byte != -1) {
219215
bytes.write(byte)
@@ -222,6 +218,39 @@ private class LoggingInputStream(
222218

223219
return byte
224220
}
221+
222+
/**
223+
* Chunked read. The read bytes are also logged into the corresponding byte stream. If limit of [LoggingLimits.MAX_OUTPUT_SIZE] is
224+
* reached, then the logged bytes are truncated.
225+
*/
226+
override fun read(b: ByteArray, off: Int, len: Int): Int {
227+
if (closed.get()) {
228+
return -1
229+
}
230+
231+
val finalLen = backingInputStream.read(b, off, len)
232+
233+
if (finalLen != -1) {
234+
val truncatedLen = if (tail + finalLen > LoggingLimits.MAX_OUTPUT_SIZE) {
235+
LoggingLimits.MAX_OUTPUT_SIZE - tail
236+
}
237+
else {
238+
finalLen
239+
}
240+
241+
if (truncatedLen > 0) {
242+
bytes.write(b, off, truncatedLen)
243+
tail += truncatedLen
244+
}
245+
}
246+
247+
return finalLen
248+
}
249+
250+
override fun close() {
251+
closed.set(true)
252+
super.close()
253+
}
225254
}
226255

227256
private suspend fun collectOutputLines(

python/python-process-output/impl/src/com/intellij/python/processOutput/impl/ProcessOutputControllerService.kt

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ internal interface ProcessOutputController {
5757

5858
fun collapseAllContexts()
5959
fun expandAllContexts()
60-
fun selectProcess(process: LoggedProcess)
60+
fun selectProcess(process: LoggedProcess?)
6161
fun toggleTreeFilter(filter: TreeFilter)
6262
fun toggleOutputFilter(filter: OutputFilter)
6363
fun toggleProcessInfo()
@@ -185,26 +185,27 @@ class ProcessOutputControllerService(
185185
}
186186

187187
override fun collapseAllContexts() {
188-
processTreeUiState.treeState.openNodes.forEach {
189-
processTreeUiState.treeState.toggleNode(it)
190-
}
188+
processTreeUiState.treeState.openNodes = setOf()
191189

192190
ProcessOutputUsageCollector.treeCollapseAllClicked()
193191
}
194192

195193
override fun expandAllContexts() {
196-
loggedProcesses.value
197-
.mapNotNull { it.traceContext }
198-
.toSet()
199-
.subtract(processTreeUiState.treeState.openNodes)
200-
.forEach {
201-
processTreeUiState.treeState.toggleNode(it)
202-
}
194+
processTreeUiState.treeState.openNodes =
195+
processTreeUiState.tree.value
196+
.walkDepthFirst()
197+
.mapNotNull {
198+
when (val data = it.data) {
199+
is TreeNode.Context -> data.traceContext
200+
is TreeNode.Process -> null
201+
}
202+
}
203+
.toSet()
203204

204205
ProcessOutputUsageCollector.treeExpandAllClicked()
205206
}
206207

207-
override fun selectProcess(process: LoggedProcess) {
208+
override fun selectProcess(process: LoggedProcess?) {
208209
selectedProcess.value = process
209210
ProcessOutputUsageCollector.treeProcessSelected()
210211
}

python/python-process-output/impl/src/com/intellij/python/processOutput/impl/ui/components/TreeSection.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ internal fun TreeSection(controller: ProcessOutputController) {
9090

9191
if (node is TreeNode.Process) {
9292
controller.selectProcess(node.process)
93+
} else {
94+
controller.selectProcess(null)
9395
}
9496
},
9597
style = LazyTreeStyle(

python/python-process-output/impl/test/com/intellij/python/processOutput/impl/util.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ internal abstract class ProcessOutputTest {
7878
controllerSpy.expandAllContexts()
7979
}
8080

81-
override fun selectProcess(process: LoggedProcess) {
81+
override fun selectProcess(process: LoggedProcess?) {
8282
controllerSpy.selectProcess(process)
8383
}
8484

0 commit comments

Comments
 (0)