aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/dev/README.md111
-rw-r--r--docs/dev/architecture.md4
-rw-r--r--docs/dev/debugging.md14
-rw-r--r--docs/dev/guide.md8
-rw-r--r--docs/dev/lsp-extensions.md445
-rw-r--r--docs/dev/lsp-features.md72
-rw-r--r--docs/dev/syntax.md42
-rw-r--r--docs/user/assists.md697
-rw-r--r--docs/user/features.md202
-rw-r--r--docs/user/generated_assists.adoc1015
-rw-r--r--docs/user/generated_features.adoc298
-rw-r--r--docs/user/manual.adoc (renamed from docs/user/readme.adoc)95
12 files changed, 1959 insertions, 1044 deletions
diff --git a/docs/dev/README.md b/docs/dev/README.md
index f230dc1db..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),
@@ -74,7 +74,7 @@ relevant test and execute it (VS Code includes an action for running a single
74test). 74test).
75 75
76However, launching a VS Code instance with locally build language server is 76However, launching a VS Code instance with locally build language server is
77possible. There's **"Run Extension (Dev Server)"** launch configuration for this. 77possible. There's **"Run Extension (Debug Build)"** launch configuration for this.
78 78
79In general, I use one of the following workflows for fixing bugs and 79In general, I use one of the following workflows for fixing bugs and
80implementing features. 80implementing features.
@@ -86,7 +86,7 @@ then just do printf-driven development/debugging. As a sanity check after I'm
86done, I use `cargo xtask install --server` and **Reload Window** action in VS 86done, I use `cargo xtask install --server` and **Reload Window** action in VS
87Code to sanity check that the thing works as I expect. 87Code to sanity check that the thing works as I expect.
88 88
89If the problem concerns only the VS Code extension, I use **Run Extension** 89If the problem concerns only the VS Code extension, I use **Run Installed Extension**
90launch configuration from `launch.json`. Notably, this uses the usual 90launch configuration from `launch.json`. Notably, this uses the usual
91`rust-analyzer` binary from `PATH`. For this it is important to have the following 91`rust-analyzer` binary from `PATH`. For this it is important to have the following
92in `setting.json` file: 92in `setting.json` file:
@@ -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
@@ -134,7 +237,7 @@ To log all communication between the server and the client, there are two choice
134 237
135* you can log on the server side, by running something like 238* you can log on the server side, by running something like
136 ``` 239 ```
137 env RUST_LOG=gen_lsp_server=trace code . 240 env RA_LOG=gen_lsp_server=trace code .
138 ``` 241 ```
139 242
140* you can log on the client side, by enabling `"rust-analyzer.trace.server": 243* you can log on the client side, by enabling `"rust-analyzer.trace.server":
diff --git a/docs/dev/architecture.md b/docs/dev/architecture.md
index 3a337c574..cee916c09 100644
--- a/docs/dev/architecture.md
+++ b/docs/dev/architecture.md
@@ -46,7 +46,7 @@ can be quickly updated for small modifications.
46 46
47Some of the components of this repository are generated through automatic 47Some of the components of this repository are generated through automatic
48processes. `cargo xtask codegen` runs all generation tasks. Generated code is 48processes. `cargo xtask codegen` runs all generation tasks. Generated code is
49commited to the git repository. 49committed to the git repository.
50 50
51In particular, `cargo xtask codegen` generates: 51In particular, `cargo xtask codegen` generates:
52 52
@@ -114,7 +114,7 @@ is responsible for guessing a HIR for a particular source position.
114Underneath, HIR works on top of salsa, using a `HirDatabase` trait. 114Underneath, HIR works on top of salsa, using a `HirDatabase` trait.
115 115
116`ra_hir_xxx` crates have a strong ECS flavor, in that they work with raw ids and 116`ra_hir_xxx` crates have a strong ECS flavor, in that they work with raw ids and
117directly query the databse. 117directly query the database.
118 118
119The top-level `ra_hir` façade crate wraps ids into a more OO-flavored API. 119The top-level `ra_hir` façade crate wraps ids into a more OO-flavored API.
120 120
diff --git a/docs/dev/debugging.md b/docs/dev/debugging.md
index bece6a572..59a83f7d7 100644
--- a/docs/dev/debugging.md
+++ b/docs/dev/debugging.md
@@ -22,11 +22,11 @@ where **only** the `rust-analyzer` extension being debugged is enabled.
22 22
23## Debug TypeScript VSCode extension 23## Debug TypeScript VSCode extension
24 24
25- `Run Extension` - runs the extension with the globally installed `rust-analyzer` binary. 25- `Run Installed Extension` - runs the extension with the globally installed `rust-analyzer` binary.
26- `Run Extension (Dev Server)` - runs extension with the locally built LSP server (`target/debug/rust-analyzer`). 26- `Run Extension (Debug Build)` - runs extension with the locally built LSP server (`target/debug/rust-analyzer`).
27 27
28TypeScript debugging is configured to watch your source edits and recompile. 28TypeScript debugging is configured to watch your source edits and recompile.
29To apply changes to an already running debug process press <kbd>Ctrl+Shift+P</kbd> and run the following command in your `[Extension Development Host]` 29To apply changes to an already running debug process, press <kbd>Ctrl+Shift+P</kbd> and run the following command in your `[Extension Development Host]`
30 30
31``` 31```
32> Developer: Reload Window 32> Developer: Reload Window
@@ -47,7 +47,7 @@ To apply changes to an already running debug process press <kbd>Ctrl+Shift+P</kb
47 debug = 2 47 debug = 2
48 ``` 48 ```
49 49
50- Select `Run Extension (Dev Server)` to run your locally built `target/debug/rust-analyzer`. 50- Select `Run Extension (Debug Build)` to run your locally built `target/debug/rust-analyzer`.
51 51
52- In the original VSCode window once again select the `Attach To Server` debug configuration. 52- In the original VSCode window once again select the `Attach To Server` debug configuration.
53 53
@@ -76,11 +76,11 @@ Make sure you open a rust file in the `[Extension Development Host]` and try aga
76 76
77Make sure you have run `echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope`. 77Make sure you have run `echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope`.
78 78
79By default this should reset back to 1 everytime you log in. 79By default this should reset back to 1 every time you log in.
80 80
81### Breakpoints are never being hit 81### Breakpoints are never being hit
82 82
83Check your version of `lldb` if it's version 6 and lower use the `classic` adapter type. 83Check your version of `lldb`. If it's version 6 and lower, use the `classic` adapter type.
84It's `lldb.adapterType` in settings file. 84It's `lldb.adapterType` in settings file.
85 85
86If you're running `lldb` version 7 change the lldb adapter type to `bundled` or `native`. 86If you're running `lldb` version 7, change the lldb adapter type to `bundled` or `native`.
diff --git a/docs/dev/guide.md b/docs/dev/guide.md
index abbe4c154..c3252f1f6 100644
--- a/docs/dev/guide.md
+++ b/docs/dev/guide.md
@@ -26,7 +26,7 @@ properties hold:
26 26
27## IDE API 27## IDE API
28 28
29To see the bigger picture of how the IDE features works, let's take a look at the [`AnalysisHost`] and 29To see the bigger picture of how the IDE features work, let's take a look at the [`AnalysisHost`] and
30[`Analysis`] pair of types. `AnalysisHost` has three methods: 30[`Analysis`] pair of types. `AnalysisHost` has three methods:
31 31
32* `default()` for creating an empty analysis instance 32* `default()` for creating an empty analysis instance
@@ -131,7 +131,7 @@ mapping between `SourceRoot` IDs (which are assigned by the client) and actual
131analyzer. 131analyzer.
132 132
133Note that `mod`, `#[path]` and `include!()` can only reference files from the 133Note that `mod`, `#[path]` and `include!()` can only reference files from the
134same source root. It is of course is possible to explicitly add extra files to 134same source root. It is of course possible to explicitly add extra files to
135the source root, even `/dev/random`. 135the source root, even `/dev/random`.
136 136
137## Language Server Protocol 137## Language Server Protocol
@@ -192,7 +192,7 @@ task will be canceled as soon as the main loop calls `apply_change` on the
192[`schedule`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L426-L455 192[`schedule`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L426-L455
193[The task]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop/handlers.rs#L205-L223 193[The task]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop/handlers.rs#L205-L223
194 194
195This concludes the overview of the analyzer's programing *interface*. Next, lets 195This concludes the overview of the analyzer's programing *interface*. Next, let's
196dig into the implementation! 196dig into the implementation!
197 197
198## Salsa 198## Salsa
@@ -480,7 +480,7 @@ throughout the analyzer:
480## Source Map pattern 480## Source Map pattern
481 481
482Due to an obscure edge case in completion, IDE needs to know the syntax node of 482Due to an obscure edge case in completion, IDE needs to know the syntax node of
483an use statement which imported the given completion candidate. We can't just 483a use statement which imported the given completion candidate. We can't just
484store the syntax node as a part of name resolution: this will break 484store the syntax node as a part of name resolution: this will break
485incrementality, due to the fact that syntax changes after every file 485incrementality, due to the fact that syntax changes after every file
486modification. 486modification.
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
new file mode 100644
index 000000000..647cf6107
--- /dev/null
+++ b/docs/dev/lsp-extensions.md
@@ -0,0 +1,445 @@
1# LSP Extensions
2
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 ;-) ).
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` 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.
19
20## Snippet `TextEdit`
21
22**Issue:** https://github.com/microsoft/language-server-protocol/issues/724
23
24**Client Capability:** `{ "snippetTextEdit": boolean }`
25
26If this capability is set, `WorkspaceEdit`s returned from `codeAction` requests might contain `SnippetTextEdit`s instead of usual `TextEdit`s:
27
28```typescript
29interface SnippetTextEdit extends TextEdit {
30 insertTextFormat?: InsertTextFormat;
31}
32```
33
34```typescript
35export interface TextDocumentEdit {
36 textDocument: VersionedTextDocumentIdentifier;
37 edits: (TextEdit | SnippetTextEdit)[];
38}
39```
40
41When applying such code action, the editor should insert snippet, with tab stops and placeholder.
42At the moment, rust-analyzer guarantees that only a single edit will have `InsertTextFormat.Snippet`.
43
44### Example
45
46"Add `derive`" code action transforms `struct S;` into `#[derive($0)] struct S;`
47
48### Unresolved Questions
49
50* Where exactly are `SnippetTextEdit`s allowed (only in code actions at the moment)?
51* Can snippets span multiple files (so far, no)?
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
134## Join Lines
135
136**Issue:** https://github.com/microsoft/language-server-protocol/issues/992
137
138**Server Capability:** `{ "joinLines": boolean }`
139
140This request is send from client to server to handle "Join Lines" editor action.
141
142**Method:** `experimental/joinLines`
143
144**Request:**
145
146```typescript
147interface JoinLinesParams {
148 textDocument: TextDocumentIdentifier,
149 /// Currently active selections/cursor offsets.
150 /// This is an array to support multiple cursors.
151 ranges: Range[],
152}
153```
154
155**Response:** `TextEdit[]`
156
157### Example
158
159```rust
160fn main() {
161 /*cursor here*/let x = {
162 92
163 };
164}
165```
166
167`experimental/joinLines` yields (curly braces are automagically removed)
168
169```rust
170fn main() {
171 let x = 92;
172}
173```
174
175### Unresolved Question
176
177* What is the position of the cursor after `joinLines`?
178 Currently this is left to editor's discretion, but it might be useful to specify on the server via snippets.
179 However, it then becomes unclear how it works with multi cursor.
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
234## Structural Search Replace (SSR)
235
236**Server Capability:** `{ "ssr": boolean }`
237
238This request is send from client to server to handle structural search replace -- automated syntax tree based transformation of the source.
239
240**Method:** `experimental/ssr`
241
242**Request:**
243
244```typescript
245interface SsrParams {
246 /// Search query.
247 /// The specific syntax is specified outside of the protocol.
248 query: string,
249 /// If true, only check the syntax of the query and don't compute the actual edit.
250 parseOnly: bool,
251}
252```
253
254**Response:**
255
256```typescript
257WorkspaceEdit
258```
259
260### Example
261
262SSR with query `foo($a:expr, $b:expr) ==>> ($a).foo($b)` will transform, eg `foo(y + 5, z)` into `(y + 5).foo(z)`.
263
264### Unresolved Question
265
266* Probably needs search without replace mode
267* Needs a way to limit the scope to certain files.
268
269## Matching Brace
270
271**Issue:** https://github.com/microsoft/language-server-protocol/issues/999
272
273**Server Capability:** `{ "matchingBrace": boolean }`
274
275This request is send from client to server to handle "Matching Brace" editor action.
276
277**Method:** `experimental/matchingBrace`
278
279**Request:**
280
281```typescript
282interface MatchingBraceParams {
283 textDocument: TextDocumentIdentifier,
284 /// Position for each cursor
285 positions: Position[],
286}
287```
288
289**Response:**
290
291```typescript
292Position[]
293```
294
295### Example
296
297```rust
298fn main() {
299 let x: Vec<()>/*cursor here*/ = vec![]
300}
301```
302
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
307
308### Unresolved Question
309
310* Should we return a a nested brace structure, to allow paredit-like actions of jump *out* of the current brace pair?
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/dev/syntax.md b/docs/dev/syntax.md
index 33973ffec..c2864bbbc 100644
--- a/docs/dev/syntax.md
+++ b/docs/dev/syntax.md
@@ -64,7 +64,7 @@ struct Token {
64} 64}
65``` 65```
66 66
67All the difference bettwen the above sketch and the real implementation are strictly due to optimizations. 67All the difference between the above sketch and the real implementation are strictly due to optimizations.
68 68
69Points of note: 69Points of note:
70* The tree is untyped. Each node has a "type tag", `SyntaxKind`. 70* The tree is untyped. Each node has a "type tag", `SyntaxKind`.
@@ -72,7 +72,7 @@ Points of note:
72* Trivia and non-trivia tokens are not distinguished on the type level. 72* Trivia and non-trivia tokens are not distinguished on the type level.
73* Each token carries its full text. 73* Each token carries its full text.
74* The original text can be recovered by concatenating the texts of all tokens in order. 74* The original text can be recovered by concatenating the texts of all tokens in order.
75* Accessing a child of particular type (for example, parameter list of a function) generarly involves linerary traversing the children, looking for a specific `kind`. 75* Accessing a child of particular type (for example, parameter list of a function) generally involves linerary traversing the children, looking for a specific `kind`.
76* Modifying the tree is roughly `O(depth)`. 76* Modifying the tree is roughly `O(depth)`.
77 We don't make special efforts to guarantree that the depth is not liner, but, in practice, syntax trees are branchy and shallow. 77 We don't make special efforts to guarantree that the depth is not liner, but, in practice, syntax trees are branchy and shallow.
78* If mandatory (grammar wise) node is missing from the input, it's just missing from the tree. 78* If mandatory (grammar wise) node is missing from the input, it's just missing from the tree.
@@ -123,7 +123,7 @@ To more compactly store the children, we box *both* interior nodes and tokens, a
123`Either<Arc<Node>, Arc<Token>>` as a single pointer with a tag in the last bit. 123`Either<Arc<Node>, Arc<Token>>` as a single pointer with a tag in the last bit.
124 124
125To avoid allocating EVERY SINGLE TOKEN on the heap, syntax trees use interning. 125To avoid allocating EVERY SINGLE TOKEN on the heap, syntax trees use interning.
126Because the tree is fully imutable, it's valid to structuraly share subtrees. 126Because the tree is fully immutable, it's valid to structurally share subtrees.
127For example, in `1 + 1`, there will be a *single* token for `1` with ref count 2; the same goes for the ` ` whitespace token. 127For example, in `1 + 1`, there will be a *single* token for `1` with ref count 2; the same goes for the ` ` whitespace token.
128Interior nodes are shared as well (for example in `(1 + 1) * (1 + 1)`). 128Interior nodes are shared as well (for example in `(1 + 1) * (1 + 1)`).
129 129
@@ -134,8 +134,8 @@ Currently, the interner is created per-file, but it will be easy to use a per-th
134 134
135We use a `TextSize`, a newtyped `u32`, to store the length of the text. 135We use a `TextSize`, a newtyped `u32`, to store the length of the text.
136 136
137We currently use `SmolStr`, an small object optimized string to store text. 137We currently use `SmolStr`, a small object optimized string to store text.
138This was mostly relevant *before* we implmented tree interning, to avoid allocating common keywords and identifiers. We should switch to storing text data alongside the interned tokens. 138This was mostly relevant *before* we implemented tree interning, to avoid allocating common keywords and identifiers. We should switch to storing text data alongside the interned tokens.
139 139
140#### Alternative designs 140#### Alternative designs
141 141
@@ -162,12 +162,12 @@ Explicit trivia nodes, like in `rowan`, are used by IntelliJ.
162 162
163##### Accessing Children 163##### Accessing Children
164 164
165As noted before, accesing a specific child in the node requires a linear traversal of the children (though we can skip tokens, beacuse the tag is encoded in the pointer itself). 165As noted before, accessing a specific child in the node requires a linear traversal of the children (though we can skip tokens, because the tag is encoded in the pointer itself).
166It is possible to recover O(1) access with another representation. 166It is possible to recover O(1) access with another representation.
167We explicitly store optional and missing (required by the grammar, but not present) nodes. 167We explicitly store optional and missing (required by the grammar, but not present) nodes.
168That is, we use `Option<Node>` for children. 168That is, we use `Option<Node>` for children.
169We also remove trivia tokens from the tree. 169We also remove trivia tokens from the tree.
170This way, each child kind genrerally occupies a fixed position in a parent, and we can use index access to fetch it. 170This way, each child kind generally occupies a fixed position in a parent, and we can use index access to fetch it.
171The cost is that we now need to allocate space for all not-present optional nodes. 171The cost is that we now need to allocate space for all not-present optional nodes.
172So, `fn foo() {}` will have slots for visibility, unsafeness, attributes, abi and return type. 172So, `fn foo() {}` will have slots for visibility, unsafeness, attributes, abi and return type.
173 173
@@ -193,7 +193,7 @@ Modeling this with immutable trees is possible, but annoying.
193### Syntax Nodes 193### Syntax Nodes
194 194
195A function green tree is not super-convenient to use. 195A function green tree is not super-convenient to use.
196The biggest problem is acessing parents (there are no parent pointers!). 196The biggest problem is accessing parents (there are no parent pointers!).
197But there are also "identify" issues. 197But there are also "identify" issues.
198Let's say you want to write a code which builds a list of expressions in a file: `fn collect_exrepssions(file: GreenNode) -> HashSet<GreenNode>`. 198Let's say you want to write a code which builds a list of expressions in a file: `fn collect_exrepssions(file: GreenNode) -> HashSet<GreenNode>`.
199For the input like 199For the input like
@@ -207,7 +207,7 @@ fn main() {
207} 207}
208``` 208```
209 209
210both copies of the `x + 2` expression are representing by equal (and, with interning in mind, actualy the same) green nodes. 210both copies of the `x + 2` expression are representing by equal (and, with interning in mind, actually the same) green nodes.
211Green trees just can't differentiate between the two. 211Green trees just can't differentiate between the two.
212 212
213`SyntaxNode` adds parent pointers and identify semantics to green nodes. 213`SyntaxNode` adds parent pointers and identify semantics to green nodes.
@@ -285,9 +285,9 @@ They also point to the parent (and, consequently, to the root) with an owning `R
285In other words, one needs *one* arc bump when initiating a traversal. 285In other words, one needs *one* arc bump when initiating a traversal.
286 286
287To get rid of allocations, `rowan` takes advantage of `SyntaxNode: !Sync` and uses a thread-local free list of `SyntaxNode`s. 287To get rid of allocations, `rowan` takes advantage of `SyntaxNode: !Sync` and uses a thread-local free list of `SyntaxNode`s.
288In a typical traversal, you only directly hold a few `SyntaxNode`s at a time (and their ancesstors indirectly), so a free list proportional to the depth of the tree removes all allocations in a typical case. 288In a typical traversal, you only directly hold a few `SyntaxNode`s at a time (and their ancestors indirectly), so a free list proportional to the depth of the tree removes all allocations in a typical case.
289 289
290So, while traversal is not exactly incrementing a pointer, it's still prety cheep: tls + rc bump! 290So, while traversal is not exactly incrementing a pointer, it's still pretty cheap: TLS + rc bump!
291 291
292Traversal also yields (cheap) owned nodes, which improves ergonomics quite a bit. 292Traversal also yields (cheap) owned nodes, which improves ergonomics quite a bit.
293 293
@@ -308,15 +308,15 @@ struct SyntaxData {
308} 308}
309``` 309```
310 310
311This allows using true pointer equality for comparision of identities of `SyntaxNodes`. 311This allows using true pointer equality for comparison of identities of `SyntaxNodes`.
312rust-analyzer used to have this design as well, but since we've switch to cursors. 312rust-analyzer used to have this design as well, but we've since switched to cursors.
313The main problem with memoizing the red nodes is that it more than doubles the memory requirenments for fully realized syntax trees. 313The main problem with memoizing the red nodes is that it more than doubles the memory requirements for fully realized syntax trees.
314In contrast, cursors generally retain only a path to the root. 314In contrast, cursors generally retain only a path to the root.
315C# combats increased memory usage by using weak references. 315C# combats increased memory usage by using weak references.
316 316
317### AST 317### AST
318 318
319`GreenTree`s are untyped and homogeneous, because it makes accomodating error nodes, arbitrary whitespace and comments natural, and because it makes possible to write generic tree traversals. 319`GreenTree`s are untyped and homogeneous, because it makes accommodating error nodes, arbitrary whitespace and comments natural, and because it makes possible to write generic tree traversals.
320However, when working with a specific node, like a function definition, one would want a strongly typed API. 320However, when working with a specific node, like a function definition, one would want a strongly typed API.
321 321
322This is what is provided by the AST layer. AST nodes are transparent wrappers over untyped syntax nodes: 322This is what is provided by the AST layer. AST nodes are transparent wrappers over untyped syntax nodes:
@@ -397,7 +397,7 @@ impl HasVisbility for FnDef {
397Points of note: 397Points of note:
398 398
399* Like `SyntaxNode`s, AST nodes are cheap to clone pointer-sized owned values. 399* Like `SyntaxNode`s, AST nodes are cheap to clone pointer-sized owned values.
400* All "fields" are optional, to accomodate incomplete and/or erroneous source code. 400* All "fields" are optional, to accommodate incomplete and/or erroneous source code.
401* It's always possible to go from an ast node to an untyped `SyntaxNode`. 401* It's always possible to go from an ast node to an untyped `SyntaxNode`.
402* It's possible to go in the opposite direction with a checked cast. 402* It's possible to go in the opposite direction with a checked cast.
403* `enum`s allow modeling of arbitrary intersecting subsets of AST types. 403* `enum`s allow modeling of arbitrary intersecting subsets of AST types.
@@ -437,13 +437,13 @@ impl GreenNodeBuilder {
437} 437}
438``` 438```
439 439
440The parser, ultimatelly, needs to invoke the `GreenNodeBuilder`. 440The parser, ultimately, needs to invoke the `GreenNodeBuilder`.
441There are two principal sources of inputs for the parser: 441There are two principal sources of inputs for the parser:
442 * source text, which contains trivia tokens (whitespace and comments) 442 * source text, which contains trivia tokens (whitespace and comments)
443 * token trees from macros, which lack trivia 443 * token trees from macros, which lack trivia
444 444
445Additionaly, input tokens do not correspond 1-to-1 with output tokens. 445Additionally, input tokens do not correspond 1-to-1 with output tokens.
446For example, two consequtive `>` tokens might be glued, by the parser, into a single `>>`. 446For example, two consecutive `>` tokens might be glued, by the parser, into a single `>>`.
447 447
448For these reasons, the parser crate defines a callback interfaces for both input tokens and output trees. 448For these reasons, the parser crate defines a callback interfaces for both input tokens and output trees.
449The explicit glue layer then bridges various gaps. 449The explicit glue layer then bridges various gaps.
@@ -491,7 +491,7 @@ Syntax errors are not stored directly in the tree.
491The primary motivation for this is that syntax tree is not necessary produced by the parser, it may also be assembled manually from pieces (which happens all the time in refactorings). 491The primary motivation for this is that syntax tree is not necessary produced by the parser, it may also be assembled manually from pieces (which happens all the time in refactorings).
492Instead, parser reports errors to an error sink, which stores them in a `Vec`. 492Instead, parser reports errors to an error sink, which stores them in a `Vec`.
493If possible, errors are not reported during parsing and are postponed for a separate validation step. 493If possible, errors are not reported during parsing and are postponed for a separate validation step.
494For example, parser accepts visibility modifiers on trait methods, but then a separate tree traversal flags all such visibilites as erroneous. 494For example, parser accepts visibility modifiers on trait methods, but then a separate tree traversal flags all such visibilities as erroneous.
495 495
496### Macros 496### Macros
497 497
@@ -501,7 +501,7 @@ Specifically, `TreeSink` constructs the tree in lockstep with draining the origi
501In the process, it records which tokens of the tree correspond to which tokens of the input, by using text ranges to identify syntax tokens. 501In the process, it records which tokens of the tree correspond to which tokens of the input, by using text ranges to identify syntax tokens.
502The end result is that parsing an expanded code yields a syntax tree and a mapping of text-ranges of the tree to original tokens. 502The end result is that parsing an expanded code yields a syntax tree and a mapping of text-ranges of the tree to original tokens.
503 503
504To deal with precedence in cases like `$expr * 1`, we use special invisible parenthesis, which are explicitelly handled by the parser 504To deal with precedence in cases like `$expr * 1`, we use special invisible parenthesis, which are explicitly handled by the parser
505 505
506### Whitespace & Comments 506### Whitespace & Comments
507 507
diff --git a/docs/user/assists.md b/docs/user/assists.md
deleted file mode 100644
index 6c6943622..000000000
--- a/docs/user/assists.md
+++ /dev/null
@@ -1,697 +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
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()]
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 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
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 fn 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 { todo!() }
179
180}
181```
182
183## `add_new`
184
185Adds a new inherent impl for a type.
186
187```rust
188// BEFORE
189struct Ctx<T: Clone> {
190 data: T,┃
191}
192
193// AFTER
194struct Ctx<T: Clone> {
195 data: T,
196}
197
198impl<T: Clone> Ctx<T> {
199 fn new(data: T) -> Self { Self { data } }
200}
201
202```
203
204## `apply_demorgan`
205
206Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws).
207This transforms expressions of the form `!l || !r` into `!(l && r)`.
208This also works with `&&`. This assist can only be applied with the cursor
209on either `||` or `&&`, with both operands being a negation of some kind.
210This means something of the form `!x` or `x != y`.
211
212```rust
213// BEFORE
214fn main() {
215 if x != 4 ||┃ !y {}
216}
217
218// AFTER
219fn main() {
220 if !(x == 4 && y) {}
221}
222```
223
224## `auto_import`
225
226If the name is unresolved, provides all possible imports for it.
227
228```rust
229// BEFORE
230fn main() {
231 let map = HashMap┃::new();
232}
233
234// AFTER
235use std::collections::HashMap;
236
237fn main() {
238 let map = HashMap::new();
239}
240```
241
242## `change_visibility`
243
244Adds or changes existing visibility specifier.
245
246```rust
247// BEFORE
248┃fn frobnicate() {}
249
250// AFTER
251pub(crate) fn frobnicate() {}
252```
253
254## `convert_to_guarded_return`
255
256Replace a large conditional with a guarded return.
257
258```rust
259// BEFORE
260fn main() {
261 ┃if cond {
262 foo();
263 bar();
264 }
265}
266
267// AFTER
268fn main() {
269 if !cond {
270 return;
271 }
272 foo();
273 bar();
274}
275```
276
277## `fill_match_arms`
278
279Adds missing clauses to a `match` expression.
280
281```rust
282// BEFORE
283enum Action { Move { distance: u32 }, Stop }
284
285fn handle(action: Action) {
286 match action {
287
288 }
289}
290
291// AFTER
292enum Action { Move { distance: u32 }, Stop }
293
294fn handle(action: Action) {
295 match action {
296 Action::Move { distance } => {}
297 Action::Stop => {}
298 }
299}
300```
301
302## `flip_binexpr`
303
304Flips operands of a binary expression.
305
306```rust
307// BEFORE
308fn main() {
309 let _ = 90 +┃ 2;
310}
311
312// AFTER
313fn main() {
314 let _ = 2 + 90;
315}
316```
317
318## `flip_comma`
319
320Flips two comma-separated items.
321
322```rust
323// BEFORE
324fn main() {
325 ((1, 2),┃ (3, 4));
326}
327
328// AFTER
329fn main() {
330 ((3, 4), (1, 2));
331}
332```
333
334## `flip_trait_bound`
335
336Flips two trait bounds.
337
338```rust
339// BEFORE
340fn foo<T: Clone +┃ Copy>() { }
341
342// AFTER
343fn foo<T: Copy + Clone>() { }
344```
345
346## `inline_local_variable`
347
348Inlines local variable.
349
350```rust
351// BEFORE
352fn main() {
353 let x┃ = 1 + 2;
354 x * 4;
355}
356
357// AFTER
358fn main() {
359 (1 + 2) * 4;
360}
361```
362
363## `introduce_variable`
364
365Extracts subexpression into a variable.
366
367```rust
368// BEFORE
369fn main() {
370 ┃(1 + 2)┃ * 4;
371}
372
373// AFTER
374fn main() {
375 let var_name = (1 + 2);
376 var_name * 4;
377}
378```
379
380## `invert_if`
381
382Apply invert_if
383This transforms if expressions of the form `if !x {A} else {B}` into `if x {B} else {A}`
384This also works with `!=`. This assist can only be applied with the cursor
385on `if`.
386
387```rust
388// BEFORE
389fn main() {
390 if┃ !y { A } else { B }
391}
392
393// AFTER
394fn main() {
395 if y { B } else { A }
396}
397```
398
399## `make_raw_string`
400
401Adds `r#` to a plain string literal.
402
403```rust
404// BEFORE
405fn main() {
406 "Hello,┃ World!";
407}
408
409// AFTER
410fn main() {
411 r#"Hello, World!"#;
412}
413```
414
415## `make_usual_string`
416
417Turns a raw string into a plain string.
418
419```rust
420// BEFORE
421fn main() {
422 r#"Hello,┃ "World!""#;
423}
424
425// AFTER
426fn main() {
427 "Hello, \"World!\"";
428}
429```
430
431## `merge_imports`
432
433Merges two imports with a common prefix.
434
435```rust
436// BEFORE
437use std::┃fmt::Formatter;
438use std::io;
439
440// AFTER
441use std::{fmt::Formatter, io};
442```
443
444## `merge_match_arms`
445
446Merges identical match arms.
447
448```rust
449// BEFORE
450enum Action { Move { distance: u32 }, Stop }
451
452fn handle(action: Action) {
453 match action {
454 ┃Action::Move(..) => foo(),
455 Action::Stop => foo(),
456 }
457}
458
459// AFTER
460enum Action { Move { distance: u32 }, Stop }
461
462fn handle(action: Action) {
463 match action {
464 Action::Move(..) | Action::Stop => foo(),
465 }
466}
467```
468
469## `move_arm_cond_to_match_guard`
470
471Moves if expression from match arm body into a guard.
472
473```rust
474// BEFORE
475enum Action { Move { distance: u32 }, Stop }
476
477fn handle(action: Action) {
478 match action {
479 Action::Move { distance } => ┃if distance > 10 { foo() },
480 _ => (),
481 }
482}
483
484// AFTER
485enum Action { Move { distance: u32 }, Stop }
486
487fn handle(action: Action) {
488 match action {
489 Action::Move { distance } if distance > 10 => foo(),
490 _ => (),
491 }
492}
493```
494
495## `move_bounds_to_where_clause`
496
497Moves inline type bounds to a where clause.
498
499```rust
500// BEFORE
501fn apply<T, U, ┃F: FnOnce(T) -> U>(f: F, x: T) -> U {
502 f(x)
503}
504
505// AFTER
506fn apply<T, U, F>(f: F, x: T) -> U where F: FnOnce(T) -> U {
507 f(x)
508}
509```
510
511## `move_guard_to_arm_body`
512
513Moves match guard into match arm body.
514
515```rust
516// BEFORE
517enum Action { Move { distance: u32 }, Stop }
518
519fn handle(action: Action) {
520 match action {
521 Action::Move { distance } ┃if distance > 10 => foo(),
522 _ => (),
523 }
524}
525
526// AFTER
527enum Action { Move { distance: u32 }, Stop }
528
529fn handle(action: Action) {
530 match action {
531 Action::Move { distance } => if distance > 10 { foo() },
532 _ => (),
533 }
534}
535```
536
537## `remove_dbg`
538
539Removes `dbg!()` macro call.
540
541```rust
542// BEFORE
543fn main() {
544 ┃dbg!(92);
545}
546
547// AFTER
548fn main() {
549 92;
550}
551```
552
553## `remove_hash`
554
555Removes a hash from a raw string literal.
556
557```rust
558// BEFORE
559fn main() {
560 r#"Hello,┃ World!"#;
561}
562
563// AFTER
564fn main() {
565 r"Hello, World!";
566}
567```
568
569## `remove_mut`
570
571Removes the `mut` keyword.
572
573```rust
574// BEFORE
575impl Walrus {
576 fn feed(&mut┃ self, amount: u32) {}
577}
578
579// AFTER
580impl Walrus {
581 fn feed(&self, amount: u32) {}
582}
583```
584
585## `reorder_fields`
586
587Reorder the fields of record literals and record patterns in the same order as in
588the definition.
589
590```rust
591// BEFORE
592struct Foo {foo: i32, bar: i32};
593const test: Foo = ┃Foo {bar: 0, foo: 1}
594
595// AFTER
596struct Foo {foo: i32, bar: i32};
597const test: Foo = Foo {foo: 1, bar: 0}
598```
599
600## `replace_if_let_with_match`
601
602Replaces `if let` with an else branch with a `match` expression.
603
604```rust
605// BEFORE
606enum Action { Move { distance: u32 }, Stop }
607
608fn handle(action: Action) {
609 ┃if let Action::Move { distance } = action {
610 foo(distance)
611 } else {
612 bar()
613 }
614}
615
616// AFTER
617enum Action { Move { distance: u32 }, Stop }
618
619fn handle(action: Action) {
620 match action {
621 Action::Move { distance } => foo(distance),
622 _ => bar(),
623 }
624}
625```
626
627## `replace_let_with_if_let`
628
629Replaces `let` with an `if-let`.
630
631```rust
632// BEFORE
633
634fn main(action: Action) {
635 ┃let x = compute();
636}
637
638fn compute() -> Option<i32> { None }
639
640// AFTER
641
642fn main(action: Action) {
643 if let Some(x) = compute() {
644 }
645}
646
647fn compute() -> Option<i32> { None }
648```
649
650## `replace_qualified_name_with_use`
651
652Adds a use statement for a given fully-qualified name.
653
654```rust
655// BEFORE
656fn process(map: std::collections::┃HashMap<String, String>) {}
657
658// AFTER
659use std::collections::HashMap;
660
661fn process(map: HashMap<String, String>) {}
662```
663
664## `replace_unwrap_with_match`
665
666Replaces `unwrap` a `match` expression. Works for Result and Option.
667
668```rust
669// BEFORE
670enum Result<T, E> { Ok(T), Err(E) }
671fn main() {
672 let x: Result<i32, i32> = Result::Ok(92);
673 let y = x.┃unwrap();
674}
675
676// AFTER
677enum Result<T, E> { Ok(T), Err(E) }
678fn main() {
679 let x: Result<i32, i32> = Result::Ok(92);
680 let y = match x {
681 Ok(a) => a,
682 _ => unreachable!(),
683 };
684}
685```
686
687## `split_import`
688
689Wraps the tail of import into braces.
690
691```rust
692// BEFORE
693use std::┃collections::HashMap;
694
695// AFTER
696use std::{collections::HashMap};
697```
diff --git a/docs/user/features.md b/docs/user/features.md
deleted file mode 100644
index b9a365fc1..000000000
--- a/docs/user/features.md
+++ /dev/null
@@ -1,202 +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 {}`
147- `expr.match` -> `match expr {}`
148- `expr.while` -> `while expr {}`
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
165### Code Highlighting
166
167Experimental feature to let rust-analyzer highlight Rust code instead of using the
168default highlighter.
169
170#### Rainbow Highlighting
171
172Experimental feature that, given code highlighting using rust-analyzer is
173active, will pick unique colors for identifiers.
174
175### Code hints
176
177Rust-analyzer has two types of hints to show the information about the code:
178
179* hover hints, appearing on hover on any element.
180
181These contain extended information on the hovered language item.
182
183* inlay hints, shown near the element hinted directly in the editor.
184
185Two types of inlay hints are displayed currently:
186
187* type hints, displaying the minimal information on the type of the expression (if the information is available)
188* method chaining hints, type information for multi-line method chains
189* parameter name hints, displaying the names of the parameters in the corresponding methods
190
191#### VS Code
192
193In VS Code, the following settings can be used to configure the inlay hints:
194
195* `rust-analyzer.inlayHints.typeHints` - enable hints for inferred types.
196* `rust-analyzer.inlayHints.chainingHints` - enable hints for inferred types on method chains.
197* `rust-analyzer.inlayHints.parameterHints` - enable hints for function parameters.
198* `rust-analyzer.inlayHints.maxLength` — shortens the hints if their length exceeds the value specified. If no value is specified (`null`), no shortening is applied.
199
200**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.
201This approach has limitations, the caret movement and bracket highlighting near the edges of the hint may be weird:
202[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/generated_assists.adoc b/docs/user/generated_assists.adoc
new file mode 100644
index 000000000..4d2fb31d4
--- /dev/null
+++ b/docs/user/generated_assists.adoc
@@ -0,0 +1,1015 @@
1[discrete]
2=== `add_custom_impl`
3**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/add_custom_impl.rs#L14[add_custom_impl.rs]
4
5Adds impl block for derived trait.
6
7.Before
8```rust
9#[derive(Deb┃ug, Display)]
10struct S;
11```
12
13.After
14```rust
15#[derive(Display)]
16struct S;
17
18impl Debug for S {
19 $0
20}
21```
22
23
24[discrete]
25=== `add_derive`
26**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/add_derive.rs#L9[add_derive.rs]
27
28Adds a new `#[derive()]` clause to a struct or enum.
29
30.Before
31```rust
32struct Point {
33 x: u32,
34 y: u32,┃
35}
36```
37
38.After
39```rust
40#[derive($0)]
41struct Point {
42 x: u32,
43 y: u32,
44}
45```
46
47
48[discrete]
49=== `add_explicit_type`
50**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/add_explicit_type.rs#L9[add_explicit_type.rs]
51
52Specify type for a let binding.
53
54.Before
55```rust
56fn main() {
57 let x┃ = 92;
58}
59```
60
61.After
62```rust
63fn main() {
64 let x: i32 = 92;
65}
66```
67
68
69[discrete]
70=== `add_from_impl_for_enum`
71**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs#L7[add_from_impl_for_enum.rs]
72
73Adds a From impl for an enum variant with one tuple field.
74
75.Before
76```rust
77enum A { ┃One(u32) }
78```
79
80.After
81```rust
82enum A { One(u32) }
83
84impl From<u32> for A {
85 fn from(v: u32) -> Self {
86 A::One(v)
87 }
88}
89```
90
91
92[discrete]
93=== `add_function`
94**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/add_function.rs#L19[add_function.rs]
95
96Adds a stub function with a signature matching the function under the cursor.
97
98.Before
99```rust
100struct Baz;
101fn baz() -> Baz { Baz }
102fn foo() {
103 bar┃("", baz());
104}
105
106```
107
108.After
109```rust
110struct Baz;
111fn baz() -> Baz { Baz }
112fn foo() {
113 bar("", baz());
114}
115
116fn bar(arg: &str, baz: Baz) {
117 ${0:todo!()}
118}
119
120```
121
122
123[discrete]
124=== `add_hash`
125**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/raw_string.rs#L65[raw_string.rs]
126
127Adds a hash to a raw string literal.
128
129.Before
130```rust
131fn main() {
132 r#"Hello,┃ World!"#;
133}
134```
135
136.After
137```rust
138fn main() {
139 r##"Hello, World!"##;
140}
141```
142
143
144[discrete]
145=== `add_impl`
146**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/add_impl.rs#L6[add_impl.rs]
147
148Adds a new inherent impl for a type.
149
150.Before
151```rust
152struct Ctx<T: Clone> {
153 data: T,┃
154}
155```
156
157.After
158```rust
159struct Ctx<T: Clone> {
160 data: T,
161}
162
163impl<T: Clone> Ctx<T> {
164 $0
165}
166```
167
168
169[discrete]
170=== `add_impl_default_members`
171**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/add_missing_impl_members.rs#L64[add_missing_impl_members.rs]
172
173Adds scaffold for overriding default impl members.
174
175.Before
176```rust
177trait Trait {
178 Type X;
179 fn foo(&self);
180 fn bar(&self) {}
181}
182
183impl Trait for () {
184 Type X = ();
185 fn foo(&self) {}┃
186
187}
188```
189
190.After
191```rust
192trait Trait {
193 Type X;
194 fn foo(&self);
195 fn bar(&self) {}
196}
197
198impl Trait for () {
199 Type X = ();
200 fn foo(&self) {}
201 $0fn bar(&self) {}
202
203}
204```
205
206
207[discrete]
208=== `add_impl_missing_members`
209**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/add_missing_impl_members.rs#L24[add_missing_impl_members.rs]
210
211Adds scaffold for required impl members.
212
213.Before
214```rust
215trait Trait<T> {
216 Type X;
217 fn foo(&self) -> T;
218 fn bar(&self) {}
219}
220
221impl Trait<u32> for () {┃
222
223}
224```
225
226.After
227```rust
228trait Trait<T> {
229 Type X;
230 fn foo(&self) -> T;
231 fn bar(&self) {}
232}
233
234impl Trait<u32> for () {
235 fn foo(&self) -> u32 {
236 ${0:todo!()}
237 }
238
239}
240```
241
242
243[discrete]
244=== `add_new`
245**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/add_new.rs#L12[add_new.rs]
246
247Adds a new inherent impl for a type.
248
249.Before
250```rust
251struct Ctx<T: Clone> {
252 data: T,┃
253}
254```
255
256.After
257```rust
258struct Ctx<T: Clone> {
259 data: T,
260}
261
262impl<T: Clone> Ctx<T> {
263 fn $0new(data: T) -> Self { Self { data } }
264}
265
266```
267
268
269[discrete]
270=== `add_turbo_fish`
271**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/add_turbo_fish.rs#L10[add_turbo_fish.rs]
272
273Adds `::<_>` to a call of a generic method or function.
274
275.Before
276```rust
277fn make<T>() -> T { todo!() }
278fn main() {
279 let x = make┃();
280}
281```
282
283.After
284```rust
285fn make<T>() -> T { todo!() }
286fn main() {
287 let x = make::<${0:_}>();
288}
289```
290
291
292[discrete]
293=== `apply_demorgan`
294**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/apply_demorgan.rs#L5[apply_demorgan.rs]
295
296Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws).
297This transforms expressions of the form `!l || !r` into `!(l && r)`.
298This also works with `&&`. This assist can only be applied with the cursor
299on either `||` or `&&`, with both operands being a negation of some kind.
300This means something of the form `!x` or `x != y`.
301
302.Before
303```rust
304fn main() {
305 if x != 4 ||┃ !y {}
306}
307```
308
309.After
310```rust
311fn main() {
312 if !(x == 4 && y) {}
313}
314```
315
316
317[discrete]
318=== `auto_import`
319**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/auto_import.rs#L18[auto_import.rs]
320
321If the name is unresolved, provides all possible imports for it.
322
323.Before
324```rust
325fn main() {
326 let map = HashMap┃::new();
327}
328```
329
330.After
331```rust
332use std::collections::HashMap;
333
334fn main() {
335 let map = HashMap::new();
336}
337```
338
339
340[discrete]
341=== `change_return_type_to_result`
342**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/change_return_type_to_result.rs#L8[change_return_type_to_result.rs]
343
344Change the function's return type to Result.
345
346.Before
347```rust
348fn foo() -> i32┃ { 42i32 }
349```
350
351.After
352```rust
353fn foo() -> Result<i32, ${0:_}> { Ok(42i32) }
354```
355
356
357[discrete]
358=== `change_visibility`
359**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/change_visibility.rs#L14[change_visibility.rs]
360
361Adds or changes existing visibility specifier.
362
363.Before
364```rust
365┃fn frobnicate() {}
366```
367
368.After
369```rust
370pub(crate) fn frobnicate() {}
371```
372
373
374[discrete]
375=== `convert_to_guarded_return`
376**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/early_return.rs#L21[early_return.rs]
377
378Replace a large conditional with a guarded return.
379
380.Before
381```rust
382fn main() {
383 ┃if cond {
384 foo();
385 bar();
386 }
387}
388```
389
390.After
391```rust
392fn main() {
393 if !cond {
394 return;
395 }
396 foo();
397 bar();
398}
399```
400
401
402[discrete]
403=== `fill_match_arms`
404**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/fill_match_arms.rs#L14[fill_match_arms.rs]
405
406Adds missing clauses to a `match` expression.
407
408.Before
409```rust
410enum Action { Move { distance: u32 }, Stop }
411
412fn handle(action: Action) {
413 match action {
414
415 }
416}
417```
418
419.After
420```rust
421enum Action { Move { distance: u32 }, Stop }
422
423fn handle(action: Action) {
424 match action {
425 $0Action::Move { distance } => {}
426 Action::Stop => {}
427 }
428}
429```
430
431
432[discrete]
433=== `fix_visibility`
434**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/fix_visibility.rs#L13[fix_visibility.rs]
435
436Makes inaccessible item public.
437
438.Before
439```rust
440mod m {
441 fn frobnicate() {}
442}
443fn main() {
444 m::frobnicate┃() {}
445}
446```
447
448.After
449```rust
450mod m {
451 $0pub(crate) fn frobnicate() {}
452}
453fn main() {
454 m::frobnicate() {}
455}
456```
457
458
459[discrete]
460=== `flip_binexpr`
461**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/flip_binexpr.rs#L5[flip_binexpr.rs]
462
463Flips operands of a binary expression.
464
465.Before
466```rust
467fn main() {
468 let _ = 90 +┃ 2;
469}
470```
471
472.After
473```rust
474fn main() {
475 let _ = 2 + 90;
476}
477```
478
479
480[discrete]
481=== `flip_comma`
482**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/flip_comma.rs#L5[flip_comma.rs]
483
484Flips two comma-separated items.
485
486.Before
487```rust
488fn main() {
489 ((1, 2),┃ (3, 4));
490}
491```
492
493.After
494```rust
495fn main() {
496 ((3, 4), (1, 2));
497}
498```
499
500
501[discrete]
502=== `flip_trait_bound`
503**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/flip_trait_bound.rs#L9[flip_trait_bound.rs]
504
505Flips two trait bounds.
506
507.Before
508```rust
509fn foo<T: Clone +┃ Copy>() { }
510```
511
512.After
513```rust
514fn foo<T: Copy + Clone>() { }
515```
516
517
518[discrete]
519=== `inline_local_variable`
520**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/inline_local_variable.rs#L13[inline_local_variable.rs]
521
522Inlines local variable.
523
524.Before
525```rust
526fn main() {
527 let x┃ = 1 + 2;
528 x * 4;
529}
530```
531
532.After
533```rust
534fn main() {
535 (1 + 2) * 4;
536}
537```
538
539
540[discrete]
541=== `introduce_named_lifetime`
542**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/introduce_named_lifetime.rs#L12[introduce_named_lifetime.rs]
543
544Change an anonymous lifetime to a named lifetime.
545
546.Before
547```rust
548impl Cursor<'_┃> {
549 fn node(self) -> &SyntaxNode {
550 match self {
551 Cursor::Replace(node) | Cursor::Before(node) => node,
552 }
553 }
554}
555```
556
557.After
558```rust
559impl<'a> Cursor<'a> {
560 fn node(self) -> &SyntaxNode {
561 match self {
562 Cursor::Replace(node) | Cursor::Before(node) => node,
563 }
564 }
565}
566```
567
568
569[discrete]
570=== `introduce_variable`
571**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/introduce_variable.rs#L14[introduce_variable.rs]
572
573Extracts subexpression into a variable.
574
575.Before
576```rust
577fn main() {
578 ┃(1 + 2)┃ * 4;
579}
580```
581
582.After
583```rust
584fn main() {
585 let $0var_name = (1 + 2);
586 var_name * 4;
587}
588```
589
590
591[discrete]
592=== `invert_if`
593**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/invert_if.rs#L12[invert_if.rs]
594
595Apply invert_if
596This transforms if expressions of the form `if !x {A} else {B}` into `if x {B} else {A}`
597This also works with `!=`. This assist can only be applied with the cursor
598on `if`.
599
600.Before
601```rust
602fn main() {
603 if┃ !y { A } else { B }
604}
605```
606
607.After
608```rust
609fn main() {
610 if y { B } else { A }
611}
612```
613
614
615[discrete]
616=== `make_raw_string`
617**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/raw_string.rs#L10[raw_string.rs]
618
619Adds `r#` to a plain string literal.
620
621.Before
622```rust
623fn main() {
624 "Hello,┃ World!";
625}
626```
627
628.After
629```rust
630fn main() {
631 r#"Hello, World!"#;
632}
633```
634
635
636[discrete]
637=== `make_usual_string`
638**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/raw_string.rs#L39[raw_string.rs]
639
640Turns a raw string into a plain string.
641
642.Before
643```rust
644fn main() {
645 r#"Hello,┃ "World!""#;
646}
647```
648
649.After
650```rust
651fn main() {
652 "Hello, \"World!\"";
653}
654```
655
656
657[discrete]
658=== `merge_imports`
659**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/merge_imports.rs#L14[merge_imports.rs]
660
661Merges two imports with a common prefix.
662
663.Before
664```rust
665use std::┃fmt::Formatter;
666use std::io;
667```
668
669.After
670```rust
671use std::{fmt::Formatter, io};
672```
673
674
675[discrete]
676=== `merge_match_arms`
677**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/merge_match_arms.rs#L11[merge_match_arms.rs]
678
679Merges identical match arms.
680
681.Before
682```rust
683enum Action { Move { distance: u32 }, Stop }
684
685fn handle(action: Action) {
686 match action {
687 ┃Action::Move(..) => foo(),
688 Action::Stop => foo(),
689 }
690}
691```
692
693.After
694```rust
695enum Action { Move { distance: u32 }, Stop }
696
697fn handle(action: Action) {
698 match action {
699 Action::Move(..) | Action::Stop => foo(),
700 }
701}
702```
703
704
705[discrete]
706=== `move_arm_cond_to_match_guard`
707**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/move_guard.rs#L56[move_guard.rs]
708
709Moves if expression from match arm body into a guard.
710
711.Before
712```rust
713enum Action { Move { distance: u32 }, Stop }
714
715fn handle(action: Action) {
716 match action {
717 Action::Move { distance } => ┃if distance > 10 { foo() },
718 _ => (),
719 }
720}
721```
722
723.After
724```rust
725enum Action { Move { distance: u32 }, Stop }
726
727fn handle(action: Action) {
728 match action {
729 Action::Move { distance } if distance > 10 => foo(),
730 _ => (),
731 }
732}
733```
734
735
736[discrete]
737=== `move_bounds_to_where_clause`
738**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/move_bounds.rs#L10[move_bounds.rs]
739
740Moves inline type bounds to a where clause.
741
742.Before
743```rust
744fn apply<T, U, ┃F: FnOnce(T) -> U>(f: F, x: T) -> U {
745 f(x)
746}
747```
748
749.After
750```rust
751fn apply<T, U, F>(f: F, x: T) -> U where F: FnOnce(T) -> U {
752 f(x)
753}
754```
755
756
757[discrete]
758=== `move_guard_to_arm_body`
759**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/move_guard.rs#L8[move_guard.rs]
760
761Moves match guard into match arm body.
762
763.Before
764```rust
765enum Action { Move { distance: u32 }, Stop }
766
767fn handle(action: Action) {
768 match action {
769 Action::Move { distance } ┃if distance > 10 => foo(),
770 _ => (),
771 }
772}
773```
774
775.After
776```rust
777enum Action { Move { distance: u32 }, Stop }
778
779fn handle(action: Action) {
780 match action {
781 Action::Move { distance } => if distance > 10 { foo() },
782 _ => (),
783 }
784}
785```
786
787
788[discrete]
789=== `remove_dbg`
790**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/remove_dbg.rs#L8[remove_dbg.rs]
791
792Removes `dbg!()` macro call.
793
794.Before
795```rust
796fn main() {
797 ┃dbg!(92);
798}
799```
800
801.After
802```rust
803fn main() {
804 92;
805}
806```
807
808
809[discrete]
810=== `remove_hash`
811**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/raw_string.rs#L89[raw_string.rs]
812
813Removes a hash from a raw string literal.
814
815.Before
816```rust
817fn main() {
818 r#"Hello,┃ World!"#;
819}
820```
821
822.After
823```rust
824fn main() {
825 r"Hello, World!";
826}
827```
828
829
830[discrete]
831=== `remove_mut`
832**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/remove_mut.rs#L5[remove_mut.rs]
833
834Removes the `mut` keyword.
835
836.Before
837```rust
838impl Walrus {
839 fn feed(&mut┃ self, amount: u32) {}
840}
841```
842
843.After
844```rust
845impl Walrus {
846 fn feed(&self, amount: u32) {}
847}
848```
849
850
851[discrete]
852=== `reorder_fields`
853**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/reorder_fields.rs#L10[reorder_fields.rs]
854
855Reorder the fields of record literals and record patterns in the same order as in
856the definition.
857
858.Before
859```rust
860struct Foo {foo: i32, bar: i32};
861const test: Foo = ┃Foo {bar: 0, foo: 1}
862```
863
864.After
865```rust
866struct Foo {foo: i32, bar: i32};
867const test: Foo = Foo {foo: 1, bar: 0}
868```
869
870
871[discrete]
872=== `replace_if_let_with_match`
873**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/replace_if_let_with_match.rs#L13[replace_if_let_with_match.rs]
874
875Replaces `if let` with an else branch with a `match` expression.
876
877.Before
878```rust
879enum Action { Move { distance: u32 }, Stop }
880
881fn handle(action: Action) {
882 ┃if let Action::Move { distance } = action {
883 foo(distance)
884 } else {
885 bar()
886 }
887}
888```
889
890.After
891```rust
892enum Action { Move { distance: u32 }, Stop }
893
894fn handle(action: Action) {
895 match action {
896 Action::Move { distance } => foo(distance),
897 _ => bar(),
898 }
899}
900```
901
902
903[discrete]
904=== `replace_let_with_if_let`
905**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/replace_let_with_if_let.rs#L14[replace_let_with_if_let.rs]
906
907Replaces `let` with an `if-let`.
908
909.Before
910```rust
911
912fn main(action: Action) {
913 ┃let x = compute();
914}
915
916fn compute() -> Option<i32> { None }
917```
918
919.After
920```rust
921
922fn main(action: Action) {
923 if let Some(x) = compute() {
924 }
925}
926
927fn compute() -> Option<i32> { None }
928```
929
930
931[discrete]
932=== `replace_qualified_name_with_use`
933**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs#L6[replace_qualified_name_with_use.rs]
934
935Adds a use statement for a given fully-qualified name.
936
937.Before
938```rust
939fn process(map: std::collections::┃HashMap<String, String>) {}
940```
941
942.After
943```rust
944use std::collections::HashMap;
945
946fn process(map: HashMap<String, String>) {}
947```
948
949
950[discrete]
951=== `replace_unwrap_with_match`
952**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs#L17[replace_unwrap_with_match.rs]
953
954Replaces `unwrap` a `match` expression. Works for Result and Option.
955
956.Before
957```rust
958enum Result<T, E> { Ok(T), Err(E) }
959fn main() {
960 let x: Result<i32, i32> = Result::Ok(92);
961 let y = x.┃unwrap();
962}
963```
964
965.After
966```rust
967enum Result<T, E> { Ok(T), Err(E) }
968fn main() {
969 let x: Result<i32, i32> = Result::Ok(92);
970 let y = match x {
971 Ok(a) => a,
972 $0_ => unreachable!(),
973 };
974}
975```
976
977
978[discrete]
979=== `split_import`
980**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/split_import.rs#L7[split_import.rs]
981
982Wraps the tail of import into braces.
983
984.Before
985```rust
986use std::┃collections::HashMap;
987```
988
989.After
990```rust
991use std::{collections::HashMap};
992```
993
994
995[discrete]
996=== `unwrap_block`
997**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/unwrap_block.rs#L9[unwrap_block.rs]
998
999This assist removes if...else, for, while and loop control statements to just keep the body.
1000
1001.Before
1002```rust
1003fn foo() {
1004 if true {┃
1005 println!("foo");
1006 }
1007}
1008```
1009
1010.After
1011```rust
1012fn foo() {
1013 println!("foo");
1014}
1015```
diff --git a/docs/user/generated_features.adoc b/docs/user/generated_features.adoc
new file mode 100644
index 000000000..12812fa0b
--- /dev/null
+++ b/docs/user/generated_features.adoc
@@ -0,0 +1,298 @@
1=== Expand Macro Recursively
2**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/expand_macro.rs#L15[expand_macro.rs]
3
4Shows the full macro expansion of the macro at current cursor.
5
6|===
7| Editor | Action Name
8
9| VS Code | **Rust Analyzer: Expand macro recursively**
10|===
11
12
13=== Extend Selection
14**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/extend_selection.rs#L15[extend_selection.rs]
15
16Extends the current selection to the encompassing syntactic construct
17(expression, statement, item, module, etc). It works with multiple cursors.
18
19|===
20| Editor | Shortcut
21
22| VS Code | kbd:[Ctrl+Shift+→]
23|===
24
25
26=== File Structure
27**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/display/structure.rs#L17[structure.rs]
28
29Provides a tree of the symbols defined in the file. Can be used to
30
31* fuzzy search symbol in a file (super useful)
32* draw breadcrumbs to describe the context around the cursor
33* draw outline of the file
34
35|===
36| Editor | Shortcut
37
38| VS Code | kbd:[Ctrl+Shift+O]
39|===
40
41
42=== Go to Definition
43**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/goto_definition.rs#L18[goto_definition.rs]
44
45Navigates to the definition of an identifier.
46
47|===
48| Editor | Shortcut
49
50| VS Code | kbd:[F12]
51|===
52
53
54=== Go to Implementation
55**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/goto_implementation.rs#L7[goto_implementation.rs]
56
57Navigates to the impl block of structs, enums or traits. Also implemented as a code lens.
58
59|===
60| Editor | Shortcut
61
62| VS Code | kbd:[Ctrl+F12]
63|===
64
65
66=== Go to Type Definition
67**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/goto_type_definition.rs#L6[goto_type_definition.rs]
68
69Navigates to the type of an identifier.
70
71|===
72| Editor | Action Name
73
74| VS Code | **Go to Type Definition*
75|===
76
77
78=== Hover
79**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/hover.rs#L63[hover.rs]
80
81Shows additional information, like type of an expression or documentation for definition when "focusing" code.
82Focusing is usually hovering with a mouse, but can also be triggered with a shortcut.
83
84
85=== Inlay Hints
86**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/inlay_hints.rs#L40[inlay_hints.rs]
87
88rust-analyzer shows additional information inline with the source code.
89Editors usually render this using read-only virtual text snippets interspersed with code.
90
91rust-analyzer shows hits for
92
93* types of local variables
94* names of function arguments
95* types of chained expressions
96
97**Note:** VS Code does not have native support for inlay hints https://github.com/microsoft/vscode/issues/16221[yet] and the hints are implemented using decorations.
98This approach has limitations, the caret movement and bracket highlighting near the edges of the hint may be weird:
99https://github.com/rust-analyzer/rust-analyzer/issues/1623[1], https://github.com/rust-analyzer/rust-analyzer/issues/3453[2].
100
101|===
102| Editor | Action Name
103
104| VS Code | **Rust Analyzer: Toggle inlay hints*
105|===
106
107
108=== Join Lines
109**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/join_lines.rs#L12[join_lines.rs]
110
111Join selected lines into one, smartly fixing up whitespace, trailing commas, and braces.
112
113|===
114| Editor | Action Name
115
116| VS Code | **Rust Analyzer: Join lines**
117|===
118
119
120=== Magic Completions
121**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/completion.rs#L38[completion.rs]
122
123In addition to usual reference completion, rust-analyzer provides some ✨magic✨
124completions as well:
125
126Keywords like `if`, `else` `while`, `loop` are completed with braces, and cursor
127is placed at the appropriate position. Even though `if` is easy to type, you
128still want to complete it, to get ` { }` for free! `return` is inserted with a
129space or `;` depending on the return type of the function.
130
131When completing a function call, `()` are automatically inserted. If a function
132takes arguments, the cursor is positioned inside the parenthesis.
133
134There are postfix completions, which can be triggered by typing something like
135`foo().if`. The word after `.` determines postfix completion. Possible variants are:
136
137- `expr.if` -> `if expr {}` or `if let ... {}` for `Option` or `Result`
138- `expr.match` -> `match expr {}`
139- `expr.while` -> `while expr {}` or `while let ... {}` for `Option` or `Result`
140- `expr.ref` -> `&expr`
141- `expr.refm` -> `&mut expr`
142- `expr.not` -> `!expr`
143- `expr.dbg` -> `dbg!(expr)`
144
145There also snippet completions:
146
147.Expressions
148- `pd` -> `println!("{:?}")`
149- `ppd` -> `println!("{:#?}")`
150
151.Items
152- `tfn` -> `#[test] fn f(){}`
153- `tmod` ->
154```rust
155#[cfg(test)]
156mod tests {
157 use super::*;
158
159 #[test]
160 fn test_fn() {}
161}
162```
163
164
165=== Matching Brace
166**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/matching_brace.rs#L3[matching_brace.rs]
167
168If the cursor is on any brace (`<>(){}[]`) which is a part of a brace-pair,
169moves cursor to the matching brace. It uses the actual parser to determine
170braces, so it won't confuse generics with comparisons.
171
172|===
173| Editor | Action Name
174
175| VS Code | **Rust Analyzer: Find matching brace**
176|===
177
178
179=== On Typing Assists
180**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/typing.rs#L35[typing.rs]
181
182Some features trigger on typing certain characters:
183
184- typing `let =` tries to smartly add `;` if `=` is followed by an existing expression
185- Enter inside comments automatically inserts `///`
186- typing `.` in a chain method call auto-indents
187
188
189=== Parent Module
190**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/parent_module.rs#L12[parent_module.rs]
191
192Navigates to the parent module of the current module.
193
194|===
195| Editor | Action Name
196
197| VS Code | **Rust Analyzer: Locate parent module**
198|===
199
200
201=== Run
202**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/runnables.rs#L45[runnables.rs]
203
204Shows a popup suggesting to run a test/benchmark/binary **at the current cursor
205location**. Super useful for repeatedly running just a single test. Do bind this
206to a shortcut!
207
208|===
209| Editor | Action Name
210
211| VS Code | **Rust Analyzer: Run**
212|===
213
214
215=== Semantic Syntax Highlighting
216**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/syntax_highlighting.rs#L33[syntax_highlighting.rs]
217
218rust-analyzer highlights the code semantically.
219For example, `bar` in `foo::Bar` might be colored differently depending on whether `Bar` is an enum or a trait.
220rust-analyzer does not specify colors directly, instead it assigns tag (like `struct`) and a set of modifiers (like `declaration`) to each token.
221It's up to the client to map those to specific colors.
222
223The general rule is that a reference to an entity gets colored the same way as the entity itself.
224We also give special modifier for `mut` and `&mut` local variables.
225
226
227=== Show Syntax Tree
228**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/syntax_tree.rs#L9[syntax_tree.rs]
229
230Shows the parse tree of the current file. It exists mostly for debugging
231rust-analyzer itself.
232
233|===
234| Editor | Action Name
235
236| VS Code | **Rust Analyzer: Show Syntax Tree**
237|===
238
239
240=== Status
241**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/status.rs#L27[status.rs]
242
243Shows internal statistic about memory usage of rust-analyzer.
244
245|===
246| Editor | Action Name
247
248| VS Code | **Rust Analyzer: Status**
249|===
250
251
252=== Structural Seach and Replace
253**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/ssr.rs#L26[ssr.rs]
254
255Search and replace with named wildcards that will match any expression.
256The syntax for a structural search replace command is `<search_pattern> ==>> <replace_pattern>`.
257A `$<name>:expr` placeholder in the search pattern will match any expression and `$<name>` will reference it in the replacement.
258Available via the command `rust-analyzer.ssr`.
259
260```rust
261// Using structural search replace command [foo($a:expr, $b:expr) ==>> ($a).foo($b)]
262
263// BEFORE
264String::from(foo(y + 5, z))
265
266// AFTER
267String::from((y + 5).foo(z))
268```
269
270|===
271| Editor | Action Name
272
273| VS Code | **Rust Analyzer: Structural Search Replace**
274|===
275
276
277=== Workspace Symbol
278**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide_db/src/symbol_index.rs#L113[symbol_index.rs]
279
280Uses fuzzy-search to find types, modules and functions by name across your
281project and dependencies. This is **the** most useful feature, which improves code
282navigation tremendously. It mostly works on top of the built-in LSP
283functionality, however `#` and `*` symbols can be used to narrow down the
284search. Specifically,
285
286- `Foo` searches for `Foo` type in the current workspace
287- `foo#` searches for `foo` function in the current workspace
288- `Foo*` searches for `Foo` type among dependencies, including `stdlib`
289- `foo#*` searches for `foo` function among dependencies
290
291That is, `#` switches from "types" to all symbols, `*` switches from the current
292workspace to dependencies.
293
294|===
295| Editor | Shortcut
296
297| VS Code | kbd:[Ctrl+T]
298|===
diff --git a/docs/user/readme.adoc b/docs/user/manual.adoc
index 4cb1e23e8..202783fd9 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
@@ -57,9 +54,13 @@ To disable this notification put the following to `settings.json`
57---- 54----
58==== 55====
59 56
60The server binary is stored in `~/.config/Code/User/globalStorage/matklad.rust-analyzer` (Linux) or in `~/.Library/Application Support/Code/User/globalStorage/matklad.rust-analyzer` (macOS) or in `%APPDATA%\Code\User\globalStorage` (Windows). 57The server binary is stored in:
61 58
62Note that we only support the latest version of VS Code. 59* Linux: `~/.config/Code/User/globalStorage/matklad.rust-analyzer`
60* macOS: `~/Library/Application Support/Code/User/globalStorage/matklad.rust-analyzer`
61* Windows: `%APPDATA%\Code\User\globalStorage\matklad.rust-analyzer`
62
63Note that we only support two most recent versions of VS Code.
63 64
64==== Updates 65==== Updates
65 66
@@ -104,14 +105,27 @@ Here are some useful self-diagnostic commands:
104 105
105* **Rust Analyzer: Show RA Version** shows the version of `rust-analyzer` binary 106* **Rust Analyzer: Show RA Version** shows the version of `rust-analyzer` binary
106* **Rust Analyzer: Status** prints some statistics about the server, like the few latest LSP requests 107* **Rust Analyzer: Status** prints some statistics about the server, like the few latest LSP requests
107* To enable server-side logging, run with `env RUST_LOG=info` and see `Output > Rust Analyzer Language Server` in VS Code's panel. 108* To enable server-side logging, run with `env RA_LOG=info` and see `Output > Rust Analyzer Language Server` in VS Code's panel.
108* 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.
109* 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.
110 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
111=== rust-analyzer Language Server Binary 124=== rust-analyzer Language Server Binary
112 125
113Other editors generally require the `rust-analyzer` binary to be in `$PATH`. 126Other editors generally require the `rust-analyzer` binary to be in `$PATH`.
114You 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`.
115 129
116On 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
117 131
@@ -131,21 +145,21 @@ $ git clone https://github.com/rust-analyzer/rust-analyzer.git && cd rust-analyz
131$ cargo xtask install --server 145$ cargo xtask install --server
132---- 146----
133 147
134If 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.
135 150
136==== Arch Linux 151==== Arch Linux
137 152
138The `rust-analyzer` binary can be installed from AUR (Arch User Repository): 153The `rust-analyzer` binary can be installed from the repos or AUR (Arch User Repository):
139 154
140- https://aur.archlinux.org/packages/rust-analyzer-bin[`rust-analyzer-bin`] (binary from GitHub releases) 155- https://www.archlinux.org/packages/community/x86_64/rust-analyzer/[`rust-analyzer`] (built from latest tagged source)
141- https://aur.archlinux.org/packages/rust-analyzer[`rust-analyzer`] (built from latest tagged source) 156- https://aur.archlinux.org/packages/rust-analyzer-git[`rust-analyzer-git`] (latest Git version)
142- https://aur.archlinux.org/packages/rust-analyzer-git[`rust-analyzer-git`] (latest git version)
143 157
144Install it with AUR helper of your choice, for example: 158Install it with pacman, for example:
145 159
146[source,bash] 160[source,bash]
147---- 161----
148$ yay -S rust-analyzer-bin 162$ pacman -S rust-analyzer
149---- 163----
150 164
151=== Emacs 165=== Emacs
@@ -159,11 +173,11 @@ Emacs support is maintained as part of the https://github.com/emacs-lsp/lsp-mode
1593. Run `lsp` in a Rust buffer. 1733. Run `lsp` in a Rust buffer.
1604. (Optionally) bind commands like `lsp-rust-analyzer-join-lines`, `lsp-extend-selection` and `lsp-rust-analyzer-expand-macro` to keys. 1744. (Optionally) bind commands like `lsp-rust-analyzer-join-lines`, `lsp-extend-selection` and `lsp-rust-analyzer-expand-macro` to keys.
161 175
162=== Vim 176=== Vim/NeoVim
163 177
164Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>. 178Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>. Not needed if the extension can install/update it on its own, coc-rust-analyzer is one example.
165 179
166The are several LSP client implementations for vim: 180The are several LSP client implementations for vim or neovim:
167 181
168==== coc-rust-analyzer 182==== coc-rust-analyzer
169 183
@@ -183,7 +197,7 @@ The are several LSP client implementations for vim:
183 197
1841. Install LanguageClient-neovim by following the instructions 1981. Install LanguageClient-neovim by following the instructions
185 https://github.com/autozimu/LanguageClient-neovim[here] 199 https://github.com/autozimu/LanguageClient-neovim[here]
186 * The github project wiki has extra tips on configuration 200 * The GitHub project wiki has extra tips on configuration
187 201
1882. Configure by adding this to your vim/neovim config file (replacing the existing Rust-specific line if it exists): 2022. Configure by adding this to your vim/neovim config file (replacing the existing Rust-specific line if it exists):
189+ 203+
@@ -201,7 +215,7 @@ let g:LanguageClient_serverCommands = {
201 215
2022. Configure by adding this to your vim/neovim config file (replacing the existing Rust-specific line if it exists): 2162. Configure by adding this to your vim/neovim config file (replacing the existing Rust-specific line if it exists):
203+ 217+
204[source,vim] 218[source,vim]
205---- 219----
206let g:ycm_language_server = 220let g:ycm_language_server =
207\ [ 221\ [
@@ -216,17 +230,11 @@ let g:ycm_language_server =
216 230
217==== ALE 231==== ALE
218 232
219To add the LSP server to https://github.com/dense-analysis/ale[ale]: 233To use the LSP server in https://github.com/dense-analysis/ale[ale]:
220 234
221[source,vim] 235[source,vim]
222---- 236----
223call ale#linter#Define('rust', { 237let g:ale_linters = {'rust': ['analyzer']}
224\ 'name': 'rust-analyzer',
225\ 'lsp': 'stdio',
226\ 'executable': 'rust-analyzer',
227\ 'command': '%e',
228\ 'project_root': '.',
229\})
230---- 238----
231 239
232==== nvim-lsp 240==== nvim-lsp
@@ -252,6 +260,23 @@ If it worked, you should see "rust-analyzer, Line X, Column Y" on the left side
252 260
253If you get an error saying `No such file or directory: 'rust-analyzer'`, see the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>> section on installing the language server binary. 261If you get an error saying `No such file or directory: 'rust-analyzer'`, see the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>> section on installing the language server binary.
254 262
255== Usage 263=== GNOME Builder
264
265Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>.
266
267Gnome Builder currently has support for RLS, and there's no way to configure the language server executable. A future version might support `rust-analyzer` out of the box.
268
2691. Rename, symlink or copy the `rust-analyzer` binary to `rls` and place it somewhere Builder can find (in `PATH`, or under `~/.cargo/bin`).
2702. Enable the Rust Builder plugin.
271
272== Features
273
274include::./generated_features.adoc[]
275
276== Assists (Code Actions)
277
278Assists, or code actions, are small local refactorings, available in a particular context.
279They are usually triggered by a shortcut or by clicking a light bulb icon in the editor.
280Cursor position or selection is signified by `┃` character.
256 281
257See https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/features.md[features.md]. 282include::./generated_assists.adoc[]