Skip to content

Commit bcff166

Browse files
committed
Add ExternCrateDecl to HIR
1 parent 151c750 commit bcff166

39 files changed

+584
-166
lines changed

crates/hir-def/src/child_by_source.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ use crate::{
1414
item_scope::ItemScope,
1515
nameres::DefMap,
1616
src::{HasChildSource, HasSource},
17-
AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, FieldId, ImplId, Lookup, MacroId,
18-
ModuleDefId, ModuleId, TraitId, VariantId,
17+
AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FieldId, ImplId,
18+
Lookup, MacroId, ModuleDefId, ModuleId, TraitId, VariantId,
1919
};
2020

2121
pub trait ChildBySource {
@@ -91,6 +91,7 @@ impl ChildBySource for ItemScope {
9191
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
9292
self.declarations().for_each(|item| add_module_def(db, res, file_id, item));
9393
self.impls().for_each(|imp| add_impl(db, res, file_id, imp));
94+
self.extern_crate_decls().for_each(|ext| add_extern_crate(db, res, file_id, ext));
9495
self.unnamed_consts().for_each(|konst| {
9596
let loc = konst.lookup(db);
9697
if loc.id.file_id() == file_id {
@@ -167,6 +168,17 @@ impl ChildBySource for ItemScope {
167168
map[keys::IMPL].insert(loc.source(db).value, imp)
168169
}
169170
}
171+
fn add_extern_crate(
172+
db: &dyn DefDatabase,
173+
map: &mut DynMap,
174+
file_id: HirFileId,
175+
ext: ExternCrateId,
176+
) {
177+
let loc = ext.lookup(db);
178+
if loc.id.file_id() == file_id {
179+
map[keys::EXTERN_CRATE].insert(loc.source(db).value, ext)
180+
}
181+
}
170182
}
171183
}
172184

crates/hir-def/src/data.rs

+16
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
pub mod adt;
44

5+
use base_db::CrateId;
56
use hir_expand::{
67
name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind,
78
};
@@ -467,6 +468,7 @@ pub struct ExternCrateDeclData {
467468
pub name: Name,
468469
pub alias: Option<ImportAlias>,
469470
pub visibility: RawVisibility,
471+
pub crate_id: CrateId,
470472
}
471473

472474
impl ExternCrateDeclData {
@@ -478,10 +480,24 @@ impl ExternCrateDeclData {
478480
let item_tree = loc.id.item_tree(db);
479481
let extern_crate = &item_tree[loc.id.value];
480482

483+
let name = extern_crate.name.clone();
484+
let crate_id = if name == hir_expand::name![self] {
485+
loc.container.krate()
486+
} else {
487+
db.crate_def_map(loc.container.krate())
488+
.extern_prelude()
489+
.find(|&(prelude_name, ..)| *prelude_name == name)
490+
// FIXME: Suspicious unwrap
491+
.unwrap()
492+
.1
493+
.krate()
494+
};
495+
481496
Arc::new(Self {
482497
name: extern_crate.name.clone(),
483498
visibility: item_tree[extern_crate.visibility].clone(),
484499
alias: extern_crate.alias.clone(),
500+
crate_id,
485501
})
486502
}
487503
}

crates/hir-def/src/item_scope.rs

+6
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,12 @@ impl ItemScope {
113113
self.declarations.iter().copied()
114114
}
115115

116+
pub fn extern_crate_decls(
117+
&self,
118+
) -> impl Iterator<Item = ExternCrateId> + ExactSizeIterator + '_ {
119+
self.extern_crate_decls.iter().copied()
120+
}
121+
116122
pub fn impls(&self) -> impl Iterator<Item = ImplId> + ExactSizeIterator + '_ {
117123
self.impls.iter().copied()
118124
}

crates/hir-def/src/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,12 @@ impl From<CrateRootModuleId> for ModuleDefId {
121121
}
122122
}
123123

124+
impl From<CrateId> for CrateRootModuleId {
125+
fn from(krate: CrateId) -> Self {
126+
CrateRootModuleId { krate }
127+
}
128+
}
129+
124130
impl TryFrom<ModuleId> for CrateRootModuleId {
125131
type Error = ();
126132

crates/hir-def/src/nameres/tests/incremental.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -213,17 +213,17 @@ pub type Ty = ();
213213

214214
for (_, res) in module_data.scope.resolutions() {
215215
match res.values.or(res.types).unwrap().0 {
216-
ModuleDefId::FunctionId(f) => drop(db.function_data(f)),
216+
ModuleDefId::FunctionId(f) => _ = db.function_data(f),
217217
ModuleDefId::AdtId(adt) => match adt {
218-
AdtId::StructId(it) => drop(db.struct_data(it)),
219-
AdtId::UnionId(it) => drop(db.union_data(it)),
220-
AdtId::EnumId(it) => drop(db.enum_data(it)),
218+
AdtId::StructId(it) => _ = db.struct_data(it),
219+
AdtId::UnionId(it) => _ = db.union_data(it),
220+
AdtId::EnumId(it) => _ = db.enum_data(it),
221221
},
222-
ModuleDefId::ConstId(it) => drop(db.const_data(it)),
223-
ModuleDefId::StaticId(it) => drop(db.static_data(it)),
224-
ModuleDefId::TraitId(it) => drop(db.trait_data(it)),
225-
ModuleDefId::TraitAliasId(it) => drop(db.trait_alias_data(it)),
226-
ModuleDefId::TypeAliasId(it) => drop(db.type_alias_data(it)),
222+
ModuleDefId::ConstId(it) => _ = db.const_data(it),
223+
ModuleDefId::StaticId(it) => _ = db.static_data(it),
224+
ModuleDefId::TraitId(it) => _ = db.trait_data(it),
225+
ModuleDefId::TraitAliasId(it) => _ = db.trait_alias_data(it),
226+
ModuleDefId::TypeAliasId(it) => _ = db.type_alias_data(it),
227227
ModuleDefId::EnumVariantId(_)
228228
| ModuleDefId::ModuleId(_)
229229
| ModuleDefId::MacroId(_)

crates/hir/src/attrs.rs

+36-3
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ use hir_ty::db::HirDatabase;
1212
use syntax::{ast, AstNode};
1313

1414
use crate::{
15-
Adt, AssocItem, Const, ConstParam, Enum, Field, Function, GenericParam, Impl, LifetimeParam,
16-
Macro, Module, ModuleDef, Static, Struct, Trait, TraitAlias, TypeAlias, TypeParam, Union,
17-
Variant,
15+
Adt, AssocItem, Const, ConstParam, Enum, ExternCrateDecl, Field, Function, GenericParam, Impl,
16+
LifetimeParam, Macro, Module, ModuleDef, Static, Struct, Trait, TraitAlias, TypeAlias,
17+
TypeParam, Union, Variant,
1818
};
1919

2020
pub trait HasAttrs {
@@ -120,6 +120,39 @@ impl HasAttrs for AssocItem {
120120
}
121121
}
122122

123+
impl HasAttrs for ExternCrateDecl {
124+
fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner {
125+
let def = AttrDefId::ExternCrateId(self.into());
126+
db.attrs_with_owner(def)
127+
}
128+
fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> {
129+
let crate_docs = self.resolved_crate(db).root_module().attrs(db).docs().map(String::from);
130+
let def = AttrDefId::ExternCrateId(self.into());
131+
let decl_docs = db.attrs(def).docs().map(String::from);
132+
match (decl_docs, crate_docs) {
133+
(None, None) => None,
134+
(Some(decl_docs), None) => Some(decl_docs),
135+
(None, Some(crate_docs)) => Some(crate_docs),
136+
(Some(mut decl_docs), Some(crate_docs)) => {
137+
decl_docs.push('\n');
138+
decl_docs.push('\n');
139+
decl_docs += &crate_docs;
140+
Some(decl_docs)
141+
}
142+
}
143+
.map(Documentation::new)
144+
}
145+
fn resolve_doc_path(
146+
self,
147+
db: &dyn HirDatabase,
148+
link: &str,
149+
ns: Option<Namespace>,
150+
) -> Option<ModuleDef> {
151+
let def = AttrDefId::ExternCrateId(self.into());
152+
resolve_doc_path(db, def, link, ns).map(ModuleDef::from)
153+
}
154+
}
155+
123156
/// Resolves the item `link` points to in the scope of `def`.
124157
fn resolve_doc_path(
125158
db: &dyn HirDatabase,

crates/hir/src/db.rs

-5
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,3 @@ pub use hir_expand::db::{
1010
MacroExpandQuery, ParseMacroExpansionErrorQuery, ParseMacroExpansionQuery,
1111
};
1212
pub use hir_ty::db::*;
13-
14-
#[test]
15-
fn hir_database_is_object_safe() {
16-
fn _assert_object_safe(_: &dyn HirDatabase) {}
17-
}

crates/hir/src/display.rs

+15-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ use hir_ty::{
1818
};
1919

2020
use crate::{
21-
Adt, AsAssocItem, AssocItemContainer, Const, ConstParam, Enum, Field, Function, GenericParam,
22-
HasCrate, HasVisibility, LifetimeParam, Macro, Module, Static, Struct, Trait, TraitAlias,
23-
TyBuilder, Type, TypeAlias, TypeOrConstParam, TypeParam, Union, Variant,
21+
Adt, AsAssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, Field,
22+
Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, Static, Struct,
23+
Trait, TraitAlias, TyBuilder, Type, TypeAlias, TypeOrConstParam, TypeParam, Union, Variant,
2424
};
2525

2626
impl HirDisplay for Function {
@@ -238,6 +238,18 @@ impl HirDisplay for Type {
238238
}
239239
}
240240

241+
impl HirDisplay for ExternCrateDecl {
242+
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
243+
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
244+
f.write_str("extern crate ")?;
245+
write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
246+
if let Some(alias) = self.alias(f.db) {
247+
write!(f, " as {alias}",)?;
248+
}
249+
Ok(())
250+
}
251+
}
252+
241253
impl HirDisplay for GenericParam {
242254
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
243255
match self {

crates/hir/src/from_id.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::{
1515
};
1616

1717
macro_rules! from_id {
18-
($(($id:path, $ty:path)),*) => {$(
18+
($(($id:path, $ty:path)),* $(,)?) => {$(
1919
impl From<$id> for $ty {
2020
fn from(id: $id) -> $ty {
2121
$ty { id }
@@ -47,7 +47,8 @@ from_id![
4747
(hir_def::TypeParamId, crate::TypeParam),
4848
(hir_def::ConstParamId, crate::ConstParam),
4949
(hir_def::LifetimeParamId, crate::LifetimeParam),
50-
(hir_def::MacroId, crate::Macro)
50+
(hir_def::MacroId, crate::Macro),
51+
(hir_def::ExternCrateId, crate::ExternCrateDecl),
5152
];
5253

5354
impl From<AdtId> for Adt {

crates/hir/src/has_source.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ use hir_expand::{HirFileId, InFile};
1111
use syntax::ast;
1212

1313
use crate::{
14-
db::HirDatabase, Adt, Const, Enum, Field, FieldSource, Function, Impl, LifetimeParam,
15-
LocalSource, Macro, Module, Static, Struct, Trait, TraitAlias, TypeAlias, TypeOrConstParam,
16-
Union, Variant,
14+
db::HirDatabase, Adt, Const, Enum, ExternCrateDecl, Field, FieldSource, Function, Impl,
15+
LifetimeParam, LocalSource, Macro, Module, Static, Struct, Trait, TraitAlias, TypeAlias,
16+
TypeOrConstParam, Union, Variant,
1717
};
1818

1919
pub trait HasSource {
@@ -207,3 +207,11 @@ impl HasSource for LocalSource {
207207
Some(self.source)
208208
}
209209
}
210+
211+
impl HasSource for ExternCrateDecl {
212+
type Ast = ast::ExternCrate;
213+
214+
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
215+
Some(self.id.lookup(db.upcast()).source(db.upcast()))
216+
}
217+
}

crates/hir/src/lib.rs

+56-9
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,15 @@ use hir_def::{
4848
layout::{self, ReprOptions, TargetDataLayout},
4949
macro_id_to_def_id,
5050
nameres::{self, diagnostics::DefDiagnostic},
51+
path::ImportAlias,
5152
per_ns::PerNs,
5253
resolver::{HasResolver, Resolver},
5354
src::HasSource as _,
54-
AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, DefWithBodyId, EnumId,
55-
EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, InTypeConstId, ItemContainerId,
56-
LifetimeParamId, LocalEnumVariantId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId,
57-
StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId,
58-
UnionId,
55+
AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId,
56+
EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, HasModule, ImplId,
57+
InTypeConstId, ItemContainerId, LifetimeParamId, LocalEnumVariantId, LocalFieldId, Lookup,
58+
MacroExpander, MacroId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId,
59+
TypeOrConstParamId, TypeParamId, UnionId,
5960
};
6061
use hir_expand::{name::name, MacroCallKind};
6162
use hir_ty::{
@@ -200,9 +201,8 @@ impl Crate {
200201
db.crate_graph().transitive_rev_deps(self.id).map(|id| Crate { id })
201202
}
202203

203-
pub fn root_module(self, db: &dyn HirDatabase) -> Module {
204-
let def_map = db.crate_def_map(self.id);
205-
Module { id: def_map.crate_root().into() }
204+
pub fn root_module(self) -> Module {
205+
Module { id: CrateRootModuleId::from(self.id).into() }
206206
}
207207

208208
pub fn modules(self, db: &dyn HirDatabase) -> Vec<Module> {
@@ -247,7 +247,7 @@ impl Crate {
247247
/// Try to get the root URL of the documentation of a crate.
248248
pub fn get_html_root_url(self: &Crate, db: &dyn HirDatabase) -> Option<String> {
249249
// Look for #![doc(html_root_url = "...")]
250-
let attrs = db.attrs(AttrDefId::ModuleId(self.root_module(db).into()));
250+
let attrs = db.attrs(AttrDefId::ModuleId(self.root_module().into()));
251251
let doc_url = attrs.by_key("doc").find_string_value_in_tt("html_root_url");
252252
doc_url.map(|s| s.trim_matches('"').trim_end_matches('/').to_owned() + "/")
253253
}
@@ -2128,6 +2128,47 @@ impl HasVisibility for Function {
21282128
}
21292129
}
21302130

2131+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2132+
pub struct ExternCrateDecl {
2133+
pub(crate) id: ExternCrateId,
2134+
}
2135+
2136+
impl ExternCrateDecl {
2137+
pub fn module(self, db: &dyn HirDatabase) -> Module {
2138+
self.id.module(db.upcast()).into()
2139+
}
2140+
2141+
pub fn resolved_crate(self, db: &dyn HirDatabase) -> Crate {
2142+
db.extern_crate_decl_data(self.id).crate_id.into()
2143+
}
2144+
2145+
pub fn name(self, db: &dyn HirDatabase) -> Name {
2146+
db.extern_crate_decl_data(self.id).name.clone()
2147+
}
2148+
2149+
pub fn alias(self, db: &dyn HirDatabase) -> Option<ImportAlias> {
2150+
db.extern_crate_decl_data(self.id).alias.clone()
2151+
}
2152+
2153+
/// Returns the name under which this crate is made accessible, taking `_` into account.
2154+
pub fn alias_or_name(self, db: &dyn HirDatabase) -> Option<Name> {
2155+
let extern_crate_decl_data = db.extern_crate_decl_data(self.id);
2156+
match &extern_crate_decl_data.alias {
2157+
Some(ImportAlias::Underscore) => None,
2158+
Some(ImportAlias::Alias(alias)) => Some(alias.clone()),
2159+
None => Some(extern_crate_decl_data.name.clone()),
2160+
}
2161+
}
2162+
}
2163+
2164+
impl HasVisibility for ExternCrateDecl {
2165+
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2166+
db.extern_crate_decl_data(self.id)
2167+
.visibility
2168+
.resolve(db.upcast(), &self.id.resolver(db.upcast()))
2169+
}
2170+
}
2171+
21312172
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
21322173
pub struct InTypeConst {
21332174
pub(crate) id: InTypeConstId,
@@ -4715,6 +4756,12 @@ pub trait HasContainer {
47154756
fn container(&self, db: &dyn HirDatabase) -> ItemContainer;
47164757
}
47174758

4759+
impl HasContainer for ExternCrateDecl {
4760+
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
4761+
container_id_to_hir(self.id.lookup(db.upcast()).container.into())
4762+
}
4763+
}
4764+
47184765
impl HasContainer for Module {
47194766
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
47204767
// FIXME: handle block expressions as modules (their parent is in a different DefMap)

0 commit comments

Comments
 (0)