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