|
1 | 1 | use either::Either;
|
2 |
| -use hir::{AssocItem, HasVisibility, Module, ModuleDef, Name, PathResolution, ScopeDef}; |
| 2 | +use hir::{AssocItem, Enum, HasVisibility, Module, ModuleDef, Name, PathResolution, ScopeDef}; |
3 | 3 | use ide_db::{
|
4 | 4 | defs::{Definition, NameRefClass},
|
5 | 5 | search::SearchScope,
|
@@ -45,7 +45,8 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext<'_>) ->
|
45 | 45 | let use_tree = star.parent().and_then(ast::UseTree::cast)?;
|
46 | 46 | let (parent, mod_path) = find_parent_and_path(&star)?;
|
47 | 47 | let target_module = match ctx.sema.resolve_path(&mod_path)? {
|
48 |
| - PathResolution::Def(ModuleDef::Module(it)) => it, |
| 48 | + PathResolution::Def(ModuleDef::Module(it)) => Expandable::Module(it), |
| 49 | + PathResolution::Def(ModuleDef::Adt(hir::Adt::Enum(e))) => Expandable::Enum(e), |
49 | 50 | _ => return None,
|
50 | 51 | };
|
51 | 52 |
|
@@ -90,6 +91,11 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext<'_>) ->
|
90 | 91 | )
|
91 | 92 | }
|
92 | 93 |
|
| 94 | +enum Expandable { |
| 95 | + Module(Module), |
| 96 | + Enum(Enum), |
| 97 | +} |
| 98 | + |
93 | 99 | fn find_parent_and_path(
|
94 | 100 | star: &SyntaxToken,
|
95 | 101 | ) -> Option<(Either<ast::UseTree, ast::UseTreeList>, ast::Path)> {
|
@@ -168,23 +174,59 @@ impl Refs {
|
168 | 174 | }
|
169 | 175 | }
|
170 | 176 |
|
171 |
| -fn find_refs_in_mod(ctx: &AssistContext<'_>, module: Module, visible_from: Module) -> Option<Refs> { |
172 |
| - if !is_mod_visible_from(ctx, module, visible_from) { |
| 177 | +fn find_refs_in_mod( |
| 178 | + ctx: &AssistContext<'_>, |
| 179 | + expandable: Expandable, |
| 180 | + visible_from: Module, |
| 181 | +) -> Option<Refs> { |
| 182 | + if !is_expandable_visible_from(ctx, &expandable, visible_from) { |
173 | 183 | return None;
|
174 | 184 | }
|
175 | 185 |
|
176 |
| - let module_scope = module.scope(ctx.db(), Some(visible_from)); |
177 |
| - let refs = module_scope.into_iter().filter_map(|(n, d)| Ref::from_scope_def(n, d)).collect(); |
178 |
| - Some(Refs(refs)) |
| 186 | + match expandable { |
| 187 | + Expandable::Module(module) => { |
| 188 | + let module_scope = module.scope(ctx.db(), Some(visible_from)); |
| 189 | + let refs = |
| 190 | + module_scope.into_iter().filter_map(|(n, d)| Ref::from_scope_def(n, d)).collect(); |
| 191 | + Some(Refs(refs)) |
| 192 | + } |
| 193 | + Expandable::Enum(enm) => Some(Refs( |
| 194 | + enm.variants(ctx.db()) |
| 195 | + .into_iter() |
| 196 | + .map(|v| Ref { visible_name: v.name(ctx.db()), def: Definition::Variant(v) }) |
| 197 | + .collect(), |
| 198 | + )), |
| 199 | + } |
179 | 200 | }
|
180 | 201 |
|
181 |
| -fn is_mod_visible_from(ctx: &AssistContext<'_>, module: Module, from: Module) -> bool { |
182 |
| - match module.parent(ctx.db()) { |
183 |
| - Some(parent) => { |
184 |
| - module.visibility(ctx.db()).is_visible_from(ctx.db(), from.into()) |
185 |
| - && is_mod_visible_from(ctx, parent, from) |
| 202 | +fn is_expandable_visible_from( |
| 203 | + ctx: &AssistContext<'_>, |
| 204 | + expandable: &Expandable, |
| 205 | + from: Module, |
| 206 | +) -> bool { |
| 207 | + fn is_mod_visible_from(ctx: &AssistContext<'_>, module: Module, from: Module) -> bool { |
| 208 | + match module.parent(ctx.db()) { |
| 209 | + Some(parent) => { |
| 210 | + module.visibility(ctx.db()).is_visible_from(ctx.db(), from.into()) |
| 211 | + && is_mod_visible_from(ctx, parent, from) |
| 212 | + } |
| 213 | + None => true, |
| 214 | + } |
| 215 | + } |
| 216 | + |
| 217 | + match expandable { |
| 218 | + Expandable::Module(module) => match module.parent(ctx.db()) { |
| 219 | + Some(parent) => { |
| 220 | + module.visibility(ctx.db()).is_visible_from(ctx.db(), from.into()) |
| 221 | + && is_mod_visible_from(ctx, parent, from) |
| 222 | + } |
| 223 | + None => true, |
| 224 | + }, |
| 225 | + Expandable::Enum(enm) => { |
| 226 | + let module = enm.module(ctx.db()); |
| 227 | + enm.visibility(ctx.db()).is_visible_from(ctx.db(), from.into()) |
| 228 | + && is_mod_visible_from(ctx, module, from) |
186 | 229 | }
|
187 |
| - None => true, |
188 | 230 | }
|
189 | 231 | }
|
190 | 232 |
|
@@ -897,4 +939,98 @@ struct Baz {
|
897 | 939 | ",
|
898 | 940 | );
|
899 | 941 | }
|
| 942 | + |
| 943 | + #[test] |
| 944 | + fn test_support_for_enums() { |
| 945 | + check_assist( |
| 946 | + expand_glob_import, |
| 947 | + r#" |
| 948 | +mod foo { |
| 949 | + pub enum Foo { |
| 950 | + Bar, |
| 951 | + Baz, |
| 952 | + } |
| 953 | +} |
| 954 | +
|
| 955 | +use foo::Foo; |
| 956 | +use foo::Foo::*$0; |
| 957 | +
|
| 958 | +struct Strukt { |
| 959 | + bar: Foo, |
| 960 | +} |
| 961 | +
|
| 962 | +fn main() { |
| 963 | + let s: Strukt = Strukt { bar: Bar }; |
| 964 | +}"#, |
| 965 | + r#" |
| 966 | +mod foo { |
| 967 | + pub enum Foo { |
| 968 | + Bar, |
| 969 | + Baz, |
| 970 | + } |
| 971 | +} |
| 972 | +
|
| 973 | +use foo::Foo; |
| 974 | +use foo::Foo::Bar; |
| 975 | +
|
| 976 | +struct Strukt { |
| 977 | + bar: Foo, |
| 978 | +} |
| 979 | +
|
| 980 | +fn main() { |
| 981 | + let s: Strukt = Strukt { bar: Bar }; |
| 982 | +}"#, |
| 983 | + ) |
| 984 | + } |
| 985 | + |
| 986 | + #[test] |
| 987 | + fn test_expanding_multiple_variants_at_once() { |
| 988 | + check_assist( |
| 989 | + expand_glob_import, |
| 990 | + r#" |
| 991 | +mod foo { |
| 992 | + pub enum Foo { |
| 993 | + Bar, |
| 994 | + Baz, |
| 995 | + } |
| 996 | +} |
| 997 | +
|
| 998 | +mod abc { |
| 999 | + use super::foo; |
| 1000 | + use super::foo::Foo::*$0; |
| 1001 | +
|
| 1002 | + struct Strukt { |
| 1003 | + baz: foo::Foo, |
| 1004 | + bar: foo::Foo, |
| 1005 | + } |
| 1006 | +
|
| 1007 | + fn trying_calling() { |
| 1008 | + let s: Strukt = Strukt { bar: Bar , baz : Baz }; |
| 1009 | + } |
| 1010 | +
|
| 1011 | +}"#, |
| 1012 | + r#" |
| 1013 | +mod foo { |
| 1014 | + pub enum Foo { |
| 1015 | + Bar, |
| 1016 | + Baz, |
| 1017 | + } |
| 1018 | +} |
| 1019 | +
|
| 1020 | +mod abc { |
| 1021 | + use super::foo; |
| 1022 | + use super::foo::Foo::{Bar, Baz}; |
| 1023 | +
|
| 1024 | + struct Strukt { |
| 1025 | + baz: foo::Foo, |
| 1026 | + bar: foo::Foo, |
| 1027 | + } |
| 1028 | +
|
| 1029 | + fn trying_calling() { |
| 1030 | + let s: Strukt = Strukt { bar: Bar , baz : Baz }; |
| 1031 | + } |
| 1032 | +
|
| 1033 | +}"#, |
| 1034 | + ) |
| 1035 | + } |
900 | 1036 | }
|
0 commit comments