Skip to content

Commit

Permalink
Add ExternCrateDecl to HIR
Browse files Browse the repository at this point in the history
  • Loading branch information
Veykril committed Aug 2, 2023
1 parent 151c750 commit bcff166
Show file tree
Hide file tree
Showing 39 changed files with 584 additions and 166 deletions.
16 changes: 14 additions & 2 deletions crates/hir-def/src/child_by_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ use crate::{
item_scope::ItemScope,
nameres::DefMap,
src::{HasChildSource, HasSource},
AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, FieldId, ImplId, Lookup, MacroId,
ModuleDefId, ModuleId, TraitId, VariantId,
AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FieldId, ImplId,
Lookup, MacroId, ModuleDefId, ModuleId, TraitId, VariantId,
};

pub trait ChildBySource {
Expand Down Expand Up @@ -91,6 +91,7 @@ impl ChildBySource for ItemScope {
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
self.declarations().for_each(|item| add_module_def(db, res, file_id, item));
self.impls().for_each(|imp| add_impl(db, res, file_id, imp));
self.extern_crate_decls().for_each(|ext| add_extern_crate(db, res, file_id, ext));
self.unnamed_consts().for_each(|konst| {
let loc = konst.lookup(db);
if loc.id.file_id() == file_id {
Expand Down Expand Up @@ -167,6 +168,17 @@ impl ChildBySource for ItemScope {
map[keys::IMPL].insert(loc.source(db).value, imp)
}
}
fn add_extern_crate(
db: &dyn DefDatabase,
map: &mut DynMap,
file_id: HirFileId,
ext: ExternCrateId,
) {
let loc = ext.lookup(db);
if loc.id.file_id() == file_id {
map[keys::EXTERN_CRATE].insert(loc.source(db).value, ext)
}
}
}
}

Expand Down
16 changes: 16 additions & 0 deletions crates/hir-def/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pub mod adt;

use base_db::CrateId;
use hir_expand::{
name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind,
};
Expand Down Expand Up @@ -467,6 +468,7 @@ pub struct ExternCrateDeclData {
pub name: Name,
pub alias: Option<ImportAlias>,
pub visibility: RawVisibility,
pub crate_id: CrateId,
}

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

let name = extern_crate.name.clone();
let crate_id = if name == hir_expand::name![self] {
loc.container.krate()
} else {
db.crate_def_map(loc.container.krate())
.extern_prelude()
.find(|&(prelude_name, ..)| *prelude_name == name)
// FIXME: Suspicious unwrap
.unwrap()
.1
.krate()
};

Arc::new(Self {
name: extern_crate.name.clone(),
visibility: item_tree[extern_crate.visibility].clone(),
alias: extern_crate.alias.clone(),
crate_id,
})
}
}
Expand Down
6 changes: 6 additions & 0 deletions crates/hir-def/src/item_scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ impl ItemScope {
self.declarations.iter().copied()
}

pub fn extern_crate_decls(
&self,
) -> impl Iterator<Item = ExternCrateId> + ExactSizeIterator + '_ {
self.extern_crate_decls.iter().copied()
}

pub fn impls(&self) -> impl Iterator<Item = ImplId> + ExactSizeIterator + '_ {
self.impls.iter().copied()
}
Expand Down
6 changes: 6 additions & 0 deletions crates/hir-def/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@ impl From<CrateRootModuleId> for ModuleDefId {
}
}

impl From<CrateId> for CrateRootModuleId {
fn from(krate: CrateId) -> Self {
CrateRootModuleId { krate }
}
}

impl TryFrom<ModuleId> for CrateRootModuleId {
type Error = ();

Expand Down
18 changes: 9 additions & 9 deletions crates/hir-def/src/nameres/tests/incremental.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,17 +213,17 @@ pub type Ty = ();

for (_, res) in module_data.scope.resolutions() {
match res.values.or(res.types).unwrap().0 {
ModuleDefId::FunctionId(f) => drop(db.function_data(f)),
ModuleDefId::FunctionId(f) => _ = db.function_data(f),
ModuleDefId::AdtId(adt) => match adt {
AdtId::StructId(it) => drop(db.struct_data(it)),
AdtId::UnionId(it) => drop(db.union_data(it)),
AdtId::EnumId(it) => drop(db.enum_data(it)),
AdtId::StructId(it) => _ = db.struct_data(it),
AdtId::UnionId(it) => _ = db.union_data(it),
AdtId::EnumId(it) => _ = db.enum_data(it),
},
ModuleDefId::ConstId(it) => drop(db.const_data(it)),
ModuleDefId::StaticId(it) => drop(db.static_data(it)),
ModuleDefId::TraitId(it) => drop(db.trait_data(it)),
ModuleDefId::TraitAliasId(it) => drop(db.trait_alias_data(it)),
ModuleDefId::TypeAliasId(it) => drop(db.type_alias_data(it)),
ModuleDefId::ConstId(it) => _ = db.const_data(it),
ModuleDefId::StaticId(it) => _ = db.static_data(it),
ModuleDefId::TraitId(it) => _ = db.trait_data(it),
ModuleDefId::TraitAliasId(it) => _ = db.trait_alias_data(it),
ModuleDefId::TypeAliasId(it) => _ = db.type_alias_data(it),
ModuleDefId::EnumVariantId(_)
| ModuleDefId::ModuleId(_)
| ModuleDefId::MacroId(_)
Expand Down
39 changes: 36 additions & 3 deletions crates/hir/src/attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ use hir_ty::db::HirDatabase;
use syntax::{ast, AstNode};

use crate::{
Adt, AssocItem, Const, ConstParam, Enum, Field, Function, GenericParam, Impl, LifetimeParam,
Macro, Module, ModuleDef, Static, Struct, Trait, TraitAlias, TypeAlias, TypeParam, Union,
Variant,
Adt, AssocItem, Const, ConstParam, Enum, ExternCrateDecl, Field, Function, GenericParam, Impl,
LifetimeParam, Macro, Module, ModuleDef, Static, Struct, Trait, TraitAlias, TypeAlias,
TypeParam, Union, Variant,
};

pub trait HasAttrs {
Expand Down Expand Up @@ -120,6 +120,39 @@ impl HasAttrs for AssocItem {
}
}

impl HasAttrs for ExternCrateDecl {
fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner {
let def = AttrDefId::ExternCrateId(self.into());
db.attrs_with_owner(def)
}
fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> {
let crate_docs = self.resolved_crate(db).root_module().attrs(db).docs().map(String::from);
let def = AttrDefId::ExternCrateId(self.into());
let decl_docs = db.attrs(def).docs().map(String::from);
match (decl_docs, crate_docs) {
(None, None) => None,
(Some(decl_docs), None) => Some(decl_docs),
(None, Some(crate_docs)) => Some(crate_docs),
(Some(mut decl_docs), Some(crate_docs)) => {
decl_docs.push('\n');
decl_docs.push('\n');
decl_docs += &crate_docs;
Some(decl_docs)
}
}
.map(Documentation::new)
}
fn resolve_doc_path(
self,
db: &dyn HirDatabase,
link: &str,
ns: Option<Namespace>,
) -> Option<ModuleDef> {
let def = AttrDefId::ExternCrateId(self.into());
resolve_doc_path(db, def, link, ns).map(ModuleDef::from)
}
}

/// Resolves the item `link` points to in the scope of `def`.
fn resolve_doc_path(
db: &dyn HirDatabase,
Expand Down
5 changes: 0 additions & 5 deletions crates/hir/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,3 @@ pub use hir_expand::db::{
MacroExpandQuery, ParseMacroExpansionErrorQuery, ParseMacroExpansionQuery,
};
pub use hir_ty::db::*;

#[test]
fn hir_database_is_object_safe() {
fn _assert_object_safe(_: &dyn HirDatabase) {}
}
18 changes: 15 additions & 3 deletions crates/hir/src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ use hir_ty::{
};

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

impl HirDisplay for Function {
Expand Down Expand Up @@ -238,6 +238,18 @@ impl HirDisplay for Type {
}
}

impl HirDisplay for ExternCrateDecl {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
f.write_str("extern crate ")?;
write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
if let Some(alias) = self.alias(f.db) {
write!(f, " as {alias}",)?;
}
Ok(())
}
}

impl HirDisplay for GenericParam {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
match self {
Expand Down
5 changes: 3 additions & 2 deletions crates/hir/src/from_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::{
};

macro_rules! from_id {
($(($id:path, $ty:path)),*) => {$(
($(($id:path, $ty:path)),* $(,)?) => {$(
impl From<$id> for $ty {
fn from(id: $id) -> $ty {
$ty { id }
Expand Down Expand Up @@ -47,7 +47,8 @@ from_id![
(hir_def::TypeParamId, crate::TypeParam),
(hir_def::ConstParamId, crate::ConstParam),
(hir_def::LifetimeParamId, crate::LifetimeParam),
(hir_def::MacroId, crate::Macro)
(hir_def::MacroId, crate::Macro),
(hir_def::ExternCrateId, crate::ExternCrateDecl),
];

impl From<AdtId> for Adt {
Expand Down
14 changes: 11 additions & 3 deletions crates/hir/src/has_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ use hir_expand::{HirFileId, InFile};
use syntax::ast;

use crate::{
db::HirDatabase, Adt, Const, Enum, Field, FieldSource, Function, Impl, LifetimeParam,
LocalSource, Macro, Module, Static, Struct, Trait, TraitAlias, TypeAlias, TypeOrConstParam,
Union, Variant,
db::HirDatabase, Adt, Const, Enum, ExternCrateDecl, Field, FieldSource, Function, Impl,
LifetimeParam, LocalSource, Macro, Module, Static, Struct, Trait, TraitAlias, TypeAlias,
TypeOrConstParam, Union, Variant,
};

pub trait HasSource {
Expand Down Expand Up @@ -207,3 +207,11 @@ impl HasSource for LocalSource {
Some(self.source)
}
}

impl HasSource for ExternCrateDecl {
type Ast = ast::ExternCrate;

fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
Some(self.id.lookup(db.upcast()).source(db.upcast()))
}
}
65 changes: 56 additions & 9 deletions crates/hir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,15 @@ use hir_def::{
layout::{self, ReprOptions, TargetDataLayout},
macro_id_to_def_id,
nameres::{self, diagnostics::DefDiagnostic},
path::ImportAlias,
per_ns::PerNs,
resolver::{HasResolver, Resolver},
src::HasSource as _,
AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, DefWithBodyId, EnumId,
EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, InTypeConstId, ItemContainerId,
LifetimeParamId, LocalEnumVariantId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId,
StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId,
UnionId,
AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId,
EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, HasModule, ImplId,
InTypeConstId, ItemContainerId, LifetimeParamId, LocalEnumVariantId, LocalFieldId, Lookup,
MacroExpander, MacroId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId,
TypeOrConstParamId, TypeParamId, UnionId,
};
use hir_expand::{name::name, MacroCallKind};
use hir_ty::{
Expand Down Expand Up @@ -200,9 +201,8 @@ impl Crate {
db.crate_graph().transitive_rev_deps(self.id).map(|id| Crate { id })
}

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

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

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ExternCrateDecl {
pub(crate) id: ExternCrateId,
}

impl ExternCrateDecl {
pub fn module(self, db: &dyn HirDatabase) -> Module {
self.id.module(db.upcast()).into()
}

pub fn resolved_crate(self, db: &dyn HirDatabase) -> Crate {
db.extern_crate_decl_data(self.id).crate_id.into()
}

pub fn name(self, db: &dyn HirDatabase) -> Name {
db.extern_crate_decl_data(self.id).name.clone()
}

pub fn alias(self, db: &dyn HirDatabase) -> Option<ImportAlias> {
db.extern_crate_decl_data(self.id).alias.clone()
}

/// Returns the name under which this crate is made accessible, taking `_` into account.
pub fn alias_or_name(self, db: &dyn HirDatabase) -> Option<Name> {
let extern_crate_decl_data = db.extern_crate_decl_data(self.id);
match &extern_crate_decl_data.alias {
Some(ImportAlias::Underscore) => None,
Some(ImportAlias::Alias(alias)) => Some(alias.clone()),
None => Some(extern_crate_decl_data.name.clone()),
}
}
}

impl HasVisibility for ExternCrateDecl {
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
db.extern_crate_decl_data(self.id)
.visibility
.resolve(db.upcast(), &self.id.resolver(db.upcast()))
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct InTypeConst {
pub(crate) id: InTypeConstId,
Expand Down Expand Up @@ -4715,6 +4756,12 @@ pub trait HasContainer {
fn container(&self, db: &dyn HirDatabase) -> ItemContainer;
}

impl HasContainer for ExternCrateDecl {
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
container_id_to_hir(self.id.lookup(db.upcast()).container.into())
}
}

impl HasContainer for Module {
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
// FIXME: handle block expressions as modules (their parent is in a different DefMap)
Expand Down
Loading

0 comments on commit bcff166

Please sign in to comment.