blob: ef6490e331b8aa22376e309a145e8ba708473366 [file] [log] [blame]
use super::*;
use delimited::Delimited;
ast_struct! {
/// An enum variant.
pub struct Variant {
/// Name of the variant.
pub ident: Ident,
/// Attributes tagged on the variant.
pub attrs: Vec<Attribute>,
/// Type of variant.
pub data: VariantData,
/// Explicit discriminant, e.g. `Foo = 1`
pub discriminant: Option<ConstExpr>,
pub eq_token: Option<tokens::Eq>,
}
}
ast_enum! {
/// Data stored within an enum variant or struct.
pub enum VariantData {
/// Struct variant, e.g. `Point { x: f64, y: f64 }`.
Struct(Delimited<Field, tokens::Comma>, tokens::Brace),
/// Tuple variant, e.g. `Some(T)`.
Tuple(Delimited<Field, tokens::Comma>, tokens::Paren),
/// Unit variant, e.g. `None`.
Unit,
}
}
impl VariantData {
// TODO: expose this?
// /// Slice containing the fields stored in the variant.
// pub fn fields(&self) -> &Delimited<Field, tokens::Comma> {
// match *self {
// VariantData::Struct(ref fields, _) |
// VariantData::Tuple(ref fields, _) => fields,
// VariantData::Unit => &[],
// }
// }
//
// /// Mutable slice containing the fields stored in the variant.
// pub fn fields_mut(&mut self) -> &mut Delimited<Field, tokens::Comma> {
// match *self {
// VariantData::Struct(ref mut fields, _) |
// VariantData::Tuple(ref mut fields, _) => fields,
// VariantData::Unit => &mut [],
// }
// }
}
ast_struct! {
/// A field of a struct or enum variant.
pub struct Field {
/// Name of the field, if any.
///
/// Fields of tuple structs have no names.
pub ident: Option<Ident>,
/// Visibility of the field.
pub vis: Visibility,
/// Attributes tagged on the field.
pub attrs: Vec<Attribute>,
/// Type of the field.
pub ty: Ty,
pub colon_token: Option<tokens::Colon>,
}
}
ast_enum_of_structs! {
/// Visibility level of an item.
pub enum Visibility {
/// Public, i.e. `pub`.
pub Public(VisPublic {
pub pub_token: tokens::Pub,
}),
/// Crate-visible, i.e. `pub(crate)`.
pub Crate(VisCrate {
pub pub_token: tokens::Pub,
pub paren_token: tokens::Paren,
pub crate_token: tokens::Crate,
}),
/// Restricted, e.g. `pub(self)` or `pub(super)` or `pub(in some::module)`.
pub Restricted(VisRestricted {
pub pub_token: tokens::Pub,
pub paren_token: tokens::Paren,
pub in_token: Option<tokens::In>,
pub path: Box<Path>,
}),
/// Inherited, i.e. private.
pub Inherited(VisInherited {}),
}
}
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
use synom::Synom;
use synom::tokens;
use synom::tokens::*;
impl Field {
named!(pub parse_struct -> Self, do_parse!(
attrs: many0!(call!(Attribute::parse_outer)) >>
vis: syn!(Visibility) >>
id: syn!(Ident) >>
colon: syn!(Colon) >>
ty: syn!(Ty) >>
(Field {
ident: Some(id),
vis: vis,
attrs: attrs,
ty: ty,
colon_token: Some(colon),
})
));
named!(pub parse_tuple -> Self, do_parse!(
attrs: many0!(call!(Attribute::parse_outer)) >>
vis: syn!(Visibility) >>
ty: syn!(Ty) >>
(Field {
ident: None,
colon_token: None,
vis: vis,
attrs: attrs,
ty: ty,
})
));
}
impl Synom for Visibility {
named!(parse -> Self, alt!(
do_parse!(
pub_token: syn!(Pub) >>
other: parens!(syn!(tokens::Crate)) >>
(Visibility::Crate(VisCrate {
crate_token: other.0,
paren_token: other.1,
pub_token: pub_token,
}))
)
|
do_parse!(
pub_token: syn!(Pub) >>
other: parens!(syn!(Self_)) >>
(Visibility::Restricted(VisRestricted {
path: Box::new(other.0.into()),
in_token: None,
paren_token: other.1,
pub_token: pub_token,
}))
)
|
do_parse!(
pub_token: syn!(Pub) >>
other: parens!(syn!(Super)) >>
(Visibility::Restricted(VisRestricted {
path: Box::new(other.0.into()),
in_token: None,
paren_token: other.1,
pub_token: pub_token,
}))
)
|
do_parse!(
pub_token: syn!(Pub) >>
other: parens!(do_parse!(
in_tok: syn!(In) >>
restricted: call!(Path::parse_mod_style) >>
(in_tok, restricted)
)) >>
(Visibility::Restricted(VisRestricted {
path: Box::new((other.0).1),
in_token: Some((other.0).0),
paren_token: other.1,
pub_token: pub_token,
}))
)
|
syn!(Pub) => { |tok| {
Visibility::Public(VisPublic {
pub_token: tok,
})
} }
|
epsilon!() => { |_| Visibility::Inherited(VisInherited {}) }
));
}
}
#[cfg(feature = "printing")]
mod printing {
use super::*;
use quote::{Tokens, ToTokens};
impl ToTokens for Variant {
fn to_tokens(&self, tokens: &mut Tokens) {
tokens.append_all(&self.attrs);
self.ident.to_tokens(tokens);
self.data.to_tokens(tokens);
self.eq_token.to_tokens(tokens);
self.discriminant.to_tokens(tokens);
}
}
impl ToTokens for VariantData {
fn to_tokens(&self, tokens: &mut Tokens) {
match *self {
VariantData::Struct(ref fields, ref brace) => {
brace.surround(tokens, |tokens| {
fields.to_tokens(tokens);
});
}
VariantData::Tuple(ref fields, ref paren) => {
paren.surround(tokens, |tokens| {
fields.to_tokens(tokens);
});
}
VariantData::Unit => {}
}
}
}
impl ToTokens for Field {
fn to_tokens(&self, tokens: &mut Tokens) {
tokens.append_all(&self.attrs);
self.vis.to_tokens(tokens);
self.ident.to_tokens(tokens);
self.colon_token.to_tokens(tokens);
self.ty.to_tokens(tokens);
}
}
impl ToTokens for VisPublic {
fn to_tokens(&self, tokens: &mut Tokens) {
self.pub_token.to_tokens(tokens)
}
}
impl ToTokens for VisCrate {
fn to_tokens(&self, tokens: &mut Tokens) {
self.pub_token.to_tokens(tokens);
self.paren_token.surround(tokens, |tokens| {
self.crate_token.to_tokens(tokens);
})
}
}
impl ToTokens for VisRestricted {
fn to_tokens(&self, tokens: &mut Tokens) {
self.pub_token.to_tokens(tokens);
self.paren_token.surround(tokens, |tokens| {
self.in_token.to_tokens(tokens);
self.path.to_tokens(tokens);
});
}
}
impl ToTokens for VisInherited {
fn to_tokens(&self, _tokens: &mut Tokens) {
}
}
}