From 1e8a99b307ce6495028595bf8fa568a5cfed2e82 Mon Sep 17 00:00:00 2001 From: Nikita Katkov Date: Sun, 26 Jul 2026 22:53:38 +0200 Subject: [PATCH] [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 --- .../src/com/intellij/ide/rpc/BackendBasedDocument.kt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/rpc/src/com/intellij/ide/rpc/BackendBasedDocument.kt b/platform/platform-impl/rpc/src/com/intellij/ide/rpc/BackendBasedDocument.kt index 9e4accc7e41f..9c67cecfc007 100644 --- a/platform/platform-impl/rpc/src/com/intellij/ide/rpc/BackendBasedDocument.kt +++ b/platform/platform-impl/rpc/src/com/intellij/ide/rpc/BackendBasedDocument.kt @@ -35,11 +35,14 @@ fun Document.bindToBackend( service().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) \ No newline at end of file +private class BackendBasedDocumentCoroutineScopeProvider(val cs: CoroutineScope)