aboutsummaryrefslogtreecommitdiff
path: root/docs/user/features.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/user/features.md')
-rw-r--r--docs/user/features.md359
1 files changed, 359 insertions, 0 deletions
diff --git a/docs/user/features.md b/docs/user/features.md
new file mode 100644
index 000000000..b9d2aa84f
--- /dev/null
+++ b/docs/user/features.md
@@ -0,0 +1,359 @@
1This documents is an index of features that rust-analyzer language server
2provides. Shortcuts are for the default VS Code layout. If there's no shortcut,
3you can use <kbd>Ctrl+Shift+P</kbd> to search for the corresponding action.
4
5### Workspace Symbol <kbd>ctrl+t</kbd>
6
7Uses fuzzy-search to find types, modules and function by name across your
8project and dependencies. This **the** most useful feature, which improves code
9navigation tremendously. It mostly works on top of the built-in LSP
10functionality, however `#` and `*` symbols can be used to narrow down the
11search. Specifically,
12
13- `Foo` searches for `Foo` type in the current workspace
14- `foo#` searches for `foo` function in the current workspace
15- `Foo*` searches for `Foo` type among dependencies, excluding `stdlib`
16- `foo#*` searches for `foo` function among dependencies.
17
18That is, `#` switches from "types" to all symbols, `*` switches from the current
19workspace to dependencies.
20
21### Document Symbol <kbd>ctrl+shift+o</kbd>
22
23Provides a tree of the symbols defined in the file. Can be used to
24
25* fuzzy search symbol in a file (super useful)
26* draw breadcrumbs to describe the context around the cursor
27* draw outline of the file
28
29### On Typing Assists
30
31Some features trigger on typing certain characters:
32
33- typing `let =` tries to smartly add `;` if `=` is followed by an existing expression.
34- Enter inside comments automatically inserts `///`
35- typing `.` in a chain method call auto-indents
36
37### Commands <kbd>ctrl+shift+p</kbd>
38
39#### Extend Selection
40
41Extends the current selection to the encompassing syntactic construct
42(expression, statement, item, module, etc). It works with multiple cursors. Do
43bind this command to a key, it's super-useful! Expected to be upstreamed to LSP
44soonish: https://github.com/Microsoft/language-server-protocol/issues/613
45
46#### Run
47
48Shows popup suggesting to run a test/benchmark/binary **at the current cursor
49location**. Super useful for repeatedly running just a single test. Do bind this
50to a shortcut!
51
52#### Parent Module
53
54Navigates to the parent module of the current module.
55
56#### Matching Brace
57
58If the cursor is on any brace (`<>(){}[]`) which is a part of a brace-pair,
59moves cursor to the matching brace. It uses the actual parser to determine
60braces, so it won't confuse generics with comparisons.
61
62#### Join Lines
63
64Join selected lines into one, smartly fixing up whitespace and trailing commas.
65
66#### Show Syntax Tree
67
68Shows the parse tree of the current file. It exists mostly for debugging
69rust-analyzer itself.
70
71#### Status
72
73Shows internal statistic about memory usage of rust-analyzer
74
75#### Run garbage collection
76
77Manually triggers GC
78
79### Code Actions (Assists)
80
81These are triggered in a particular context via light bulb. We use custom code on
82the VS Code side to be able to position cursor. `<|>` signifies cursor
83
84- Add `#[derive]`
85
86```rust
87// before:
88struct Foo {
89 <|>x: i32
90}
91// after:
92#[derive(<|>)]
93struct Foo {
94 x: i32
95}
96```
97
98- Add `impl`
99
100```rust
101// before:
102struct Foo<'a, T: Debug> {
103 <|>t: T
104}
105// after:
106struct Foo<'a, T: Debug> {
107 t: T
108}
109
110impl<'a, T: Debug> Foo<'a, T> {
111 <|>
112}
113```
114
115- Add missing `impl` members
116
117```rust
118// before:
119trait Foo {
120 fn foo(&self);
121 fn bar(&self);
122 fn baz(&self);
123}
124
125struct S;
126
127impl Foo for S {
128 fn bar(&self) {}
129 <|>
130}
131
132// after:
133trait Foo {
134 fn foo(&self);
135 fn bar(&self);
136 fn baz(&self);
137}
138
139struct S;
140
141impl Foo for S {
142 fn bar(&self) {}
143 fn foo(&self) { unimplemented!() }
144 fn baz(&self) { unimplemented!() }<|>
145}
146```
147
148- Import path
149
150```rust
151// before:
152impl std::fmt::Debug<|> for Foo {
153}
154
155// after:
156use std::fmt::Debug;
157
158impl Debug<|> for Foo {
159}
160```
161
162- Change Visibility
163
164```rust
165// before:
166<|>fn foo() {}
167
168// after:
169<|>pub(crate) fn foo() {}
170
171// after:
172<|>pub fn foo() {}
173```
174
175- Fill match arms
176
177```rust
178// before:
179enum A {
180 As,
181 Bs,
182 Cs(String),
183 Ds(String, String),
184 Es{x: usize, y: usize}
185}
186
187fn main() {
188 let a = A::As;
189 match a<|> {}
190}
191
192// after:
193enum A {
194 As,
195 Bs,
196 Cs(String),
197 Ds(String, String),
198 Es{x: usize, y: usize}
199}
200
201fn main() {
202 let a = A::As;
203 match <|>a {
204 A::As => (),
205 A::Bs => (),
206 A::Cs(_) => (),
207 A::Ds(_, _) => (),
208 A::Es{x, y} => (),
209 }
210}
211```
212
213-- Fill struct fields
214
215```rust
216// before:
217struct S<'a, D> {
218 a: u32,
219 b: String,
220 c: (i32, i32),
221 d: D,
222 r: &'a str,
223}
224
225fn main() {
226 let s = S<|> {}
227}
228
229// after:
230struct S<'a, D> {
231 a: u32,
232 b: String,
233 c: (i32, i32),
234 d: D,
235 r: &'a str,
236}
237
238fn main() {
239 let s = <|>S {
240 a: (),
241 b: (),
242 c: (),
243 d: (),
244 r: (),
245 }
246}
247```
248
249- Flip `,`
250
251```rust
252// before:
253fn foo(x: usize,<|> dim: (usize, usize)) {}
254// after:
255fn foo(dim: (usize, usize), x: usize) {}
256```
257
258- Introduce variable:
259
260```rust
261// before:
262fn foo() {
263 foo(<|>1 + 1<|>);
264}
265
266// after:
267fn foo() {
268 let var_name = 1 + 1;
269 foo(var_name);
270}
271```
272
273-- Remove `dbg!`
274
275```rust
276// before:
277fn foo(n: usize) {
278 if let Some(_) = dbg!(n.<|>checked_sub(4)) {
279 // ...
280 }
281}
282
283// after:
284fn foo(n: usize) {
285 if let Some(_) = n.<|>checked_sub(4) {
286 // ...
287 }
288}
289```
290
291- Replace if-let with match:
292
293```rust
294// before:
295impl VariantData {
296 pub fn is_struct(&self) -> bool {
297 if <|>let VariantData::Struct(..) = *self {
298 true
299 } else {
300 false
301 }
302 }
303}
304
305// after:
306impl VariantData {
307 pub fn is_struct(&self) -> bool {
308 <|>match *self {
309 VariantData::Struct(..) => true,
310 _ => false,
311 }
312 }
313}
314```
315
316- Split import
317
318```rust
319// before:
320use algo:<|>:visitor::{Visitor, visit};
321//after:
322use algo::{<|>visitor::{Visitor, visit}};
323```
324
325### Magic Completions
326
327In addition to usual reference completion, rust-analyzer provides some ✨magic✨
328completions as well:
329
330Keywords like `if`, `else` `while`, `loop` are completed with braces, and cursor
331is placed at the appropriate position. Even though `if` is easy to type, you
332still want to complete it, to get ` { }` for free! `return` is inserted with a
333space or `;` depending on the return type of the function.
334
335When completing a function call, `()` are automatically inserted. If function
336takes arguments, cursor is positioned inside the parenthesis.
337
338There are postifx completions, which can be triggerd by typing something like
339`foo().if`. The word after `.` determines postifx completion, possible variants are:
340
341- `expr.if` -> `if expr {}`
342- `expr.match` -> `match expr {}`
343- `expr.while` -> `while expr {}`
344- `expr.ref` -> `&expr`
345- `expr.refm` -> `&mut expr`
346- `expr.not` -> `!expr`
347- `expr.dbg` -> `dbg!(expr)`
348
349There also snippet completions:
350
351#### Inside Expressions
352
353- `pd` -> `println!("{:?}")`
354- `ppd` -> `println!("{:#?}")`
355
356#### Inside Modules
357
358- `tfn` -> `#[test] fn f(){}`
359