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