From 9e71dd9799879fc9070f8717f8711fba5dae490a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 28 May 2021 02:40:40 +0200 Subject: Only complete modules in empty use-statements --- .../src/completions/unqualified_path.rs | 30 ++++++++++++---------- crates/ide_completion/src/context.rs | 4 +++ crates/ide_completion/src/patterns.rs | 7 +++++ 3 files changed, 27 insertions(+), 14 deletions(-) (limited to 'crates/ide_completion') diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs index c901b358b..ede07f605 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs @@ -1,7 +1,6 @@ //! Completion of names from the current scope, e.g. locals and imported items. use hir::ScopeDef; -use syntax::AstNode; use crate::{CompletionContext, Completions}; @@ -24,6 +23,15 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC return; } + if ctx.expects_use_tree() { + cov_mark::hit!(only_completes_modules_in_import); + ctx.scope.process_all_names(&mut |name, res| { + if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res { + acc.add_resolution(ctx, name.to_string(), &res); + } + }); + return; + } if let Some(hir::Adt::Enum(e)) = ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt()) { @@ -37,14 +45,6 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC cov_mark::hit!(skip_lifetime_completion); return; } - if ctx.use_item_syntax.is_some() { - if let (ScopeDef::Unknown, Some(name_ref)) = (&res, &ctx.name_ref_syntax) { - if name_ref.syntax().text() == name.to_string().as_str() { - cov_mark::hit!(self_fulfilling_completion); - return; - } - } - } acc.add_resolution(ctx, name.to_string(), &res); }); } @@ -68,15 +68,17 @@ mod tests { } #[test] - fn self_fulfilling_completion() { - cov_mark::check!(self_fulfilling_completion); + fn only_completes_modules_in_import() { + cov_mark::check!(only_completes_modules_in_import); check( r#" -use foo$0 -use std::collections; +use f$0 + +struct Foo; +mod foo {} "#, expect![[r#" - ?? collections + md foo "#]], ); } diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs index fbef54408..923e35dbb 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs @@ -276,6 +276,10 @@ impl<'a> CompletionContext<'a> { ) } + pub(crate) fn expects_use_tree(&self) -> bool { + matches!(self.completion_location, Some(ImmediateLocation::Use)) + } + pub(crate) fn expects_non_trait_assoc_item(&self) -> bool { matches!(self.completion_location, Some(ImmediateLocation::Impl)) } diff --git a/crates/ide_completion/src/patterns.rs b/crates/ide_completion/src/patterns.rs index 19e42ba43..7bae7d12c 100644 --- a/crates/ide_completion/src/patterns.rs +++ b/crates/ide_completion/src/patterns.rs @@ -14,6 +14,7 @@ use crate::test_utils::{check_pattern_is_applicable, check_pattern_is_not_applic /// Direct parent container of the cursor position #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub(crate) enum ImmediateLocation { + Use, Impl, Trait, RecordField, @@ -58,6 +59,7 @@ pub(crate) fn determine_location(tok: SyntaxToken) -> Option let res = match_ast! { match parent { ast::IdentPat(_it) => ImmediateLocation::IdentPat, + ast::Use(_it) => ImmediateLocation::Use, ast::BlockExpr(_it) => ImmediateLocation::BlockExpr, ast::SourceFile(_it) => ImmediateLocation::ItemList, ast::ItemList(_it) => ImmediateLocation::ItemList, @@ -87,6 +89,11 @@ fn test_has_trait_parent() { check_location(r"trait A { f$0 }", ImmediateLocation::Trait); } +#[test] +fn test_has_use_parent() { + check_location(r"use f$0", ImmediateLocation::Use); +} + #[test] fn test_has_impl_parent() { check_location(r"impl A { f$0 }", ImmediateLocation::Impl); -- cgit v1.2.3