diff options
Diffstat (limited to 'docs/user')
-rw-r--r-- | docs/user/assists.md | 697 | ||||
-rw-r--r-- | docs/user/features.md | 202 | ||||
-rw-r--r-- | docs/user/generated_assists.adoc | 1015 | ||||
-rw-r--r-- | docs/user/generated_features.adoc | 298 | ||||
-rw-r--r-- | docs/user/manual.adoc (renamed from docs/user/readme.adoc) | 95 |
5 files changed, 1373 insertions, 934 deletions
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 | |||
3 | Cursor position or selection is signified by `┃` character. | ||
4 | |||
5 | |||
6 | ## `add_custom_impl` | ||
7 | |||
8 | Adds impl block for derived trait. | ||
9 | |||
10 | ```rust | ||
11 | // BEFORE | ||
12 | #[derive(Deb┃ug, Display)] | ||
13 | struct S; | ||
14 | |||
15 | // AFTER | ||
16 | #[derive(Display)] | ||
17 | struct S; | ||
18 | |||
19 | impl Debug for S { | ||
20 | |||
21 | } | ||
22 | ``` | ||
23 | |||
24 | ## `add_derive` | ||
25 | |||
26 | Adds a new `#[derive()]` clause to a struct or enum. | ||
27 | |||
28 | ```rust | ||
29 | // BEFORE | ||
30 | struct Point { | ||
31 | x: u32, | ||
32 | y: u32,┃ | ||
33 | } | ||
34 | |||
35 | // AFTER | ||
36 | #[derive()] | ||
37 | struct Point { | ||
38 | x: u32, | ||
39 | y: u32, | ||
40 | } | ||
41 | ``` | ||
42 | |||
43 | ## `add_explicit_type` | ||
44 | |||
45 | Specify type for a let binding. | ||
46 | |||
47 | ```rust | ||
48 | // BEFORE | ||
49 | fn main() { | ||
50 | let x┃ = 92; | ||
51 | } | ||
52 | |||
53 | // AFTER | ||
54 | fn main() { | ||
55 | let x: i32 = 92; | ||
56 | } | ||
57 | ``` | ||
58 | |||
59 | ## `add_function` | ||
60 | |||
61 | Adds a stub function with a signature matching the function under the cursor. | ||
62 | |||
63 | ```rust | ||
64 | // BEFORE | ||
65 | struct Baz; | ||
66 | fn baz() -> Baz { Baz } | ||
67 | fn foo() { | ||
68 | bar┃("", baz()); | ||
69 | } | ||
70 | |||
71 | |||
72 | // AFTER | ||
73 | struct Baz; | ||
74 | fn baz() -> Baz { Baz } | ||
75 | fn foo() { | ||
76 | bar("", baz()); | ||
77 | } | ||
78 | |||
79 | fn bar(arg: &str, baz: Baz) { | ||
80 | todo!() | ||
81 | } | ||
82 | |||
83 | ``` | ||
84 | |||
85 | ## `add_hash` | ||
86 | |||
87 | Adds a hash to a raw string literal. | ||
88 | |||
89 | ```rust | ||
90 | // BEFORE | ||
91 | fn main() { | ||
92 | r#"Hello,┃ World!"#; | ||
93 | } | ||
94 | |||
95 | // AFTER | ||
96 | fn main() { | ||
97 | r##"Hello, World!"##; | ||
98 | } | ||
99 | ``` | ||
100 | |||
101 | ## `add_impl` | ||
102 | |||
103 | Adds a new inherent impl for a type. | ||
104 | |||
105 | ```rust | ||
106 | // BEFORE | ||
107 | struct Ctx<T: Clone> { | ||
108 | data: T,┃ | ||
109 | } | ||
110 | |||
111 | // AFTER | ||
112 | struct Ctx<T: Clone> { | ||
113 | data: T, | ||
114 | } | ||
115 | |||
116 | impl<T: Clone> Ctx<T> { | ||
117 | |||
118 | } | ||
119 | ``` | ||
120 | |||
121 | ## `add_impl_default_members` | ||
122 | |||
123 | Adds scaffold for overriding default impl members. | ||
124 | |||
125 | ```rust | ||
126 | // BEFORE | ||
127 | trait Trait { | ||
128 | Type X; | ||
129 | fn foo(&self); | ||
130 | fn bar(&self) {} | ||
131 | } | ||
132 | |||
133 | impl Trait for () { | ||
134 | Type X = (); | ||
135 | fn foo(&self) {}┃ | ||
136 | |||
137 | } | ||
138 | |||
139 | // AFTER | ||
140 | trait Trait { | ||
141 | Type X; | ||
142 | fn foo(&self); | ||
143 | fn bar(&self) {} | ||
144 | } | ||
145 | |||
146 | impl Trait for () { | ||
147 | Type X = (); | ||
148 | fn foo(&self) {} | ||
149 | fn bar(&self) {} | ||
150 | |||
151 | } | ||
152 | ``` | ||
153 | |||
154 | ## `add_impl_missing_members` | ||
155 | |||
156 | Adds scaffold for required impl members. | ||
157 | |||
158 | ```rust | ||
159 | // BEFORE | ||
160 | trait Trait<T> { | ||
161 | Type X; | ||
162 | fn foo(&self) -> T; | ||
163 | fn bar(&self) {} | ||
164 | } | ||
165 | |||
166 | impl Trait<u32> for () {┃ | ||
167 | |||
168 | } | ||
169 | |||
170 | // AFTER | ||
171 | trait Trait<T> { | ||
172 | Type X; | ||
173 | fn foo(&self) -> T; | ||
174 | fn bar(&self) {} | ||
175 | } | ||
176 | |||
177 | impl Trait<u32> for () { | ||
178 | fn foo(&self) -> u32 { todo!() } | ||
179 | |||
180 | } | ||
181 | ``` | ||
182 | |||
183 | ## `add_new` | ||
184 | |||
185 | Adds a new inherent impl for a type. | ||
186 | |||
187 | ```rust | ||
188 | // BEFORE | ||
189 | struct Ctx<T: Clone> { | ||
190 | data: T,┃ | ||
191 | } | ||
192 | |||
193 | // AFTER | ||
194 | struct Ctx<T: Clone> { | ||
195 | data: T, | ||
196 | } | ||
197 | |||
198 | impl<T: Clone> Ctx<T> { | ||
199 | fn new(data: T) -> Self { Self { data } } | ||
200 | } | ||
201 | |||
202 | ``` | ||
203 | |||
204 | ## `apply_demorgan` | ||
205 | |||
206 | Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws). | ||
207 | This transforms expressions of the form `!l || !r` into `!(l && r)`. | ||
208 | This also works with `&&`. This assist can only be applied with the cursor | ||
209 | on either `||` or `&&`, with both operands being a negation of some kind. | ||
210 | This means something of the form `!x` or `x != y`. | ||
211 | |||
212 | ```rust | ||
213 | // BEFORE | ||
214 | fn main() { | ||
215 | if x != 4 ||┃ !y {} | ||
216 | } | ||
217 | |||
218 | // AFTER | ||
219 | fn main() { | ||
220 | if !(x == 4 && y) {} | ||
221 | } | ||
222 | ``` | ||
223 | |||
224 | ## `auto_import` | ||
225 | |||
226 | If the name is unresolved, provides all possible imports for it. | ||
227 | |||
228 | ```rust | ||
229 | // BEFORE | ||
230 | fn main() { | ||
231 | let map = HashMap┃::new(); | ||
232 | } | ||
233 | |||
234 | // AFTER | ||
235 | use std::collections::HashMap; | ||
236 | |||
237 | fn main() { | ||
238 | let map = HashMap::new(); | ||
239 | } | ||
240 | ``` | ||
241 | |||
242 | ## `change_visibility` | ||
243 | |||
244 | Adds or changes existing visibility specifier. | ||
245 | |||
246 | ```rust | ||
247 | // BEFORE | ||
248 | ┃fn frobnicate() {} | ||
249 | |||
250 | // AFTER | ||
251 | pub(crate) fn frobnicate() {} | ||
252 | ``` | ||
253 | |||
254 | ## `convert_to_guarded_return` | ||
255 | |||
256 | Replace a large conditional with a guarded return. | ||
257 | |||
258 | ```rust | ||
259 | // BEFORE | ||
260 | fn main() { | ||
261 | ┃if cond { | ||
262 | foo(); | ||
263 | bar(); | ||
264 | } | ||
265 | } | ||
266 | |||
267 | // AFTER | ||
268 | fn main() { | ||
269 | if !cond { | ||
270 | return; | ||
271 | } | ||
272 | foo(); | ||
273 | bar(); | ||
274 | } | ||
275 | ``` | ||
276 | |||
277 | ## `fill_match_arms` | ||
278 | |||
279 | Adds missing clauses to a `match` expression. | ||
280 | |||
281 | ```rust | ||
282 | // BEFORE | ||
283 | enum Action { Move { distance: u32 }, Stop } | ||
284 | |||
285 | fn handle(action: Action) { | ||
286 | match action { | ||
287 | ┃ | ||
288 | } | ||
289 | } | ||
290 | |||
291 | // AFTER | ||
292 | enum Action { Move { distance: u32 }, Stop } | ||
293 | |||
294 | fn handle(action: Action) { | ||
295 | match action { | ||
296 | Action::Move { distance } => {} | ||
297 | Action::Stop => {} | ||
298 | } | ||
299 | } | ||
300 | ``` | ||
301 | |||
302 | ## `flip_binexpr` | ||
303 | |||
304 | Flips operands of a binary expression. | ||
305 | |||
306 | ```rust | ||
307 | // BEFORE | ||
308 | fn main() { | ||
309 | let _ = 90 +┃ 2; | ||
310 | } | ||
311 | |||
312 | // AFTER | ||
313 | fn main() { | ||
314 | let _ = 2 + 90; | ||
315 | } | ||
316 | ``` | ||
317 | |||
318 | ## `flip_comma` | ||
319 | |||
320 | Flips two comma-separated items. | ||
321 | |||
322 | ```rust | ||
323 | // BEFORE | ||
324 | fn main() { | ||
325 | ((1, 2),┃ (3, 4)); | ||
326 | } | ||
327 | |||
328 | // AFTER | ||
329 | fn main() { | ||
330 | ((3, 4), (1, 2)); | ||
331 | } | ||
332 | ``` | ||
333 | |||
334 | ## `flip_trait_bound` | ||
335 | |||
336 | Flips two trait bounds. | ||
337 | |||
338 | ```rust | ||
339 | // BEFORE | ||
340 | fn foo<T: Clone +┃ Copy>() { } | ||
341 | |||
342 | // AFTER | ||
343 | fn foo<T: Copy + Clone>() { } | ||
344 | ``` | ||
345 | |||
346 | ## `inline_local_variable` | ||
347 | |||
348 | Inlines local variable. | ||
349 | |||
350 | ```rust | ||
351 | // BEFORE | ||
352 | fn main() { | ||
353 | let x┃ = 1 + 2; | ||
354 | x * 4; | ||
355 | } | ||
356 | |||
357 | // AFTER | ||
358 | fn main() { | ||
359 | (1 + 2) * 4; | ||
360 | } | ||
361 | ``` | ||
362 | |||
363 | ## `introduce_variable` | ||
364 | |||
365 | Extracts subexpression into a variable. | ||
366 | |||
367 | ```rust | ||
368 | // BEFORE | ||
369 | fn main() { | ||
370 | ┃(1 + 2)┃ * 4; | ||
371 | } | ||
372 | |||
373 | // AFTER | ||
374 | fn main() { | ||
375 | let var_name = (1 + 2); | ||
376 | var_name * 4; | ||
377 | } | ||
378 | ``` | ||
379 | |||
380 | ## `invert_if` | ||
381 | |||
382 | Apply invert_if | ||
383 | This transforms if expressions of the form `if !x {A} else {B}` into `if x {B} else {A}` | ||
384 | This also works with `!=`. This assist can only be applied with the cursor | ||
385 | on `if`. | ||
386 | |||
387 | ```rust | ||
388 | // BEFORE | ||
389 | fn main() { | ||
390 | if┃ !y { A } else { B } | ||
391 | } | ||
392 | |||
393 | // AFTER | ||
394 | fn main() { | ||
395 | if y { B } else { A } | ||
396 | } | ||
397 | ``` | ||
398 | |||
399 | ## `make_raw_string` | ||
400 | |||
401 | Adds `r#` to a plain string literal. | ||
402 | |||
403 | ```rust | ||
404 | // BEFORE | ||
405 | fn main() { | ||
406 | "Hello,┃ World!"; | ||
407 | } | ||
408 | |||
409 | // AFTER | ||
410 | fn main() { | ||
411 | r#"Hello, World!"#; | ||
412 | } | ||
413 | ``` | ||
414 | |||
415 | ## `make_usual_string` | ||
416 | |||
417 | Turns a raw string into a plain string. | ||
418 | |||
419 | ```rust | ||
420 | // BEFORE | ||
421 | fn main() { | ||
422 | r#"Hello,┃ "World!""#; | ||
423 | } | ||
424 | |||
425 | // AFTER | ||
426 | fn main() { | ||
427 | "Hello, \"World!\""; | ||
428 | } | ||
429 | ``` | ||
430 | |||
431 | ## `merge_imports` | ||
432 | |||
433 | Merges two imports with a common prefix. | ||
434 | |||
435 | ```rust | ||
436 | // BEFORE | ||
437 | use std::┃fmt::Formatter; | ||
438 | use std::io; | ||
439 | |||
440 | // AFTER | ||
441 | use std::{fmt::Formatter, io}; | ||
442 | ``` | ||
443 | |||
444 | ## `merge_match_arms` | ||
445 | |||
446 | Merges identical match arms. | ||
447 | |||
448 | ```rust | ||
449 | // BEFORE | ||
450 | enum Action { Move { distance: u32 }, Stop } | ||
451 | |||
452 | fn handle(action: Action) { | ||
453 | match action { | ||
454 | ┃Action::Move(..) => foo(), | ||
455 | Action::Stop => foo(), | ||
456 | } | ||
457 | } | ||
458 | |||
459 | // AFTER | ||
460 | enum Action { Move { distance: u32 }, Stop } | ||
461 | |||
462 | fn handle(action: Action) { | ||
463 | match action { | ||
464 | Action::Move(..) | Action::Stop => foo(), | ||
465 | } | ||
466 | } | ||
467 | ``` | ||
468 | |||
469 | ## `move_arm_cond_to_match_guard` | ||
470 | |||
471 | Moves if expression from match arm body into a guard. | ||
472 | |||
473 | ```rust | ||
474 | // BEFORE | ||
475 | enum Action { Move { distance: u32 }, Stop } | ||
476 | |||
477 | fn handle(action: Action) { | ||
478 | match action { | ||
479 | Action::Move { distance } => ┃if distance > 10 { foo() }, | ||
480 | _ => (), | ||
481 | } | ||
482 | } | ||
483 | |||
484 | // AFTER | ||
485 | enum Action { Move { distance: u32 }, Stop } | ||
486 | |||
487 | fn 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 | |||
497 | Moves inline type bounds to a where clause. | ||
498 | |||
499 | ```rust | ||
500 | // BEFORE | ||
501 | fn apply<T, U, ┃F: FnOnce(T) -> U>(f: F, x: T) -> U { | ||
502 | f(x) | ||
503 | } | ||
504 | |||
505 | // AFTER | ||
506 | fn 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 | |||
513 | Moves match guard into match arm body. | ||
514 | |||
515 | ```rust | ||
516 | // BEFORE | ||
517 | enum Action { Move { distance: u32 }, Stop } | ||
518 | |||
519 | fn handle(action: Action) { | ||
520 | match action { | ||
521 | Action::Move { distance } ┃if distance > 10 => foo(), | ||
522 | _ => (), | ||
523 | } | ||
524 | } | ||
525 | |||
526 | // AFTER | ||
527 | enum Action { Move { distance: u32 }, Stop } | ||
528 | |||
529 | fn handle(action: Action) { | ||
530 | match action { | ||
531 | Action::Move { distance } => if distance > 10 { foo() }, | ||
532 | _ => (), | ||
533 | } | ||
534 | } | ||
535 | ``` | ||
536 | |||
537 | ## `remove_dbg` | ||
538 | |||
539 | Removes `dbg!()` macro call. | ||
540 | |||
541 | ```rust | ||
542 | // BEFORE | ||
543 | fn main() { | ||
544 | ┃dbg!(92); | ||
545 | } | ||
546 | |||
547 | // AFTER | ||
548 | fn main() { | ||
549 | 92; | ||
550 | } | ||
551 | ``` | ||
552 | |||
553 | ## `remove_hash` | ||
554 | |||
555 | Removes a hash from a raw string literal. | ||
556 | |||
557 | ```rust | ||
558 | // BEFORE | ||
559 | fn main() { | ||
560 | r#"Hello,┃ World!"#; | ||
561 | } | ||
562 | |||
563 | // AFTER | ||
564 | fn main() { | ||
565 | r"Hello, World!"; | ||
566 | } | ||
567 | ``` | ||
568 | |||
569 | ## `remove_mut` | ||
570 | |||
571 | Removes the `mut` keyword. | ||
572 | |||
573 | ```rust | ||
574 | // BEFORE | ||
575 | impl Walrus { | ||
576 | fn feed(&mut┃ self, amount: u32) {} | ||
577 | } | ||
578 | |||
579 | // AFTER | ||
580 | impl Walrus { | ||
581 | fn feed(&self, amount: u32) {} | ||
582 | } | ||
583 | ``` | ||
584 | |||
585 | ## `reorder_fields` | ||
586 | |||
587 | Reorder the fields of record literals and record patterns in the same order as in | ||
588 | the definition. | ||
589 | |||
590 | ```rust | ||
591 | // BEFORE | ||
592 | struct Foo {foo: i32, bar: i32}; | ||
593 | const test: Foo = ┃Foo {bar: 0, foo: 1} | ||
594 | |||
595 | // AFTER | ||
596 | struct Foo {foo: i32, bar: i32}; | ||
597 | const test: Foo = Foo {foo: 1, bar: 0} | ||
598 | ``` | ||
599 | |||
600 | ## `replace_if_let_with_match` | ||
601 | |||
602 | Replaces `if let` with an else branch with a `match` expression. | ||
603 | |||
604 | ```rust | ||
605 | // BEFORE | ||
606 | enum Action { Move { distance: u32 }, Stop } | ||
607 | |||
608 | fn handle(action: Action) { | ||
609 | ┃if let Action::Move { distance } = action { | ||
610 | foo(distance) | ||
611 | } else { | ||
612 | bar() | ||
613 | } | ||
614 | } | ||
615 | |||
616 | // AFTER | ||
617 | enum Action { Move { distance: u32 }, Stop } | ||
618 | |||
619 | fn 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 | |||
629 | Replaces `let` with an `if-let`. | ||
630 | |||
631 | ```rust | ||
632 | // BEFORE | ||
633 | |||
634 | fn main(action: Action) { | ||
635 | ┃let x = compute(); | ||
636 | } | ||
637 | |||
638 | fn compute() -> Option<i32> { None } | ||
639 | |||
640 | // AFTER | ||
641 | |||
642 | fn main(action: Action) { | ||
643 | if let Some(x) = compute() { | ||
644 | } | ||
645 | } | ||
646 | |||
647 | fn compute() -> Option<i32> { None } | ||
648 | ``` | ||
649 | |||
650 | ## `replace_qualified_name_with_use` | ||
651 | |||
652 | Adds a use statement for a given fully-qualified name. | ||
653 | |||
654 | ```rust | ||
655 | // BEFORE | ||
656 | fn process(map: std::collections::┃HashMap<String, String>) {} | ||
657 | |||
658 | // AFTER | ||
659 | use std::collections::HashMap; | ||
660 | |||
661 | fn process(map: HashMap<String, String>) {} | ||
662 | ``` | ||
663 | |||
664 | ## `replace_unwrap_with_match` | ||
665 | |||
666 | Replaces `unwrap` a `match` expression. Works for Result and Option. | ||
667 | |||
668 | ```rust | ||
669 | // BEFORE | ||
670 | enum Result<T, E> { Ok(T), Err(E) } | ||
671 | fn main() { | ||
672 | let x: Result<i32, i32> = Result::Ok(92); | ||
673 | let y = x.┃unwrap(); | ||
674 | } | ||
675 | |||
676 | // AFTER | ||
677 | enum Result<T, E> { Ok(T), Err(E) } | ||
678 | fn 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 | |||
689 | Wraps the tail of import into braces. | ||
690 | |||
691 | ```rust | ||
692 | // BEFORE | ||
693 | use std::┃collections::HashMap; | ||
694 | |||
695 | // AFTER | ||
696 | use 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 @@ | |||
1 | This document is an index of features that the rust-analyzer language server | ||
2 | provides. Shortcuts are for the default VS Code layout. If there's no shortcut, | ||
3 | you can use <kbd>Ctrl+Shift+P</kbd> to search for the corresponding action. | ||
4 | |||
5 | ### Workspace Symbol <kbd>ctrl+t</kbd> | ||
6 | |||
7 | Uses fuzzy-search to find types, modules and functions by name across your | ||
8 | project and dependencies. This is **the** most useful feature, which improves code | ||
9 | navigation tremendously. It mostly works on top of the built-in LSP | ||
10 | functionality, however `#` and `*` symbols can be used to narrow down the | ||
11 | search. 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 | |||
18 | That is, `#` switches from "types" to all symbols, `*` switches from the current | ||
19 | workspace to dependencies. | ||
20 | |||
21 | ### Document Symbol <kbd>ctrl+shift+o</kbd> | ||
22 | |||
23 | Provides 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 | |||
31 | Some 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 | |||
39 | Extends the current selection to the encompassing syntactic construct | ||
40 | (expression, statement, item, module, etc). It works with multiple cursors. This | ||
41 | is a relatively new feature of LSP: | ||
42 | https://github.com/Microsoft/language-server-protocol/issues/613, check your | ||
43 | editor's LSP library to see if this feature is supported. | ||
44 | |||
45 | ### Go to Definition | ||
46 | |||
47 | Navigates to the definition of an identifier. | ||
48 | |||
49 | ### Go to Implementation | ||
50 | |||
51 | Navigates to the impl block of structs, enums or traits. Also implemented as a code lens. | ||
52 | |||
53 | ### Go to Type Defintion | ||
54 | |||
55 | Navigates to the type of an identifier. | ||
56 | |||
57 | ### Commands <kbd>ctrl+shift+p</kbd> | ||
58 | |||
59 | #### Run | ||
60 | |||
61 | Shows a popup suggesting to run a test/benchmark/binary **at the current cursor | ||
62 | location**. Super useful for repeatedly running just a single test. Do bind this | ||
63 | to a shortcut! | ||
64 | |||
65 | #### Parent Module | ||
66 | |||
67 | Navigates to the parent module of the current module. | ||
68 | |||
69 | #### Matching Brace | ||
70 | |||
71 | If the cursor is on any brace (`<>(){}[]`) which is a part of a brace-pair, | ||
72 | moves cursor to the matching brace. It uses the actual parser to determine | ||
73 | braces, so it won't confuse generics with comparisons. | ||
74 | |||
75 | #### Join Lines | ||
76 | |||
77 | Join selected lines into one, smartly fixing up whitespace and trailing commas. | ||
78 | |||
79 | #### Show Syntax Tree | ||
80 | |||
81 | Shows the parse tree of the current file. It exists mostly for debugging | ||
82 | rust-analyzer itself. | ||
83 | |||
84 | #### Expand Macro Recursively | ||
85 | |||
86 | Shows the full macro expansion of the macro at current cursor. | ||
87 | |||
88 | #### Status | ||
89 | |||
90 | Shows internal statistic about memory usage of rust-analyzer. | ||
91 | |||
92 | #### Show RA Version | ||
93 | |||
94 | Show current rust-analyzer version. | ||
95 | |||
96 | #### Run Garbage Collection | ||
97 | |||
98 | Manually triggers GC. | ||
99 | |||
100 | #### Start Cargo Watch | ||
101 | |||
102 | Start `cargo watch` for live error highlighting. Will prompt to install if it's not already installed. | ||
103 | |||
104 | #### Stop Cargo Watch | ||
105 | |||
106 | Stop `cargo watch`. | ||
107 | |||
108 | #### Structural Seach and Replace | ||
109 | |||
110 | Search and replace with named wildcards that will match any expression. | ||
111 | The 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 | ||
117 | String::from(foo(y + 5, z)) | ||
118 | |||
119 | // AFTER | ||
120 | String::from((y + 5).foo(z)) | ||
121 | ``` | ||
122 | |||
123 | ### Assists (Code Actions) | ||
124 | |||
125 | Assists, or code actions, are small local refactorings, available in a particular context. | ||
126 | They are usually triggered by a shortcut or by clicking a light bulb icon in the editor. | ||
127 | |||
128 | See [assists.md](./assists.md) for the list of available assists. | ||
129 | |||
130 | ### Magic Completions | ||
131 | |||
132 | In addition to usual reference completion, rust-analyzer provides some ✨magic✨ | ||
133 | completions as well: | ||
134 | |||
135 | Keywords like `if`, `else` `while`, `loop` are completed with braces, and cursor | ||
136 | is placed at the appropriate position. Even though `if` is easy to type, you | ||
137 | still want to complete it, to get ` { }` for free! `return` is inserted with a | ||
138 | space or `;` depending on the return type of the function. | ||
139 | |||
140 | When completing a function call, `()` are automatically inserted. If a function | ||
141 | takes arguments, the cursor is positioned inside the parenthesis. | ||
142 | |||
143 | There 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 | |||
154 | There 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 | |||
167 | Experimental feature to let rust-analyzer highlight Rust code instead of using the | ||
168 | default highlighter. | ||
169 | |||
170 | #### Rainbow Highlighting | ||
171 | |||
172 | Experimental feature that, given code highlighting using rust-analyzer is | ||
173 | active, will pick unique colors for identifiers. | ||
174 | |||
175 | ### Code hints | ||
176 | |||
177 | Rust-analyzer has two types of hints to show the information about the code: | ||
178 | |||
179 | * hover hints, appearing on hover on any element. | ||
180 | |||
181 | These contain extended information on the hovered language item. | ||
182 | |||
183 | * inlay hints, shown near the element hinted directly in the editor. | ||
184 | |||
185 | Two 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 | |||
193 | In 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. | ||
201 | This 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 | |||
5 | Adds impl block for derived trait. | ||
6 | |||
7 | .Before | ||
8 | ```rust | ||
9 | #[derive(Deb┃ug, Display)] | ||
10 | struct S; | ||
11 | ``` | ||
12 | |||
13 | .After | ||
14 | ```rust | ||
15 | #[derive(Display)] | ||
16 | struct S; | ||
17 | |||
18 | impl 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 | |||
28 | Adds a new `#[derive()]` clause to a struct or enum. | ||
29 | |||
30 | .Before | ||
31 | ```rust | ||
32 | struct Point { | ||
33 | x: u32, | ||
34 | y: u32,┃ | ||
35 | } | ||
36 | ``` | ||
37 | |||
38 | .After | ||
39 | ```rust | ||
40 | #[derive($0)] | ||
41 | struct 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 | |||
52 | Specify type for a let binding. | ||
53 | |||
54 | .Before | ||
55 | ```rust | ||
56 | fn main() { | ||
57 | let x┃ = 92; | ||
58 | } | ||
59 | ``` | ||
60 | |||
61 | .After | ||
62 | ```rust | ||
63 | fn 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 | |||
73 | Adds a From impl for an enum variant with one tuple field. | ||
74 | |||
75 | .Before | ||
76 | ```rust | ||
77 | enum A { ┃One(u32) } | ||
78 | ``` | ||
79 | |||
80 | .After | ||
81 | ```rust | ||
82 | enum A { One(u32) } | ||
83 | |||
84 | impl 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 | |||
96 | Adds a stub function with a signature matching the function under the cursor. | ||
97 | |||
98 | .Before | ||
99 | ```rust | ||
100 | struct Baz; | ||
101 | fn baz() -> Baz { Baz } | ||
102 | fn foo() { | ||
103 | bar┃("", baz()); | ||
104 | } | ||
105 | |||
106 | ``` | ||
107 | |||
108 | .After | ||
109 | ```rust | ||
110 | struct Baz; | ||
111 | fn baz() -> Baz { Baz } | ||
112 | fn foo() { | ||
113 | bar("", baz()); | ||
114 | } | ||
115 | |||
116 | fn 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 | |||
127 | Adds a hash to a raw string literal. | ||
128 | |||
129 | .Before | ||
130 | ```rust | ||
131 | fn main() { | ||
132 | r#"Hello,┃ World!"#; | ||
133 | } | ||
134 | ``` | ||
135 | |||
136 | .After | ||
137 | ```rust | ||
138 | fn 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 | |||
148 | Adds a new inherent impl for a type. | ||
149 | |||
150 | .Before | ||
151 | ```rust | ||
152 | struct Ctx<T: Clone> { | ||
153 | data: T,┃ | ||
154 | } | ||
155 | ``` | ||
156 | |||
157 | .After | ||
158 | ```rust | ||
159 | struct Ctx<T: Clone> { | ||
160 | data: T, | ||
161 | } | ||
162 | |||
163 | impl<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 | |||
173 | Adds scaffold for overriding default impl members. | ||
174 | |||
175 | .Before | ||
176 | ```rust | ||
177 | trait Trait { | ||
178 | Type X; | ||
179 | fn foo(&self); | ||
180 | fn bar(&self) {} | ||
181 | } | ||
182 | |||
183 | impl Trait for () { | ||
184 | Type X = (); | ||
185 | fn foo(&self) {}┃ | ||
186 | |||
187 | } | ||
188 | ``` | ||
189 | |||
190 | .After | ||
191 | ```rust | ||
192 | trait Trait { | ||
193 | Type X; | ||
194 | fn foo(&self); | ||
195 | fn bar(&self) {} | ||
196 | } | ||
197 | |||
198 | impl 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 | |||
211 | Adds scaffold for required impl members. | ||
212 | |||
213 | .Before | ||
214 | ```rust | ||
215 | trait Trait<T> { | ||
216 | Type X; | ||
217 | fn foo(&self) -> T; | ||
218 | fn bar(&self) {} | ||
219 | } | ||
220 | |||
221 | impl Trait<u32> for () {┃ | ||
222 | |||
223 | } | ||
224 | ``` | ||
225 | |||
226 | .After | ||
227 | ```rust | ||
228 | trait Trait<T> { | ||
229 | Type X; | ||
230 | fn foo(&self) -> T; | ||
231 | fn bar(&self) {} | ||
232 | } | ||
233 | |||
234 | impl 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 | |||
247 | Adds a new inherent impl for a type. | ||
248 | |||
249 | .Before | ||
250 | ```rust | ||
251 | struct Ctx<T: Clone> { | ||
252 | data: T,┃ | ||
253 | } | ||
254 | ``` | ||
255 | |||
256 | .After | ||
257 | ```rust | ||
258 | struct Ctx<T: Clone> { | ||
259 | data: T, | ||
260 | } | ||
261 | |||
262 | impl<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 | |||
273 | Adds `::<_>` to a call of a generic method or function. | ||
274 | |||
275 | .Before | ||
276 | ```rust | ||
277 | fn make<T>() -> T { todo!() } | ||
278 | fn main() { | ||
279 | let x = make┃(); | ||
280 | } | ||
281 | ``` | ||
282 | |||
283 | .After | ||
284 | ```rust | ||
285 | fn make<T>() -> T { todo!() } | ||
286 | fn 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 | |||
296 | Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws). | ||
297 | This transforms expressions of the form `!l || !r` into `!(l && r)`. | ||
298 | This also works with `&&`. This assist can only be applied with the cursor | ||
299 | on either `||` or `&&`, with both operands being a negation of some kind. | ||
300 | This means something of the form `!x` or `x != y`. | ||
301 | |||
302 | .Before | ||
303 | ```rust | ||
304 | fn main() { | ||
305 | if x != 4 ||┃ !y {} | ||
306 | } | ||
307 | ``` | ||
308 | |||
309 | .After | ||
310 | ```rust | ||
311 | fn 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 | |||
321 | If the name is unresolved, provides all possible imports for it. | ||
322 | |||
323 | .Before | ||
324 | ```rust | ||
325 | fn main() { | ||
326 | let map = HashMap┃::new(); | ||
327 | } | ||
328 | ``` | ||
329 | |||
330 | .After | ||
331 | ```rust | ||
332 | use std::collections::HashMap; | ||
333 | |||
334 | fn 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 | |||
344 | Change the function's return type to Result. | ||
345 | |||
346 | .Before | ||
347 | ```rust | ||
348 | fn foo() -> i32┃ { 42i32 } | ||
349 | ``` | ||
350 | |||
351 | .After | ||
352 | ```rust | ||
353 | fn 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 | |||
361 | Adds or changes existing visibility specifier. | ||
362 | |||
363 | .Before | ||
364 | ```rust | ||
365 | ┃fn frobnicate() {} | ||
366 | ``` | ||
367 | |||
368 | .After | ||
369 | ```rust | ||
370 | pub(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 | |||
378 | Replace a large conditional with a guarded return. | ||
379 | |||
380 | .Before | ||
381 | ```rust | ||
382 | fn main() { | ||
383 | ┃if cond { | ||
384 | foo(); | ||
385 | bar(); | ||
386 | } | ||
387 | } | ||
388 | ``` | ||
389 | |||
390 | .After | ||
391 | ```rust | ||
392 | fn 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 | |||
406 | Adds missing clauses to a `match` expression. | ||
407 | |||
408 | .Before | ||
409 | ```rust | ||
410 | enum Action { Move { distance: u32 }, Stop } | ||
411 | |||
412 | fn handle(action: Action) { | ||
413 | match action { | ||
414 | ┃ | ||
415 | } | ||
416 | } | ||
417 | ``` | ||
418 | |||
419 | .After | ||
420 | ```rust | ||
421 | enum Action { Move { distance: u32 }, Stop } | ||
422 | |||
423 | fn 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 | |||
436 | Makes inaccessible item public. | ||
437 | |||
438 | .Before | ||
439 | ```rust | ||
440 | mod m { | ||
441 | fn frobnicate() {} | ||
442 | } | ||
443 | fn main() { | ||
444 | m::frobnicate┃() {} | ||
445 | } | ||
446 | ``` | ||
447 | |||
448 | .After | ||
449 | ```rust | ||
450 | mod m { | ||
451 | $0pub(crate) fn frobnicate() {} | ||
452 | } | ||
453 | fn 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 | |||
463 | Flips operands of a binary expression. | ||
464 | |||
465 | .Before | ||
466 | ```rust | ||
467 | fn main() { | ||
468 | let _ = 90 +┃ 2; | ||
469 | } | ||
470 | ``` | ||
471 | |||
472 | .After | ||
473 | ```rust | ||
474 | fn 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 | |||
484 | Flips two comma-separated items. | ||
485 | |||
486 | .Before | ||
487 | ```rust | ||
488 | fn main() { | ||
489 | ((1, 2),┃ (3, 4)); | ||
490 | } | ||
491 | ``` | ||
492 | |||
493 | .After | ||
494 | ```rust | ||
495 | fn 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 | |||
505 | Flips two trait bounds. | ||
506 | |||
507 | .Before | ||
508 | ```rust | ||
509 | fn foo<T: Clone +┃ Copy>() { } | ||
510 | ``` | ||
511 | |||
512 | .After | ||
513 | ```rust | ||
514 | fn 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 | |||
522 | Inlines local variable. | ||
523 | |||
524 | .Before | ||
525 | ```rust | ||
526 | fn main() { | ||
527 | let x┃ = 1 + 2; | ||
528 | x * 4; | ||
529 | } | ||
530 | ``` | ||
531 | |||
532 | .After | ||
533 | ```rust | ||
534 | fn 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 | |||
544 | Change an anonymous lifetime to a named lifetime. | ||
545 | |||
546 | .Before | ||
547 | ```rust | ||
548 | impl 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 | ||
559 | impl<'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 | |||
573 | Extracts subexpression into a variable. | ||
574 | |||
575 | .Before | ||
576 | ```rust | ||
577 | fn main() { | ||
578 | ┃(1 + 2)┃ * 4; | ||
579 | } | ||
580 | ``` | ||
581 | |||
582 | .After | ||
583 | ```rust | ||
584 | fn 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 | |||
595 | Apply invert_if | ||
596 | This transforms if expressions of the form `if !x {A} else {B}` into `if x {B} else {A}` | ||
597 | This also works with `!=`. This assist can only be applied with the cursor | ||
598 | on `if`. | ||
599 | |||
600 | .Before | ||
601 | ```rust | ||
602 | fn main() { | ||
603 | if┃ !y { A } else { B } | ||
604 | } | ||
605 | ``` | ||
606 | |||
607 | .After | ||
608 | ```rust | ||
609 | fn 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 | |||
619 | Adds `r#` to a plain string literal. | ||
620 | |||
621 | .Before | ||
622 | ```rust | ||
623 | fn main() { | ||
624 | "Hello,┃ World!"; | ||
625 | } | ||
626 | ``` | ||
627 | |||
628 | .After | ||
629 | ```rust | ||
630 | fn 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 | |||
640 | Turns a raw string into a plain string. | ||
641 | |||
642 | .Before | ||
643 | ```rust | ||
644 | fn main() { | ||
645 | r#"Hello,┃ "World!""#; | ||
646 | } | ||
647 | ``` | ||
648 | |||
649 | .After | ||
650 | ```rust | ||
651 | fn 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 | |||
661 | Merges two imports with a common prefix. | ||
662 | |||
663 | .Before | ||
664 | ```rust | ||
665 | use std::┃fmt::Formatter; | ||
666 | use std::io; | ||
667 | ``` | ||
668 | |||
669 | .After | ||
670 | ```rust | ||
671 | use 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 | |||
679 | Merges identical match arms. | ||
680 | |||
681 | .Before | ||
682 | ```rust | ||
683 | enum Action { Move { distance: u32 }, Stop } | ||
684 | |||
685 | fn handle(action: Action) { | ||
686 | match action { | ||
687 | ┃Action::Move(..) => foo(), | ||
688 | Action::Stop => foo(), | ||
689 | } | ||
690 | } | ||
691 | ``` | ||
692 | |||
693 | .After | ||
694 | ```rust | ||
695 | enum Action { Move { distance: u32 }, Stop } | ||
696 | |||
697 | fn 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 | |||
709 | Moves if expression from match arm body into a guard. | ||
710 | |||
711 | .Before | ||
712 | ```rust | ||
713 | enum Action { Move { distance: u32 }, Stop } | ||
714 | |||
715 | fn handle(action: Action) { | ||
716 | match action { | ||
717 | Action::Move { distance } => ┃if distance > 10 { foo() }, | ||
718 | _ => (), | ||
719 | } | ||
720 | } | ||
721 | ``` | ||
722 | |||
723 | .After | ||
724 | ```rust | ||
725 | enum Action { Move { distance: u32 }, Stop } | ||
726 | |||
727 | fn 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 | |||
740 | Moves inline type bounds to a where clause. | ||
741 | |||
742 | .Before | ||
743 | ```rust | ||
744 | fn apply<T, U, ┃F: FnOnce(T) -> U>(f: F, x: T) -> U { | ||
745 | f(x) | ||
746 | } | ||
747 | ``` | ||
748 | |||
749 | .After | ||
750 | ```rust | ||
751 | fn 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 | |||
761 | Moves match guard into match arm body. | ||
762 | |||
763 | .Before | ||
764 | ```rust | ||
765 | enum Action { Move { distance: u32 }, Stop } | ||
766 | |||
767 | fn handle(action: Action) { | ||
768 | match action { | ||
769 | Action::Move { distance } ┃if distance > 10 => foo(), | ||
770 | _ => (), | ||
771 | } | ||
772 | } | ||
773 | ``` | ||
774 | |||
775 | .After | ||
776 | ```rust | ||
777 | enum Action { Move { distance: u32 }, Stop } | ||
778 | |||
779 | fn 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 | |||
792 | Removes `dbg!()` macro call. | ||
793 | |||
794 | .Before | ||
795 | ```rust | ||
796 | fn main() { | ||
797 | ┃dbg!(92); | ||
798 | } | ||
799 | ``` | ||
800 | |||
801 | .After | ||
802 | ```rust | ||
803 | fn 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 | |||
813 | Removes a hash from a raw string literal. | ||
814 | |||
815 | .Before | ||
816 | ```rust | ||
817 | fn main() { | ||
818 | r#"Hello,┃ World!"#; | ||
819 | } | ||
820 | ``` | ||
821 | |||
822 | .After | ||
823 | ```rust | ||
824 | fn 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 | |||
834 | Removes the `mut` keyword. | ||
835 | |||
836 | .Before | ||
837 | ```rust | ||
838 | impl Walrus { | ||
839 | fn feed(&mut┃ self, amount: u32) {} | ||
840 | } | ||
841 | ``` | ||
842 | |||
843 | .After | ||
844 | ```rust | ||
845 | impl 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 | |||
855 | Reorder the fields of record literals and record patterns in the same order as in | ||
856 | the definition. | ||
857 | |||
858 | .Before | ||
859 | ```rust | ||
860 | struct Foo {foo: i32, bar: i32}; | ||
861 | const test: Foo = ┃Foo {bar: 0, foo: 1} | ||
862 | ``` | ||
863 | |||
864 | .After | ||
865 | ```rust | ||
866 | struct Foo {foo: i32, bar: i32}; | ||
867 | const 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 | |||
875 | Replaces `if let` with an else branch with a `match` expression. | ||
876 | |||
877 | .Before | ||
878 | ```rust | ||
879 | enum Action { Move { distance: u32 }, Stop } | ||
880 | |||
881 | fn 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 | ||
892 | enum Action { Move { distance: u32 }, Stop } | ||
893 | |||
894 | fn 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 | |||
907 | Replaces `let` with an `if-let`. | ||
908 | |||
909 | .Before | ||
910 | ```rust | ||
911 | |||
912 | fn main(action: Action) { | ||
913 | ┃let x = compute(); | ||
914 | } | ||
915 | |||
916 | fn compute() -> Option<i32> { None } | ||
917 | ``` | ||
918 | |||
919 | .After | ||
920 | ```rust | ||
921 | |||
922 | fn main(action: Action) { | ||
923 | if let Some(x) = compute() { | ||
924 | } | ||
925 | } | ||
926 | |||
927 | fn 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 | |||
935 | Adds a use statement for a given fully-qualified name. | ||
936 | |||
937 | .Before | ||
938 | ```rust | ||
939 | fn process(map: std::collections::┃HashMap<String, String>) {} | ||
940 | ``` | ||
941 | |||
942 | .After | ||
943 | ```rust | ||
944 | use std::collections::HashMap; | ||
945 | |||
946 | fn 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 | |||
954 | Replaces `unwrap` a `match` expression. Works for Result and Option. | ||
955 | |||
956 | .Before | ||
957 | ```rust | ||
958 | enum Result<T, E> { Ok(T), Err(E) } | ||
959 | fn main() { | ||
960 | let x: Result<i32, i32> = Result::Ok(92); | ||
961 | let y = x.┃unwrap(); | ||
962 | } | ||
963 | ``` | ||
964 | |||
965 | .After | ||
966 | ```rust | ||
967 | enum Result<T, E> { Ok(T), Err(E) } | ||
968 | fn 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 | |||
982 | Wraps the tail of import into braces. | ||
983 | |||
984 | .Before | ||
985 | ```rust | ||
986 | use std::┃collections::HashMap; | ||
987 | ``` | ||
988 | |||
989 | .After | ||
990 | ```rust | ||
991 | use 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 | |||
999 | This assist removes if...else, for, while and loop control statements to just keep the body. | ||
1000 | |||
1001 | .Before | ||
1002 | ```rust | ||
1003 | fn foo() { | ||
1004 | if true {┃ | ||
1005 | println!("foo"); | ||
1006 | } | ||
1007 | } | ||
1008 | ``` | ||
1009 | |||
1010 | .After | ||
1011 | ```rust | ||
1012 | fn 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 | |||
4 | Shows 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 | |||
16 | Extends 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 | |||
29 | Provides 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 | |||
45 | Navigates 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 | |||
57 | Navigates 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 | |||
69 | Navigates 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 | |||
81 | Shows additional information, like type of an expression or documentation for definition when "focusing" code. | ||
82 | Focusing 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 | |||
88 | rust-analyzer shows additional information inline with the source code. | ||
89 | Editors usually render this using read-only virtual text snippets interspersed with code. | ||
90 | |||
91 | rust-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. | ||
98 | This approach has limitations, the caret movement and bracket highlighting near the edges of the hint may be weird: | ||
99 | https://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 | |||
111 | Join 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 | |||
123 | In addition to usual reference completion, rust-analyzer provides some ✨magic✨ | ||
124 | completions as well: | ||
125 | |||
126 | Keywords like `if`, `else` `while`, `loop` are completed with braces, and cursor | ||
127 | is placed at the appropriate position. Even though `if` is easy to type, you | ||
128 | still want to complete it, to get ` { }` for free! `return` is inserted with a | ||
129 | space or `;` depending on the return type of the function. | ||
130 | |||
131 | When completing a function call, `()` are automatically inserted. If a function | ||
132 | takes arguments, the cursor is positioned inside the parenthesis. | ||
133 | |||
134 | There 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 | |||
145 | There 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)] | ||
156 | mod 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 | |||
168 | If the cursor is on any brace (`<>(){}[]`) which is a part of a brace-pair, | ||
169 | moves cursor to the matching brace. It uses the actual parser to determine | ||
170 | braces, 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 | |||
182 | Some 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 | |||
192 | Navigates 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 | |||
204 | Shows a popup suggesting to run a test/benchmark/binary **at the current cursor | ||
205 | location**. Super useful for repeatedly running just a single test. Do bind this | ||
206 | to 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 | |||
218 | rust-analyzer highlights the code semantically. | ||
219 | For example, `bar` in `foo::Bar` might be colored differently depending on whether `Bar` is an enum or a trait. | ||
220 | rust-analyzer does not specify colors directly, instead it assigns tag (like `struct`) and a set of modifiers (like `declaration`) to each token. | ||
221 | It's up to the client to map those to specific colors. | ||
222 | |||
223 | The general rule is that a reference to an entity gets colored the same way as the entity itself. | ||
224 | We 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 | |||
230 | Shows the parse tree of the current file. It exists mostly for debugging | ||
231 | rust-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 | |||
243 | Shows 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 | |||
255 | Search and replace with named wildcards that will match any expression. | ||
256 | The syntax for a structural search replace command is `<search_pattern> ==>> <replace_pattern>`. | ||
257 | A `$<name>:expr` placeholder in the search pattern will match any expression and `$<name>` will reference it in the replacement. | ||
258 | Available 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 | ||
264 | String::from(foo(y + 5, z)) | ||
265 | |||
266 | // AFTER | ||
267 | String::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 | |||
280 | Uses fuzzy-search to find types, modules and functions by name across your | ||
281 | project and dependencies. This is **the** most useful feature, which improves code | ||
282 | navigation tremendously. It mostly works on top of the built-in LSP | ||
283 | functionality, however `#` and `*` symbols can be used to narrow down the | ||
284 | search. 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 | |||
291 | That is, `#` switches from "types" to all symbols, `*` switches from the current | ||
292 | workspace 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] | |||
19 | The 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. | 14 | The 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 | ||
21 | To improve this document, send a pull request against | 16 | To improve this document, send a pull request against |
22 | https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/readme.adoc[this file]. | 17 | https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/manual.adoc[this file]. |
18 | |||
19 | If 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 | ||
60 | The 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). | 57 | The server binary is stored in: |
61 | 58 | ||
62 | Note 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 | |||
63 | Note 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. | ||
113 | You 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 | ---- | ||
122 | More 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 | ||
113 | Other editors generally require the `rust-analyzer` binary to be in `$PATH`. | 126 | Other editors generally require the `rust-analyzer` binary to be in `$PATH`. |
114 | You 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`. | 127 | You can download the pre-built binary from the https://github.com/rust-analyzer/rust-analyzer/releases[releases] page. |
128 | 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`. | ||
115 | 129 | ||
116 | On Linux to install the `rust-analyzer` binary into `~/.local/bin`, this commands could be used | 130 | On 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 | ||
134 | If 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. | 148 | If 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]. |
149 | On 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 | ||
138 | The `rust-analyzer` binary can be installed from AUR (Arch User Repository): | 153 | The `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 | ||
144 | Install it with AUR helper of your choice, for example: | 158 | Install 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 | |||
159 | 3. Run `lsp` in a Rust buffer. | 173 | 3. Run `lsp` in a Rust buffer. |
160 | 4. (Optionally) bind commands like `lsp-rust-analyzer-join-lines`, `lsp-extend-selection` and `lsp-rust-analyzer-expand-macro` to keys. | 174 | 4. (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 | ||
164 | Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>. | 178 | Prerequisites: 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 | ||
166 | The are several LSP client implementations for vim: | 180 | The 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 | ||
184 | 1. Install LanguageClient-neovim by following the instructions | 198 | 1. 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 | ||
188 | 2. Configure by adding this to your vim/neovim config file (replacing the existing Rust-specific line if it exists): | 202 | 2. 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 | ||
202 | 2. Configure by adding this to your vim/neovim config file (replacing the existing Rust-specific line if it exists): | 216 | 2. 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 | ---- |
206 | let g:ycm_language_server = | 220 | let g:ycm_language_server = |
207 | \ [ | 221 | \ [ |
@@ -216,17 +230,11 @@ let g:ycm_language_server = | |||
216 | 230 | ||
217 | ==== ALE | 231 | ==== ALE |
218 | 232 | ||
219 | To add the LSP server to https://github.com/dense-analysis/ale[ale]: | 233 | To use the LSP server in https://github.com/dense-analysis/ale[ale]: |
220 | 234 | ||
221 | [source,vim] | 235 | [source,vim] |
222 | ---- | 236 | ---- |
223 | call ale#linter#Define('rust', { | 237 | let 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 | ||
253 | If 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. | 261 | If 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 | |||
265 | Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>. | ||
266 | |||
267 | Gnome 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 | |||
269 | 1. Rename, symlink or copy the `rust-analyzer` binary to `rls` and place it somewhere Builder can find (in `PATH`, or under `~/.cargo/bin`). | ||
270 | 2. Enable the Rust Builder plugin. | ||
271 | |||
272 | == Features | ||
273 | |||
274 | include::./generated_features.adoc[] | ||
275 | |||
276 | == Assists (Code Actions) | ||
277 | |||
278 | Assists, or code actions, are small local refactorings, available in a particular context. | ||
279 | They are usually triggered by a shortcut or by clicking a light bulb icon in the editor. | ||
280 | Cursor position or selection is signified by `┃` character. | ||
256 | 281 | ||
257 | See https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/features.md[features.md]. | 282 | include::./generated_assists.adoc[] |