diff options
-rw-r--r-- | docs/user/generated_assists.adoc (renamed from docs/user/assists.md) | 424 | ||||
-rw-r--r-- | docs/user/manual.adoc | 3 | ||||
-rw-r--r-- | xtask/src/codegen.rs | 33 | ||||
-rw-r--r-- | xtask/src/codegen/gen_assists_docs.rs | 71 | ||||
-rw-r--r-- | xtask/src/codegen/gen_feature_docs.rs | 22 | ||||
-rw-r--r-- | xtask/src/lib.rs | 2 |
6 files changed, 366 insertions, 189 deletions
diff --git a/docs/user/assists.md b/docs/user/generated_assists.adoc index 04387e3b0..b8cdfb1cd 100644 --- a/docs/user/assists.md +++ b/docs/user/generated_assists.adoc | |||
@@ -1,18 +1,16 @@ | |||
1 | # Assists | 1 | [discrete] |
2 | 2 | === `add_custom_impl` | |
3 | Cursor position or selection is signified by `┃` character. | ||
4 | |||
5 | |||
6 | ## `add_custom_impl` | ||
7 | 3 | ||
8 | Adds impl block for derived trait. | 4 | Adds impl block for derived trait. |
9 | 5 | ||
6 | .Before | ||
10 | ```rust | 7 | ```rust |
11 | // BEFORE | ||
12 | #[derive(Deb┃ug, Display)] | 8 | #[derive(Deb┃ug, Display)] |
13 | struct S; | 9 | struct S; |
10 | ``` | ||
14 | 11 | ||
15 | // AFTER | 12 | .After |
13 | ```rust | ||
16 | #[derive(Display)] | 14 | #[derive(Display)] |
17 | struct S; | 15 | struct S; |
18 | 16 | ||
@@ -21,18 +19,22 @@ impl Debug for S { | |||
21 | } | 19 | } |
22 | ``` | 20 | ``` |
23 | 21 | ||
24 | ## `add_derive` | 22 | |
23 | [discrete] | ||
24 | === `add_derive` | ||
25 | 25 | ||
26 | Adds a new `#[derive()]` clause to a struct or enum. | 26 | Adds a new `#[derive()]` clause to a struct or enum. |
27 | 27 | ||
28 | .Before | ||
28 | ```rust | 29 | ```rust |
29 | // BEFORE | ||
30 | struct Point { | 30 | struct Point { |
31 | x: u32, | 31 | x: u32, |
32 | y: u32,┃ | 32 | y: u32,┃ |
33 | } | 33 | } |
34 | ``` | ||
34 | 35 | ||
35 | // AFTER | 36 | .After |
37 | ```rust | ||
36 | #[derive($0)] | 38 | #[derive($0)] |
37 | struct Point { | 39 | struct Point { |
38 | x: u32, | 40 | x: u32, |
@@ -40,31 +42,39 @@ struct Point { | |||
40 | } | 42 | } |
41 | ``` | 43 | ``` |
42 | 44 | ||
43 | ## `add_explicit_type` | 45 | |
46 | [discrete] | ||
47 | === `add_explicit_type` | ||
44 | 48 | ||
45 | Specify type for a let binding. | 49 | Specify type for a let binding. |
46 | 50 | ||
51 | .Before | ||
47 | ```rust | 52 | ```rust |
48 | // BEFORE | ||
49 | fn main() { | 53 | fn main() { |
50 | let x┃ = 92; | 54 | let x┃ = 92; |
51 | } | 55 | } |
56 | ``` | ||
52 | 57 | ||
53 | // AFTER | 58 | .After |
59 | ```rust | ||
54 | fn main() { | 60 | fn main() { |
55 | let x: i32 = 92; | 61 | let x: i32 = 92; |
56 | } | 62 | } |
57 | ``` | 63 | ``` |
58 | 64 | ||
59 | ## `add_from_impl_for_enum` | 65 | |
66 | [discrete] | ||
67 | === `add_from_impl_for_enum` | ||
60 | 68 | ||
61 | Adds a From impl for an enum variant with one tuple field. | 69 | Adds a From impl for an enum variant with one tuple field. |
62 | 70 | ||
71 | .Before | ||
63 | ```rust | 72 | ```rust |
64 | // BEFORE | ||
65 | enum A { ┃One(u32) } | 73 | enum A { ┃One(u32) } |
74 | ``` | ||
66 | 75 | ||
67 | // AFTER | 76 | .After |
77 | ```rust | ||
68 | enum A { One(u32) } | 78 | enum A { One(u32) } |
69 | 79 | ||
70 | impl From<u32> for A { | 80 | impl From<u32> for A { |
@@ -74,20 +84,24 @@ impl From<u32> for A { | |||
74 | } | 84 | } |
75 | ``` | 85 | ``` |
76 | 86 | ||
77 | ## `add_function` | 87 | |
88 | [discrete] | ||
89 | === `add_function` | ||
78 | 90 | ||
79 | Adds a stub function with a signature matching the function under the cursor. | 91 | Adds a stub function with a signature matching the function under the cursor. |
80 | 92 | ||
93 | .Before | ||
81 | ```rust | 94 | ```rust |
82 | // BEFORE | ||
83 | struct Baz; | 95 | struct Baz; |
84 | fn baz() -> Baz { Baz } | 96 | fn baz() -> Baz { Baz } |
85 | fn foo() { | 97 | fn foo() { |
86 | bar┃("", baz()); | 98 | bar┃("", baz()); |
87 | } | 99 | } |
88 | 100 | ||
101 | ``` | ||
89 | 102 | ||
90 | // AFTER | 103 | .After |
104 | ```rust | ||
91 | struct Baz; | 105 | struct Baz; |
92 | fn baz() -> Baz { Baz } | 106 | fn baz() -> Baz { Baz } |
93 | fn foo() { | 107 | fn foo() { |
@@ -100,33 +114,41 @@ fn bar(arg: &str, baz: Baz) { | |||
100 | 114 | ||
101 | ``` | 115 | ``` |
102 | 116 | ||
103 | ## `add_hash` | 117 | |
118 | [discrete] | ||
119 | === `add_hash` | ||
104 | 120 | ||
105 | Adds a hash to a raw string literal. | 121 | Adds a hash to a raw string literal. |
106 | 122 | ||
123 | .Before | ||
107 | ```rust | 124 | ```rust |
108 | // BEFORE | ||
109 | fn main() { | 125 | fn main() { |
110 | r#"Hello,┃ World!"#; | 126 | r#"Hello,┃ World!"#; |
111 | } | 127 | } |
128 | ``` | ||
112 | 129 | ||
113 | // AFTER | 130 | .After |
131 | ```rust | ||
114 | fn main() { | 132 | fn main() { |
115 | r##"Hello, World!"##; | 133 | r##"Hello, World!"##; |
116 | } | 134 | } |
117 | ``` | 135 | ``` |
118 | 136 | ||
119 | ## `add_impl` | 137 | |
138 | [discrete] | ||
139 | === `add_impl` | ||
120 | 140 | ||
121 | Adds a new inherent impl for a type. | 141 | Adds a new inherent impl for a type. |
122 | 142 | ||
143 | .Before | ||
123 | ```rust | 144 | ```rust |
124 | // BEFORE | ||
125 | struct Ctx<T: Clone> { | 145 | struct Ctx<T: Clone> { |
126 | data: T,┃ | 146 | data: T,┃ |
127 | } | 147 | } |
148 | ``` | ||
128 | 149 | ||
129 | // AFTER | 150 | .After |
151 | ```rust | ||
130 | struct Ctx<T: Clone> { | 152 | struct Ctx<T: Clone> { |
131 | data: T, | 153 | data: T, |
132 | } | 154 | } |
@@ -136,12 +158,14 @@ impl<T: Clone> Ctx<T> { | |||
136 | } | 158 | } |
137 | ``` | 159 | ``` |
138 | 160 | ||
139 | ## `add_impl_default_members` | 161 | |
162 | [discrete] | ||
163 | === `add_impl_default_members` | ||
140 | 164 | ||
141 | Adds scaffold for overriding default impl members. | 165 | Adds scaffold for overriding default impl members. |
142 | 166 | ||
167 | .Before | ||
143 | ```rust | 168 | ```rust |
144 | // BEFORE | ||
145 | trait Trait { | 169 | trait Trait { |
146 | Type X; | 170 | Type X; |
147 | fn foo(&self); | 171 | fn foo(&self); |
@@ -153,8 +177,10 @@ impl Trait for () { | |||
153 | fn foo(&self) {}┃ | 177 | fn foo(&self) {}┃ |
154 | 178 | ||
155 | } | 179 | } |
180 | ``` | ||
156 | 181 | ||
157 | // AFTER | 182 | .After |
183 | ```rust | ||
158 | trait Trait { | 184 | trait Trait { |
159 | Type X; | 185 | Type X; |
160 | fn foo(&self); | 186 | fn foo(&self); |
@@ -169,12 +195,14 @@ impl Trait for () { | |||
169 | } | 195 | } |
170 | ``` | 196 | ``` |
171 | 197 | ||
172 | ## `add_impl_missing_members` | 198 | |
199 | [discrete] | ||
200 | === `add_impl_missing_members` | ||
173 | 201 | ||
174 | Adds scaffold for required impl members. | 202 | Adds scaffold for required impl members. |
175 | 203 | ||
204 | .Before | ||
176 | ```rust | 205 | ```rust |
177 | // BEFORE | ||
178 | trait Trait<T> { | 206 | trait Trait<T> { |
179 | Type X; | 207 | Type X; |
180 | fn foo(&self) -> T; | 208 | fn foo(&self) -> T; |
@@ -184,8 +212,10 @@ trait Trait<T> { | |||
184 | impl Trait<u32> for () {┃ | 212 | impl Trait<u32> for () {┃ |
185 | 213 | ||
186 | } | 214 | } |
215 | ``` | ||
187 | 216 | ||
188 | // AFTER | 217 | .After |
218 | ```rust | ||
189 | trait Trait<T> { | 219 | trait Trait<T> { |
190 | Type X; | 220 | Type X; |
191 | fn foo(&self) -> T; | 221 | fn foo(&self) -> T; |
@@ -200,17 +230,21 @@ impl Trait<u32> for () { | |||
200 | } | 230 | } |
201 | ``` | 231 | ``` |
202 | 232 | ||
203 | ## `add_new` | 233 | |
234 | [discrete] | ||
235 | === `add_new` | ||
204 | 236 | ||
205 | Adds a new inherent impl for a type. | 237 | Adds a new inherent impl for a type. |
206 | 238 | ||
239 | .Before | ||
207 | ```rust | 240 | ```rust |
208 | // BEFORE | ||
209 | struct Ctx<T: Clone> { | 241 | struct Ctx<T: Clone> { |
210 | data: T,┃ | 242 | data: T,┃ |
211 | } | 243 | } |
244 | ``` | ||
212 | 245 | ||
213 | // AFTER | 246 | .After |
247 | ```rust | ||
214 | struct Ctx<T: Clone> { | 248 | struct Ctx<T: Clone> { |
215 | data: T, | 249 | data: T, |
216 | } | 250 | } |
@@ -221,25 +255,31 @@ impl<T: Clone> Ctx<T> { | |||
221 | 255 | ||
222 | ``` | 256 | ``` |
223 | 257 | ||
224 | ## `add_turbo_fish` | 258 | |
259 | [discrete] | ||
260 | === `add_turbo_fish` | ||
225 | 261 | ||
226 | Adds `::<_>` to a call of a generic method or function. | 262 | Adds `::<_>` to a call of a generic method or function. |
227 | 263 | ||
264 | .Before | ||
228 | ```rust | 265 | ```rust |
229 | // BEFORE | ||
230 | fn make<T>() -> T { todo!() } | 266 | fn make<T>() -> T { todo!() } |
231 | fn main() { | 267 | fn main() { |
232 | let x = make┃(); | 268 | let x = make┃(); |
233 | } | 269 | } |
270 | ``` | ||
234 | 271 | ||
235 | // AFTER | 272 | .After |
273 | ```rust | ||
236 | fn make<T>() -> T { todo!() } | 274 | fn make<T>() -> T { todo!() } |
237 | fn main() { | 275 | fn main() { |
238 | let x = make::<${0:_}>(); | 276 | let x = make::<${0:_}>(); |
239 | } | 277 | } |
240 | ``` | 278 | ``` |
241 | 279 | ||
242 | ## `apply_demorgan` | 280 | |
281 | [discrete] | ||
282 | === `apply_demorgan` | ||
243 | 283 | ||
244 | Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws). | 284 | Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws). |
245 | This transforms expressions of the form `!l || !r` into `!(l && r)`. | 285 | This transforms expressions of the form `!l || !r` into `!(l && r)`. |
@@ -247,29 +287,35 @@ This also works with `&&`. This assist can only be applied with the cursor | |||
247 | on either `||` or `&&`, with both operands being a negation of some kind. | 287 | on either `||` or `&&`, with both operands being a negation of some kind. |
248 | This means something of the form `!x` or `x != y`. | 288 | This means something of the form `!x` or `x != y`. |
249 | 289 | ||
290 | .Before | ||
250 | ```rust | 291 | ```rust |
251 | // BEFORE | ||
252 | fn main() { | 292 | fn main() { |
253 | if x != 4 ||┃ !y {} | 293 | if x != 4 ||┃ !y {} |
254 | } | 294 | } |
295 | ``` | ||
255 | 296 | ||
256 | // AFTER | 297 | .After |
298 | ```rust | ||
257 | fn main() { | 299 | fn main() { |
258 | if !(x == 4 && y) {} | 300 | if !(x == 4 && y) {} |
259 | } | 301 | } |
260 | ``` | 302 | ``` |
261 | 303 | ||
262 | ## `auto_import` | 304 | |
305 | [discrete] | ||
306 | === `auto_import` | ||
263 | 307 | ||
264 | If the name is unresolved, provides all possible imports for it. | 308 | If the name is unresolved, provides all possible imports for it. |
265 | 309 | ||
310 | .Before | ||
266 | ```rust | 311 | ```rust |
267 | // BEFORE | ||
268 | fn main() { | 312 | fn main() { |
269 | let map = HashMap┃::new(); | 313 | let map = HashMap┃::new(); |
270 | } | 314 | } |
315 | ``` | ||
271 | 316 | ||
272 | // AFTER | 317 | .After |
318 | ```rust | ||
273 | use std::collections::HashMap; | 319 | use std::collections::HashMap; |
274 | 320 | ||
275 | fn main() { | 321 | fn main() { |
@@ -277,12 +323,14 @@ fn main() { | |||
277 | } | 323 | } |
278 | ``` | 324 | ``` |
279 | 325 | ||
280 | ## `change_lifetime_anon_to_named` | 326 | |
327 | [discrete] | ||
328 | === `change_lifetime_anon_to_named` | ||
281 | 329 | ||
282 | Change an anonymous lifetime to a named lifetime. | 330 | Change an anonymous lifetime to a named lifetime. |
283 | 331 | ||
332 | .Before | ||
284 | ```rust | 333 | ```rust |
285 | // BEFORE | ||
286 | impl Cursor<'_┃> { | 334 | impl Cursor<'_┃> { |
287 | fn node(self) -> &SyntaxNode { | 335 | fn node(self) -> &SyntaxNode { |
288 | match self { | 336 | match self { |
@@ -290,8 +338,10 @@ impl Cursor<'_┃> { | |||
290 | } | 338 | } |
291 | } | 339 | } |
292 | } | 340 | } |
341 | ``` | ||
293 | 342 | ||
294 | // AFTER | 343 | .After |
344 | ```rust | ||
295 | impl<'a> Cursor<'a> { | 345 | impl<'a> Cursor<'a> { |
296 | fn node(self) -> &SyntaxNode { | 346 | fn node(self) -> &SyntaxNode { |
297 | match self { | 347 | match self { |
@@ -301,44 +351,56 @@ impl<'a> Cursor<'a> { | |||
301 | } | 351 | } |
302 | ``` | 352 | ``` |
303 | 353 | ||
304 | ## `change_return_type_to_result` | 354 | |
355 | [discrete] | ||
356 | === `change_return_type_to_result` | ||
305 | 357 | ||
306 | Change the function's return type to Result. | 358 | Change the function's return type to Result. |
307 | 359 | ||
360 | .Before | ||
308 | ```rust | 361 | ```rust |
309 | // BEFORE | ||
310 | fn foo() -> i32┃ { 42i32 } | 362 | fn foo() -> i32┃ { 42i32 } |
363 | ``` | ||
311 | 364 | ||
312 | // AFTER | 365 | .After |
366 | ```rust | ||
313 | fn foo() -> Result<i32, ${0:_}> { Ok(42i32) } | 367 | fn foo() -> Result<i32, ${0:_}> { Ok(42i32) } |
314 | ``` | 368 | ``` |
315 | 369 | ||
316 | ## `change_visibility` | 370 | |
371 | [discrete] | ||
372 | === `change_visibility` | ||
317 | 373 | ||
318 | Adds or changes existing visibility specifier. | 374 | Adds or changes existing visibility specifier. |
319 | 375 | ||
376 | .Before | ||
320 | ```rust | 377 | ```rust |
321 | // BEFORE | ||
322 | ┃fn frobnicate() {} | 378 | ┃fn frobnicate() {} |
379 | ``` | ||
323 | 380 | ||
324 | // AFTER | 381 | .After |
382 | ```rust | ||
325 | pub(crate) fn frobnicate() {} | 383 | pub(crate) fn frobnicate() {} |
326 | ``` | 384 | ``` |
327 | 385 | ||
328 | ## `convert_to_guarded_return` | 386 | |
387 | [discrete] | ||
388 | === `convert_to_guarded_return` | ||
329 | 389 | ||
330 | Replace a large conditional with a guarded return. | 390 | Replace a large conditional with a guarded return. |
331 | 391 | ||
392 | .Before | ||
332 | ```rust | 393 | ```rust |
333 | // BEFORE | ||
334 | fn main() { | 394 | fn main() { |
335 | ┃if cond { | 395 | ┃if cond { |
336 | foo(); | 396 | foo(); |
337 | bar(); | 397 | bar(); |
338 | } | 398 | } |
339 | } | 399 | } |
400 | ``` | ||
340 | 401 | ||
341 | // AFTER | 402 | .After |
403 | ```rust | ||
342 | fn main() { | 404 | fn main() { |
343 | if !cond { | 405 | if !cond { |
344 | return; | 406 | return; |
@@ -348,12 +410,14 @@ fn main() { | |||
348 | } | 410 | } |
349 | ``` | 411 | ``` |
350 | 412 | ||
351 | ## `fill_match_arms` | 413 | |
414 | [discrete] | ||
415 | === `fill_match_arms` | ||
352 | 416 | ||
353 | Adds missing clauses to a `match` expression. | 417 | Adds missing clauses to a `match` expression. |
354 | 418 | ||
419 | .Before | ||
355 | ```rust | 420 | ```rust |
356 | // BEFORE | ||
357 | enum Action { Move { distance: u32 }, Stop } | 421 | enum Action { Move { distance: u32 }, Stop } |
358 | 422 | ||
359 | fn handle(action: Action) { | 423 | fn handle(action: Action) { |
@@ -361,8 +425,10 @@ fn handle(action: Action) { | |||
361 | ┃ | 425 | ┃ |
362 | } | 426 | } |
363 | } | 427 | } |
428 | ``` | ||
364 | 429 | ||
365 | // AFTER | 430 | .After |
431 | ```rust | ||
366 | enum Action { Move { distance: u32 }, Stop } | 432 | enum Action { Move { distance: u32 }, Stop } |
367 | 433 | ||
368 | fn handle(action: Action) { | 434 | fn handle(action: Action) { |
@@ -373,20 +439,24 @@ fn handle(action: Action) { | |||
373 | } | 439 | } |
374 | ``` | 440 | ``` |
375 | 441 | ||
376 | ## `fix_visibility` | 442 | |
443 | [discrete] | ||
444 | === `fix_visibility` | ||
377 | 445 | ||
378 | Makes inaccessible item public. | 446 | Makes inaccessible item public. |
379 | 447 | ||
448 | .Before | ||
380 | ```rust | 449 | ```rust |
381 | // BEFORE | ||
382 | mod m { | 450 | mod m { |
383 | fn frobnicate() {} | 451 | fn frobnicate() {} |
384 | } | 452 | } |
385 | fn main() { | 453 | fn main() { |
386 | m::frobnicate┃() {} | 454 | m::frobnicate┃() {} |
387 | } | 455 | } |
456 | ``` | ||
388 | 457 | ||
389 | // AFTER | 458 | .After |
459 | ```rust | ||
390 | mod m { | 460 | mod m { |
391 | $0pub(crate) fn frobnicate() {} | 461 | $0pub(crate) fn frobnicate() {} |
392 | } | 462 | } |
@@ -395,154 +465,192 @@ fn main() { | |||
395 | } | 465 | } |
396 | ``` | 466 | ``` |
397 | 467 | ||
398 | ## `flip_binexpr` | 468 | |
469 | [discrete] | ||
470 | === `flip_binexpr` | ||
399 | 471 | ||
400 | Flips operands of a binary expression. | 472 | Flips operands of a binary expression. |
401 | 473 | ||
474 | .Before | ||
402 | ```rust | 475 | ```rust |
403 | // BEFORE | ||
404 | fn main() { | 476 | fn main() { |
405 | let _ = 90 +┃ 2; | 477 | let _ = 90 +┃ 2; |
406 | } | 478 | } |
479 | ``` | ||
407 | 480 | ||
408 | // AFTER | 481 | .After |
482 | ```rust | ||
409 | fn main() { | 483 | fn main() { |
410 | let _ = 2 + 90; | 484 | let _ = 2 + 90; |
411 | } | 485 | } |
412 | ``` | 486 | ``` |
413 | 487 | ||
414 | ## `flip_comma` | 488 | |
489 | [discrete] | ||
490 | === `flip_comma` | ||
415 | 491 | ||
416 | Flips two comma-separated items. | 492 | Flips two comma-separated items. |
417 | 493 | ||
494 | .Before | ||
418 | ```rust | 495 | ```rust |
419 | // BEFORE | ||
420 | fn main() { | 496 | fn main() { |
421 | ((1, 2),┃ (3, 4)); | 497 | ((1, 2),┃ (3, 4)); |
422 | } | 498 | } |
499 | ``` | ||
423 | 500 | ||
424 | // AFTER | 501 | .After |
502 | ```rust | ||
425 | fn main() { | 503 | fn main() { |
426 | ((3, 4), (1, 2)); | 504 | ((3, 4), (1, 2)); |
427 | } | 505 | } |
428 | ``` | 506 | ``` |
429 | 507 | ||
430 | ## `flip_trait_bound` | 508 | |
509 | [discrete] | ||
510 | === `flip_trait_bound` | ||
431 | 511 | ||
432 | Flips two trait bounds. | 512 | Flips two trait bounds. |
433 | 513 | ||
514 | .Before | ||
434 | ```rust | 515 | ```rust |
435 | // BEFORE | ||
436 | fn foo<T: Clone +┃ Copy>() { } | 516 | fn foo<T: Clone +┃ Copy>() { } |
517 | ``` | ||
437 | 518 | ||
438 | // AFTER | 519 | .After |
520 | ```rust | ||
439 | fn foo<T: Copy + Clone>() { } | 521 | fn foo<T: Copy + Clone>() { } |
440 | ``` | 522 | ``` |
441 | 523 | ||
442 | ## `inline_local_variable` | 524 | |
525 | [discrete] | ||
526 | === `inline_local_variable` | ||
443 | 527 | ||
444 | Inlines local variable. | 528 | Inlines local variable. |
445 | 529 | ||
530 | .Before | ||
446 | ```rust | 531 | ```rust |
447 | // BEFORE | ||
448 | fn main() { | 532 | fn main() { |
449 | let x┃ = 1 + 2; | 533 | let x┃ = 1 + 2; |
450 | x * 4; | 534 | x * 4; |
451 | } | 535 | } |
536 | ``` | ||
452 | 537 | ||
453 | // AFTER | 538 | .After |
539 | ```rust | ||
454 | fn main() { | 540 | fn main() { |
455 | (1 + 2) * 4; | 541 | (1 + 2) * 4; |
456 | } | 542 | } |
457 | ``` | 543 | ``` |
458 | 544 | ||
459 | ## `introduce_variable` | 545 | |
546 | [discrete] | ||
547 | === `introduce_variable` | ||
460 | 548 | ||
461 | Extracts subexpression into a variable. | 549 | Extracts subexpression into a variable. |
462 | 550 | ||
551 | .Before | ||
463 | ```rust | 552 | ```rust |
464 | // BEFORE | ||
465 | fn main() { | 553 | fn main() { |
466 | ┃(1 + 2)┃ * 4; | 554 | ┃(1 + 2)┃ * 4; |
467 | } | 555 | } |
556 | ``` | ||
468 | 557 | ||
469 | // AFTER | 558 | .After |
559 | ```rust | ||
470 | fn main() { | 560 | fn main() { |
471 | let $0var_name = (1 + 2); | 561 | let $0var_name = (1 + 2); |
472 | var_name * 4; | 562 | var_name * 4; |
473 | } | 563 | } |
474 | ``` | 564 | ``` |
475 | 565 | ||
476 | ## `invert_if` | 566 | |
567 | [discrete] | ||
568 | === `invert_if` | ||
477 | 569 | ||
478 | Apply invert_if | 570 | Apply invert_if |
479 | This transforms if expressions of the form `if !x {A} else {B}` into `if x {B} else {A}` | 571 | This transforms if expressions of the form `if !x {A} else {B}` into `if x {B} else {A}` |
480 | This also works with `!=`. This assist can only be applied with the cursor | 572 | This also works with `!=`. This assist can only be applied with the cursor |
481 | on `if`. | 573 | on `if`. |
482 | 574 | ||
575 | .Before | ||
483 | ```rust | 576 | ```rust |
484 | // BEFORE | ||
485 | fn main() { | 577 | fn main() { |
486 | if┃ !y { A } else { B } | 578 | if┃ !y { A } else { B } |
487 | } | 579 | } |
580 | ``` | ||
488 | 581 | ||
489 | // AFTER | 582 | .After |
583 | ```rust | ||
490 | fn main() { | 584 | fn main() { |
491 | if y { B } else { A } | 585 | if y { B } else { A } |
492 | } | 586 | } |
493 | ``` | 587 | ``` |
494 | 588 | ||
495 | ## `make_raw_string` | 589 | |
590 | [discrete] | ||
591 | === `make_raw_string` | ||
496 | 592 | ||
497 | Adds `r#` to a plain string literal. | 593 | Adds `r#` to a plain string literal. |
498 | 594 | ||
595 | .Before | ||
499 | ```rust | 596 | ```rust |
500 | // BEFORE | ||
501 | fn main() { | 597 | fn main() { |
502 | "Hello,┃ World!"; | 598 | "Hello,┃ World!"; |
503 | } | 599 | } |
600 | ``` | ||
504 | 601 | ||
505 | // AFTER | 602 | .After |
603 | ```rust | ||
506 | fn main() { | 604 | fn main() { |
507 | r#"Hello, World!"#; | 605 | r#"Hello, World!"#; |
508 | } | 606 | } |
509 | ``` | 607 | ``` |
510 | 608 | ||
511 | ## `make_usual_string` | 609 | |
610 | [discrete] | ||
611 | === `make_usual_string` | ||
512 | 612 | ||
513 | Turns a raw string into a plain string. | 613 | Turns a raw string into a plain string. |
514 | 614 | ||
615 | .Before | ||
515 | ```rust | 616 | ```rust |
516 | // BEFORE | ||
517 | fn main() { | 617 | fn main() { |
518 | r#"Hello,┃ "World!""#; | 618 | r#"Hello,┃ "World!""#; |
519 | } | 619 | } |
620 | ``` | ||
520 | 621 | ||
521 | // AFTER | 622 | .After |
623 | ```rust | ||
522 | fn main() { | 624 | fn main() { |
523 | "Hello, \"World!\""; | 625 | "Hello, \"World!\""; |
524 | } | 626 | } |
525 | ``` | 627 | ``` |
526 | 628 | ||
527 | ## `merge_imports` | 629 | |
630 | [discrete] | ||
631 | === `merge_imports` | ||
528 | 632 | ||
529 | Merges two imports with a common prefix. | 633 | Merges two imports with a common prefix. |
530 | 634 | ||
635 | .Before | ||
531 | ```rust | 636 | ```rust |
532 | // BEFORE | ||
533 | use std::┃fmt::Formatter; | 637 | use std::┃fmt::Formatter; |
534 | use std::io; | 638 | use std::io; |
639 | ``` | ||
535 | 640 | ||
536 | // AFTER | 641 | .After |
642 | ```rust | ||
537 | use std::{fmt::Formatter, io}; | 643 | use std::{fmt::Formatter, io}; |
538 | ``` | 644 | ``` |
539 | 645 | ||
540 | ## `merge_match_arms` | 646 | |
647 | [discrete] | ||
648 | === `merge_match_arms` | ||
541 | 649 | ||
542 | Merges identical match arms. | 650 | Merges identical match arms. |
543 | 651 | ||
652 | .Before | ||
544 | ```rust | 653 | ```rust |
545 | // BEFORE | ||
546 | enum Action { Move { distance: u32 }, Stop } | 654 | enum Action { Move { distance: u32 }, Stop } |
547 | 655 | ||
548 | fn handle(action: Action) { | 656 | fn handle(action: Action) { |
@@ -551,8 +659,10 @@ fn handle(action: Action) { | |||
551 | Action::Stop => foo(), | 659 | Action::Stop => foo(), |
552 | } | 660 | } |
553 | } | 661 | } |
662 | ``` | ||
554 | 663 | ||
555 | // AFTER | 664 | .After |
665 | ```rust | ||
556 | enum Action { Move { distance: u32 }, Stop } | 666 | enum Action { Move { distance: u32 }, Stop } |
557 | 667 | ||
558 | fn handle(action: Action) { | 668 | fn handle(action: Action) { |
@@ -562,12 +672,14 @@ fn handle(action: Action) { | |||
562 | } | 672 | } |
563 | ``` | 673 | ``` |
564 | 674 | ||
565 | ## `move_arm_cond_to_match_guard` | 675 | |
676 | [discrete] | ||
677 | === `move_arm_cond_to_match_guard` | ||
566 | 678 | ||
567 | Moves if expression from match arm body into a guard. | 679 | Moves if expression from match arm body into a guard. |
568 | 680 | ||
681 | .Before | ||
569 | ```rust | 682 | ```rust |
570 | // BEFORE | ||
571 | enum Action { Move { distance: u32 }, Stop } | 683 | enum Action { Move { distance: u32 }, Stop } |
572 | 684 | ||
573 | fn handle(action: Action) { | 685 | fn handle(action: Action) { |
@@ -576,8 +688,10 @@ fn handle(action: Action) { | |||
576 | _ => (), | 688 | _ => (), |
577 | } | 689 | } |
578 | } | 690 | } |
691 | ``` | ||
579 | 692 | ||
580 | // AFTER | 693 | .After |
694 | ```rust | ||
581 | enum Action { Move { distance: u32 }, Stop } | 695 | enum Action { Move { distance: u32 }, Stop } |
582 | 696 | ||
583 | fn handle(action: Action) { | 697 | fn handle(action: Action) { |
@@ -588,28 +702,34 @@ fn handle(action: Action) { | |||
588 | } | 702 | } |
589 | ``` | 703 | ``` |
590 | 704 | ||
591 | ## `move_bounds_to_where_clause` | 705 | |
706 | [discrete] | ||
707 | === `move_bounds_to_where_clause` | ||
592 | 708 | ||
593 | Moves inline type bounds to a where clause. | 709 | Moves inline type bounds to a where clause. |
594 | 710 | ||
711 | .Before | ||
595 | ```rust | 712 | ```rust |
596 | // BEFORE | ||
597 | fn apply<T, U, ┃F: FnOnce(T) -> U>(f: F, x: T) -> U { | 713 | fn apply<T, U, ┃F: FnOnce(T) -> U>(f: F, x: T) -> U { |
598 | f(x) | 714 | f(x) |
599 | } | 715 | } |
716 | ``` | ||
600 | 717 | ||
601 | // AFTER | 718 | .After |
719 | ```rust | ||
602 | fn apply<T, U, F>(f: F, x: T) -> U where F: FnOnce(T) -> U { | 720 | fn apply<T, U, F>(f: F, x: T) -> U where F: FnOnce(T) -> U { |
603 | f(x) | 721 | f(x) |
604 | } | 722 | } |
605 | ``` | 723 | ``` |
606 | 724 | ||
607 | ## `move_guard_to_arm_body` | 725 | |
726 | [discrete] | ||
727 | === `move_guard_to_arm_body` | ||
608 | 728 | ||
609 | Moves match guard into match arm body. | 729 | Moves match guard into match arm body. |
610 | 730 | ||
731 | .Before | ||
611 | ```rust | 732 | ```rust |
612 | // BEFORE | ||
613 | enum Action { Move { distance: u32 }, Stop } | 733 | enum Action { Move { distance: u32 }, Stop } |
614 | 734 | ||
615 | fn handle(action: Action) { | 735 | fn handle(action: Action) { |
@@ -618,8 +738,10 @@ fn handle(action: Action) { | |||
618 | _ => (), | 738 | _ => (), |
619 | } | 739 | } |
620 | } | 740 | } |
741 | ``` | ||
621 | 742 | ||
622 | // AFTER | 743 | .After |
744 | ```rust | ||
623 | enum Action { Move { distance: u32 }, Stop } | 745 | enum Action { Move { distance: u32 }, Stop } |
624 | 746 | ||
625 | fn handle(action: Action) { | 747 | fn handle(action: Action) { |
@@ -630,75 +752,93 @@ fn handle(action: Action) { | |||
630 | } | 752 | } |
631 | ``` | 753 | ``` |
632 | 754 | ||
633 | ## `remove_dbg` | 755 | |
756 | [discrete] | ||
757 | === `remove_dbg` | ||
634 | 758 | ||
635 | Removes `dbg!()` macro call. | 759 | Removes `dbg!()` macro call. |
636 | 760 | ||
761 | .Before | ||
637 | ```rust | 762 | ```rust |
638 | // BEFORE | ||
639 | fn main() { | 763 | fn main() { |
640 | ┃dbg!(92); | 764 | ┃dbg!(92); |
641 | } | 765 | } |
766 | ``` | ||
642 | 767 | ||
643 | // AFTER | 768 | .After |
769 | ```rust | ||
644 | fn main() { | 770 | fn main() { |
645 | 92; | 771 | 92; |
646 | } | 772 | } |
647 | ``` | 773 | ``` |
648 | 774 | ||
649 | ## `remove_hash` | 775 | |
776 | [discrete] | ||
777 | === `remove_hash` | ||
650 | 778 | ||
651 | Removes a hash from a raw string literal. | 779 | Removes a hash from a raw string literal. |
652 | 780 | ||
781 | .Before | ||
653 | ```rust | 782 | ```rust |
654 | // BEFORE | ||
655 | fn main() { | 783 | fn main() { |
656 | r#"Hello,┃ World!"#; | 784 | r#"Hello,┃ World!"#; |
657 | } | 785 | } |
786 | ``` | ||
658 | 787 | ||
659 | // AFTER | 788 | .After |
789 | ```rust | ||
660 | fn main() { | 790 | fn main() { |
661 | r"Hello, World!"; | 791 | r"Hello, World!"; |
662 | } | 792 | } |
663 | ``` | 793 | ``` |
664 | 794 | ||
665 | ## `remove_mut` | 795 | |
796 | [discrete] | ||
797 | === `remove_mut` | ||
666 | 798 | ||
667 | Removes the `mut` keyword. | 799 | Removes the `mut` keyword. |
668 | 800 | ||
801 | .Before | ||
669 | ```rust | 802 | ```rust |
670 | // BEFORE | ||
671 | impl Walrus { | 803 | impl Walrus { |
672 | fn feed(&mut┃ self, amount: u32) {} | 804 | fn feed(&mut┃ self, amount: u32) {} |
673 | } | 805 | } |
806 | ``` | ||
674 | 807 | ||
675 | // AFTER | 808 | .After |
809 | ```rust | ||
676 | impl Walrus { | 810 | impl Walrus { |
677 | fn feed(&self, amount: u32) {} | 811 | fn feed(&self, amount: u32) {} |
678 | } | 812 | } |
679 | ``` | 813 | ``` |
680 | 814 | ||
681 | ## `reorder_fields` | 815 | |
816 | [discrete] | ||
817 | === `reorder_fields` | ||
682 | 818 | ||
683 | Reorder the fields of record literals and record patterns in the same order as in | 819 | Reorder the fields of record literals and record patterns in the same order as in |
684 | the definition. | 820 | the definition. |
685 | 821 | ||
822 | .Before | ||
686 | ```rust | 823 | ```rust |
687 | // BEFORE | ||
688 | struct Foo {foo: i32, bar: i32}; | 824 | struct Foo {foo: i32, bar: i32}; |
689 | const test: Foo = ┃Foo {bar: 0, foo: 1} | 825 | const test: Foo = ┃Foo {bar: 0, foo: 1} |
826 | ``` | ||
690 | 827 | ||
691 | // AFTER | 828 | .After |
829 | ```rust | ||
692 | struct Foo {foo: i32, bar: i32}; | 830 | struct Foo {foo: i32, bar: i32}; |
693 | const test: Foo = Foo {foo: 1, bar: 0} | 831 | const test: Foo = Foo {foo: 1, bar: 0} |
694 | ``` | 832 | ``` |
695 | 833 | ||
696 | ## `replace_if_let_with_match` | 834 | |
835 | [discrete] | ||
836 | === `replace_if_let_with_match` | ||
697 | 837 | ||
698 | Replaces `if let` with an else branch with a `match` expression. | 838 | Replaces `if let` with an else branch with a `match` expression. |
699 | 839 | ||
840 | .Before | ||
700 | ```rust | 841 | ```rust |
701 | // BEFORE | ||
702 | enum Action { Move { distance: u32 }, Stop } | 842 | enum Action { Move { distance: u32 }, Stop } |
703 | 843 | ||
704 | fn handle(action: Action) { | 844 | fn handle(action: Action) { |
@@ -708,8 +848,10 @@ fn handle(action: Action) { | |||
708 | bar() | 848 | bar() |
709 | } | 849 | } |
710 | } | 850 | } |
851 | ``` | ||
711 | 852 | ||
712 | // AFTER | 853 | .After |
854 | ```rust | ||
713 | enum Action { Move { distance: u32 }, Stop } | 855 | enum Action { Move { distance: u32 }, Stop } |
714 | 856 | ||
715 | fn handle(action: Action) { | 857 | fn handle(action: Action) { |
@@ -720,20 +862,24 @@ fn handle(action: Action) { | |||
720 | } | 862 | } |
721 | ``` | 863 | ``` |
722 | 864 | ||
723 | ## `replace_let_with_if_let` | 865 | |
866 | [discrete] | ||
867 | === `replace_let_with_if_let` | ||
724 | 868 | ||
725 | Replaces `let` with an `if-let`. | 869 | Replaces `let` with an `if-let`. |
726 | 870 | ||
871 | .Before | ||
727 | ```rust | 872 | ```rust |
728 | // BEFORE | ||
729 | 873 | ||
730 | fn main(action: Action) { | 874 | fn main(action: Action) { |
731 | ┃let x = compute(); | 875 | ┃let x = compute(); |
732 | } | 876 | } |
733 | 877 | ||
734 | fn compute() -> Option<i32> { None } | 878 | fn compute() -> Option<i32> { None } |
879 | ``` | ||
735 | 880 | ||
736 | // AFTER | 881 | .After |
882 | ```rust | ||
737 | 883 | ||
738 | fn main(action: Action) { | 884 | fn main(action: Action) { |
739 | if let Some(x) = compute() { | 885 | if let Some(x) = compute() { |
@@ -743,33 +889,41 @@ fn main(action: Action) { | |||
743 | fn compute() -> Option<i32> { None } | 889 | fn compute() -> Option<i32> { None } |
744 | ``` | 890 | ``` |
745 | 891 | ||
746 | ## `replace_qualified_name_with_use` | 892 | |
893 | [discrete] | ||
894 | === `replace_qualified_name_with_use` | ||
747 | 895 | ||
748 | Adds a use statement for a given fully-qualified name. | 896 | Adds a use statement for a given fully-qualified name. |
749 | 897 | ||
898 | .Before | ||
750 | ```rust | 899 | ```rust |
751 | // BEFORE | ||
752 | fn process(map: std::collections::┃HashMap<String, String>) {} | 900 | fn process(map: std::collections::┃HashMap<String, String>) {} |
901 | ``` | ||
753 | 902 | ||
754 | // AFTER | 903 | .After |
904 | ```rust | ||
755 | use std::collections::HashMap; | 905 | use std::collections::HashMap; |
756 | 906 | ||
757 | fn process(map: HashMap<String, String>) {} | 907 | fn process(map: HashMap<String, String>) {} |
758 | ``` | 908 | ``` |
759 | 909 | ||
760 | ## `replace_unwrap_with_match` | 910 | |
911 | [discrete] | ||
912 | === `replace_unwrap_with_match` | ||
761 | 913 | ||
762 | Replaces `unwrap` a `match` expression. Works for Result and Option. | 914 | Replaces `unwrap` a `match` expression. Works for Result and Option. |
763 | 915 | ||
916 | .Before | ||
764 | ```rust | 917 | ```rust |
765 | // BEFORE | ||
766 | enum Result<T, E> { Ok(T), Err(E) } | 918 | enum Result<T, E> { Ok(T), Err(E) } |
767 | fn main() { | 919 | fn main() { |
768 | let x: Result<i32, i32> = Result::Ok(92); | 920 | let x: Result<i32, i32> = Result::Ok(92); |
769 | let y = x.┃unwrap(); | 921 | let y = x.┃unwrap(); |
770 | } | 922 | } |
923 | ``` | ||
771 | 924 | ||
772 | // AFTER | 925 | .After |
926 | ```rust | ||
773 | enum Result<T, E> { Ok(T), Err(E) } | 927 | enum Result<T, E> { Ok(T), Err(E) } |
774 | fn main() { | 928 | fn main() { |
775 | let x: Result<i32, i32> = Result::Ok(92); | 929 | let x: Result<i32, i32> = Result::Ok(92); |
@@ -780,31 +934,39 @@ fn main() { | |||
780 | } | 934 | } |
781 | ``` | 935 | ``` |
782 | 936 | ||
783 | ## `split_import` | 937 | |
938 | [discrete] | ||
939 | === `split_import` | ||
784 | 940 | ||
785 | Wraps the tail of import into braces. | 941 | Wraps the tail of import into braces. |
786 | 942 | ||
943 | .Before | ||
787 | ```rust | 944 | ```rust |
788 | // BEFORE | ||
789 | use std::┃collections::HashMap; | 945 | use std::┃collections::HashMap; |
946 | ``` | ||
790 | 947 | ||
791 | // AFTER | 948 | .After |
949 | ```rust | ||
792 | use std::{collections::HashMap}; | 950 | use std::{collections::HashMap}; |
793 | ``` | 951 | ``` |
794 | 952 | ||
795 | ## `unwrap_block` | 953 | |
954 | [discrete] | ||
955 | === `unwrap_block` | ||
796 | 956 | ||
797 | This assist removes if...else, for, while and loop control statements to just keep the body. | 957 | This assist removes if...else, for, while and loop control statements to just keep the body. |
798 | 958 | ||
959 | .Before | ||
799 | ```rust | 960 | ```rust |
800 | // BEFORE | ||
801 | fn foo() { | 961 | fn foo() { |
802 | if true {┃ | 962 | if true {┃ |
803 | println!("foo"); | 963 | println!("foo"); |
804 | } | 964 | } |
805 | } | 965 | } |
966 | ``` | ||
806 | 967 | ||
807 | // AFTER | 968 | .After |
969 | ```rust | ||
808 | fn foo() { | 970 | fn foo() { |
809 | println!("foo"); | 971 | println!("foo"); |
810 | } | 972 | } |
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc index f40139804..27b379213 100644 --- a/docs/user/manual.adoc +++ b/docs/user/manual.adoc | |||
@@ -278,5 +278,6 @@ include::./generated_features.adoc[] | |||
278 | 278 | ||
279 | Assists, or code actions, are small local refactorings, available in a particular context. | 279 | Assists, or code actions, are small local refactorings, available in a particular context. |
280 | They are usually triggered by a shortcut or by clicking a light bulb icon in the editor. | 280 | They are usually triggered by a shortcut or by clicking a light bulb icon in the editor. |
281 | Cursor position or selection is signified by `┃` character. | ||
281 | 282 | ||
282 | See [assists.md](./assists.md) for the list of available assists. | 283 | include::./generated_assists.adoc[] |
diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs index f47d54125..f3917a244 100644 --- a/xtask/src/codegen.rs +++ b/xtask/src/codegen.rs | |||
@@ -10,9 +10,12 @@ mod gen_parser_tests; | |||
10 | mod gen_assists_docs; | 10 | mod gen_assists_docs; |
11 | mod gen_feature_docs; | 11 | mod gen_feature_docs; |
12 | 12 | ||
13 | use std::{mem, path::Path}; | 13 | use std::{ |
14 | fmt, mem, | ||
15 | path::{Path, PathBuf}, | ||
16 | }; | ||
14 | 17 | ||
15 | use crate::{not_bash::fs2, Result}; | 18 | use crate::{not_bash::fs2, project_root, Result}; |
16 | 19 | ||
17 | pub use self::{ | 20 | pub use self::{ |
18 | gen_assists_docs::generate_assists_docs, gen_feature_docs::generate_feature_docs, | 21 | gen_assists_docs::generate_assists_docs, gen_feature_docs::generate_feature_docs, |
@@ -29,7 +32,6 @@ const AST_TOKENS: &str = "crates/ra_syntax/src/ast/generated/tokens.rs"; | |||
29 | 32 | ||
30 | const ASSISTS_DIR: &str = "crates/ra_assists/src/handlers"; | 33 | const ASSISTS_DIR: &str = "crates/ra_assists/src/handlers"; |
31 | const ASSISTS_TESTS: &str = "crates/ra_assists/src/tests/generated.rs"; | 34 | const ASSISTS_TESTS: &str = "crates/ra_assists/src/tests/generated.rs"; |
32 | const ASSISTS_DOCS: &str = "docs/user/assists.md"; | ||
33 | 35 | ||
34 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] | 36 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] |
35 | pub enum Mode { | 37 | pub enum Mode { |
@@ -107,3 +109,28 @@ fn do_extract_comment_blocks(text: &str, allow_blocks_with_empty_lines: bool) -> | |||
107 | } | 109 | } |
108 | res | 110 | res |
109 | } | 111 | } |
112 | |||
113 | #[derive(Debug)] | ||
114 | struct Location { | ||
115 | file: PathBuf, | ||
116 | } | ||
117 | |||
118 | impl Location { | ||
119 | fn new(file: PathBuf) -> Self { | ||
120 | Self { file } | ||
121 | } | ||
122 | } | ||
123 | |||
124 | impl fmt::Display for Location { | ||
125 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
126 | let path = self.file.strip_prefix(&project_root()).unwrap().display().to_string(); | ||
127 | let path = path.replace('\\', "/"); | ||
128 | let name = self.file.file_name().unwrap(); | ||
129 | write!( | ||
130 | f, | ||
131 | "https://github.com/rust-analyzer/rust-analyzer/blob/master/{}[{}]", | ||
132 | path, | ||
133 | name.to_str().unwrap() | ||
134 | ) | ||
135 | } | ||
136 | } | ||
diff --git a/xtask/src/codegen/gen_assists_docs.rs b/xtask/src/codegen/gen_assists_docs.rs index 6ebeb8aea..15a02d317 100644 --- a/xtask/src/codegen/gen_assists_docs.rs +++ b/xtask/src/codegen/gen_assists_docs.rs | |||
@@ -1,22 +1,28 @@ | |||
1 | //! Generates `assists.md` documentation. | 1 | //! Generates `assists.md` documentation. |
2 | 2 | ||
3 | use std::{fs, path::Path}; | 3 | use std::{fmt, fs, path::Path}; |
4 | 4 | ||
5 | use crate::{ | 5 | use crate::{ |
6 | codegen::{self, extract_comment_blocks_with_empty_lines, Mode}, | 6 | codegen::{self, extract_comment_blocks_with_empty_lines, Location, Mode}, |
7 | project_root, rust_files, Result, | 7 | project_root, rust_files, Result, |
8 | }; | 8 | }; |
9 | 9 | ||
10 | pub fn generate_assists_docs(mode: Mode) -> Result<()> { | 10 | pub fn generate_assists_docs(mode: Mode) -> Result<()> { |
11 | let assists = Assist::collect()?; | 11 | let assists = Assist::collect()?; |
12 | generate_tests(&assists, mode)?; | 12 | generate_tests(&assists, mode)?; |
13 | generate_docs(&assists, mode)?; | 13 | |
14 | let contents = assists.into_iter().map(|it| it.to_string()).collect::<Vec<_>>().join("\n\n"); | ||
15 | let contents = contents.trim().to_string() + "\n"; | ||
16 | let dst = project_root().join("docs/user/generated_assists.adoc"); | ||
17 | codegen::update(&dst, &contents, mode)?; | ||
18 | |||
14 | Ok(()) | 19 | Ok(()) |
15 | } | 20 | } |
16 | 21 | ||
17 | #[derive(Debug)] | 22 | #[derive(Debug)] |
18 | struct Assist { | 23 | struct Assist { |
19 | id: String, | 24 | id: String, |
25 | location: Location, | ||
20 | doc: String, | 26 | doc: String, |
21 | before: String, | 27 | before: String, |
22 | after: String, | 28 | after: String, |
@@ -58,7 +64,8 @@ impl Assist { | |||
58 | assert_eq!(lines.next().unwrap().as_str(), "->"); | 64 | assert_eq!(lines.next().unwrap().as_str(), "->"); |
59 | assert_eq!(lines.next().unwrap().as_str(), "```"); | 65 | assert_eq!(lines.next().unwrap().as_str(), "```"); |
60 | let after = take_until(lines.by_ref(), "```"); | 66 | let after = take_until(lines.by_ref(), "```"); |
61 | acc.push(Assist { id, doc, before, after }) | 67 | let location = Location::new(path.to_path_buf()); |
68 | acc.push(Assist { id, location, doc, before, after }) | ||
62 | } | 69 | } |
63 | 70 | ||
64 | fn take_until<'a>(lines: impl Iterator<Item = &'a String>, marker: &str) -> String { | 71 | fn take_until<'a>(lines: impl Iterator<Item = &'a String>, marker: &str) -> String { |
@@ -76,6 +83,31 @@ impl Assist { | |||
76 | } | 83 | } |
77 | } | 84 | } |
78 | 85 | ||
86 | impl fmt::Display for Assist { | ||
87 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
88 | let before = self.before.replace("<|>", "┃"); // Unicode pseudo-graphics bar | ||
89 | let after = self.after.replace("<|>", "┃"); | ||
90 | writeln!( | ||
91 | f, | ||
92 | "[discrete]\n=== `{}` | ||
93 | |||
94 | {} | ||
95 | |||
96 | .Before | ||
97 | ```rust | ||
98 | {}``` | ||
99 | |||
100 | .After | ||
101 | ```rust | ||
102 | {}```", | ||
103 | self.id, | ||
104 | self.doc, | ||
105 | hide_hash_comments(&before), | ||
106 | hide_hash_comments(&after) | ||
107 | ) | ||
108 | } | ||
109 | } | ||
110 | |||
79 | fn generate_tests(assists: &[Assist], mode: Mode) -> Result<()> { | 111 | fn generate_tests(assists: &[Assist], mode: Mode) -> Result<()> { |
80 | let mut buf = String::from("use super::check_doc_test;\n"); | 112 | let mut buf = String::from("use super::check_doc_test;\n"); |
81 | 113 | ||
@@ -103,37 +135,6 @@ r#####" | |||
103 | codegen::update(&project_root().join(codegen::ASSISTS_TESTS), &buf, mode) | 135 | codegen::update(&project_root().join(codegen::ASSISTS_TESTS), &buf, mode) |
104 | } | 136 | } |
105 | 137 | ||
106 | fn generate_docs(assists: &[Assist], mode: Mode) -> Result<()> { | ||
107 | let mut buf = String::from( | ||
108 | "# Assists\n\nCursor position or selection is signified by `┃` character.\n\n", | ||
109 | ); | ||
110 | |||
111 | for assist in assists { | ||
112 | let before = assist.before.replace("<|>", "┃"); // Unicode pseudo-graphics bar | ||
113 | let after = assist.after.replace("<|>", "┃"); | ||
114 | let docs = format!( | ||
115 | " | ||
116 | ## `{}` | ||
117 | |||
118 | {} | ||
119 | |||
120 | ```rust | ||
121 | // BEFORE | ||
122 | {} | ||
123 | // AFTER | ||
124 | {}``` | ||
125 | ", | ||
126 | assist.id, | ||
127 | assist.doc, | ||
128 | hide_hash_comments(&before), | ||
129 | hide_hash_comments(&after) | ||
130 | ); | ||
131 | buf.push_str(&docs); | ||
132 | } | ||
133 | |||
134 | codegen::update(&project_root().join(codegen::ASSISTS_DOCS), &buf, mode) | ||
135 | } | ||
136 | |||
137 | fn hide_hash_comments(text: &str) -> String { | 138 | fn hide_hash_comments(text: &str) -> String { |
138 | text.split('\n') // want final newline | 139 | text.split('\n') // want final newline |
139 | .filter(|&it| !(it.starts_with("# ") || it == "#")) | 140 | .filter(|&it| !(it.starts_with("# ") || it == "#")) |
diff --git a/xtask/src/codegen/gen_feature_docs.rs b/xtask/src/codegen/gen_feature_docs.rs index dbe583e8e..731e7ecf2 100644 --- a/xtask/src/codegen/gen_feature_docs.rs +++ b/xtask/src/codegen/gen_feature_docs.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use std::{fmt, fs, path::PathBuf}; | 3 | use std::{fmt, fs, path::PathBuf}; |
4 | 4 | ||
5 | use crate::{ | 5 | use crate::{ |
6 | codegen::{self, extract_comment_blocks_with_empty_lines, Mode}, | 6 | codegen::{self, extract_comment_blocks_with_empty_lines, Location, Mode}, |
7 | project_root, rust_files, Result, | 7 | project_root, rust_files, Result, |
8 | }; | 8 | }; |
9 | 9 | ||
@@ -19,7 +19,7 @@ pub fn generate_feature_docs(mode: Mode) -> Result<()> { | |||
19 | #[derive(Debug)] | 19 | #[derive(Debug)] |
20 | struct Feature { | 20 | struct Feature { |
21 | id: String, | 21 | id: String, |
22 | path: PathBuf, | 22 | location: Location, |
23 | doc: String, | 23 | doc: String, |
24 | } | 24 | } |
25 | 25 | ||
@@ -40,7 +40,7 @@ impl Feature { | |||
40 | let id = block.id; | 40 | let id = block.id; |
41 | assert!(is_valid_feature_name(&id), "invalid feature name: {:?}", id); | 41 | assert!(is_valid_feature_name(&id), "invalid feature name: {:?}", id); |
42 | let doc = block.contents.join("\n"); | 42 | let doc = block.contents.join("\n"); |
43 | acc.push(Feature { id, path: path.clone(), doc }) | 43 | acc.push(Feature { id, location: Location::new(path.clone()), doc }) |
44 | } | 44 | } |
45 | 45 | ||
46 | Ok(()) | 46 | Ok(()) |
@@ -69,20 +69,6 @@ fn is_valid_feature_name(feature: &str) -> bool { | |||
69 | 69 | ||
70 | impl fmt::Display for Feature { | 70 | impl fmt::Display for Feature { |
71 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 71 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
72 | writeln!(f, "=== {}", self.id)?; | 72 | writeln!(f, "=== {}\n**Source:** {}\n{}", self.id, self.location, self.doc) |
73 | let path = self.path.strip_prefix(&project_root()).unwrap().display().to_string(); | ||
74 | let path = path.replace('\\', "/"); | ||
75 | let name = self.path.file_name().unwrap(); | ||
76 | |||
77 | //FIXME: generate line number as well | ||
78 | writeln!( | ||
79 | f, | ||
80 | "**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/{}[{}]", | ||
81 | path, | ||
82 | name.to_str().unwrap(), | ||
83 | )?; | ||
84 | |||
85 | writeln!(f, "{}", self.doc)?; | ||
86 | Ok(()) | ||
87 | } | 73 | } |
88 | } | 74 | } |
diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index 06043d19f..874957885 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs | |||
@@ -191,7 +191,7 @@ Release: release:{}[] | |||
191 | let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n)); | 191 | let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n)); |
192 | fs2::write(&path, &contents)?; | 192 | fs2::write(&path, &contents)?; |
193 | 193 | ||
194 | for &adoc in ["manual.adoc", "generated_features.adoc"].iter() { | 194 | for &adoc in ["manual.adoc", "generated_features.adoc", "generated_assists.adoc"].iter() { |
195 | let src = project_root().join("./docs/user/").join(adoc); | 195 | let src = project_root().join("./docs/user/").join(adoc); |
196 | let dst = website_root.join(adoc); | 196 | let dst = website_root.join(adoc); |
197 | fs2::copy(src, dst)?; | 197 | fs2::copy(src, dst)?; |