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