From b2422c8faf5577d62fe29b1b63fb4422df3953a3 Mon Sep 17 00:00:00 2001 From: Ludwig Valda Vasquez Date: Thu, 27 Nov 2025 17:09:26 +0100 Subject: [PATCH] [air] lsp: make features dynamic Most of the used conditional features (i.e. the features that require a capability check) are now implemented as dynamic features, meaning they can be registered through the `registerCapability` request while the client is running. The capability check is replaced by a feature registration check instead. GitOrigin-RevId: 0601feb9f5f14c58a8b30c66bae65940e53166c6 --- .../com/jetbrains/lsp/protocol/CodeAction.kt | 37 +++- .../jetbrains/lsp/protocol/DocumentSync.kt | 10 - .../lsp/protocol/ServerCapabilities.kt | 206 +++++++++++++----- .../jetbrains/lsp/protocol/SignatureHelp.kt | 33 ++- .../com/jetbrains/lsp/protocol/references.kt | 6 + .../com/jetbrains/lsp/protocol/symbols.kt | 20 +- 6 files changed, 225 insertions(+), 87 deletions(-) diff --git a/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/CodeAction.kt b/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/CodeAction.kt index 56b65cc3a5b9..7448f3ae8c89 100644 --- a/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/CodeAction.kt +++ b/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/CodeAction.kt @@ -12,18 +12,14 @@ import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonPrimitive import kotlin.jvm.JvmInline -/** - * @see codeActionOptions (LSP spec) - */ -@Serializable -data class CodeActionOptions( +interface CodeActionOptions : WorkDoneProgressOptions { /** * CodeActionKinds that this server may return. * * The list of kinds may be generic, such as `CodeActionKind.Refactor`, * or the server may list out every specific kind they provide. */ - val codeActionKinds: List, + val codeActionKinds: List /** * The server provides support to resolve additional @@ -31,9 +27,32 @@ data class CodeActionOptions( * * @since 3.16.0 */ - val resolveProvider: Boolean?, - override val workDoneProgress: Boolean?, -) : WorkDoneProgressOptions + val resolveProvider: Boolean? +} + +/** + * @see codeActionOptions (LSP spec) + */ +@Serializable +data class CodeActionRegistrationOptions( + /** + * CodeActionKinds that this server may return. + * + * The list of kinds may be generic, such as `CodeActionKind.Refactor`, + * or the server may list out every specific kind they provide. + */ + override val codeActionKinds: List, + + /** + * The server provides support to resolve additional + * information for a code action. + * + * @since 3.16.0 + */ + override val resolveProvider: Boolean?, + override val workDoneProgress: Boolean? = null, + override val documentSelector: DocumentSelector? = null, +) : CodeActionOptions, TextDocumentRegistrationOptions /** * The kind of code action. diff --git a/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/DocumentSync.kt b/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/DocumentSync.kt index b22baa02f1fe..337896439dc7 100644 --- a/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/DocumentSync.kt +++ b/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/DocumentSync.kt @@ -1,20 +1,10 @@ package com.jetbrains.lsp.protocol import kotlinx.serialization.DeserializationStrategy -import kotlinx.serialization.InternalSerializationApi -import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable -import kotlinx.serialization.SerializationException import kotlinx.serialization.builtins.ListSerializer import kotlinx.serialization.builtins.serializer -import kotlinx.serialization.descriptors.PolymorphicKind -import kotlinx.serialization.descriptors.SerialDescriptor -import kotlinx.serialization.descriptors.buildSerialDescriptor -import kotlinx.serialization.encoding.Decoder -import kotlinx.serialization.encoding.Encoder -import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonContentPolymorphicSerializer -import kotlinx.serialization.json.JsonDecoder import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonObject diff --git a/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/ServerCapabilities.kt b/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/ServerCapabilities.kt index 2203ac775db9..a9cf71bc52a6 100644 --- a/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/ServerCapabilities.kt +++ b/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/ServerCapabilities.kt @@ -140,43 +140,43 @@ data class ServerCapabilities( /** * The server provides hover support. */ - val hoverProvider: OrBoolean? = null, + val hoverProvider: OrBoolean? = null, /** * The server provides signature help support. */ - val signatureHelpProvider: SignatureHelpOptions? = null, + val signatureHelpProvider: SignatureHelpRegistrationOptions? = null, /** * The server provides go to declaration support. * * @since 3.14.0 */ - val declarationProvider: OrBoolean? = null, + val declarationProvider: OrBoolean? = null, /** * The server provides goto definition support. */ - val definitionProvider: OrBoolean? = null, + val definitionProvider: OrBoolean? = null, /** * The server provides goto type definition support. * * @since 3.6.0 */ - val typeDefinitionProvider: OrBoolean? = null, + val typeDefinitionProvider: OrBoolean? = null, /** * The server provides goto implementation support. * * @since 3.6.0 */ - val implementationProvider: OrBoolean? = null, + val implementationProvider: OrBoolean? = null, /** * The server provides find references support. */ - val referencesProvider: OrBoolean? = null, + val referencesProvider: OrBoolean? = null, /** * The server provides document highlight support. @@ -186,19 +186,19 @@ data class ServerCapabilities( /** * The server provides document symbol support. */ - val documentSymbolProvider: OrBoolean? = null, + val documentSymbolProvider: OrBoolean? = null, /** * The server provides code actions. The `CodeActionOptions` return type is * only valid if the client signals code action literal support via the * property `textDocument.codeAction.codeActionLiteralSupport`. */ - val codeActionProvider: OrBoolean? = null, + val codeActionProvider: OrBoolean? = null, /** * The server provides code lens. */ - val codeLensProvider: CodeLensOptions? = null, + val codeLensProvider: CodeLensRegistrationOptions? = null, /** * The server provides document link support. @@ -210,17 +210,17 @@ data class ServerCapabilities( * * @since 3.6.0 */ - val colorProvider: OrBoolean? = null, + val colorProvider: OrBoolean? = null, /** * The server provides document formatting. */ - val documentFormattingProvider: OrBoolean? = null, + val documentFormattingProvider: OrBoolean? = null, /** * The server provides document range formatting. */ - val documentRangeFormattingProvider: OrBoolean? = null, + val documentRangeFormattingProvider: OrBoolean? = null, /** * The server provides document formatting on typing. @@ -232,7 +232,7 @@ data class ServerCapabilities( * specified if the client states that it supports * `prepareSupport` in its initial `initialize` request. */ - val renameProvider: OrBoolean? = null, + val renameProvider: OrBoolean? = null, /** * The server provides folding provider support. @@ -272,7 +272,7 @@ data class ServerCapabilities( * * @since 3.16.0 */ - val semanticTokensProvider: SemanticTokensOptions? = null, // SemanticTokensOptions | SemanticTokensRegistrationOptions + val semanticTokensProvider: SemanticTokensRegistrationOptions? = null, /** * Whether server provides moniker support. @@ -312,7 +312,7 @@ data class ServerCapabilities( /** * The server provides workspace symbol support. */ - val workspaceSymbolProvider: OrBoolean? = null, + val workspaceSymbolProvider: OrBoolean? = null, /** * Workspace specific server capabilities @@ -325,59 +325,132 @@ data class ServerCapabilities( val experimental: JsonElement? = null, ) -typealias HoverOptions = Unknown -typealias TypeDefinitionOptions = Unknown -typealias ImplementationOptions = Unknown -typealias DocumentSymbolOptions = Unknown typealias DocumentLinkOptions = Unknown -typealias DocumentColorOptions = Unknown -typealias DocumentFormattingOptions = Unknown -typealias DocumentRangeFormattingOptions = Unknown typealias DocumentOnTypeFormattingOptions = Unknown typealias FoldingRangeOptions = Unknown typealias SelectionRangeOptions = Unknown typealias LinkedEditingRangeOptions = Unknown typealias CallHierarchyOptions = Unknown -typealias SemanticTokensRegistrationOptions = Unknown typealias MonikerOptions = Unknown typealias TypeHierarchyOptions = Unknown typealias InlineValueOptions = Unknown +interface DocumentRangeFormattingOptions : WorkDoneProgressOptions + +@Serializable +data class DocumentRangeFormattingRegistrationOptions( + override val workDoneProgress: Boolean? = null, + override val documentSelector: DocumentSelector? = null, +) : DocumentRangeFormattingOptions, TextDocumentRegistrationOptions + +interface DocumentFormattingOptions : WorkDoneProgressOptions + +@Serializable +data class DocumentFormattingRegistrationOptions( + override val workDoneProgress: Boolean? = null, + override val documentSelector: DocumentSelector? = null, +) : DocumentFormattingOptions, TextDocumentRegistrationOptions + +interface DocumentSymbolOptions : WorkDoneProgressOptions { + /** + * A human-readable string that is shown when multiple outlines trees + * are shown for the same document. + * + * @since 3.16.0 + */ + val label: String? +} + +@Serializable +data class DocumentSymbolRegistrationOptions( + override val label: String?, + override val workDoneProgress: Boolean? = null, + override val documentSelector: DocumentSelector? = null, +) : DocumentSymbolOptions, TextDocumentRegistrationOptions + +interface ImplementationOptions : WorkDoneProgressOptions + +@Serializable +data class ImplementationRegistrationOptions( + override val workDoneProgress: Boolean? = null, + override val documentSelector: DocumentSelector? = null, + override val id: String? = null, +) : ImplementationOptions, TextDocumentRegistrationOptions, StaticRegistrationOptions + +interface HoverOptions: WorkDoneProgressOptions + +@Serializable +data class HoverRegistrationOptions( + override val documentSelector: DocumentSelector? = null, + override val workDoneProgress: Boolean? = null, +) : HoverOptions, TextDocumentRegistrationOptions + +interface TypeDefinitionOptions : WorkDoneProgressOptions + +@Serializable +data class TypeDefinitionRegistrationOptions( + override val workDoneProgress: Boolean? = null, + override val documentSelector: DocumentSelector? = null, + override val id: String? = null, +) : TypeDefinitionOptions, TextDocumentRegistrationOptions, StaticRegistrationOptions + +interface DocumentColorOptions : WorkDoneProgressOptions + +@Serializable +data class DocumentColorRegistrationOptions( + override val workDoneProgress: Boolean? = null, + override val documentSelector: DocumentSelector? = null, + override val id: String? = null, +) : DocumentColorOptions, TextDocumentRegistrationOptions, StaticRegistrationOptions + @Serializable data class DocumentHighlightOptions( override val workDoneProgress: Boolean? = null, ) : WorkDoneProgressOptions -@Serializable -data class RenameOptions( - /** - * Renames should be checked and tested before being executed. - */ - val prepareProvider: Boolean?, - - override val workDoneProgress: Boolean? = null, -) : WorkDoneProgressOptions +interface RenameOptions : WorkDoneProgressOptions { + /** + * Renames should be checked and tested before being executed. + */ + val prepareProvider: Boolean? +} @Serializable -data class CodeLensOptions( - override val workDoneProgress: Boolean? = null, +data class RenameRegistrationOptions( + /** + * Renames should be checked and tested before being executed. + */ + override val prepareProvider: Boolean?, + + override val workDoneProgress: Boolean? = null, + override val documentSelector: DocumentSelector? = null, +) : RenameOptions, TextDocumentRegistrationOptions + +interface CodeLensOptions : WorkDoneProgressOptions { + /** + * Code lens has a resolve provider as well. + */ + val resolveProvider: Boolean? +} + +@Serializable +data class CodeLensRegistrationOptions( + override val workDoneProgress: Boolean? = null, + override val documentSelector: DocumentSelector? = null, /** * Code lens has a resolve provider as well. */ - val resolveProvider: Boolean? = null, - ) : WorkDoneProgressOptions + override val resolveProvider: Boolean? = null, +) : CodeLensOptions, TextDocumentRegistrationOptions -@Serializable -data class InlayHintOptions( +interface InlayHintOptions : WorkDoneProgressOptions { /** * The server provides support to resolve additional * information for an inlay hint item. */ - val resolveProvider: Boolean?, - - override val workDoneProgress: Boolean?, -) : WorkDoneProgressOptions + val resolveProvider: Boolean? +} @Serializable data class InlayHintRegistrationOptions( @@ -385,43 +458,62 @@ data class InlayHintRegistrationOptions( * The server provides support to resolve additional * information for an inlay hint item. */ - val resolveProvider: Boolean?, + override val resolveProvider: Boolean?, override val workDoneProgress: Boolean? = null, override val documentSelector: DocumentSelector? = null, override val id: String? = null, -) : TextDocumentRegistrationOptions, StaticRegistrationOptions, WorkDoneProgressOptions +) : InlayHintOptions, TextDocumentRegistrationOptions, StaticRegistrationOptions -@Serializable -data class SemanticTokensOptions( +interface SemanticTokensOptions : WorkDoneProgressOptions { /** * The legend used by the server */ - val legend: SemanticTokensLegend, + val legend: SemanticTokensLegend /** * Server supports providing semantic tokens for a specific range * of a document. */ - val range: OrBoolean?, + val range: OrBoolean? /** * Server supports providing semantic tokens for a full document. */ - val full: OrBoolean?, - - override val workDoneProgress: Boolean? = null, -) : WorkDoneProgressOptions { + val full: OrBoolean? @Serializable data class Full( - /** - * The server supports deltas for full documents. - */ - val delta: Boolean?, + /** + * The server supports deltas for full documents. + */ + val delta: Boolean?, ) } +@Serializable +data class SemanticTokensRegistrationOptions( + /** + * The legend used by the server + */ + override val legend: SemanticTokensLegend, + + /** + * Server supports providing semantic tokens for a specific range + * of a document. + */ + override val range: OrBoolean?, + + /** + * Server supports providing semantic tokens for a full document. + */ + override val full: OrBoolean?, + + override val workDoneProgress: Boolean? = null, + override val documentSelector: DocumentSelector? = null, + override val id: String? = null, +) : SemanticTokensOptions, TextDocumentRegistrationOptions, StaticRegistrationOptions + @Serializable data class ServerWorkspaceCapabilities( /** diff --git a/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/SignatureHelp.kt b/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/SignatureHelp.kt index 931dce974e29..3408ebf986c9 100644 --- a/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/SignatureHelp.kt +++ b/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/SignatureHelp.kt @@ -17,13 +17,13 @@ import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonPrimitive import kotlin.jvm.JvmInline -@Serializable -data class SignatureHelpOptions( +interface SignatureHelpOptions : WorkDoneProgressOptions { /** * The characters that trigger signature help * automatically. */ - val triggerCharacters: List?, + val triggerCharacters: List? + /** * List of characters that re-trigger signature help. * @@ -33,9 +33,30 @@ data class SignatureHelpOptions( * * @since 3.15.0 */ - val retriggerCharacters: List?, - override val workDoneProgress: Boolean?, -) : WorkDoneProgressOptions + val retriggerCharacters: List? +} + +@Serializable +data class SignatureHelpRegistrationOptions( + /** + * The characters that trigger signature help + * automatically. + */ + override val triggerCharacters: List?, + + /** + * List of characters that re-trigger signature help. + * + * These trigger characters are only active when signature help is already + * showing. All trigger characters are also counted as re-trigger + * characters. + * + * @since 3.15.0 + */ + override val retriggerCharacters: List?, + override val workDoneProgress: Boolean? = null, + override val documentSelector: DocumentSelector? = null, +) : SignatureHelpOptions, TextDocumentRegistrationOptions @Serializable data class SignatureHelpParams( diff --git a/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/references.kt b/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/references.kt index ab61b15f5d4d..23a42d2b9a26 100644 --- a/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/references.kt +++ b/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/references.kt @@ -8,6 +8,12 @@ import kotlinx.serialization.builtins.serializer interface ReferenceOptions : WorkDoneProgressOptions +@Serializable +data class ReferenceRegistrationOptions( + override val workDoneProgress: Boolean? = null, + override val documentSelector: DocumentSelector? = null, +) : ReferenceOptions, TextDocumentRegistrationOptions + @Serializable data class ReferenceParams( override val textDocument: TextDocumentIdentifier, diff --git a/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/symbols.kt b/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/symbols.kt index 2625cb23a5d7..99d60d97dbbf 100644 --- a/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/symbols.kt +++ b/fleet/lsp.protocol/srcCommonMain/com/jetbrains/lsp/protocol/symbols.kt @@ -9,17 +9,27 @@ import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonObject import kotlin.jvm.JvmInline -@Serializable -data class WorkspaceSymbolOptions( +interface WorkspaceSymbolOptions : WorkDoneProgressOptions{ /** * The server provides support to resolve additional * information for a workspace symbol. * * @since 3.17.0 */ - val resolveProvider: Boolean?, - override val workDoneProgress: Boolean?, -) : WorkDoneProgressOptions + val resolveProvider: Boolean? +} + +@Serializable +data class WorkspaceSymbolRegistrationOptions( + /** + * The server provides support to resolve additional + * information for a workspace symbol. + * + * @since 3.17.0 + */ + override val resolveProvider: Boolean?, + override val workDoneProgress: Boolean? = null, +) : WorkspaceSymbolOptions /** * The parameters of a Workspace Symbol Request.