1 #![allow(
2 clippy::disallowed_names,
3 clippy::shadow_unrelated,
4 clippy::unseparated_literal_suffix,
5 clippy::used_underscore_binding
6 )]
7
8 use std::borrow::Cow;
9 use std::collections::BTreeSet;
10
11 use proc_macro2::{Ident, Span, TokenStream};
12 use quote::{format_ident, quote, quote_spanned, TokenStreamExt};
13
14 struct X;
15
16 impl quote::ToTokens for X {
to_tokens(&self, tokens: &mut TokenStream)17 fn to_tokens(&self, tokens: &mut TokenStream) {
18 tokens.append(Ident::new("X", Span::call_site()));
19 }
20 }
21
22 #[test]
test_quote_impl()23 fn test_quote_impl() {
24 let tokens = quote! {
25 impl<'a, T: ToTokens> ToTokens for &'a T {
26 fn to_tokens(&self, tokens: &mut TokenStream) {
27 (**self).to_tokens(tokens)
28 }
29 }
30 };
31
32 let expected = concat!(
33 "impl < 'a , T : ToTokens > ToTokens for & 'a T { ",
34 "fn to_tokens (& self , tokens : & mut TokenStream) { ",
35 "(* * self) . to_tokens (tokens) ",
36 "} ",
37 "}"
38 );
39
40 assert_eq!(expected, tokens.to_string());
41 }
42
43 #[test]
test_quote_spanned_impl()44 fn test_quote_spanned_impl() {
45 let span = Span::call_site();
46 let tokens = quote_spanned! {span=>
47 impl<'a, T: ToTokens> ToTokens for &'a T {
48 fn to_tokens(&self, tokens: &mut TokenStream) {
49 (**self).to_tokens(tokens)
50 }
51 }
52 };
53
54 let expected = concat!(
55 "impl < 'a , T : ToTokens > ToTokens for & 'a T { ",
56 "fn to_tokens (& self , tokens : & mut TokenStream) { ",
57 "(* * self) . to_tokens (tokens) ",
58 "} ",
59 "}"
60 );
61
62 assert_eq!(expected, tokens.to_string());
63 }
64
65 #[test]
test_substitution()66 fn test_substitution() {
67 let x = X;
68 let tokens = quote!(#x <#x> (#x) [#x] {#x});
69
70 let expected = "X < X > (X) [X] { X }";
71
72 assert_eq!(expected, tokens.to_string());
73 }
74
75 #[test]
test_iter()76 fn test_iter() {
77 let primes = &[X, X, X, X];
78
79 assert_eq!("X X X X", quote!(#(#primes)*).to_string());
80
81 assert_eq!("X , X , X , X ,", quote!(#(#primes,)*).to_string());
82
83 assert_eq!("X , X , X , X", quote!(#(#primes),*).to_string());
84 }
85
86 #[test]
test_array()87 fn test_array() {
88 let array: [u8; 40] = [0; 40];
89 let _ = quote!(#(#array #array)*);
90
91 let ref_array: &[u8; 40] = &[0; 40];
92 let _ = quote!(#(#ref_array #ref_array)*);
93
94 let ref_slice: &[u8] = &[0; 40];
95 let _ = quote!(#(#ref_slice #ref_slice)*);
96
97 let array: [X; 2] = [X, X]; // !Copy
98 let _ = quote!(#(#array #array)*);
99
100 let ref_array: &[X; 2] = &[X, X];
101 let _ = quote!(#(#ref_array #ref_array)*);
102
103 let ref_slice: &[X] = &[X, X];
104 let _ = quote!(#(#ref_slice #ref_slice)*);
105 }
106
107 #[test]
test_advanced()108 fn test_advanced() {
109 let generics = quote!( <'a, T> );
110
111 let where_clause = quote!( where T: Serialize );
112
113 let field_ty = quote!(String);
114
115 let item_ty = quote!(Cow<'a, str>);
116
117 let path = quote!(SomeTrait::serialize_with);
118
119 let value = quote!(self.x);
120
121 let tokens = quote! {
122 struct SerializeWith #generics #where_clause {
123 value: &'a #field_ty,
124 phantom: ::std::marker::PhantomData<#item_ty>,
125 }
126
127 impl #generics ::serde::Serialize for SerializeWith #generics #where_clause {
128 fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
129 where S: ::serde::Serializer
130 {
131 #path(self.value, s)
132 }
133 }
134
135 SerializeWith {
136 value: #value,
137 phantom: ::std::marker::PhantomData::<#item_ty>,
138 }
139 };
140
141 let expected = concat!(
142 "struct SerializeWith < 'a , T > where T : Serialize { ",
143 "value : & 'a String , ",
144 "phantom : :: std :: marker :: PhantomData < Cow < 'a , str > > , ",
145 "} ",
146 "impl < 'a , T > :: serde :: Serialize for SerializeWith < 'a , T > where T : Serialize { ",
147 "fn serialize < S > (& self , s : & mut S) -> Result < () , S :: Error > ",
148 "where S : :: serde :: Serializer ",
149 "{ ",
150 "SomeTrait :: serialize_with (self . value , s) ",
151 "} ",
152 "} ",
153 "SerializeWith { ",
154 "value : self . x , ",
155 "phantom : :: std :: marker :: PhantomData :: < Cow < 'a , str > > , ",
156 "}"
157 );
158
159 assert_eq!(expected, tokens.to_string());
160 }
161
162 #[test]
test_integer()163 fn test_integer() {
164 let ii8 = -1i8;
165 let ii16 = -1i16;
166 let ii32 = -1i32;
167 let ii64 = -1i64;
168 let ii128 = -1i128;
169 let iisize = -1isize;
170 let uu8 = 1u8;
171 let uu16 = 1u16;
172 let uu32 = 1u32;
173 let uu64 = 1u64;
174 let uu128 = 1u128;
175 let uusize = 1usize;
176
177 let tokens = quote! {
178 1 1i32 1u256
179 #ii8 #ii16 #ii32 #ii64 #ii128 #iisize
180 #uu8 #uu16 #uu32 #uu64 #uu128 #uusize
181 };
182 let expected =
183 "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 = '\u{1}';
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{1}' '#' '\"' '\\'' '\\n' '\u{2764}'";
214 assert_eq!(expected, tokens.to_string());
215 }
216
217 #[test]
test_str()218 fn test_str() {
219 let s = "\u{1} a 'b \" c";
220 let tokens = quote!(#s);
221 let expected = "\"\\u{1} a 'b \\\" c\"";
222 assert_eq!(expected, tokens.to_string());
223 }
224
225 #[test]
test_string()226 fn test_string() {
227 let s = "\u{1} a 'b \" c".to_string();
228 let tokens = quote!(#s);
229 let expected = "\"\\u{1} 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