Something went wrong. Try again.
Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262// 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); } } } }}