mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[analyzer] fix initialisation progress reporting
Progress reporting during initialisation has a time-based debounce: the sending coroutine (working concurrently with the passed-in block) is waiting 100ms after sending a progress update, before proceeding with the next update. When the block returns, the sending coroutine is immediately cancelled, robbing it of a chance to wake up and deliver the end progress message, that the block requests at the very end. This caused the never-ending progress displaying in Air. The "withProgress" function has been fixed to always send begin/end message out of bound and only debounce intermediate progress updates. Since the end message may be a subject for customisation, depending on the execution path taken, to enforce the begin/end contract on progress, the signature was updated: the function now takes the begin progress title, and the block is now required to return "WorkDoneProgress.End" instance that will be sent to the client. To keep the code simple, the function no longer returns a generic T. It can be added back, if necessary, however, currently it only has one usage that expects Unit. GitOrigin-RevId: ea8b390cb7bca4c894c5c2b75e304b71eaf03481
This commit is contained in:
committed by
intellij-monorepo-bot
parent
1750e77384
commit
8ca4e2c3d7
@@ -1,7 +1,6 @@
|
||||
package com.jetbrains.lsp.implementation
|
||||
|
||||
import com.jetbrains.lsp.protocol.*
|
||||
import com.jetbrains.lsp.implementation.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
@@ -11,19 +10,27 @@ fun interface ProgressReporter {
|
||||
companion object {
|
||||
val NOOP: ProgressReporter = ProgressReporter {}
|
||||
}
|
||||
|
||||
fun report(progress: WorkDoneProgress)
|
||||
}
|
||||
|
||||
suspend fun<T> LspClient.withProgress(
|
||||
suspend fun LspClient.withProgress(
|
||||
request: WorkDoneProgressParams,
|
||||
body: suspend CoroutineScope.(ProgressReporter) -> T
|
||||
): T =
|
||||
beginTitle: String,
|
||||
body: suspend CoroutineScope.(ProgressReporter) -> WorkDoneProgress.End,
|
||||
) {
|
||||
coroutineScope {
|
||||
when (val token = request.workDoneToken) {
|
||||
null -> body(ProgressReporter.NOOP)
|
||||
else -> {
|
||||
val beginProgress = WorkDoneProgress.Begin(title = beginTitle)
|
||||
notify(
|
||||
LSP.ProgressNotificationType,
|
||||
ProgressParams(token, LSP.json.encodeToJsonElement(WorkDoneProgress.serializer(), beginProgress)),
|
||||
)
|
||||
|
||||
val state = MutableStateFlow<WorkDoneProgress?>(null)
|
||||
launch {
|
||||
val endProgress = launch {
|
||||
state.filterNotNull().collect { p ->
|
||||
notify(LSP.ProgressNotificationType, ProgressParams(token, LSP.json.encodeToJsonElement(WorkDoneProgress.serializer(), p)))
|
||||
delay(100.milliseconds)
|
||||
@@ -31,6 +38,12 @@ suspend fun<T> LspClient.withProgress(
|
||||
}.use {
|
||||
body(ProgressReporter { p -> state.value = p })
|
||||
}
|
||||
|
||||
notify(
|
||||
LSP.ProgressNotificationType,
|
||||
ProgressParams(token, LSP.json.encodeToJsonElement(WorkDoneProgress.serializer(), endProgress))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user