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