File Index
Files and directories
Sign in
FILE

derive.rs

File preview with syntax highlighting.

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