1 // SPDX-License-Identifier: Apache-2.0 OR MIT 2 3 use crate::attr::Attribute; 4 use crate::data::{Fields, FieldsNamed, Variant}; 5 use crate::generics::Generics; 6 use crate::ident::Ident; 7 use crate::punctuated::Punctuated; 8 use crate::restriction::Visibility; 9 use crate::token; 10 11 ast_struct! { 12 /// Data structure sent to a `proc_macro_derive` macro. 13 #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] 14 pub struct DeriveInput { 15 pub attrs: Vec<Attribute>, 16 pub vis: Visibility, 17 pub ident: Ident, 18 pub generics: Generics, 19 pub data: Data, 20 } 21 } 22 23 ast_enum! { 24 /// The storage of a struct, enum or union data structure. 25 /// 26 /// # Syntax tree enum 27 /// 28 /// This type is a [syntax tree enum]. 29 /// 30 /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums 31 #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] 32 pub enum Data { 33 Struct(DataStruct), 34 Enum(DataEnum), 35 Union(DataUnion), 36 } 37 } 38 39 ast_struct! { 40 /// A struct input to a `proc_macro_derive` macro. 41 #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] 42 pub struct DataStruct { 43 pub struct_token: Token![struct], 44 pub fields: Fields, 45 pub semi_token: Option<Token![;]>, 46 } 47 } 48 49 ast_struct! { 50 /// An enum input to a `proc_macro_derive` macro. 51 #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] 52 pub struct DataEnum { 53 pub enum_token: Token![enum], 54 pub brace_token: token::Brace, 55 pub variants: Punctuated<Variant, Token![,]>, 56 } 57 } 58 59 ast_struct! { 60 /// An untagged union input to a `proc_macro_derive` macro. 61 #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] 62 pub struct DataUnion { 63 pub union_token: Token![union], 64 pub fields: FieldsNamed, 65 } 66 } 67 68 #[cfg(feature = "parsing")] 69 pub(crate) mod parsing { 70 use crate::attr::Attribute; 71 use crate::data::{Fields, FieldsNamed, Variant}; 72 use crate::derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput}; 73 use crate::error::Result; 74 use crate::generics::{Generics, WhereClause}; 75 use crate::ident::Ident; 76 use crate::parse::{Parse, ParseStream}; 77 use crate::punctuated::Punctuated; 78 use crate::restriction::Visibility; 79 use crate::token; 80 81 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 82 impl Parse for DeriveInput { parse(input: ParseStream) -> Result<Self>83 fn parse(input: ParseStream) -> Result<Self> { 84 let attrs = input.call(Attribute::parse_outer)?; 85 let vis = input.parse::<Visibility>()?; 86 87 let lookahead = input.lookahead1(); 88 if lookahead.peek(Token![struct]) { 89 let struct_token = input.parse::<Token![struct]>()?; 90 let ident = input.parse::<Ident>()?; 91 let generics = input.parse::<Generics>()?; 92 let (where_clause, fields, semi) = data_struct(input)?; 93 Ok(DeriveInput { 94 attrs, 95 vis, 96 ident, 97 generics: Generics { 98 where_clause, 99 ..generics 100 }, 101 data: Data::Struct(DataStruct { 102 struct_token, 103 fields, 104 semi_token: semi, 105 }), 106 }) 107 } else if lookahead.peek(Token![enum]) { 108 let enum_token = input.parse::<Token![enum]>()?; 109 let ident = input.parse::<Ident>()?; 110 let generics = input.parse::<Generics>()?; 111 let (where_clause, brace, variants) = data_enum(input)?; 112 Ok(DeriveInput { 113 attrs, 114 vis, 115 ident, 116 generics: Generics { 117 where_clause, 118 ..generics 119 }, 120 data: Data::Enum(DataEnum { 121 enum_token, 122 brace_token: brace, 123 variants, 124 }), 125 }) 126 } else if lookahead.peek(Token![union]) { 127 let union_token = input.parse::<Token![union]>()?; 128 let ident = input.parse::<Ident>()?; 129 let generics = input.parse::<Generics>()?; 130 let (where_clause, fields) = data_union(input)?; 131 Ok(DeriveInput { 132 attrs, 133 vis, 134 ident, 135 generics: Generics { 136 where_clause, 137 ..generics 138 }, 139 data: Data::Union(DataUnion { 140 union_token, 141 fields, 142 }), 143 }) 144 } else { 145 Err(lookahead.error()) 146 } 147 } 148 } 149 data_struct( input: ParseStream, ) -> Result<(Option<WhereClause>, Fields, Option<Token![;]>)>150 pub(crate) fn data_struct( 151 input: ParseStream, 152 ) -> Result<(Option<WhereClause>, Fields, Option<Token![;]>)> { 153 let mut lookahead = input.lookahead1(); 154 let mut where_clause = None; 155 if lookahead.peek(Token![where]) { 156 where_clause = Some(input.parse()?); 157 lookahead = input.lookahead1(); 158 } 159 160 if where_clause.is_none() && lookahead.peek(token::Paren) { 161 let fields = input.parse()?; 162 163 lookahead = input.lookahead1(); 164 if lookahead.peek(Token![where]) { 165 where_clause = Some(input.parse()?); 166 lookahead = input.lookahead1(); 167 } 168 169 if lookahead.peek(Token![;]) { 170 let semi = input.parse()?; 171 Ok((where_clause, Fields::Unnamed(fields), Some(semi))) 172 } else { 173 Err(lookahead.error()) 174 } 175 } else if lookahead.peek(token::Brace) { 176 let fields = input.parse()?; 177 Ok((where_clause, Fields::Named(fields), None)) 178 } else if lookahead.peek(Token![;]) { 179 let semi = input.parse()?; 180 Ok((where_clause, Fields::Unit, Some(semi))) 181 } else { 182 Err(lookahead.error()) 183 } 184 } 185 data_enum( input: ParseStream, ) -> Result<( Option<WhereClause>, token::Brace, Punctuated<Variant, Token![,]>, )>186 pub(crate) fn data_enum( 187 input: ParseStream, 188 ) -> Result<( 189 Option<WhereClause>, 190 token::Brace, 191 Punctuated<Variant, Token![,]>, 192 )> { 193 let where_clause = input.parse()?; 194 195 let content; 196 let brace = braced!(content in input); 197 let variants = content.parse_terminated(Variant::parse, Token![,])?; 198 199 Ok((where_clause, brace, variants)) 200 } 201 data_union(input: ParseStream) -> Result<(Option<WhereClause>, FieldsNamed)>202 pub(crate) fn data_union(input: ParseStream) -> Result<(Option<WhereClause>, FieldsNamed)> { 203 let where_clause = input.parse()?; 204 let fields = input.parse()?; 205 Ok((where_clause, fields)) 206 } 207 } 208 209 #[cfg(feature = "printing")] 210 mod printing { 211 use crate::attr::FilterAttrs; 212 use crate::data::Fields; 213 use crate::derive::{Data, DeriveInput}; 214 use crate::print::TokensOrDefault; 215 use proc_macro2::TokenStream; 216 use quote::ToTokens; 217 218 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 219 impl ToTokens for DeriveInput { to_tokens(&self, tokens: &mut TokenStream)220 fn to_tokens(&self, tokens: &mut TokenStream) { 221 for attr in self.attrs.outer() { 222 attr.to_tokens(tokens); 223 } 224 self.vis.to_tokens(tokens); 225 match &self.data { 226 Data::Struct(d) => d.struct_token.to_tokens(tokens), 227 Data::Enum(d) => d.enum_token.to_tokens(tokens), 228 Data::Union(d) => d.union_token.to_tokens(tokens), 229 } 230 self.ident.to_tokens(tokens); 231 self.generics.to_tokens(tokens); 232 match &self.data { 233 Data::Struct(data) => match &data.fields { 234 Fields::Named(fields) => { 235 self.generics.where_clause.to_tokens(tokens); 236 fields.to_tokens(tokens); 237 } 238 Fields::Unnamed(fields) => { 239 fields.to_tokens(tokens); 240 self.generics.where_clause.to_tokens(tokens); 241 TokensOrDefault(&data.semi_token).to_tokens(tokens); 242 } 243 Fields::Unit => { 244 self.generics.where_clause.to_tokens(tokens); 245 TokensOrDefault(&data.semi_token).to_tokens(tokens); 246 } 247 }, 248 Data::Enum(data) => { 249 self.generics.where_clause.to_tokens(tokens); 250 data.brace_token.surround(tokens, |tokens| { 251 data.variants.to_tokens(tokens); 252 }); 253 } 254 Data::Union(data) => { 255 self.generics.where_clause.to_tokens(tokens); 256 data.fields.to_tokens(tokens); 257 } 258 } 259 } 260 } 261 } 262