diff options
-rw-r--r-- | crates/ra_assists/src/assists/add_missing_impl_members.rs | 127 |
1 files changed, 126 insertions, 1 deletions
diff --git a/crates/ra_assists/src/assists/add_missing_impl_members.rs b/crates/ra_assists/src/assists/add_missing_impl_members.rs index 2b0726869..dd62b1b78 100644 --- a/crates/ra_assists/src/assists/add_missing_impl_members.rs +++ b/crates/ra_assists/src/assists/add_missing_impl_members.rs | |||
@@ -239,9 +239,11 @@ fn substitute_type_params<N: AstNode>( | |||
239 | 239 | ||
240 | use hir::PathResolution; | 240 | use hir::PathResolution; |
241 | 241 | ||
242 | // TODO handle partial paths, with generic args | 242 | // TODO handle generic args |
243 | // TODO handle associated item paths | ||
243 | // TODO handle value ns? | 244 | // TODO handle value ns? |
244 | 245 | ||
246 | // FIXME extract this to a general utility as well | ||
245 | fn qualify_paths<N: AstNode>(db: &impl HirDatabase, node: hir::InFile<N>, from: hir::Module) -> N { | 247 | fn qualify_paths<N: AstNode>(db: &impl HirDatabase, node: hir::InFile<N>, from: hir::Module) -> N { |
246 | let path_replacements = node | 248 | let path_replacements = node |
247 | .value | 249 | .value |
@@ -249,6 +251,10 @@ fn qualify_paths<N: AstNode>(db: &impl HirDatabase, node: hir::InFile<N>, from: | |||
249 | .descendants() | 251 | .descendants() |
250 | .filter_map(ast::Path::cast) | 252 | .filter_map(ast::Path::cast) |
251 | .filter_map(|p| { | 253 | .filter_map(|p| { |
254 | if p.segment().and_then(|s| s.param_list()).is_some() { | ||
255 | // don't try to qualify `Fn(Foo) -> Bar` paths, they are in prelude anyway | ||
256 | return None; | ||
257 | } | ||
252 | let analyzer = hir::SourceAnalyzer::new(db, node.with_value(p.syntax()), None); | 258 | let analyzer = hir::SourceAnalyzer::new(db, node.with_value(p.syntax()), None); |
253 | let resolution = analyzer.resolve_path(db, &p)?; | 259 | let resolution = analyzer.resolve_path(db, &p)?; |
254 | match resolution { | 260 | match resolution { |
@@ -469,6 +475,125 @@ impl foo::Foo for S { | |||
469 | } | 475 | } |
470 | 476 | ||
471 | #[test] | 477 | #[test] |
478 | fn test_qualify_path_generic() { | ||
479 | check_assist( | ||
480 | add_missing_impl_members, | ||
481 | " | ||
482 | mod foo { | ||
483 | pub struct Bar<T>; | ||
484 | trait Foo { fn foo(&self, bar: Bar<u32>); } | ||
485 | } | ||
486 | struct S; | ||
487 | impl foo::Foo for S { <|> }", | ||
488 | " | ||
489 | mod foo { | ||
490 | pub struct Bar<T>; | ||
491 | trait Foo { fn foo(&self, bar: Bar<u32>); } | ||
492 | } | ||
493 | struct S; | ||
494 | impl foo::Foo for S { | ||
495 | <|>fn foo(&self, bar: foo::Bar<u32>) { unimplemented!() } | ||
496 | }", | ||
497 | ); | ||
498 | } | ||
499 | |||
500 | #[test] | ||
501 | fn test_qualify_path_and_substitute_param() { | ||
502 | check_assist( | ||
503 | add_missing_impl_members, | ||
504 | " | ||
505 | mod foo { | ||
506 | pub struct Bar<T>; | ||
507 | trait Foo<T> { fn foo(&self, bar: Bar<T>); } | ||
508 | } | ||
509 | struct S; | ||
510 | impl foo::Foo<u32> for S { <|> }", | ||
511 | " | ||
512 | mod foo { | ||
513 | pub struct Bar<T>; | ||
514 | trait Foo<T> { fn foo(&self, bar: Bar<T>); } | ||
515 | } | ||
516 | struct S; | ||
517 | impl foo::Foo<u32> for S { | ||
518 | <|>fn foo(&self, bar: foo::Bar<u32>) { unimplemented!() } | ||
519 | }", | ||
520 | ); | ||
521 | } | ||
522 | |||
523 | #[test] | ||
524 | fn test_qualify_path_associated_item() { | ||
525 | check_assist( | ||
526 | add_missing_impl_members, | ||
527 | " | ||
528 | mod foo { | ||
529 | pub struct Bar<T>; | ||
530 | impl Bar<T> { type Assoc = u32; } | ||
531 | trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); } | ||
532 | } | ||
533 | struct S; | ||
534 | impl foo::Foo for S { <|> }", | ||
535 | " | ||
536 | mod foo { | ||
537 | pub struct Bar<T>; | ||
538 | impl Bar { type Assoc = u32; } | ||
539 | trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); } | ||
540 | } | ||
541 | struct S; | ||
542 | impl foo::Foo for S { | ||
543 | <|>fn foo(&self, bar: foo::Bar<u32>::Assoc) { unimplemented!() } | ||
544 | }", | ||
545 | ); | ||
546 | } | ||
547 | |||
548 | #[test] | ||
549 | fn test_qualify_path_nested() { | ||
550 | check_assist( | ||
551 | add_missing_impl_members, | ||
552 | " | ||
553 | mod foo { | ||
554 | pub struct Bar<T>; | ||
555 | pub struct Baz; | ||
556 | trait Foo { fn foo(&self, bar: Bar<Baz>); } | ||
557 | } | ||
558 | struct S; | ||
559 | impl foo::Foo for S { <|> }", | ||
560 | " | ||
561 | mod foo { | ||
562 | pub struct Bar<T>; | ||
563 | pub struct Baz; | ||
564 | trait Foo { fn foo(&self, bar: Bar<Baz>); } | ||
565 | } | ||
566 | struct S; | ||
567 | impl foo::Foo for S { | ||
568 | <|>fn foo(&self, bar: foo::Bar<foo::Baz>) { unimplemented!() } | ||
569 | }", | ||
570 | ); | ||
571 | } | ||
572 | |||
573 | #[test] | ||
574 | fn test_qualify_path_fn_trait_notation() { | ||
575 | check_assist( | ||
576 | add_missing_impl_members, | ||
577 | " | ||
578 | mod foo { | ||
579 | pub trait Fn<Args> { type Output; } | ||
580 | trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); } | ||
581 | } | ||
582 | struct S; | ||
583 | impl foo::Foo for S { <|> }", | ||
584 | " | ||
585 | mod foo { | ||
586 | pub trait Fn<Args> { type Output; } | ||
587 | trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); } | ||
588 | } | ||
589 | struct S; | ||
590 | impl foo::Foo for S { | ||
591 | <|>fn foo(&self, bar: dyn Fn(u32) -> i32) { unimplemented!() } | ||
592 | }", | ||
593 | ); | ||
594 | } | ||
595 | |||
596 | #[test] | ||
472 | fn test_empty_trait() { | 597 | fn test_empty_trait() { |
473 | check_assist_not_applicable( | 598 | check_assist_not_applicable( |
474 | add_missing_impl_members, | 599 | add_missing_impl_members, |