Skip to main content

syn/
macros.rs

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)]
7macro_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"))]
43macro_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
55macro_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
72macro_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
88macro_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")]
102macro_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"))]
145macro_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"))]
155macro_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
164macro_rules! check_keyword_matches {
165    (enum enum) => {};
166    (pub pub) => {};
167    (struct struct) => {};
168}
169
170#[cfg(any(feature = "full", feature = "derive"))]
171macro_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}