1 #![cfg_attr(feature = "cargo-clippy", allow(blacklisted_name))]
2 
3 use std::borrow::Cow;
4 
5 extern crate proc_macro2;
6 #[macro_use]
7 extern crate quote;
8 
9 use proc_macro2::{Ident, Span, TokenStream};
10 use quote::TokenStreamExt;
11 
12 mod conditional {
13     #[cfg(integer128)]
14     mod integer128;
15 }
16 
17 struct X;
18 
19 impl quote::ToTokens for X {
to_tokens(&self, tokens: &mut TokenStream)20     fn to_tokens(&self, tokens: &mut TokenStream) {
21         tokens.append(Ident::new("X", Span::call_site()));
22     }
23 }
24 
25 #[test]
test_quote_impl()26 fn test_quote_impl() {
27     let tokens = quote! {
28         impl<'a, T: ToTokens> ToTokens for &'a T {
29             fn to_tokens(&self, tokens: &mut TokenStream) {
30                 (**self).to_tokens(tokens)
31             }
32         }
33     };
34 
35     let expected = concat!(
36         "impl < 'a , T : ToTokens > ToTokens for & 'a T { ",
37         "fn to_tokens ( & self , tokens : & mut TokenStream ) { ",
38         "( * * self ) . to_tokens ( tokens ) ",
39         "} ",
40         "}"
41     );
42 
43     assert_eq!(expected, tokens.to_string());
44 }
45 
46 #[test]
test_substitution()47 fn test_substitution() {
48     let x = X;
49     let tokens = quote!(#x <#x> (#x) [#x] {#x});
50 
51     let expected = "X < X > ( X ) [ X ] { X }";
52 
53     assert_eq!(expected, tokens.to_string());
54 }
55 
56 #[test]
test_iter()57 fn test_iter() {
58     let primes = &[X, X, X, X];
59 
60     assert_eq!("X X X X", quote!(#(#primes)*).to_string());
61 
62     assert_eq!("X , X , X , X ,", quote!(#(#primes,)*).to_string());
63 
64     assert_eq!("X , X , X , X", quote!(#(#primes),*).to_string());
65 }
66 
67 #[test]
test_advanced()68 fn test_advanced() {
69     let generics = quote!( <'a, T> );
70 
71     let where_clause = quote!( where T: Serialize );
72 
73     let field_ty = quote!(String);
74 
75     let item_ty = quote!(Cow<'a, str>);
76 
77     let path = quote!(SomeTrait::serialize_with);
78 
79     let value = quote!(self.x);
80 
81     let tokens = quote! {
82         struct SerializeWith #generics #where_clause {
83             value: &'a #field_ty,
84             phantom: ::std::marker::PhantomData<#item_ty>,
85         }
86 
87         impl #generics ::serde::Serialize for SerializeWith #generics #where_clause {
88             fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
89                 where S: ::serde::Serializer
90             {
91                 #path(self.value, s)
92             }
93         }
94 
95         SerializeWith {
96             value: #value,
97             phantom: ::std::marker::PhantomData::<#item_ty>,
98         }
99     };
100 
101     let expected = concat!(
102         "struct SerializeWith < 'a , T > where T : Serialize { ",
103         "value : & 'a String , ",
104         "phantom : :: std :: marker :: PhantomData < Cow < 'a , str > > , ",
105         "} ",
106         "impl < 'a , T > :: serde :: Serialize for SerializeWith < 'a , T > where T : Serialize { ",
107         "fn serialize < S > ( & self , s : & mut S ) -> Result < ( ) , S :: Error > ",
108         "where S : :: serde :: Serializer ",
109         "{ ",
110         "SomeTrait :: serialize_with ( self . value , s ) ",
111         "} ",
112         "} ",
113         "SerializeWith { ",
114         "value : self . x , ",
115         "phantom : :: std :: marker :: PhantomData :: < Cow < 'a , str > > , ",
116         "}"
117     );
118 
119     assert_eq!(expected, tokens.to_string());
120 }
121 
122 #[test]
test_integer()123 fn test_integer() {
124     let ii8 = -1i8;
125     let ii16 = -1i16;
126     let ii32 = -1i32;
127     let ii64 = -1i64;
128     let iisize = -1isize;
129     let uu8 = 1u8;
130     let uu16 = 1u16;
131     let uu32 = 1u32;
132     let uu64 = 1u64;
133     let uusize = 1usize;
134 
135     let tokens = quote! {
136         #ii8 #ii16 #ii32 #ii64 #iisize
137         #uu8 #uu16 #uu32 #uu64 #uusize
138     };
139     let expected = "-1i8 -1i16 -1i32 -1i64 -1isize 1u8 1u16 1u32 1u64 1usize";
140     assert_eq!(expected, tokens.to_string());
141 }
142 
143 #[test]
test_floating()144 fn test_floating() {
145     let e32 = 2.345f32;
146 
147     let e64 = 2.345f64;
148 
149     let tokens = quote! {
150         #e32
151         #e64
152     };
153     let expected = concat!("2.345f32 2.345f64");
154     assert_eq!(expected, tokens.to_string());
155 }
156 
157 #[test]
test_char()158 fn test_char() {
159     let zero = '\0';
160     let pound = '#';
161     let quote = '"';
162     let apost = '\'';
163     let newline = '\n';
164     let heart = '\u{2764}';
165 
166     let tokens = quote! {
167         #zero #pound #quote #apost #newline #heart
168     };
169     let expected = "'\\u{0}' '#' '\"' '\\'' '\\n' '\\u{2764}'";
170     assert_eq!(expected, tokens.to_string());
171 }
172 
173 #[test]
test_str()174 fn test_str() {
175     let s = "\0 a 'b \" c";
176     let tokens = quote!(#s);
177     let expected = "\"\\u{0} a 'b \\\" c\"";
178     assert_eq!(expected, tokens.to_string());
179 }
180 
181 #[test]
test_string()182 fn test_string() {
183     let s = "\0 a 'b \" c".to_string();
184     let tokens = quote!(#s);
185     let expected = "\"\\u{0} a 'b \\\" c\"";
186     assert_eq!(expected, tokens.to_string());
187 }
188 
189 #[test]
test_ident()190 fn test_ident() {
191     let foo = Ident::new("Foo", Span::call_site());
192     let bar = Ident::new(&format!("Bar{}", 7), Span::call_site());
193     let tokens = quote!(struct #foo; enum #bar {});
194     let expected = "struct Foo ; enum Bar7 { }";
195     assert_eq!(expected, tokens.to_string());
196 }
197 
198 #[test]
test_duplicate()199 fn test_duplicate() {
200     let ch = 'x';
201 
202     let tokens = quote!(#ch #ch);
203 
204     let expected = "'x' 'x'";
205     assert_eq!(expected, tokens.to_string());
206 }
207 
208 #[test]
test_fancy_repetition()209 fn test_fancy_repetition() {
210     let foo = vec!["a", "b"];
211     let bar = vec![true, false];
212 
213     let tokens = quote! {
214         #(#foo: #bar),*
215     };
216 
217     let expected = r#""a" : true , "b" : false"#;
218     assert_eq!(expected, tokens.to_string());
219 }
220 
221 #[test]
test_nested_fancy_repetition()222 fn test_nested_fancy_repetition() {
223     let nested = vec![vec!['a', 'b', 'c'], vec!['x', 'y', 'z']];
224 
225     let tokens = quote! {
226         #(
227             #(#nested)*
228         ),*
229     };
230 
231     let expected = "'a' 'b' 'c' , 'x' 'y' 'z'";
232     assert_eq!(expected, tokens.to_string());
233 }
234 
235 #[test]
test_empty_repetition()236 fn test_empty_repetition() {
237     let tokens = quote!(#(a b)* #(c d),*);
238     assert_eq!("", tokens.to_string());
239 }
240 
241 #[test]
test_variable_name_conflict()242 fn test_variable_name_conflict() {
243     // The implementation of `#(...),*` uses the variable `_i` but it should be
244     // fine, if a little confusing when debugging.
245     let _i = vec!['a', 'b'];
246     let tokens = quote! { #(#_i),* };
247     let expected = "'a' , 'b'";
248     assert_eq!(expected, tokens.to_string());
249 }
250 
251 #[test]
test_empty_quote()252 fn test_empty_quote() {
253     let tokens = quote!();
254     assert_eq!("", tokens.to_string());
255 }
256 
257 #[test]
test_box_str()258 fn test_box_str() {
259     let b = "str".to_owned().into_boxed_str();
260     let tokens = quote! { #b };
261     assert_eq!("\"str\"", tokens.to_string());
262 }
263 
264 #[test]
test_cow()265 fn test_cow() {
266     let owned: Cow<Ident> = Cow::Owned(Ident::new("owned", Span::call_site()));
267 
268     let ident = Ident::new("borrowed", Span::call_site());
269     let borrowed = Cow::Borrowed(&ident);
270 
271     let tokens = quote! { #owned #borrowed };
272     assert_eq!("owned borrowed", tokens.to_string());
273 }
274 
275 #[test]
test_closure()276 fn test_closure() {
277     fn field_i(i: usize) -> Ident {
278         Ident::new(&format!("__field{}", i), Span::call_site())
279     }
280 
281     let fields = (0usize..3)
282         .map(field_i as fn(_) -> _)
283         .map(|var| quote! { #var });
284 
285     let tokens = quote! { #(#fields)* };
286     assert_eq!("__field0 __field1 __field2", tokens.to_string());
287 }
288 
289 #[test]
test_append_tokens()290 fn test_append_tokens() {
291     let mut a = quote!(a);
292     let b = quote!(b);
293     a.append_all(b);
294     assert_eq!("a b", a.to_string());
295 }
296