mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-10-28 02:42:15 +08:00
fix(jetbrains): stabilize worktree list updates
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@kilocode/kilo-jetbrains": patch
|
||||
---
|
||||
|
||||
Improve Agent Manager worktree activity refreshes and keep worktree list filtering responsive.
|
||||
+1
-1
@@ -45,9 +45,9 @@ class KiloBackendActivityManager(
|
||||
directory: (String) -> String?,
|
||||
chatEvents: SharedFlow<ChatEventDto>,
|
||||
) {
|
||||
if (status?.isActive == true || events?.isActive == true) stop()
|
||||
this.statuses = statuses
|
||||
this.directory = directory
|
||||
if (status?.isActive == true || events?.isActive == true) return
|
||||
status = cs.launch {
|
||||
statuses.collect { synchronized(lock) { recompute() } }
|
||||
}
|
||||
|
||||
+17
@@ -103,6 +103,23 @@ class KiloBackendActivityManagerTest {
|
||||
assertFalse("ses_unknown" in snap)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `start rebinds collectors to the latest flows`() = runBlocking {
|
||||
val nextStatuses = MutableStateFlow<Map<String, SessionStatusDto>>(emptyMap())
|
||||
val nextEvents = MutableSharedFlow<ChatEventDto>(extraBufferCapacity = 16)
|
||||
directories["ses_old"] = "/repo/old"
|
||||
directories["ses_new"] = "/repo/new"
|
||||
start()
|
||||
|
||||
manager.start(nextStatuses, { directories[it] }, nextEvents)
|
||||
statuses.value = mapOf("ses_old" to SessionStatusDto("busy"))
|
||||
nextStatuses.value = mapOf("ses_new" to SessionStatusDto("busy"))
|
||||
|
||||
val snap = await("ses_new", SessionActivityKindDto.RUNNING)
|
||||
assertFalse("ses_old" in snap)
|
||||
assertEquals("/repo/new", snap["ses_new"]?.directory)
|
||||
}
|
||||
|
||||
private suspend fun await(id: String, kind: SessionActivityKindDto) = withTimeout(5_000) {
|
||||
manager.activity.first { it[id]?.kind == kind }
|
||||
}
|
||||
|
||||
+1
-9
@@ -1,6 +1,7 @@
|
||||
package ai.kilocode.client.agentManager.worktree
|
||||
|
||||
import ai.kilocode.client.telemetry.Telemetry
|
||||
import ai.kilocode.client.util.edt
|
||||
import ai.kilocode.client.session.SessionActivityKind
|
||||
import ai.kilocode.rpc.dto.CreateWorktreeRequestDto
|
||||
import ai.kilocode.rpc.dto.RemoveWorktreeResultDto
|
||||
@@ -226,12 +227,3 @@ class WorktreeController(
|
||||
return ApplicationManager.getApplication().service()
|
||||
}
|
||||
}
|
||||
|
||||
private fun edt(block: () -> Unit) {
|
||||
val app = ApplicationManager.getApplication()
|
||||
if (app.isDispatchThread) {
|
||||
block()
|
||||
return
|
||||
}
|
||||
app.invokeLater(block)
|
||||
}
|
||||
|
||||
+4
@@ -16,6 +16,7 @@ class WorktreeNameCache {
|
||||
private val names = linkedMapOf<String, String>()
|
||||
private val listeners = mutableListOf<(String, String?) -> Unit>()
|
||||
|
||||
@RequiresEdt
|
||||
fun get(path: String): String? = names[path]
|
||||
|
||||
@RequiresEdt
|
||||
@@ -33,6 +34,7 @@ class WorktreeNameCache {
|
||||
if (names.remove(path) != null) fire(path, null)
|
||||
}
|
||||
|
||||
@RequiresEdt
|
||||
fun clear() {
|
||||
names.clear()
|
||||
}
|
||||
@@ -41,10 +43,12 @@ class WorktreeNameCache {
|
||||
* Bulk sync from a worktree list reload. Does not notify: it mirrors the list model that
|
||||
* triggered it, so notifying would only echo back into that same list.
|
||||
*/
|
||||
@RequiresEdt
|
||||
fun putAll(items: List<WorktreeDto>) {
|
||||
items.forEach { names[it.path] = it.name }
|
||||
}
|
||||
|
||||
@RequiresEdt
|
||||
fun addListener(parent: Disposable, listener: (path: String, name: String?) -> Unit) {
|
||||
listeners.add(listener)
|
||||
Disposer.register(parent) { listeners.remove(listener) }
|
||||
|
||||
+1
-5
@@ -15,6 +15,7 @@ import ai.kilocode.client.session.history.HistoryTime
|
||||
import ai.kilocode.client.session.history.LocalHistoryItem
|
||||
import ai.kilocode.client.util.UiTimerSource
|
||||
import ai.kilocode.client.util.UiTimers
|
||||
import ai.kilocode.client.util.edt
|
||||
import ai.kilocode.client.vfs.KiloVfsManager
|
||||
import ai.kilocode.rpc.dto.RenameWorktreeResultDto
|
||||
import ai.kilocode.rpc.dto.SessionDto
|
||||
@@ -253,11 +254,6 @@ open class WorktreeSessionEditorManager(
|
||||
}
|
||||
}
|
||||
|
||||
private fun edt(block: () -> Unit) {
|
||||
val app = ApplicationManager.getApplication()
|
||||
if (app.isDispatchThread) block() else app.invokeLater(block)
|
||||
}
|
||||
|
||||
// Mirrors the CLI's Session.isDefaultTitle (packages/opencode/src/session/session.ts): a session
|
||||
// keeps a "New session - <ISO>" / "Child session - <ISO>" placeholder until the agent names it.
|
||||
private val DEFAULT_SESSION_TITLE =
|
||||
|
||||
+1
-10
@@ -2,9 +2,9 @@ package ai.kilocode.client.agentManager.worktree
|
||||
|
||||
import ai.kilocode.client.app.KiloSessionService
|
||||
import ai.kilocode.client.telemetry.Telemetry
|
||||
import ai.kilocode.client.util.edt
|
||||
import ai.kilocode.log.KiloLog
|
||||
import ai.kilocode.rpc.dto.SessionDto
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.ui.CollectionListModel
|
||||
import com.intellij.util.concurrency.annotations.RequiresEdt
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -125,12 +125,3 @@ class WorktreeSessionListController(
|
||||
return (0 until model.size).firstOrNull { model.getElementAt(it).id == id } ?: -1
|
||||
}
|
||||
}
|
||||
|
||||
private fun edt(block: () -> Unit) {
|
||||
val app = ApplicationManager.getApplication()
|
||||
if (app.isDispatchThread) {
|
||||
block()
|
||||
return
|
||||
}
|
||||
app.invokeLater(block)
|
||||
}
|
||||
|
||||
+1
-10
@@ -2,8 +2,8 @@ package ai.kilocode.client.session.controller
|
||||
|
||||
import ai.kilocode.client.util.UiTimerSource
|
||||
import ai.kilocode.client.util.UiTimers
|
||||
import ai.kilocode.client.util.edt
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
|
||||
internal class DelayedState(
|
||||
private val ms: Long,
|
||||
@@ -62,15 +62,6 @@ internal class DelayedState(
|
||||
return now + ms.coerceAtMost(Long.MAX_VALUE - now)
|
||||
}
|
||||
|
||||
private fun edt(block: () -> Unit) {
|
||||
val app = ApplicationManager.getApplication()
|
||||
if (app.isDispatchThread) {
|
||||
block()
|
||||
return
|
||||
}
|
||||
app.invokeLater(block)
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
alive = false
|
||||
cancel()
|
||||
|
||||
+1
-4
@@ -28,6 +28,7 @@ import ai.kilocode.client.telemetry.Telemetry
|
||||
import ai.kilocode.client.util.UiTimer
|
||||
import ai.kilocode.client.util.UiTimerSource
|
||||
import ai.kilocode.client.util.UiTimers
|
||||
import ai.kilocode.client.util.edtLater as edt
|
||||
import ai.kilocode.rpc.dto.ChatEventDto
|
||||
import ai.kilocode.rpc.dto.ConfigWarningDto
|
||||
import ai.kilocode.rpc.dto.ConfigUpdateDto
|
||||
@@ -2322,10 +2323,6 @@ class SessionController(
|
||||
check(ApplicationManager.getApplication().isDispatchThread) { "SessionController state must be accessed on EDT" }
|
||||
}
|
||||
|
||||
private fun edt(block: () -> Unit) {
|
||||
ApplicationManager.getApplication().invokeLater(block)
|
||||
}
|
||||
|
||||
private fun runEdt(block: () -> Unit) {
|
||||
val application = ApplicationManager.getApplication()
|
||||
if (application.isDispatchThread) {
|
||||
|
||||
+6
-17
@@ -1,10 +1,10 @@
|
||||
package ai.kilocode.client.session.controller
|
||||
|
||||
import ai.kilocode.client.util.edt
|
||||
import ai.kilocode.log.ChatLogSummary
|
||||
import ai.kilocode.log.KiloLog
|
||||
import ai.kilocode.rpc.dto.ChatEventDto
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import java.awt.Component
|
||||
import java.awt.event.HierarchyEvent
|
||||
@@ -33,7 +33,6 @@ internal class SessionUpdateQueue(
|
||||
private val LOG = KiloLog.create(SessionUpdateQueue::class.java)
|
||||
}
|
||||
|
||||
private val app = ApplicationManager.getApplication()
|
||||
private val condenser = SessionQueueCondenser()
|
||||
private val pending = mutableListOf<ChatEventDto>()
|
||||
private val lock = Any()
|
||||
@@ -58,7 +57,7 @@ internal class SessionUpdateQueue(
|
||||
|
||||
init {
|
||||
Disposer.register(parent, this)
|
||||
if (comp != null && watch != null) edt {
|
||||
if (comp != null && watch != null) run {
|
||||
visible.set(comp.isShowing)
|
||||
comp.addHierarchyListener(watch)
|
||||
}
|
||||
@@ -81,7 +80,7 @@ internal class SessionUpdateQueue(
|
||||
|
||||
fun holdFlush(hold: Boolean) {
|
||||
if (disposed.get()) return
|
||||
edt {
|
||||
run {
|
||||
LOG.debug { "${ChatLogSummary.sid(sid())} hold=$hold" }
|
||||
this.hold = hold
|
||||
}
|
||||
@@ -90,7 +89,7 @@ internal class SessionUpdateQueue(
|
||||
fun requestFlush(forced: Boolean, source: String = "api") {
|
||||
if (disposed.get()) return
|
||||
if (!forced && !visible.get()) return
|
||||
edt { flushNow(forced, source) }
|
||||
run { flushNow(forced, source) }
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
@@ -102,7 +101,7 @@ internal class SessionUpdateQueue(
|
||||
if (comp != null && watch != null) comp.removeHierarchyListener(watch)
|
||||
synchronized(lock) { pending.clear() }
|
||||
}
|
||||
if (app.isDispatchThread) cleanup() else app.invokeLater(cleanup)
|
||||
edt(cleanup)
|
||||
}
|
||||
|
||||
private fun flushNow(forced: Boolean, source: String) {
|
||||
@@ -133,15 +132,5 @@ internal class SessionUpdateQueue(
|
||||
requestFlush(true, "visible")
|
||||
}
|
||||
|
||||
private fun edt(block: () -> Unit) {
|
||||
if (disposed.get()) return
|
||||
if (app.isDispatchThread) {
|
||||
block()
|
||||
return
|
||||
}
|
||||
app.invokeLater {
|
||||
if (disposed.get()) return@invokeLater
|
||||
block()
|
||||
}
|
||||
}
|
||||
private fun run(block: () -> Unit) = edt({ !disposed.get() }, block)
|
||||
}
|
||||
|
||||
+1
-10
@@ -5,9 +5,9 @@ import ai.kilocode.client.app.Workspace
|
||||
import ai.kilocode.client.plugin.KiloBundle
|
||||
import ai.kilocode.client.session.SessionRef
|
||||
import ai.kilocode.client.telemetry.Telemetry
|
||||
import ai.kilocode.client.util.edt
|
||||
import ai.kilocode.rpc.dto.CloudSessionDto
|
||||
import ai.kilocode.rpc.dto.SessionDto
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -222,15 +222,6 @@ class HistoryController(
|
||||
}
|
||||
}
|
||||
|
||||
private fun edt(block: () -> Unit) {
|
||||
val app = ApplicationManager.getApplication()
|
||||
if (app.isDispatchThread) {
|
||||
block()
|
||||
return
|
||||
}
|
||||
app.invokeLater(block)
|
||||
}
|
||||
|
||||
private fun localItem(session: SessionDto) = LocalHistoryItem(session)
|
||||
|
||||
private fun cloudItem(session: CloudSessionDto) = CloudHistoryItem(session)
|
||||
|
||||
+66
-29
@@ -87,6 +87,7 @@ internal class ActiveListView(
|
||||
private var press: Press? = null
|
||||
private var popups = 0
|
||||
private var hovered = -1
|
||||
private var heightKey: ActiveListHeightKey? = null
|
||||
internal var onSelect: (() -> Unit)? = null
|
||||
|
||||
fun setEmptyText(text: String) {
|
||||
@@ -271,6 +272,7 @@ internal class ActiveListView(
|
||||
@RequiresEdt
|
||||
fun update(items: List<ActiveListItem>, selection: ActiveListSelection = ActiveListSelection.Preserve) {
|
||||
checkEdt()
|
||||
if (this.items != items) heightKey = null
|
||||
this.items = items
|
||||
val key = when (selection) {
|
||||
is ActiveListSelection.Key -> selection.key
|
||||
@@ -301,40 +303,13 @@ internal class ActiveListView(
|
||||
@RequiresEdt
|
||||
fun trackPopup(popup: JBPopup) {
|
||||
checkEdt()
|
||||
var tracked = false
|
||||
fun activate() {
|
||||
if (tracked) return
|
||||
tracked = true
|
||||
popups++
|
||||
list.repaint()
|
||||
}
|
||||
popup.addListener(object : JBPopupListener {
|
||||
override fun beforeShown(event: LightweightWindowEvent) = activate()
|
||||
|
||||
override fun onClosed(event: LightweightWindowEvent) {
|
||||
if (!tracked) return
|
||||
tracked = false
|
||||
popups = maxOf(0, popups - 1)
|
||||
list.repaint()
|
||||
}
|
||||
})
|
||||
if (popup.isVisible) activate()
|
||||
trackPopupState(popup.isVisible) { listener -> popup.addListener(listener) }
|
||||
}
|
||||
|
||||
@RequiresEdt
|
||||
fun trackBalloon(balloon: Balloon) {
|
||||
checkEdt()
|
||||
var tracked = true
|
||||
popups++
|
||||
list.repaint()
|
||||
balloon.addListener(object : JBPopupListener {
|
||||
override fun onClosed(event: LightweightWindowEvent) {
|
||||
if (!tracked) return
|
||||
tracked = false
|
||||
popups = maxOf(0, popups - 1)
|
||||
list.repaint()
|
||||
}
|
||||
})
|
||||
trackPopupState(true) { listener -> balloon.addListener(listener) }
|
||||
}
|
||||
|
||||
@RequiresEdt
|
||||
@@ -380,6 +355,9 @@ internal class ActiveListView(
|
||||
@RequiresEdt
|
||||
private fun syncCellHeight(rows: List<ActiveListItem>) {
|
||||
checkEdt()
|
||||
val key = ActiveListHeightKey(cfg, list.width, rows.map(::activeListHeightRow))
|
||||
if (heightKey == key) return
|
||||
heightKey = key
|
||||
renderer.setBodyHeight(null)
|
||||
if (cfg.height == ActiveListRowHeight.PREFERRED) {
|
||||
if (list.fixedCellHeight == -1) return
|
||||
@@ -503,6 +481,27 @@ internal class ActiveListView(
|
||||
return Hit(item, id)
|
||||
}
|
||||
|
||||
private fun trackPopupState(visible: Boolean, add: (JBPopupListener) -> Unit) {
|
||||
var tracked = false
|
||||
fun activate() {
|
||||
if (tracked) return
|
||||
tracked = true
|
||||
popups++
|
||||
list.repaint()
|
||||
}
|
||||
add(object : JBPopupListener {
|
||||
override fun beforeShown(event: LightweightWindowEvent) = activate()
|
||||
|
||||
override fun onClosed(event: LightweightWindowEvent) {
|
||||
if (!tracked) return
|
||||
tracked = false
|
||||
popups = maxOf(0, popups - 1)
|
||||
list.repaint()
|
||||
}
|
||||
})
|
||||
if (visible) activate()
|
||||
}
|
||||
|
||||
private fun checkEdt() {
|
||||
check(ApplicationManager.getApplication().isDispatchThread) { "Active list updates must run on EDT" }
|
||||
}
|
||||
@@ -546,6 +545,42 @@ internal class ActiveListView(
|
||||
|
||||
private data class Press(val key: String, val id: String)
|
||||
|
||||
private data class ActiveListHeightKey(
|
||||
val cfg: ActiveListConfig,
|
||||
val width: Int,
|
||||
val rows: List<ActiveListHeightRow>,
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
private data class ActiveListHeightRow(
|
||||
val key: String,
|
||||
val title: String,
|
||||
val note: String?,
|
||||
val description: String?,
|
||||
val icon: Any?,
|
||||
val section: String?,
|
||||
val badges: List<ActiveListBadge>,
|
||||
val trailing: String?,
|
||||
val cells: List<ActiveListCell>,
|
||||
val disabled: Boolean,
|
||||
val deleting: Boolean,
|
||||
)
|
||||
|
||||
private fun activeListHeightRow(item: ActiveListItem): ActiveListHeightRow {
|
||||
return ActiveListHeightRow(
|
||||
item.key,
|
||||
item.title,
|
||||
item.note,
|
||||
item.description,
|
||||
item.icon,
|
||||
item.section,
|
||||
item.badges,
|
||||
item.trailing,
|
||||
item.cells,
|
||||
item.disabled,
|
||||
item.deleting,
|
||||
)
|
||||
}
|
||||
|
||||
private fun activeListIndex(items: List<ActiveListItem>, key: String?): Int {
|
||||
@@ -582,9 +617,11 @@ private fun activeListTextMatches(query: String, text: String): Boolean {
|
||||
|
||||
private fun activeListAcronym(text: String, query: String): Boolean {
|
||||
val words = activeListWords(text)
|
||||
val seen = HashSet<Pair<Int, Int>>()
|
||||
fun attempt(wi: Int, qi: Int): Boolean {
|
||||
if (qi == query.length) return true
|
||||
if (wi >= words.size) return false
|
||||
if (!seen.add(wi to qi)) return false
|
||||
val word = words[wi]
|
||||
var count = 0
|
||||
while (qi + count < query.length && count < word.length && word[count] == query[qi + count]) {
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package ai.kilocode.client.util
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
|
||||
internal fun edt(block: () -> Unit) {
|
||||
val app = ApplicationManager.getApplication()
|
||||
if (app.isDispatchThread) {
|
||||
block()
|
||||
return
|
||||
}
|
||||
app.invokeLater(block)
|
||||
}
|
||||
|
||||
internal fun edt(alive: () -> Boolean, block: () -> Unit) {
|
||||
if (!alive()) return
|
||||
val app = ApplicationManager.getApplication()
|
||||
if (app.isDispatchThread) {
|
||||
if (alive()) block()
|
||||
return
|
||||
}
|
||||
app.invokeLater {
|
||||
if (alive()) block()
|
||||
}
|
||||
}
|
||||
|
||||
internal fun edtLater(block: () -> Unit) {
|
||||
ApplicationManager.getApplication().invokeLater(block)
|
||||
}
|
||||
|
||||
internal fun <T> edtWait(block: () -> T): T {
|
||||
val app = ApplicationManager.getApplication()
|
||||
if (app.isDispatchThread) return block()
|
||||
var out: T? = null
|
||||
app.invokeAndWait { out = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return out as T
|
||||
}
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.agentManager
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.agentManager.worktree.KiloWorktreeService
|
||||
import ai.kilocode.client.agentManager.worktree.WorktreeController
|
||||
import ai.kilocode.client.agentManager.worktree.WorktreeEditorMatcher
|
||||
@@ -408,12 +409,7 @@ class AgentManagerPanelTest : BasePlatformTestCase() {
|
||||
flush()
|
||||
}
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
val out = arrayOfNulls<Any?>(1)
|
||||
ApplicationManager.getApplication().invokeAndWait { out[0] = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return out[0] as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
|
||||
private fun flush() = coroutines.drain(::pump)
|
||||
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
package ai.kilocode.client.agentManager.worktree
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.rpc.dto.WorktreeDto
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.testFramework.fixtures.BasePlatformTestCase
|
||||
|
||||
@Suppress("UnstableApiUsage")
|
||||
class WorktreeNameCacheTest : BasePlatformTestCase() {
|
||||
override fun tearDown() {
|
||||
try {
|
||||
edt { cache().clear() }
|
||||
} finally {
|
||||
super.tearDown()
|
||||
}
|
||||
}
|
||||
|
||||
fun `test put and remove notify only when value changes`() = edt {
|
||||
val events = mutableListOf<Pair<String, String?>>()
|
||||
cache().addListener(testRootDisposable) { path, name -> events += path to name }
|
||||
|
||||
cache().put("/repo/wt", "First")
|
||||
cache().put("/repo/wt", "First")
|
||||
cache().put("/repo/wt", "Second")
|
||||
cache().remove("/repo/wt")
|
||||
cache().remove("/repo/wt")
|
||||
|
||||
assertEquals(
|
||||
listOf("/repo/wt" to "First", "/repo/wt" to "Second", "/repo/wt" to null),
|
||||
events,
|
||||
)
|
||||
}
|
||||
|
||||
fun `test bulk sync updates names without notifying`() = edt {
|
||||
val events = mutableListOf<Pair<String, String?>>()
|
||||
cache().addListener(testRootDisposable) { path, name -> events += path to name }
|
||||
|
||||
cache().putAll(listOf(WorktreeDto("/repo/wt", "Feature", "feature/x", "/repo/wt")))
|
||||
|
||||
assertEquals("Feature", cache().get("/repo/wt"))
|
||||
assertTrue(events.isEmpty())
|
||||
}
|
||||
|
||||
fun `test listener is removed with parent disposable`() = edt {
|
||||
val parent = Disposer.newDisposable("worktree-cache-listener")
|
||||
Disposer.register(testRootDisposable, parent)
|
||||
val events = mutableListOf<Pair<String, String?>>()
|
||||
cache().addListener(parent) { path, name -> events += path to name }
|
||||
|
||||
cache().put("/repo/one", "One")
|
||||
Disposer.dispose(parent)
|
||||
cache().put("/repo/two", "Two")
|
||||
|
||||
assertEquals(listOf("/repo/one" to "One"), events)
|
||||
}
|
||||
|
||||
private fun cache(): WorktreeNameCache = ApplicationManager.getApplication().service()
|
||||
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
}
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.agentManager.worktree
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.app.KiloAppService
|
||||
import ai.kilocode.client.app.KiloSessionService
|
||||
import ai.kilocode.client.app.KiloWorkspaceService
|
||||
@@ -373,12 +374,7 @@ class WorktreeSessionEditorManagerTest : BasePlatformTestCase() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
val out = arrayOfNulls<Any?>(1)
|
||||
com.intellij.openapi.application.ApplicationManager.getApplication().invokeAndWait { out[0] = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return out[0] as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
|
||||
private companion object {
|
||||
const val DIR = "/repo/.kilo/worktrees/feature-x"
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.agentManager.worktree
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.app.KiloSessionService
|
||||
import ai.kilocode.client.app.Workspace
|
||||
import ai.kilocode.client.session.SessionActivityKind
|
||||
@@ -405,12 +406,7 @@ class WorktreeSessionEditorPanelTest : BasePlatformTestCase() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
val out = arrayOfNulls<Any?>(1)
|
||||
com.intellij.openapi.application.ApplicationManager.getApplication().invokeAndWait { out[0] = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return out[0] as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
|
||||
private fun components(root: java.awt.Component): List<java.awt.Component> {
|
||||
val out = mutableListOf<java.awt.Component>()
|
||||
|
||||
+2
-3
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.session.controller
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.testing.TestUiTimers
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.util.Disposer
|
||||
@@ -138,7 +139,5 @@ class DelayedStateTest : BasePlatformTestCase() {
|
||||
return state
|
||||
}
|
||||
|
||||
private fun edt(block: () -> Unit) {
|
||||
ApplicationManager.getApplication().invokeAndWait(block)
|
||||
}
|
||||
private fun edt(block: () -> Unit) = edtWait(block)
|
||||
}
|
||||
|
||||
+3
-9
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.session.controller
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.app.KiloAppService
|
||||
import ai.kilocode.client.app.KiloSessionService
|
||||
import ai.kilocode.client.session.model.SessionModel
|
||||
@@ -267,16 +268,9 @@ abstract class SessionControllerTestBase : BasePlatformTestCase() {
|
||||
}
|
||||
}
|
||||
|
||||
protected fun edt(block: () -> Unit) {
|
||||
ApplicationManager.getApplication().invokeAndWait(block)
|
||||
}
|
||||
protected fun edt(block: () -> Unit) = edtWait(block)
|
||||
|
||||
protected fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
protected fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
|
||||
/** Emit a chat event into the fake RPC flow. */
|
||||
protected fun emit(event: ChatEventDto, flush: Boolean = true) {
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.session.model
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.rpc.dto.DiffFileDto
|
||||
import ai.kilocode.rpc.dto.KiloAppStateDto
|
||||
import ai.kilocode.rpc.dto.KiloAppStatusDto
|
||||
@@ -1197,10 +1198,5 @@ class SessionModelTest : BasePlatformTestCase() {
|
||||
assertEquals(expected.trimIndent().trim(), model.toString().trim())
|
||||
}
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
}
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.session.views
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.session.ui.style.SessionEditorStyle
|
||||
import ai.kilocode.client.session.ui.style.SessionUiStyle
|
||||
import ai.kilocode.client.ui.UiStyle
|
||||
@@ -185,12 +186,7 @@ class LoginRequiredViewTest : BasePlatformTestCase() {
|
||||
|
||||
// ------ helpers ------
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
|
||||
private inline fun <reified T> findAll(root: Container): List<T> =
|
||||
findAllCls(root, T::class.java)
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.session.views.base
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.session.ui.style.SessionEditorStyle
|
||||
import ai.kilocode.client.session.ui.style.SessionUiStyle
|
||||
import ai.kilocode.client.ui.UiStyle
|
||||
@@ -436,12 +437,7 @@ class BaseQuestionViewTest : BasePlatformTestCase() {
|
||||
|
||||
// ------ helpers ------
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
|
||||
private fun region(panel: BaseQuestionView, region: String) = (panel.layout as BorderLayout).getLayoutComponent(region)
|
||||
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.settings
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.settings.profile.UserProfileConfigurable
|
||||
import ai.kilocode.client.settings.context.ContextConfigurable
|
||||
import ai.kilocode.client.settings.models.ModelsConfigurable
|
||||
@@ -141,12 +142,7 @@ class KiloSettingsConfigurableTest : BasePlatformTestCase() {
|
||||
|
||||
// -- helpers --
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
|
||||
private fun links(root: Container): List<ActionLink> = buildList {
|
||||
for (comp in root.components) {
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.settings
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.app.KiloAppService
|
||||
import ai.kilocode.client.settings.profile.ProfileUi
|
||||
import ai.kilocode.client.settings.profile.formatResetDate
|
||||
@@ -1067,12 +1068,7 @@ class UserProfileConfigurableTest : BasePlatformTestCase() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
|
||||
private fun flush() = coroutines.drain(::pump)
|
||||
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.settings.agents
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.settings.rules.RulesConfigurable
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.options.SearchableConfigurable
|
||||
@@ -42,12 +43,7 @@ class AgentBehaviorConfigurableTest : BasePlatformTestCase() {
|
||||
assertFalse(cfg.isModified)
|
||||
}
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
|
||||
private fun links(root: Container): List<ActionLink> = buildList {
|
||||
for (comp in root.components) {
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.settings.agents
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.cli.KiloCliParser
|
||||
import ai.kilocode.client.plugin.KiloBundle
|
||||
import ai.kilocode.client.settings.base.SettingsRow
|
||||
@@ -101,10 +102,5 @@ class AgentCreateDialogTest : BasePlatformTestCase() {
|
||||
return out
|
||||
}
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
}
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.settings.agents
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.cli.KiloCliParser
|
||||
import ai.kilocode.client.app.KiloAppService
|
||||
import ai.kilocode.client.plugin.KiloBundle
|
||||
@@ -232,10 +233,5 @@ class AgentEditDialogTest : BasePlatformTestCase() {
|
||||
return out
|
||||
}
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
}
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.settings.agents
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.cli.KiloCliParser
|
||||
import ai.kilocode.client.app.KiloAgentBehaviorService
|
||||
import ai.kilocode.client.app.KiloAppService
|
||||
@@ -498,12 +499,7 @@ class AgentsSettingsUiTest : BasePlatformTestCase() {
|
||||
MouseEvent.BUTTON1,
|
||||
)
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
|
||||
private fun flushUntil(done: () -> Boolean) = runBlocking {
|
||||
repeat(300) {
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.settings.agents
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.plugin.KiloBundle
|
||||
import ai.kilocode.client.settings.base.SettingsRow
|
||||
import ai.kilocode.client.settings.base.SettingsStackedRow
|
||||
@@ -197,10 +198,5 @@ class McpEditDialogTest : BasePlatformTestCase() {
|
||||
return out
|
||||
}
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
}
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.settings.agents
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.app.KiloAgentBehaviorService
|
||||
import ai.kilocode.client.app.KiloAppService
|
||||
import ai.kilocode.client.plugin.KiloBundle
|
||||
@@ -430,12 +431,7 @@ class McpSettingsUiTest : BasePlatformTestCase() {
|
||||
MouseEvent.BUTTON1,
|
||||
)
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
|
||||
private fun flushUntil(done: () -> Boolean) = runBlocking {
|
||||
repeat(300) {
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.settings.agents
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.app.KiloAgentBehaviorService
|
||||
import ai.kilocode.client.app.KiloAppService
|
||||
import ai.kilocode.client.app.KiloWorkspaceService
|
||||
@@ -583,12 +584,7 @@ class SkillsSettingsUiTest : BasePlatformTestCase() {
|
||||
MouseEvent.BUTTON1,
|
||||
)
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
|
||||
private fun flushUntil(done: () -> Boolean) = runBlocking {
|
||||
repeat(300) {
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.settings.autoapprove
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.app.KiloAppService
|
||||
import ai.kilocode.client.app.KiloWorkspaceService
|
||||
import ai.kilocode.client.testing.FakeAppRpcApi
|
||||
@@ -433,12 +434,7 @@ class AutoApproveSettingsUiTest : BasePlatformTestCase() {
|
||||
combo.selectedItem = item
|
||||
}
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
|
||||
private fun flushUntil(done: () -> Boolean) = runBlocking {
|
||||
repeat(200) {
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.settings.autoapprove
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.testing.fire
|
||||
import ai.kilocode.client.ui.UiStyle
|
||||
import ai.kilocode.client.ui.list.ActiveListItem
|
||||
@@ -336,10 +337,5 @@ class SettingsInlineListTest : BasePlatformTestCase() {
|
||||
return out
|
||||
}
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
}
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.settings.base
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.app.KiloAppService
|
||||
import ai.kilocode.client.app.KiloWorkspaceService
|
||||
import ai.kilocode.client.testing.FakeAppRpcApi
|
||||
@@ -172,12 +173,7 @@ class BaseSettingsUiTest : BasePlatformTestCase() {
|
||||
edt { UIUtil.dispatchAllInvocationEvents() }
|
||||
}
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
|
||||
private fun text(root: Container): String {
|
||||
val out = mutableListOf<String>()
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.settings.base
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.app.KiloAppService
|
||||
import ai.kilocode.client.app.KiloWorkspaceService
|
||||
import ai.kilocode.client.testing.FakeAppRpcApi
|
||||
@@ -102,12 +103,7 @@ class BaseSettingsUiWorkspaceTest : BasePlatformTestCase() {
|
||||
config = ConfigDto(model = model),
|
||||
)
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
|
||||
private fun flushUntil(done: () -> Boolean) = runBlocking {
|
||||
repeat(20) {
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.settings.base
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.app.KiloAppService
|
||||
import ai.kilocode.client.plugin.KiloBundle
|
||||
import ai.kilocode.client.testing.FakeAppRpcApi
|
||||
@@ -190,12 +191,7 @@ class KiloReadyConfigurableTest : BasePlatformTestCase() {
|
||||
assertTrue(done())
|
||||
}
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
|
||||
private fun text(root: Container): String {
|
||||
val out = mutableListOf<String>()
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.settings.base
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.testing.fire
|
||||
import ai.kilocode.client.session.ui.PickerRow
|
||||
import ai.kilocode.client.ui.FilledBadgeIcon
|
||||
@@ -856,10 +857,5 @@ class SettingsListViewTest : BasePlatformTestCase() {
|
||||
false,
|
||||
)
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
}
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.settings.context
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.app.KiloAppService
|
||||
import ai.kilocode.client.app.KiloWorkspaceService
|
||||
import ai.kilocode.client.settings.base.SettingsToggle
|
||||
@@ -284,12 +285,7 @@ class ContextSettingsUiTest : BasePlatformTestCase() {
|
||||
.filterIsInstance<HoverIcon>()
|
||||
.single { it.toolTipText == tip }
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
|
||||
private fun flushUntil(done: () -> Boolean) = runBlocking {
|
||||
repeat(200) {
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.settings.models
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.app.KiloAppService
|
||||
import ai.kilocode.client.app.KiloWorkspaceService
|
||||
import ai.kilocode.client.session.ui.model.ModelPicker
|
||||
@@ -365,12 +366,7 @@ class ModelsSettingsUiTest : BasePlatformTestCase() {
|
||||
|
||||
private fun requireUi(): ModelsSettingsUi = requireNotNull(ui)
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
|
||||
private fun flushUntil(done: () -> Boolean) = runBlocking {
|
||||
repeat(200) {
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.settings.providers
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.app.KiloProviderService
|
||||
import ai.kilocode.client.plugin.KiloBundle
|
||||
import ai.kilocode.client.testing.FakeProviderRpcApi
|
||||
@@ -1290,12 +1291,7 @@ class ProvidersSettingsUiTest : BasePlatformTestCase() {
|
||||
return out.joinToString("\n")
|
||||
}
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
|
||||
private fun flushUntil(done: () -> Boolean) = runBlocking {
|
||||
repeat(200) {
|
||||
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.settings.rules
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.app.KiloAgentBehaviorService
|
||||
import ai.kilocode.client.app.KiloAppService
|
||||
import ai.kilocode.client.app.KiloWorkspaceService
|
||||
@@ -358,12 +359,7 @@ class RulesSettingsUiTest : BasePlatformTestCase() {
|
||||
MouseEvent.BUTTON1,
|
||||
)
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
|
||||
private fun flushUntil(done: () -> Boolean) {
|
||||
repeat(200) {
|
||||
|
||||
+2
-8
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.testing
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import ai.kilocode.client.util.UiTimer
|
||||
import ai.kilocode.client.util.UiTimerSource
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
@@ -28,14 +29,7 @@ class TestUiTimers : UiTimerSource {
|
||||
}
|
||||
}
|
||||
|
||||
private fun edt(action: () -> Unit) {
|
||||
val app = ApplicationManager.getApplication()
|
||||
if (app.isDispatchThread) {
|
||||
action()
|
||||
return
|
||||
}
|
||||
app.invokeAndWait(action)
|
||||
}
|
||||
private fun edt(action: () -> Unit) = edtWait(action)
|
||||
|
||||
private inner class TestTimer(
|
||||
private val ms: Int,
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package ai.kilocode.client.ui.list
|
||||
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlin.time.measureTime
|
||||
|
||||
class ActiveListMatchTest {
|
||||
@Test
|
||||
fun `matches words and camel case acronyms`() {
|
||||
assertTrue(activeListMatches("wc", item("WorktreeController")))
|
||||
assertTrue(activeListMatches("ws ses", item("Worktree Session Editor")))
|
||||
assertTrue(activeListMatches("feature", item("feature-branch")))
|
||||
assertFalse(activeListMatches("zz", item("WorktreeController")))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `matcher handles repeated ambiguous prefixes quickly`() {
|
||||
val text = List(28) { "aaaaaaaaaa" }.joinToString("-")
|
||||
val query = "aaaaaaaaaab"
|
||||
|
||||
val duration = measureTime {
|
||||
assertFalse(activeListMatches(query, item(text)))
|
||||
}
|
||||
|
||||
assertTrue(duration < 200.milliseconds, "ambiguous match took $duration")
|
||||
}
|
||||
|
||||
private fun item(title: String) = object : ActiveListItem {
|
||||
override val key = title
|
||||
override val title = title
|
||||
}
|
||||
}
|
||||
+2
-6
@@ -1,5 +1,6 @@
|
||||
package ai.kilocode.client.ui.picker
|
||||
|
||||
import ai.kilocode.client.util.edtWait
|
||||
import com.intellij.CommonBundle
|
||||
import com.intellij.ide.ui.laf.darcula.ui.DarculaButtonUI
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
@@ -69,12 +70,7 @@ class PickerPopupTest : BasePlatformTestCase() {
|
||||
return out
|
||||
}
|
||||
|
||||
private fun <T> edt(block: () -> T): T {
|
||||
var result: T? = null
|
||||
ApplicationManager.getApplication().invokeAndWait { result = block() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as T
|
||||
}
|
||||
private fun <T> edt(block: () -> T): T = edtWait(block)
|
||||
|
||||
private class TestRenderer(model: CollectionListModel<String>) : PickerListRenderer<String>(
|
||||
model = model,
|
||||
|
||||
Reference in New Issue
Block a user