// Copyright 2018 Syn Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use super::*;
use punctuated::Punctuated;
ast_struct! {
/// Data structure sent to a `proc_macro_derive` macro.
///
/// *This type is available if Syn is built with the `"derive"` feature.*
pub struct DeriveInput {
/// Attributes tagged on the whole struct or enum.
pub attrs: Vec<Attribute>,
/// Visibility of the struct or enum.
pub vis: Visibility,
/// Name of the struct or enum.
pub ident: Ident,
/// Generics required to complete the definition.
pub generics: Generics,
/// Data within the struct or enum.
pub data: Data,
}
}
ast_enum_of_structs! {
/// The storage of a struct, enum or union data structure.
///
/// *This type is available if Syn is built with the `"derive"` feature.*
///
/// # Syntax tree enum
///
/// This type is a [syntax tree enum].
///
/// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
pub enum Data {
/// A struct input to a `proc_macro_derive` macro.
///
/// *This type is available if Syn is built with the `"derive"`
/// feature.*
pub Struct(DataStruct {
pub struct_token: Token![struct],
pub fields: Fields,
pub semi_token: Option<Token![;]>,
}),
/// An enum input to a `proc_macro_derive` macro.
///
/// *This type is available if Syn is built with the `"derive"`
/// feature.*
pub Enum(DataEnum {
pub enum_token: Token![enum],
pub brace_token: token::Brace,
pub variants: Punctuated<Variant, Token![,]>,
}),
/// A tagged union input to a `proc_macro_derive` macro.
///
/// *This type is available if Syn is built with the `"derive"`
/// feature.*
pub Union(DataUnion {
pub union_token: Token![union],
pub fields: FieldsNamed,
}),
}
do_not_generate_to_tokens
}
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
use synom::Synom;
impl Synom for DeriveInput {
named!(parse -> Self, do_parse!(
attrs: many0!(Attribute::parse_outer) >>
vis: syn!(Visibility) >>
which: alt!(
keyword!(struct) => { Ok }
|
keyword!(enum) => { Err }
) >>
id: syn!(Ident) >>
generics: syn!(Generics) >>
item: switch!(value!(which),
Ok(s) => map!(data_struct, move |(wh, fields, semi)| DeriveInput {
ident: id,
vis: vis,
attrs: attrs,
generics: Generics {
where_clause: wh,
.. generics
},
data: Data::Struct(DataStruct {
struct_token: s,
fields: fields,
semi_token: semi,
}),
})
|
Err(e) => map!(data_enum, move |(wh, brace, variants)| DeriveInput {
ident: id,
vis: vis,
attrs: attrs,
generics: Generics {
where_clause: wh,
.. generics
},
data: Data::Enum(DataEnum {
variants: variants,
brace_token: brace,
enum_token: e,
}),
})
) >>
(item)
));
fn description() -> Option<&'static str> {
Some("derive input")
}
}
named!(data_struct -> (Option<WhereClause>, Fields, Option<Token![;]>), alt!(
do_parse!(
wh: option!(syn!(WhereClause)) >>
fields: syn!(FieldsNamed) >>
(wh, Fields::Named(fields), None)
)
|
do_parse!(
fields: syn!(FieldsUnnamed) >>
wh: option!(syn!(WhereClause)) >>
semi: punct!(;) >>
(wh, Fields::Unnamed(fields), Some(semi))
)
|
do_parse!(
wh: option!(syn!(WhereClause)) >>
semi: punct!(;) >>
(wh, Fields::Unit, Some(semi))
)
));
named!(data_enum -> (Option<WhereClause>, token::Brace, Punctuated<Variant, Token![,]>), do_parse!(
wh: option!(syn!(WhereClause)) >>
data: braces!(Punctuated::parse_terminated) >>
(wh, data.0, data.1)
));
}
#[cfg(feature = "printing")]
mod printing {
use super::*;
use attr::FilterAttrs;
use quote::{ToTokens, Tokens};
impl ToTokens for DeriveInput {
fn to_tokens(&self, tokens: &mut Tokens) {
for attr in self.attrs.outer() {
attr.to_tokens(tokens);
}
self.vis.to_tokens(tokens);
match self.data {
Data::Struct(ref d) => d.struct_token.to_tokens(tokens),
Data::Enum(ref d) => d.enum_token.to_tokens(tokens),
Data::Union(ref d) => d.union_token.to_tokens(tokens),
}
self.ident.to_tokens(tokens);
self.generics.to_tokens(tokens);
match self.data {
Data::Struct(ref data) => match data.fields {
Fields::Named(ref fields) => {
self.generics.where_clause.to_tokens(tokens);
fields.to_tokens(tokens);
}
Fields::Unnamed(ref 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(ref data) => {
self.generics.where_clause.to_tokens(tokens);
data.brace_token.surround(tokens, |tokens| {
data.variants.to_tokens(tokens);
});
}
Data::Union(ref data) => {
self.generics.where_clause.to_tokens(tokens);
data.fields.to_tokens(tokens);
}
}
}
}
}