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