]>
Commit | Line | Data |
---|---|---|
85aaf69f | 1 | // Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT |
1a4d82fc JJ |
2 | // file at the top-level directory of this distribution and at |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
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. | |
10 | ||
11 | // force-host | |
12 | ||
9e0c209e | 13 | #![feature(dotdot_in_tuple_patterns)] |
d9579d0f | 14 | #![feature(plugin_registrar, quote, rustc_private)] |
1a4d82fc JJ |
15 | |
16 | extern crate syntax; | |
3157f602 | 17 | extern crate syntax_pos; |
1a4d82fc | 18 | extern crate rustc; |
92a42be0 | 19 | extern crate rustc_plugin; |
1a4d82fc | 20 | |
9e0c209e | 21 | use syntax::ast::{self, Item, MetaItem, ItemKind}; |
1a4d82fc | 22 | use syntax::ext::base::*; |
d9579d0f | 23 | use syntax::parse::{self, token}; |
1a4d82fc | 24 | use syntax::ptr::P; |
3157f602 XL |
25 | use syntax::tokenstream::TokenTree; |
26 | use syntax_pos::Span; | |
92a42be0 | 27 | use rustc_plugin::Registry; |
1a4d82fc JJ |
28 | |
29 | #[macro_export] | |
85aaf69f | 30 | macro_rules! exported_macro { () => (2) } |
85aaf69f | 31 | macro_rules! unexported_macro { () => (3) } |
1a4d82fc JJ |
32 | |
33 | #[plugin_registrar] | |
34 | pub fn plugin_registrar(reg: &mut Registry) { | |
35 | reg.register_macro("make_a_1", expand_make_a_1); | |
1a4d82fc | 36 | reg.register_macro("identity", expand_identity); |
85aaf69f SL |
37 | reg.register_syntax_extension( |
38 | token::intern("into_multi_foo"), | |
c34b1796 AL |
39 | // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. |
40 | MultiModifier(Box::new(expand_into_foo_multi))); | |
d9579d0f AL |
41 | reg.register_syntax_extension( |
42 | token::intern("duplicate"), | |
43 | // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. | |
44 | MultiDecorator(Box::new(expand_duplicate))); | |
1a4d82fc JJ |
45 | } |
46 | ||
47 | fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) | |
48 | -> Box<MacResult+'static> { | |
49 | if !tts.is_empty() { | |
50 | cx.span_fatal(sp, "make_a_1 takes no arguments"); | |
51 | } | |
c34b1796 | 52 | MacEager::expr(quote_expr!(cx, 1)) |
1a4d82fc JJ |
53 | } |
54 | ||
55 | // See Issue #15750 | |
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(), | |
60 | cx.cfg(), tts.to_vec()); | |
92a42be0 | 61 | let expr = parser.parse_expr().unwrap(); |
c34b1796 | 62 | MacEager::expr(quote_expr!(&mut *cx, $expr)) |
1a4d82fc JJ |
63 | } |
64 | ||
85aaf69f | 65 | fn expand_into_foo_multi(cx: &mut ExtCtxt, |
9e0c209e SL |
66 | _sp: Span, |
67 | _attr: &MetaItem, | |
85aaf69f SL |
68 | it: Annotatable) -> Annotatable { |
69 | match it { | |
70 | Annotatable::Item(it) => { | |
71 | Annotatable::Item(P(Item { | |
72 | attrs: it.attrs.clone(), | |
73 | ..(*quote_item!(cx, enum Foo2 { Bar2, Baz2 }).unwrap()).clone() | |
74 | })) | |
75 | } | |
9e0c209e | 76 | Annotatable::ImplItem(_) => { |
c34b1796 AL |
77 | quote_item!(cx, impl X { fn foo(&self) -> i32 { 42 } }).unwrap().and_then(|i| { |
78 | match i.node { | |
9e0c209e | 79 | ItemKind::Impl(.., mut items) => { |
7453a54e | 80 | Annotatable::ImplItem(P(items.pop().expect("impl method not found"))) |
c34b1796 AL |
81 | } |
82 | _ => unreachable!("impl parsed to something other than impl") | |
83 | } | |
84 | }) | |
85aaf69f | 85 | } |
9e0c209e | 86 | Annotatable::TraitItem(_) => { |
c34b1796 AL |
87 | quote_item!(cx, trait X { fn foo(&self) -> i32 { 0 } }).unwrap().and_then(|i| { |
88 | match i.node { | |
9e0c209e | 89 | ItemKind::Trait(.., mut items) => { |
7453a54e | 90 | Annotatable::TraitItem(P(items.pop().expect("trait method not found"))) |
c34b1796 AL |
91 | } |
92 | _ => unreachable!("trait parsed to something other than trait") | |
93 | } | |
94 | }) | |
85aaf69f SL |
95 | } |
96 | } | |
97 | } | |
98 | ||
d9579d0f AL |
99 | // Create a duplicate of the annotatable, based on the MetaItem |
100 | fn expand_duplicate(cx: &mut ExtCtxt, | |
9e0c209e | 101 | _sp: Span, |
d9579d0f | 102 | mi: &MetaItem, |
62682a34 | 103 | it: &Annotatable, |
d9579d0f AL |
104 | push: &mut FnMut(Annotatable)) |
105 | { | |
106 | let copy_name = match mi.node { | |
7453a54e | 107 | ast::MetaItemKind::List(_, ref xs) => { |
9e0c209e SL |
108 | if let Some(word) = xs[0].word() { |
109 | token::str_to_ident(&word.name()) | |
d9579d0f AL |
110 | } else { |
111 | cx.span_err(mi.span, "Expected word"); | |
112 | return; | |
113 | } | |
114 | } | |
115 | _ => { | |
116 | cx.span_err(mi.span, "Expected list"); | |
117 | return; | |
118 | } | |
119 | }; | |
1a4d82fc | 120 | |
d9579d0f AL |
121 | // Duplicate the item but replace its ident by the MetaItem |
122 | match it.clone() { | |
123 | Annotatable::Item(it) => { | |
124 | let mut new_it = (*it).clone(); | |
125 | new_it.attrs.clear(); | |
126 | new_it.ident = copy_name; | |
127 | push(Annotatable::Item(P(new_it))); | |
128 | } | |
129 | Annotatable::ImplItem(it) => { | |
130 | let mut new_it = (*it).clone(); | |
131 | new_it.attrs.clear(); | |
132 | new_it.ident = copy_name; | |
133 | push(Annotatable::ImplItem(P(new_it))); | |
134 | } | |
135 | Annotatable::TraitItem(tt) => { | |
136 | let mut new_it = (*tt).clone(); | |
137 | new_it.attrs.clear(); | |
138 | new_it.ident = copy_name; | |
139 | push(Annotatable::TraitItem(P(new_it))); | |
140 | } | |
1a4d82fc | 141 | } |
1a4d82fc JJ |
142 | } |
143 | ||
144 | pub fn foo() {} |