1 // Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 #![feature(plugin_registrar, quote, rustc_private)]
16 extern crate syntax_pos
;
18 extern crate rustc_plugin
;
20 use syntax
::ast
::{self, Item, MetaItem, ItemKind}
;
21 use syntax
::ext
::base
::*;
24 use syntax
::symbol
::Symbol
;
25 use syntax
::tokenstream
::TokenTree
;
27 use rustc_plugin
::Registry
;
30 macro_rules
! exported_macro { () => (2) }
31 macro_rules
! unexported_macro { () => (3) }
34 pub fn plugin_registrar(reg
: &mut Registry
) {
35 reg
.register_macro("make_a_1", expand_make_a_1
);
36 reg
.register_macro("identity", expand_identity
);
37 reg
.register_syntax_extension(
38 Symbol
::intern("into_multi_foo"),
39 // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
40 MultiModifier(Box
::new(expand_into_foo_multi
)));
41 reg
.register_syntax_extension(
42 Symbol
::intern("duplicate"),
43 // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
44 MultiDecorator(Box
::new(expand_duplicate
)));
47 fn expand_make_a_1(cx
: &mut ExtCtxt
, sp
: Span
, tts
: &[TokenTree
])
48 -> Box
<MacResult
+'
static> {
50 cx
.span_fatal(sp
, "make_a_1 takes no arguments");
52 MacEager
::expr(quote_expr
!(cx
, 1))
56 fn expand_identity(cx
: &mut ExtCtxt
, _span
: Span
, tts
: &[TokenTree
])
57 -> Box
<MacResult
+'
static> {
58 // Parse an expression and emit it unchanged.
59 let mut parser
= parse
::new_parser_from_tts(cx
.parse_sess(), tts
.to_vec());
60 let expr
= parser
.parse_expr().unwrap();
61 MacEager
::expr(quote_expr
!(&mut *cx
, $expr
))
64 fn expand_into_foo_multi(cx
: &mut ExtCtxt
,
67 it
: Annotatable
) -> Annotatable
{
69 Annotatable
::Item(it
) => {
70 Annotatable
::Item(P(Item
{
71 attrs
: it
.attrs
.clone(),
72 ..(*quote_item
!(cx
, enum Foo2 { Bar2, Baz2 }
).unwrap()).clone()
75 Annotatable
::ImplItem(_
) => {
76 quote_item
!(cx
, impl X { fn foo(&self) -> i32 { 42 }
}).unwrap().and_then(|i
| {
78 ItemKind
::Impl(.., mut items
) => {
79 Annotatable
::ImplItem(P(items
.pop().expect("impl method not found")))
81 _
=> unreachable
!("impl parsed to something other than impl")
85 Annotatable
::TraitItem(_
) => {
86 quote_item
!(cx
, trait X { fn foo(&self) -> i32 { 0 }
}).unwrap().and_then(|i
| {
88 ItemKind
::Trait(.., mut items
) => {
89 Annotatable
::TraitItem(P(items
.pop().expect("trait method not found")))
91 _
=> unreachable
!("trait parsed to something other than trait")
98 // Create a duplicate of the annotatable, based on the MetaItem
99 fn expand_duplicate(cx
: &mut ExtCtxt
,
103 push
: &mut FnMut(Annotatable
))
105 let copy_name
= match mi
.node
{
106 ast
::MetaItemKind
::List(ref xs
) => {
107 if let Some(word
) = xs
[0].word() {
108 ast
::Ident
::with_empty_ctxt(word
.name())
110 cx
.span_err(mi
.span
, "Expected word");
115 cx
.span_err(mi
.span
, "Expected list");
120 // Duplicate the item but replace its ident by the MetaItem
122 Annotatable
::Item(it
) => {
123 let mut new_it
= (*it
).clone();
124 new_it
.attrs
.clear();
125 new_it
.ident
= copy_name
;
126 push(Annotatable
::Item(P(new_it
)));
128 Annotatable
::ImplItem(it
) => {
129 let mut new_it
= (*it
).clone();
130 new_it
.attrs
.clear();
131 new_it
.ident
= copy_name
;
132 push(Annotatable
::ImplItem(P(new_it
)));
134 Annotatable
::TraitItem(tt
) => {
135 let mut new_it
= (*tt
).clone();
136 new_it
.attrs
.clear();
137 new_it
.ident
= copy_name
;
138 push(Annotatable
::TraitItem(P(new_it
)));