syn/
macros.rs

1macro_rules! ast_struct {
2    (
3        [$($attrs_pub:tt)*]
4        struct $name:ident #full $($rest:tt)*
5    ) => {
6        #[cfg(feature = "full")]
7        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
8        #[cfg_attr(feature = "clone-impls", derive(Clone))]
9        $($attrs_pub)* struct $name $($rest)*
10
11        #[cfg(not(feature = "full"))]
12        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
13        #[cfg_attr(feature = "clone-impls", derive(Clone))]
14        $($attrs_pub)* struct $name {
15            _noconstruct: (),
16        }
17
18        #[cfg(all(not(feature = "full"), feature = "printing"))]
19        impl ::quote::ToTokens for $name {
20            fn to_tokens(&self, _: &mut ::proc_macro2::TokenStream) {
21                unreachable!()
22            }
23        }
24    };
25
26    (
27        [$($attrs_pub:tt)*]
28        struct $name:ident #manual_extra_traits $($rest:tt)*
29    ) => {
30        #[cfg_attr(feature = "extra-traits", derive(Debug))]
31        #[cfg_attr(feature = "clone-impls", derive(Clone))]
32        $($attrs_pub)* struct $name $($rest)*
33    };
34
35    (
36        [$($attrs_pub:tt)*]
37        struct $name:ident #manual_extra_traits_debug $($rest:tt)*
38    ) => {
39        #[cfg_attr(feature = "clone-impls", derive(Clone))]
40        $($attrs_pub)* struct $name $($rest)*
41    };
42
43    (
44        [$($attrs_pub:tt)*]
45        struct $name:ident $($rest:tt)*
46    ) => {
47        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
48        #[cfg_attr(feature = "clone-impls", derive(Clone))]
49        $($attrs_pub)* struct $name $($rest)*
50    };
51
52    ($($t:tt)*) => {
53        strip_attrs_pub!(ast_struct!($($t)*));
54    };
55}
56
57macro_rules! ast_enum {
58    // Drop the `#no_visit` attribute, if present.
59    (
60        [$($attrs_pub:tt)*]
61        enum $name:ident #no_visit $($rest:tt)*
62    ) => (
63        ast_enum!([$($attrs_pub)*] enum $name $($rest)*);
64    );
65
66    (
67        [$($attrs_pub:tt)*]
68        enum $name:ident #manual_extra_traits $($rest:tt)*
69    ) => (
70        #[cfg_attr(feature = "extra-traits", derive(Debug))]
71        #[cfg_attr(feature = "clone-impls", derive(Clone))]
72        $($attrs_pub)* enum $name $($rest)*
73    );
74
75    (
76        [$($attrs_pub:tt)*]
77        enum $name:ident $($rest:tt)*
78    ) => (
79        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
80        #[cfg_attr(feature = "clone-impls", derive(Clone))]
81        $($attrs_pub)* enum $name $($rest)*
82    );
83
84    ($($t:tt)*) => {
85        strip_attrs_pub!(ast_enum!($($t)*));
86    };
87}
88
89macro_rules! ast_enum_of_structs {
90    (
91        $(#[$enum_attr:meta])*
92        $pub:ident $enum:ident $name:ident #$tag:ident $body:tt
93        $($remaining:tt)*
94    ) => {
95        ast_enum!($(#[$enum_attr])* $pub $enum $name #$tag $body);
96        ast_enum_of_structs_impl!($pub $enum $name $body $($remaining)*);
97    };
98
99    (
100        $(#[$enum_attr:meta])*
101        $pub:ident $enum:ident $name:ident $body:tt
102        $($remaining:tt)*
103    ) => {
104        ast_enum!($(#[$enum_attr])* $pub $enum $name $body);
105        ast_enum_of_structs_impl!($pub $enum $name $body $($remaining)*);
106    };
107}
108
109macro_rules! ast_enum_of_structs_impl {
110    (
111        $pub:ident $enum:ident $name:ident {
112            $(
113                $(#[$variant_attr:meta])*
114                $variant:ident $( ($member:ident) )*,
115            )*
116        }
117
118        $($remaining:tt)*
119    ) => {
120        check_keyword_matches!(pub $pub);
121        check_keyword_matches!(enum $enum);
122
123        $($(
124            ast_enum_from_struct!($name::$variant, $member);
125        )*)*
126
127        #[cfg(feature = "printing")]
128        generate_to_tokens! {
129            $($remaining)*
130            ()
131            tokens
132            $name { $($variant $($member)*,)* }
133        }
134    };
135}
136
137macro_rules! ast_enum_from_struct {
138    // No From<TokenStream> for verbatim variants.
139    ($name:ident::Verbatim, $member:ident) => {};
140
141    ($name:ident::$variant:ident, $member:ident) => {
142        impl From<$member> for $name {
143            fn from(e: $member) -> $name {
144                $name::$variant(e)
145            }
146        }
147    };
148}
149
150#[cfg(feature = "printing")]
151macro_rules! generate_to_tokens {
152    (do_not_generate_to_tokens $($foo:tt)*) => ();
153
154    (($($arms:tt)*) $tokens:ident $name:ident { $variant:ident, $($next:tt)*}) => {
155        generate_to_tokens!(
156            ($($arms)* $name::$variant => {})
157            $tokens $name { $($next)* }
158        );
159    };
160
161    (($($arms:tt)*) $tokens:ident $name:ident { $variant:ident $member:ident, $($next:tt)*}) => {
162        generate_to_tokens!(
163            ($($arms)* $name::$variant(_e) => _e.to_tokens($tokens),)
164            $tokens $name { $($next)* }
165        );
166    };
167
168    (($($arms:tt)*) $tokens:ident $name:ident {}) => {
169        impl ::quote::ToTokens for $name {
170            fn to_tokens(&self, $tokens: &mut ::proc_macro2::TokenStream) {
171                match self {
172                    $($arms)*
173                }
174            }
175        }
176    };
177}
178
179macro_rules! strip_attrs_pub {
180    ($mac:ident!($(#[$m:meta])* $pub:ident $($t:tt)*)) => {
181        check_keyword_matches!(pub $pub);
182
183        $mac!([$(#[$m])* $pub] $($t)*);
184    };
185}
186
187macro_rules! check_keyword_matches {
188    (struct struct) => {};
189    (enum enum) => {};
190    (pub pub) => {};
191}