Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide_completion/src/completions/qualified_path.rs')
-rw-r--r--crates/ide_completion/src/completions/qualified_path.rs116
1 files changed, 21 insertions, 95 deletions
diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs
index 2c6899ff0c..cf78f7c1ad 100644
--- a/crates/ide_completion/src/completions/qualified_path.rs
+++ b/crates/ide_completion/src/completions/qualified_path.rs
@@ -1,14 +1,12 @@
//! Completion of paths, i.e. `some::prefix::$0`.
-use std::iter;
-
use hir::{ScopeDef, Trait};
use rustc_hash::FxHashSet;
-use syntax::{ast, AstNode};
+use syntax::ast;
use crate::{
- completions::{module_or_attr, module_or_fn_macro},
- context::{PathCompletionContext, PathKind},
+ completions::module_or_fn_macro,
+ context::{PathCompletionCtx, PathKind},
patterns::ImmediateLocation,
CompletionContext, Completions,
};
@@ -17,21 +15,19 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
if ctx.is_path_disallowed() || ctx.has_impl_or_trait_prev_sibling() {
return;
}
- let (path, use_tree_parent, kind) = match ctx.path_context {
+ if ctx.pattern_ctx.is_some() {
+ return;
+ }
+ let (qualifier, kind) = match ctx.path_context {
// let ... else, syntax would come in really handy here right now
- Some(PathCompletionContext {
- qualifier: Some(ref qualifier),
- use_tree_parent,
- kind,
- ..
- }) => (qualifier, use_tree_parent, kind),
+ Some(PathCompletionCtx { qualifier: Some(ref qualifier), kind, .. }) => (qualifier, kind),
_ => return,
};
// special case `<_>::$0` as this doesn't resolve to anything.
- if path.qualifier().is_none() {
+ if qualifier.path.qualifier().is_none() {
if matches!(
- path.segment().and_then(|it| it.kind()),
+ qualifier.path.segment().and_then(|it| it.kind()),
Some(ast::PathSegmentKind::Type {
type_ref: Some(ast::Type::InferType(_)),
trait_ref: None,
@@ -47,17 +43,15 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
}
}
- let resolution = match ctx.sema.resolve_path(path) {
+ let resolution = match &qualifier.resolution {
Some(res) => res,
None => return,
};
- let context_module = ctx.module;
-
match ctx.completion_location {
Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
- for (name, def) in module.scope(ctx.db, context_module) {
+ for (name, def) in module.scope(ctx.db, ctx.module) {
if let Some(def) = module_or_fn_macro(def) {
acc.add_resolution(ctx, name, def);
}
@@ -69,78 +63,22 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
}
match kind {
- // Complete next child module that comes after the qualified module which is still our parent
- Some(PathKind::Vis { .. }) => {
- if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
- if let Some(current_module) = ctx.module {
- let next_towards_current = current_module
- .path_to_root(ctx.db)
- .into_iter()
- .take_while(|&it| it != module)
- .next();
- if let Some(next) = next_towards_current {
- if let Some(name) = next.name(ctx.db) {
- cov_mark::hit!(visibility_qualified);
- acc.add_resolution(ctx, name, ScopeDef::ModuleDef(next.into()));
- }
- }
- }
- }
- return;
- }
- Some(PathKind::Attr) => {
- if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
- for (name, def) in module.scope(ctx.db, context_module) {
- if let Some(def) = module_or_attr(def) {
- acc.add_resolution(ctx, name, def);
- }
- }
- }
+ Some(PathKind::Pat | PathKind::Attr { .. } | PathKind::Vis { .. } | PathKind::Use) => {
return;
}
- Some(PathKind::Use) => {
- if iter::successors(Some(path.clone()), |p| p.qualifier())
- .all(|p| p.segment().and_then(|s| s.super_token()).is_some())
- {
- acc.add_keyword(ctx, "super::");
- }
- // only show `self` in a new use-tree when the qualifier doesn't end in self
- if use_tree_parent
- && !matches!(
- path.segment().and_then(|it| it.kind()),
- Some(ast::PathSegmentKind::SelfKw)
- )
- {
- acc.add_keyword(ctx, "self");
- }
+ _ => {
+ // Add associated types on type parameters and `Self`.
+ ctx.scope.assoc_type_shorthand_candidates(&resolution, |_, alias| {
+ acc.add_type_alias(ctx, alias);
+ None::<()>
+ });
}
- _ => (),
- }
-
- if !matches!(kind, Some(PathKind::Pat)) {
- // 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, context_module);
+ let module_scope = module.scope(ctx.db, ctx.module);
for (name, def) in module_scope {
- if let Some(PathKind::Use) = kind {
- if let ScopeDef::Unknown = def {
- if let Some(ast::NameLike::NameRef(name_ref)) = ctx.name_syntax.as_ref() {
- if name_ref.syntax().text() == name.to_smol_str().as_str() {
- // for `use self::foo$0`, don't suggest `foo` as a completion
- cov_mark::hit!(dont_complete_current_use);
- continue;
- }
- }
- }
- }
-
let add_resolution = match def {
// Don't suggest attribute macros and derives.
ScopeDef::MacroDef(mac) => mac.is_fn_like(),
@@ -168,7 +106,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
| hir::ModuleDef::TypeAlias(_)
| hir::ModuleDef::BuiltinType(_)),
) => {
- if let hir::ModuleDef::Adt(hir::Adt::Enum(e)) = def {
+ if let &hir::ModuleDef::Adt(hir::Adt::Enum(e)) = def {
add_enum_variants(acc, ctx, e);
}
let ty = match def {
@@ -623,18 +561,6 @@ fn foo() {
}
#[test]
- fn dont_complete_attr() {
- check(
- r#"
-mod foo { pub struct Foo; }
-#[foo::$0]
-fn f() {}
-"#,
- expect![[""]],
- );
- }
-
- #[test]
fn completes_variant_through_self() {
check(
r#"