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.rs | 116 |
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#" |