Complete trait assoc items

This commit is contained in:
Florian Diebold 2019-10-31 21:21:48 +01:00
parent 5da941897d
commit 79cb0a0dab
5 changed files with 56 additions and 17 deletions

View file

@ -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,
},
};

View file

@ -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<T>,
) -> Option<T> {
// 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,
)
}

View file

@ -176,7 +176,7 @@ pub(crate) fn lookup_method(
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub(crate) enum LookupMode {
pub enum LookupMode {
MethodCall,
Path,
}

View file

@ -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)]

View file

@ -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",
),
},
]
"###
);
}