Unnamed repository; edit this file 'description' to name the repository.
Include enum variants in the import map
So they can be autoimported for external crates.
Chayim Refael Friedman 3 weeks ago
parent 6c910e1 · commit 5acd0fe
-rw-r--r--crates/hir-def/src/import_map.rs36
-rw-r--r--crates/ide-assists/src/handlers/auto_import.rs25
-rw-r--r--crates/ide-completion/src/render.rs2
3 files changed, 60 insertions, 3 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/ide-assists/src/handlers/auto_import.rs b/crates/ide-assists/src/handlers/auto_import.rs
index 5c5261c898..d6e459d044 100644
--- a/crates/ide-assists/src/handlers/auto_import.rs
+++ b/crates/ide-assists/src/handlers/auto_import.rs
@@ -2068,4 +2068,29 @@ fn main() {
"#,
);
}
+
+ #[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 fbbdffefe3..fe7a9a9d4a 100644
--- a/crates/ide-completion/src/render.rs
+++ b/crates/ide-completion/src/render.rs
@@ -1059,6 +1059,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() []