Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22385 from ChayimFriedman2/import-variant
fix: Autoimport enum variants
Lukas Wirth 2 weeks ago
parent 124e11d · parent 5acd0fe · commit b5df936
-rw-r--r--crates/hir-def/src/import_map.rs36
-rw-r--r--crates/hir/src/symbols.rs2
-rw-r--r--crates/ide-assists/src/handlers/auto_import.rs56
-rw-r--r--crates/ide-completion/src/render.rs2
-rw-r--r--crates/ide-completion/src/tests/expression.rs1
-rw-r--r--crates/ide-db/src/test_data/test_symbol_index_collection.txt4
6 files changed, 95 insertions, 6 deletions
diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs
index ba077b1b2e..f8be211bf9 100644
--- a/crates/hir-def/src/import_map.rs
+++ b/crates/hir-def/src/import_map.rs
@@ -12,7 +12,7 @@ use span::Edition;
use stdx::format_to;
use crate::{
- AssocItemId, AttrDefId, Complete, FxIndexMap, ModuleDefId, ModuleId, TraitId,
+ AdtId, AssocItemId, AttrDefId, Complete, EnumId, FxIndexMap, ModuleDefId, ModuleId, TraitId,
attrs::AttrFlags,
db::DefDatabase,
item_scope::{ImportOrExternCrate, ItemInNs},
@@ -208,7 +208,8 @@ impl ImportMap {
complete: do_not_complete,
};
- if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() {
+ let module_def = item.as_module_def_id();
+ if let Some(ModuleDefId::TraitId(tr)) = module_def {
Self::collect_trait_assoc_items(
db,
&mut map,
@@ -216,6 +217,8 @@ impl ImportMap {
matches!(item, ItemInNs::Types(_)),
&import_info,
);
+ } else if let Some(ModuleDefId::AdtId(AdtId::EnumId(enum_))) = module_def {
+ Self::collect_enum_variants(db, &mut map, enum_, &import_info);
}
let (infos, _) =
@@ -224,7 +227,7 @@ impl ImportMap {
infos.push(import_info);
// If we've just added a module, descend into it.
- if let Some(ModuleDefId::ModuleId(mod_id)) = item.as_module_def_id() {
+ if let Some(ModuleDefId::ModuleId(mod_id)) = module_def {
worklist.push(mod_id);
}
}
@@ -234,6 +237,33 @@ impl ImportMap {
map
}
+ fn collect_enum_variants(
+ db: &dyn DefDatabase,
+ map: &mut ImportMapIndex,
+ enum_: EnumId,
+ enum_import_info: &ImportInfo,
+ ) {
+ let _p = tracing::info_span!("collect_enum_variants").entered();
+ for (variant_name, &(variant, _)) in &enum_.enum_variants(db).variants {
+ let attr_id = variant.into();
+ let attrs = AttrFlags::query(db, attr_id);
+ let do_not_complete = Complete::extract(false, attrs);
+ let variant_info = ImportInfo {
+ container: enum_import_info.container,
+ name: variant_name.clone(),
+ is_doc_hidden: attrs.contains(AttrFlags::IS_DOC_HIDDEN),
+ is_unstable: attrs.contains(AttrFlags::IS_UNSTABLE),
+ complete: do_not_complete,
+ };
+
+ let (infos, _) = map
+ .entry(ItemInNs::Types(variant.into()))
+ .or_insert_with(|| (SmallVec::new(), IsTraitAssocItem::No));
+ infos.reserve_exact(1);
+ infos.push(variant_info);
+ }
+ }
+
fn collect_trait_assoc_items(
db: &dyn DefDatabase,
map: &mut ImportMapIndex,
diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs
index a00c3219b2..c4040c1c00 100644
--- a/crates/hir/src/symbols.rs
+++ b/crates/hir/src/symbols.rs
@@ -191,7 +191,7 @@ impl<'a> SymbolCollector<'a> {
this.with_container_name(Some(enum_name), |this| {
let variants = id.enum_variants(this.db);
for (variant_name, (variant_id, _)) in &variants.variants {
- this.push_decl(*variant_id, variant_name, true, None);
+ this.push_decl(*variant_id, variant_name, false, None);
}
});
}
diff --git a/crates/ide-assists/src/handlers/auto_import.rs b/crates/ide-assists/src/handlers/auto_import.rs
index ac0bae7cd9..d6e459d044 100644
--- a/crates/ide-assists/src/handlers/auto_import.rs
+++ b/crates/ide-assists/src/handlers/auto_import.rs
@@ -2037,4 +2037,60 @@ fn baz() {
"Import `foo::Ext` without `as _`",
);
}
+
+ #[test]
+ fn local_enum_variant() {
+ check_assist(
+ auto_import,
+ r#"
+mod foo {
+ pub enum ControlFlow {
+ Continue,
+ }
+}
+
+fn main() {
+ Continue$0;
+}
+ "#,
+ r#"
+use foo::ControlFlow::Continue;
+
+mod foo {
+ pub enum ControlFlow {
+ Continue,
+ }
+}
+
+fn main() {
+ Continue;
+}
+ "#,
+ );
+ }
+
+ #[test]
+ fn foreign_enum_variant() {
+ check_assist(
+ auto_import,
+ r#"
+//- /foo.rs crate:foo
+pub enum ControlFlow {
+ Continue,
+}
+
+//- /main.rs crate:main deps:foo
+fn main() {
+ Continue$0;
+}
+ "#,
+ r#"
+use foo::ControlFlow::Continue;
+
+fn main() {
+ Continue;
+}
+ "#,
+ );
+ }
}
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs
index 575c869093..bc71c1da2b 100644
--- a/crates/ide-completion/src/render.rs
+++ b/crates/ide-completion/src/render.rs
@@ -1067,6 +1067,8 @@ fn main() {
"#,
expect![[r#"
ev dep::test_mod_b::Enum::Variant dep::test_mod_b::Enum::Variant [type_could_unify]
+ ev Variant Variant [type_could_unify+requires_import]
+ ev Variant Variant [requires_import]
ex dep::test_mod_b::Enum::Variant [type_could_unify]
md dep:: []
fn main() fn() []
diff --git a/crates/ide-completion/src/tests/expression.rs b/crates/ide-completion/src/tests/expression.rs
index e2baf42848..b5465ee87a 100644
--- a/crates/ide-completion/src/tests/expression.rs
+++ b/crates/ide-completion/src/tests/expression.rs
@@ -1055,6 +1055,7 @@ fn brr() {
fn brr() fn()
st YoloVariant YoloVariant
st YoloVariant {…} YoloVariant { f: usize }
+ ev Yolo(…) (use HH::Yolo) Yolo(YoloVariant)
bt u32 u32
kw const
kw crate::
diff --git a/crates/ide-db/src/test_data/test_symbol_index_collection.txt b/crates/ide-db/src/test_data/test_symbol_index_collection.txt
index 1b20a574bd..a84f75cb4e 100644
--- a/crates/ide-db/src/test_data/test_symbol_index_collection.txt
+++ b/crates/ide-db/src/test_data/test_symbol_index_collection.txt
@@ -38,7 +38,7 @@
"Enum",
),
is_alias: false,
- is_assoc: true,
+ is_assoc: false,
is_import: false,
do_not_complete: Yes,
_marker: PhantomData<&()>,
@@ -110,7 +110,7 @@
"Enum",
),
is_alias: false,
- is_assoc: true,
+ is_assoc: false,
is_import: false,
do_not_complete: Yes,
_marker: PhantomData<&()>,