Skip to content

Commit ff52e1c

Browse files
committed
Add snippetTextEdit protocol extension
1 parent 97994db commit ff52e1c

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
@@ -234,6 +234,7 @@ impl Config {
234234
{
235235
self.client_caps.code_action_literals = value;
236236
}
237+
237238
self.completion.allow_snippets(false);
238239
if let Some(completion) = &doc_caps.completion {
239240
if let Some(completion_item) = &completion.completion_item {
@@ -242,13 +243,19 @@ impl Config {
242243
}
243244
}
244245
}
245-
self.assist.allow_snippets(false);
246246
}
247247

248248
if let Some(window_caps) = caps.window.as_ref() {
249249
if let Some(value) = window_caps.work_done_progress {
250250
self.client_caps.work_done_progress = value;
251251
}
252252
}
253+
254+
self.assist.allow_snippets(false);
255+
if let Some(experimental) = &caps.experimental {
256+
let enable =
257+
experimental.get("snippetTextEdit").and_then(|it| it.as_bool()) == Some(true);
258+
self.assist.allow_snippets(enable);
259+
}
253260
}
254261
}

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)