Skip to content

Commit a752853

Browse files
committed
Add snippetTextEdit protocol extension
1 parent fa2e529 commit a752853

File tree

3 files changed

+57
-5
lines changed

3 files changed

+57
-5
lines changed

crates/rust-analyzer/src/config.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ impl Config {
275275
{
276276
self.client_caps.code_action_literals = value;
277277
}
278+
278279
self.completion.allow_snippets(false);
279280
if let Some(completion) = &doc_caps.completion {
280281
if let Some(completion_item) = &completion.completion_item {
@@ -283,13 +284,19 @@ impl Config {
283284
}
284285
}
285286
}
286-
self.assist.allow_snippets(false);
287287
}
288288

289289
if let Some(window_caps) = caps.window.as_ref() {
290290
if let Some(value) = window_caps.work_done_progress {
291291
self.client_caps.work_done_progress = value;
292292
}
293293
}
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+
}
294301
}
295302
}

docs/dev/lsp-extensions.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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`.

editors/code/src/client.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export function createClient(serverPath: string, cwd: string): lc.LanguageClient
3535
} as any
3636
};
3737

38-
const res = new lc.LanguageClient(
38+
const client = new lc.LanguageClient(
3939
'rust-analyzer',
4040
'Rust Analyzer Language Server',
4141
serverOptions,
@@ -47,8 +47,19 @@ export function createClient(serverPath: string, cwd: string): lc.LanguageClient
4747
// since they are available on stable.
4848
// Note that while these features are stable in vscode their LSP protocol
4949
// implementations are still in the "proposed" category for 3.16.
50-
res.registerFeature(new CallHierarchyFeature(res));
51-
res.registerFeature(new SemanticTokensFeature(res));
50+
client.registerFeature(new CallHierarchyFeature(client));
51+
client.registerFeature(new SemanticTokensFeature(client));
52+
client.registerFeature(new SnippetTextEditFeature());
5253

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+
}
5465
}

0 commit comments

Comments
 (0)