aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorMikhail Rakhmanov <[email protected]>2020-06-03 19:10:54 +0100
committerMikhail Rakhmanov <[email protected]>2020-06-03 19:10:54 +0100
commiteefa10bc6bff3624ddd0bbb6bc89d8beb4bed186 (patch)
tree15c38c2993c52f4065d338090ca9185cc1fcd3da /docs
parenta9d567584857b1be4ca8eaa5ef2c7d85f7b2845e (diff)
parent794f6da821c5d6e2490b996baffe162e4753262d (diff)
Merge branch 'master' into assists_extract_enum
Diffstat (limited to 'docs')
-rw-r--r--docs/dev/README.md105
-rw-r--r--docs/dev/lsp-extensions.md341
-rw-r--r--docs/dev/lsp-features.md72
-rw-r--r--docs/user/assists.md769
-rw-r--r--docs/user/features.md212
-rw-r--r--docs/user/manual.adoc (renamed from docs/user/readme.adoc)96
6 files changed, 494 insertions, 1101 deletions
diff --git a/docs/dev/README.md b/docs/dev/README.md
index 65cc9fc12..1de5a2aab 100644
--- a/docs/dev/README.md
+++ b/docs/dev/README.md
@@ -30,7 +30,7 @@ https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0
30 30
31* [good-first-issue](https://github.com/rust-analyzer/rust-analyzer/labels/good%20first%20issue) 31* [good-first-issue](https://github.com/rust-analyzer/rust-analyzer/labels/good%20first%20issue)
32 are good issues to get into the project. 32 are good issues to get into the project.
33* [E-mentor](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-mentor) 33* [E-has-instructions](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-has-instructions)
34 issues have links to the code in question and tests. 34 issues have links to the code in question and tests.
35* [E-easy](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy), 35* [E-easy](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy),
36 [E-medium](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-medium), 36 [E-medium](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-medium),
@@ -117,6 +117,109 @@ Additionally, I use `cargo run --release -p rust-analyzer -- analysis-stats
117path/to/some/rust/crate` to run a batch analysis. This is primarily useful for 117path/to/some/rust/crate` to run a batch analysis. This is primarily useful for
118performance optimizations, or for bug minimization. 118performance optimizations, or for bug minimization.
119 119
120# Code Style & Review Process
121
122Our approach to "clean code" is two fold:
123
124* We generally don't block PRs on style changes.
125* At the same time, all code in rust-analyzer is constantly refactored.
126
127It is explicitly OK for reviewer to flag only some nits in the PR, and than send a follow up cleanup PR for things which are easier to explain by example, cc-ing the original author.
128Sending small cleanup PRs (like rename a single local variable) is encouraged.
129
130## Scale of Changes
131
132Everyone knows that it's better to send small & focused pull requests.
133The problem is, sometimes you *have* to, eg, rewrite the whole compiler, and that just doesn't fit into a set of isolated PRs.
134
135The main thing too keep an eye on is the boundaries between various components.
136There are three kinds of changes:
137
1381. Internals of a single component are changed.
139 Specifically, you don't change any `pub` items.
140 A good example here would be an addition of a new assist.
141
1422. API of a component is expanded.
143 Specifically, you add a new `pub` function which wasn't there before.
144 A good example here would be expansion of assist API, for example, to implement lazy assists or assists groups.
145
1463. A new dependency between components is introduced.
147 Specifically, you add a `pub use` reexport from another crate or you add a new line to `[dependencies]` section of `Cargo.toml`.
148 A good example here would be adding reference search capability to the assists crates.
149
150For the first group, the change is generally merged as long as:
151
152* it works for the happy case,
153* it has tests,
154* it doesn't panic for unhappy case.
155
156For the second group, the change would be subjected to quite a bit of scrutiny and iteration.
157The new API needs to be right (or at least easy to change later).
158The actual implementation doesn't matter that much.
159It's very important to minimize the amount of changed lines of code for changes of the second kind.
160Often, you start doing change of the first kind, only to realise that you need to elevate to a change of the second kind.
161In this case, we'll probably ask you to split API changes into a separate PR.
162
163Changes of the third group should be pretty rare, so we don't specify any specific process for them.
164That said, adding an innocent-looking `pub use` is a very simple way to break encapsulation, keep an eye on it!
165
166Note: if you enjoyed this abstract hand-waving about boundaries, you might appreciate
167https://www.tedinski.com/2018/02/06/system-boundaries.html
168
169## Order of Imports
170
171We separate import groups with blank lines
172
173```
174mod x;
175mod y;
176
177use std::{ ... }
178
179use crate_foo::{ ... }
180use crate_bar::{ ... }
181
182use crate::{}
183
184use super::{} // but prefer `use crate::`
185```
186
187## Order of Items
188
189Optimize for the reader who sees the file for the first time, and wants to get the general idea about what's going on.
190People read things from top to bottom, so place most important things first.
191
192Specifically, if all items except one are private, always put the non-private item on top.
193
194Put `struct`s and `enum`s first, functions and impls last.
195
196Do
197
198```
199// Good
200struct Foo {
201 bars: Vec<Bar>
202}
203
204struct Bar;
205```
206
207rather than
208
209```
210// Not as good
211struct Bar;
212
213struct Foo {
214 bars: Vec<Bar>
215}
216```
217
218## Documentation
219
220For `.md` and `.adoc` files, prefer a sentence-per-line format, don't wrap lines.
221If the line is too long, you want to split the sentence in two :-)
222
120# Logging 223# Logging
121 224
122Logging is done by both rust-analyzer and VS Code, so it might be tricky to 225Logging is done by both rust-analyzer and VS Code, so it might be tricky to
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
index 158d3c599..647cf6107 100644
--- a/docs/dev/lsp-extensions.md
+++ b/docs/dev/lsp-extensions.md
@@ -3,7 +3,19 @@
3This document describes LSP extensions used by rust-analyzer. 3This document describes LSP extensions used by rust-analyzer.
4It's a best effort document, when in doubt, consult the source (and send a PR with clarification ;-) ). 4It's a best effort document, when in doubt, consult the source (and send a PR with clarification ;-) ).
5We aim to upstream all non Rust-specific extensions to the protocol, but this is not a top priority. 5We aim to upstream all non Rust-specific extensions to the protocol, but this is not a top priority.
6All capabilities are enabled via `experimental` field of `ClientCapabilities`. 6All capabilities are enabled via `experimental` field of `ClientCapabilities` or `ServerCapabilities`.
7Requests which we hope to upstream live under `experimental/` namespace.
8Requests, which are likely to always remain specific to `rust-analyzer` are under `rust-analyzer/` namespace.
9
10If you want to be notified about the changes to this document, subscribe to [#4604](https://github.com/rust-analyzer/rust-analyzer/issues/4604).
11
12## `initializationOptions`
13
14As `initializationOptions`, `rust-analyzer` expects `"rust-analyzer"` section of the configuration.
15That is, `rust-analyzer` usually sends `"workspace/configuration"` request with `{ "items": ["rust-analyzer"] }` payload.
16`initializationOptions` should contain the same data that would be in the first item of the result.
17It's OK to not send anything, then all the settings would take their default values.
18However, some settings can not be changed after startup at the moment.
7 19
8## Snippet `TextEdit` 20## Snippet `TextEdit`
9 21
@@ -38,6 +50,87 @@ At the moment, rust-analyzer guarantees that only a single edit will have `Inser
38* Where exactly are `SnippetTextEdit`s allowed (only in code actions at the moment)? 50* Where exactly are `SnippetTextEdit`s allowed (only in code actions at the moment)?
39* Can snippets span multiple files (so far, no)? 51* Can snippets span multiple files (so far, no)?
40 52
53## `CodeAction` Groups
54
55**Issue:** https://github.com/microsoft/language-server-protocol/issues/994
56
57**Client Capability:** `{ "codeActionGroup": boolean }`
58
59If this capability is set, `CodeAction` returned from the server contain an additional field, `group`:
60
61```typescript
62interface CodeAction {
63 title: string;
64 group?: string;
65 ...
66}
67```
68
69All code-actions with the same `group` should be grouped under single (extendable) entry in lightbulb menu.
70The set of actions `[ { title: "foo" }, { group: "frobnicate", title: "bar" }, { group: "frobnicate", title: "baz" }]` should be rendered as
71
72```
73💡
74 +-------------+
75 | foo |
76 +-------------+-----+
77 | frobnicate >| bar |
78 +-------------+-----+
79 | baz |
80 +-----+
81```
82
83Alternatively, selecting `frobnicate` could present a user with an additional menu to choose between `bar` and `baz`.
84
85### Example
86
87```rust
88fn main() {
89 let x: Entry/*cursor here*/ = todo!();
90}
91```
92
93Invoking code action at this position will yield two code actions for importing `Entry` from either `collections::HashMap` or `collection::BTreeMap`, grouped under a single "import" group.
94
95### Unresolved Questions
96
97* Is a fixed two-level structure enough?
98* Should we devise a general way to encode custom interaction protocols for GUI refactorings?
99
100## Parent Module
101
102**Issue:** https://github.com/microsoft/language-server-protocol/issues/1002
103
104**Server Capability:** `{ "parentModule": boolean }`
105
106This request is send from client to server to handle "Goto Parent Module" editor action.
107
108**Method:** `experimental/parentModule`
109
110**Request:** `TextDocumentPositionParams`
111
112**Response:** `Location | Location[] | LocationLink[] | null`
113
114
115### Example
116
117```rust
118// src/main.rs
119mod foo;
120// src/foo.rs
121
122/* cursor here*/
123```
124
125`experimental/parentModule` returns a single `Link` to the `mod foo;` declaration.
126
127### Unresolved Question
128
129* An alternative would be to use a more general "gotoSuper" request, which would work for super methods, super classes and super modules.
130 This is the approach IntelliJ Rust is takeing.
131 However, experience shows that super module (which generally has a feeling of navigation between files) should be separate.
132 If you want super module, but the cursor happens to be inside an overriden function, the behavior with single "gotoSuper" request is surprising.
133
41## Join Lines 134## Join Lines
42 135
43**Issue:** https://github.com/microsoft/language-server-protocol/issues/992 136**Issue:** https://github.com/microsoft/language-server-protocol/issues/992
@@ -46,7 +139,7 @@ At the moment, rust-analyzer guarantees that only a single edit will have `Inser
46 139
47This request is send from client to server to handle "Join Lines" editor action. 140This request is send from client to server to handle "Join Lines" editor action.
48 141
49**Method:** `experimental/JoinLines` 142**Method:** `experimental/joinLines`
50 143
51**Request:** 144**Request:**
52 145
@@ -59,11 +152,7 @@ interface JoinLinesParams {
59} 152}
60``` 153```
61 154
62**Response:** 155**Response:** `TextEdit[]`
63
64```typescript
65TextEdit[]
66```
67 156
68### Example 157### Example
69 158
@@ -75,7 +164,7 @@ fn main() {
75} 164}
76``` 165```
77 166
78`experimental/joinLines` yields (curly braces are automagiacally removed) 167`experimental/joinLines` yields (curly braces are automagically removed)
79 168
80```rust 169```rust
81fn main() { 170fn main() {
@@ -89,6 +178,59 @@ fn main() {
89 Currently this is left to editor's discretion, but it might be useful to specify on the server via snippets. 178 Currently this is left to editor's discretion, but it might be useful to specify on the server via snippets.
90 However, it then becomes unclear how it works with multi cursor. 179 However, it then becomes unclear how it works with multi cursor.
91 180
181## On Enter
182
183**Issue:** https://github.com/microsoft/language-server-protocol/issues/1001
184
185**Server Capability:** `{ "onEnter": boolean }`
186
187This request is send from client to server to handle <kbd>Enter</kbd> keypress.
188
189**Method:** `experimental/onEnter`
190
191**Request:**: `TextDocumentPositionParams`
192
193**Response:**
194
195```typescript
196SnippetTextEdit[]
197```
198
199### Example
200
201```rust
202fn main() {
203 // Some /*cursor here*/ docs
204 let x = 92;
205}
206```
207
208`experimental/onEnter` returns the following snippet
209
210```rust
211fn main() {
212 // Some
213 // $0 docs
214 let x = 92;
215}
216```
217
218The primary goal of `onEnter` is to handle automatic indentation when opening a new line.
219This is not yet implemented.
220The secondary goal is to handle fixing up syntax, like continuing doc strings and comments, and escaping `\n` in string literals.
221
222As proper cursor positioning is raison-d'etat for `onEnter`, it uses `SnippetTextEdit`.
223
224### Unresolved Question
225
226* How to deal with synchronicity of the request?
227 One option is to require the client to block until the server returns the response.
228 Another option is to do a OT-style merging of edits from client and server.
229 A third option is to do a record-replay: client applies heuristic on enter immediatelly, then applies all user's keypresses.
230 When the server is ready with the response, the client rollbacks all the changes and applies the recorded actions on top of the correct response.
231* How to deal with multiple carets?
232* Should we extend this to arbitrary typed events and not just `onEnter`?
233
92## Structural Search Replace (SSR) 234## Structural Search Replace (SSR)
93 235
94**Server Capability:** `{ "ssr": boolean }` 236**Server Capability:** `{ "ssr": boolean }`
@@ -124,49 +266,180 @@ SSR with query `foo($a:expr, $b:expr) ==>> ($a).foo($b)` will transform, eg `foo
124* Probably needs search without replace mode 266* Probably needs search without replace mode
125* Needs a way to limit the scope to certain files. 267* Needs a way to limit the scope to certain files.
126 268
127## `CodeAction` Groups 269## Matching Brace
128 270
129**Issue:** https://github.com/microsoft/language-server-protocol/issues/994 271**Issue:** https://github.com/microsoft/language-server-protocol/issues/999
130 272
131**Client Capability:** `{ "codeActionGroup": boolean }` 273**Server Capability:** `{ "matchingBrace": boolean }`
132 274
133If this capability is set, `CodeAction` returned from the server contain an additional field, `group`: 275This request is send from client to server to handle "Matching Brace" editor action.
276
277**Method:** `experimental/matchingBrace`
278
279**Request:**
134 280
135```typescript 281```typescript
136interface CodeAction { 282interface MatchingBraceParams {
137 title: string; 283 textDocument: TextDocumentIdentifier,
138 group?: string; 284 /// Position for each cursor
139 ... 285 positions: Position[],
140} 286}
141``` 287```
142 288
143All code-actions with the same `group` should be grouped under single (extendable) entry in lightbulb menu. 289**Response:**
144The set of actions `[ { title: "foo" }, { group: "frobnicate", title: "bar" }, { group: "frobnicate", title: "baz" }]` should be rendered as
145 290
146``` 291```typescript
147💡 292Position[]
148 +-------------+
149 | foo |
150 +-------------+-----+
151 | frobnicate >| bar |
152 +-------------+-----+
153 | baz |
154 +-----+
155``` 293```
156 294
157Alternatively, selecting `frobnicate` could present a user with an additional menu to choose between `bar` and `baz`.
158
159### Example 295### Example
160 296
161```rust 297```rust
162fn main() { 298fn main() {
163 let x: Entry/*cursor here*/ = todo!(); 299 let x: Vec<()>/*cursor here*/ = vec![]
164} 300}
165``` 301```
166 302
167Invoking code action at this position will yield two code actions for importing `Entry` from either `collections::HashMap` or `collection::BTreeMap`, grouped under a single "import" group. 303`experimental/matchingBrace` yields the position of `<`.
304In many cases, matching braces can be handled by the editor.
305However, some cases (like disambiguating between generics and comparison operations) need a real parser.
306Moreover, it would be cool if editors didn't need to implement even basic language parsing
168 307
169### Unresolved Questions 308### Unresolved Question
170 309
171* Is a fixed two-level structure enough? 310* Should we return a a nested brace structure, to allow paredit-like actions of jump *out* of the current brace pair?
172* Should we devise a general way to encode custom interaction protocols for GUI refactorings? 311 This is how `SelectionRange` request works.
312* Alternatively, should we perhaps flag certain `SelectionRange`s as being brace pairs?
313
314## Runnables
315
316**Issue:** https://github.com/microsoft/language-server-protocol/issues/944
317
318**Server Capability:** `{ "runnables": { "kinds": string[] } }`
319
320This request is send from client to server to get the list of things that can be run (tests, binaries, `cargo check -p`).
321
322**Method:** `experimental/runnables`
323
324**Request:**
325
326```typescript
327interface RunnablesParams {
328 textDocument: TextDocumentIdentifier;
329 /// If null, compute runnables for the whole file.
330 position?: Position;
331}
332```
333
334**Response:** `Runnable[]`
335
336```typescript
337interface Runnable {
338 label: string;
339 /// If this Runnable is associated with a specific function/module, etc, the location of this item
340 location?: LocationLink;
341 /// Running things is necessary technology specific, `kind` needs to be advertised via server capabilities,
342 // the type of `args` is specific to `kind`. The actual running is handled by the client.
343 kind: string;
344 args: any;
345}
346```
347
348rust-analyzer supports only one `kind`, `"cargo"`. The `args` for `"cargo"` look like this:
349
350```typescript
351{
352 workspaceRoot?: string;
353 cargoArgs: string[];
354 executableArgs: string[];
355}
356```
357
358## Analyzer Status
359
360**Method:** `rust-analyzer/analyzerStatus`
361
362**Request:** `null`
363
364**Response:** `string`
365
366Returns internal status message, mostly for debugging purposes.
367
368## Collect Garbage
369
370**Method:** `rust-analyzer/collectGarbage`
371
372**Request:** `null`
373
374**Response:** `null`
375
376Frees some caches. For internal use, and is mostly broken at the moment.
377
378## Syntax Tree
379
380**Method:** `rust-analyzer/syntaxTree`
381
382**Request:**
383
384```typescript
385interface SyntaxTeeParams {
386 textDocument: TextDocumentIdentifier,
387 range?: Range,
388}
389```
390
391**Response:** `string`
392
393Returns textual representation of a parse tree for the file/selected region.
394Primarily for debugging, but very useful for all people working on rust-analyzer itself.
395
396## Expand Macro
397
398**Method:** `rust-analyzer/expandMacro`
399
400**Request:**
401
402```typescript
403interface ExpandMacroParams {
404 textDocument: TextDocumentIdentifier,
405 position: Position,
406}
407```
408
409**Response:**
410
411```typescript
412interface ExpandedMacro {
413 name: string,
414 expansion: string,
415}
416```
417
418Expands macro call at a given position.
419
420## Inlay Hints
421
422**Method:** `rust-analyzer/inlayHints`
423
424This request is send from client to server to render "inlay hints" -- virtual text inserted into editor to show things like inferred types.
425Generally, the client should re-query inlay hints after every modification.
426Note that we plan to move this request to `experimental/inlayHints`, as it is not really Rust-specific, but the current API is not necessary the right one.
427Upstream issue: https://github.com/microsoft/language-server-protocol/issues/956
428
429**Request:**
430
431```typescript
432interface InlayHintsParams {
433 textDocument: TextDocumentIdentifier,
434}
435```
436
437**Response:** `InlayHint[]`
438
439```typescript
440interface InlayHint {
441 kind: "TypeHint" | "ParameterHint" | "ChainingHint",
442 range: Range,
443 label: string,
444}
445```
diff --git a/docs/dev/lsp-features.md b/docs/dev/lsp-features.md
deleted file mode 100644
index 00b0867d7..000000000
--- a/docs/dev/lsp-features.md
+++ /dev/null
@@ -1,72 +0,0 @@
1# Supported LSP features
2
3This list documents LSP features, supported by rust-analyzer.
4
5## General
6- [x] [initialize](https://microsoft.github.io/language-server-protocol/specification#initialize)
7- [x] [initialized](https://microsoft.github.io/language-server-protocol/specification#initialized)
8- [x] [shutdown](https://microsoft.github.io/language-server-protocol/specification#shutdown)
9- [ ] [exit](https://microsoft.github.io/language-server-protocol/specification#exit)
10- [x] [$/cancelRequest](https://microsoft.github.io/language-server-protocol/specification#cancelRequest)
11
12## Workspace
13- [ ] [workspace/workspaceFolders](https://microsoft.github.io/language-server-protocol/specification#workspace_workspaceFolders)
14- [ ] [workspace/didChangeWorkspaceFolders](https://microsoft.github.io/language-server-protocol/specification#workspace_didChangeWorkspaceFolders)
15- [x] [workspace/didChangeConfiguration](https://microsoft.github.io/language-server-protocol/specification#workspace_didChangeConfiguration)
16- [ ] [workspace/configuration](https://microsoft.github.io/language-server-protocol/specification#workspace_configuration)
17- [x] [workspace/didChangeWatchedFiles](https://microsoft.github.io/language-server-protocol/specification#workspace_didChangeWatchedFiles)
18- [x] [workspace/symbol](https://microsoft.github.io/language-server-protocol/specification#workspace_symbol)
19- [ ] [workspace/applyEdit](https://microsoft.github.io/language-server-protocol/specification#workspace_applyEdit)
20
21## Text Synchronization
22- [x] [textDocument/didOpen](https://microsoft.github.io/language-server-protocol/specification#textDocument_didOpen)
23- [x] [textDocument/didChange](https://microsoft.github.io/language-server-protocol/specification#textDocument_didChange)
24- [ ] [textDocument/willSave](https://microsoft.github.io/language-server-protocol/specification#textDocument_willSave)
25- [ ] [textDocument/willSaveWaitUntil](https://microsoft.github.io/language-server-protocol/specification#textDocument_willSaveWaitUntil)
26- [x] [textDocument/didSave](https://microsoft.github.io/language-server-protocol/specification#textDocument_didSave)
27- [x] [textDocument/didClose](https://microsoft.github.io/language-server-protocol/specification#textDocument_didClose)
28
29## Diagnostics
30- [x] [textDocument/publishDiagnostics](https://microsoft.github.io/language-server-protocol/specification#textDocument_publishDiagnostics)
31
32## Lanuguage Features
33- [x] [textDocument/completion](https://microsoft.github.io/language-server-protocol/specification#textDocument_completion)
34 - open close: false
35 - change: Full
36 - will save: false
37 - will save wait until: false
38 - save: false
39- [x] [completionItem/resolve](https://microsoft.github.io/language-server-protocol/specification#completionItem_resolve)
40 - resolve provider: none
41 - trigger characters: `:`, `.`
42- [x] [textDocument/hover](https://microsoft.github.io/language-server-protocol/specification#textDocument_hover)
43- [x] [textDocument/signatureHelp](https://microsoft.github.io/language-server-protocol/specification#textDocument_signatureHelp)
44 - trigger characters: `(`, `,`
45- [ ] [textDocument/declaration](https://microsoft.github.io/language-server-protocol/specification#textDocument_declaration)
46- [x] [textDocument/definition](https://microsoft.github.io/language-server-protocol/specification#textDocument_definition)
47- [x] [textDocument/typeDefinition](https://microsoft.github.io/language-server-protocol/specification#textDocument_typeDefinition)
48- [x] [textDocument/implementation](https://microsoft.github.io/language-server-protocol/specification#textDocument_implementation)
49- [x] [textDocument/references](https://microsoft.github.io/language-server-protocol/specification#textDocument_references)
50- [x] [textDocument/documentHighlight](https://microsoft.github.io/language-server-protocol/specification#textDocument_documentHighlight)
51- [x] [textDocument/documentSymbol](https://microsoft.github.io/language-server-protocol/specification#textDocument_documentSymbol)
52- [x] [textDocument/codeAction](https://microsoft.github.io/language-server-protocol/specification#textDocument_codeAction)
53- [x] [textDocument/selectionRange](https://github.com/Microsoft/language-server-protocol/issues/613)
54 - rust-analyzer.syntaxTree
55 - rust-analyzer.matchingBrace
56 - rust-analyzer.parentModule
57 - rust-analyzer.joinLines
58 - rust-analyzer.run
59 - rust-analyzer.analyzerStatus
60- [x] [textDocument/codeLens](https://microsoft.github.io/language-server-protocol/specification#textDocument_codeLens)
61- [x] [codeLens/resolve](https://microsoft.github.io/language-server-protocol/specification#codeLens_resolve)
62- [ ] [documentLink/resolve](https://microsoft.github.io/language-server-protocol/specification#documentLink_resolve)
63- [ ] [textDocument/documentColor](https://microsoft.github.io/language-server-protocol/specification#textDocument_documentColor)
64- [ ] [textDocument/colorPresentation](https://microsoft.github.io/language-server-protocol/specification#textDocument_colorPresentation)
65- [x] [textDocument/formatting](https://microsoft.github.io/language-server-protocol/specification#textDocument_formatting)
66- [ ] [textDocument/rangeFormatting](https://microsoft.github.io/language-server-protocol/specification#textDocument_rangeFormatting)
67- [x] [textDocument/onTypeFormatting](https://microsoft.github.io/language-server-protocol/specification#textDocument_onTypeFormatting)
68 - first trigger character: `=`
69 - more trigger character `.`
70- [x] [textDocument/rename](https://microsoft.github.io/language-server-protocol/specification#textDocument_rename)
71- [x] [textDocument/prepareRename](https://microsoft.github.io/language-server-protocol/specification#textDocument_prepareRename)
72- [x] [textDocument/foldingRange](https://microsoft.github.io/language-server-protocol/specification#textDocument_foldingRange)
diff --git a/docs/user/assists.md b/docs/user/assists.md
deleted file mode 100644
index 4ad7ea59d..000000000
--- a/docs/user/assists.md
+++ /dev/null
@@ -1,769 +0,0 @@
1# Assists
2
3Cursor position or selection is signified by `┃` character.
4
5
6## `add_custom_impl`
7
8Adds impl block for derived trait.
9
10```rust
11// BEFORE
12#[derive(Deb┃ug, Display)]
13struct S;
14
15// AFTER
16#[derive(Display)]
17struct S;
18
19impl Debug for S {
20 $0
21}
22```
23
24## `add_derive`
25
26Adds a new `#[derive()]` clause to a struct or enum.
27
28```rust
29// BEFORE
30struct Point {
31 x: u32,
32 y: u32,┃
33}
34
35// AFTER
36#[derive($0)]
37struct Point {
38 x: u32,
39 y: u32,
40}
41```
42
43## `add_explicit_type`
44
45Specify type for a let binding.
46
47```rust
48// BEFORE
49fn main() {
50 let x┃ = 92;
51}
52
53// AFTER
54fn main() {
55 let x: i32 = 92;
56}
57```
58
59## `add_function`
60
61Adds a stub function with a signature matching the function under the cursor.
62
63```rust
64// BEFORE
65struct Baz;
66fn baz() -> Baz { Baz }
67fn foo() {
68 bar┃("", baz());
69}
70
71
72// AFTER
73struct Baz;
74fn baz() -> Baz { Baz }
75fn foo() {
76 bar("", baz());
77}
78
79fn bar(arg: &str, baz: Baz) {
80 ${0:todo!()}
81}
82
83```
84
85## `add_hash`
86
87Adds a hash to a raw string literal.
88
89```rust
90// BEFORE
91fn main() {
92 r#"Hello,┃ World!"#;
93}
94
95// AFTER
96fn main() {
97 r##"Hello, World!"##;
98}
99```
100
101## `add_impl`
102
103Adds a new inherent impl for a type.
104
105```rust
106// BEFORE
107struct Ctx<T: Clone> {
108 data: T,┃
109}
110
111// AFTER
112struct Ctx<T: Clone> {
113 data: T,
114}
115
116impl<T: Clone> Ctx<T> {
117 $0
118}
119```
120
121## `add_impl_default_members`
122
123Adds scaffold for overriding default impl members.
124
125```rust
126// BEFORE
127trait Trait {
128 Type X;
129 fn foo(&self);
130 fn bar(&self) {}
131}
132
133impl Trait for () {
134 Type X = ();
135 fn foo(&self) {}┃
136
137}
138
139// AFTER
140trait Trait {
141 Type X;
142 fn foo(&self);
143 fn bar(&self) {}
144}
145
146impl Trait for () {
147 Type X = ();
148 fn foo(&self) {}
149 $0fn bar(&self) {}
150
151}
152```
153
154## `add_impl_missing_members`
155
156Adds scaffold for required impl members.
157
158```rust
159// BEFORE
160trait Trait<T> {
161 Type X;
162 fn foo(&self) -> T;
163 fn bar(&self) {}
164}
165
166impl Trait<u32> for () {┃
167
168}
169
170// AFTER
171trait Trait<T> {
172 Type X;
173 fn foo(&self) -> T;
174 fn bar(&self) {}
175}
176
177impl Trait<u32> for () {
178 fn foo(&self) -> u32 {
179 ${0:todo!()}
180 }
181
182}
183```
184
185## `add_new`
186
187Adds a new inherent impl for a type.
188
189```rust
190// BEFORE
191struct Ctx<T: Clone> {
192 data: T,┃
193}
194
195// AFTER
196struct Ctx<T: Clone> {
197 data: T,
198}
199
200impl<T: Clone> Ctx<T> {
201 fn $0new(data: T) -> Self { Self { data } }
202}
203
204```
205
206## `add_turbo_fish`
207
208Adds `::<_>` to a call of a generic method or function.
209
210```rust
211// BEFORE
212fn make<T>() -> T { todo!() }
213fn main() {
214 let x = make┃();
215}
216
217// AFTER
218fn make<T>() -> T { todo!() }
219fn main() {
220 let x = make::<${0:_}>();
221}
222```
223
224## `apply_demorgan`
225
226Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws).
227This transforms expressions of the form `!l || !r` into `!(l && r)`.
228This also works with `&&`. This assist can only be applied with the cursor
229on either `||` or `&&`, with both operands being a negation of some kind.
230This means something of the form `!x` or `x != y`.
231
232```rust
233// BEFORE
234fn main() {
235 if x != 4 ||┃ !y {}
236}
237
238// AFTER
239fn main() {
240 if !(x == 4 && y) {}
241}
242```
243
244## `auto_import`
245
246If the name is unresolved, provides all possible imports for it.
247
248```rust
249// BEFORE
250fn main() {
251 let map = HashMap┃::new();
252}
253
254// AFTER
255use std::collections::HashMap;
256
257fn main() {
258 let map = HashMap::new();
259}
260```
261
262## `change_return_type_to_result`
263
264Change the function's return type to Result.
265
266```rust
267// BEFORE
268fn foo() -> i32┃ { 42i32 }
269
270// AFTER
271fn foo() -> Result<i32, ${0:_}> { Ok(42i32) }
272```
273
274## `change_visibility`
275
276Adds or changes existing visibility specifier.
277
278```rust
279// BEFORE
280┃fn frobnicate() {}
281
282// AFTER
283pub(crate) fn frobnicate() {}
284```
285
286## `convert_to_guarded_return`
287
288Replace a large conditional with a guarded return.
289
290```rust
291// BEFORE
292fn main() {
293 ┃if cond {
294 foo();
295 bar();
296 }
297}
298
299// AFTER
300fn main() {
301 if !cond {
302 return;
303 }
304 foo();
305 bar();
306}
307```
308
309## `fill_match_arms`
310
311Adds missing clauses to a `match` expression.
312
313```rust
314// BEFORE
315enum Action { Move { distance: u32 }, Stop }
316
317fn handle(action: Action) {
318 match action {
319 ┃
320 }
321}
322
323// AFTER
324enum Action { Move { distance: u32 }, Stop }
325
326fn handle(action: Action) {
327 match action {
328 $0Action::Move { distance } => {}
329 Action::Stop => {}
330 }
331}
332```
333
334## `fix_visibility`
335
336Makes inaccessible item public.
337
338```rust
339// BEFORE
340mod m {
341 fn frobnicate() {}
342}
343fn main() {
344 m::frobnicate┃() {}
345}
346
347// AFTER
348mod m {
349 $0pub(crate) fn frobnicate() {}
350}
351fn main() {
352 m::frobnicate() {}
353}
354```
355
356## `flip_binexpr`
357
358Flips operands of a binary expression.
359
360```rust
361// BEFORE
362fn main() {
363 let _ = 90 +┃ 2;
364}
365
366// AFTER
367fn main() {
368 let _ = 2 + 90;
369}
370```
371
372## `flip_comma`
373
374Flips two comma-separated items.
375
376```rust
377// BEFORE
378fn main() {
379 ((1, 2),┃ (3, 4));
380}
381
382// AFTER
383fn main() {
384 ((3, 4), (1, 2));
385}
386```
387
388## `flip_trait_bound`
389
390Flips two trait bounds.
391
392```rust
393// BEFORE
394fn foo<T: Clone +┃ Copy>() { }
395
396// AFTER
397fn foo<T: Copy + Clone>() { }
398```
399
400## `inline_local_variable`
401
402Inlines local variable.
403
404```rust
405// BEFORE
406fn main() {
407 let x┃ = 1 + 2;
408 x * 4;
409}
410
411// AFTER
412fn main() {
413 (1 + 2) * 4;
414}
415```
416
417## `introduce_variable`
418
419Extracts subexpression into a variable.
420
421```rust
422// BEFORE
423fn main() {
424 ┃(1 + 2)┃ * 4;
425}
426
427// AFTER
428fn main() {
429 let $0var_name = (1 + 2);
430 var_name * 4;
431}
432```
433
434## `invert_if`
435
436Apply invert_if
437This transforms if expressions of the form `if !x {A} else {B}` into `if x {B} else {A}`
438This also works with `!=`. This assist can only be applied with the cursor
439on `if`.
440
441```rust
442// BEFORE
443fn main() {
444 if┃ !y { A } else { B }
445}
446
447// AFTER
448fn main() {
449 if y { B } else { A }
450}
451```
452
453## `make_raw_string`
454
455Adds `r#` to a plain string literal.
456
457```rust
458// BEFORE
459fn main() {
460 "Hello,┃ World!";
461}
462
463// AFTER
464fn main() {
465 r#"Hello, World!"#;
466}
467```
468
469## `make_usual_string`
470
471Turns a raw string into a plain string.
472
473```rust
474// BEFORE
475fn main() {
476 r#"Hello,┃ "World!""#;
477}
478
479// AFTER
480fn main() {
481 "Hello, \"World!\"";
482}
483```
484
485## `merge_imports`
486
487Merges two imports with a common prefix.
488
489```rust
490// BEFORE
491use std::┃fmt::Formatter;
492use std::io;
493
494// AFTER
495use std::{fmt::Formatter, io};
496```
497
498## `merge_match_arms`
499
500Merges identical match arms.
501
502```rust
503// BEFORE
504enum Action { Move { distance: u32 }, Stop }
505
506fn handle(action: Action) {
507 match action {
508 ┃Action::Move(..) => foo(),
509 Action::Stop => foo(),
510 }
511}
512
513// AFTER
514enum Action { Move { distance: u32 }, Stop }
515
516fn handle(action: Action) {
517 match action {
518 Action::Move(..) | Action::Stop => foo(),
519 }
520}
521```
522
523## `move_arm_cond_to_match_guard`
524
525Moves if expression from match arm body into a guard.
526
527```rust
528// BEFORE
529enum Action { Move { distance: u32 }, Stop }
530
531fn handle(action: Action) {
532 match action {
533 Action::Move { distance } => ┃if distance > 10 { foo() },
534 _ => (),
535 }
536}
537
538// AFTER
539enum Action { Move { distance: u32 }, Stop }
540
541fn handle(action: Action) {
542 match action {
543 Action::Move { distance } if distance > 10 => foo(),
544 _ => (),
545 }
546}
547```
548
549## `move_bounds_to_where_clause`
550
551Moves inline type bounds to a where clause.
552
553```rust
554// BEFORE
555fn apply<T, U, ┃F: FnOnce(T) -> U>(f: F, x: T) -> U {
556 f(x)
557}
558
559// AFTER
560fn apply<T, U, F>(f: F, x: T) -> U where F: FnOnce(T) -> U {
561 f(x)
562}
563```
564
565## `move_guard_to_arm_body`
566
567Moves match guard into match arm body.
568
569```rust
570// BEFORE
571enum Action { Move { distance: u32 }, Stop }
572
573fn handle(action: Action) {
574 match action {
575 Action::Move { distance } ┃if distance > 10 => foo(),
576 _ => (),
577 }
578}
579
580// AFTER
581enum Action { Move { distance: u32 }, Stop }
582
583fn handle(action: Action) {
584 match action {
585 Action::Move { distance } => if distance > 10 { foo() },
586 _ => (),
587 }
588}
589```
590
591## `remove_dbg`
592
593Removes `dbg!()` macro call.
594
595```rust
596// BEFORE
597fn main() {
598 ┃dbg!(92);
599}
600
601// AFTER
602fn main() {
603 92;
604}
605```
606
607## `remove_hash`
608
609Removes a hash from a raw string literal.
610
611```rust
612// BEFORE
613fn main() {
614 r#"Hello,┃ World!"#;
615}
616
617// AFTER
618fn main() {
619 r"Hello, World!";
620}
621```
622
623## `remove_mut`
624
625Removes the `mut` keyword.
626
627```rust
628// BEFORE
629impl Walrus {
630 fn feed(&mut┃ self, amount: u32) {}
631}
632
633// AFTER
634impl Walrus {
635 fn feed(&self, amount: u32) {}
636}
637```
638
639## `reorder_fields`
640
641Reorder the fields of record literals and record patterns in the same order as in
642the definition.
643
644```rust
645// BEFORE
646struct Foo {foo: i32, bar: i32};
647const test: Foo = ┃Foo {bar: 0, foo: 1}
648
649// AFTER
650struct Foo {foo: i32, bar: i32};
651const test: Foo = Foo {foo: 1, bar: 0}
652```
653
654## `replace_if_let_with_match`
655
656Replaces `if let` with an else branch with a `match` expression.
657
658```rust
659// BEFORE
660enum Action { Move { distance: u32 }, Stop }
661
662fn handle(action: Action) {
663 ┃if let Action::Move { distance } = action {
664 foo(distance)
665 } else {
666 bar()
667 }
668}
669
670// AFTER
671enum Action { Move { distance: u32 }, Stop }
672
673fn handle(action: Action) {
674 match action {
675 Action::Move { distance } => foo(distance),
676 _ => bar(),
677 }
678}
679```
680
681## `replace_let_with_if_let`
682
683Replaces `let` with an `if-let`.
684
685```rust
686// BEFORE
687
688fn main(action: Action) {
689 ┃let x = compute();
690}
691
692fn compute() -> Option<i32> { None }
693
694// AFTER
695
696fn main(action: Action) {
697 if let Some(x) = compute() {
698 }
699}
700
701fn compute() -> Option<i32> { None }
702```
703
704## `replace_qualified_name_with_use`
705
706Adds a use statement for a given fully-qualified name.
707
708```rust
709// BEFORE
710fn process(map: std::collections::┃HashMap<String, String>) {}
711
712// AFTER
713use std::collections::HashMap;
714
715fn process(map: HashMap<String, String>) {}
716```
717
718## `replace_unwrap_with_match`
719
720Replaces `unwrap` a `match` expression. Works for Result and Option.
721
722```rust
723// BEFORE
724enum Result<T, E> { Ok(T), Err(E) }
725fn main() {
726 let x: Result<i32, i32> = Result::Ok(92);
727 let y = x.┃unwrap();
728}
729
730// AFTER
731enum Result<T, E> { Ok(T), Err(E) }
732fn main() {
733 let x: Result<i32, i32> = Result::Ok(92);
734 let y = match x {
735 Ok(a) => a,
736 $0_ => unreachable!(),
737 };
738}
739```
740
741## `split_import`
742
743Wraps the tail of import into braces.
744
745```rust
746// BEFORE
747use std::┃collections::HashMap;
748
749// AFTER
750use std::{collections::HashMap};
751```
752
753## `unwrap_block`
754
755This assist removes if...else, for, while and loop control statements to just keep the body.
756
757```rust
758// BEFORE
759fn foo() {
760 if true {┃
761 println!("foo");
762 }
763}
764
765// AFTER
766fn foo() {
767 println!("foo");
768}
769```
diff --git a/docs/user/features.md b/docs/user/features.md
deleted file mode 100644
index 340bce835..000000000
--- a/docs/user/features.md
+++ /dev/null
@@ -1,212 +0,0 @@
1This document is an index of features that the rust-analyzer language server
2provides. Shortcuts are for the default VS Code layout. If there's no shortcut,
3you can use <kbd>Ctrl+Shift+P</kbd> to search for the corresponding action.
4
5### Workspace Symbol <kbd>ctrl+t</kbd>
6
7Uses fuzzy-search to find types, modules and functions by name across your
8project and dependencies. This is **the** most useful feature, which improves code
9navigation tremendously. It mostly works on top of the built-in LSP
10functionality, however `#` and `*` symbols can be used to narrow down the
11search. Specifically,
12
13- `Foo` searches for `Foo` type in the current workspace
14- `foo#` searches for `foo` function in the current workspace
15- `Foo*` searches for `Foo` type among dependencies, including `stdlib`
16- `foo#*` searches for `foo` function among dependencies
17
18That is, `#` switches from "types" to all symbols, `*` switches from the current
19workspace to dependencies.
20
21### Document Symbol <kbd>ctrl+shift+o</kbd>
22
23Provides a tree of the symbols defined in the file. Can be used to
24
25* fuzzy search symbol in a file (super useful)
26* draw breadcrumbs to describe the context around the cursor
27* draw outline of the file
28
29### On Typing Assists
30
31Some features trigger on typing certain characters:
32
33- typing `let =` tries to smartly add `;` if `=` is followed by an existing expression
34- Enter inside comments automatically inserts `///`
35- typing `.` in a chain method call auto-indents
36
37### Extend Selection
38
39Extends the current selection to the encompassing syntactic construct
40(expression, statement, item, module, etc). It works with multiple cursors. This
41is a relatively new feature of LSP:
42https://github.com/Microsoft/language-server-protocol/issues/613, check your
43editor's LSP library to see if this feature is supported.
44
45### Go to Definition
46
47Navigates to the definition of an identifier.
48
49### Go to Implementation
50
51Navigates to the impl block of structs, enums or traits. Also implemented as a code lens.
52
53### Go to Type Defintion
54
55Navigates to the type of an identifier.
56
57### Commands <kbd>ctrl+shift+p</kbd>
58
59#### Run
60
61Shows a popup suggesting to run a test/benchmark/binary **at the current cursor
62location**. Super useful for repeatedly running just a single test. Do bind this
63to a shortcut!
64
65#### Parent Module
66
67Navigates to the parent module of the current module.
68
69#### Matching Brace
70
71If the cursor is on any brace (`<>(){}[]`) which is a part of a brace-pair,
72moves cursor to the matching brace. It uses the actual parser to determine
73braces, so it won't confuse generics with comparisons.
74
75#### Join Lines
76
77Join selected lines into one, smartly fixing up whitespace and trailing commas.
78
79#### Show Syntax Tree
80
81Shows the parse tree of the current file. It exists mostly for debugging
82rust-analyzer itself.
83
84#### Expand Macro Recursively
85
86Shows the full macro expansion of the macro at current cursor.
87
88#### Status
89
90Shows internal statistic about memory usage of rust-analyzer.
91
92#### Show RA Version
93
94Show current rust-analyzer version.
95
96#### Run Garbage Collection
97
98Manually triggers GC.
99
100#### Start Cargo Watch
101
102Start `cargo watch` for live error highlighting. Will prompt to install if it's not already installed.
103
104#### Stop Cargo Watch
105
106Stop `cargo watch`.
107
108#### Structural Seach and Replace
109
110Search and replace with named wildcards that will match any expression.
111The syntax for a structural search replace command is `<search_pattern> ==>> <replace_pattern>`. A `$<name>:expr` placeholder in the search pattern will match any expression and `$<name>` will reference it in the replacement. Available via the command `rust-analyzer.ssr`.
112
113```rust
114// Using structural search replace command [foo($a:expr, $b:expr) ==>> ($a).foo($b)]
115
116// BEFORE
117String::from(foo(y + 5, z))
118
119// AFTER
120String::from((y + 5).foo(z))
121```
122
123### Assists (Code Actions)
124
125Assists, or code actions, are small local refactorings, available in a particular context.
126They are usually triggered by a shortcut or by clicking a light bulb icon in the editor.
127
128See [assists.md](./assists.md) for the list of available assists.
129
130### Magic Completions
131
132In addition to usual reference completion, rust-analyzer provides some ✨magic✨
133completions as well:
134
135Keywords like `if`, `else` `while`, `loop` are completed with braces, and cursor
136is placed at the appropriate position. Even though `if` is easy to type, you
137still want to complete it, to get ` { }` for free! `return` is inserted with a
138space or `;` depending on the return type of the function.
139
140When completing a function call, `()` are automatically inserted. If a function
141takes arguments, the cursor is positioned inside the parenthesis.
142
143There are postfix completions, which can be triggered by typing something like
144`foo().if`. The word after `.` determines postfix completion. Possible variants are:
145
146- `expr.if` -> `if expr {}` or `if let ... {}` for `Option` or `Result`
147- `expr.match` -> `match expr {}`
148- `expr.while` -> `while expr {}` or `while let ... {}` for `Option` or `Result`
149- `expr.ref` -> `&expr`
150- `expr.refm` -> `&mut expr`
151- `expr.not` -> `!expr`
152- `expr.dbg` -> `dbg!(expr)`
153
154There also snippet completions:
155
156#### Inside Expressions
157
158- `pd` -> `println!("{:?}")`
159- `ppd` -> `println!("{:#?}")`
160
161#### Inside Modules
162
163- `tfn` -> `#[test] fn f(){}`
164- `tmod` ->
165```rust
166#[cfg(test)]
167mod tests {
168 use super::*;
169
170 #[test]
171 fn test_fn() {}
172}
173```
174
175### Code Highlighting
176
177Experimental feature to let rust-analyzer highlight Rust code instead of using the
178default highlighter.
179
180#### Rainbow Highlighting
181
182Experimental feature that, given code highlighting using rust-analyzer is
183active, will pick unique colors for identifiers.
184
185### Code hints
186
187Rust-analyzer has two types of hints to show the information about the code:
188
189* hover hints, appearing on hover on any element.
190
191These contain extended information on the hovered language item.
192
193* inlay hints, shown near the element hinted directly in the editor.
194
195Two types of inlay hints are displayed currently:
196
197* type hints, displaying the minimal information on the type of the expression (if the information is available)
198* method chaining hints, type information for multi-line method chains
199* parameter name hints, displaying the names of the parameters in the corresponding methods
200
201#### VS Code
202
203In VS Code, the following settings can be used to configure the inlay hints:
204
205* `rust-analyzer.inlayHints.typeHints` - enable hints for inferred types.
206* `rust-analyzer.inlayHints.chainingHints` - enable hints for inferred types on method chains.
207* `rust-analyzer.inlayHints.parameterHints` - enable hints for function parameters.
208* `rust-analyzer.inlayHints.maxLength` — shortens the hints if their length exceeds the value specified. If no value is specified (`null`), no shortening is applied.
209
210**Note:** VS Code does not have native support for inlay hints [yet](https://github.com/microsoft/vscode/issues/16221) and the hints are implemented using decorations.
211This approach has limitations, the caret movement and bracket highlighting near the edges of the hint may be weird:
212[1](https://github.com/rust-analyzer/rust-analyzer/issues/1623), [2](https://github.com/rust-analyzer/rust-analyzer/issues/3453).
diff --git a/docs/user/readme.adoc b/docs/user/manual.adoc
index 40ed54809..ea714f49a 100644
--- a/docs/user/readme.adoc
+++ b/docs/user/manual.adoc
@@ -2,14 +2,9 @@
2:toc: preamble 2:toc: preamble
3:sectanchors: 3:sectanchors:
4:page-layout: post 4:page-layout: post
5// https://gist.github.com/dcode/0cfbf2699a1fe9b46ff04c41721dda74#admonitions 5:icons: font
6:tip-caption: :bulb: 6:source-highlighter: rouge
7:note-caption: :information_source: 7:experimental:
8:important-caption: :heavy_exclamation_mark:
9:caution-caption: :fire:
10:warning-caption: :warning:
11
12
13 8
14// Master copy of this document lives in the https://github.com/rust-analyzer/rust-analyzer repository 9// Master copy of this document lives in the https://github.com/rust-analyzer/rust-analyzer repository
15 10
@@ -19,7 +14,9 @@ https://microsoft.github.io/language-server-protocol/[Language Server Protocol]
19The LSP allows various code editors, like VS Code, Emacs or Vim, to implement semantic features like completion or goto definition by talking to an external language server process. 14The LSP allows various code editors, like VS Code, Emacs or Vim, to implement semantic features like completion or goto definition by talking to an external language server process.
20 15
21To improve this document, send a pull request against 16To improve this document, send a pull request against
22https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/readme.adoc[this file]. 17https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/manual.adoc[this file].
18
19If you have questions about using rust-analyzer, please ask them in the https://users.rust-lang.org/c/ide/14["`IDEs and Editors`"] topic of Rust users forum.
23 20
24== Installation 21== Installation
25 22
@@ -112,10 +109,23 @@ Here are some useful self-diagnostic commands:
112* To log all LSP requests, add `"rust-analyzer.trace.server": "verbose"` to the settings and look for `Server Trace` in the panel. 109* To log all LSP requests, add `"rust-analyzer.trace.server": "verbose"` to the settings and look for `Server Trace` in the panel.
113* To enable client-side logging, add `"rust-analyzer.trace.extension": true` to the settings and open the `Console` tab of VS Code developer tools. 110* To enable client-side logging, add `"rust-analyzer.trace.extension": true` to the settings and open the `Console` tab of VS Code developer tools.
114 111
112==== Special `when` clause context for keybindings.
113You may use `inRustProject` context to configure keybindings for rust projects only. For example:
114[source,json]
115----
116{
117 "key": "ctrl+i",
118 "command": "rust-analyzer.toggleInlayHints",
119 "when": "inRustProject"
120}
121----
122More about `when` clause contexts https://code.visualstudio.com/docs/getstarted/keybindings#_when-clause-contexts[here].
123
115=== rust-analyzer Language Server Binary 124=== rust-analyzer Language Server Binary
116 125
117Other editors generally require the `rust-analyzer` binary to be in `$PATH`. 126Other editors generally require the `rust-analyzer` binary to be in `$PATH`.
118You can download the pre-built binary from the https://github.com/rust-analyzer/rust-analyzer/releases[releases] page. Typically, you then need to rename the binary for your platform, e.g. `rust-analyzer-mac` if you're on Mac OS, to `rust-analyzer` and make it executable in addition to moving it into a directory in your `$PATH`. 127You can download the pre-built binary from the https://github.com/rust-analyzer/rust-analyzer/releases[releases] page.
128Typically, you then need to rename the binary for your platform, e.g. `rust-analyzer-mac` if you're on Mac OS, to `rust-analyzer` and make it executable in addition to moving it into a directory in your `$PATH`.
119 129
120On Linux to install the `rust-analyzer` binary into `~/.local/bin`, this commands could be used 130On Linux to install the `rust-analyzer` binary into `~/.local/bin`, this commands could be used
121 131
@@ -135,7 +145,8 @@ $ git clone https://github.com/rust-analyzer/rust-analyzer.git && cd rust-analyz
135$ cargo xtask install --server 145$ cargo xtask install --server
136---- 146----
137 147
138If your editor can't find the binary even though the binary is on your `$PATH`, the likely explanation is that it doesn't see the same `$PATH` as the shell, see https://github.com/rust-analyzer/rust-analyzer/issues/1811[this issue]. On Unix, running the editor from a shell or changing the `.desktop` file to set the environment should help. 148If your editor can't find the binary even though the binary is on your `$PATH`, the likely explanation is that it doesn't see the same `$PATH` as the shell, see https://github.com/rust-analyzer/rust-analyzer/issues/1811[this issue].
149On Unix, running the editor from a shell or changing the `.desktop` file to set the environment should help.
139 150
140==== Arch Linux 151==== Arch Linux
141 152
@@ -258,6 +269,65 @@ Gnome Builder currently has support for RLS, and there's no way to configure the
2581. Rename, symlink or copy the `rust-analyzer` binary to `rls` and place it somewhere Builder can find (in `PATH`, or under `~/.cargo/bin`). 2691. Rename, symlink or copy the `rust-analyzer` binary to `rls` and place it somewhere Builder can find (in `PATH`, or under `~/.cargo/bin`).
2592. Enable the Rust Builder plugin. 2702. Enable the Rust Builder plugin.
260 271
261== Usage 272== Non-Cargo Based Projects
273
274rust-analyzer does not require Cargo.
275However, if you use some other build system, you'll have to describe the structure of your project for rust-analyzer in the `rust-project.json` format:
276
277[source,TypeScript]
278----
279interface JsonProject {
280 /// The set of paths containing the crates for this project.
281 /// Any `Crate` must be nested inside some `root`.
282 roots: string[];
283 /// The set of crates comprising the current project.
284 /// Must include all transitive dependencies as well as sysroot crate (libstd, libcore and such).
285 crates: Crate[];
286}
287
288interface Crate {
289 /// Path to the root module of the crate.
290 root_module: string;
291 /// Edition of the crate.
292 edition: "2015" | "2018";
293 /// Dependencies
294 deps: Dep[];
295 /// The set of cfgs activated for a given crate, like `["unix", "feature=foo", "feature=bar"]`.
296 cfg: string[];
297
298 /// value of the OUT_DIR env variable.
299 out_dir?: string;
300 /// For proc-macro crates, path to compiles proc-macro (.so file).
301 proc_macro_dylib_path?: string;
302}
303
304interface Dep {
305 /// Index of a crate in the `crates` array.
306 crate: number,
307 /// Name as should appear in the (implicit) `extern crate name` declaration.
308 name: string,
309}
310----
311
312This format is provisional and subject to change.
313Specifically, the `roots` setup will be different eventually.
314
315There are tree ways to feed `rust-project.json` to rust-analyzer:
316
317* Place `rust-project.json` file at the root of the project, and rust-anlayzer will discover it.
318* Specify `"rust-analyzer.linkedProjects": [ "path/to/rust-project.json" ]` in the settings (and make sure that your LSP client sends settings as a part of initialize request).
319* Specify `"rust-analyzer.linkedProjects": [ { "roots": [...], "crates": [...] }]` inline.
320
321See https://github.com/rust-analyzer/rust-project.json-example for a small example.
322
323== Features
324
325include::./generated_features.adoc[]
326
327== Assists (Code Actions)
328
329Assists, or code actions, are small local refactorings, available in a particular context.
330They are usually triggered by a shortcut or by clicking a light bulb icon in the editor.
331Cursor position or selection is signified by `┃` character.
262 332
263See https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/features.md[features.md]. 333include::./generated_assists.adoc[]