Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir_def/src/lib.rs')
| -rw-r--r-- | crates/hir_def/src/lib.rs | 163 |
1 files changed, 153 insertions, 10 deletions
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index 21096166d7..d7292b0063 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs @@ -58,11 +58,15 @@ use std::{ }; use attr::Attr; -use base_db::{impl_intern_key, salsa, CrateId}; +use base_db::{impl_intern_key, salsa, CrateId, ProcMacroKind}; use hir_expand::{ ast_id_map::FileAstId, + builtin_attr_macro::BuiltinAttrExpander, + builtin_derive_macro::BuiltinDeriveExpander, + builtin_fn_macro::{BuiltinFnLikeExpander, EagerExpander}, eager::{expand_eager_macro, ErrorEmitted, ErrorSink}, hygiene::Hygiene, + proc_macro::ProcMacroExpander, AstId, ExpandError, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, UnresolvedMacro, }; @@ -77,8 +81,8 @@ use crate::{ attr::AttrId, builtin_type::BuiltinType, item_tree::{ - Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, ModItem, Static, Struct, Trait, - TypeAlias, Union, + Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, MacroDef, MacroRules, ModItem, + Static, Struct, Trait, TypeAlias, Union, }, }; @@ -268,6 +272,48 @@ pub struct ExternBlockId(salsa::InternId); type ExternBlockLoc = ItemLoc<ExternBlock>; impl_intern!(ExternBlockId, ExternBlockLoc, intern_extern_block, lookup_intern_extern_block); +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum MacroExpander { + Declarative, + BuiltIn(BuiltinFnLikeExpander), + BuiltInAttr(BuiltinAttrExpander), + BuiltInDerive(BuiltinDeriveExpander), + BuiltInEager(EagerExpander), +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] +pub struct Macro2Id(salsa::InternId); +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct Macro2Loc { + pub container: ModuleId, + pub id: ItemTreeId<MacroDef>, + pub expander: MacroExpander, +} +impl_intern!(Macro2Id, Macro2Loc, intern_macro2, lookup_intern_macro2); + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] +pub struct MacroRulesId(salsa::InternId); +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct MacroRulesLoc { + pub container: ModuleId, + pub id: ItemTreeId<MacroRules>, + pub local_inner: bool, + pub expander: MacroExpander, +} +impl_intern!(MacroRulesId, MacroRulesLoc, intern_macro_rules, lookup_intern_macro_rules); + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] +pub struct ProcMacroId(salsa::InternId); +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct ProcMacroLoc { + // FIXME: this should be a crate? or just a crate-root module + pub container: ModuleId, + pub id: ItemTreeId<Function>, + pub expander: ProcMacroExpander, + pub kind: ProcMacroKind, +} +impl_intern!(ProcMacroId, ProcMacroLoc, intern_proc_macro, lookup_intern_proc_macro); + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] pub struct BlockId(salsa::InternId); #[derive(Debug, Hash, PartialEq, Eq, Clone)] @@ -284,8 +330,8 @@ pub struct TypeOrConstParamId { pub local_id: LocalTypeOrConstParamId, } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] /// A TypeOrConstParamId with an invariant that it actually belongs to a type +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TypeParamId(TypeOrConstParamId); impl TypeParamId { @@ -359,6 +405,24 @@ pub enum AdtId { } impl_from!(StructId, UnionId, EnumId for AdtId); +/// A macro +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub enum MacroId { + Macro2Id(Macro2Id), + MacroRulesId(MacroRulesId), + ProcMacroId(ProcMacroId), +} +impl_from!(Macro2Id, MacroRulesId, ProcMacroId for MacroId); + +impl MacroId { + pub fn is_attribute(self, db: &dyn db::DefDatabase) -> bool { + match self { + MacroId::ProcMacroId(it) => it.lookup(db).kind == ProcMacroKind::Attr, + _ => false, + } + } +} + /// A generic param #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum GenericParamId { @@ -381,8 +445,10 @@ pub enum ModuleDefId { TraitId(TraitId), TypeAliasId(TypeAliasId), BuiltinType(BuiltinType), + MacroId(MacroId), } impl_from!( + MacroId(Macro2Id, MacroRulesId, ProcMacroId), ModuleId, FunctionId, AdtId(StructId, EnumId, UnionId), @@ -472,7 +538,7 @@ pub enum AttrDefId { ConstId(ConstId), TraitId(TraitId), TypeAliasId(TypeAliasId), - MacroDefId(MacroDefId), + MacroId(MacroId), ImplId(ImplId), GenericParamId(GenericParamId), ExternBlockId(ExternBlockId), @@ -488,7 +554,7 @@ impl_from!( FunctionId, TraitId, TypeAliasId, - MacroDefId, + MacroId(Macro2Id, MacroRulesId, ProcMacroId), ImplId, GenericParamId for AttrDefId @@ -592,6 +658,16 @@ impl HasModule for VariantId { } } +impl HasModule for MacroId { + fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { + match self { + MacroId::MacroRulesId(it) => it.lookup(db).container, + MacroId::Macro2Id(it) => it.lookup(db).container, + MacroId::ProcMacroId(it) => it.lookup(db).container, + } + } +} + impl HasModule for DefWithBodyId { fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { match self { @@ -652,6 +728,7 @@ impl ModuleDefId { ModuleDefId::StaticId(id) => id.lookup(db).module(db), ModuleDefId::TraitId(id) => id.lookup(db).container, ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db), + ModuleDefId::MacroId(id) => id.module(db), ModuleDefId::BuiltinType(_) => return None, }) } @@ -680,9 +757,7 @@ impl AttrDefId { .module(db) .krate } - // FIXME: `MacroDefId` should store the defining module, then this can implement - // `HasModule` - AttrDefId::MacroDefId(it) => it.krate, + AttrDefId::MacroId(it) => it.module(db).krate, } } } @@ -762,7 +837,7 @@ fn macro_call_as_call_id( resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, error_sink: &mut dyn FnMut(ExpandError), ) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> { - let def: MacroDefId = + let def = resolver(call.path.clone()).ok_or_else(|| UnresolvedMacro { path: call.path.clone() })?; let res = if let MacroDefKind::BuiltInEager(..) = def.kind { @@ -779,6 +854,74 @@ fn macro_call_as_call_id( Ok(res) } +pub fn macro_id_to_def_id(db: &dyn db::DefDatabase, id: MacroId) -> MacroDefId { + match id { + MacroId::Macro2Id(it) => { + let loc = it.lookup(db); + + let item_tree = loc.id.item_tree(db); + let makro = &item_tree[loc.id.value]; + let in_file = |m: FileAstId<ast::MacroDef>| InFile::new(loc.id.file_id(), m.upcast()); + MacroDefId { + krate: loc.container.krate, + kind: match loc.expander { + MacroExpander::Declarative => MacroDefKind::Declarative(in_file(makro.ast_id)), + MacroExpander::BuiltIn(it) => MacroDefKind::BuiltIn(it, in_file(makro.ast_id)), + MacroExpander::BuiltInAttr(it) => { + MacroDefKind::BuiltInAttr(it, in_file(makro.ast_id)) + } + MacroExpander::BuiltInDerive(it) => { + MacroDefKind::BuiltInDerive(it, in_file(makro.ast_id)) + } + MacroExpander::BuiltInEager(it) => { + MacroDefKind::BuiltInEager(it, in_file(makro.ast_id)) + } + }, + local_inner: false, + } + } + MacroId::MacroRulesId(it) => { + let loc = it.lookup(db); + + let item_tree = loc.id.item_tree(db); + let makro = &item_tree[loc.id.value]; + let in_file = |m: FileAstId<ast::MacroRules>| InFile::new(loc.id.file_id(), m.upcast()); + MacroDefId { + krate: loc.container.krate, + kind: match loc.expander { + MacroExpander::Declarative => MacroDefKind::Declarative(in_file(makro.ast_id)), + MacroExpander::BuiltIn(it) => MacroDefKind::BuiltIn(it, in_file(makro.ast_id)), + MacroExpander::BuiltInAttr(it) => { + MacroDefKind::BuiltInAttr(it, in_file(makro.ast_id)) + } + MacroExpander::BuiltInDerive(it) => { + MacroDefKind::BuiltInDerive(it, in_file(makro.ast_id)) + } + MacroExpander::BuiltInEager(it) => { + MacroDefKind::BuiltInEager(it, in_file(makro.ast_id)) + } + }, + local_inner: loc.local_inner, + } + } + MacroId::ProcMacroId(it) => { + let loc = it.lookup(db); + + let item_tree = loc.id.item_tree(db); + let makro = &item_tree[loc.id.value]; + MacroDefId { + krate: loc.container.krate, + kind: MacroDefKind::ProcMacro( + loc.expander, + loc.kind, + InFile::new(loc.id.file_id(), makro.ast_id), + ), + local_inner: false, + } + } + } +} + fn derive_macro_as_call_id( db: &dyn db::DefDatabase, item_attr: &AstIdWithPath<ast::Adt>, |