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.rs | 64 |
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(¯o_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(¯o_def).unwrap_or(Transparency::Opaque), + transparency(macro_def.into()).unwrap_or(Transparency::Opaque), ), }; let edition = ctx_edition(match id.file_id { |