diff options
-rw-r--r-- | crates/rust-analyzer/src/config.rs | 9 | ||||
-rw-r--r-- | docs/dev/lsp-extensions.md | 34 | ||||
-rw-r--r-- | editors/code/src/client.ts | 19 |
3 files changed, 57 insertions, 5 deletions
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 { | |||
275 | { | 275 | { |
276 | self.client_caps.code_action_literals = value; | 276 | self.client_caps.code_action_literals = value; |
277 | } | 277 | } |
278 | |||
278 | self.completion.allow_snippets(false); | 279 | self.completion.allow_snippets(false); |
279 | if let Some(completion) = &doc_caps.completion { | 280 | if let Some(completion) = &doc_caps.completion { |
280 | if let Some(completion_item) = &completion.completion_item { | 281 | if let Some(completion_item) = &completion.completion_item { |
@@ -283,7 +284,6 @@ impl Config { | |||
283 | } | 284 | } |
284 | } | 285 | } |
285 | } | 286 | } |
286 | self.assist.allow_snippets(false); | ||
287 | } | 287 | } |
288 | 288 | ||
289 | if let Some(window_caps) = caps.window.as_ref() { | 289 | if let Some(window_caps) = caps.window.as_ref() { |
@@ -291,5 +291,12 @@ impl Config { | |||
291 | self.client_caps.work_done_progress = value; | 291 | self.client_caps.work_done_progress = value; |
292 | } | 292 | } |
293 | } | 293 | } |
294 | |||
295 | self.assist.allow_snippets(false); | ||
296 | if let Some(experimental) = &caps.experimental { | ||
297 | let enable = | ||
298 | experimental.get("snippetTextEdit").and_then(|it| it.as_bool()) == Some(true); | ||
299 | self.assist.allow_snippets(enable); | ||
300 | } | ||
294 | } | 301 | } |
295 | } | 302 | } |
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 @@ | |||
1 | # LSP Extensions | ||
2 | |||
3 | This document describes LSP extensions used by rust-analyzer. | ||
4 | It's a best effort document, when in doubt, consult the source (and send a PR with clarification ;-) ). | ||
5 | We aim to upstream all non Rust-specific extensions to the protocol, but this is not a top priority. | ||
6 | All capabilities are enabled via `experimental` field of `ClientCapabilities`. | ||
7 | |||
8 | ## `SnippetTextEdit` | ||
9 | |||
10 | **Capability** | ||
11 | |||
12 | ```typescript | ||
13 | { | ||
14 | "snippetTextEdit": boolean | ||
15 | } | ||
16 | ``` | ||
17 | |||
18 | If this capability is set, `WorkspaceEdit`s returned from `codeAction` requests might contain `SnippetTextEdit`s instead of usual `TextEdit`s: | ||
19 | |||
20 | ```typescript | ||
21 | interface SnippetTextEdit extends TextEdit { | ||
22 | insertTextFormat?: InsertTextFormat; | ||
23 | } | ||
24 | ``` | ||
25 | |||
26 | ```typescript | ||
27 | export interface TextDocumentEdit { | ||
28 | textDocument: VersionedTextDocumentIdentifier; | ||
29 | edits: (TextEdit | SnippetTextEdit)[]; | ||
30 | } | ||
31 | ``` | ||
32 | |||
33 | When applying such code action, the editor should insert snippet, with tab stops and placeholder. | ||
34 | 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 | |||
35 | } as any | 35 | } as any |
36 | }; | 36 | }; |
37 | 37 | ||
38 | const res = new lc.LanguageClient( | 38 | const client = new lc.LanguageClient( |
39 | 'rust-analyzer', | 39 | 'rust-analyzer', |
40 | 'Rust Analyzer Language Server', | 40 | 'Rust Analyzer Language Server', |
41 | serverOptions, | 41 | serverOptions, |
@@ -47,8 +47,19 @@ export function createClient(serverPath: string, cwd: string): lc.LanguageClient | |||
47 | // since they are available on stable. | 47 | // since they are available on stable. |
48 | // Note that while these features are stable in vscode their LSP protocol | 48 | // Note that while these features are stable in vscode their LSP protocol |
49 | // implementations are still in the "proposed" category for 3.16. | 49 | // implementations are still in the "proposed" category for 3.16. |
50 | res.registerFeature(new CallHierarchyFeature(res)); | 50 | client.registerFeature(new CallHierarchyFeature(client)); |
51 | res.registerFeature(new SemanticTokensFeature(res)); | 51 | client.registerFeature(new SemanticTokensFeature(client)); |
52 | client.registerFeature(new SnippetTextEditFeature()); | ||
52 | 53 | ||
53 | return res; | 54 | return client; |
55 | } | ||
56 | |||
57 | class SnippetTextEditFeature implements lc.StaticFeature { | ||
58 | fillClientCapabilities(capabilities: lc.ClientCapabilities): void { | ||
59 | const caps: any = capabilities.experimental ?? {}; | ||
60 | caps.snippetTextEdit = true; | ||
61 | capabilities.experimental = caps | ||
62 | } | ||
63 | initialize(_capabilities: lc.ServerCapabilities<any>, _documentSelector: lc.DocumentSelector | undefined): void { | ||
64 | } | ||
54 | } | 65 | } |