| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- // SPDX-License-Identifier: Apache-2.0 OR MIT
- use crate::attr::Attribute;
- use crate::data::{Fields, FieldsNamed, Variant};
- use crate::generics::Generics;
- use crate::ident::Ident;
- use crate::punctuated::Punctuated;
- use crate::restriction::Visibility;
- use crate::token;
- ast_struct! {
- /// Data structure sent to a `proc_macro_derive` macro.
- #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
- pub struct DeriveInput {
- pub attrs: Vec<Attribute>,
- pub vis: Visibility,
- pub ident: Ident,
- pub generics: Generics,
- pub data: Data,
- }
- }
- ast_enum! {
- /// The storage of a struct, enum or union data structure.
- ///
- /// # Syntax tree enum
- ///
- /// This type is a [syntax tree enum].
- ///
- /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
- #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
- pub enum Data {
- Struct(DataStruct),
- Enum(DataEnum),
- Union(DataUnion),
- }
- }
- ast_struct! {
- /// A struct input to a `proc_macro_derive` macro.
- #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
- pub struct DataStruct {
- pub struct_token: Token![struct],
- pub fields: Fields,
- pub semi_token: Option<Token![;]>,
- }
- }
- ast_struct! {
- /// An enum input to a `proc_macro_derive` macro.
- #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
- pub struct DataEnum {
- pub enum_token: Token![enum],
- pub brace_token: token::Brace,
- pub variants: Punctuated<Variant, Token![,]>,
- }
- }
- ast_struct! {
- /// An untagged union input to a `proc_macro_derive` macro.
- #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
- pub struct DataUnion {
- pub union_token: Token![union],
- pub fields: FieldsNamed,
- }
- }
- #[cfg(feature = "parsing")]
- pub(crate) mod parsing {
- use crate::attr::Attribute;
- use crate::data::{Fields, FieldsNamed, Variant};
- use crate::derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput};
- use crate::error::Result;
- use crate::generics::{Generics, WhereClause};
- use crate::ident::Ident;
- use crate::parse::{Parse, ParseStream};
- use crate::punctuated::Punctuated;
- use crate::restriction::Visibility;
- use crate::token;
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for DeriveInput {
- fn parse(input: ParseStream) -> Result<Self> {
- let attrs = input.call(Attribute::parse_outer)?;
- let vis = input.parse::<Visibility>()?;
- let lookahead = input.lookahead1();
- if lookahead.peek(Token![struct]) {
- let struct_token = input.parse::<Token![struct]>()?;
- let ident = input.parse::<Ident>()?;
- let generics = input.parse::<Generics>()?;
- let (where_clause, fields, semi) = data_struct(input)?;
- Ok(DeriveInput {
- attrs,
- vis,
- ident,
- generics: Generics {
- where_clause,
- ..generics
- },
- data: Data::Struct(DataStruct {
- struct_token,
- fields,
- semi_token: semi,
- }),
- })
- } else if lookahead.peek(Token![enum]) {
- let enum_token = input.parse::<Token![enum]>()?;
- let ident = input.parse::<Ident>()?;
- let generics = input.parse::<Generics>()?;
- let (where_clause, brace, variants) = data_enum(input)?;
- Ok(DeriveInput {
- attrs,
- vis,
- ident,
- generics: Generics {
- where_clause,
- ..generics
- },
- data: Data::Enum(DataEnum {
- enum_token,
- brace_token: brace,
- variants,
- }),
- })
- } else if lookahead.peek(Token![union]) {
- let union_token = input.parse::<Token![union]>()?;
- let ident = input.parse::<Ident>()?;
- let generics = input.parse::<Generics>()?;
- let (where_clause, fields) = data_union(input)?;
- Ok(DeriveInput {
- attrs,
- vis,
- ident,
- generics: Generics {
- where_clause,
- ..generics
- },
- data: Data::Union(DataUnion {
- union_token,
- fields,
- }),
- })
- } else {
- Err(lookahead.error())
- }
- }
- }
- pub(crate) fn data_struct(
- input: ParseStream,
- ) -> Result<(Option<WhereClause>, Fields, Option<Token![;]>)> {
- let mut lookahead = input.lookahead1();
- let mut where_clause = None;
- if lookahead.peek(Token![where]) {
- where_clause = Some(input.parse()?);
- lookahead = input.lookahead1();
- }
- if where_clause.is_none() && lookahead.peek(token::Paren) {
- let fields = input.parse()?;
- lookahead = input.lookahead1();
- if lookahead.peek(Token![where]) {
- where_clause = Some(input.parse()?);
- lookahead = input.lookahead1();
- }
- if lookahead.peek(Token![;]) {
- let semi = input.parse()?;
- Ok((where_clause, Fields::Unnamed(fields), Some(semi)))
- } else {
- Err(lookahead.error())
- }
- } else if lookahead.peek(token::Brace) {
- let fields = input.parse()?;
- Ok((where_clause, Fields::Named(fields), None))
- } else if lookahead.peek(Token![;]) {
- let semi = input.parse()?;
- Ok((where_clause, Fields::Unit, Some(semi)))
- } else {
- Err(lookahead.error())
- }
- }
- pub(crate) fn data_enum(
- input: ParseStream,
- ) -> Result<(
- Option<WhereClause>,
- token::Brace,
- Punctuated<Variant, Token![,]>,
- )> {
- let where_clause = input.parse()?;
- let content;
- let brace = braced!(content in input);
- let variants = content.parse_terminated(Variant::parse, Token![,])?;
- Ok((where_clause, brace, variants))
- }
- pub(crate) fn data_union(input: ParseStream) -> Result<(Option<WhereClause>, FieldsNamed)> {
- let where_clause = input.parse()?;
- let fields = input.parse()?;
- Ok((where_clause, fields))
- }
- }
- #[cfg(feature = "printing")]
- mod printing {
- use crate::attr::FilterAttrs;
- use crate::data::Fields;
- use crate::derive::{Data, DeriveInput};
- use crate::print::TokensOrDefault;
- use proc_macro2::TokenStream;
- use quote::ToTokens;
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for DeriveInput {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- for attr in self.attrs.outer() {
- attr.to_tokens(tokens);
- }
- self.vis.to_tokens(tokens);
- match &self.data {
- Data::Struct(d) => d.struct_token.to_tokens(tokens),
- Data::Enum(d) => d.enum_token.to_tokens(tokens),
- Data::Union(d) => d.union_token.to_tokens(tokens),
- }
- self.ident.to_tokens(tokens);
- self.generics.to_tokens(tokens);
- match &self.data {
- Data::Struct(data) => match &data.fields {
- Fields::Named(fields) => {
- self.generics.where_clause.to_tokens(tokens);
- fields.to_tokens(tokens);
- }
- Fields::Unnamed(fields) => {
- fields.to_tokens(tokens);
- self.generics.where_clause.to_tokens(tokens);
- TokensOrDefault(&data.semi_token).to_tokens(tokens);
- }
- Fields::Unit => {
- self.generics.where_clause.to_tokens(tokens);
- TokensOrDefault(&data.semi_token).to_tokens(tokens);
- }
- },
- Data::Enum(data) => {
- self.generics.where_clause.to_tokens(tokens);
- data.brace_token.surround(tokens, |tokens| {
- data.variants.to_tokens(tokens);
- });
- }
- Data::Union(data) => {
- self.generics.where_clause.to_tokens(tokens);
- data.fields.to_tokens(tokens);
- }
- }
- }
- }
- }
|