[air] IJAI-1 Support optional backend completion for frontend only documents/editors

This is intentioanlly implemented with the source of truth in frontend to be able to work without backend modules enabled in light mode.

The idea:
- if backend available, bind a mock backend document/editor to the existing frontend native document/editor and run completion session in the bound doc to have backend variants provided
- in light mode, do not bind because the corresponding rpc is not available - have reduced functionality and not fail/break the entire plugin

(cherry picked from commit d565129ebc9deae4facb78bff3957f075d7686f3)

GitOrigin-RevId: 15d483a87fa58b924a11be8309de950091996387
This commit is contained in:
Nikita Katkov
2026-08-01 01:02:26 +00:00
committed by intellij-monorepo-bot
parent 1fd8ae043d
commit 1e8a99b307
@@ -35,11 +35,14 @@ fun Document.bindToBackend(
service<BackendBasedDocumentCoroutineScopeProvider>().cs.launch(Dispatchers.EDT) {
val builder = BackendDocumentBindBuilder().apply(builder)
val backendDocumentIdProvider = builder.backendDocumentIdProvider
if (backendDocumentIdProvider != null) {
val documentBound = if (backendDocumentIdProvider != null) {
bindToBackend(backendDocumentIdProvider, builder.onBindingDispose)
}
else {
true
}
if (builder.bindEditors) {
if (documentBound && builder.bindEditors) {
// mark the document, so future editors will be bind
bindEditorsToBackend()
// bind current editors (since they might be created during backends' documents initialization)
@@ -87,7 +90,7 @@ private fun Document.bindCurrentEditors() {
private suspend fun Document.bindToBackend(
backendDocumentIdProvider: suspend (FrontendDocumentId) -> BackendDocumentId?,
onBindingDispose: (() -> Unit)?,
) {
): Boolean {
val frontendDocument = this
val frontendDocumentId = FrontendDocumentId(UID.random())
val registry = FrontendDocumentIdRegistry.EP_NAME.extensionList.firstOrNull()
@@ -102,6 +105,7 @@ private suspend fun Document.bindToBackend(
registry?.unregisterFrontendDocumentId(frontendDocumentId)
}
}
return backendDocumentId != null
}
@ApiStatus.Internal
@@ -188,4 +192,4 @@ interface BackendDocumentBinder {
// TODO: should BackendBasedDocument take cs as argument? Let's see by usages
@Service(Service.Level.APP)
private class BackendBasedDocumentCoroutineScopeProvider(val cs: CoroutineScope)
private class BackendBasedDocumentCoroutineScopeProvider(val cs: CoroutineScope)