Skip to content

Commit

Permalink
Auto merge of rust-lang#12168 - Veykril:completion-rev, r=Veykril
Browse files Browse the repository at this point in the history
internal: Remove unqualified_path completions module
  • Loading branch information
bors committed May 5, 2022
2 parents cc9ae2b + 0c4e23b commit dd3f5e0
Show file tree
Hide file tree
Showing 15 changed files with 769 additions and 732 deletions.
2 changes: 1 addition & 1 deletion crates/hir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ pub use crate::{
UnresolvedModule, UnresolvedProcMacro,
},
has_source::HasSource,
semantics::{PathResolution, Semantics, SemanticsScope, TypeInfo},
semantics::{PathResolution, Semantics, SemanticsScope, TypeInfo, VisibleTraits},
};

// Be careful with these re-exports.
Expand Down
8 changes: 5 additions & 3 deletions crates/hir/src/semantics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1370,10 +1370,10 @@ impl<'a> SemanticsScope<'a> {
&self.resolver
}

/// Note: `FxHashSet<TraitId>` should be treated as an opaque type, passed into `Type
pub fn visible_traits(&self) -> FxHashSet<TraitId> {
/// Note: `VisibleTraits` should be treated as an opaque type, passed into `Type
pub fn visible_traits(&self) -> VisibleTraits {
let resolver = &self.resolver;
resolver.traits_in_scope(self.db.upcast())
VisibleTraits(resolver.traits_in_scope(self.db.upcast()))
}

pub fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef)) {
Expand Down Expand Up @@ -1424,3 +1424,5 @@ impl<'a> SemanticsScope<'a> {
)
}
}

pub struct VisibleTraits(pub FxHashSet<TraitId>);
Original file line number Diff line number Diff line change
Expand Up @@ -148,14 +148,13 @@ fn is_ref_and_impls_iter_method(
let ty = sema.type_of_expr(&expr_behind_ref)?.adjusted();
let scope = sema.scope(iterable.syntax())?;
let krate = scope.krate();
let traits_in_scope = scope.visible_traits();
let iter_trait = FamousDefs(sema, krate).core_iter_Iterator()?;

let has_wanted_method = ty
.iterate_method_candidates(
sema.db,
&scope,
&traits_in_scope,
&scope.visible_traits().0,
None,
Some(&wanted_method),
|func| {
Expand Down
12 changes: 8 additions & 4 deletions crates/ide-assists/src/handlers/generate_is_empty_from_len.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,14 @@ fn get_impl_method(

let scope = ctx.sema.scope(impl_.syntax())?;
let ty = impl_def.self_ty(db);
let traits_in_scope = scope.visible_traits();
ty.iterate_method_candidates(db, &scope, &traits_in_scope, None, Some(fn_name), |func| {
Some(func)
})
ty.iterate_method_candidates(
db,
&scope,
&scope.visible_traits().0,
None,
Some(fn_name),
|func| Some(func),
)
}

#[cfg(test)]
Expand Down
1 change: 0 additions & 1 deletion crates/ide-completion/src/completions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ pub(crate) mod lifetime;
pub(crate) mod mod_;
pub(crate) mod pattern;
pub(crate) mod postfix;
pub(crate) mod qualified_path;
pub(crate) mod record;
pub(crate) mod snippet;
pub(crate) mod trait_impl;
Expand Down
11 changes: 1 addition & 10 deletions crates/ide-completion/src/completions/dot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,10 @@ fn complete_methods(
mut f: impl FnMut(hir::Function),
) {
let mut seen_methods = FxHashSet::default();
let mut traits_in_scope = ctx.scope.visible_traits();

// Remove drop from the environment as calling `Drop::drop` is not allowed
if let Some(drop_trait) = ctx.famous_defs().core_ops_Drop() {
cov_mark::hit!(dot_remove_drop_trait);
traits_in_scope.remove(&drop_trait.into());
}

receiver.iterate_method_candidates(
ctx.db,
&ctx.scope,
&traits_in_scope,
&ctx.traits_in_scope().0,
Some(ctx.module),
None,
|func| {
Expand Down Expand Up @@ -758,7 +750,6 @@ fn main() {

#[test]
fn postfix_drop_completion() {
cov_mark::check!(dot_remove_drop_trait);
cov_mark::check!(postfix_drop_completion);
check_edit(
"drop",
Expand Down
145 changes: 136 additions & 9 deletions crates/ide-completion/src/completions/expr.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Completion of names from the current scope in expression position.
use hir::ScopeDef;
use ide_db::FxHashSet;

use crate::{
context::{PathCompletionCtx, PathKind, PathQualifierCtx},
Expand All @@ -20,8 +21,129 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext)
_ => return,
};

let scope_def_applicable = |def| {
use hir::{GenericParam::*, ModuleDef::*};
match def {
ScopeDef::GenericParam(LifetimeParam(_)) | ScopeDef::Label(_) => false,
// Don't suggest attribute macros and derives.
ScopeDef::ModuleDef(Macro(mac)) => mac.is_fn_like(ctx.db),
_ => true,
}
};

match qualifier {
Some(PathQualifierCtx { .. }) => return,
Some(PathQualifierCtx { is_infer_qualifier, resolution, .. }) => {
if *is_infer_qualifier {
ctx.traits_in_scope()
.0
.into_iter()
.flat_map(|it| hir::Trait::from(it).items(ctx.sema.db))
.for_each(|item| add_assoc_item(acc, ctx, item));
return;
}
let resolution = match resolution {
Some(it) => it,
None => return,
};
// Add associated types on type parameters and `Self`.
ctx.scope.assoc_type_shorthand_candidates(resolution, |_, alias| {
acc.add_type_alias(ctx, alias);
None::<()>
});
match resolution {
hir::PathResolution::Def(hir::ModuleDef::Module(module)) => {
let module_scope = module.scope(ctx.db, Some(ctx.module));
for (name, def) in module_scope {
if scope_def_applicable(def) {
acc.add_resolution(ctx, name, def);
}
}
}

hir::PathResolution::Def(
def @ (hir::ModuleDef::Adt(_)
| hir::ModuleDef::TypeAlias(_)
| hir::ModuleDef::BuiltinType(_)),
) => {
if let &hir::ModuleDef::Adt(hir::Adt::Enum(e)) = def {
add_enum_variants(acc, ctx, e);
}
let ty = match def {
hir::ModuleDef::Adt(adt) => adt.ty(ctx.db),
hir::ModuleDef::TypeAlias(a) => {
let ty = a.ty(ctx.db);
if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
cov_mark::hit!(completes_variant_through_alias);
add_enum_variants(acc, ctx, e);
}
ty
}
hir::ModuleDef::BuiltinType(builtin) => {
cov_mark::hit!(completes_primitive_assoc_const);
builtin.ty(ctx.db)
}
_ => unreachable!(),
};

// XXX: For parity with Rust bug #22519, this does not complete Ty::AssocType.
// (where AssocType is defined on a trait, not an inherent impl)

ty.iterate_path_candidates(
ctx.db,
&ctx.scope,
&ctx.traits_in_scope().0,
Some(ctx.module),
None,
|item| {
add_assoc_item(acc, ctx, item);
None::<()>
},
);

// Iterate assoc types separately
ty.iterate_assoc_items(ctx.db, ctx.krate, |item| {
if let hir::AssocItem::TypeAlias(ty) = item {
acc.add_type_alias(ctx, ty)
}
None::<()>
});
}
hir::PathResolution::Def(hir::ModuleDef::Trait(t)) => {
// Handles `Trait::assoc` as well as `<Ty as Trait>::assoc`.
for item in t.items(ctx.db) {
add_assoc_item(acc, ctx, item);
}
}
hir::PathResolution::TypeParam(_) | hir::PathResolution::SelfType(_) => {
let ty = match resolution {
hir::PathResolution::TypeParam(param) => param.ty(ctx.db),
hir::PathResolution::SelfType(impl_def) => impl_def.self_ty(ctx.db),
_ => return,
};

if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
add_enum_variants(acc, ctx, e);
}
let mut seen = FxHashSet::default();
ty.iterate_path_candidates(
ctx.db,
&ctx.scope,
&ctx.traits_in_scope().0,
Some(ctx.module),
None,
|item| {
// We might iterate candidates of a trait multiple times here, so deduplicate
// them.
if seen.insert(item) {
add_assoc_item(acc, ctx, item);
}
None::<()>
},
);
}
_ => (),
}
}
None if is_absolute_path => acc.add_crate_roots(ctx),
None => {
acc.add_nameref_keywords_with_colon(ctx);
Expand All @@ -33,17 +155,22 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext)
});
}
ctx.process_all_names(&mut |name, def| {
use hir::{GenericParam::*, ModuleDef::*};
let add_resolution = match def {
ScopeDef::GenericParam(LifetimeParam(_)) | ScopeDef::Label(_) => false,
// Don't suggest attribute macros and derives.
ScopeDef::ModuleDef(Macro(mac)) => mac.is_fn_like(ctx.db),
_ => true,
};
if add_resolution {
if scope_def_applicable(def) {
acc.add_resolution(ctx, name, def);
}
});
}
}
}

fn add_assoc_item(acc: &mut Completions, ctx: &CompletionContext, item: hir::AssocItem) {
match item {
hir::AssocItem::Function(func) => acc.add_function(ctx, func, None),
hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
}
}

fn add_enum_variants(acc: &mut Completions, ctx: &CompletionContext, e: hir::Enum) {
e.variants(ctx.db).into_iter().for_each(|variant| acc.add_enum_variant(ctx, variant, None));
}
3 changes: 1 addition & 2 deletions crates/ide-completion/src/completions/pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,11 @@ fn pattern_path_completion(
_ => return,
};

let traits_in_scope = ctx.scope.visible_traits();
let mut seen = FxHashSet::default();
ty.iterate_path_candidates(
ctx.db,
&ctx.scope,
&traits_in_scope,
&ctx.scope.visible_traits().0,
Some(ctx.module),
None,
|item| {
Expand Down
Loading

0 comments on commit dd3f5e0

Please sign in to comment.