about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/ide-assists/src/handlers/expand_glob_import.rs162
1 files changed, 149 insertions, 13 deletions
diff --git a/crates/ide-assists/src/handlers/expand_glob_import.rs b/crates/ide-assists/src/handlers/expand_glob_import.rs
index 5c435dd9c29..3aff5c9144f 100644
--- a/crates/ide-assists/src/handlers/expand_glob_import.rs
+++ b/crates/ide-assists/src/handlers/expand_glob_import.rs
@@ -1,5 +1,5 @@
 use either::Either;
-use hir::{AssocItem, HasVisibility, Module, ModuleDef, Name, PathResolution, ScopeDef};
+use hir::{AssocItem, Enum, HasVisibility, Module, ModuleDef, Name, PathResolution, ScopeDef};
 use ide_db::{
     defs::{Definition, NameRefClass},
     search::SearchScope,
@@ -45,7 +45,8 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext<'_>) ->
     let use_tree = star.parent().and_then(ast::UseTree::cast)?;
     let (parent, mod_path) = find_parent_and_path(&star)?;
     let target_module = match ctx.sema.resolve_path(&mod_path)? {
-        PathResolution::Def(ModuleDef::Module(it)) => it,
+        PathResolution::Def(ModuleDef::Module(it)) => Expandable::Module(it),
+        PathResolution::Def(ModuleDef::Adt(hir::Adt::Enum(e))) => Expandable::Enum(e),
         _ => return None,
     };
 
@@ -90,6 +91,11 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext<'_>) ->
     )
 }
 
+enum Expandable {
+    Module(Module),
+    Enum(Enum),
+}
+
 fn find_parent_and_path(
     star: &SyntaxToken,
 ) -> Option<(Either<ast::UseTree, ast::UseTreeList>, ast::Path)> {
@@ -168,23 +174,59 @@ impl Refs {
     }
 }
 
-fn find_refs_in_mod(ctx: &AssistContext<'_>, module: Module, visible_from: Module) -> Option<Refs> {
-    if !is_mod_visible_from(ctx, module, visible_from) {
+fn find_refs_in_mod(
+    ctx: &AssistContext<'_>,
+    expandable: Expandable,
+    visible_from: Module,
+) -> Option<Refs> {
+    if !is_expandable_visible_from(ctx, &expandable, visible_from) {
         return None;
     }
 
-    let module_scope = module.scope(ctx.db(), Some(visible_from));
-    let refs = module_scope.into_iter().filter_map(|(n, d)| Ref::from_scope_def(n, d)).collect();
-    Some(Refs(refs))
+    match expandable {
+        Expandable::Module(module) => {
+            let module_scope = module.scope(ctx.db(), Some(visible_from));
+            let refs =
+                module_scope.into_iter().filter_map(|(n, d)| Ref::from_scope_def(n, d)).collect();
+            Some(Refs(refs))
+        }
+        Expandable::Enum(enm) => Some(Refs(
+            enm.variants(ctx.db())
+                .into_iter()
+                .map(|v| Ref { visible_name: v.name(ctx.db()), def: Definition::Variant(v) })
+                .collect(),
+        )),
+    }
 }
 
-fn is_mod_visible_from(ctx: &AssistContext<'_>, module: Module, from: Module) -> bool {
-    match module.parent(ctx.db()) {
-        Some(parent) => {
-            module.visibility(ctx.db()).is_visible_from(ctx.db(), from.into())
-                && is_mod_visible_from(ctx, parent, from)
+fn is_expandable_visible_from(
+    ctx: &AssistContext<'_>,
+    expandable: &Expandable,
+    from: Module,
+) -> bool {
+    fn is_mod_visible_from(ctx: &AssistContext<'_>, module: Module, from: Module) -> bool {
+        match module.parent(ctx.db()) {
+            Some(parent) => {
+                module.visibility(ctx.db()).is_visible_from(ctx.db(), from.into())
+                    && is_mod_visible_from(ctx, parent, from)
+            }
+            None => true,
+        }
+    }
+
+    match expandable {
+        Expandable::Module(module) => match module.parent(ctx.db()) {
+            Some(parent) => {
+                module.visibility(ctx.db()).is_visible_from(ctx.db(), from.into())
+                    && is_mod_visible_from(ctx, parent, from)
+            }
+            None => true,
+        },
+        Expandable::Enum(enm) => {
+            let module = enm.module(ctx.db());
+            enm.visibility(ctx.db()).is_visible_from(ctx.db(), from.into())
+                && is_mod_visible_from(ctx, module, from)
         }
-        None => true,
     }
 }
 
@@ -897,4 +939,98 @@ struct Baz {
 ",
         );
     }
+
+    #[test]
+    fn test_support_for_enums() {
+        check_assist(
+            expand_glob_import,
+            r#"
+mod foo {
+    pub enum Foo {
+        Bar,
+        Baz,
+    }
+}
+
+use foo::Foo;
+use foo::Foo::*$0;
+
+struct Strukt {
+    bar: Foo,
+}
+
+fn main() {
+    let s: Strukt = Strukt { bar: Bar };
+}"#,
+            r#"
+mod foo {
+    pub enum Foo {
+        Bar,
+        Baz,
+    }
+}
+
+use foo::Foo;
+use foo::Foo::Bar;
+
+struct Strukt {
+    bar: Foo,
+}
+
+fn main() {
+    let s: Strukt = Strukt { bar: Bar };
+}"#,
+        )
+    }
+
+    #[test]
+    fn test_expanding_multiple_variants_at_once() {
+        check_assist(
+            expand_glob_import,
+            r#"
+mod foo {
+    pub enum Foo {
+        Bar,
+        Baz,
+    }
+}
+
+mod abc {
+    use super::foo;
+    use super::foo::Foo::*$0;
+
+    struct Strukt {
+        baz: foo::Foo,
+        bar: foo::Foo,
+    }
+
+    fn trying_calling() {
+        let s: Strukt = Strukt { bar: Bar , baz : Baz };
+    }
+
+}"#,
+            r#"
+mod foo {
+    pub enum Foo {
+        Bar,
+        Baz,
+    }
+}
+
+mod abc {
+    use super::foo;
+    use super::foo::Foo::{Bar, Baz};
+
+    struct Strukt {
+        baz: foo::Foo,
+        bar: foo::Foo,
+    }
+
+    fn trying_calling() {
+        let s: Strukt = Strukt { bar: Bar , baz : Baz };
+    }
+
+}"#,
+        )
+    }
 }