diff options
Diffstat (limited to 'crates/ra_ide_api/src')
-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( |