fix(jetbrains): reconcile session layout cache

This commit is contained in:
kirillk
2026-08-03 16:55:50 -04:00
parent 6eba817857
commit 4cdbe9d325
2 changed files with 75 additions and 0 deletions
@@ -152,6 +152,33 @@ open class SessionLayoutPanel(
layout = SessionLayout(gap, pad)
}
override fun doLayout() {
super.doLayout()
reconcileValidateRoot()
}
/**
* Keep the parent [SessionLayout]'s cached height honest across validate-root boundaries.
*
* A validate root, such as a settled [ai.kilocode.client.session.views.TurnView], can be laid out
* independently by `RepaintManager`. Its `isValid` flag can flip back to `true` before the parent
* transcript remeasures it, so [SessionLayout] may otherwise keep stacking it at a stale cached
* height until some unrelated resize changes the cache key.
*
* Once this root has laid out its own content, its rendered height should match its preferred
* height. If it does not, the parent cache is stale: drop this entry and revalidate the parent so
* the outer transcript geometry follows the content. Non-roots are skipped because their
* invalidation already propagates to the parent and keeps `isValid` an honest cache signal.
*/
private fun reconcileValidateRoot() {
if (!isValidateRoot()) return
val host = parent ?: return
val layout = host.layout as? SessionLayout ?: return
if (preferredSize.height == height) return
layout.forget(this)
(host as? javax.swing.JComponent)?.revalidate()
}
override fun getScrollableTracksViewportWidth() = true
override fun getScrollableTracksViewportHeight() = false
override fun getPreferredScrollableViewportSize(): Dimension = preferredSize
@@ -361,6 +361,34 @@ class SessionLayoutTest : BasePlatformTestCase() {
assertEquals(sCount + 1, second.count)
}
fun `test validate root child reconciles stale parent cache after self layout`() {
val p = panel(width = 300)
val child = rootProbe(root = true)
p.add(child)
p.doLayout()
child.markValid()
child.preferred = 80
child.doLayout()
p.doLayout()
assertEquals(80, child.height)
}
fun `test non validate root child keeps parent cache until it invalidates upward`() {
val p = panel(width = 300)
val child = rootProbe(root = false)
p.add(child)
p.doLayout()
child.markValid()
child.preferred = 80
child.doLayout()
p.doLayout()
assertEquals(20, child.height)
}
// ---- helpers ------
/** A fixed-height JLabel. The width is reported as 0 until layout sets it. */
@@ -394,4 +422,24 @@ class SessionLayoutTest : BasePlatformTestCase() {
return Dimension(0, height)
}
}
private fun rootProbe(root: Boolean) = object : SessionLayoutPanel() {
var preferred = 20
private var valid = false
override fun isValid() = valid
override fun invalidate() {
valid = false
super.invalidate()
}
fun markValid() {
valid = true
}
override fun isValidateRoot() = root
override fun getPreferredSize(): Dimension = Dimension(0, preferred)
}
}