Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-expand/src/declarative.rs')
-rw-r--r--crates/hir-expand/src/declarative.rs64
1 files changed, 34 insertions, 30 deletions
diff --git a/crates/hir-expand/src/declarative.rs b/crates/hir-expand/src/declarative.rs
index e4375e05d2..d2df9a1ff6 100644
--- a/crates/hir-expand/src/declarative.rs
+++ b/crates/hir-expand/src/declarative.rs
@@ -1,17 +1,21 @@
//! Compiled declarative macro expanders (`macro_rules!` and `macro`)
+use std::{cell::OnceCell, ops::ControlFlow};
+
use base_db::Crate;
-use intern::sym;
use span::{Edition, Span, SyntaxContext};
use stdx::TupleExt;
-use syntax::{AstNode, ast};
+use syntax::{
+ AstNode, AstToken,
+ ast::{self, HasAttrs},
+};
use syntax_bridge::DocCommentDesugarMode;
use triomphe::Arc;
use crate::{
AstId, ExpandError, ExpandErrorKind, ExpandResult, HirFileId, Lookup, MacroCallId,
MacroCallStyle,
- attrs::RawAttrs,
+ attrs::{Meta, expand_cfg_attr},
db::ExpandDatabase,
hygiene::{Transparency, apply_mark},
tt,
@@ -42,6 +46,7 @@ impl DeclarativeMacroExpander {
None => self
.mac
.expand(
+ db,
&tt,
|s| {
s.ctx =
@@ -49,7 +54,6 @@ impl DeclarativeMacroExpander {
},
loc.kind.call_style(),
span,
- loc.def.edition,
)
.map_err(Into::into),
}
@@ -57,10 +61,10 @@ impl DeclarativeMacroExpander {
pub fn expand_unhygienic(
&self,
+ db: &dyn ExpandDatabase,
tt: tt::TopSubtree,
call_style: MacroCallStyle,
call_site: Span,
- def_site_edition: Edition,
) -> ExpandResult<tt::TopSubtree> {
match self.mac.err() {
Some(_) => ExpandResult::new(
@@ -69,7 +73,7 @@ impl DeclarativeMacroExpander {
),
None => self
.mac
- .expand(&tt, |_| (), call_style, call_site, def_site_edition)
+ .expand(db, &tt, |_| (), call_style, call_site)
.map(TupleExt::head)
.map_err(Into::into),
}
@@ -83,29 +87,28 @@ impl DeclarativeMacroExpander {
let (root, map) = crate::db::parse_with_map(db, id.file_id);
let root = root.syntax_node();
- let transparency = |node| {
- // ... would be nice to have the item tree here
- let attrs = RawAttrs::new_expanded(db, node, map.as_ref(), def_crate.cfg_options(db));
- match attrs
- .iter()
- .find(|it| {
- it.path
- .as_ident()
- .map(|it| *it == sym::rustc_macro_transparency)
- .unwrap_or(false)
- })?
- .token_tree_value()?
- .token_trees()
- .flat_tokens()
- {
- [tt::TokenTree::Leaf(tt::Leaf::Ident(i)), ..] => match &i.sym {
- s if *s == sym::transparent => Some(Transparency::Transparent),
- s if *s == sym::semitransparent => Some(Transparency::SemiTransparent),
- s if *s == sym::opaque => Some(Transparency::Opaque),
- _ => None,
+ let transparency = |node: ast::AnyHasAttrs| {
+ let cfg_options = OnceCell::new();
+ expand_cfg_attr(
+ node.attrs(),
+ || cfg_options.get_or_init(|| def_crate.cfg_options(db)),
+ |attr, _, _, _| {
+ if let Meta::NamedKeyValue { name: Some(name), value, .. } = attr
+ && name.text() == "rustc_macro_transparency"
+ && let Some(value) = value.and_then(ast::String::cast)
+ && let Ok(value) = value.value()
+ {
+ match &*value {
+ "transparent" => ControlFlow::Break(Transparency::Transparent),
+ "semitransparent" => ControlFlow::Break(Transparency::SemiTransparent),
+ "opaque" => ControlFlow::Break(Transparency::Opaque),
+ _ => ControlFlow::Continue(()),
+ }
+ } else {
+ ControlFlow::Continue(())
+ }
},
- _ => None,
- }
+ )
};
let ctx_edition = |ctx: SyntaxContext| {
if ctx.is_root() {
@@ -136,7 +139,8 @@ impl DeclarativeMacroExpander {
"expected a token tree".into(),
)),
},
- transparency(&macro_rules).unwrap_or(Transparency::SemiTransparent),
+ transparency(ast::AnyHasAttrs::from(macro_rules))
+ .unwrap_or(Transparency::SemiTransparent),
),
ast::Macro::MacroDef(macro_def) => (
match macro_def.body() {
@@ -164,7 +168,7 @@ impl DeclarativeMacroExpander {
"expected a token tree".into(),
)),
},
- transparency(&macro_def).unwrap_or(Transparency::Opaque),
+ transparency(macro_def.into()).unwrap_or(Transparency::Opaque),
),
};
let edition = ctx_edition(match id.file_id {