mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 14:51:48 +00:00
Add MacroId to hir_def in attempt to unify Macros with ModuleDefId
This commit is contained in:
parent
d425c5b534
commit
42d46325a1
19 changed files with 386 additions and 215 deletions
|
@ -13,7 +13,7 @@ use drop_bomb::DropBomb;
|
|||
use either::Either;
|
||||
use hir_expand::{
|
||||
ast_id_map::AstIdMap, hygiene::Hygiene, AstId, ExpandError, ExpandResult, HirFileId, InFile,
|
||||
MacroCallId, MacroDefId,
|
||||
MacroCallId,
|
||||
};
|
||||
use la_arena::{Arena, ArenaMap};
|
||||
use limit::Limit;
|
||||
|
@ -26,10 +26,11 @@ use crate::{
|
|||
db::DefDatabase,
|
||||
expr::{Expr, ExprId, Label, LabelId, Pat, PatId},
|
||||
item_scope::BuiltinShadowMode,
|
||||
macro_id_to_def_id,
|
||||
nameres::DefMap,
|
||||
path::{ModPath, Path},
|
||||
src::HasSource,
|
||||
AsMacroCall, BlockId, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleId,
|
||||
AsMacroCall, BlockId, DefWithBodyId, HasModule, LocalModuleId, Lookup, MacroId, ModuleId,
|
||||
UnresolvedMacro,
|
||||
};
|
||||
|
||||
|
@ -105,7 +106,7 @@ impl Expander {
|
|||
let macro_call = InFile::new(self.current_file_id, ¯o_call);
|
||||
|
||||
let resolver =
|
||||
|path: ModPath| -> Option<MacroDefId> { self.resolve_path_as_macro(db, &path) };
|
||||
|path| self.resolve_path_as_macro(db, &path).map(|it| macro_id_to_def_id(db, it));
|
||||
|
||||
let mut err = None;
|
||||
let call_id =
|
||||
|
@ -208,7 +209,7 @@ impl Expander {
|
|||
Path::from_src(path, &ctx)
|
||||
}
|
||||
|
||||
fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroDefId> {
|
||||
fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroId> {
|
||||
self.def_map.resolve_path(db, self.module, path, BuiltinShadowMode::Other).0.take_macros()
|
||||
}
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ use crate::{
|
|||
item_scope::ItemScope,
|
||||
keys,
|
||||
src::{HasChildSource, HasSource},
|
||||
AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, FieldId, ImplId, Lookup, ModuleDefId,
|
||||
ModuleId, TraitId, VariantId,
|
||||
AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, FieldId, ImplId, Lookup, MacroId,
|
||||
ModuleDefId, ModuleId, TraitId, VariantId,
|
||||
};
|
||||
|
||||
pub trait ChildBySource {
|
||||
|
@ -97,17 +97,6 @@ impl ChildBySource for ItemScope {
|
|||
res[keys::CONST].insert(loc.source(db).value, konst);
|
||||
}
|
||||
});
|
||||
self.macros().for_each(|(_, makro)| {
|
||||
let ast_id = makro.ast_id();
|
||||
if ast_id.either(|it| it.file_id, |it| it.file_id) == file_id {
|
||||
let src = match ast_id {
|
||||
Either::Left(ast_id) => ast_id.to_node(db.upcast()),
|
||||
// FIXME: Do we need to add proc-macros into a PROCMACRO dynmap here?
|
||||
Either::Right(_fn) => return,
|
||||
};
|
||||
res[keys::MACRO].insert(src, makro);
|
||||
}
|
||||
});
|
||||
self.attr_macro_invocs().filter(|(id, _)| id.file_id == file_id).for_each(
|
||||
|(ast_id, call_id)| {
|
||||
res[keys::ATTR_MACRO_CALL].insert(ast_id.to_node(db.upcast()), call_id);
|
||||
|
@ -151,6 +140,11 @@ impl ChildBySource for ItemScope {
|
|||
AdtId::UnionId(id) => insert!(map[keys::UNION].insert(id)),
|
||||
AdtId::EnumId(id) => insert!(map[keys::ENUM].insert(id)),
|
||||
},
|
||||
ModuleDefId::MacroId(id) => match id {
|
||||
MacroId::Macro2Id(id) => insert!(map[keys::MACRO2].insert(id)),
|
||||
MacroId::MacroRulesId(id) => insert!(map[keys::MACRO_RULES].insert(id)),
|
||||
MacroId::ProcMacroId(id) => insert!(map[keys::PROC_MACRO].insert(id)),
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,9 @@ use crate::{
|
|||
visibility::{self, Visibility},
|
||||
AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, ExternBlockId,
|
||||
ExternBlockLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalEnumVariantId,
|
||||
LocalFieldId, StaticId, StaticLoc, StructId, StructLoc, TraitId, TraitLoc, TypeAliasId,
|
||||
TypeAliasLoc, UnionId, UnionLoc, VariantId,
|
||||
LocalFieldId, Macro2Id, Macro2Loc, MacroRulesId, MacroRulesLoc, ProcMacroId, ProcMacroLoc,
|
||||
StaticId, StaticLoc, StructId, StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc,
|
||||
UnionId, UnionLoc, VariantId,
|
||||
};
|
||||
|
||||
#[salsa::query_group(InternDatabaseStorage)]
|
||||
|
@ -49,6 +50,12 @@ pub trait InternDatabase: SourceDatabase {
|
|||
fn intern_extern_block(&self, loc: ExternBlockLoc) -> ExternBlockId;
|
||||
#[salsa::interned]
|
||||
fn intern_block(&self, loc: BlockLoc) -> BlockId;
|
||||
#[salsa::interned]
|
||||
fn intern_macro2(&self, loc: Macro2Loc) -> Macro2Id;
|
||||
#[salsa::interned]
|
||||
fn intern_proc_macro(&self, loc: ProcMacroLoc) -> ProcMacroId;
|
||||
#[salsa::interned]
|
||||
fn intern_macro_rules(&self, loc: MacroRulesLoc) -> MacroRulesId;
|
||||
}
|
||||
|
||||
#[salsa::query_group(DefDatabaseStorage)]
|
||||
|
|
|
@ -98,6 +98,7 @@ impl PrefixKind {
|
|||
}
|
||||
}
|
||||
|
||||
/// Attempts to find a path to refer to the given `item` visible from the `from` ModuleId
|
||||
fn find_path_inner(
|
||||
db: &dyn DefDatabase,
|
||||
item: ItemInNs,
|
||||
|
|
|
@ -271,6 +271,7 @@ pub enum ImportKind {
|
|||
TypeAlias,
|
||||
BuiltinType,
|
||||
AssociatedItem,
|
||||
Macro,
|
||||
}
|
||||
|
||||
/// A way to match import map contents against the search query.
|
||||
|
@ -464,6 +465,7 @@ fn item_import_kind(item: ItemInNs) -> Option<ImportKind> {
|
|||
ModuleDefId::TraitId(_) => ImportKind::Trait,
|
||||
ModuleDefId::TypeAliasId(_) => ImportKind::TypeAlias,
|
||||
ModuleDefId::BuiltinType(_) => ImportKind::BuiltinType,
|
||||
ModuleDefId::MacroId(_) => ImportKind::Macro,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
use std::collections::hash_map::Entry;
|
||||
|
||||
use base_db::CrateId;
|
||||
use hir_expand::{name::Name, AstId, MacroCallId, MacroDefKind};
|
||||
use hir_expand::{name::Name, AstId, MacroCallId};
|
||||
use once_cell::sync::Lazy;
|
||||
use profile::Count;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
@ -14,7 +14,8 @@ use syntax::ast;
|
|||
|
||||
use crate::{
|
||||
attr::AttrId, db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType,
|
||||
ConstId, ImplId, LocalModuleId, MacroDefId, ModuleDefId, ModuleId, TraitId,
|
||||
ConstId, HasModule, ImplId, LocalModuleId, MacroId, MacroRulesId, ModuleDefId, ModuleId,
|
||||
TraitId,
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
|
@ -38,13 +39,13 @@ pub struct ItemScope {
|
|||
/// imports.
|
||||
types: FxHashMap<Name, (ModuleDefId, Visibility)>,
|
||||
values: FxHashMap<Name, (ModuleDefId, Visibility)>,
|
||||
macros: FxHashMap<Name, (MacroDefId, Visibility)>,
|
||||
macros: FxHashMap<Name, (MacroId, Visibility)>,
|
||||
unresolved: FxHashSet<Name>,
|
||||
|
||||
/// The defs declared in this scope. Each def has a single scope where it is
|
||||
/// declared.
|
||||
declarations: Vec<ModuleDefId>,
|
||||
macro_declarations: Vec<MacroDefId>,
|
||||
macro_declarations: Vec<MacroId>,
|
||||
|
||||
impls: Vec<ImplId>,
|
||||
unnamed_consts: Vec<ConstId>,
|
||||
|
@ -62,7 +63,7 @@ pub struct ItemScope {
|
|||
/// Module scoped macros will be inserted into `items` instead of here.
|
||||
// FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
|
||||
// be all resolved to the last one defined if shadowing happens.
|
||||
legacy_macros: FxHashMap<Name, MacroDefId>,
|
||||
legacy_macros: FxHashMap<Name, MacroRulesId>,
|
||||
attr_macros: FxHashMap<AstId<ast::Item>, MacroCallId>,
|
||||
/// The derive macro invocations in this scope, keyed by the owner item over the actual derive attributes
|
||||
/// paired with the derive macro invocations for the specific attribute.
|
||||
|
@ -108,7 +109,7 @@ impl ItemScope {
|
|||
self.declarations.iter().copied()
|
||||
}
|
||||
|
||||
pub fn macro_declarations(&self) -> impl Iterator<Item = MacroDefId> + '_ {
|
||||
pub fn macro_declarations(&self) -> impl Iterator<Item = MacroId> + '_ {
|
||||
self.macro_declarations.iter().copied()
|
||||
}
|
||||
|
||||
|
@ -127,12 +128,14 @@ impl ItemScope {
|
|||
}
|
||||
|
||||
/// Iterate over all module scoped macros
|
||||
pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
|
||||
pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroId)> + 'a {
|
||||
self.entries().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_)))
|
||||
}
|
||||
|
||||
/// Iterate over all legacy textual scoped macros visible at the end of the module
|
||||
pub(crate) fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
|
||||
pub(crate) fn legacy_macros<'a>(
|
||||
&'a self,
|
||||
) -> impl Iterator<Item = (&'a Name, MacroRulesId)> + 'a {
|
||||
self.legacy_macros.iter().map(|(name, def)| (name, *def))
|
||||
}
|
||||
|
||||
|
@ -163,8 +166,8 @@ impl ItemScope {
|
|||
pub(crate) fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a {
|
||||
self.types
|
||||
.values()
|
||||
.filter_map(|(def, _)| match def {
|
||||
ModuleDefId::TraitId(t) => Some(*t),
|
||||
.filter_map(|&(def, _)| match def {
|
||||
ModuleDefId::TraitId(t) => Some(t),
|
||||
_ => None,
|
||||
})
|
||||
.chain(self.unnamed_trait_imports.keys().copied())
|
||||
|
@ -174,11 +177,11 @@ impl ItemScope {
|
|||
self.declarations.push(def)
|
||||
}
|
||||
|
||||
pub(crate) fn declare_macro(&mut self, def: MacroDefId) {
|
||||
pub(crate) fn declare_macro(&mut self, def: MacroId) {
|
||||
self.macro_declarations.push(def);
|
||||
}
|
||||
|
||||
pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option<MacroDefId> {
|
||||
pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option<MacroRulesId> {
|
||||
self.legacy_macros.get(name).copied()
|
||||
}
|
||||
|
||||
|
@ -190,7 +193,7 @@ impl ItemScope {
|
|||
self.unnamed_consts.push(konst);
|
||||
}
|
||||
|
||||
pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroDefId) {
|
||||
pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroRulesId) {
|
||||
self.legacy_macros.insert(name, mac);
|
||||
}
|
||||
|
||||
|
@ -320,7 +323,7 @@ impl ItemScope {
|
|||
)
|
||||
}
|
||||
|
||||
pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> {
|
||||
pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroRulesId> {
|
||||
self.legacy_macros.clone()
|
||||
}
|
||||
|
||||
|
@ -334,7 +337,7 @@ impl ItemScope {
|
|||
.for_each(|vis| *vis = Visibility::Module(this_module));
|
||||
|
||||
for (mac, vis) in self.macros.values_mut() {
|
||||
if let MacroDefKind::ProcMacro(..) = mac.kind {
|
||||
if let MacroId::ProcMacroId(_) = mac {
|
||||
// FIXME: Technically this is insufficient since reexports of proc macros are also
|
||||
// forbidden. Practically nobody does that.
|
||||
continue;
|
||||
|
@ -421,6 +424,7 @@ impl PerNs {
|
|||
ModuleDefId::TraitId(_) => PerNs::types(def, v),
|
||||
ModuleDefId::TypeAliasId(_) => PerNs::types(def, v),
|
||||
ModuleDefId::BuiltinType(_) => PerNs::types(def, v),
|
||||
ModuleDefId::MacroId(mac) => PerNs::macros(mac, v),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -429,7 +433,7 @@ impl PerNs {
|
|||
pub enum ItemInNs {
|
||||
Types(ModuleDefId),
|
||||
Values(ModuleDefId),
|
||||
Macros(MacroDefId),
|
||||
Macros(MacroId),
|
||||
}
|
||||
|
||||
impl ItemInNs {
|
||||
|
@ -444,7 +448,7 @@ impl ItemInNs {
|
|||
pub fn krate(&self, db: &dyn DefDatabase) -> Option<CrateId> {
|
||||
match self {
|
||||
ItemInNs::Types(did) | ItemInNs::Values(did) => did.module(db).map(|m| m.krate),
|
||||
ItemInNs::Macros(id) => Some(id.krate),
|
||||
ItemInNs::Macros(id) => Some(id.module(db).krate),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,16 @@
|
|||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use hir_expand::{MacroCallId, MacroDefId};
|
||||
use hir_expand::MacroCallId;
|
||||
use rustc_hash::FxHashMap;
|
||||
use syntax::{ast, AstNode, AstPtr};
|
||||
|
||||
use crate::{
|
||||
attr::AttrId,
|
||||
dyn_map::{DynMap, Policy},
|
||||
ConstId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId, StaticId,
|
||||
StructId, TraitId, TypeAliasId, TypeOrConstParamId, UnionId,
|
||||
ConstId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId, Macro2Id,
|
||||
MacroRulesId, ProcMacroId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId,
|
||||
UnionId,
|
||||
};
|
||||
|
||||
pub type Key<K, V> = crate::dyn_map::Key<K, V, AstPtrPolicy<K, V>>;
|
||||
|
@ -32,7 +33,9 @@ pub const TYPE_PARAM: Key<ast::TypeParam, TypeOrConstParamId> = Key::new();
|
|||
pub const CONST_PARAM: Key<ast::ConstParam, TypeOrConstParamId> = Key::new();
|
||||
pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new();
|
||||
|
||||
pub const MACRO: Key<ast::Macro, MacroDefId> = Key::new();
|
||||
pub const MACRO_RULES: Key<ast::MacroRules, MacroRulesId> = Key::new();
|
||||
pub const MACRO2: Key<ast::MacroDef, Macro2Id> = Key::new();
|
||||
pub const PROC_MACRO: Key<ast::Fn, ProcMacroId> = Key::new();
|
||||
pub const ATTR_MACRO_CALL: Key<ast::Item, MacroCallId> = Key::new();
|
||||
pub const DERIVE_MACRO_CALL: Key<ast::Attr, (AttrId, MacroCallId, Box<[Option<MacroCallId>]>)> =
|
||||
Key::new();
|
||||
|
|
|
@ -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,
|
||||
ModuleId,
|
||||
FunctionId,
|
||||
AdtId(StructId, EnumId, UnionId),
|
||||
|
@ -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,
|
||||
})
|
||||
}
|
||||
|
@ -762,7 +839,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 +856,74 @@ fn macro_call_as_call_id(
|
|||
Ok(res)
|
||||
}
|
||||
|
||||
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>,
|
||||
|
|
|
@ -33,8 +33,8 @@ use syntax::{
|
|||
use tt::{Subtree, TokenId};
|
||||
|
||||
use crate::{
|
||||
db::DefDatabase, nameres::ModuleSource, resolver::HasResolver, src::HasSource, test_db::TestDB,
|
||||
AdtId, AsMacroCall, Lookup, ModuleDefId,
|
||||
db::DefDatabase, macro_id_to_def_id, nameres::ModuleSource, resolver::HasResolver,
|
||||
src::HasSource, test_db::TestDB, AdtId, AsMacroCall, Lookup, ModuleDefId,
|
||||
};
|
||||
|
||||
#[track_caller]
|
||||
|
@ -128,7 +128,9 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
|
|||
.as_call_id_with_errors(
|
||||
&db,
|
||||
krate,
|
||||
|path| resolver.resolve_path_as_macro(&db, &path),
|
||||
|path| {
|
||||
resolver.resolve_path_as_macro(&db, &path).map(|it| macro_id_to_def_id(&db, it))
|
||||
},
|
||||
&mut |err| error = Some(err),
|
||||
)
|
||||
.unwrap()
|
||||
|
|
|
@ -8,6 +8,7 @@ use crate::{
|
|||
attr_macro_as_call_id, builtin_attr,
|
||||
db::DefDatabase,
|
||||
item_scope::BuiltinShadowMode,
|
||||
macro_id_to_def_id,
|
||||
nameres::path_resolution::ResolveMode,
|
||||
path::{ModPath, PathKind},
|
||||
AstIdWithPath, LocalModuleId, UnresolvedMacro,
|
||||
|
@ -45,7 +46,7 @@ impl DefMap {
|
|||
);
|
||||
let def = match resolved_res.resolved_def.take_macros() {
|
||||
Some(def) => {
|
||||
if def.is_attribute() {
|
||||
if def.is_attribute(db) {
|
||||
def
|
||||
} else {
|
||||
return Ok(ResolvedAttr::Other);
|
||||
|
@ -54,7 +55,14 @@ impl DefMap {
|
|||
None => return Err(UnresolvedMacro { path: ast_id.path.clone() }),
|
||||
};
|
||||
|
||||
Ok(ResolvedAttr::Macro(attr_macro_as_call_id(db, &ast_id, attr, self.krate, def, false)))
|
||||
Ok(ResolvedAttr::Macro(attr_macro_as_call_id(
|
||||
db,
|
||||
&ast_id,
|
||||
attr,
|
||||
self.krate,
|
||||
macro_id_to_def_id(db, def),
|
||||
false,
|
||||
)))
|
||||
}
|
||||
|
||||
pub(crate) fn is_builtin_or_registered_attr(&self, path: &ModPath) -> bool {
|
||||
|
|
|
@ -5,8 +5,9 @@
|
|||
|
||||
use std::iter;
|
||||
|
||||
use base_db::{CrateId, Edition, FileId, ProcMacroId};
|
||||
use base_db::{CrateId, Edition, FileId};
|
||||
use cfg::{CfgExpr, CfgOptions};
|
||||
use either::Either;
|
||||
use hir_expand::{
|
||||
ast_id_map::FileAstId,
|
||||
builtin_attr_macro::find_builtin_attr,
|
||||
|
@ -34,7 +35,7 @@ use crate::{
|
|||
self, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode, MacroCall,
|
||||
MacroDef, MacroRules, Mod, ModItem, ModKind, TreeId,
|
||||
},
|
||||
macro_call_as_call_id,
|
||||
macro_call_as_call_id, macro_id_to_def_id,
|
||||
nameres::{
|
||||
diagnostics::DefDiagnostic,
|
||||
mod_resolution::ModDir,
|
||||
|
@ -46,8 +47,9 @@ use crate::{
|
|||
per_ns::PerNs,
|
||||
visibility::{RawVisibility, Visibility},
|
||||
AdtId, AstId, AstIdWithPath, ConstLoc, EnumLoc, EnumVariantId, ExternBlockLoc, FunctionLoc,
|
||||
ImplLoc, Intern, ItemContainerId, LocalModuleId, ModuleDefId, StaticLoc, StructLoc, TraitLoc,
|
||||
TypeAliasLoc, UnionLoc, UnresolvedMacro,
|
||||
ImplLoc, Intern, ItemContainerId, LocalModuleId, Macro2Id, Macro2Loc, MacroExpander, MacroId,
|
||||
MacroRulesId, MacroRulesLoc, ModuleDefId, ModuleId, ProcMacroId, ProcMacroLoc, StaticLoc,
|
||||
StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro,
|
||||
};
|
||||
|
||||
static GLOB_RECURSION_LIMIT: Limit = Limit::new(100);
|
||||
|
@ -79,7 +81,10 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap, tree_id: T
|
|||
.map(|(idx, it)| {
|
||||
// FIXME: a hacky way to create a Name from string.
|
||||
let name = tt::Ident { text: it.name.clone(), id: tt::TokenId::unspecified() };
|
||||
(name.as_name(), ProcMacroExpander::new(def_map.krate, ProcMacroId(idx as u32)))
|
||||
(
|
||||
name.as_name(),
|
||||
ProcMacroExpander::new(def_map.krate, base_db::ProcMacroId(idx as u32)),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -543,28 +548,26 @@ impl DefCollector<'_> {
|
|||
/// use a dummy expander that always errors. This comes with the drawback of macros potentially
|
||||
/// going out of sync with what the build system sees (since we resolve using VFS state, but
|
||||
/// Cargo builds only on-disk files). We could and probably should add diagnostics for that.
|
||||
fn export_proc_macro(&mut self, def: ProcMacroDef, ast_id: AstId<ast::Fn>) {
|
||||
fn export_proc_macro(
|
||||
&mut self,
|
||||
def: ProcMacroDef,
|
||||
id: ItemTreeId<item_tree::Function>,
|
||||
module_id: ModuleId,
|
||||
) {
|
||||
let kind = def.kind.to_basedb_kind();
|
||||
self.exports_proc_macros = true;
|
||||
let macro_def = match self.proc_macros.iter().find(|(n, _)| n == &def.name) {
|
||||
Some(&(_, expander)) => MacroDefId {
|
||||
krate: self.def_map.krate,
|
||||
kind: MacroDefKind::ProcMacro(expander, kind, ast_id),
|
||||
local_inner: false,
|
||||
},
|
||||
None => MacroDefId {
|
||||
krate: self.def_map.krate,
|
||||
kind: MacroDefKind::ProcMacro(
|
||||
ProcMacroExpander::dummy(self.def_map.krate),
|
||||
kind,
|
||||
ast_id,
|
||||
),
|
||||
local_inner: false,
|
||||
},
|
||||
|
||||
let (expander, kind) = match self.proc_macros.iter().find(|(n, _)| n == &def.name) {
|
||||
Some(&(_, expander)) => (expander, kind),
|
||||
None => (ProcMacroExpander::dummy(self.def_map.krate), kind),
|
||||
};
|
||||
|
||||
self.define_proc_macro(def.name.clone(), macro_def);
|
||||
self.def_map.exported_proc_macros.insert(macro_def, def);
|
||||
let proc_macro_id =
|
||||
ProcMacroLoc { container: module_id, id, expander, kind }.intern(self.db);
|
||||
self.define_proc_macro(def.name.clone(), proc_macro_id.into());
|
||||
self.def_map
|
||||
.exported_proc_macros
|
||||
.insert(macro_id_to_def_id(self.db, proc_macro_id.into()), def);
|
||||
}
|
||||
|
||||
/// Define a macro with `macro_rules`.
|
||||
|
@ -596,11 +599,12 @@ impl DefCollector<'_> {
|
|||
&mut self,
|
||||
module_id: LocalModuleId,
|
||||
name: Name,
|
||||
macro_: MacroDefId,
|
||||
macro_: MacroRulesId,
|
||||
export: bool,
|
||||
) {
|
||||
// Textual scoping
|
||||
self.define_legacy_macro(module_id, name.clone(), macro_);
|
||||
let macro_ = macro_.into();
|
||||
self.def_map.modules[module_id].scope.declare_macro(macro_);
|
||||
|
||||
// Module scoping
|
||||
|
@ -623,7 +627,7 @@ impl DefCollector<'_> {
|
|||
/// the definition of current module.
|
||||
/// And also, `macro_use` on a module will import all legacy macros visible inside to
|
||||
/// current legacy scope, with possible shadowing.
|
||||
fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, mac: MacroDefId) {
|
||||
fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, mac: MacroRulesId) {
|
||||
// Always shadowing
|
||||
self.def_map.modules[module_id].scope.define_legacy_macro(name, mac);
|
||||
}
|
||||
|
@ -635,11 +639,12 @@ impl DefCollector<'_> {
|
|||
&mut self,
|
||||
module_id: LocalModuleId,
|
||||
name: Name,
|
||||
macro_: MacroDefId,
|
||||
macro_: Macro2Id,
|
||||
vis: &RawVisibility,
|
||||
) {
|
||||
let vis =
|
||||
self.def_map.resolve_visibility(self.db, module_id, vis).unwrap_or(Visibility::Public);
|
||||
let macro_ = macro_.into();
|
||||
self.def_map.modules[module_id].scope.declare_macro(macro_);
|
||||
self.update(module_id, &[(Some(name), PerNs::macros(macro_, vis))], vis, ImportType::Named);
|
||||
}
|
||||
|
@ -648,7 +653,8 @@ impl DefCollector<'_> {
|
|||
///
|
||||
/// A proc macro is similar to normal macro scope, but it would not visible in legacy textual scoped.
|
||||
/// And unconditionally exported.
|
||||
fn define_proc_macro(&mut self, name: Name, macro_: MacroDefId) {
|
||||
fn define_proc_macro(&mut self, name: Name, macro_: ProcMacroId) {
|
||||
let macro_ = macro_.into();
|
||||
self.def_map.modules[self.def_map.root].scope.declare_macro(macro_);
|
||||
self.update(
|
||||
self.def_map.root,
|
||||
|
@ -691,10 +697,12 @@ impl DefCollector<'_> {
|
|||
fn import_all_macros_exported(&mut self, current_module_id: LocalModuleId, krate: CrateId) {
|
||||
let def_map = self.db.crate_def_map(krate);
|
||||
for (name, def) in def_map[def_map.root].scope.macros() {
|
||||
if let MacroId::MacroRulesId(def) = def {
|
||||
// `macro_use` only bring things into legacy scope.
|
||||
self.define_legacy_macro(current_module_id, name.clone(), def);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Tries to resolve every currently unresolved import.
|
||||
fn resolve_imports(&mut self) -> ReachedFixedPoint {
|
||||
|
@ -1049,7 +1057,7 @@ impl DefCollector<'_> {
|
|||
&path,
|
||||
BuiltinShadowMode::Module,
|
||||
);
|
||||
resolved_res.resolved_def.take_macros()
|
||||
resolved_res.resolved_def.take_macros().map(|it| macro_id_to_def_id(self.db, it))
|
||||
};
|
||||
|
||||
match &directive.kind {
|
||||
|
@ -1339,7 +1347,10 @@ impl DefCollector<'_> {
|
|||
&path,
|
||||
BuiltinShadowMode::Module,
|
||||
);
|
||||
resolved_res.resolved_def.take_macros()
|
||||
resolved_res
|
||||
.resolved_def
|
||||
.take_macros()
|
||||
.map(|it| macro_id_to_def_id(self.db, it))
|
||||
},
|
||||
&mut |_| (),
|
||||
);
|
||||
|
@ -1525,10 +1536,9 @@ impl ModCollector<'_, '_> {
|
|||
),
|
||||
),
|
||||
ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac], container),
|
||||
ModItem::MacroRules(id) => self.collect_macro_rules(id),
|
||||
ModItem::MacroDef(id) => self.collect_macro_def(id),
|
||||
ModItem::MacroRules(id) => self.collect_macro_rules(id, module),
|
||||
ModItem::MacroDef(id) => self.collect_macro_def(id, module),
|
||||
ModItem::Impl(imp) => {
|
||||
let module = self.def_collector.def_map.module_id(self.module_id);
|
||||
let impl_id =
|
||||
ImplLoc { container: module, id: ItemTreeId::new(self.tree_id, imp) }
|
||||
.intern(db);
|
||||
|
@ -1541,9 +1551,13 @@ impl ModCollector<'_, '_> {
|
|||
let vis = match is_proc_macro {
|
||||
Some(proc_macro) => {
|
||||
// FIXME: this should only be done in the root module of `proc-macro` crates, not everywhere
|
||||
let ast_id = InFile::new(self.tree_id.file_id(), it.ast_id);
|
||||
let module_id = def_map.module_id(def_map.root());
|
||||
self.def_collector.export_proc_macro(proc_macro, ast_id);
|
||||
|
||||
self.def_collector.export_proc_macro(
|
||||
proc_macro,
|
||||
ItemTreeId::new(self.tree_id, id),
|
||||
module_id,
|
||||
);
|
||||
Visibility::Module(module_id)
|
||||
}
|
||||
None => resolve_vis(def_map, &self.item_tree[it.visibility]),
|
||||
|
@ -1845,7 +1859,7 @@ impl ModCollector<'_, '_> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>) {
|
||||
fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>, module: ModuleId) {
|
||||
let krate = self.def_collector.def_map.krate;
|
||||
let mac = &self.item_tree[id];
|
||||
let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
|
||||
|
@ -1854,7 +1868,7 @@ impl ModCollector<'_, '_> {
|
|||
let export_attr = attrs.by_key("macro_export");
|
||||
|
||||
let is_export = export_attr.exists();
|
||||
let is_local_inner = if is_export {
|
||||
let local_inner = if is_export {
|
||||
export_attr.tt_values().flat_map(|it| &it.token_trees).any(|it| match it {
|
||||
tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
|
||||
ident.text.contains("local_inner_macros")
|
||||
|
@ -1866,7 +1880,7 @@ impl ModCollector<'_, '_> {
|
|||
};
|
||||
|
||||
// Case 1: builtin macros
|
||||
if attrs.by_key("rustc_builtin_macro").exists() {
|
||||
let expander = if attrs.by_key("rustc_builtin_macro").exists() {
|
||||
// `#[rustc_builtin_macro = "builtin_name"]` overrides the `macro_rules!` name.
|
||||
let name;
|
||||
let name = match attrs.by_key("rustc_builtin_macro").string_value() {
|
||||
|
@ -1892,32 +1906,29 @@ impl ModCollector<'_, '_> {
|
|||
}
|
||||
}
|
||||
};
|
||||
let krate = self.def_collector.def_map.krate;
|
||||
match find_builtin_macro(name, krate, ast_id) {
|
||||
Some(macro_id) => {
|
||||
self.def_collector.define_macro_rules(
|
||||
self.module_id,
|
||||
mac.name.clone(),
|
||||
macro_id,
|
||||
is_export,
|
||||
);
|
||||
return;
|
||||
}
|
||||
match find_builtin_macro(name) {
|
||||
Some(Either::Left(it)) => MacroExpander::BuiltIn(it),
|
||||
Some(Either::Right(it)) => MacroExpander::BuiltInEager(it),
|
||||
None => {
|
||||
self.def_collector
|
||||
.def_map
|
||||
.diagnostics
|
||||
.push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// Case 2: normal `macro_rules!` macro
|
||||
let macro_id = MacroDefId {
|
||||
krate: self.def_collector.def_map.krate,
|
||||
kind: MacroDefKind::Declarative(ast_id),
|
||||
local_inner: is_local_inner,
|
||||
MacroExpander::Declarative
|
||||
};
|
||||
|
||||
let macro_id = MacroRulesLoc {
|
||||
container: module,
|
||||
id: ItemTreeId::new(self.tree_id, id),
|
||||
local_inner,
|
||||
expander,
|
||||
}
|
||||
.intern(self.def_collector.db);
|
||||
self.def_collector.define_macro_rules(
|
||||
self.module_id,
|
||||
mac.name.clone(),
|
||||
|
@ -1926,44 +1937,38 @@ impl ModCollector<'_, '_> {
|
|||
);
|
||||
}
|
||||
|
||||
fn collect_macro_def(&mut self, id: FileItemTreeId<MacroDef>) {
|
||||
fn collect_macro_def(&mut self, id: FileItemTreeId<MacroDef>, module: ModuleId) {
|
||||
let krate = self.def_collector.def_map.krate;
|
||||
let mac = &self.item_tree[id];
|
||||
let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast());
|
||||
|
||||
// Case 1: builtin macros
|
||||
let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
|
||||
if attrs.by_key("rustc_builtin_macro").exists() {
|
||||
let macro_id = find_builtin_macro(&mac.name, krate, ast_id)
|
||||
.or_else(|| find_builtin_derive(&mac.name, krate, ast_id))
|
||||
.or_else(|| find_builtin_attr(&mac.name, krate, ast_id));
|
||||
|
||||
match macro_id {
|
||||
Some(macro_id) => {
|
||||
self.def_collector.define_macro_def(
|
||||
self.module_id,
|
||||
mac.name.clone(),
|
||||
macro_id,
|
||||
&self.item_tree[mac.visibility],
|
||||
);
|
||||
return;
|
||||
let expander = if attrs.by_key("rustc_builtin_macro").exists() {
|
||||
if let Some(expander) = find_builtin_macro(&mac.name) {
|
||||
match expander {
|
||||
Either::Left(it) => MacroExpander::BuiltIn(it),
|
||||
Either::Right(it) => MacroExpander::BuiltInEager(it),
|
||||
}
|
||||
None => {
|
||||
} else if let Some(expander) = find_builtin_derive(&mac.name) {
|
||||
MacroExpander::BuiltInDerive(expander)
|
||||
} else if let Some(expander) = find_builtin_attr(&mac.name) {
|
||||
MacroExpander::BuiltInAttr(expander)
|
||||
} else {
|
||||
self.def_collector
|
||||
.def_map
|
||||
.diagnostics
|
||||
.push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// Case 2: normal `macro`
|
||||
let macro_id = MacroDefId {
|
||||
krate: self.def_collector.def_map.krate,
|
||||
kind: MacroDefKind::Declarative(ast_id),
|
||||
local_inner: false,
|
||||
MacroExpander::Declarative
|
||||
};
|
||||
|
||||
let macro_id =
|
||||
Macro2Loc { container: module, id: ItemTreeId::new(self.tree_id, id), expander }
|
||||
.intern(self.def_collector.db);
|
||||
self.def_collector.define_macro_def(
|
||||
self.module_id,
|
||||
mac.name.clone(),
|
||||
|
@ -1987,7 +1992,12 @@ impl ModCollector<'_, '_> {
|
|||
self.def_collector.def_map.with_ancestor_maps(
|
||||
self.def_collector.db,
|
||||
self.module_id,
|
||||
&mut |map, module| map[module].scope.get_legacy_macro(name),
|
||||
&mut |map, module| {
|
||||
map[module]
|
||||
.scope
|
||||
.get_legacy_macro(name)
|
||||
.map(|it| macro_id_to_def_id(self.def_collector.db, it.into()))
|
||||
},
|
||||
)
|
||||
})
|
||||
},
|
||||
|
|
|
@ -389,7 +389,7 @@ impl DefMap {
|
|||
let from_legacy_macro = self[module]
|
||||
.scope
|
||||
.get_legacy_macro(name)
|
||||
.map_or_else(PerNs::none, |m| PerNs::macros(m, Visibility::Public));
|
||||
.map_or_else(PerNs::none, |m| PerNs::macros(m.into(), Visibility::Public));
|
||||
let from_scope = self[module].scope.get(name);
|
||||
let from_builtin = match self.block {
|
||||
Some(_) => {
|
||||
|
|
|
@ -226,6 +226,7 @@ pub type Ty = ();
|
|||
ModuleDefId::TypeAliasId(it) => drop(db.type_alias_data(it)),
|
||||
ModuleDefId::EnumVariantId(_)
|
||||
| ModuleDefId::ModuleId(_)
|
||||
| ModuleDefId::MacroId(_)
|
||||
| ModuleDefId::BuiltinType(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,15 +3,13 @@
|
|||
//!
|
||||
//! `PerNs` (per namespace) captures this.
|
||||
|
||||
use hir_expand::MacroDefId;
|
||||
|
||||
use crate::{item_scope::ItemInNs, visibility::Visibility, ModuleDefId};
|
||||
use crate::{item_scope::ItemInNs, visibility::Visibility, MacroId, ModuleDefId};
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct PerNs {
|
||||
pub types: Option<(ModuleDefId, Visibility)>,
|
||||
pub values: Option<(ModuleDefId, Visibility)>,
|
||||
pub macros: Option<(MacroDefId, Visibility)>,
|
||||
pub macros: Option<(MacroId, Visibility)>,
|
||||
}
|
||||
|
||||
impl Default for PerNs {
|
||||
|
@ -37,7 +35,7 @@ impl PerNs {
|
|||
PerNs { types: Some((types, v)), values: Some((values, v)), macros: None }
|
||||
}
|
||||
|
||||
pub fn macros(macro_: MacroDefId, v: Visibility) -> PerNs {
|
||||
pub fn macros(macro_: MacroId, v: Visibility) -> PerNs {
|
||||
PerNs { types: None, values: None, macros: Some((macro_, v)) }
|
||||
}
|
||||
|
||||
|
@ -57,7 +55,7 @@ impl PerNs {
|
|||
self.values.map(|it| it.0)
|
||||
}
|
||||
|
||||
pub fn take_macros(self) -> Option<MacroDefId> {
|
||||
pub fn take_macros(self) -> Option<MacroId> {
|
||||
self.macros.map(|it| it.0)
|
||||
}
|
||||
|
||||
|
|
|
@ -2,10 +2,7 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use base_db::CrateId;
|
||||
use hir_expand::{
|
||||
name::{name, Name},
|
||||
MacroDefId,
|
||||
};
|
||||
use hir_expand::name::{name, Name};
|
||||
use indexmap::IndexMap;
|
||||
use rustc_hash::FxHashSet;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
|
@ -24,8 +21,8 @@ use crate::{
|
|||
visibility::{RawVisibility, Visibility},
|
||||
AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId,
|
||||
FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, ItemContainerId, LifetimeParamId,
|
||||
LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, TypeAliasId,
|
||||
TypeOrConstParamId, TypeParamId, VariantId,
|
||||
LocalModuleId, Lookup, MacroId, ModuleDefId, ModuleId, StaticId, StructId, TraitId,
|
||||
TypeAliasId, TypeOrConstParamId, TypeParamId, VariantId,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
|
@ -347,11 +344,7 @@ impl Resolver {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn resolve_path_as_macro(
|
||||
&self,
|
||||
db: &dyn DefDatabase,
|
||||
path: &ModPath,
|
||||
) -> Option<MacroDefId> {
|
||||
pub fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroId> {
|
||||
let (item_map, module) = self.module_scope()?;
|
||||
item_map.resolve_path(db, module, path, BuiltinShadowMode::Other).0.take_macros()
|
||||
}
|
||||
|
@ -485,7 +478,6 @@ impl Resolver {
|
|||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum ScopeDef {
|
||||
ModuleDef(ModuleDefId),
|
||||
MacroDef(MacroDefId),
|
||||
Unknown,
|
||||
ImplSelfType(ImplId),
|
||||
AdtSelfType(AdtId),
|
||||
|
@ -509,7 +501,7 @@ impl Scope {
|
|||
acc.add_per_ns(name, def);
|
||||
});
|
||||
m.def_map[m.module_id].scope.legacy_macros().for_each(|(name, mac)| {
|
||||
acc.add(name, ScopeDef::MacroDef(mac));
|
||||
acc.add(name, ScopeDef::ModuleDef(ModuleDefId::MacroId(MacroId::from(mac))));
|
||||
});
|
||||
m.def_map.extern_prelude().for_each(|(name, &def)| {
|
||||
acc.add(name, ScopeDef::ModuleDef(def));
|
||||
|
@ -651,6 +643,7 @@ impl ModuleItemMap {
|
|||
| ModuleDefId::FunctionId(_)
|
||||
| ModuleDefId::EnumVariantId(_)
|
||||
| ModuleDefId::ConstId(_)
|
||||
| ModuleDefId::MacroId(_)
|
||||
| ModuleDefId::StaticId(_) => return None,
|
||||
};
|
||||
Some(ResolveValueResult::Partial(ty, idx))
|
||||
|
@ -682,6 +675,7 @@ fn to_value_ns(per_ns: PerNs) -> Option<ValueNs> {
|
|||
| ModuleDefId::TraitId(_)
|
||||
| ModuleDefId::TypeAliasId(_)
|
||||
| ModuleDefId::BuiltinType(_)
|
||||
| ModuleDefId::MacroId(_)
|
||||
| ModuleDefId::ModuleId(_) => return None,
|
||||
};
|
||||
Some(res)
|
||||
|
@ -699,6 +693,7 @@ fn to_type_ns(per_ns: PerNs) -> Option<TypeNs> {
|
|||
|
||||
ModuleDefId::FunctionId(_)
|
||||
| ModuleDefId::ConstId(_)
|
||||
| ModuleDefId::MacroId(_)
|
||||
| ModuleDefId::StaticId(_)
|
||||
| ModuleDefId::ModuleId(_) => return None,
|
||||
};
|
||||
|
@ -718,14 +713,14 @@ impl ScopeNames {
|
|||
}
|
||||
}
|
||||
fn add_per_ns(&mut self, name: &Name, def: PerNs) {
|
||||
if let Some(ty) = &def.types {
|
||||
self.add(name, ScopeDef::ModuleDef(ty.0))
|
||||
if let &Some((ty, _)) = &def.types {
|
||||
self.add(name, ScopeDef::ModuleDef(ty))
|
||||
}
|
||||
if let Some(val) = &def.values {
|
||||
self.add(name, ScopeDef::ModuleDef(val.0))
|
||||
if let &Some((def, _)) = &def.values {
|
||||
self.add(name, ScopeDef::ModuleDef(def))
|
||||
}
|
||||
if let Some(mac) = &def.macros {
|
||||
self.add(name, ScopeDef::MacroDef(mac.0))
|
||||
if let &Some((mac, _)) = &def.macros {
|
||||
self.add(name, ScopeDef::ModuleDef(ModuleDefId::MacroId(mac)))
|
||||
}
|
||||
if def.is_none() {
|
||||
self.add(name, ScopeDef::Unknown)
|
||||
|
|
|
@ -2,8 +2,12 @@
|
|||
|
||||
use hir_expand::InFile;
|
||||
use la_arena::ArenaMap;
|
||||
use syntax::ast;
|
||||
|
||||
use crate::{db::DefDatabase, item_tree::ItemTreeNode, AssocItemLoc, ItemLoc};
|
||||
use crate::{
|
||||
db::DefDatabase, item_tree::ItemTreeNode, AssocItemLoc, ItemLoc, Macro2Loc, MacroRulesLoc,
|
||||
ProcMacroLoc,
|
||||
};
|
||||
|
||||
pub trait HasSource {
|
||||
type Value;
|
||||
|
@ -36,6 +40,45 @@ impl<N: ItemTreeNode> HasSource for ItemLoc<N> {
|
|||
}
|
||||
}
|
||||
|
||||
impl HasSource for Macro2Loc {
|
||||
type Value = ast::MacroDef;
|
||||
|
||||
fn source(&self, db: &dyn DefDatabase) -> InFile<Self::Value> {
|
||||
let tree = self.id.item_tree(db);
|
||||
let ast_id_map = db.ast_id_map(self.id.file_id());
|
||||
let root = db.parse_or_expand(self.id.file_id()).unwrap();
|
||||
let node = &tree[self.id.value];
|
||||
|
||||
InFile::new(self.id.file_id(), ast_id_map.get(node.ast_id()).to_node(&root))
|
||||
}
|
||||
}
|
||||
|
||||
impl HasSource for MacroRulesLoc {
|
||||
type Value = ast::MacroRules;
|
||||
|
||||
fn source(&self, db: &dyn DefDatabase) -> InFile<Self::Value> {
|
||||
let tree = self.id.item_tree(db);
|
||||
let ast_id_map = db.ast_id_map(self.id.file_id());
|
||||
let root = db.parse_or_expand(self.id.file_id()).unwrap();
|
||||
let node = &tree[self.id.value];
|
||||
|
||||
InFile::new(self.id.file_id(), ast_id_map.get(node.ast_id()).to_node(&root))
|
||||
}
|
||||
}
|
||||
|
||||
impl HasSource for ProcMacroLoc {
|
||||
type Value = ast::Fn;
|
||||
|
||||
fn source(&self, db: &dyn DefDatabase) -> InFile<Self::Value> {
|
||||
let tree = self.id.item_tree(db);
|
||||
let ast_id_map = db.ast_id_map(self.id.file_id());
|
||||
let root = db.parse_or_expand(self.id.file_id()).unwrap();
|
||||
let node = &tree[self.id.value];
|
||||
|
||||
InFile::new(self.id.file_id(), ast_id_map.get(node.ast_id()).to_node(&root))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HasChildSource<ChildId> {
|
||||
type Value;
|
||||
fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<ChildId, Self::Value>>;
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
//! Builtin attributes.
|
||||
|
||||
use itertools::Itertools;
|
||||
use syntax::ast;
|
||||
|
||||
use crate::{
|
||||
db::AstDatabase, name, AstId, CrateId, ExpandResult, MacroCallId, MacroCallKind, MacroDefId,
|
||||
MacroDefKind,
|
||||
};
|
||||
use crate::{db::AstDatabase, name, ExpandResult, MacroCallId, MacroCallKind};
|
||||
|
||||
macro_rules! register_builtin {
|
||||
( $(($name:ident, $variant:ident) => $expand:ident),* ) => {
|
||||
|
@ -61,17 +57,8 @@ register_builtin! {
|
|||
(test_case, TestCase) => dummy_attr_expand
|
||||
}
|
||||
|
||||
pub fn find_builtin_attr(
|
||||
ident: &name::Name,
|
||||
krate: CrateId,
|
||||
ast_id: AstId<ast::Macro>,
|
||||
) -> Option<MacroDefId> {
|
||||
let expander = BuiltinAttrExpander::find_by_name(ident)?;
|
||||
Some(MacroDefId {
|
||||
krate,
|
||||
kind: MacroDefKind::BuiltInAttr(expander, ast_id),
|
||||
local_inner: false,
|
||||
})
|
||||
pub fn find_builtin_attr(ident: &name::Name) -> Option<BuiltinAttrExpander> {
|
||||
BuiltinAttrExpander::find_by_name(ident)
|
||||
}
|
||||
|
||||
fn dummy_attr_expand(
|
||||
|
|
|
@ -8,10 +8,7 @@ use syntax::{
|
|||
};
|
||||
use tt::TokenId;
|
||||
|
||||
use crate::{
|
||||
db::AstDatabase, name, quote, AstId, CrateId, ExpandError, ExpandResult, MacroCallId,
|
||||
MacroDefId, MacroDefKind,
|
||||
};
|
||||
use crate::{db::AstDatabase, name, quote, ExpandError, ExpandResult, MacroCallId};
|
||||
|
||||
macro_rules! register_builtin {
|
||||
( $($trait:ident => $expand:ident),* ) => {
|
||||
|
@ -56,17 +53,8 @@ register_builtin! {
|
|||
PartialEq => partial_eq_expand
|
||||
}
|
||||
|
||||
pub fn find_builtin_derive(
|
||||
ident: &name::Name,
|
||||
krate: CrateId,
|
||||
ast_id: AstId<ast::Macro>,
|
||||
) -> Option<MacroDefId> {
|
||||
let expander = BuiltinDeriveExpander::find_by_name(ident)?;
|
||||
Some(MacroDefId {
|
||||
krate,
|
||||
kind: MacroDefKind::BuiltInDerive(expander, ast_id),
|
||||
local_inner: false,
|
||||
})
|
||||
pub fn find_builtin_derive(ident: &name::Name) -> Option<BuiltinDeriveExpander> {
|
||||
BuiltinDeriveExpander::find_by_name(ident)
|
||||
}
|
||||
|
||||
struct BasicAdtInfo {
|
||||
|
|
|
@ -9,10 +9,7 @@ use syntax::{
|
|||
SmolStr,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
db::AstDatabase, name, quote, AstId, CrateId, ExpandError, ExpandResult, MacroCallId,
|
||||
MacroCallLoc, MacroDefId, MacroDefKind,
|
||||
};
|
||||
use crate::{db::AstDatabase, name, quote, ExpandError, ExpandResult, MacroCallId, MacroCallLoc};
|
||||
|
||||
macro_rules! register_builtin {
|
||||
( LAZY: $(($name:ident, $kind: ident) => $expand:ident),* , EAGER: $(($e_name:ident, $e_kind: ident) => $e_expand:ident),* ) => {
|
||||
|
@ -79,23 +76,8 @@ impl ExpandedEager {
|
|||
|
||||
pub fn find_builtin_macro(
|
||||
ident: &name::Name,
|
||||
krate: CrateId,
|
||||
ast_id: AstId<ast::Macro>,
|
||||
) -> Option<MacroDefId> {
|
||||
let kind = find_by_name(ident)?;
|
||||
|
||||
match kind {
|
||||
Either::Left(kind) => Some(MacroDefId {
|
||||
krate,
|
||||
kind: MacroDefKind::BuiltIn(kind, ast_id),
|
||||
local_inner: false,
|
||||
}),
|
||||
Either::Right(kind) => Some(MacroDefId {
|
||||
krate,
|
||||
kind: MacroDefKind::BuiltInEager(kind, ast_id),
|
||||
local_inner: false,
|
||||
}),
|
||||
}
|
||||
) -> Option<Either<BuiltinFnLikeExpander, EagerExpander>> {
|
||||
find_by_name(ident)
|
||||
}
|
||||
|
||||
register_builtin! {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue