1 //! Each macro must have a definition, so `#[plugin]` attributes
2 //! inject a dummy `macro_rules` item for each macro they define.
6 use syntax::edition::Edition;
8 use syntax::source_map::respan;
9 use syntax::symbol::sym;
11 use syntax::tokenstream::*;
12 use syntax_expand::base::{Resolver, NamedSyntaxExtension};
13 use syntax_pos::{Span, DUMMY_SP};
14 use syntax_pos::hygiene::{ExpnData, ExpnKind, AstPass};
18 fn plugin_macro_def(name: Name, span: Span) -> P<Item> {
19 let rustc_builtin_macro = attr::mk_attr_outer(
20 attr::mk_word_item(Ident::new(sym::rustc_builtin_macro, span)));
22 let parens: TreeAndJoint = TokenTree::Delimited(
23 DelimSpan::from_single(span), token::Paren, TokenStream::default()
25 let trees = vec![parens.clone(), TokenTree::token(token::FatArrow, span).into(), parens];
28 ident: Ident::new(name, span),
29 attrs: vec![rustc_builtin_macro],
31 kind: ItemKind::MacroDef(MacroDef { tokens: TokenStream::new(trees), legacy: true }),
32 vis: respan(span, VisibilityKind::Inherited),
40 resolver: &mut dyn Resolver,
41 named_exts: Vec<NamedSyntaxExtension>,
44 if !named_exts.is_empty() {
45 let mut extra_items = Vec::new();
46 let span = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable(
47 ExpnKind::AstPass(AstPass::PluginMacroDefs), DUMMY_SP, edition,
48 [sym::rustc_attrs][..].into(),
50 for (name, ext) in named_exts {
51 resolver.register_builtin_macro(Ident::with_dummy_span(name), ext);
52 extra_items.push(plugin_macro_def(name, span));
54 // The `macro_rules` items must be inserted before any other items.
55 mem::swap(&mut extra_items, &mut krate.module.items);
56 krate.module.items.append(&mut extra_items);