From a752853350639a915178ea900a51f3c45443795e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 17 May 2020 21:24:33 +0200 Subject: Add snippetTextEdit protocol extension --- crates/rust-analyzer/src/config.rs | 9 ++++++++- docs/dev/lsp-extensions.md | 34 ++++++++++++++++++++++++++++++++++ editors/code/src/client.ts | 19 +++++++++++++++---- 3 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 docs/dev/lsp-extensions.md diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 063b1b316..d75c48597 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -275,6 +275,7 @@ impl Config { { self.client_caps.code_action_literals = value; } + self.completion.allow_snippets(false); if let Some(completion) = &doc_caps.completion { if let Some(completion_item) = &completion.completion_item { @@ -283,7 +284,6 @@ impl Config { } } } - self.assist.allow_snippets(false); } if let Some(window_caps) = caps.window.as_ref() { @@ -291,5 +291,12 @@ impl Config { self.client_caps.work_done_progress = value; } } + + self.assist.allow_snippets(false); + if let Some(experimental) = &caps.experimental { + let enable = + experimental.get("snippetTextEdit").and_then(|it| it.as_bool()) == Some(true); + self.assist.allow_snippets(enable); + } } } diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md new file mode 100644 index 000000000..d2ec6c021 --- /dev/null +++ b/docs/dev/lsp-extensions.md @@ -0,0 +1,34 @@ +# LSP Extensions + +This document describes LSP extensions used by rust-analyzer. +It's a best effort document, when in doubt, consult the source (and send a PR with clarification ;-) ). +We aim to upstream all non Rust-specific extensions to the protocol, but this is not a top priority. +All capabilities are enabled via `experimental` field of `ClientCapabilities`. + +## `SnippetTextEdit` + +**Capability** + +```typescript +{ + "snippetTextEdit": boolean +} +``` + +If this capability is set, `WorkspaceEdit`s returned from `codeAction` requests might contain `SnippetTextEdit`s instead of usual `TextEdit`s: + +```typescript +interface SnippetTextEdit extends TextEdit { + insertTextFormat?: InsertTextFormat; +} +``` + +```typescript +export interface TextDocumentEdit { + textDocument: VersionedTextDocumentIdentifier; + edits: (TextEdit | SnippetTextEdit)[]; +} +``` + +When applying such code action, the editor should insert snippet, with tab stops and placeholder. +At the moment, rust-analyzer guarantees that only a single edit will have `InsertTextFormat.Snippet`. diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts index cffdcf11a..2067738ea 100644 --- a/editors/code/src/client.ts +++ b/editors/code/src/client.ts @@ -35,7 +35,7 @@ export function createClient(serverPath: string, cwd: string): lc.LanguageClient } as any }; - const res = new lc.LanguageClient( + const client = new lc.LanguageClient( 'rust-analyzer', 'Rust Analyzer Language Server', serverOptions, @@ -47,8 +47,19 @@ export function createClient(serverPath: string, cwd: string): lc.LanguageClient // since they are available on stable. // Note that while these features are stable in vscode their LSP protocol // implementations are still in the "proposed" category for 3.16. - res.registerFeature(new CallHierarchyFeature(res)); - res.registerFeature(new SemanticTokensFeature(res)); + client.registerFeature(new CallHierarchyFeature(client)); + client.registerFeature(new SemanticTokensFeature(client)); + client.registerFeature(new SnippetTextEditFeature()); - return res; + return client; +} + +class SnippetTextEditFeature implements lc.StaticFeature { + fillClientCapabilities(capabilities: lc.ClientCapabilities): void { + const caps: any = capabilities.experimental ?? {}; + caps.snippetTextEdit = true; + capabilities.experimental = caps + } + initialize(_capabilities: lc.ServerCapabilities, _documentSelector: lc.DocumentSelector | undefined): void { + } } -- cgit v1.2.3