aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorMikhail Rakhmanov <[email protected]>2020-06-13 07:42:15 +0100
committerMikhail Rakhmanov <[email protected]>2020-06-13 07:42:15 +0100
commit16bbf4ab7f132e6e5e5318dccdef9a5d71afdd7f (patch)
tree4b79fa8c046be56b02427ba843e70cdf3ac05767 /docs
parenteeb8b9e236796da8734ba81a49164864497f7226 (diff)
parentb56ad148db0c69eb279c225f45d324b4e80e7367 (diff)
Merge branch 'master' into keyword_completion
# Conflicts: # docs/user/generated_features.adoc
Diffstat (limited to 'docs')
-rw-r--r--docs/dev/README.md209
-rw-r--r--docs/dev/lsp-extensions.md122
-rw-r--r--docs/user/generated_assists.adoc1015
-rw-r--r--docs/user/generated_features.adoc10
-rw-r--r--docs/user/manual.adoc51
5 files changed, 355 insertions, 1052 deletions
diff --git a/docs/dev/README.md b/docs/dev/README.md
index 65cc9fc12..ef5ffbf59 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),
@@ -55,7 +55,7 @@ You can run `cargo xtask install-pre-commit-hook` to install git-hook to run rus
55All Rust code lives in the `crates` top-level directory, and is organized as a 55All Rust code lives in the `crates` top-level directory, and is organized as a
56single Cargo workspace. The `editors` top-level directory contains code for 56single Cargo workspace. The `editors` top-level directory contains code for
57integrating with editors. Currently, it contains the plugin for VS Code (in 57integrating with editors. Currently, it contains the plugin for VS Code (in
58typescript). The `docs` top-level directory contains both developer and user 58TypeScript). The `docs` top-level directory contains both developer and user
59documentation. 59documentation.
60 60
61We have some automation infra in Rust in the `xtask` package. It contains 61We have some automation infra in Rust in the `xtask` package. It contains
@@ -79,8 +79,8 @@ possible. There's **"Run Extension (Debug Build)"** launch configuration for thi
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.
81 81
82If the problem concerns only internal parts of rust-analyzer (ie, I don't need 82If the problem concerns only internal parts of rust-analyzer (i.e. I don't need
83to touch `rust-analyzer` crate or typescript code), there is a unit-test for it. 83to touch `rust-analyzer` crate or TypeScript code), there is a unit-test for it.
84So, I use **Rust Analyzer: Run** action in VS Code to run this single test, and 84So, I use **Rust Analyzer: Run** action in VS Code to run this single test, and
85then just do printf-driven development/debugging. As a sanity check after I'm 85then 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
@@ -117,6 +117,203 @@ 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```rust
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## Import Style
188
189Items from `hir` and `ast` should be used qualified:
190
191```rust
192// Good
193use ra_syntax::ast;
194
195fn frobnicate(func: hir::Function, strukt: ast::StructDef) {}
196
197// Not as good
198use hir::Function;
199use ra_syntax::ast::StructDef;
200
201fn frobnicate(func: Function, strukt: StructDef) {}
202```
203
204Avoid local `use MyEnum::*` imports.
205
206Prefer `use crate::foo::bar` to `use super::bar`.
207
208## Order of Items
209
210Optimize for the reader who sees the file for the first time, and wants to get the general idea about what's going on.
211People read things from top to bottom, so place most important things first.
212
213Specifically, if all items except one are private, always put the non-private item on top.
214
215Put `struct`s and `enum`s first, functions and impls last.
216
217Do
218
219```rust
220// Good
221struct Foo {
222 bars: Vec<Bar>
223}
224
225struct Bar;
226```
227
228rather than
229
230```rust
231// Not as good
232struct Bar;
233
234struct Foo {
235 bars: Vec<Bar>
236}
237```
238
239## Documentation
240
241For `.md` and `.adoc` files, prefer a sentence-per-line format, don't wrap lines.
242If the line is too long, you want to split the sentence in two :-)
243
244## Preconditions
245
246Function preconditions should generally be expressed in types and provided by the caller (rather than checked by callee):
247
248```rust
249// Good
250fn frbonicate(walrus: Walrus) {
251 ...
252}
253
254// Not as good
255fn frobnicate(walrus: Option<Walrus>) {
256 let walrus = match walrus {
257 Some(it) => it,
258 None => return,
259 };
260 ...
261}
262```
263
264## Commit Style
265
266We don't have specific rules around git history hygiene.
267Maintaining clean git history is encouraged, but not enforced.
268We use rebase workflow, it's OK to rewrite history during PR review process.
269
270Avoid @mentioning people in commit messages, as such messages create a lot of duplicate notification traffic during rebases.
271
272# Architecture Invariants
273
274This section tries to document high-level design constraints, which are not
275always obvious from the low-level code.
276
277## Incomplete syntax trees
278
279Syntax trees are by design incomplete and do not enforce well-formedness.
280If ast method returns an `Option`, it *can* be `None` at runtime, even if this is forbidden by the grammar.
281
282## LSP independence
283
284rust-analyzer is independent from LSP.
285It provides features for a hypothetical perfect Rust-specific IDE client.
286Internal representations are lowered to LSP in the `rust-analyzer` crate (the only crate which is allowed to use LSP types).
287
288## IDE/Compiler split
289
290There's a semi-hard split between "compiler" and "IDE", at the `ra_hir` crate.
291Compiler derives new facts about source code.
292It explicitly acknowledges that not all info is available (i.e. you can't look at types during name resolution).
293
294IDE assumes that all information is available at all times.
295
296IDE should use only types from `ra_hir`, and should not depend on the underling compiler types.
297`ra_hir` is a facade.
298
299## IDE API
300
301The main IDE crate (`ra_ide`) uses "Plain Old Data" for the API.
302Rather than talking in definitions and references, it talks in Strings and textual offsets.
303In general, API is centered around UI concerns -- the result of the call is what the user sees in the editor, and not what the compiler sees underneath.
304The results are 100% Rust specific though.
305
306## Parser Tests
307
308Test for parser (`ra_parser`) live in `ra_syntax` crate (see `test_data` direcotory).
309There are two kinds of tests:
310
311* Manually written test cases in `parser/ok` and `parser/err`
312* "Inline" tests in `parser/inline` (these are generated) from comments in `ra_parser` crate.
313
314The purpose of inline tests is not to achieve full coverage by test cases, but to explain to the reader of the code what each particular `if` and `match` is responsible for.
315If you are tempted to add a large inline test, it might be a good idea to leave only the simplest example in place, and move the test to a manual `parser/ok` test.
316
120# Logging 317# Logging
121 318
122Logging is done by both rust-analyzer and VS Code, so it might be tricky to 319Logging is done by both rust-analyzer and VS Code, so it might be tricky to
@@ -159,8 +356,8 @@ There's also two VS Code commands which might be of interest:
159 rust code that it refers to and the rust editor will also highlight the proper 356 rust code that it refers to and the rust editor will also highlight the proper
160 text range. 357 text range.
161 358
162 If you press <kbd>Ctrl</kbd> (i.e. trigger goto definition) in the inspected 359 If you trigger Go to Definition in the inspected Rust source file,
163 Rust source file the syntax tree read-only editor should scroll to and select the 360 the syntax tree read-only editor should scroll to and select the
164 appropriate syntax node token. 361 appropriate syntax node token.
165 362
166 ![demo](https://user-images.githubusercontent.com/36276403/78225773-6636a480-74d3-11ea-9d9f-1c9d42da03b0.png) 363 ![demo](https://user-images.githubusercontent.com/36276403/78225773-6636a480-74d3-11ea-9d9f-1c9d42da03b0.png)
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
index c57a93f12..a0847dad3 100644
--- a/docs/dev/lsp-extensions.md
+++ b/docs/dev/lsp-extensions.md
@@ -97,6 +97,30 @@ Invoking code action at this position will yield two code actions for importing
97* Is a fixed two-level structure enough? 97* Is a fixed two-level structure enough?
98* Should we devise a general way to encode custom interaction protocols for GUI refactorings? 98* Should we devise a general way to encode custom interaction protocols for GUI refactorings?
99 99
100## Lazy assists with `ResolveCodeAction`
101
102**Issue:** https://github.com/microsoft/language-server-protocol/issues/787
103
104**Client Capability** `{ "resolveCodeAction": boolean }`
105
106If this capability is set, the assists will be computed lazily. Thus `CodeAction` returned from the server will only contain `id` but not `edit` or `command` fields. The only exclusion from the rule is the diagnostic edits.
107
108After the client got the id, it should then call `experimental/resolveCodeAction` command on the server and provide the following payload:
109
110```typescript
111interface ResolveCodeActionParams {
112 id: string;
113 codeActionParams: lc.CodeActionParams;
114}
115```
116
117As a result of the command call the client will get the respective workspace edit (`lc.WorkspaceEdit`).
118
119### Unresolved Questions
120
121* Apply smarter filtering for ids?
122* Upon `resolveCodeAction` command only call the assits which should be resolved and not all of them?
123
100## Parent Module 124## Parent Module
101 125
102**Issue:** https://github.com/microsoft/language-server-protocol/issues/1002 126**Issue:** https://github.com/microsoft/language-server-protocol/issues/1002
@@ -311,6 +335,50 @@ Moreover, it would be cool if editors didn't need to implement even basic langua
311 This is how `SelectionRange` request works. 335 This is how `SelectionRange` request works.
312* Alternatively, should we perhaps flag certain `SelectionRange`s as being brace pairs? 336* Alternatively, should we perhaps flag certain `SelectionRange`s as being brace pairs?
313 337
338## Runnables
339
340**Issue:** https://github.com/microsoft/language-server-protocol/issues/944
341
342**Server Capability:** `{ "runnables": { "kinds": string[] } }`
343
344This request is send from client to server to get the list of things that can be run (tests, binaries, `cargo check -p`).
345
346**Method:** `experimental/runnables`
347
348**Request:**
349
350```typescript
351interface RunnablesParams {
352 textDocument: TextDocumentIdentifier;
353 /// If null, compute runnables for the whole file.
354 position?: Position;
355}
356```
357
358**Response:** `Runnable[]`
359
360```typescript
361interface Runnable {
362 label: string;
363 /// If this Runnable is associated with a specific function/module, etc, the location of this item
364 location?: LocationLink;
365 /// Running things is necessary technology specific, `kind` needs to be advertised via server capabilities,
366 // the type of `args` is specific to `kind`. The actual running is handled by the client.
367 kind: string;
368 args: any;
369}
370```
371
372rust-analyzer supports only one `kind`, `"cargo"`. The `args` for `"cargo"` look like this:
373
374```typescript
375{
376 workspaceRoot?: string;
377 cargoArgs: string[];
378 executableArgs: string[];
379}
380```
381
314## Analyzer Status 382## Analyzer Status
315 383
316**Method:** `rust-analyzer/analyzerStatus` 384**Method:** `rust-analyzer/analyzerStatus`
@@ -400,38 +468,40 @@ interface InlayHint {
400} 468}
401``` 469```
402 470
403## Runnables 471## Hover Actions
404
405**Method:** `rust-analyzer/runnables`
406 472
407This request is send from client to server to get the list of things that can be run (tests, binaries, `cargo check -p`). 473**Client Capability:** `{ "hoverActions": boolean }`
408Note that we plan to move this request to `experimental/runnables`, as it is not really Rust-specific, but the current API is not necessary the right one.
409Upstream issue: https://github.com/microsoft/language-server-protocol/issues/944
410 474
411**Request:** 475If this capability is set, `Hover` request returned from the server might contain an additional field, `actions`:
412 476
413```typescript 477```typescript
414interface RunnablesParams { 478interface Hover {
415 textDocument: TextDocumentIdentifier; 479 ...
416 /// If null, compute runnables for the whole file. 480 actions?: CommandLinkGroup[];
417 position?: Position;
418} 481}
419```
420 482
421**Response:** `Runnable[]` 483interface CommandLink extends Command {
484 /**
485 * A tooltip for the command, when represented in the UI.
486 */
487 tooltip?: string;
488}
422 489
423```typescript 490interface CommandLinkGroup {
424interface Runnable { 491 title?: string;
425 /// The range this runnable is applicable for. 492 commands: CommandLink[];
426 range: lc.Range;
427 /// The label to show in the UI.
428 label: string;
429 /// The following fields describe a process to spawn.
430 bin: string;
431 args: string[];
432 /// Args for cargo after `--`.
433 extraArgs: string[];
434 env: { [key: string]: string };
435 cwd: string | null;
436} 493}
437``` 494```
495
496Such actions on the client side are appended to a hover bottom as command links:
497```
498 +-----------------------------+
499 | Hover content |
500 | |
501 +-----------------------------+
502 | _Action1_ | _Action2_ | <- first group, no TITLE
503 +-----------------------------+
504 | TITLE _Action1_ | _Action2_ | <- second group
505 +-----------------------------+
506 ...
507``` \ No newline at end of file
diff --git a/docs/user/generated_assists.adoc b/docs/user/generated_assists.adoc
deleted file mode 100644
index 4d2fb31d4..000000000
--- a/docs/user/generated_assists.adoc
+++ /dev/null
@@ -1,1015 +0,0 @@
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
index 56538ca90..23a071cf1 100644
--- a/docs/user/generated_features.adoc
+++ b/docs/user/generated_features.adoc
@@ -76,7 +76,7 @@ Navigates to the type of an identifier.
76 76
77 77
78=== Hover 78=== Hover
79**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/hover.rs#L63[hover.rs] 79**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/hover.rs#L106[hover.rs]
80 80
81Shows additional information, like type of an expression or documentation for definition when "focusing" code. 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. 82Focusing is usually hovering with a mouse, but can also be triggered with a shortcut.
@@ -177,7 +177,7 @@ braces, so it won't confuse generics with comparisons.
177 177
178 178
179=== On Typing Assists 179=== On Typing Assists
180**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/typing.rs#L35[typing.rs] 180**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/typing.rs#L37[typing.rs]
181 181
182Some features trigger on typing certain characters: 182Some features trigger on typing certain characters:
183 183
@@ -199,7 +199,7 @@ Navigates to the parent module of the current module.
199 199
200 200
201=== Run 201=== Run
202**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/runnables.rs#L45[runnables.rs] 202**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/runnables.rs#L81[runnables.rs]
203 203
204Shows a popup suggesting to run a test/benchmark/binary **at the current cursor 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 205location**. Super useful for repeatedly running just a single test. Do bind this
@@ -213,7 +213,7 @@ to a shortcut!
213 213
214 214
215=== Semantic Syntax Highlighting 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] 216**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/syntax_highlighting.rs#L34[syntax_highlighting.rs]
217 217
218rust-analyzer highlights the code semantically. 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. 219For example, `bar` in `foo::Bar` might be colored differently depending on whether `Bar` is an enum or a trait.
@@ -275,7 +275,7 @@ String::from((y + 5).foo(z))
275 275
276 276
277=== Workspace Symbol 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] 278**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide_db/src/symbol_index.rs#L122[symbol_index.rs]
279 279
280Uses fuzzy-search to find types, modules and functions by name across your 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 281project and dependencies. This is **the** most useful feature, which improves code
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc
index 202783fd9..ea714f49a 100644
--- a/docs/user/manual.adoc
+++ b/docs/user/manual.adoc
@@ -269,6 +269,57 @@ Gnome Builder currently has support for RLS, and there's no way to configure the
2691. Rename, symlink or copy the `rust-analyzer` binary to `rls` and place it somewhere Builder can find (in `PATH`, or under `~/.cargo/bin`). 2691. Rename, symlink or copy the `rust-analyzer` binary to `rls` and place it somewhere Builder can find (in `PATH`, or under `~/.cargo/bin`).
2702. Enable the Rust Builder plugin. 2702. Enable the Rust Builder plugin.
271 271
272== Non-Cargo Based Projects
273
274rust-analyzer does not require Cargo.
275However, if you use some other build system, you'll have to describe the structure of your project for rust-analyzer in the `rust-project.json` format:
276
277[source,TypeScript]
278----
279interface JsonProject {
280 /// The set of paths containing the crates for this project.
281 /// Any `Crate` must be nested inside some `root`.
282 roots: string[];
283 /// The set of crates comprising the current project.
284 /// Must include all transitive dependencies as well as sysroot crate (libstd, libcore and such).
285 crates: Crate[];
286}
287
288interface Crate {
289 /// Path to the root module of the crate.
290 root_module: string;
291 /// Edition of the crate.
292 edition: "2015" | "2018";
293 /// Dependencies
294 deps: Dep[];
295 /// The set of cfgs activated for a given crate, like `["unix", "feature=foo", "feature=bar"]`.
296 cfg: string[];
297
298 /// value of the OUT_DIR env variable.
299 out_dir?: string;
300 /// For proc-macro crates, path to compiles proc-macro (.so file).
301 proc_macro_dylib_path?: string;
302}
303
304interface Dep {
305 /// Index of a crate in the `crates` array.
306 crate: number,
307 /// Name as should appear in the (implicit) `extern crate name` declaration.
308 name: string,
309}
310----
311
312This format is provisional and subject to change.
313Specifically, the `roots` setup will be different eventually.
314
315There are tree ways to feed `rust-project.json` to rust-analyzer:
316
317* Place `rust-project.json` file at the root of the project, and rust-anlayzer will discover it.
318* Specify `"rust-analyzer.linkedProjects": [ "path/to/rust-project.json" ]` in the settings (and make sure that your LSP client sends settings as a part of initialize request).
319* Specify `"rust-analyzer.linkedProjects": [ { "roots": [...], "crates": [...] }]` inline.
320
321See https://github.com/rust-analyzer/rust-project.json-example for a small example.
322
272== Features 323== Features
273 324
274include::./generated_features.adoc[] 325include::./generated_features.adoc[]