• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![cfg_attr(feature = "cargo-clippy", allow(blacklisted_name))]
2 
3 use std::borrow::Cow;
4 use std::collections::BTreeSet;
5 
6 use proc_macro2::{Ident, Span, TokenStream};
7 use quote::{format_ident, quote, quote_spanned, TokenStreamExt};
8 
9 struct X;
10 
11 impl quote::ToTokens for X {
to_tokens(&self, tokens: &mut TokenStream)12     fn to_tokens(&self, tokens: &mut TokenStream) {
13         tokens.append(Ident::new("X", Span::call_site()));
14     }
15 }
16 
17 #[test]
test_quote_impl()18 fn test_quote_impl() {
19     let tokens = quote! {
20         impl<'a, T: ToTokens> ToTokens for &'a T {
21             fn to_tokens(&self, tokens: &mut TokenStream) {
22                 (**self).to_tokens(tokens)
23             }
24         }
25     };
26 
27     let expected = concat!(
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     assert_eq!(expected, tokens.to_string());
36 }
37 
38 #[test]
test_quote_spanned_impl()39 fn test_quote_spanned_impl() {
40     let span = Span::call_site();
41     let tokens = quote_spanned! {span=>
42         impl<'a, T: ToTokens> ToTokens for &'a T {
43             fn to_tokens(&self, tokens: &mut TokenStream) {
44                 (**self).to_tokens(tokens)
45             }
46         }
47     };
48 
49     let expected = concat!(
50         "impl < 'a , T : ToTokens > ToTokens for & 'a T { ",
51         "fn to_tokens (& self , tokens : & mut TokenStream) { ",
52         "(* * self) . to_tokens (tokens) ",
53         "} ",
54         "}"
55     );
56 
57     assert_eq!(expected, tokens.to_string());
58 }
59 
60 #[test]
test_substitution()61 fn test_substitution() {
62     let x = X;
63     let tokens = quote!(#x <#x> (#x) [#x] {#x});
64 
65     let expected = "X < X > (X) [X] { X }";
66 
67     assert_eq!(expected, tokens.to_string());
68 }
69 
70 #[test]
test_iter()71 fn test_iter() {
72     let primes = &[X, X, X, X];
73 
74     assert_eq!("X X X X", quote!(#(#primes)*).to_string());
75 
76     assert_eq!("X , X , X , X ,", quote!(#(#primes,)*).to_string());
77 
78     assert_eq!("X , X , X , X", quote!(#(#primes),*).to_string());
79 }
80 
81 #[test]
test_advanced()82 fn test_advanced() {
83     let generics = quote!( <'a, T> );
84 
85     let where_clause = quote!( where T: Serialize );
86 
87     let field_ty = quote!(String);
88 
89     let item_ty = quote!(Cow<'a, str>);
90 
91     let path = quote!(SomeTrait::serialize_with);
92 
93     let value = quote!(self.x);
94 
95     let tokens = quote! {
96         struct SerializeWith #generics #where_clause {
97             value: &'a #field_ty,
98             phantom: ::std::marker::PhantomData<#item_ty>,
99         }
100 
101         impl #generics ::serde::Serialize for SerializeWith #generics #where_clause {
102             fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
103                 where S: ::serde::Serializer
104             {
105                 #path(self.value, s)
106             }
107         }
108 
109         SerializeWith {
110             value: #value,
111             phantom: ::std::marker::PhantomData::<#item_ty>,
112         }
113     };
114 
115     let expected = concat!(
116         "struct SerializeWith < 'a , T > where T : Serialize { ",
117         "value : & 'a String , ",
118         "phantom : :: std :: marker :: PhantomData < Cow < 'a , str > > , ",
119         "} ",
120         "impl < 'a , T > :: serde :: Serialize for SerializeWith < 'a , T > where T : Serialize { ",
121         "fn serialize < S > (& self , s : & mut S) -> Result < () , S :: Error > ",
122         "where S : :: serde :: Serializer ",
123         "{ ",
124         "SomeTrait :: serialize_with (self . value , s) ",
125         "} ",
126         "} ",
127         "SerializeWith { ",
128         "value : self . x , ",
129         "phantom : :: std :: marker :: PhantomData :: < Cow < 'a , str > > , ",
130         "}"
131     );
132 
133     assert_eq!(expected, tokens.to_string());
134 }
135 
136 #[test]
test_integer()137 fn test_integer() {
138     let ii8 = -1i8;
139     let ii16 = -1i16;
140     let ii32 = -1i32;
141     let ii64 = -1i64;
142     let ii128 = -1i128;
143     let iisize = -1isize;
144     let uu8 = 1u8;
145     let uu16 = 1u16;
146     let uu32 = 1u32;
147     let uu64 = 1u64;
148     let uu128 = 1u128;
149     let uusize = 1usize;
150 
151     let tokens = quote! {
152         #ii8 #ii16 #ii32 #ii64 #ii128 #iisize
153         #uu8 #uu16 #uu32 #uu64 #uu128 #uusize
154     };
155     let expected = "- 1i8 - 1i16 - 1i32 - 1i64 - 1i128 - 1isize 1u8 1u16 1u32 1u64 1u128 1usize";
156     assert_eq!(expected, tokens.to_string());
157 }
158 
159 #[test]
test_floating()160 fn test_floating() {
161     let e32 = 2.345f32;
162 
163     let e64 = 2.345f64;
164 
165     let tokens = quote! {
166         #e32
167         #e64
168     };
169     let expected = concat!("2.345f32 2.345f64");
170     assert_eq!(expected, tokens.to_string());
171 }
172 
173 #[test]
test_char()174 fn test_char() {
175     let zero = '\0';
176     let pound = '#';
177     let quote = '"';
178     let apost = '\'';
179     let newline = '\n';
180     let heart = '\u{2764}';
181 
182     let tokens = quote! {
183         #zero #pound #quote #apost #newline #heart
184     };
185     let expected = "'\\u{0}' '#' '\"' '\\'' '\\n' '\u{2764}'";
186     assert_eq!(expected, tokens.to_string());
187 }
188 
189 #[test]
test_str()190 fn test_str() {
191     let s = "\0 a 'b \" c";
192     let tokens = quote!(#s);
193     let expected = "\"\\u{0} a 'b \\\" c\"";
194     assert_eq!(expected, tokens.to_string());
195 }
196 
197 #[test]
test_string()198 fn test_string() {
199     let s = "\0 a 'b \" c".to_string();
200     let tokens = quote!(#s);
201     let expected = "\"\\u{0} a 'b \\\" c\"";
202     assert_eq!(expected, tokens.to_string());
203 }
204 
205 #[test]
test_ident()206 fn test_ident() {
207     let foo = Ident::new("Foo", Span::call_site());
208     let bar = Ident::new(&format!("Bar{}", 7), Span::call_site());
209     let tokens = quote!(struct #foo; enum #bar {});
210     let expected = "struct Foo ; enum Bar7 { }";
211     assert_eq!(expected, tokens.to_string());
212 }
213 
214 #[test]
test_duplicate()215 fn test_duplicate() {
216     let ch = 'x';
217 
218     let tokens = quote!(#ch #ch);
219 
220     let expected = "'x' 'x'";
221     assert_eq!(expected, tokens.to_string());
222 }
223 
224 #[test]
test_fancy_repetition()225 fn test_fancy_repetition() {
226     let foo = vec!["a", "b"];
227     let bar = vec![true, false];
228 
229     let tokens = quote! {
230         #(#foo: #bar),*
231     };
232 
233     let expected = r#""a" : true , "b" : false"#;
234     assert_eq!(expected, tokens.to_string());
235 }
236 
237 #[test]
test_nested_fancy_repetition()238 fn test_nested_fancy_repetition() {
239     let nested = vec![vec!['a', 'b', 'c'], vec!['x', 'y', 'z']];
240 
241     let tokens = quote! {
242         #(
243             #(#nested)*
244         ),*
245     };
246 
247     let expected = "'a' 'b' 'c' , 'x' 'y' 'z'";
248     assert_eq!(expected, tokens.to_string());
249 }
250 
251 #[test]
test_duplicate_name_repetition()252 fn test_duplicate_name_repetition() {
253     let foo = &["a", "b"];
254 
255     let tokens = quote! {
256         #(#foo: #foo),*
257         #(#foo: #foo),*
258     };
259 
260     let expected = r#""a" : "a" , "b" : "b" "a" : "a" , "b" : "b""#;
261     assert_eq!(expected, tokens.to_string());
262 }
263 
264 #[test]
test_duplicate_name_repetition_no_copy()265 fn test_duplicate_name_repetition_no_copy() {
266     let foo = vec!["a".to_owned(), "b".to_owned()];
267 
268     let tokens = quote! {
269         #(#foo: #foo),*
270     };
271 
272     let expected = r#""a" : "a" , "b" : "b""#;
273     assert_eq!(expected, tokens.to_string());
274 }
275 
276 #[test]
test_btreeset_repetition()277 fn test_btreeset_repetition() {
278     let mut set = BTreeSet::new();
279     set.insert("a".to_owned());
280     set.insert("b".to_owned());
281 
282     let tokens = quote! {
283         #(#set: #set),*
284     };
285 
286     let expected = r#""a" : "a" , "b" : "b""#;
287     assert_eq!(expected, tokens.to_string());
288 }
289 
290 #[test]
test_variable_name_conflict()291 fn test_variable_name_conflict() {
292     // The implementation of `#(...),*` uses the variable `_i` but it should be
293     // fine, if a little confusing when debugging.
294     let _i = vec!['a', 'b'];
295     let tokens = quote! { #(#_i),* };
296     let expected = "'a' , 'b'";
297     assert_eq!(expected, tokens.to_string());
298 }
299 
300 #[test]
test_nonrep_in_repetition()301 fn test_nonrep_in_repetition() {
302     let rep = vec!["a", "b"];
303     let nonrep = "c";
304 
305     let tokens = quote! {
306         #(#rep #rep : #nonrep #nonrep),*
307     };
308 
309     let expected = r#""a" "a" : "c" "c" , "b" "b" : "c" "c""#;
310     assert_eq!(expected, tokens.to_string());
311 }
312 
313 #[test]
test_empty_quote()314 fn test_empty_quote() {
315     let tokens = quote!();
316     assert_eq!("", tokens.to_string());
317 }
318 
319 #[test]
test_box_str()320 fn test_box_str() {
321     let b = "str".to_owned().into_boxed_str();
322     let tokens = quote! { #b };
323     assert_eq!("\"str\"", tokens.to_string());
324 }
325 
326 #[test]
test_cow()327 fn test_cow() {
328     let owned: Cow<Ident> = Cow::Owned(Ident::new("owned", Span::call_site()));
329 
330     let ident = Ident::new("borrowed", Span::call_site());
331     let borrowed = Cow::Borrowed(&ident);
332 
333     let tokens = quote! { #owned #borrowed };
334     assert_eq!("owned borrowed", tokens.to_string());
335 }
336 
337 #[test]
test_closure()338 fn test_closure() {
339     fn field_i(i: usize) -> Ident {
340         format_ident!("__field{}", i)
341     }
342 
343     let fields = (0usize..3)
344         .map(field_i as fn(_) -> _)
345         .map(|var| quote! { #var });
346 
347     let tokens = quote! { #(#fields)* };
348     assert_eq!("__field0 __field1 __field2", tokens.to_string());
349 }
350 
351 #[test]
test_append_tokens()352 fn test_append_tokens() {
353     let mut a = quote!(a);
354     let b = quote!(b);
355     a.append_all(b);
356     assert_eq!("a b", a.to_string());
357 }
358 
359 #[test]
test_format_ident()360 fn test_format_ident() {
361     let id0 = format_ident!("Aa");
362     let id1 = format_ident!("Hello{x}", x = id0);
363     let id2 = format_ident!("Hello{x}", x = 5usize);
364     let id3 = format_ident!("Hello{}_{x}", id0, x = 10usize);
365     let id4 = format_ident!("Aa", span = Span::call_site());
366     let id5 = format_ident!("Hello{}", Cow::Borrowed("World"));
367 
368     assert_eq!(id0, "Aa");
369     assert_eq!(id1, "HelloAa");
370     assert_eq!(id2, "Hello5");
371     assert_eq!(id3, "HelloAa_10");
372     assert_eq!(id4, "Aa");
373     assert_eq!(id5, "HelloWorld");
374 }
375 
376 #[test]
test_format_ident_strip_raw()377 fn test_format_ident_strip_raw() {
378     let id = format_ident!("r#struct");
379     let my_id = format_ident!("MyId{}", id);
380     let raw_my_id = format_ident!("r#MyId{}", id);
381 
382     assert_eq!(id, "r#struct");
383     assert_eq!(my_id, "MyIdstruct");
384     assert_eq!(raw_my_id, "r#MyIdstruct");
385 }
386 
387 #[test]
test_outer_line_comment()388 fn test_outer_line_comment() {
389     let tokens = quote! {
390         /// doc
391     };
392     let expected = "# [doc = r\" doc\"]";
393     assert_eq!(expected, tokens.to_string());
394 }
395 
396 #[test]
test_inner_line_comment()397 fn test_inner_line_comment() {
398     let tokens = quote! {
399         //! doc
400     };
401     let expected = "# ! [doc = r\" doc\"]";
402     assert_eq!(expected, tokens.to_string());
403 }
404 
405 #[test]
test_outer_block_comment()406 fn test_outer_block_comment() {
407     let tokens = quote! {
408         /** doc */
409     };
410     let expected = "# [doc = r\" doc \"]";
411     assert_eq!(expected, tokens.to_string());
412 }
413 
414 #[test]
test_inner_block_comment()415 fn test_inner_block_comment() {
416     let tokens = quote! {
417         /*! doc */
418     };
419     let expected = "# ! [doc = r\" doc \"]";
420     assert_eq!(expected, tokens.to_string());
421 }
422 
423 #[test]
test_outer_attr()424 fn test_outer_attr() {
425     let tokens = quote! {
426         #[inline]
427     };
428     let expected = "# [inline]";
429     assert_eq!(expected, tokens.to_string());
430 }
431 
432 #[test]
test_inner_attr()433 fn test_inner_attr() {
434     let tokens = quote! {
435         #![no_std]
436     };
437     let expected = "# ! [no_std]";
438     assert_eq!(expected, tokens.to_string());
439 }
440 
441 // https://github.com/dtolnay/quote/issues/130
442 #[test]
test_star_after_repetition()443 fn test_star_after_repetition() {
444     let c = vec!['0', '1'];
445     let tokens = quote! {
446         #(
447             f(#c);
448         )*
449         *out = None;
450     };
451     let expected = "f ('0') ; f ('1') ; * out = None ;";
452     assert_eq!(expected, tokens.to_string());
453 }
454 
455 #[test]
test_quote_raw_id()456 fn test_quote_raw_id() {
457     let id = quote!(r#raw_id);
458     assert_eq!(id.to_string(), "r#raw_id");
459 }
460