Avoid querying attributes in item tree lowering
ItemTree is per-file, so there is no unique crate associated with it. This means that it cannot know the active CfgOptions and thus couldn't handle `cfg_attr`. Prepare it for `cfg_attr`s by avoiding accessing attributes.
This commit is contained in:
parent
067067a6c1
commit
28b5334580
@ -646,12 +646,6 @@ pub struct MacroCall {
|
||||
pub struct MacroRules {
|
||||
/// The name of the declared macro.
|
||||
pub name: Name,
|
||||
/// Has `#[macro_export]`.
|
||||
pub is_export: bool,
|
||||
/// Has `#[macro_export(local_inner_macros)]`.
|
||||
pub is_local_inner: bool,
|
||||
/// Has `#[rustc_builtin_macro]`.
|
||||
pub is_builtin: bool,
|
||||
pub ast_id: FileAstId<ast::MacroRules>,
|
||||
}
|
||||
|
||||
@ -660,8 +654,6 @@ pub struct MacroRules {
|
||||
pub struct MacroDef {
|
||||
pub name: Name,
|
||||
pub visibility: RawVisibilityId,
|
||||
/// Has `#[rustc_builtin_macro]`.
|
||||
pub is_builtin: bool,
|
||||
pub ast_id: FileAstId<ast::MacroDef>,
|
||||
}
|
||||
|
||||
|
@ -539,39 +539,19 @@ impl Ctx {
|
||||
|
||||
fn lower_macro_rules(&mut self, m: &ast::MacroRules) -> Option<FileItemTreeId<MacroRules>> {
|
||||
let name = m.name().map(|it| it.as_name())?;
|
||||
let attrs = Attrs::new(m, &self.hygiene);
|
||||
|
||||
let ast_id = self.source_ast_id_map.ast_id(m);
|
||||
|
||||
// FIXME: cfg_attr
|
||||
let export_attr = attrs.by_key("macro_export");
|
||||
|
||||
let is_export = export_attr.exists();
|
||||
let is_local_inner = if is_export {
|
||||
export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it {
|
||||
tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
|
||||
ident.text.contains("local_inner_macros")
|
||||
}
|
||||
_ => false,
|
||||
})
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let is_builtin = attrs.by_key("rustc_builtin_macro").exists();
|
||||
let res = MacroRules { name, is_export, is_builtin, is_local_inner, ast_id };
|
||||
let res = MacroRules { name, ast_id };
|
||||
Some(id(self.data().macro_rules.alloc(res)))
|
||||
}
|
||||
|
||||
fn lower_macro_def(&mut self, m: &ast::MacroDef) -> Option<FileItemTreeId<MacroDef>> {
|
||||
let name = m.name().map(|it| it.as_name())?;
|
||||
let attrs = Attrs::new(m, &self.hygiene);
|
||||
|
||||
let ast_id = self.source_ast_id_map.ast_id(m);
|
||||
let visibility = self.lower_visibility(m);
|
||||
|
||||
let is_builtin = attrs.by_key("rustc_builtin_macro").exists();
|
||||
let res = MacroDef { name, is_builtin, ast_id, visibility };
|
||||
let res = MacroDef { name, ast_id, visibility };
|
||||
Some(id(self.data().macro_defs.alloc(res)))
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,8 @@ use crate::{
|
||||
db::DefDatabase,
|
||||
item_scope::{ImportType, PerNsGlobImports},
|
||||
item_tree::{
|
||||
self, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind, StructDefKind,
|
||||
self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind,
|
||||
StructDefKind,
|
||||
},
|
||||
nameres::{
|
||||
diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
|
||||
@ -967,14 +968,15 @@ impl ModCollector<'_, '_> {
|
||||
})
|
||||
}
|
||||
ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]),
|
||||
ModItem::MacroRules(mac) => self.collect_macro_rules(&self.item_tree[mac]),
|
||||
ModItem::MacroRules(id) => self.collect_macro_rules(id),
|
||||
ModItem::MacroDef(id) => {
|
||||
let mac = &self.item_tree[id];
|
||||
let ast_id = InFile::new(self.file_id, mac.ast_id.upcast());
|
||||
|
||||
// "Macro 2.0" is not currently supported by rust-analyzer, but libcore uses it
|
||||
// to define builtin macros, so we support at least that part.
|
||||
if mac.is_builtin {
|
||||
let attrs = self.item_tree.attrs(ModItem::from(id).into());
|
||||
if attrs.by_key("rustc_builtin_macro").exists() {
|
||||
let krate = self.def_collector.def_map.krate;
|
||||
let macro_id = find_builtin_macro(&mac.name, krate, ast_id)
|
||||
.or_else(|| find_builtin_derive(&mac.name, krate, ast_id));
|
||||
@ -1300,18 +1302,34 @@ impl ModCollector<'_, '_> {
|
||||
self.def_collector.resolve_proc_macro(¯o_name);
|
||||
}
|
||||
|
||||
fn collect_macro_rules(&mut self, mac: &MacroRules) {
|
||||
fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>) {
|
||||
let mac = &self.item_tree[id];
|
||||
let attrs = self.item_tree.attrs(ModItem::from(id).into());
|
||||
let ast_id = InFile::new(self.file_id, mac.ast_id.upcast());
|
||||
|
||||
let export_attr = attrs.by_key("macro_export");
|
||||
|
||||
let is_export = export_attr.exists();
|
||||
let is_local_inner = if is_export {
|
||||
export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it {
|
||||
tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
|
||||
ident.text.contains("local_inner_macros")
|
||||
}
|
||||
_ => false,
|
||||
})
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
// Case 1: builtin macros
|
||||
if mac.is_builtin {
|
||||
if attrs.by_key("rustc_builtin_macro").exists() {
|
||||
let krate = self.def_collector.def_map.krate;
|
||||
if let Some(macro_id) = find_builtin_macro(&mac.name, krate, ast_id) {
|
||||
self.def_collector.define_macro(
|
||||
self.module_id,
|
||||
mac.name.clone(),
|
||||
macro_id,
|
||||
mac.is_export,
|
||||
is_export,
|
||||
);
|
||||
return;
|
||||
}
|
||||
@ -1322,9 +1340,9 @@ impl ModCollector<'_, '_> {
|
||||
ast_id: Some(ast_id),
|
||||
krate: self.def_collector.def_map.krate,
|
||||
kind: MacroDefKind::Declarative,
|
||||
local_inner: mac.is_local_inner,
|
||||
local_inner: is_local_inner,
|
||||
};
|
||||
self.def_collector.define_macro(self.module_id, mac.name.clone(), macro_id, mac.is_export);
|
||||
self.def_collector.define_macro(self.module_id, mac.name.clone(), macro_id, is_export);
|
||||
}
|
||||
|
||||
fn collect_macro_call(&mut self, mac: &MacroCall) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user