syn/
macros.rs

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