]>
Commit | Line | Data |
---|---|---|
416331ca XL |
1 | //! Each macro must have a definition, so `#[plugin]` attributes |
2 | //! inject a dummy `macro_rules` item for each macro they define. | |
3 | ||
4 | use syntax::ast::*; | |
5 | use syntax::attr; | |
6 | use syntax::edition::Edition; | |
e74abb32 | 7 | use syntax_expand::base::{Resolver, NamedSyntaxExtension}; |
416331ca XL |
8 | use syntax::parse::token; |
9 | use syntax::ptr::P; | |
10 | use syntax::source_map::respan; | |
11 | use syntax::symbol::sym; | |
12 | use syntax::tokenstream::*; | |
13 | use syntax_pos::{Span, DUMMY_SP}; | |
e1599b0c | 14 | use syntax_pos::hygiene::{ExpnData, ExpnKind, AstPass}; |
416331ca XL |
15 | |
16 | use std::mem; | |
17 | ||
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))); | |
21 | ||
22 | let parens: TreeAndJoint = TokenTree::Delimited( | |
e74abb32 | 23 | DelimSpan::from_single(span), token::Paren, TokenStream::default() |
416331ca XL |
24 | ).into(); |
25 | let trees = vec![parens.clone(), TokenTree::token(token::FatArrow, span).into(), parens]; | |
26 | ||
27 | P(Item { | |
28 | ident: Ident::new(name, span), | |
29 | attrs: vec![rustc_builtin_macro], | |
30 | id: DUMMY_NODE_ID, | |
e74abb32 | 31 | kind: ItemKind::MacroDef(MacroDef { tokens: TokenStream::new(trees), legacy: true }), |
416331ca XL |
32 | vis: respan(span, VisibilityKind::Inherited), |
33 | span: span, | |
34 | tokens: None, | |
35 | }) | |
36 | } | |
37 | ||
38 | pub fn inject( | |
39 | krate: &mut Crate, | |
40 | resolver: &mut dyn Resolver, | |
41 | named_exts: Vec<NamedSyntaxExtension>, | |
42 | edition: Edition, | |
43 | ) { | |
44 | if !named_exts.is_empty() { | |
45 | let mut extra_items = Vec::new(); | |
e1599b0c XL |
46 | let span = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable( |
47 | ExpnKind::AstPass(AstPass::PluginMacroDefs), DUMMY_SP, edition, | |
416331ca XL |
48 | [sym::rustc_attrs][..].into(), |
49 | )); | |
50 | for (name, ext) in named_exts { | |
e1599b0c | 51 | resolver.register_builtin_macro(Ident::with_dummy_span(name), ext); |
416331ca XL |
52 | extra_items.push(plugin_macro_def(name, span)); |
53 | } | |
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); | |
57 | } | |
58 | } |