syn_pub_items/
derive.rs

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