diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-11-01 19:03:05 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2019-11-01 19:03:05 +0000 |
commit | 9db97820f4c1c38110175f4efda2702356a4199a (patch) | |
tree | f560ab731b9da35902d3da720e19731b51ab62df /crates/ra_ide_api | |
parent | ed5212e1ac71e959d802a9a7ad28d06c8b18e022 (diff) | |
parent | 895238088417b292e35705e72182ff8cc3ab6f63 (diff) |
Merge #2151
2151: Resolve (and complete) trait calls like `Vec::default()` r=flodiebold a=flodiebold
Similar to rustc, we do this using the same code as the method call resolution, just without doing autoderef (and considering more potential candidates).
(Btw, we currently don't complete methods with `self` in path notation, even though they'd be legal to use, so maybe we should -- on the other hand, that will usually not be the most interesting completions...)
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_ide_api')
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_path.rs | 142 | ||||
-rw-r--r-- | crates/ra_ide_api/src/goto_definition.rs | 55 |
2 files changed, 190 insertions, 7 deletions
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index a58fdc036..9ac9768af 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs | |||
@@ -50,23 +50,46 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { | |||
50 | hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db), | 50 | hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db), |
51 | _ => unreachable!(), | 51 | _ => unreachable!(), |
52 | }; | 52 | }; |
53 | ctx.analyzer.iterate_path_candidates(ctx.db, ty.clone(), None, |_ty, item| { | ||
54 | match item { | ||
55 | hir::AssocItem::Function(func) => { | ||
56 | let data = func.data(ctx.db); | ||
57 | if !data.has_self_param() { | ||
58 | acc.add_function(ctx, func); | ||
59 | } | ||
60 | } | ||
61 | hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), | ||
62 | hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), | ||
63 | } | ||
64 | None::<()> | ||
65 | }); | ||
66 | // Iterate assoc types separately | ||
67 | // FIXME: complete T::AssocType | ||
53 | let krate = ctx.module.map(|m| m.krate()); | 68 | let krate = ctx.module.map(|m| m.krate()); |
54 | if let Some(krate) = krate { | 69 | if let Some(krate) = krate { |
55 | ty.iterate_impl_items(ctx.db, krate, |item| { | 70 | ty.iterate_impl_items(ctx.db, krate, |item| { |
56 | match item { | 71 | match item { |
57 | hir::AssocItem::Function(func) => { | 72 | hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {} |
58 | let data = func.data(ctx.db); | ||
59 | if !data.has_self_param() { | ||
60 | acc.add_function(ctx, func); | ||
61 | } | ||
62 | } | ||
63 | hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), | ||
64 | hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), | 73 | hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), |
65 | } | 74 | } |
66 | None::<()> | 75 | None::<()> |
67 | }); | 76 | }); |
68 | } | 77 | } |
69 | } | 78 | } |
79 | hir::ModuleDef::Trait(t) => { | ||
80 | for item in t.items(ctx.db) { | ||
81 | match item { | ||
82 | hir::AssocItem::Function(func) => { | ||
83 | let data = func.data(ctx.db); | ||
84 | if !data.has_self_param() { | ||
85 | acc.add_function(ctx, func); | ||
86 | } | ||
87 | } | ||
88 | hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), | ||
89 | hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), | ||
90 | } | ||
91 | } | ||
92 | } | ||
70 | _ => {} | 93 | _ => {} |
71 | }; | 94 | }; |
72 | } | 95 | } |
@@ -559,6 +582,111 @@ mod tests { | |||
559 | } | 582 | } |
560 | 583 | ||
561 | #[test] | 584 | #[test] |
585 | fn completes_trait_associated_method_1() { | ||
586 | assert_debug_snapshot!( | ||
587 | do_reference_completion( | ||
588 | " | ||
589 | //- /lib.rs | ||
590 | trait Trait { | ||
591 | /// A trait method | ||
592 | fn m(); | ||
593 | } | ||
594 | |||
595 | fn foo() { let _ = Trait::<|> } | ||
596 | " | ||
597 | ), | ||
598 | @r###" | ||
599 | [ | ||
600 | CompletionItem { | ||
601 | label: "m()", | ||
602 | source_range: [73; 73), | ||
603 | delete: [73; 73), | ||
604 | insert: "m()$0", | ||
605 | kind: Function, | ||
606 | lookup: "m", | ||
607 | detail: "fn m()", | ||
608 | documentation: Documentation( | ||
609 | "A trait method", | ||
610 | ), | ||
611 | }, | ||
612 | ] | ||
613 | "### | ||
614 | ); | ||
615 | } | ||
616 | |||
617 | #[test] | ||
618 | fn completes_trait_associated_method_2() { | ||
619 | assert_debug_snapshot!( | ||
620 | do_reference_completion( | ||
621 | " | ||
622 | //- /lib.rs | ||
623 | trait Trait { | ||
624 | /// A trait method | ||
625 | fn m(); | ||
626 | } | ||
627 | |||
628 | struct S; | ||
629 | impl Trait for S {} | ||
630 | |||
631 | fn foo() { let _ = S::<|> } | ||
632 | " | ||
633 | ), | ||
634 | @r###" | ||
635 | [ | ||
636 | CompletionItem { | ||
637 | label: "m()", | ||
638 | source_range: [99; 99), | ||
639 | delete: [99; 99), | ||
640 | insert: "m()$0", | ||
641 | kind: Function, | ||
642 | lookup: "m", | ||
643 | detail: "fn m()", | ||
644 | documentation: Documentation( | ||
645 | "A trait method", | ||
646 | ), | ||
647 | }, | ||
648 | ] | ||
649 | "### | ||
650 | ); | ||
651 | } | ||
652 | |||
653 | #[test] | ||
654 | fn completes_trait_associated_method_3() { | ||
655 | assert_debug_snapshot!( | ||
656 | do_reference_completion( | ||
657 | " | ||
658 | //- /lib.rs | ||
659 | trait Trait { | ||
660 | /// A trait method | ||
661 | fn m(); | ||
662 | } | ||
663 | |||
664 | struct S; | ||
665 | impl Trait for S {} | ||
666 | |||
667 | fn foo() { let _ = <S as Trait>::<|> } | ||
668 | " | ||
669 | ), | ||
670 | @r###" | ||
671 | [ | ||
672 | CompletionItem { | ||
673 | label: "m()", | ||
674 | source_range: [110; 110), | ||
675 | delete: [110; 110), | ||
676 | insert: "m()$0", | ||
677 | kind: Function, | ||
678 | lookup: "m", | ||
679 | detail: "fn m()", | ||
680 | documentation: Documentation( | ||
681 | "A trait method", | ||
682 | ), | ||
683 | }, | ||
684 | ] | ||
685 | "### | ||
686 | ); | ||
687 | } | ||
688 | |||
689 | #[test] | ||
562 | fn completes_type_alias() { | 690 | fn completes_type_alias() { |
563 | assert_debug_snapshot!( | 691 | assert_debug_snapshot!( |
564 | do_reference_completion( | 692 | do_reference_completion( |
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 323faab33..c1ce54bea 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs | |||
@@ -390,6 +390,61 @@ mod tests { | |||
390 | "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)", | 390 | "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)", |
391 | ); | 391 | ); |
392 | } | 392 | } |
393 | |||
394 | #[test] | ||
395 | fn goto_definition_works_for_ufcs_inherent_methods() { | ||
396 | check_goto( | ||
397 | " | ||
398 | //- /lib.rs | ||
399 | struct Foo; | ||
400 | impl Foo { | ||
401 | fn frobnicate() { } | ||
402 | } | ||
403 | |||
404 | fn bar(foo: &Foo) { | ||
405 | Foo::frobnicate<|>(); | ||
406 | } | ||
407 | ", | ||
408 | "frobnicate FN_DEF FileId(1) [27; 47) [30; 40)", | ||
409 | ); | ||
410 | } | ||
411 | |||
412 | #[test] | ||
413 | fn goto_definition_works_for_ufcs_trait_methods_through_traits() { | ||
414 | check_goto( | ||
415 | " | ||
416 | //- /lib.rs | ||
417 | trait Foo { | ||
418 | fn frobnicate(); | ||
419 | } | ||
420 | |||
421 | fn bar() { | ||
422 | Foo::frobnicate<|>(); | ||
423 | } | ||
424 | ", | ||
425 | "frobnicate FN_DEF FileId(1) [16; 32) [19; 29)", | ||
426 | ); | ||
427 | } | ||
428 | |||
429 | #[test] | ||
430 | fn goto_definition_works_for_ufcs_trait_methods_through_self() { | ||
431 | check_goto( | ||
432 | " | ||
433 | //- /lib.rs | ||
434 | struct Foo; | ||
435 | trait Trait { | ||
436 | fn frobnicate(); | ||
437 | } | ||
438 | impl Trait for Foo {} | ||
439 | |||
440 | fn bar() { | ||
441 | Foo::frobnicate<|>(); | ||
442 | } | ||
443 | ", | ||
444 | "frobnicate FN_DEF FileId(1) [30; 46) [33; 43)", | ||
445 | ); | ||
446 | } | ||
447 | |||
393 | #[test] | 448 | #[test] |
394 | fn goto_definition_on_self() { | 449 | fn goto_definition_on_self() { |
395 | check_goto( | 450 | check_goto( |