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_hir/src/lib.rs | 3 +- crates/ra_hir/src/source_binder.rs | 8 +++-- crates/ra_hir/src/ty/method_resolution.rs | 2 +- crates/ra_ide_api/src/completion/complete_dot.rs | 22 ++++++++----- crates/ra_ide_api/src/completion/complete_path.rs | 38 ++++++++++++++++++++--- 5 files changed, 56 insertions(+), 17 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 40f5562b4..4cace432e 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -76,7 +76,8 @@ pub use crate::{ resolve::ScopeDef, source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, ty::{ - display::HirDisplay, ApplicationTy, CallableDef, Substs, TraitRef, Ty, TypeCtor, TypeWalk, + display::HirDisplay, method_resolution::LookupMode, ApplicationTy, CallableDef, Substs, + TraitRef, Ty, TypeCtor, TypeWalk, }, }; diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 0398806fd..82e6eb852 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -27,7 +27,7 @@ use crate::{ }, ids::LocationCtx, resolve::{ScopeDef, TypeNs, ValueNs}, - ty::method_resolution::implements_trait, + ty::method_resolution::{self, implements_trait}, AssocItem, Const, DefWithBody, Either, Enum, FromSource, Function, HasBody, HirFileId, MacroDef, Module, Name, Path, Resolver, Static, Struct, Ty, }; @@ -327,17 +327,19 @@ impl SourceAnalyzer { db: &impl HirDatabase, ty: Ty, name: Option<&Name>, + mode: method_resolution::LookupMode, callback: impl FnMut(&Ty, AssocItem) -> Option, ) -> Option { // There should be no inference vars in types passed here // FIXME check that? + // FIXME replace Unknown by bound vars here let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; - crate::ty::method_resolution::iterate_method_candidates( + method_resolution::iterate_method_candidates( &canonical, db, &self.resolver, name, - crate::ty::method_resolution::LookupMode::MethodCall, + mode, callback, ) } diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 43b485ec0..9caff422f 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -176,7 +176,7 @@ pub(crate) fn lookup_method( } #[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub(crate) enum LookupMode { +pub enum LookupMode { MethodCall, Path, } 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