xref: /linux/rust/syn/macros.rs (revision 784faa8eca8270671e0ed6d9d21f04bbb80fc5f7)
1 // SPDX-License-Identifier: Apache-2.0 OR MIT
2 
3 #[cfg_attr(
4     not(any(feature = "full", feature = "derive")),
5     allow(unknown_lints, unused_macro_rules)
6 )]
7 macro_rules! ast_struct {
8     (
9         $(#[$attr:meta])*
10         $pub:ident $struct:ident $name:ident #full $body:tt
11     ) => {
12         check_keyword_matches!(pub $pub);
13         check_keyword_matches!(struct $struct);
14 
15         #[cfg(feature = "full")]
16         $(#[$attr])* $pub $struct $name $body
17 
18         #[cfg(not(feature = "full"))]
19         $(#[$attr])* $pub $struct $name {
20             _noconstruct: ::std::marker::PhantomData<::proc_macro2::Span>,
21         }
22 
23         #[cfg(all(not(feature = "full"), feature = "printing"))]
24         impl ::quote::ToTokens for $name {
25             fn to_tokens(&self, _: &mut ::proc_macro2::TokenStream) {
26                 unreachable!()
27             }
28         }
29     };
30 
31     (
32         $(#[$attr:meta])*
33         $pub:ident $struct:ident $name:ident $body:tt
34     ) => {
35         check_keyword_matches!(pub $pub);
36         check_keyword_matches!(struct $struct);
37 
38         $(#[$attr])* $pub $struct $name $body
39     };
40 }
41 
42 #[cfg(any(feature = "full", feature = "derive"))]
43 macro_rules! ast_enum {
44     (
45         $(#[$enum_attr:meta])*
46         $pub:ident $enum:ident $name:ident $body:tt
47     ) => {
48         check_keyword_matches!(pub $pub);
49         check_keyword_matches!(enum $enum);
50 
51         $(#[$enum_attr])* $pub $enum $name $body
52     };
53 }
54 
55 macro_rules! ast_enum_of_structs {
56     (
57         $(#[$enum_attr:meta])*
58         $pub:ident $enum:ident $name:ident $body:tt
59     ) => {
60         check_keyword_matches!(pub $pub);
61         check_keyword_matches!(enum $enum);
62 
63         $(#[$enum_attr])* $pub $enum $name $body
64 
65         ast_enum_of_structs_impl!($name $body);
66 
67         #[cfg(feature = "printing")]
68         generate_to_tokens!(() tokens $name $body);
69     };
70 }
71 
72 macro_rules! ast_enum_of_structs_impl {
73     (
74         $name:ident {
75             $(
76                 $(#[cfg $cfg_attr:tt])*
77                 $(#[doc $($doc_attr:tt)*])*
78                 $variant:ident $( ($member:ident) )*,
79             )*
80         }
81     ) => {
82         $($(
83             ast_enum_from_struct!($name::$variant, $member);
84         )*)*
85     };
86 }
87 
88 macro_rules! ast_enum_from_struct {
89     // No From<TokenStream> for verbatim variants.
90     ($name:ident::Verbatim, $member:ident) => {};
91 
92     ($name:ident::$variant:ident, $member:ident) => {
93         impl From<$member> for $name {
94             fn from(e: $member) -> $name {
95                 $name::$variant(e)
96             }
97         }
98     };
99 }
100 
101 #[cfg(feature = "printing")]
102 macro_rules! generate_to_tokens {
103     (
104         ($($arms:tt)*) $tokens:ident $name:ident {
105             $(#[cfg $cfg_attr:tt])*
106             $(#[doc $($doc_attr:tt)*])*
107             $variant:ident,
108             $($next:tt)*
109         }
110     ) => {
111         generate_to_tokens!(
112             ($($arms)* $(#[cfg $cfg_attr])* $name::$variant => {})
113             $tokens $name { $($next)* }
114         );
115     };
116 
117     (
118         ($($arms:tt)*) $tokens:ident $name:ident {
119             $(#[cfg $cfg_attr:tt])*
120             $(#[doc $($doc_attr:tt)*])*
121             $variant:ident($member:ident),
122             $($next:tt)*
123         }
124     ) => {
125         generate_to_tokens!(
126             ($($arms)* $(#[cfg $cfg_attr])* $name::$variant(_e) => _e.to_tokens($tokens),)
127             $tokens $name { $($next)* }
128         );
129     };
130 
131     (($($arms:tt)*) $tokens:ident $name:ident {}) => {
132         #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
133         impl ::quote::ToTokens for $name {
134             fn to_tokens(&self, $tokens: &mut ::proc_macro2::TokenStream) {
135                 match self {
136                     $($arms)*
137                 }
138             }
139         }
140     };
141 }
142 
143 // Rustdoc bug: does not respect the doc(hidden) on some items.
144 #[cfg(all(doc, feature = "parsing"))]
145 macro_rules! pub_if_not_doc {
146     ($(#[$m:meta])* $pub:ident $($item:tt)*) => {
147         check_keyword_matches!(pub $pub);
148 
149         $(#[$m])*
150         $pub(crate) $($item)*
151     };
152 }
153 
154 #[cfg(all(not(doc), feature = "parsing"))]
155 macro_rules! pub_if_not_doc {
156     ($(#[$m:meta])* $pub:ident $($item:tt)*) => {
157         check_keyword_matches!(pub $pub);
158 
159         $(#[$m])*
160         $pub $($item)*
161     };
162 }
163 
164 macro_rules! check_keyword_matches {
165     (enum enum) => {};
166     (pub pub) => {};
167     (struct struct) => {};
168 }
169 
170 #[cfg(any(feature = "full", feature = "derive"))]
171 macro_rules! return_impl_trait {
172     (
173         $(#[$attr:meta])*
174         $vis:vis fn $name:ident $args:tt -> $impl_trait:ty [$concrete:ty] $body:block
175     ) => {
176         #[cfg(not(docsrs))]
177         $(#[$attr])*
178         $vis fn $name $args -> $concrete $body
179 
180         #[cfg(docsrs)]
181         $(#[$attr])*
182         $vis fn $name $args -> $impl_trait $body
183     };
184 }
185