]> git.proxmox.com Git - rustc.git/blob - vendor/syn/tests/test_derive_input.rs
New upstream version 1.46.0~beta.2+dfsg1
[rustc.git] / vendor / syn / tests / test_derive_input.rs
1 #[macro_use]
2 mod macros;
3
4 use quote::quote;
5 use syn::{Data, DeriveInput};
6
7 #[test]
8 fn test_unit() {
9 let input = quote! {
10 struct Unit;
11 };
12
13 snapshot!(input as DeriveInput, @r###"
14 DeriveInput {
15 vis: Inherited,
16 ident: "Unit",
17 generics: Generics,
18 data: Data::Struct {
19 fields: Unit,
20 semi_token: Some,
21 },
22 }
23 "###);
24 }
25
26 #[test]
27 fn test_struct() {
28 let input = quote! {
29 #[derive(Debug, Clone)]
30 pub struct Item {
31 pub ident: Ident,
32 pub attrs: Vec<Attribute>
33 }
34 };
35
36 snapshot!(input as DeriveInput, @r###"
37 DeriveInput {
38 attrs: [
39 Attribute {
40 style: Outer,
41 path: Path {
42 segments: [
43 PathSegment {
44 ident: "derive",
45 arguments: None,
46 },
47 ],
48 },
49 tokens: TokenStream(`( Debug , Clone )`),
50 },
51 ],
52 vis: Visibility::Public,
53 ident: "Item",
54 generics: Generics,
55 data: Data::Struct {
56 fields: Fields::Named {
57 named: [
58 Field {
59 vis: Visibility::Public,
60 ident: Some("ident"),
61 colon_token: Some,
62 ty: Type::Path {
63 path: Path {
64 segments: [
65 PathSegment {
66 ident: "Ident",
67 arguments: None,
68 },
69 ],
70 },
71 },
72 },
73 Field {
74 vis: Visibility::Public,
75 ident: Some("attrs"),
76 colon_token: Some,
77 ty: Type::Path {
78 path: Path {
79 segments: [
80 PathSegment {
81 ident: "Vec",
82 arguments: PathArguments::AngleBracketed {
83 args: [
84 Type(Type::Path {
85 path: Path {
86 segments: [
87 PathSegment {
88 ident: "Attribute",
89 arguments: None,
90 },
91 ],
92 },
93 }),
94 ],
95 },
96 },
97 ],
98 },
99 },
100 },
101 ],
102 },
103 },
104 }
105 "###);
106
107 snapshot!(input.attrs[0].parse_meta().unwrap(), @r###"
108 Meta::List {
109 path: Path {
110 segments: [
111 PathSegment {
112 ident: "derive",
113 arguments: None,
114 },
115 ],
116 },
117 nested: [
118 Meta(Path(Path {
119 segments: [
120 PathSegment {
121 ident: "Debug",
122 arguments: None,
123 },
124 ],
125 })),
126 Meta(Path(Path {
127 segments: [
128 PathSegment {
129 ident: "Clone",
130 arguments: None,
131 },
132 ],
133 })),
134 ],
135 }
136 "###);
137 }
138
139 #[test]
140 fn test_union() {
141 let input = quote! {
142 union MaybeUninit<T> {
143 uninit: (),
144 value: T
145 }
146 };
147
148 snapshot!(input as DeriveInput, @r###"
149 DeriveInput {
150 vis: Inherited,
151 ident: "MaybeUninit",
152 generics: Generics {
153 lt_token: Some,
154 params: [
155 Type(TypeParam {
156 ident: "T",
157 }),
158 ],
159 gt_token: Some,
160 },
161 data: Data::Union {
162 fields: FieldsNamed {
163 named: [
164 Field {
165 vis: Inherited,
166 ident: Some("uninit"),
167 colon_token: Some,
168 ty: Type::Tuple,
169 },
170 Field {
171 vis: Inherited,
172 ident: Some("value"),
173 colon_token: Some,
174 ty: Type::Path {
175 path: Path {
176 segments: [
177 PathSegment {
178 ident: "T",
179 arguments: None,
180 },
181 ],
182 },
183 },
184 },
185 ],
186 },
187 },
188 }
189 "###);
190 }
191
192 #[test]
193 #[cfg(feature = "full")]
194 fn test_enum() {
195 let input = quote! {
196 /// See the std::result module documentation for details.
197 #[must_use]
198 pub enum Result<T, E> {
199 Ok(T),
200 Err(E),
201 Surprise = 0isize,
202
203 // Smuggling data into a proc_macro_derive,
204 // in the style of https://github.com/dtolnay/proc-macro-hack
205 ProcMacroHack = (0, "data").0
206 }
207 };
208
209 snapshot!(input as DeriveInput, @r###"
210 DeriveInput {
211 attrs: [
212 Attribute {
213 style: Outer,
214 path: Path {
215 segments: [
216 PathSegment {
217 ident: "doc",
218 arguments: None,
219 },
220 ],
221 },
222 tokens: TokenStream(`= r" See the std::result module documentation for details."`),
223 },
224 Attribute {
225 style: Outer,
226 path: Path {
227 segments: [
228 PathSegment {
229 ident: "must_use",
230 arguments: None,
231 },
232 ],
233 },
234 tokens: TokenStream(``),
235 },
236 ],
237 vis: Visibility::Public,
238 ident: "Result",
239 generics: Generics {
240 lt_token: Some,
241 params: [
242 Type(TypeParam {
243 ident: "T",
244 }),
245 Type(TypeParam {
246 ident: "E",
247 }),
248 ],
249 gt_token: Some,
250 },
251 data: Data::Enum {
252 variants: [
253 Variant {
254 ident: "Ok",
255 fields: Fields::Unnamed {
256 unnamed: [
257 Field {
258 vis: Inherited,
259 ty: Type::Path {
260 path: Path {
261 segments: [
262 PathSegment {
263 ident: "T",
264 arguments: None,
265 },
266 ],
267 },
268 },
269 },
270 ],
271 },
272 },
273 Variant {
274 ident: "Err",
275 fields: Fields::Unnamed {
276 unnamed: [
277 Field {
278 vis: Inherited,
279 ty: Type::Path {
280 path: Path {
281 segments: [
282 PathSegment {
283 ident: "E",
284 arguments: None,
285 },
286 ],
287 },
288 },
289 },
290 ],
291 },
292 },
293 Variant {
294 ident: "Surprise",
295 fields: Unit,
296 discriminant: Some(Expr::Lit {
297 lit: 0isize,
298 }),
299 },
300 Variant {
301 ident: "ProcMacroHack",
302 fields: Unit,
303 discriminant: Some(Expr::Field {
304 base: Expr::Tuple {
305 elems: [
306 Expr::Lit {
307 lit: 0,
308 },
309 Expr::Lit {
310 lit: "data",
311 },
312 ],
313 },
314 member: Unnamed(Index {
315 index: 0,
316 }),
317 }),
318 },
319 ],
320 },
321 }
322 "###);
323
324 let meta_items: Vec<_> = input
325 .attrs
326 .into_iter()
327 .map(|attr| attr.parse_meta().unwrap())
328 .collect();
329
330 snapshot!(meta_items, @r###"
331 [
332 Meta::NameValue {
333 path: Path {
334 segments: [
335 PathSegment {
336 ident: "doc",
337 arguments: None,
338 },
339 ],
340 },
341 lit: " See the std::result module documentation for details.",
342 },
343 Path(Path {
344 segments: [
345 PathSegment {
346 ident: "must_use",
347 arguments: None,
348 },
349 ],
350 }),
351 ]
352 "###);
353 }
354
355 #[test]
356 fn test_attr_with_path() {
357 let input = quote! {
358 #[::attr_args::identity
359 fn main() { assert_eq!(foo(), "Hello, world!"); }]
360 struct Dummy;
361 };
362
363 snapshot!(input as DeriveInput, @r###"
364 DeriveInput {
365 attrs: [
366 Attribute {
367 style: Outer,
368 path: Path {
369 leading_colon: Some,
370 segments: [
371 PathSegment {
372 ident: "attr_args",
373 arguments: None,
374 },
375 PathSegment {
376 ident: "identity",
377 arguments: None,
378 },
379 ],
380 },
381 tokens: TokenStream(`fn main ( ) { assert_eq ! ( foo ( ) , "Hello, world!" ) ; }`),
382 },
383 ],
384 vis: Inherited,
385 ident: "Dummy",
386 generics: Generics,
387 data: Data::Struct {
388 fields: Unit,
389 semi_token: Some,
390 },
391 }
392 "###);
393
394 assert!(input.attrs[0].parse_meta().is_err());
395 }
396
397 #[test]
398 fn test_attr_with_non_mod_style_path() {
399 let input = quote! {
400 #[inert <T>]
401 struct S;
402 };
403
404 snapshot!(input as DeriveInput, @r###"
405 DeriveInput {
406 attrs: [
407 Attribute {
408 style: Outer,
409 path: Path {
410 segments: [
411 PathSegment {
412 ident: "inert",
413 arguments: None,
414 },
415 ],
416 },
417 tokens: TokenStream(`< T >`),
418 },
419 ],
420 vis: Inherited,
421 ident: "S",
422 generics: Generics,
423 data: Data::Struct {
424 fields: Unit,
425 semi_token: Some,
426 },
427 }
428 "###);
429
430 assert!(input.attrs[0].parse_meta().is_err());
431 }
432
433 #[test]
434 fn test_attr_with_mod_style_path_with_self() {
435 let input = quote! {
436 #[foo::self]
437 struct S;
438 };
439
440 snapshot!(input as DeriveInput, @r###"
441 DeriveInput {
442 attrs: [
443 Attribute {
444 style: Outer,
445 path: Path {
446 segments: [
447 PathSegment {
448 ident: "foo",
449 arguments: None,
450 },
451 PathSegment {
452 ident: "self",
453 arguments: None,
454 },
455 ],
456 },
457 tokens: TokenStream(``),
458 },
459 ],
460 vis: Inherited,
461 ident: "S",
462 generics: Generics,
463 data: Data::Struct {
464 fields: Unit,
465 semi_token: Some,
466 },
467 }
468 "###);
469
470 snapshot!(input.attrs[0].parse_meta().unwrap(), @r###"
471 Path(Path {
472 segments: [
473 PathSegment {
474 ident: "foo",
475 arguments: None,
476 },
477 PathSegment {
478 ident: "self",
479 arguments: None,
480 },
481 ],
482 })
483 "###);
484 }
485
486 #[test]
487 fn test_pub_restricted() {
488 // Taken from tests/rust/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs
489 let input = quote! {
490 pub(in m) struct Z(pub(in m::n) u8);
491 };
492
493 snapshot!(input as DeriveInput, @r###"
494 DeriveInput {
495 vis: Visibility::Restricted {
496 in_token: Some,
497 path: Path {
498 segments: [
499 PathSegment {
500 ident: "m",
501 arguments: None,
502 },
503 ],
504 },
505 },
506 ident: "Z",
507 generics: Generics,
508 data: Data::Struct {
509 fields: Fields::Unnamed {
510 unnamed: [
511 Field {
512 vis: Visibility::Restricted {
513 in_token: Some,
514 path: Path {
515 segments: [
516 PathSegment {
517 ident: "m",
518 arguments: None,
519 },
520 PathSegment {
521 ident: "n",
522 arguments: None,
523 },
524 ],
525 },
526 },
527 ty: Type::Path {
528 path: Path {
529 segments: [
530 PathSegment {
531 ident: "u8",
532 arguments: None,
533 },
534 ],
535 },
536 },
537 },
538 ],
539 },
540 semi_token: Some,
541 },
542 }
543 "###);
544 }
545
546 #[test]
547 fn test_vis_crate() {
548 let input = quote! {
549 crate struct S;
550 };
551
552 snapshot!(input as DeriveInput, @r###"
553 DeriveInput {
554 vis: Visibility::Crate,
555 ident: "S",
556 generics: Generics,
557 data: Data::Struct {
558 fields: Unit,
559 semi_token: Some,
560 },
561 }
562 "###);
563 }
564
565 #[test]
566 fn test_pub_restricted_crate() {
567 let input = quote! {
568 pub(crate) struct S;
569 };
570
571 snapshot!(input as DeriveInput, @r###"
572 DeriveInput {
573 vis: Visibility::Restricted {
574 path: Path {
575 segments: [
576 PathSegment {
577 ident: "crate",
578 arguments: None,
579 },
580 ],
581 },
582 },
583 ident: "S",
584 generics: Generics,
585 data: Data::Struct {
586 fields: Unit,
587 semi_token: Some,
588 },
589 }
590 "###);
591 }
592
593 #[test]
594 fn test_pub_restricted_super() {
595 let input = quote! {
596 pub(super) struct S;
597 };
598
599 snapshot!(input as DeriveInput, @r###"
600 DeriveInput {
601 vis: Visibility::Restricted {
602 path: Path {
603 segments: [
604 PathSegment {
605 ident: "super",
606 arguments: None,
607 },
608 ],
609 },
610 },
611 ident: "S",
612 generics: Generics,
613 data: Data::Struct {
614 fields: Unit,
615 semi_token: Some,
616 },
617 }
618 "###);
619 }
620
621 #[test]
622 fn test_pub_restricted_in_super() {
623 let input = quote! {
624 pub(in super) struct S;
625 };
626
627 snapshot!(input as DeriveInput, @r###"
628 DeriveInput {
629 vis: Visibility::Restricted {
630 in_token: Some,
631 path: Path {
632 segments: [
633 PathSegment {
634 ident: "super",
635 arguments: None,
636 },
637 ],
638 },
639 },
640 ident: "S",
641 generics: Generics,
642 data: Data::Struct {
643 fields: Unit,
644 semi_token: Some,
645 },
646 }
647 "###);
648 }
649
650 #[test]
651 fn test_fields_on_unit_struct() {
652 let input = quote! {
653 struct S;
654 };
655
656 snapshot!(input as DeriveInput, @r###"
657 DeriveInput {
658 vis: Inherited,
659 ident: "S",
660 generics: Generics,
661 data: Data::Struct {
662 fields: Unit,
663 semi_token: Some,
664 },
665 }
666 "###);
667
668 let data = match input.data {
669 Data::Struct(data) => data,
670 _ => panic!("expected a struct"),
671 };
672
673 assert_eq!(0, data.fields.iter().count());
674 }
675
676 #[test]
677 fn test_fields_on_named_struct() {
678 let input = quote! {
679 struct S {
680 foo: i32,
681 pub bar: String,
682 }
683 };
684
685 snapshot!(input as DeriveInput, @r###"
686 DeriveInput {
687 vis: Inherited,
688 ident: "S",
689 generics: Generics,
690 data: Data::Struct {
691 fields: Fields::Named {
692 named: [
693 Field {
694 vis: Inherited,
695 ident: Some("foo"),
696 colon_token: Some,
697 ty: Type::Path {
698 path: Path {
699 segments: [
700 PathSegment {
701 ident: "i32",
702 arguments: None,
703 },
704 ],
705 },
706 },
707 },
708 Field {
709 vis: Visibility::Public,
710 ident: Some("bar"),
711 colon_token: Some,
712 ty: Type::Path {
713 path: Path {
714 segments: [
715 PathSegment {
716 ident: "String",
717 arguments: None,
718 },
719 ],
720 },
721 },
722 },
723 ],
724 },
725 },
726 }
727 "###);
728
729 let data = match input.data {
730 Data::Struct(data) => data,
731 _ => panic!("expected a struct"),
732 };
733
734 snapshot!(data.fields.into_iter().collect::<Vec<_>>(), @r###"
735 [
736 Field {
737 vis: Inherited,
738 ident: Some("foo"),
739 colon_token: Some,
740 ty: Type::Path {
741 path: Path {
742 segments: [
743 PathSegment {
744 ident: "i32",
745 arguments: None,
746 },
747 ],
748 },
749 },
750 },
751 Field {
752 vis: Visibility::Public,
753 ident: Some("bar"),
754 colon_token: Some,
755 ty: Type::Path {
756 path: Path {
757 segments: [
758 PathSegment {
759 ident: "String",
760 arguments: None,
761 },
762 ],
763 },
764 },
765 },
766 ]
767 "###);
768 }
769
770 #[test]
771 fn test_fields_on_tuple_struct() {
772 let input = quote! {
773 struct S(i32, pub String);
774 };
775
776 snapshot!(input as DeriveInput, @r###"
777 DeriveInput {
778 vis: Inherited,
779 ident: "S",
780 generics: Generics,
781 data: Data::Struct {
782 fields: Fields::Unnamed {
783 unnamed: [
784 Field {
785 vis: Inherited,
786 ty: Type::Path {
787 path: Path {
788 segments: [
789 PathSegment {
790 ident: "i32",
791 arguments: None,
792 },
793 ],
794 },
795 },
796 },
797 Field {
798 vis: Visibility::Public,
799 ty: Type::Path {
800 path: Path {
801 segments: [
802 PathSegment {
803 ident: "String",
804 arguments: None,
805 },
806 ],
807 },
808 },
809 },
810 ],
811 },
812 semi_token: Some,
813 },
814 }
815 "###);
816
817 let data = match input.data {
818 Data::Struct(data) => data,
819 _ => panic!("expected a struct"),
820 };
821
822 snapshot!(data.fields.iter().collect::<Vec<_>>(), @r###"
823 [
824 Field {
825 vis: Inherited,
826 ty: Type::Path {
827 path: Path {
828 segments: [
829 PathSegment {
830 ident: "i32",
831 arguments: None,
832 },
833 ],
834 },
835 },
836 },
837 Field {
838 vis: Visibility::Public,
839 ty: Type::Path {
840 path: Path {
841 segments: [
842 PathSegment {
843 ident: "String",
844 arguments: None,
845 },
846 ],
847 },
848 },
849 },
850 ]
851 "###);
852 }
853
854 #[test]
855 fn test_ambiguous_crate() {
856 let input = quote! {
857 // The field type is `(crate::X)` not `crate (::X)`.
858 struct S(crate::X);
859 };
860
861 snapshot!(input as DeriveInput, @r###"
862 DeriveInput {
863 vis: Inherited,
864 ident: "S",
865 generics: Generics,
866 data: Data::Struct {
867 fields: Fields::Unnamed {
868 unnamed: [
869 Field {
870 vis: Inherited,
871 ty: Type::Path {
872 path: Path {
873 segments: [
874 PathSegment {
875 ident: "crate",
876 arguments: None,
877 },
878 PathSegment {
879 ident: "X",
880 arguments: None,
881 },
882 ],
883 },
884 },
885 },
886 ],
887 },
888 semi_token: Some,
889 },
890 }
891 "###);
892 }