65 lines
2.2 KiB
Rust
65 lines
2.2 KiB
Rust
|
|
//! Each macro must have a definition, so `#[plugin]` attributes
|
||
|
|
//! inject a dummy `macro_rules` item for each macro they define.
|
||
|
|
|
||
|
|
use syntax::ast::*;
|
||
|
|
use syntax::attr;
|
||
|
|
use syntax::edition::Edition;
|
||
|
|
use syntax::ext::base::{Resolver, NamedSyntaxExtension};
|
||
|
|
use syntax::parse::token;
|
||
|
|
use syntax::ptr::P;
|
||
|
|
use syntax::source_map::respan;
|
||
|
|
use syntax::symbol::sym;
|
||
|
|
use syntax::tokenstream::*;
|
||
|
|
use syntax_pos::{Span, DUMMY_SP};
|
||
|
|
use syntax_pos::hygiene::{ExpnId, ExpnInfo, ExpnKind, MacroKind};
|
||
|
|
|
||
|
|
use std::mem;
|
||
|
|
|
||
|
|
fn plugin_macro_def(name: Name, span: Span) -> P<Item> {
|
||
|
|
let rustc_builtin_macro = Attribute {
|
||
|
|
id: attr::mk_attr_id(),
|
||
|
|
style: AttrStyle::Outer,
|
||
|
|
path: Path::from_ident(Ident::new(sym::rustc_builtin_macro, span)),
|
||
|
|
tokens: TokenStream::empty(),
|
||
|
|
is_sugared_doc: false,
|
||
|
|
span,
|
||
|
|
};
|
||
|
|
|
||
|
|
let parens: TreeAndJoint = TokenTree::Delimited(
|
||
|
|
DelimSpan::from_single(span), token::Paren, TokenStream::empty()
|
||
|
|
).into();
|
||
|
|
let trees = vec![parens.clone(), TokenTree::token(token::FatArrow, span).into(), parens];
|
||
|
|
|
||
|
|
P(Item {
|
||
|
|
ident: Ident::new(name, span),
|
||
|
|
attrs: vec![rustc_builtin_macro],
|
||
|
|
id: DUMMY_NODE_ID,
|
||
|
|
node: ItemKind::MacroDef(MacroDef { tokens: TokenStream::new(trees), legacy: true }),
|
||
|
|
vis: respan(span, VisibilityKind::Inherited),
|
||
|
|
span: span,
|
||
|
|
tokens: None,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn inject(
|
||
|
|
krate: &mut Crate,
|
||
|
|
resolver: &mut dyn Resolver,
|
||
|
|
named_exts: Vec<NamedSyntaxExtension>,
|
||
|
|
edition: Edition,
|
||
|
|
) {
|
||
|
|
if !named_exts.is_empty() {
|
||
|
|
let mut extra_items = Vec::new();
|
||
|
|
let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable(
|
||
|
|
ExpnKind::Macro(MacroKind::Attr, sym::plugin), DUMMY_SP, edition,
|
||
|
|
[sym::rustc_attrs][..].into(),
|
||
|
|
));
|
||
|
|
for (name, ext) in named_exts {
|
||
|
|
resolver.register_builtin_macro(Ident::with_empty_ctxt(name), ext);
|
||
|
|
extra_items.push(plugin_macro_def(name, span));
|
||
|
|
}
|
||
|
|
// The `macro_rules` items must be inserted before any other items.
|
||
|
|
mem::swap(&mut extra_items, &mut krate.module.items);
|
||
|
|
krate.module.items.append(&mut extra_items);
|
||
|
|
}
|
||
|
|
}
|