aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-11-01 19:03:05 +0000
committerGitHub <[email protected]>2019-11-01 19:03:05 +0000
commit9db97820f4c1c38110175f4efda2702356a4199a (patch)
treef560ab731b9da35902d3da720e19731b51ab62df /crates/ra_ide_api
parented5212e1ac71e959d802a9a7ad28d06c8b18e022 (diff)
parent895238088417b292e35705e72182ff8cc3ab6f63 (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.rs142
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs55
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(