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 check_keyword_matches!(pub $pub);
81 check_keyword_matches!(enum $enum);
82
83 $($(
84 ast_enum_from_struct!($name::$variant, $($member)::+);
85 )*)*
86
87 #[cfg(feature = "printing")]
88 generate_to_tokens! {
89 ()
90 tokens
91 $name {
92 $(
93 $(#[cfg $cfg_attr])*
94 $(#[doc $($doc_attr)*])*
95 $variant $($($member)::+)*,
96 )*
97 }
98 }
99 };
100}
101
102macro_rules! ast_enum_from_struct {
103 // No From<TokenStream> for verbatim variants.
104 ($name:ident::Verbatim, $member:ident) => {};
105
106 ($name:ident::$variant:ident, $member:ident) => {
107 impl From<$member> for $name {
108 fn from(e: $member) -> $name {
109 $name::$variant(e)
110 }
111 }
112 };
113}
114
115#[cfg(feature = "printing")]
116macro_rules! generate_to_tokens {
117 (
118 ($($arms:tt)*) $tokens:ident $name:ident {
119 $(#[cfg $cfg_attr:tt])*
120 $(#[doc $($doc_attr:tt)*])*
121 $variant:ident,
122 $($next:tt)*
123 }
124 ) => {
125 generate_to_tokens!(
126 ($($arms)* $(#[cfg $cfg_attr])* $name::$variant => {})
127 $tokens $name { $($next)* }
128 );
129 };
130
131 (
132 ($($arms:tt)*) $tokens:ident $name:ident {
133 $(#[cfg $cfg_attr:tt])*
134 $(#[doc $($doc_attr:tt)*])*
135 $variant:ident $member:ident,
136 $($next:tt)*
137 }
138 ) => {
139 generate_to_tokens!(
140 ($($arms)* $(#[cfg $cfg_attr])* $name::$variant(_e) => _e.to_tokens($tokens),)
141 $tokens $name { $($next)* }
142 );
143 };
144
145 (($($arms:tt)*) $tokens:ident $name:ident {}) => {
146 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
147 impl ::quote::ToTokens for $name {
148 fn to_tokens(&self, $tokens: &mut ::proc_macro2::TokenStream) {
149 match self {
150 $($arms)*
151 }
152 }
153 }
154 };
155}
156
157macro_rules! strip_attrs_pub {
158 ($mac:ident!($(#[$m:meta])* $pub:ident $($t:tt)*)) => {
159 check_keyword_matches!(pub $pub);
160
161 $mac!([$(#[$m])* $pub] $($t)*);
162 };
163}
164
165macro_rules! check_keyword_matches {
166 (enum enum) => {};
167 (pub pub) => {};
168}
169
170// Rustdoc bug: does not respect the doc(hidden) on some items.
171#[cfg(all(doc, feature = "parsing"))]
172macro_rules! pub_if_not_doc {
173 ($(#[$m:meta])* pub $($item:tt)*) => {
174 $(#[$m])*
175 pub(crate) $($item)*
176 };
177}
178
179#[cfg(all(not(doc), feature = "parsing"))]
180macro_rules! pub_if_not_doc {
181 ($(#[$m:meta])* pub $($item:tt)*) => {
182 $(#[$m])*
183 pub $($item)*
184 };
185}
186