6
6
extern crate proc_macro;
7
7
8
8
use proc_macro:: { TokenStream , TokenTree , Delimiter , Literal , Spacing , Group } ;
9
+ use std:: iter;
9
10
10
11
#[ proc_macro_attribute]
11
12
pub fn foo ( attr : TokenStream , input : TokenStream ) -> TokenStream {
12
13
assert ! ( attr. is_empty( ) ) ;
13
- let input = input. into_iter ( ) . collect :: < Vec < _ > > ( ) ;
14
+ let mut input = input. into_iter ( ) . collect :: < Vec < _ > > ( ) ;
15
+ let ( namespace_start, namespace_end) ;
14
16
{
15
17
let mut cursor = & input[ ..] ;
16
18
assert_inline ( & mut cursor) ;
17
19
assert_doc ( & mut cursor) ;
18
20
assert_inline ( & mut cursor) ;
19
21
assert_doc ( & mut cursor) ;
22
+
23
+ // Splice out the #[namespace = ...] attribute as it is an inert
24
+ // attribute, not a proc macro.
25
+ namespace_start = input. len ( ) - cursor. len ( ) ;
26
+ assert_namespace ( & mut cursor) ;
27
+ namespace_end = input. len ( ) - cursor. len ( ) ;
28
+
20
29
assert_foo ( & mut cursor) ;
21
30
assert ! ( cursor. is_empty( ) ) ;
22
31
}
32
+ input. splice ( namespace_start..namespace_end, iter:: empty ( ) ) ;
23
33
fold_stream ( input. into_iter ( ) . collect ( ) )
24
34
}
25
35
@@ -34,6 +44,7 @@ pub fn bar(attr: TokenStream, input: TokenStream) -> TokenStream {
34
44
assert_invoc ( & mut cursor) ;
35
45
assert_inline ( & mut cursor) ;
36
46
assert_doc ( & mut cursor) ;
47
+ assert_namespace ( & mut cursor) ;
37
48
assert_foo ( & mut cursor) ;
38
49
assert ! ( cursor. is_empty( ) ) ;
39
50
}
@@ -93,6 +104,51 @@ fn assert_doc(slice: &mut &[TokenTree]) {
93
104
* slice = & slice[ 2 ..] ;
94
105
}
95
106
107
+ fn assert_namespace ( slice : & mut & [ TokenTree ] ) {
108
+ match & slice[ 0 ] {
109
+ TokenTree :: Punct ( tt) => assert_eq ! ( tt. as_char( ) , '#' ) ,
110
+ _ => panic ! ( "expected `#`" ) ,
111
+ }
112
+ let inner = match & slice[ 1 ] {
113
+ TokenTree :: Group ( tt) => tt. stream ( ) . into_iter ( ) . collect :: < Vec < _ > > ( ) ,
114
+ _ => panic ! ( "expected brackets" ) ,
115
+ } ;
116
+ if inner. len ( ) != 6 {
117
+ panic ! ( "expected 6 tokens in namespace attr" )
118
+ }
119
+ match & inner[ 0 ] {
120
+ TokenTree :: Ident ( tt) => assert_eq ! ( "namespace" , tt. to_string( ) ) ,
121
+ _ => panic ! ( "expected `namespace`" ) ,
122
+ }
123
+ match & inner[ 1 ] {
124
+ TokenTree :: Punct ( tt) => assert_eq ! ( tt. as_char( ) , '=' ) ,
125
+ _ => panic ! ( "expected `=`" ) ,
126
+ }
127
+ match & inner[ 2 ] {
128
+ TokenTree :: Ident ( tt) => assert_eq ! ( "std" , tt. to_string( ) ) ,
129
+ _ => panic ! ( "expected `std`" ) ,
130
+ }
131
+ match & inner[ 3 ] {
132
+ TokenTree :: Punct ( tt) => {
133
+ assert_eq ! ( tt. as_char( ) , ':' ) ;
134
+ assert_eq ! ( tt. spacing( ) , Spacing :: Joint ) ;
135
+ }
136
+ _ => panic ! ( "expected `:`" ) ,
137
+ }
138
+ match & inner[ 4 ] {
139
+ TokenTree :: Punct ( tt) => {
140
+ assert_eq ! ( tt. as_char( ) , ':' ) ;
141
+ assert_eq ! ( tt. spacing( ) , Spacing :: Alone ) ;
142
+ }
143
+ _ => panic ! ( "expected `:`" ) ,
144
+ }
145
+ match & inner[ 5 ] {
146
+ TokenTree :: Ident ( tt) => assert_eq ! ( "experimental" , tt. to_string( ) ) ,
147
+ _ => panic ! ( "expected `experimental`" ) ,
148
+ }
149
+ * slice = & slice[ 2 ..] ;
150
+ }
151
+
96
152
fn assert_invoc ( slice : & mut & [ TokenTree ] ) {
97
153
match & slice[ 0 ] {
98
154
TokenTree :: Punct ( tt) => assert_eq ! ( tt. as_char( ) , '#' ) ,
0 commit comments