| 1 | #[cfg_attr ( |
| 2 | not(any(feature = "full" , feature = "derive" )), |
| 3 | allow(unknown_lints, unused_macro_rules) |
| 4 | )] |
| 5 | macro_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 | |
| 38 | macro_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 | |
| 59 | macro_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 | |
| 70 | macro_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 | |
| 102 | macro_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" )] |
| 116 | macro_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 | |
| 157 | macro_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 | |
| 165 | macro_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" ))] |
| 172 | macro_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" ))] |
| 180 | macro_rules! pub_if_not_doc { |
| 181 | ($(#[$m:meta])* pub $($item:tt)*) => { |
| 182 | $(#[$m])* |
| 183 | pub $($item)* |
| 184 | }; |
| 185 | } |
| 186 | |