aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api/src')
-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(