internal: Record all macro definitions in ItemScope

This commit is contained in:
Lukas Wirth 2022-07-05 11:28:47 +02:00
parent cd42b20ce3
commit db49ac8734
9 changed files with 57 additions and 27 deletions

View File

@ -102,13 +102,15 @@ fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: Hi
res[keys::ATTR_MACRO_CALL].insert(ast_id.to_node(db.upcast()), call_id); res[keys::ATTR_MACRO_CALL].insert(ast_id.to_node(db.upcast()), call_id);
}, },
); );
self.legacy_macros().for_each(|(_, id)| { self.legacy_macros().for_each(|(_, ids)| {
ids.iter().for_each(|&id| {
if let MacroId::MacroRulesId(id) = id { if let MacroId::MacroRulesId(id) = id {
let loc = id.lookup(db); let loc = id.lookup(db);
if loc.id.file_id() == file_id { if loc.id.file_id() == file_id {
res[keys::MACRO_RULES].insert(loc.source(db).value, id); res[keys::MACRO_RULES].insert(loc.source(db).value, id);
} }
} }
})
}); });
self.derive_macro_invocs().filter(|(id, _)| id.file_id == file_id).for_each( self.derive_macro_invocs().filter(|(id, _)| id.file_id == file_id).for_each(
|(ast_id, calls)| { |(ast_id, calls)| {

View File

@ -61,7 +61,7 @@ pub struct ItemScope {
/// Module scoped macros will be inserted into `items` instead of here. /// 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 // 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. // be all resolved to the last one defined if shadowing happens.
legacy_macros: FxHashMap<Name, MacroId>, legacy_macros: FxHashMap<Name, SmallVec<[MacroId; 1]>>,
/// The derive macro invocations in this scope. /// The derive macro invocations in this scope.
attr_macros: FxHashMap<AstId<ast::Item>, MacroCallId>, attr_macros: FxHashMap<AstId<ast::Item>, MacroCallId>,
/// The derive macro invocations in this scope, keyed by the owner item over the actual derive attributes /// The derive macro invocations in this scope, keyed by the owner item over the actual derive attributes
@ -129,13 +129,13 @@ pub fn unnamed_consts(&self) -> impl Iterator<Item = ConstId> + '_ {
} }
/// Iterate over all module scoped macros /// Iterate over all module scoped macros
pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroId)> + 'a { pub(crate) fn macros(&self) -> impl Iterator<Item = (&Name, MacroId)> + '_ {
self.entries().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_))) 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 /// Iterate over all legacy textual scoped macros visible at the end of the module
pub fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroId)> + 'a { pub fn legacy_macros(&self) -> impl Iterator<Item = (&Name, &[MacroId])> + '_ {
self.legacy_macros.iter().map(|(name, def)| (name, *def)) self.legacy_macros.iter().map(|(name, def)| (name, &**def))
} }
/// Get a name from current module scope, legacy macros are not included /// Get a name from current module scope, legacy macros are not included
@ -180,8 +180,8 @@ pub(crate) fn declare(&mut self, def: ModuleDefId) {
self.declarations.push(def) self.declarations.push(def)
} }
pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option<MacroId> { pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option<&[MacroId]> {
self.legacy_macros.get(name).copied() self.legacy_macros.get(name).map(|it| &**it)
} }
pub(crate) fn define_impl(&mut self, imp: ImplId) { pub(crate) fn define_impl(&mut self, imp: ImplId) {
@ -193,7 +193,7 @@ pub(crate) fn define_unnamed_const(&mut self, konst: ConstId) {
} }
pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroId) { pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroId) {
self.legacy_macros.insert(name, mac); self.legacy_macros.entry(name).or_default().push(mac);
} }
pub(crate) fn add_attr_macro_invoc(&mut self, item: AstId<ast::Item>, call: MacroCallId) { pub(crate) fn add_attr_macro_invoc(&mut self, item: AstId<ast::Item>, call: MacroCallId) {
@ -322,7 +322,7 @@ pub(crate) fn resolutions<'a>(&'a self) -> impl Iterator<Item = (Option<Name>, P
) )
} }
pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroId> { pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, SmallVec<[MacroId; 1]>> {
self.legacy_macros.clone() self.legacy_macros.clone()
} }

View File

@ -1809,7 +1809,9 @@ fn push_child_module(
let res = modules.alloc(ModuleData::new(origin, vis)); let res = modules.alloc(ModuleData::new(origin, vis));
modules[res].parent = Some(self.module_id); modules[res].parent = Some(self.module_id);
for (name, mac) in modules[self.module_id].scope.collect_legacy_macros() { for (name, mac) in modules[self.module_id].scope.collect_legacy_macros() {
modules[res].scope.define_legacy_macro(name, mac) for &mac in &mac {
modules[res].scope.define_legacy_macro(name.clone(), mac);
}
} }
modules[self.module_id].children.insert(name.clone(), res); modules[self.module_id].children.insert(name.clone(), res);
@ -2027,7 +2029,8 @@ fn collect_macro_call(&mut self, mac: &MacroCall, container: ItemContainerId) {
map[module] map[module]
.scope .scope
.get_legacy_macro(name) .get_legacy_macro(name)
.map(|it| macro_id_to_def_id(self.def_collector.db, it.into())) .and_then(|it| it.last())
.map(|&it| macro_id_to_def_id(self.def_collector.db, it.into()))
}, },
) )
}) })
@ -2080,8 +2083,10 @@ fn collect_macro_call(&mut self, mac: &MacroCall, container: ItemContainerId) {
fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) { fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) {
let macros = self.def_collector.def_map[module_id].scope.collect_legacy_macros(); let macros = self.def_collector.def_map[module_id].scope.collect_legacy_macros();
for (name, macro_) in macros { for (name, macs) in macros {
self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_); macs.last().map(|&mac| {
self.def_collector.define_legacy_macro(self.module_id, name.clone(), mac)
});
} }
} }

View File

@ -381,7 +381,9 @@ fn resolve_name_in_module(
let from_legacy_macro = self[module] let from_legacy_macro = self[module]
.scope .scope
.get_legacy_macro(name) .get_legacy_macro(name)
.map_or_else(PerNs::none, |m| PerNs::macros(m.into(), Visibility::Public)); // FIXME: shadowing
.and_then(|it| it.last())
.map_or_else(PerNs::none, |&m| PerNs::macros(m.into(), Visibility::Public));
let from_scope = self[module].scope.get(name); let from_scope = self[module].scope.get(name);
let from_builtin = match self.block { let from_builtin = match self.block {
Some(_) => { Some(_) => {

View File

@ -508,8 +508,13 @@ fn process_names(&self, acc: &mut ScopeNames, db: &dyn DefDatabase) {
m.def_map[m.module_id].scope.entries().for_each(|(name, def)| { m.def_map[m.module_id].scope.entries().for_each(|(name, def)| {
acc.add_per_ns(name, def); acc.add_per_ns(name, def);
}); });
m.def_map[m.module_id].scope.legacy_macros().for_each(|(name, mac)| { m.def_map[m.module_id].scope.legacy_macros().for_each(|(name, macs)| {
acc.add(name, ScopeDef::ModuleDef(ModuleDefId::MacroId(MacroId::from(mac)))); macs.iter().for_each(|&mac| {
acc.add(
name,
ScopeDef::ModuleDef(ModuleDefId::MacroId(MacroId::from(mac))),
);
})
}); });
m.def_map.extern_prelude().for_each(|(name, &def)| { m.def_map.extern_prelude().for_each(|(name, &def)| {
acc.add(name, ScopeDef::ModuleDef(ModuleDefId::ModuleId(def))); acc.add(name, ScopeDef::ModuleDef(ModuleDefId::ModuleId(def)));

View File

@ -559,7 +559,7 @@ pub fn declarations(self, db: &dyn HirDatabase) -> Vec<ModuleDef> {
pub fn legacy_macros(self, db: &dyn HirDatabase) -> Vec<Macro> { pub fn legacy_macros(self, db: &dyn HirDatabase) -> Vec<Macro> {
let def_map = self.id.def_map(db.upcast()); let def_map = self.id.def_map(db.upcast());
let scope = &def_map[self.id.local_id].scope; let scope = &def_map[self.id.local_id].scope;
scope.legacy_macros().map(|(_, it)| MacroId::from(it).into()).collect() scope.legacy_macros().flat_map(|(_, it)| it).map(|&it| MacroId::from(it).into()).collect()
} }
pub fn impl_defs(self, db: &dyn HirDatabase) -> Vec<Impl> { pub fn impl_defs(self, db: &dyn HirDatabase) -> Vec<Impl> {

View File

@ -176,6 +176,7 @@ fn collect_from_module(&mut self, module_id: ModuleId) {
} }
for (_, id) in scope.legacy_macros() { for (_, id) in scope.legacy_macros() {
for &id in id {
if id.module(self.db.upcast()) == module_id { if id.module(self.db.upcast()) == module_id {
match id { match id {
MacroId::Macro2Id(id) => self.push_decl(id, FileSymbolKind::Macro), MacroId::Macro2Id(id) => self.push_decl(id, FileSymbolKind::Macro),
@ -185,6 +186,7 @@ fn collect_from_module(&mut self, module_id: ModuleId) {
} }
} }
} }
}
fn collect_from_body(&mut self, body_id: impl Into<DefWithBodyId>) { fn collect_from_body(&mut self, body_id: impl Into<DefWithBodyId>) {
let body_id = body_id.into(); let body_id = body_id.into();

View File

@ -68,6 +68,13 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="brace">}</span> <span class="brace">}</span>
<span class="brace">}</span> <span class="brace">}</span>
<span class="comment documentation">/// textually shadow previous definition</span>
<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">noop</span> <span class="brace">{</span>
<span class="parenthesis">(</span><span class="punctuation">$</span>expr<span class="colon">:</span>expr<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span>
<span class="punctuation">$</span>expr
<span class="brace">}</span>
<span class="brace">}</span>
<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">keyword_frag</span> <span class="brace">{</span> <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">keyword_frag</span> <span class="brace">{</span>
<span class="parenthesis">(</span><span class="punctuation">$</span>type<span class="colon">:</span>ty<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="punctuation">$</span>type<span class="parenthesis">)</span> <span class="parenthesis">(</span><span class="punctuation">$</span>type<span class="colon">:</span>ty<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="punctuation">$</span>type<span class="parenthesis">)</span>
<span class="brace">}</span> <span class="brace">}</span>

View File

@ -63,6 +63,13 @@ macro_rules! noop {
} }
} }
/// textually shadow previous definition
macro_rules! noop {
($expr:expr) => {
$expr
}
}
macro_rules! keyword_frag { macro_rules! keyword_frag {
($type:ty) => ($type) ($type:ty) => ($type)
} }