From c7cedea270c492e9a2c8b81c1312fda44fd8217e Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Thu, 31 Oct 2019 15:13:52 +0100 Subject: Record assoc item resolution --- crates/ra_ide_api/src/goto_definition.rs | 55 ++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'crates/ra_ide_api') 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 { "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)", ); } + + #[test] + fn goto_definition_works_for_ufcs_inherent_methods() { + check_goto( + " + //- /lib.rs + struct Foo; + impl Foo { + fn frobnicate() { } + } + + fn bar(foo: &Foo) { + Foo::frobnicate<|>(); + } + ", + "frobnicate FN_DEF FileId(1) [27; 47) [30; 40)", + ); + } + + #[test] + fn goto_definition_works_for_ufcs_trait_methods_through_traits() { + check_goto( + " + //- /lib.rs + trait Foo { + fn frobnicate(); + } + + fn bar() { + Foo::frobnicate<|>(); + } + ", + "frobnicate FN_DEF FileId(1) [16; 32) [19; 29)", + ); + } + + #[test] + fn goto_definition_works_for_ufcs_trait_methods_through_self() { + check_goto( + " + //- /lib.rs + struct Foo; + trait Trait { + fn frobnicate(); + } + impl Trait for Foo {} + + fn bar() { + Foo::frobnicate<|>(); + } + ", + "frobnicate FN_DEF FileId(1) [30; 46) [33; 43)", + ); + } + #[test] fn goto_definition_on_self() { check_goto( -- cgit v1.2.3 From 1173c3dab5f77a1afd367d547790dd82c558fe0d Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Thu, 31 Oct 2019 19:28:33 +0100 Subject: Refactor to unify with method resolution --- crates/ra_ide_api/src/completion/complete_dot.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'crates/ra_ide_api') diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index b4df6ee2a..7135f481d 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs @@ -58,10 +58,12 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { let mut seen_methods = FxHashSet::default(); - ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, func| { - let data = func.data(ctx.db); - if data.has_self_param() && seen_methods.insert(data.name().clone()) { - acc.add_function(ctx, func); + ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, item| { + if let hir::AssocItem::Function(func) = item { + let data = func.data(ctx.db); + if data.has_self_param() && seen_methods.insert(data.name().clone()) { + acc.add_function(ctx, func); + } } None::<()> }); -- cgit v1.2.3 From 5da941897d4ed092a219729d7980bd103907850a Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Thu, 31 Oct 2019 20:42:57 +0100 Subject: Add failing tests for trait assoc method completion --- crates/ra_ide_api/src/completion/complete_path.rs | 60 +++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'crates/ra_ide_api') diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index a58fdc036..b471787eb 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs @@ -558,6 +558,66 @@ mod tests { ); } + #[test] + fn completes_trait_associated_method_1() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /lib.rs + trait Trait { + /// A trait method + fn m(); + } + + fn foo() { let _ = Trait::<|> } + " + ), + @"[]" + ); + } + + #[test] + fn completes_trait_associated_method_2() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /lib.rs + trait Trait { + /// A trait method + fn m(); + } + + struct S; + impl Trait for S {} + + fn foo() { let _ = S::<|> } + " + ), + @"[]" + ); + } + + #[test] + fn completes_trait_associated_method_3() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /lib.rs + trait Trait { + /// A trait method + fn m(); + } + + struct S; + impl Trait for S {} + + fn foo() { let _ = ::<|> } + " + ), + @"[]" + ); + } + #[test] fn completes_type_alias() { assert_debug_snapshot!( -- cgit v1.2.3 From 79cb0a0dab5fd8e3e84cf4a3b927ec29d2b6e65c Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Thu, 31 Oct 2019 21:21:48 +0100 Subject: Complete trait assoc items --- crates/ra_ide_api/src/completion/complete_dot.rs | 22 ++++++++----- crates/ra_ide_api/src/completion/complete_path.rs | 38 ++++++++++++++++++++--- 2 files changed, 48 insertions(+), 12 deletions(-) (limited to 'crates/ra_ide_api') diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index 7135f481d..fe32e7366 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs @@ -58,15 +58,21 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { let mut seen_methods = FxHashSet::default(); - ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, item| { - if let hir::AssocItem::Function(func) = item { - let data = func.data(ctx.db); - if data.has_self_param() && seen_methods.insert(data.name().clone()) { - acc.add_function(ctx, func); + ctx.analyzer.iterate_method_candidates( + ctx.db, + receiver, + None, + hir::LookupMode::MethodCall, + |_ty, item| { + if let hir::AssocItem::Function(func) = item { + let data = func.data(ctx.db); + if data.has_self_param() && seen_methods.insert(data.name().clone()) { + acc.add_function(ctx, func); + } } - } - None::<()> - }); + None::<()> + }, + ); } #[cfg(test)] diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index b471787eb..940858342 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs @@ -50,9 +50,12 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db), _ => unreachable!(), }; - let krate = ctx.module.map(|m| m.krate()); - if let Some(krate) = krate { - ty.iterate_impl_items(ctx.db, krate, |item| { + ctx.analyzer.iterate_method_candidates( + ctx.db, + ty.clone(), + None, + hir::LookupMode::Path, + |_ty, item| { match item { hir::AssocItem::Function(func) => { let data = func.data(ctx.db); @@ -64,6 +67,18 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), } None::<()> + }, + ); + // Iterate assoc types separately + // FIXME: complete T::AssocType + let krate = ctx.module.map(|m| m.krate()); + if let Some(krate) = krate { + ty.iterate_impl_items(ctx.db, krate, |item| { + match item { + hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {} + hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), + } + None::<()> }); } } @@ -593,7 +608,22 @@ mod tests { fn foo() { let _ = S::<|> } " ), - @"[]" + @r###" + [ + CompletionItem { + label: "m()", + source_range: [99; 99), + delete: [99; 99), + insert: "m()$0", + kind: Function, + lookup: "m", + detail: "fn m()", + documentation: Documentation( + "A trait method", + ), + }, + ] + "### ); } -- cgit v1.2.3 From 77c26c2bf111314cc3be7ef100b6318a698c8089 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 1 Nov 2019 00:15:15 +0100 Subject: Complete items on traits as well --- crates/ra_ide_api/src/completion/complete_path.rs | 48 ++++++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) (limited to 'crates/ra_ide_api') diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index 940858342..2aec8eb26 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs @@ -82,6 +82,20 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { }); } } + hir::ModuleDef::Trait(t) => { + for item in t.items(ctx.db) { + match item { + hir::AssocItem::Function(func) => { + let data = func.data(ctx.db); + if !data.has_self_param() { + acc.add_function(ctx, func); + } + } + hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), + hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), + } + } + } _ => {} }; } @@ -587,7 +601,22 @@ mod tests { fn foo() { let _ = Trait::<|> } " ), - @"[]" + @r###" + [ + CompletionItem { + label: "m()", + source_range: [73; 73), + delete: [73; 73), + insert: "m()$0", + kind: Function, + lookup: "m", + detail: "fn m()", + documentation: Documentation( + "A trait method", + ), + }, + ] + "### ); } @@ -644,7 +673,22 @@ mod tests { fn foo() { let _ = ::<|> } " ), - @"[]" + @r###" + [ + CompletionItem { + label: "m()", + source_range: [110; 110), + delete: [110; 110), + insert: "m()$0", + kind: Function, + lookup: "m", + detail: "fn m()", + documentation: Documentation( + "A trait method", + ), + }, + ] + "### ); } -- cgit v1.2.3 From 895238088417b292e35705e72182ff8cc3ab6f63 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 1 Nov 2019 20:01:21 +0100 Subject: Change SourceAnalyzer method resoltion API --- crates/ra_ide_api/src/completion/complete_dot.rs | 22 ++++++------------ crates/ra_ide_api/src/completion/complete_path.rs | 28 +++++++++-------------- 2 files changed, 18 insertions(+), 32 deletions(-) (limited to 'crates/ra_ide_api') diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index fe32e7366..b4df6ee2a 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs @@ -58,21 +58,13 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { let mut seen_methods = FxHashSet::default(); - ctx.analyzer.iterate_method_candidates( - ctx.db, - receiver, - None, - hir::LookupMode::MethodCall, - |_ty, item| { - if let hir::AssocItem::Function(func) = item { - let data = func.data(ctx.db); - if data.has_self_param() && seen_methods.insert(data.name().clone()) { - acc.add_function(ctx, func); - } - } - None::<()> - }, - ); + ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, func| { + let data = func.data(ctx.db); + if data.has_self_param() && seen_methods.insert(data.name().clone()) { + acc.add_function(ctx, func); + } + None::<()> + }); } #[cfg(test)] diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index 2aec8eb26..9ac9768af 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs @@ -50,25 +50,19 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db), _ => unreachable!(), }; - ctx.analyzer.iterate_method_candidates( - ctx.db, - ty.clone(), - None, - hir::LookupMode::Path, - |_ty, item| { - match item { - hir::AssocItem::Function(func) => { - let data = func.data(ctx.db); - if !data.has_self_param() { - acc.add_function(ctx, func); - } + ctx.analyzer.iterate_path_candidates(ctx.db, ty.clone(), None, |_ty, item| { + match item { + hir::AssocItem::Function(func) => { + let data = func.data(ctx.db); + if !data.has_self_param() { + acc.add_function(ctx, func); } - hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), - hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), } - None::<()> - }, - ); + hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), + hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), + } + None::<()> + }); // Iterate assoc types separately // FIXME: complete T::AssocType let krate = ctx.module.map(|m| m.krate()); -- cgit v1.2.3