16
16
extern crate syntax;
17
17
extern crate rustc;
18
18
19
- use syntax:: ast:: { TokenTree , Item , MetaItem , ImplItem , TraitItem , Method } ;
19
+ use syntax:: ast:: { self , TokenTree , Item , MetaItem , ImplItem , TraitItem , Method } ;
20
20
use syntax:: codemap:: Span ;
21
21
use syntax:: ext:: base:: * ;
22
- use syntax:: parse:: token;
23
- use syntax:: parse;
22
+ use syntax:: parse:: { self , token} ;
24
23
use syntax:: ptr:: P ;
25
24
use rustc:: plugin:: Registry ;
26
25
@@ -40,6 +39,9 @@ pub fn plugin_registrar(reg: &mut Registry) {
40
39
reg. register_syntax_extension (
41
40
token:: intern ( "into_multi_foo" ) ,
42
41
MultiModifier ( box expand_into_foo_multi) ) ;
42
+ reg. register_syntax_extension (
43
+ token:: intern ( "duplicate" ) ,
44
+ MultiDecorator ( box expand_duplicate) ) ;
43
45
}
44
46
45
47
fn expand_make_a_1 ( cx : & mut ExtCtxt , sp : Span , tts : & [ TokenTree ] )
@@ -92,6 +94,83 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt,
92
94
}
93
95
}
94
96
97
+ // Create a duplicate of the annotatable, based on the MetaItem
98
+ fn expand_duplicate ( cx : & mut ExtCtxt ,
99
+ sp : Span ,
100
+ mi : & MetaItem ,
101
+ it : & Annotatable ,
102
+ mut push : Box < FnMut ( Annotatable ) > )
103
+ {
104
+ let copy_name = match mi. node {
105
+ ast:: MetaItem_ :: MetaList ( _, ref xs) => {
106
+ if let ast:: MetaItem_ :: MetaWord ( ref w) = xs[ 0 ] . node {
107
+ token:: str_to_ident ( w. get ( ) )
108
+ } else {
109
+ cx. span_err ( mi. span , "Expected word" ) ;
110
+ return ;
111
+ }
112
+ }
113
+ _ => {
114
+ cx. span_err ( mi. span , "Expected list" ) ;
115
+ return ;
116
+ }
117
+ } ;
118
+
119
+ // Duplicate the item but replace its ident by the MetaItem
120
+ match it. clone ( ) {
121
+ Annotatable :: Item ( it) => {
122
+ let mut new_it = ( * it) . clone ( ) ;
123
+ new_it. attrs . clear ( ) ;
124
+ new_it. ident = copy_name;
125
+ push ( Annotatable :: Item ( P ( new_it) ) ) ;
126
+ }
127
+ Annotatable :: ImplItem ( it) => {
128
+ match it {
129
+ ImplItem :: MethodImplItem ( m) => {
130
+ let mut new_m = ( * m) . clone ( ) ;
131
+ new_m. attrs . clear ( ) ;
132
+ replace_method_name ( & mut new_m. node , copy_name) ;
133
+ push ( Annotatable :: ImplItem ( ImplItem :: MethodImplItem ( P ( new_m) ) ) ) ;
134
+ }
135
+ ImplItem :: TypeImplItem ( t) => {
136
+ let mut new_t = ( * t) . clone ( ) ;
137
+ new_t. attrs . clear ( ) ;
138
+ new_t. ident = copy_name;
139
+ push ( Annotatable :: ImplItem ( ImplItem :: TypeImplItem ( P ( new_t) ) ) ) ;
140
+ }
141
+ }
142
+ }
143
+ Annotatable :: TraitItem ( it) => {
144
+ match it {
145
+ TraitItem :: RequiredMethod ( rm) => {
146
+ let mut new_rm = rm. clone ( ) ;
147
+ new_rm. attrs . clear ( ) ;
148
+ new_rm. ident = copy_name;
149
+ push ( Annotatable :: TraitItem ( TraitItem :: RequiredMethod ( new_rm) ) ) ;
150
+ }
151
+ TraitItem :: ProvidedMethod ( pm) => {
152
+ let mut new_pm = ( * pm) . clone ( ) ;
153
+ new_pm. attrs . clear ( ) ;
154
+ replace_method_name ( & mut new_pm. node , copy_name) ;
155
+ push ( Annotatable :: TraitItem ( TraitItem :: ProvidedMethod ( P ( new_pm) ) ) ) ;
156
+ }
157
+ TraitItem :: TypeTraitItem ( t) => {
158
+ let mut new_t = ( * t) . clone ( ) ;
159
+ new_t. attrs . clear ( ) ;
160
+ new_t. ty_param . ident = copy_name;
161
+ push ( Annotatable :: TraitItem ( TraitItem :: TypeTraitItem ( P ( new_t) ) ) ) ;
162
+ }
163
+ }
164
+ }
165
+ }
166
+
167
+ fn replace_method_name ( m : & mut ast:: Method_ , i : ast:: Ident ) {
168
+ if let & mut ast:: Method_ :: MethDecl ( ref mut ident, _, _, _, _, _, _, _) = m {
169
+ * ident = i
170
+ }
171
+ }
172
+ }
173
+
95
174
fn expand_forged_ident ( cx : & mut ExtCtxt , sp : Span , tts : & [ TokenTree ] ) -> Box < MacResult +' static > {
96
175
use syntax:: ext:: quote:: rt:: * ;
97
176
0 commit comments