[terminal] IJPL-203233 Fix exception when height resize is performed right after width resize

Also, add more tests for tracking text buffer changes on resize.

GitOrigin-RevId: ceea725b485e75a10e073dfcfc60d4e9f2933e28
This commit is contained in:
Konstantin Hudyakov
2025-08-21 17:47:50 +00:00
committed by intellij-monorepo-bot
parent 992adf278f
commit a027b32550
2 changed files with 127 additions and 0 deletions
@@ -69,6 +69,7 @@ class TerminalContentChangesTracker(
// and it is not tracked now.
// TODO: consider tracking of the discarded lines in case of resizing to not replace everything.
lastChangedVisualLine = 0
anyLineChanged = true
}
})
}
@@ -7,6 +7,8 @@ import com.intellij.terminal.backend.TerminalDiscardedHistoryTracker
import com.intellij.terminal.tests.reworked.util.scrollDown
import com.intellij.terminal.tests.reworked.util.write
import com.intellij.testFramework.fixtures.BasePlatformTestCase
import com.jediterm.core.util.CellPosition
import com.jediterm.core.util.TermSize
import com.jediterm.terminal.model.StyleState
import com.jediterm.terminal.model.TerminalTextBuffer
import junit.framework.TestCase
@@ -175,6 +177,130 @@ internal class TerminalContentChangesTrackerTest : BasePlatformTestCase() {
TestCase.assertEquals(0, update.startLineLogicalIndex)
}
@Test
fun `check all text is reported after width increase`() {
val textBuffer = createTextBuffer(width = 10, height = 2, maxHistoryLinesCount = 2)
val contentChangesTracker = createChangesTracker(textBuffer)
// Prepare
textBuffer.write("first", 1, 0)
textBuffer.write("second", 2, 0)
textBuffer.scrollDown(1)
textBuffer.write("third", 2, 0)
textBuffer.scrollDown(1)
textBuffer.write("fourth", 2, 0)
contentChangesTracker.getContentUpdate()
textBuffer.resize(TermSize(12, 2), CellPosition(6, 2), null)
val update = contentChangesTracker.getContentUpdate() ?: error("Update is null")
val expectedText = """
first
second
third
fourth
""".trimIndent()
assertEquals(expectedText, update.text)
assertEquals(0, update.startLineLogicalIndex)
}
@Test
fun `check all text is reported after width decrease`() {
val textBuffer = createTextBuffer(width = 10, height = 2, maxHistoryLinesCount = 2)
val contentChangesTracker = createChangesTracker(textBuffer)
// Prepare
textBuffer.write("first", 1, 0)
textBuffer.write("second", 2, 0)
textBuffer.scrollDown(1)
textBuffer.write("third", 2, 0)
textBuffer.scrollDown(1)
textBuffer.write("fourth", 2, 0)
contentChangesTracker.getContentUpdate()
textBuffer.resize(TermSize(5, 2), CellPosition(6, 2), null)
val update = contentChangesTracker.getContentUpdate() ?: error("Update is null")
val expectedText = """
d
third
fourth
""".trimIndent()
assertEquals(expectedText, update.text)
assertEquals(0, update.startLineLogicalIndex)
}
@Test
fun `check update is flushed on history overflow after height decrease`() {
val textBuffer = createTextBuffer(width = 10, height = 3, maxHistoryLinesCount = 2)
val contentChangesTracker = createChangesTracker(textBuffer)
var update: TerminalContentUpdate? = null
contentChangesTracker.addHistoryOverflowListener {
update = it
}
textBuffer.write("first", 1, 0)
textBuffer.write("second", 2, 0)
textBuffer.write("third", 3, 0)
textBuffer.scrollDown(1)
textBuffer.write("fourth", 3, 0)
textBuffer.scrollDown(1)
textBuffer.write("fifth", 3, 0)
textBuffer.resize(TermSize(10, 2), CellPosition(5, 3), null)
update ?: error("Update is null")
val expectedText = """
first
second
third
fourth
fifth
""".trimIndent()
assertEquals(expectedText, update.text)
assertEquals(0, update.startLineLogicalIndex)
}
@Test
fun `check update is flushed on history overflow after width and height resize`() {
val textBuffer = createTextBuffer(width = 10, height = 3, maxHistoryLinesCount = 2)
val contentChangesTracker = createChangesTracker(textBuffer)
// Prepare
textBuffer.write("first", 1, 0)
textBuffer.write("second", 2, 0)
textBuffer.write("third", 3, 0)
textBuffer.scrollDown(1)
textBuffer.write("fourth", 3, 0)
textBuffer.scrollDown(1)
textBuffer.write("fifth", 3, 0)
contentChangesTracker.getContentUpdate()
var update: TerminalContentUpdate? = null
contentChangesTracker.addHistoryOverflowListener {
update = it
}
// Edit width first
textBuffer.resize(TermSize(12, 3), CellPosition(5, 3), null)
// Then edit height
textBuffer.resize(TermSize(12, 2), CellPosition(5, 3), null)
update ?: error("Update is null")
val expectedText = """
first
second
third
fourth
fifth
""".trimIndent()
assertEquals(expectedText, update.text)
assertEquals(0, update.startLineLogicalIndex)
}
@Suppress("SameParameterValue")
private fun createTextBuffer(width: Int, height: Int, maxHistoryLinesCount: Int): TerminalTextBuffer {
return TerminalTextBuffer(width, height, StyleState(), maxHistoryLinesCount)