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