Skip to content

Commit 601557f

Browse files
authored
Fix importables: add submodule imports and handle crate reexports (#7647)
1 parent e7c9c76 commit 601557f

File tree

3 files changed

+23
-29
lines changed

3 files changed

+23
-29
lines changed

crates/cairo-lang-semantic/src/db.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1649,7 +1649,7 @@ pub trait SemanticGroup:
16491649
module_id: ModuleFileId,
16501650
) -> Option<Arc<OrderedHashMap<ImportableId, String>>>;
16511651
/// Returns all visible importables in a module, alongside a visible use path to the trait.
1652-
/// `user_module_file_id` is the module from which the importables are should be visible. If
1652+
/// `user_module_file_id` is the module from which the importables should be visible. If
16531653
/// `include_parent` is true, the parent module of `module_id` is also considered.
16541654
#[salsa::invoke(lsp_helpers::visible_importables_in_module)]
16551655
fn visible_importables_in_module(
@@ -1659,7 +1659,7 @@ pub trait SemanticGroup:
16591659
include_parent: bool,
16601660
) -> Arc<[(ImportableId, String)]>;
16611661
/// Returns all visible importables in a crate, alongside a visible use path to the trait.
1662-
/// `user_module_file_id` is the module from which the importables are should be visible.
1662+
/// `user_module_file_id` is the module from which the importables should be visible.
16631663
#[salsa::invoke(lsp_helpers::visible_importables_in_crate)]
16641664
fn visible_importables_in_crate(
16651665
&self,

crates/cairo-lang-semantic/src/lsp_helpers.rs

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use crate::db::SemanticGroup;
1818
use crate::expr::inference::InferenceId;
1919
use crate::items::functions::GenericFunctionId;
2020
use crate::items::us::SemanticUseEx;
21-
use crate::items::visibility::peek_visible_in;
2221
use crate::keyword::SELF_PARAM_KW;
2322
use crate::resolve::{ResolvedGenericItem, Resolver};
2423
use crate::types::TypeHead;
@@ -124,20 +123,11 @@ fn visible_importables_in_module_ex(
124123
}
125124

126125
let resolver = Resolver::new(db, user_module_file_id, InferenceId::NoContext);
127-
let ignore_visibility = resolver.ignore_visibility_checks(module_id);
126+
128127
// Check if an item in the current module is visible from the user module.
129128
let is_visible = |item_name: SmolStr| {
130-
if ignore_visibility {
131-
Some(true)
132-
} else {
133-
let item_info = db.module_item_info_by_name(module_id, item_name).ok()??;
134-
Some(peek_visible_in(
135-
db.upcast(),
136-
item_info.visibility,
137-
module_id,
138-
user_module_file_id.0,
139-
))
140-
}
129+
let item_info = db.module_item_info_by_name(module_id, item_name).ok()??;
130+
Some(resolver.is_item_visible(module_id, &item_info, user_module_file_id.0))
141131
};
142132
visited_modules.insert(module_id);
143133
let mut modules_to_visit = vec![];
@@ -148,7 +138,15 @@ fn visible_importables_in_module_ex(
148138
}
149139
let resolved_item = db.use_resolved_item(use_id).ok()?;
150140
let (resolved_item, name) = match resolved_item {
151-
ResolvedGenericItem::Module(ModuleId::CrateRoot(_)) => continue,
141+
ResolvedGenericItem::Module(ModuleId::CrateRoot(crate_id)) => {
142+
result.extend_from_slice(
143+
&db.visible_importables_in_crate(
144+
crate_id,
145+
ModuleFileId(module_id, FileIndex(0)),
146+
)[..],
147+
);
148+
continue;
149+
}
152150
ResolvedGenericItem::Module(inner_module_id @ ModuleId::Submodule(module)) => {
153151
modules_to_visit.push(inner_module_id);
154152

@@ -163,7 +161,6 @@ fn visible_importables_in_module_ex(
163161
ResolvedGenericItem::GenericFunction(GenericFunctionId::Extern(item_id)) => {
164162
(ImportableId::ExternFunction(item_id), item_id.name(db.upcast()))
165163
}
166-
ResolvedGenericItem::GenericFunction(GenericFunctionId::Impl(_item_id)) => continue,
167164
ResolvedGenericItem::GenericType(GenericTypeId::Struct(item_id)) => {
168165
(ImportableId::Struct(item_id), item_id.name(db.upcast()))
169166
}
@@ -188,7 +185,9 @@ fn visible_importables_in_module_ex(
188185
ResolvedGenericItem::Impl(item_id) => {
189186
(ImportableId::Impl(item_id), item_id.name(db.upcast()))
190187
}
191-
ResolvedGenericItem::Variable(_) | ResolvedGenericItem::TraitItem(_) => continue,
188+
ResolvedGenericItem::Variable(_)
189+
| ResolvedGenericItem::TraitItem(_)
190+
| ResolvedGenericItem::GenericFunction(GenericFunctionId::Impl(_)) => continue,
192191
};
193192

194193
result.push((resolved_item, name.to_string()));
@@ -197,6 +196,7 @@ fn visible_importables_in_module_ex(
197196
if !is_visible(submodule_id.name(db.upcast()))? {
198197
continue;
199198
}
199+
result.push((ImportableId::Submodule(submodule_id), submodule_id.name(db).to_string()));
200200
modules_to_visit.push(ModuleId::Submodule(submodule_id));
201201
}
202202

@@ -281,14 +281,8 @@ pub fn visible_importables_from_module(
281281
module_file_id: ModuleFileId,
282282
) -> Option<Arc<OrderedHashMap<ImportableId, String>>> {
283283
let module_id = module_file_id.0;
284-
let mut current_top_module = module_id;
285-
while let ModuleId::Submodule(submodule_id) = current_top_module {
286-
current_top_module = submodule_id.parent_module(db.upcast());
287-
}
288-
let current_crate_id = match current_top_module {
289-
ModuleId::CrateRoot(crate_id) => crate_id,
290-
ModuleId::Submodule(_) => unreachable!("current module is not a top-level module"),
291-
};
284+
285+
let current_crate_id = module_id.owning_crate(db);
292286
let edition = db.crate_config(current_crate_id)?.settings.edition;
293287
let prelude_submodule_name = edition.prelude_submodule_name();
294288
let core_prelude_submodule = core_submodule(db, "prelude");
@@ -300,7 +294,7 @@ pub fn visible_importables_from_module(
300294
module_visible_importables.extend_from_slice(
301295
&db.visible_importables_in_module(prelude_submodule, prelude_submodule_file_id, false)[..],
302296
);
303-
// Collect importables from all visible crates, including the current crate.
297+
// Collect importables from all dependency crates, including the current crate and corelib.
304298
let settings = db.crate_config(current_crate_id).map(|c| c.settings).unwrap_or_default();
305299
for crate_id in chain!(
306300
[current_crate_id],
@@ -322,7 +316,7 @@ pub fn visible_importables_from_module(
322316
.extend_from_slice(&db.visible_importables_in_module(module_id, module_file_id, true)[..]);
323317

324318
// Deduplicate importables, preferring shorter paths.
325-
// This is the reason for searching in the crates before the current module- to prioritize
319+
// This is the reason for searching in the crates before the current module - to prioritize
326320
// shorter, canonical paths prefixed with `crate::` over paths using `super::` or local
327321
// imports.
328322
let mut result: OrderedHashMap<ImportableId, String> = OrderedHashMap::default();

crates/cairo-lang-semantic/src/resolve/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1912,7 +1912,7 @@ impl<'db> Resolver<'db> {
19121912
}
19131913

19141914
/// Checks if an item is visible from the current module.
1915-
fn is_item_visible(
1915+
pub fn is_item_visible(
19161916
&self,
19171917
containing_module_id: ModuleId,
19181918
item_info: &ModuleItemInfo,

0 commit comments

Comments
 (0)