support non-extern-prelude dependencies

This commit is contained in:
Jonas Schievink 2021-09-28 21:23:46 +02:00
parent cd9f27d424
commit 0b76b29512
9 changed files with 205 additions and 55 deletions

View file

@ -61,14 +61,17 @@ pub(super) fn collect_defs(
) -> DefMap {
let crate_graph = db.crate_graph();
if block.is_none() {
// populate external prelude
for dep in &crate_graph[def_map.krate].dependencies {
tracing::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
let dep_def_map = db.crate_def_map(dep.crate_id);
def_map
.extern_prelude
.insert(dep.as_name(), dep_def_map.module_id(dep_def_map.root).into());
let mut deps = FxHashMap::default();
// populate external prelude and dependency list
for dep in &crate_graph[def_map.krate].dependencies {
tracing::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
let dep_def_map = db.crate_def_map(dep.crate_id);
let dep_root = dep_def_map.module_id(dep_def_map.root);
deps.insert(dep.as_name(), dep_root.into());
if dep.is_prelude() && block.is_none() {
def_map.extern_prelude.insert(dep.as_name(), dep_root.into());
}
}
@ -87,6 +90,7 @@ pub(super) fn collect_defs(
let mut collector = DefCollector {
db,
def_map,
deps,
glob_imports: FxHashMap::default(),
unresolved_imports: Vec::new(),
resolved_imports: Vec::new(),
@ -239,6 +243,7 @@ struct DefData<'a> {
struct DefCollector<'a> {
db: &'a dyn DefDatabase,
def_map: DefMap,
deps: FxHashMap<Name, ModuleDefId>,
glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility)>>,
unresolved_imports: Vec<ImportDirective>,
resolved_imports: Vec<ImportDirective>,
@ -660,7 +665,7 @@ impl DefCollector<'_> {
self.def_map.edition,
);
let res = self.def_map.resolve_name_in_extern_prelude(self.db, &extern_crate.name);
let res = self.resolve_extern_crate(&extern_crate.name);
if let Some(ModuleDefId::ModuleId(m)) = res.take_types() {
if m == self.def_map.module_id(current_module_id) {
@ -720,13 +725,13 @@ impl DefCollector<'_> {
fn resolve_import(&self, module_id: LocalModuleId, import: &Import) -> PartialResolvedImport {
tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
if import.is_extern_crate {
let res = self.def_map.resolve_name_in_extern_prelude(
self.db,
import
.path
.as_ident()
.expect("extern crate should have been desugared to one-element path"),
);
let name = import
.path
.as_ident()
.expect("extern crate should have been desugared to one-element path");
let res = self.resolve_extern_crate(name);
if res.is_none() {
PartialResolvedImport::Unresolved
} else {
@ -766,6 +771,24 @@ impl DefCollector<'_> {
}
}
fn resolve_extern_crate(&self, name: &Name) -> PerNs {
let arc;
let root = match self.def_map.block {
Some(_) => {
arc = self.def_map.crate_root(self.db).def_map(self.db);
&*arc
}
None => &self.def_map,
};
if name == &name!(self) {
cov_mark::hit!(extern_crate_self_as);
PerNs::types(root.module_id(root.root()).into(), Visibility::Public)
} else {
self.deps.get(name).map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public))
}
}
fn record_resolved_import(&mut self, directive: &ImportDirective) {
let module_id = directive.module_id;
let import = &directive.import;
@ -2009,6 +2032,7 @@ mod tests {
let mut collector = DefCollector {
db,
def_map,
deps: FxHashMap::default(),
glob_imports: FxHashMap::default(),
unresolved_imports: Vec::new(),
resolved_imports: Vec::new(),

View file

@ -11,7 +11,6 @@
//! `ReachedFixedPoint` signals about this.
use base_db::Edition;
use hir_expand::name;
use hir_expand::name::Name;
use crate::{
@ -65,11 +64,6 @@ impl DefMap {
db: &dyn DefDatabase,
name: &Name,
) -> PerNs {
if name == &name!(self) {
cov_mark::hit!(extern_crate_self_as);
return PerNs::types(self.module_id(self.root).into(), Visibility::Public);
}
let arc;
let root = match self.block {
Some(_) => {

View file

@ -860,3 +860,33 @@ pub const settings: () = ();
"#]],
)
}
#[test]
fn non_prelude_deps() {
check(
r#"
//- /lib.rs crate:lib deps:dep extern-prelude:
use dep::Struct;
//- /dep.rs crate:dep
pub struct Struct;
"#,
expect![[r#"
crate
Struct: _
"#]],
);
check(
r#"
//- /lib.rs crate:lib deps:dep extern-prelude:
extern crate dep;
use dep::Struct;
//- /dep.rs crate:dep
pub struct Struct;
"#,
expect![[r#"
crate
Struct: t v
dep: t
"#]],
);
}