diff options
Diffstat (limited to 'crates/ra_assists')
-rw-r--r-- | crates/ra_assists/src/doc_tests/generated.rs | 19 | ||||
-rw-r--r-- | crates/ra_assists/src/handlers/add_function.rs | 54 | ||||
-rw-r--r-- | crates/ra_assists/src/handlers/add_missing_impl_members.rs | 34 | ||||
-rw-r--r-- | crates/ra_assists/src/handlers/merge_imports.rs | 33 | ||||
-rw-r--r-- | crates/ra_assists/src/handlers/reorder_fields.rs | 224 | ||||
-rw-r--r-- | crates/ra_assists/src/lib.rs | 2 |
6 files changed, 317 insertions, 49 deletions
diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs index 64444ee3a..b39e60870 100644 --- a/crates/ra_assists/src/doc_tests/generated.rs +++ b/crates/ra_assists/src/doc_tests/generated.rs | |||
@@ -78,7 +78,7 @@ fn foo() { | |||
78 | } | 78 | } |
79 | 79 | ||
80 | fn bar(arg: &str, baz: Baz) { | 80 | fn bar(arg: &str, baz: Baz) { |
81 | unimplemented!() | 81 | todo!() |
82 | } | 82 | } |
83 | 83 | ||
84 | "#####, | 84 | "#####, |
@@ -180,7 +180,7 @@ trait Trait<T> { | |||
180 | } | 180 | } |
181 | 181 | ||
182 | impl Trait<u32> for () { | 182 | impl Trait<u32> for () { |
183 | fn foo(&self) -> u32 { unimplemented!() } | 183 | fn foo(&self) -> u32 { todo!() } |
184 | 184 | ||
185 | } | 185 | } |
186 | "#####, | 186 | "#####, |
@@ -607,6 +607,21 @@ impl Walrus { | |||
607 | } | 607 | } |
608 | 608 | ||
609 | #[test] | 609 | #[test] |
610 | fn doctest_reorder_fields() { | ||
611 | check( | ||
612 | "reorder_fields", | ||
613 | r#####" | ||
614 | struct Foo {foo: i32, bar: i32}; | ||
615 | const test: Foo = <|>Foo {bar: 0, foo: 1} | ||
616 | "#####, | ||
617 | r#####" | ||
618 | struct Foo {foo: i32, bar: i32}; | ||
619 | const test: Foo = Foo {foo: 1, bar: 0} | ||
620 | "#####, | ||
621 | ) | ||
622 | } | ||
623 | |||
624 | #[test] | ||
610 | fn doctest_replace_if_let_with_match() { | 625 | fn doctest_replace_if_let_with_match() { |
611 | check( | 626 | check( |
612 | "replace_if_let_with_match", | 627 | "replace_if_let_with_match", |
diff --git a/crates/ra_assists/src/handlers/add_function.rs b/crates/ra_assists/src/handlers/add_function.rs index 488bae08f..ad4ab66ed 100644 --- a/crates/ra_assists/src/handlers/add_function.rs +++ b/crates/ra_assists/src/handlers/add_function.rs | |||
@@ -29,7 +29,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; | |||
29 | // } | 29 | // } |
30 | // | 30 | // |
31 | // fn bar(arg: &str, baz: Baz) { | 31 | // fn bar(arg: &str, baz: Baz) { |
32 | // unimplemented!() | 32 | // todo!() |
33 | // } | 33 | // } |
34 | // | 34 | // |
35 | // ``` | 35 | // ``` |
@@ -80,7 +80,7 @@ impl FunctionBuilder { | |||
80 | Some(Self { append_fn_at, fn_name, type_params, params }) | 80 | Some(Self { append_fn_at, fn_name, type_params, params }) |
81 | } | 81 | } |
82 | fn render(self) -> Option<FunctionTemplate> { | 82 | fn render(self) -> Option<FunctionTemplate> { |
83 | let placeholder_expr = ast::make::expr_unimplemented(); | 83 | let placeholder_expr = ast::make::expr_todo(); |
84 | let fn_body = ast::make::block_expr(vec![], Some(placeholder_expr)); | 84 | let fn_body = ast::make::block_expr(vec![], Some(placeholder_expr)); |
85 | let fn_def = ast::make::fn_def(self.fn_name, self.type_params, self.params, fn_body); | 85 | let fn_def = ast::make::fn_def(self.fn_name, self.type_params, self.params, fn_body); |
86 | let fn_def = ast::make::add_newlines(2, fn_def); | 86 | let fn_def = ast::make::add_newlines(2, fn_def); |
@@ -225,7 +225,7 @@ fn foo() { | |||
225 | } | 225 | } |
226 | 226 | ||
227 | fn bar() { | 227 | fn bar() { |
228 | <|>unimplemented!() | 228 | <|>todo!() |
229 | } | 229 | } |
230 | ", | 230 | ", |
231 | ) | 231 | ) |
@@ -252,7 +252,7 @@ impl Foo { | |||
252 | } | 252 | } |
253 | 253 | ||
254 | fn bar() { | 254 | fn bar() { |
255 | <|>unimplemented!() | 255 | <|>todo!() |
256 | } | 256 | } |
257 | ", | 257 | ", |
258 | ) | 258 | ) |
@@ -276,7 +276,7 @@ fn foo1() { | |||
276 | } | 276 | } |
277 | 277 | ||
278 | fn bar() { | 278 | fn bar() { |
279 | <|>unimplemented!() | 279 | <|>todo!() |
280 | } | 280 | } |
281 | 281 | ||
282 | fn foo2() {} | 282 | fn foo2() {} |
@@ -302,7 +302,7 @@ mod baz { | |||
302 | } | 302 | } |
303 | 303 | ||
304 | fn bar() { | 304 | fn bar() { |
305 | <|>unimplemented!() | 305 | <|>todo!() |
306 | } | 306 | } |
307 | } | 307 | } |
308 | ", | 308 | ", |
@@ -315,20 +315,20 @@ mod baz { | |||
315 | add_function, | 315 | add_function, |
316 | r" | 316 | r" |
317 | struct Baz; | 317 | struct Baz; |
318 | fn baz() -> Baz { unimplemented!() } | 318 | fn baz() -> Baz { todo!() } |
319 | fn foo() { | 319 | fn foo() { |
320 | bar<|>(baz()); | 320 | bar<|>(baz()); |
321 | } | 321 | } |
322 | ", | 322 | ", |
323 | r" | 323 | r" |
324 | struct Baz; | 324 | struct Baz; |
325 | fn baz() -> Baz { unimplemented!() } | 325 | fn baz() -> Baz { todo!() } |
326 | fn foo() { | 326 | fn foo() { |
327 | bar(baz()); | 327 | bar(baz()); |
328 | } | 328 | } |
329 | 329 | ||
330 | fn bar(baz: Baz) { | 330 | fn bar(baz: Baz) { |
331 | <|>unimplemented!() | 331 | <|>todo!() |
332 | } | 332 | } |
333 | ", | 333 | ", |
334 | ); | 334 | ); |
@@ -361,7 +361,7 @@ impl Baz { | |||
361 | } | 361 | } |
362 | 362 | ||
363 | fn bar(baz: Baz) { | 363 | fn bar(baz: Baz) { |
364 | <|>unimplemented!() | 364 | <|>todo!() |
365 | } | 365 | } |
366 | ", | 366 | ", |
367 | ) | 367 | ) |
@@ -382,7 +382,7 @@ fn foo() { | |||
382 | } | 382 | } |
383 | 383 | ||
384 | fn bar(arg: &str) { | 384 | fn bar(arg: &str) { |
385 | <|>unimplemented!() | 385 | <|>todo!() |
386 | } | 386 | } |
387 | "#, | 387 | "#, |
388 | ) | 388 | ) |
@@ -403,7 +403,7 @@ fn foo() { | |||
403 | } | 403 | } |
404 | 404 | ||
405 | fn bar(arg: char) { | 405 | fn bar(arg: char) { |
406 | <|>unimplemented!() | 406 | <|>todo!() |
407 | } | 407 | } |
408 | "#, | 408 | "#, |
409 | ) | 409 | ) |
@@ -424,7 +424,7 @@ fn foo() { | |||
424 | } | 424 | } |
425 | 425 | ||
426 | fn bar(arg: i32) { | 426 | fn bar(arg: i32) { |
427 | <|>unimplemented!() | 427 | <|>todo!() |
428 | } | 428 | } |
429 | ", | 429 | ", |
430 | ) | 430 | ) |
@@ -445,7 +445,7 @@ fn foo() { | |||
445 | } | 445 | } |
446 | 446 | ||
447 | fn bar(arg: u8) { | 447 | fn bar(arg: u8) { |
448 | <|>unimplemented!() | 448 | <|>todo!() |
449 | } | 449 | } |
450 | ", | 450 | ", |
451 | ) | 451 | ) |
@@ -470,7 +470,7 @@ fn foo() { | |||
470 | } | 470 | } |
471 | 471 | ||
472 | fn bar(x: u8) { | 472 | fn bar(x: u8) { |
473 | <|>unimplemented!() | 473 | <|>todo!() |
474 | } | 474 | } |
475 | ", | 475 | ", |
476 | ) | 476 | ) |
@@ -493,7 +493,7 @@ fn foo() { | |||
493 | } | 493 | } |
494 | 494 | ||
495 | fn bar(worble: ()) { | 495 | fn bar(worble: ()) { |
496 | <|>unimplemented!() | 496 | <|>todo!() |
497 | } | 497 | } |
498 | ", | 498 | ", |
499 | ) | 499 | ) |
@@ -506,7 +506,7 @@ fn bar(worble: ()) { | |||
506 | r" | 506 | r" |
507 | trait Foo {} | 507 | trait Foo {} |
508 | fn foo() -> impl Foo { | 508 | fn foo() -> impl Foo { |
509 | unimplemented!() | 509 | todo!() |
510 | } | 510 | } |
511 | fn baz() { | 511 | fn baz() { |
512 | <|>bar(foo()) | 512 | <|>bar(foo()) |
@@ -515,14 +515,14 @@ fn baz() { | |||
515 | r" | 515 | r" |
516 | trait Foo {} | 516 | trait Foo {} |
517 | fn foo() -> impl Foo { | 517 | fn foo() -> impl Foo { |
518 | unimplemented!() | 518 | todo!() |
519 | } | 519 | } |
520 | fn baz() { | 520 | fn baz() { |
521 | bar(foo()) | 521 | bar(foo()) |
522 | } | 522 | } |
523 | 523 | ||
524 | fn bar(foo: impl Foo) { | 524 | fn bar(foo: impl Foo) { |
525 | <|>unimplemented!() | 525 | <|>todo!() |
526 | } | 526 | } |
527 | ", | 527 | ", |
528 | ) | 528 | ) |
@@ -556,7 +556,7 @@ mod Foo { | |||
556 | } | 556 | } |
557 | 557 | ||
558 | fn bar(baz: super::Baz::Bof) { | 558 | fn bar(baz: super::Baz::Bof) { |
559 | <|>unimplemented!() | 559 | <|>todo!() |
560 | } | 560 | } |
561 | } | 561 | } |
562 | ", | 562 | ", |
@@ -580,7 +580,7 @@ fn foo<T>(t: T) { | |||
580 | } | 580 | } |
581 | 581 | ||
582 | fn bar<T>(t: T) { | 582 | fn bar<T>(t: T) { |
583 | <|>unimplemented!() | 583 | <|>todo!() |
584 | } | 584 | } |
585 | ", | 585 | ", |
586 | ) | 586 | ) |
@@ -611,7 +611,7 @@ fn foo() { | |||
611 | } | 611 | } |
612 | 612 | ||
613 | fn bar(arg: fn() -> Baz) { | 613 | fn bar(arg: fn() -> Baz) { |
614 | <|>unimplemented!() | 614 | <|>todo!() |
615 | } | 615 | } |
616 | ", | 616 | ", |
617 | ) | 617 | ) |
@@ -636,7 +636,7 @@ fn foo() { | |||
636 | } | 636 | } |
637 | 637 | ||
638 | fn bar(closure: impl Fn(i64) -> i64) { | 638 | fn bar(closure: impl Fn(i64) -> i64) { |
639 | <|>unimplemented!() | 639 | <|>todo!() |
640 | } | 640 | } |
641 | ", | 641 | ", |
642 | ) | 642 | ) |
@@ -657,7 +657,7 @@ fn foo() { | |||
657 | } | 657 | } |
658 | 658 | ||
659 | fn bar(baz: ()) { | 659 | fn bar(baz: ()) { |
660 | <|>unimplemented!() | 660 | <|>todo!() |
661 | } | 661 | } |
662 | ", | 662 | ", |
663 | ) | 663 | ) |
@@ -682,7 +682,7 @@ fn foo() { | |||
682 | } | 682 | } |
683 | 683 | ||
684 | fn bar(baz_1: Baz, baz_2: Baz) { | 684 | fn bar(baz_1: Baz, baz_2: Baz) { |
685 | <|>unimplemented!() | 685 | <|>todo!() |
686 | } | 686 | } |
687 | ", | 687 | ", |
688 | ) | 688 | ) |
@@ -707,7 +707,7 @@ fn foo() { | |||
707 | } | 707 | } |
708 | 708 | ||
709 | fn bar(baz_1: Baz, baz_2: Baz, arg_1: &str, arg_2: &str) { | 709 | fn bar(baz_1: Baz, baz_2: Baz, arg_1: &str, arg_2: &str) { |
710 | <|>unimplemented!() | 710 | <|>todo!() |
711 | } | 711 | } |
712 | "#, | 712 | "#, |
713 | ) | 713 | ) |
@@ -779,7 +779,7 @@ impl Foo { | |||
779 | self.bar(); | 779 | self.bar(); |
780 | } | 780 | } |
781 | fn bar(&self) { | 781 | fn bar(&self) { |
782 | unimplemented!(); | 782 | todo!(); |
783 | } | 783 | } |
784 | } | 784 | } |
785 | ", | 785 | ", |
diff --git a/crates/ra_assists/src/handlers/add_missing_impl_members.rs b/crates/ra_assists/src/handlers/add_missing_impl_members.rs index 722f207e2..2d6d44980 100644 --- a/crates/ra_assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ra_assists/src/handlers/add_missing_impl_members.rs | |||
@@ -40,7 +40,7 @@ enum AddMissingImplMembersMode { | |||
40 | // } | 40 | // } |
41 | // | 41 | // |
42 | // impl Trait<u32> for () { | 42 | // impl Trait<u32> for () { |
43 | // fn foo(&self) -> u32 { unimplemented!() } | 43 | // fn foo(&self) -> u32 { todo!() } |
44 | // | 44 | // |
45 | // } | 45 | // } |
46 | // ``` | 46 | // ``` |
@@ -165,7 +165,7 @@ fn add_missing_impl_members_inner( | |||
165 | 165 | ||
166 | fn add_body(fn_def: ast::FnDef) -> ast::FnDef { | 166 | fn add_body(fn_def: ast::FnDef) -> ast::FnDef { |
167 | if fn_def.body().is_none() { | 167 | if fn_def.body().is_none() { |
168 | fn_def.with_body(make::block_from_expr(make::expr_unimplemented())) | 168 | fn_def.with_body(make::block_from_expr(make::expr_todo())) |
169 | } else { | 169 | } else { |
170 | fn_def | 170 | fn_def |
171 | } | 171 | } |
@@ -215,8 +215,8 @@ impl Foo for S { | |||
215 | fn bar(&self) {} | 215 | fn bar(&self) {} |
216 | <|>type Output; | 216 | <|>type Output; |
217 | const CONST: usize = 42; | 217 | const CONST: usize = 42; |
218 | fn foo(&self) { unimplemented!() } | 218 | fn foo(&self) { todo!() } |
219 | fn baz(&self) { unimplemented!() } | 219 | fn baz(&self) { todo!() } |
220 | 220 | ||
221 | }", | 221 | }", |
222 | ); | 222 | ); |
@@ -250,7 +250,7 @@ struct S; | |||
250 | 250 | ||
251 | impl Foo for S { | 251 | impl Foo for S { |
252 | fn bar(&self) {} | 252 | fn bar(&self) {} |
253 | <|>fn foo(&self) { unimplemented!() } | 253 | <|>fn foo(&self) { todo!() } |
254 | 254 | ||
255 | }", | 255 | }", |
256 | ); | 256 | ); |
@@ -268,7 +268,7 @@ impl Foo for S { <|> }", | |||
268 | trait Foo { fn foo(&self); } | 268 | trait Foo { fn foo(&self); } |
269 | struct S; | 269 | struct S; |
270 | impl Foo for S { | 270 | impl Foo for S { |
271 | <|>fn foo(&self) { unimplemented!() } | 271 | <|>fn foo(&self) { todo!() } |
272 | }", | 272 | }", |
273 | ); | 273 | ); |
274 | } | 274 | } |
@@ -285,7 +285,7 @@ impl Foo<u32> for S { <|> }", | |||
285 | trait Foo<T> { fn foo(&self, t: T) -> &T; } | 285 | trait Foo<T> { fn foo(&self, t: T) -> &T; } |
286 | struct S; | 286 | struct S; |
287 | impl Foo<u32> for S { | 287 | impl Foo<u32> for S { |
288 | <|>fn foo(&self, t: u32) -> &u32 { unimplemented!() } | 288 | <|>fn foo(&self, t: u32) -> &u32 { todo!() } |
289 | }", | 289 | }", |
290 | ); | 290 | ); |
291 | } | 291 | } |
@@ -302,7 +302,7 @@ impl<U> Foo<U> for S { <|> }", | |||
302 | trait Foo<T> { fn foo(&self, t: T) -> &T; } | 302 | trait Foo<T> { fn foo(&self, t: T) -> &T; } |
303 | struct S; | 303 | struct S; |
304 | impl<U> Foo<U> for S { | 304 | impl<U> Foo<U> for S { |
305 | <|>fn foo(&self, t: U) -> &U { unimplemented!() } | 305 | <|>fn foo(&self, t: U) -> &U { todo!() } |
306 | }", | 306 | }", |
307 | ); | 307 | ); |
308 | } | 308 | } |
@@ -319,7 +319,7 @@ impl Foo for S {}<|>", | |||
319 | trait Foo { fn foo(&self); } | 319 | trait Foo { fn foo(&self); } |
320 | struct S; | 320 | struct S; |
321 | impl Foo for S { | 321 | impl Foo for S { |
322 | <|>fn foo(&self) { unimplemented!() } | 322 | <|>fn foo(&self) { todo!() } |
323 | }", | 323 | }", |
324 | ) | 324 | ) |
325 | } | 325 | } |
@@ -342,7 +342,7 @@ mod foo { | |||
342 | } | 342 | } |
343 | struct S; | 343 | struct S; |
344 | impl foo::Foo for S { | 344 | impl foo::Foo for S { |
345 | <|>fn foo(&self, bar: foo::Bar) { unimplemented!() } | 345 | <|>fn foo(&self, bar: foo::Bar) { todo!() } |
346 | }", | 346 | }", |
347 | ); | 347 | ); |
348 | } | 348 | } |
@@ -365,7 +365,7 @@ mod foo { | |||
365 | } | 365 | } |
366 | struct S; | 366 | struct S; |
367 | impl foo::Foo for S { | 367 | impl foo::Foo for S { |
368 | <|>fn foo(&self, bar: foo::Bar<u32>) { unimplemented!() } | 368 | <|>fn foo(&self, bar: foo::Bar<u32>) { todo!() } |
369 | }", | 369 | }", |
370 | ); | 370 | ); |
371 | } | 371 | } |
@@ -388,7 +388,7 @@ mod foo { | |||
388 | } | 388 | } |
389 | struct S; | 389 | struct S; |
390 | impl foo::Foo<u32> for S { | 390 | impl foo::Foo<u32> for S { |
391 | <|>fn foo(&self, bar: foo::Bar<u32>) { unimplemented!() } | 391 | <|>fn foo(&self, bar: foo::Bar<u32>) { todo!() } |
392 | }", | 392 | }", |
393 | ); | 393 | ); |
394 | } | 394 | } |
@@ -414,7 +414,7 @@ mod foo { | |||
414 | struct Param; | 414 | struct Param; |
415 | struct S; | 415 | struct S; |
416 | impl foo::Foo<Param> for S { | 416 | impl foo::Foo<Param> for S { |
417 | <|>fn foo(&self, bar: Param) { unimplemented!() } | 417 | <|>fn foo(&self, bar: Param) { todo!() } |
418 | }", | 418 | }", |
419 | ); | 419 | ); |
420 | } | 420 | } |
@@ -439,7 +439,7 @@ mod foo { | |||
439 | } | 439 | } |
440 | struct S; | 440 | struct S; |
441 | impl foo::Foo for S { | 441 | impl foo::Foo for S { |
442 | <|>fn foo(&self, bar: foo::Bar<u32>::Assoc) { unimplemented!() } | 442 | <|>fn foo(&self, bar: foo::Bar<u32>::Assoc) { todo!() } |
443 | }", | 443 | }", |
444 | ); | 444 | ); |
445 | } | 445 | } |
@@ -464,7 +464,7 @@ mod foo { | |||
464 | } | 464 | } |
465 | struct S; | 465 | struct S; |
466 | impl foo::Foo for S { | 466 | impl foo::Foo for S { |
467 | <|>fn foo(&self, bar: foo::Bar<foo::Baz>) { unimplemented!() } | 467 | <|>fn foo(&self, bar: foo::Bar<foo::Baz>) { todo!() } |
468 | }", | 468 | }", |
469 | ); | 469 | ); |
470 | } | 470 | } |
@@ -487,7 +487,7 @@ mod foo { | |||
487 | } | 487 | } |
488 | struct S; | 488 | struct S; |
489 | impl foo::Foo for S { | 489 | impl foo::Foo for S { |
490 | <|>fn foo(&self, bar: dyn Fn(u32) -> i32) { unimplemented!() } | 490 | <|>fn foo(&self, bar: dyn Fn(u32) -> i32) { todo!() } |
491 | }", | 491 | }", |
492 | ); | 492 | ); |
493 | } | 493 | } |
@@ -544,7 +544,7 @@ trait Foo { | |||
544 | struct S; | 544 | struct S; |
545 | impl Foo for S { | 545 | impl Foo for S { |
546 | <|>type Output; | 546 | <|>type Output; |
547 | fn foo(&self) { unimplemented!() } | 547 | fn foo(&self) { todo!() } |
548 | }"#, | 548 | }"#, |
549 | ) | 549 | ) |
550 | } | 550 | } |
diff --git a/crates/ra_assists/src/handlers/merge_imports.rs b/crates/ra_assists/src/handlers/merge_imports.rs index 0958f52f1..ef0ce0586 100644 --- a/crates/ra_assists/src/handlers/merge_imports.rs +++ b/crates/ra_assists/src/handlers/merge_imports.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use std::iter::successors; | 1 | use std::iter::successors; |
2 | 2 | ||
3 | use ra_syntax::{ | 3 | use ra_syntax::{ |
4 | algo::{neighbor, SyntaxRewriter}, | 4 | algo::{neighbor, skip_trivia_token, SyntaxRewriter}, |
5 | ast::{self, edit::AstNodeEdit, make}, | 5 | ast::{self, edit::AstNodeEdit, make}, |
6 | AstNode, Direction, InsertPosition, SyntaxElement, T, | 6 | AstNode, Direction, InsertPosition, SyntaxElement, T, |
7 | }; | 7 | }; |
@@ -72,9 +72,18 @@ fn try_merge_trees(old: &ast::UseTree, new: &ast::UseTree) -> Option<ast::UseTre | |||
72 | let lhs = old.split_prefix(&lhs_prefix); | 72 | let lhs = old.split_prefix(&lhs_prefix); |
73 | let rhs = new.split_prefix(&rhs_prefix); | 73 | let rhs = new.split_prefix(&rhs_prefix); |
74 | 74 | ||
75 | let should_insert_comma = lhs | ||
76 | .use_tree_list()? | ||
77 | .r_curly_token() | ||
78 | .and_then(|it| skip_trivia_token(it.prev_token()?, Direction::Prev)) | ||
79 | .map(|it| it.kind() != T![,]) | ||
80 | .unwrap_or(true); | ||
81 | |||
75 | let mut to_insert: Vec<SyntaxElement> = Vec::new(); | 82 | let mut to_insert: Vec<SyntaxElement> = Vec::new(); |
76 | to_insert.push(make::token(T![,]).into()); | 83 | if should_insert_comma { |
77 | to_insert.push(make::tokens::single_space().into()); | 84 | to_insert.push(make::token(T![,]).into()); |
85 | to_insert.push(make::tokens::single_space().into()); | ||
86 | } | ||
78 | to_insert.extend( | 87 | to_insert.extend( |
79 | rhs.use_tree_list()? | 88 | rhs.use_tree_list()? |
80 | .syntax() | 89 | .syntax() |
@@ -247,4 +256,22 @@ use { | |||
247 | ", | 256 | ", |
248 | ); | 257 | ); |
249 | } | 258 | } |
259 | |||
260 | #[test] | ||
261 | fn test_double_comma() { | ||
262 | check_assist( | ||
263 | merge_imports, | ||
264 | r" | ||
265 | use foo::bar::baz; | ||
266 | use foo::<|>{ | ||
267 | FooBar, | ||
268 | }; | ||
269 | ", | ||
270 | r" | ||
271 | use foo::{<|> | ||
272 | FooBar, | ||
273 | bar::baz}; | ||
274 | ", | ||
275 | ) | ||
276 | } | ||
250 | } | 277 | } |
diff --git a/crates/ra_assists/src/handlers/reorder_fields.rs b/crates/ra_assists/src/handlers/reorder_fields.rs new file mode 100644 index 000000000..5cbb98d73 --- /dev/null +++ b/crates/ra_assists/src/handlers/reorder_fields.rs | |||
@@ -0,0 +1,224 @@ | |||
1 | use std::collections::HashMap; | ||
2 | |||
3 | use hir::{Adt, ModuleDef, PathResolution, Semantics, Struct}; | ||
4 | use itertools::Itertools; | ||
5 | use ra_ide_db::RootDatabase; | ||
6 | use ra_syntax::{ | ||
7 | algo, | ||
8 | ast::{self, Path, RecordLit, RecordPat}, | ||
9 | match_ast, AstNode, SyntaxKind, | ||
10 | SyntaxKind::*, | ||
11 | SyntaxNode, | ||
12 | }; | ||
13 | |||
14 | use crate::{ | ||
15 | assist_ctx::{Assist, AssistCtx}, | ||
16 | AssistId, | ||
17 | }; | ||
18 | |||
19 | // Assist: reorder_fields | ||
20 | // | ||
21 | // Reorder the fields of record literals and record patterns in the same order as in | ||
22 | // the definition. | ||
23 | // | ||
24 | // ``` | ||
25 | // struct Foo {foo: i32, bar: i32}; | ||
26 | // const test: Foo = <|>Foo {bar: 0, foo: 1} | ||
27 | // ``` | ||
28 | // -> | ||
29 | // ``` | ||
30 | // struct Foo {foo: i32, bar: i32}; | ||
31 | // const test: Foo = Foo {foo: 1, bar: 0} | ||
32 | // ``` | ||
33 | // | ||
34 | pub(crate) fn reorder_fields(ctx: AssistCtx) -> Option<Assist> { | ||
35 | reorder::<RecordLit>(ctx.clone()).or_else(|| reorder::<RecordPat>(ctx)) | ||
36 | } | ||
37 | |||
38 | fn reorder<R: AstNode>(ctx: AssistCtx) -> Option<Assist> { | ||
39 | let record = ctx.find_node_at_offset::<R>()?; | ||
40 | let path = record.syntax().children().find_map(Path::cast)?; | ||
41 | |||
42 | let ranks = compute_fields_ranks(&path, &ctx)?; | ||
43 | |||
44 | let fields = get_fields(&record.syntax()); | ||
45 | let sorted_fields = sorted_by_rank(&fields, |node| { | ||
46 | *ranks.get(&get_field_name(node)).unwrap_or(&usize::max_value()) | ||
47 | }); | ||
48 | |||
49 | if sorted_fields == fields { | ||
50 | return None; | ||
51 | } | ||
52 | |||
53 | ctx.add_assist(AssistId("reorder_fields"), "Reorder record fields", |edit| { | ||
54 | for (old, new) in fields.iter().zip(&sorted_fields) { | ||
55 | algo::diff(old, new).into_text_edit(edit.text_edit_builder()); | ||
56 | } | ||
57 | edit.target(record.syntax().text_range()) | ||
58 | }) | ||
59 | } | ||
60 | |||
61 | fn get_fields_kind(node: &SyntaxNode) -> Vec<SyntaxKind> { | ||
62 | match node.kind() { | ||
63 | RECORD_LIT => vec![RECORD_FIELD], | ||
64 | RECORD_PAT => vec![RECORD_FIELD_PAT, BIND_PAT], | ||
65 | _ => vec![], | ||
66 | } | ||
67 | } | ||
68 | |||
69 | fn get_field_name(node: &SyntaxNode) -> String { | ||
70 | let res = match_ast! { | ||
71 | match node { | ||
72 | ast::RecordField(field) => field.field_name().map(|it| it.to_string()), | ||
73 | ast::RecordFieldPat(field) => field.field_name().map(|it| it.to_string()), | ||
74 | _ => None, | ||
75 | } | ||
76 | }; | ||
77 | res.unwrap_or_default() | ||
78 | } | ||
79 | |||
80 | fn get_fields(record: &SyntaxNode) -> Vec<SyntaxNode> { | ||
81 | let kinds = get_fields_kind(record); | ||
82 | record.children().flat_map(|n| n.children()).filter(|n| kinds.contains(&n.kind())).collect() | ||
83 | } | ||
84 | |||
85 | fn sorted_by_rank( | ||
86 | fields: &[SyntaxNode], | ||
87 | get_rank: impl Fn(&SyntaxNode) -> usize, | ||
88 | ) -> Vec<SyntaxNode> { | ||
89 | fields.iter().cloned().sorted_by_key(get_rank).collect() | ||
90 | } | ||
91 | |||
92 | fn struct_definition(path: &ast::Path, sema: &Semantics<RootDatabase>) -> Option<Struct> { | ||
93 | match sema.resolve_path(path) { | ||
94 | Some(PathResolution::Def(ModuleDef::Adt(Adt::Struct(s)))) => Some(s), | ||
95 | _ => None, | ||
96 | } | ||
97 | } | ||
98 | |||
99 | fn compute_fields_ranks(path: &Path, ctx: &AssistCtx) -> Option<HashMap<String, usize>> { | ||
100 | Some( | ||
101 | struct_definition(path, ctx.sema)? | ||
102 | .fields(ctx.db) | ||
103 | .iter() | ||
104 | .enumerate() | ||
105 | .map(|(idx, field)| (field.name(ctx.db).to_string(), idx)) | ||
106 | .collect(), | ||
107 | ) | ||
108 | } | ||
109 | |||
110 | #[cfg(test)] | ||
111 | mod tests { | ||
112 | use crate::helpers::{check_assist, check_assist_not_applicable}; | ||
113 | |||
114 | use super::*; | ||
115 | |||
116 | #[test] | ||
117 | fn not_applicable_if_sorted() { | ||
118 | check_assist_not_applicable( | ||
119 | reorder_fields, | ||
120 | r#" | ||
121 | struct Foo { | ||
122 | foo: i32, | ||
123 | bar: i32, | ||
124 | } | ||
125 | |||
126 | const test: Foo = <|>Foo { foo: 0, bar: 0 }; | ||
127 | "#, | ||
128 | ) | ||
129 | } | ||
130 | |||
131 | #[test] | ||
132 | fn trivial_empty_fields() { | ||
133 | check_assist_not_applicable( | ||
134 | reorder_fields, | ||
135 | r#" | ||
136 | struct Foo {}; | ||
137 | const test: Foo = <|>Foo {} | ||
138 | "#, | ||
139 | ) | ||
140 | } | ||
141 | |||
142 | #[test] | ||
143 | fn reorder_struct_fields() { | ||
144 | check_assist( | ||
145 | reorder_fields, | ||
146 | r#" | ||
147 | struct Foo {foo: i32, bar: i32}; | ||
148 | const test: Foo = <|>Foo {bar: 0, foo: 1} | ||
149 | "#, | ||
150 | r#" | ||
151 | struct Foo {foo: i32, bar: i32}; | ||
152 | const test: Foo = <|>Foo {foo: 1, bar: 0} | ||
153 | "#, | ||
154 | ) | ||
155 | } | ||
156 | |||
157 | #[test] | ||
158 | fn reorder_struct_pattern() { | ||
159 | check_assist( | ||
160 | reorder_fields, | ||
161 | r#" | ||
162 | struct Foo { foo: i64, bar: i64, baz: i64 } | ||
163 | |||
164 | fn f(f: Foo) -> { | ||
165 | match f { | ||
166 | <|>Foo { baz: 0, ref mut bar, .. } => (), | ||
167 | _ => () | ||
168 | } | ||
169 | } | ||
170 | "#, | ||
171 | r#" | ||
172 | struct Foo { foo: i64, bar: i64, baz: i64 } | ||
173 | |||
174 | fn f(f: Foo) -> { | ||
175 | match f { | ||
176 | <|>Foo { ref mut bar, baz: 0, .. } => (), | ||
177 | _ => () | ||
178 | } | ||
179 | } | ||
180 | "#, | ||
181 | ) | ||
182 | } | ||
183 | |||
184 | #[test] | ||
185 | fn reorder_with_extra_field() { | ||
186 | check_assist( | ||
187 | reorder_fields, | ||
188 | r#" | ||
189 | struct Foo { | ||
190 | foo: String, | ||
191 | bar: String, | ||
192 | } | ||
193 | |||
194 | impl Foo { | ||
195 | fn new() -> Foo { | ||
196 | let foo = String::new(); | ||
197 | <|>Foo { | ||
198 | bar: foo.clone(), | ||
199 | extra: "Extra field", | ||
200 | foo, | ||
201 | } | ||
202 | } | ||
203 | } | ||
204 | "#, | ||
205 | r#" | ||
206 | struct Foo { | ||
207 | foo: String, | ||
208 | bar: String, | ||
209 | } | ||
210 | |||
211 | impl Foo { | ||
212 | fn new() -> Foo { | ||
213 | let foo = String::new(); | ||
214 | <|>Foo { | ||
215 | foo, | ||
216 | bar: foo.clone(), | ||
217 | extra: "Extra field", | ||
218 | } | ||
219 | } | ||
220 | } | ||
221 | "#, | ||
222 | ) | ||
223 | } | ||
224 | } | ||
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 5ba5254fd..a00136da1 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -129,6 +129,7 @@ mod handlers { | |||
129 | mod replace_unwrap_with_match; | 129 | mod replace_unwrap_with_match; |
130 | mod split_import; | 130 | mod split_import; |
131 | mod add_from_impl_for_enum; | 131 | mod add_from_impl_for_enum; |
132 | mod reorder_fields; | ||
132 | 133 | ||
133 | pub(crate) fn all() -> &'static [AssistHandler] { | 134 | pub(crate) fn all() -> &'static [AssistHandler] { |
134 | &[ | 135 | &[ |
@@ -170,6 +171,7 @@ mod handlers { | |||
170 | // These are manually sorted for better priorities | 171 | // These are manually sorted for better priorities |
171 | add_missing_impl_members::add_missing_impl_members, | 172 | add_missing_impl_members::add_missing_impl_members, |
172 | add_missing_impl_members::add_missing_default_members, | 173 | add_missing_impl_members::add_missing_default_members, |
174 | reorder_fields::reorder_fields, | ||
173 | ] | 175 | ] |
174 | } | 176 | } |
175 | } | 177 | } |