about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-05-28 00:43:16 +0000
committerGitHub <noreply@github.com>2021-05-28 00:43:16 +0000
commit3a1598c3bcbf089239c2fdff698b9c02670362b3 (patch)
tree81eed23ea0f4c54e842a6128efd25b1c51d3304b
parent5b4589f4747f242c038f19f5f2b51b2e03f93252 (diff)
parent9e71dd9799879fc9070f8717f8711fba5dae490a (diff)
downloadrust-3a1598c3bcbf089239c2fdff698b9c02670362b3.tar.gz
rust-3a1598c3bcbf089239c2fdff698b9c02670362b3.zip
Merge #9032
9032: Only complete modules in empty use-statements r=Veykril a=Veykril

bors r+
Part of #8518

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
-rw-r--r--crates/ide_completion/src/completions/unqualified_path.rs30
-rw-r--r--crates/ide_completion/src/context.rs4
-rw-r--r--crates/ide_completion/src/patterns.rs7
3 files changed, 27 insertions, 14 deletions
diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs
index c901b358b2e..ede07f605f5 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 fbef5440850..923e35dbb98 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 19e42ba432e..7bae7d12c37 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<ImmediateLocation>
     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,
@@ -88,6 +90,11 @@ fn test_has_trait_parent() {
 }
 
 #[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);
 }