standalone_syn/
derive.rs

1// Copyright 2018 Syn Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use super::*;
10use punctuated::Punctuated;
11
12ast_struct! {
13    /// Data structure sent to a `proc_macro_derive` macro.
14    ///
15    /// *This type is available if Syn is built with the `"derive"` feature.*
16    pub struct DeriveInput {
17        /// Attributes tagged on the whole struct or enum.
18        pub attrs: Vec<Attribute>,
19
20        /// Visibility of the struct or enum.
21        pub vis: Visibility,
22
23        /// Name of the struct or enum.
24        pub ident: Ident,
25
26        /// Generics required to complete the definition.
27        pub generics: Generics,
28
29        /// Data within the struct or enum.
30        pub data: Data,
31    }
32}
33
34ast_enum_of_structs! {
35    /// The storage of a struct, enum or union data structure.
36    ///
37    /// *This type is available if Syn is built with the `"derive"` feature.*
38    ///
39    /// # Syntax tree enum
40    ///
41    /// This type is a [syntax tree enum].
42    ///
43    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
44    pub enum Data {
45        /// A struct input to a `proc_macro_derive` macro.
46        ///
47        /// *This type is available if Syn is built with the `"derive"`
48        /// feature.*
49        pub Struct(DataStruct {
50            pub struct_token: Token![struct],
51            pub fields: Fields,
52            pub semi_token: Option<Token![;]>,
53        }),
54
55        /// An enum input to a `proc_macro_derive` macro.
56        ///
57        /// *This type is available if Syn is built with the `"derive"`
58        /// feature.*
59        pub Enum(DataEnum {
60            pub enum_token: Token![enum],
61            pub brace_token: token::Brace,
62            pub variants: Punctuated<Variant, Token![,]>,
63        }),
64
65        /// A tagged union input to a `proc_macro_derive` macro.
66        ///
67        /// *This type is available if Syn is built with the `"derive"`
68        /// feature.*
69        pub Union(DataUnion {
70            pub union_token: Token![union],
71            pub fields: FieldsNamed,
72        }),
73    }
74
75    do_not_generate_to_tokens
76}
77
78#[cfg(feature = "parsing")]
79pub mod parsing {
80    use super::*;
81
82    use synom::Synom;
83
84    impl Synom for DeriveInput {
85        named!(parse -> Self, do_parse!(
86            attrs: many0!(Attribute::parse_outer) >>
87            vis: syn!(Visibility) >>
88            which: alt!(
89                keyword!(struct) => { Ok }
90                |
91                keyword!(enum) => { Err }
92            ) >>
93            id: syn!(Ident) >>
94            generics: syn!(Generics) >>
95            item: switch!(value!(which),
96                Ok(s) => map!(data_struct, move |(wh, fields, semi)| DeriveInput {
97                    ident: id,
98                    vis: vis,
99                    attrs: attrs,
100                    generics: Generics {
101                        where_clause: wh,
102                        .. generics
103                    },
104                    data: Data::Struct(DataStruct {
105                        struct_token: s,
106                        fields: fields,
107                        semi_token: semi,
108                    }),
109                })
110                |
111                Err(e) => map!(data_enum, move |(wh, brace, variants)| DeriveInput {
112                    ident: id,
113                    vis: vis,
114                    attrs: attrs,
115                    generics: Generics {
116                        where_clause: wh,
117                        .. generics
118                    },
119                    data: Data::Enum(DataEnum {
120                        variants: variants,
121                        brace_token: brace,
122                        enum_token: e,
123                    }),
124                })
125            ) >>
126            (item)
127        ));
128
129        fn description() -> Option<&'static str> {
130            Some("derive input")
131        }
132    }
133
134    named!(data_struct -> (Option<WhereClause>, Fields, Option<Token![;]>), alt!(
135        do_parse!(
136            wh: option!(syn!(WhereClause)) >>
137            fields: syn!(FieldsNamed) >>
138            (wh, Fields::Named(fields), None)
139        )
140        |
141        do_parse!(
142            fields: syn!(FieldsUnnamed) >>
143            wh: option!(syn!(WhereClause)) >>
144            semi: punct!(;) >>
145            (wh, Fields::Unnamed(fields), Some(semi))
146        )
147        |
148        do_parse!(
149            wh: option!(syn!(WhereClause)) >>
150            semi: punct!(;) >>
151            (wh, Fields::Unit, Some(semi))
152        )
153    ));
154
155    named!(data_enum -> (Option<WhereClause>, token::Brace, Punctuated<Variant, Token![,]>), do_parse!(
156        wh: option!(syn!(WhereClause)) >>
157        data: braces!(Punctuated::parse_terminated) >>
158        (wh, data.0, data.1)
159    ));
160}
161
162#[cfg(feature = "printing")]
163mod printing {
164    use super::*;
165    use attr::FilterAttrs;
166    use quote::{ToTokens, Tokens};
167
168    impl ToTokens for DeriveInput {
169        fn to_tokens(&self, tokens: &mut Tokens) {
170            for attr in self.attrs.outer() {
171                attr.to_tokens(tokens);
172            }
173            self.vis.to_tokens(tokens);
174            match self.data {
175                Data::Struct(ref d) => d.struct_token.to_tokens(tokens),
176                Data::Enum(ref d) => d.enum_token.to_tokens(tokens),
177                Data::Union(ref d) => d.union_token.to_tokens(tokens),
178            }
179            self.ident.to_tokens(tokens);
180            self.generics.to_tokens(tokens);
181            match self.data {
182                Data::Struct(ref data) => match data.fields {
183                    Fields::Named(ref fields) => {
184                        self.generics.where_clause.to_tokens(tokens);
185                        fields.to_tokens(tokens);
186                    }
187                    Fields::Unnamed(ref fields) => {
188                        fields.to_tokens(tokens);
189                        self.generics.where_clause.to_tokens(tokens);
190                        TokensOrDefault(&data.semi_token).to_tokens(tokens);
191                    }
192                    Fields::Unit => {
193                        self.generics.where_clause.to_tokens(tokens);
194                        TokensOrDefault(&data.semi_token).to_tokens(tokens);
195                    }
196                },
197                Data::Enum(ref data) => {
198                    self.generics.where_clause.to_tokens(tokens);
199                    data.brace_token.surround(tokens, |tokens| {
200                        data.variants.to_tokens(tokens);
201                    });
202                }
203                Data::Union(ref data) => {
204                    self.generics.where_clause.to_tokens(tokens);
205                    data.fields.to_tokens(tokens);
206                }
207            }
208        }
209    }
210}