blob: 4cbac330527611040cc8fa5dbcbc47cb6ad586ba [file] [log] [blame]
use super::*;
/// An item
///
/// The name might be a dummy name in case of anonymous items
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Item {
pub ident: Ident,
pub vis: Visibility,
pub attrs: Vec<Attribute>,
pub node: ItemKind,
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum ItemKind {
/// An`extern crate` item, with optional original crate name.
///
/// E.g. `extern crate foo` or `extern crate foo_bar as foo`
ExternCrate(Option<Ident>),
/// A use declaration (`use` or `pub use`) item.
///
/// E.g. `use foo;`, `use foo::bar;` or `use foo::bar as FooBar;`
Use(Box<ViewPath>),
/// A static item (`static` or `pub static`).
///
/// E.g. `static FOO: i32 = 42;` or `static FOO: &'static str = "bar";`
Static(Box<Ty>, Mutability, Box<Expr>),
/// A constant item (`const` or `pub const`).
///
/// E.g. `const FOO: i32 = 42;`
Const(Box<Ty>, Box<Expr>),
/// A function declaration (`fn` or `pub fn`).
///
/// E.g. `fn foo(bar: usize) -> usize { .. }`
Fn(Box<FnDecl>, Unsafety, Constness, Option<Abi>, Generics, Box<Block>),
/// A module declaration (`mod` or `pub mod`).
///
/// E.g. `mod foo;` or `mod foo { .. }`
Mod(Option<Vec<Item>>),
/// An external module (`extern` or `pub extern`).
///
/// E.g. `extern {}` or `extern "C" {}`
ForeignMod(ForeignMod),
/// A type alias (`type` or `pub type`).
///
/// E.g. `type Foo = Bar<u8>;`
Ty(Box<Ty>, Generics),
/// An enum definition (`enum` or `pub enum`).
///
/// E.g. `enum Foo<A, B> { C<A>, D<B> }`
Enum(Vec<Variant>, Generics),
/// A struct definition (`struct` or `pub struct`).
///
/// E.g. `struct Foo<A> { x: A }`
Struct(VariantData, Generics),
/// A union definition (`union` or `pub union`).
///
/// E.g. `union Foo<A, B> { x: A, y: B }`
Union(VariantData, Generics),
/// A Trait declaration (`trait` or `pub trait`).
///
/// E.g. `trait Foo { .. }` or `trait Foo<T> { .. }`
Trait(Unsafety, Generics, Vec<TyParamBound>, Vec<TraitItem>),
/// Default trait implementation.
///
/// E.g. `impl Trait for .. {}` or `impl<T> Trait<T> for .. {}`
DefaultImpl(Unsafety, Path),
/// An implementation.
///
/// E.g. `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`
Impl(Unsafety,
ImplPolarity,
Generics,
Option<Path>, // (optional) trait this impl implements
Box<Ty>, // self
Vec<ImplItem>),
/// A macro invocation (which includes macro definition).
///
/// E.g. `macro_rules! foo { .. }` or `foo!(..)`
Mac(Mac),
}
impl From<DeriveInput> for Item {
fn from(input: DeriveInput) -> Item {
Item {
ident: input.ident,
vis: input.vis,
attrs: input.attrs,
node: match input.body {
Body::Enum(variants) => ItemKind::Enum(variants, input.generics),
Body::Struct(variant_data) => ItemKind::Struct(variant_data, input.generics),
},
}
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum ViewPath {
/// `foo::bar::baz as quux`
///
/// or just
///
/// `foo::bar::baz` (with `as baz` implicitly on the right)
Simple(Path, Option<Ident>),
/// `foo::bar::*`
Glob(Path),
/// `foo::bar::{a, b, c}`
List(Path, Vec<PathListItem>),
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct PathListItem {
pub name: Ident,
/// renamed in list, e.g. `use foo::{bar as baz};`
pub rename: Option<Ident>,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Constness {
Const,
NotConst,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Defaultness {
Default,
Final,
}
/// Foreign module declaration.
///
/// E.g. `extern { .. }` or `extern "C" { .. }`
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct ForeignMod {
pub abi: Abi,
pub items: Vec<ForeignItem>,
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct ForeignItem {
pub ident: Ident,
pub attrs: Vec<Attribute>,
pub node: ForeignItemKind,
pub vis: Visibility,
}
/// An item within an `extern` block
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum ForeignItemKind {
/// A foreign function
Fn(Box<FnDecl>, Generics),
/// A foreign static item (`static ext: u8`)
Static(Box<Ty>, Mutability),
}
/// Represents an item declaration within a trait declaration,
/// possibly including a default implementation. A trait item is
/// either required (meaning it doesn't have an implementation, just a
/// signature) or provided (meaning it has a default implementation).
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct TraitItem {
pub ident: Ident,
pub attrs: Vec<Attribute>,
pub node: TraitItemKind,
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum TraitItemKind {
Const(Ty, Option<Expr>),
Method(MethodSig, Option<Block>),
Type(Vec<TyParamBound>, Option<Ty>),
Macro(Mac),
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum ImplPolarity {
/// `impl Trait for Type`
Positive,
/// `impl !Trait for Type`
Negative,
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct ImplItem {
pub ident: Ident,
pub vis: Visibility,
pub defaultness: Defaultness,
pub attrs: Vec<Attribute>,
pub node: ImplItemKind,
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum ImplItemKind {
Const(Ty, Expr),
Method(MethodSig, Block),
Type(Ty),
Macro(Mac),
}
/// Represents a method's signature in a trait declaration,
/// or in an implementation.
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct MethodSig {
pub unsafety: Unsafety,
pub constness: Constness,
pub abi: Option<Abi>,
pub decl: FnDecl,
pub generics: Generics,
}
/// Header (not the body) of a function declaration.
///
/// E.g. `fn foo(bar: baz)`
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct FnDecl {
pub inputs: Vec<FnArg>,
pub output: FunctionRetTy,
pub variadic: bool,
}
/// An argument in a function header.
///
/// E.g. `bar: usize` as in `fn foo(bar: usize)`
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum FnArg {
SelfRef(Option<Lifetime>, Mutability),
SelfValue(Mutability),
Captured(Pat, Ty),
Ignored(Ty),
}
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
use {Block, DelimToken, FunctionRetTy, Generics, Ident, Mac, Path, TokenTree, VariantData,
Visibility};
use attr::parsing::{inner_attr, outer_attr};
use data::parsing::{struct_like_body, visibility};
use expr::parsing::{expr, pat, within_block};
use generics::parsing::{generics, lifetime, ty_param_bound, where_clause};
use ident::parsing::ident;
use mac::parsing::delimited;
use derive::{Body, DeriveInput};
use derive::parsing::derive_input;
use ty::parsing::{abi, mutability, path, ty, unsafety};
named!(pub item -> Item, alt!(
item_extern_crate
|
item_use
|
item_static
|
item_const
|
item_fn
|
item_mod
|
item_foreign_mod
|
item_ty
|
item_struct_or_enum
|
item_union
|
item_trait
|
item_default_impl
|
item_impl
|
item_mac
));
named!(pub items -> Vec<Item>, many0!(item));
named!(item_mac -> Item, do_parse!(
attrs: many0!(outer_attr) >>
what: path >>
punct!("!") >>
name: option!(ident) >>
body: delimited >>
cond!(match body.delim {
DelimToken::Paren | DelimToken::Bracket => true,
DelimToken::Brace => false,
}, punct!(";")) >>
(Item {
ident: name.unwrap_or_else(|| Ident::new("")),
vis: Visibility::Inherited,
attrs: attrs,
node: ItemKind::Mac(Mac {
path: what,
tts: vec![TokenTree::Delimited(body)],
}),
})
));
named!(item_extern_crate -> Item, do_parse!(
attrs: many0!(outer_attr) >>
vis: visibility >>
keyword!("extern") >>
keyword!("crate") >>
id: ident >>
rename: option!(preceded!(
keyword!("as"),
ident
)) >>
punct!(";") >>
({
let (name, original_name) = match rename {
Some(rename) => (rename, Some(id)),
None => (id, None),
};
Item {
ident: name,
vis: vis,
attrs: attrs,
node: ItemKind::ExternCrate(original_name),
}
})
));
named!(item_use -> Item, do_parse!(
attrs: many0!(outer_attr) >>
vis: visibility >>
keyword!("use") >>
what: view_path >>
punct!(";") >>
(Item {
ident: "".into(),
vis: vis,
attrs: attrs,
node: ItemKind::Use(Box::new(what)),
})
));
named!(view_path -> ViewPath, alt!(
view_path_glob
|
view_path_list
|
view_path_list_root
|
view_path_simple // must be last
));
named!(view_path_simple -> ViewPath, do_parse!(
path: path >>
rename: option!(preceded!(keyword!("as"), ident)) >>
(ViewPath::Simple(path, rename))
));
named!(view_path_glob -> ViewPath, do_parse!(
path: path >>
punct!("::") >>
punct!("*") >>
(ViewPath::Glob(path))
));
named!(view_path_list -> ViewPath, do_parse!(
path: path >>
punct!("::") >>
punct!("{") >>
items: terminated_list!(punct!(","), path_list_item) >>
punct!("}") >>
(ViewPath::List(path, items))
));
named!(view_path_list_root -> ViewPath, do_parse!(
global: option!(punct!("::")) >>
punct!("{") >>
items: terminated_list!(punct!(","), path_list_item) >>
punct!("}") >>
(ViewPath::List(Path {
global: global.is_some(),
segments: Vec::new(),
}, items))
));
named!(path_list_item -> PathListItem, do_parse!(
name: alt!(
ident
|
map!(keyword!("self"), Into::into)
) >>
rename: option!(preceded!(keyword!("as"), ident)) >>
(PathListItem {
name: name,
rename: rename,
})
));
named!(item_static -> Item, do_parse!(
attrs: many0!(outer_attr) >>
vis: visibility >>
keyword!("static") >>
mutability: mutability >>
id: ident >>
punct!(":") >>
ty: ty >>
punct!("=") >>
value: expr >>
punct!(";") >>
(Item {
ident: id,
vis: vis,
attrs: attrs,
node: ItemKind::Static(Box::new(ty), mutability, Box::new(value)),
})
));
named!(item_const -> Item, do_parse!(
attrs: many0!(outer_attr) >>
vis: visibility >>
keyword!("const") >>
id: ident >>
punct!(":") >>
ty: ty >>
punct!("=") >>
value: expr >>
punct!(";") >>
(Item {
ident: id,
vis: vis,
attrs: attrs,
node: ItemKind::Const(Box::new(ty), Box::new(value)),
})
));
named!(item_fn -> Item, do_parse!(
outer_attrs: many0!(outer_attr) >>
vis: visibility >>
constness: constness >>
unsafety: unsafety >>
abi: option!(abi) >>
keyword!("fn") >>
name: ident >>
generics: generics >>
punct!("(") >>
inputs: terminated_list!(punct!(","), fn_arg) >>
punct!(")") >>
ret: option!(preceded!(punct!("->"), ty)) >>
where_clause: where_clause >>
punct!("{") >>
inner_attrs: many0!(inner_attr) >>
stmts: within_block >>
punct!("}") >>
(Item {
ident: name,
vis: vis,
attrs: {
let mut attrs = outer_attrs;
attrs.extend(inner_attrs);
attrs
},
node: ItemKind::Fn(
Box::new(FnDecl {
inputs: inputs,
output: ret.map(FunctionRetTy::Ty).unwrap_or(FunctionRetTy::Default),
variadic: false,
}),
unsafety,
constness,
abi,
Generics {
where_clause: where_clause,
.. generics
},
Box::new(Block {
stmts: stmts,
}),
),
})
));
named!(fn_arg -> FnArg, alt!(
do_parse!(
punct!("&") >>
lt: option!(lifetime) >>
mutability: mutability >>
keyword!("self") >>
not!(punct!(":")) >>
(FnArg::SelfRef(lt, mutability))
)
|
do_parse!(
mutability: mutability >>
keyword!("self") >>
not!(punct!(":")) >>
(FnArg::SelfValue(mutability))
)
|
do_parse!(
pat: pat >>
punct!(":") >>
ty: ty >>
(FnArg::Captured(pat, ty))
)
|
ty => { FnArg::Ignored }
));
named!(item_mod -> Item, do_parse!(
outer_attrs: many0!(outer_attr) >>
vis: visibility >>
keyword!("mod") >>
id: ident >>
content: alt!(
punct!(";") => { |_| None }
|
delimited!(
punct!("{"),
tuple!(
many0!(inner_attr),
items
),
punct!("}")
) => { Some }
) >>
(match content {
Some((inner_attrs, items)) => Item {
ident: id,
vis: vis,
attrs: {
let mut attrs = outer_attrs;
attrs.extend(inner_attrs);
attrs
},
node: ItemKind::Mod(Some(items)),
},
None => Item {
ident: id,
vis: vis,
attrs: outer_attrs,
node: ItemKind::Mod(None),
},
})
));
named!(item_foreign_mod -> Item, do_parse!(
attrs: many0!(outer_attr) >>
abi: abi >>
punct!("{") >>
items: many0!(foreign_item) >>
punct!("}") >>
(Item {
ident: "".into(),
vis: Visibility::Inherited,
attrs: attrs,
node: ItemKind::ForeignMod(ForeignMod {
abi: abi,
items: items,
}),
})
));
named!(foreign_item -> ForeignItem, alt!(
foreign_fn
|
foreign_static
));
named!(foreign_fn -> ForeignItem, do_parse!(
attrs: many0!(outer_attr) >>
vis: visibility >>
keyword!("fn") >>
name: ident >>
generics: generics >>
punct!("(") >>
inputs: separated_list!(punct!(","), fn_arg) >>
trailing_comma: option!(punct!(",")) >>
variadic: option!(cond_reduce!(trailing_comma.is_some(), punct!("..."))) >>
punct!(")") >>
ret: option!(preceded!(punct!("->"), ty)) >>
where_clause: where_clause >>
punct!(";") >>
(ForeignItem {
ident: name,
attrs: attrs,
node: ForeignItemKind::Fn(
Box::new(FnDecl {
inputs: inputs,
output: ret.map(FunctionRetTy::Ty).unwrap_or(FunctionRetTy::Default),
variadic: variadic.is_some(),
}),
Generics {
where_clause: where_clause,
.. generics
},
),
vis: vis,
})
));
named!(foreign_static -> ForeignItem, do_parse!(
attrs: many0!(outer_attr) >>
vis: visibility >>
keyword!("static") >>
mutability: mutability >>
id: ident >>
punct!(":") >>
ty: ty >>
punct!(";") >>
(ForeignItem {
ident: id,
attrs: attrs,
node: ForeignItemKind::Static(Box::new(ty), mutability),
vis: vis,
})
));
named!(item_ty -> Item, do_parse!(
attrs: many0!(outer_attr) >>
vis: visibility >>
keyword!("type") >>
id: ident >>
generics: generics >>
where_clause: where_clause >>
punct!("=") >>
ty: ty >>
punct!(";") >>
(Item {
ident: id,
vis: vis,
attrs: attrs,
node: ItemKind::Ty(
Box::new(ty),
Generics {
where_clause: where_clause,
..generics
},
),
})
));
named!(item_struct_or_enum -> Item, map!(
derive_input,
|def: DeriveInput| Item {
ident: def.ident,
vis: def.vis,
attrs: def.attrs,
node: match def.body {
Body::Enum(variants) => {
ItemKind::Enum(variants, def.generics)
}
Body::Struct(variant_data) => {
ItemKind::Struct(variant_data, def.generics)
}
}
}
));
named!(item_union -> Item, do_parse!(
attrs: many0!(outer_attr) >>
vis: visibility >>
keyword!("union") >>
id: ident >>
generics: generics >>
where_clause: where_clause >>
fields: struct_like_body >>
(Item {
ident: id,
vis: vis,
attrs: attrs,
node: ItemKind::Union(
VariantData::Struct(fields),
Generics {
where_clause: where_clause,
.. generics
},
),
})
));
named!(item_trait -> Item, do_parse!(
attrs: many0!(outer_attr) >>
vis: visibility >>
unsafety: unsafety >>
keyword!("trait") >>
id: ident >>
generics: generics >>
bounds: opt_vec!(preceded!(
punct!(":"),
separated_nonempty_list!(punct!("+"), ty_param_bound)
)) >>
where_clause: where_clause >>
punct!("{") >>
body: many0!(trait_item) >>
punct!("}") >>
(Item {
ident: id,
vis: vis,
attrs: attrs,
node: ItemKind::Trait(
unsafety,
Generics {
where_clause: where_clause,
.. generics
},
bounds,
body,
),
})
));
named!(item_default_impl -> Item, do_parse!(
attrs: many0!(outer_attr) >>
unsafety: unsafety >>
keyword!("impl") >>
path: path >>
keyword!("for") >>
punct!("..") >>
punct!("{") >>
punct!("}") >>
(Item {
ident: "".into(),
vis: Visibility::Inherited,
attrs: attrs,
node: ItemKind::DefaultImpl(unsafety, path),
})
));
named!(trait_item -> TraitItem, alt!(
trait_item_const
|
trait_item_method
|
trait_item_type
|
trait_item_mac
));
named!(trait_item_const -> TraitItem, do_parse!(
attrs: many0!(outer_attr) >>
keyword!("const") >>
id: ident >>
punct!(":") >>
ty: ty >>
value: option!(preceded!(punct!("="), expr)) >>
punct!(";") >>
(TraitItem {
ident: id,
attrs: attrs,
node: TraitItemKind::Const(ty, value),
})
));
named!(trait_item_method -> TraitItem, do_parse!(
outer_attrs: many0!(outer_attr) >>
constness: constness >>
unsafety: unsafety >>
abi: option!(abi) >>
keyword!("fn") >>
name: ident >>
generics: generics >>
punct!("(") >>
inputs: terminated_list!(punct!(","), fn_arg) >>
punct!(")") >>
ret: option!(preceded!(punct!("->"), ty)) >>
where_clause: where_clause >>
body: option!(delimited!(
punct!("{"),
tuple!(many0!(inner_attr), within_block),
punct!("}")
)) >>
cond!(body.is_none(), punct!(";")) >>
({
let (inner_attrs, stmts) = match body {
Some((inner_attrs, stmts)) => (inner_attrs, Some(stmts)),
None => (Vec::new(), None),
};
TraitItem {
ident: name,
attrs: {
let mut attrs = outer_attrs;
attrs.extend(inner_attrs);
attrs
},
node: TraitItemKind::Method(
MethodSig {
unsafety: unsafety,
constness: constness,
abi: abi,
decl: FnDecl {
inputs: inputs,
output: ret.map(FunctionRetTy::Ty).unwrap_or(FunctionRetTy::Default),
variadic: false,
},
generics: Generics {
where_clause: where_clause,
.. generics
},
},
stmts.map(|stmts| Block { stmts: stmts }),
),
}
})
));
named!(trait_item_type -> TraitItem, do_parse!(
attrs: many0!(outer_attr) >>
keyword!("type") >>
id: ident >>
bounds: opt_vec!(preceded!(
punct!(":"),
separated_nonempty_list!(punct!("+"), ty_param_bound)
)) >>
default: option!(preceded!(punct!("="), ty)) >>
punct!(";") >>
(TraitItem {
ident: id,
attrs: attrs,
node: TraitItemKind::Type(bounds, default),
})
));
named!(trait_item_mac -> TraitItem, do_parse!(
attrs: many0!(outer_attr) >>
what: path >>
punct!("!") >>
body: delimited >>
cond!(match body.delim {
DelimToken::Paren | DelimToken::Bracket => true,
DelimToken::Brace => false,
}, punct!(";")) >>
(TraitItem {
ident: Ident::new(""),
attrs: attrs,
node: TraitItemKind::Macro(Mac {
path: what,
tts: vec![TokenTree::Delimited(body)],
}),
})
));
named!(item_impl -> Item, do_parse!(
attrs: many0!(outer_attr) >>
unsafety: unsafety >>
keyword!("impl") >>
generics: generics >>
polarity_path: alt!(
do_parse!(
polarity: impl_polarity >>
path: path >>
keyword!("for") >>
(polarity, Some(path))
)
|
epsilon!() => { |_| (ImplPolarity::Positive, None) }
) >>
self_ty: ty >>
where_clause: where_clause >>
punct!("{") >>
body: many0!(impl_item) >>
punct!("}") >>
(Item {
ident: "".into(),
vis: Visibility::Inherited,
attrs: attrs,
node: ItemKind::Impl(
unsafety,
polarity_path.0,
Generics {
where_clause: where_clause,
.. generics
},
polarity_path.1,
Box::new(self_ty),
body,
),
})
));
named!(impl_item -> ImplItem, alt!(
impl_item_const
|
impl_item_method
|
impl_item_type
|
impl_item_macro
));
named!(impl_item_const -> ImplItem, do_parse!(
attrs: many0!(outer_attr) >>
vis: visibility >>
defaultness: defaultness >>
keyword!("const") >>
id: ident >>
punct!(":") >>
ty: ty >>
punct!("=") >>
value: expr >>
punct!(";") >>
(ImplItem {
ident: id,
vis: vis,
defaultness: defaultness,
attrs: attrs,
node: ImplItemKind::Const(ty, value),
})
));
named!(impl_item_method -> ImplItem, do_parse!(
outer_attrs: many0!(outer_attr) >>
vis: visibility >>
defaultness: defaultness >>
constness: constness >>
unsafety: unsafety >>
abi: option!(abi) >>
keyword!("fn") >>
name: ident >>
generics: generics >>
punct!("(") >>
inputs: terminated_list!(punct!(","), fn_arg) >>
punct!(")") >>
ret: option!(preceded!(punct!("->"), ty)) >>
where_clause: where_clause >>
punct!("{") >>
inner_attrs: many0!(inner_attr) >>
stmts: within_block >>
punct!("}") >>
(ImplItem {
ident: name,
vis: vis,
defaultness: defaultness,
attrs: {
let mut attrs = outer_attrs;
attrs.extend(inner_attrs);
attrs
},
node: ImplItemKind::Method(
MethodSig {
unsafety: unsafety,
constness: constness,
abi: abi,
decl: FnDecl {
inputs: inputs,
output: ret.map(FunctionRetTy::Ty).unwrap_or(FunctionRetTy::Default),
variadic: false,
},
generics: Generics {
where_clause: where_clause,
.. generics
},
},
Block {
stmts: stmts,
},
),
})
));
named!(impl_item_type -> ImplItem, do_parse!(
attrs: many0!(outer_attr) >>
vis: visibility >>
defaultness: defaultness >>
keyword!("type") >>
id: ident >>
punct!("=") >>
ty: ty >>
punct!(";") >>
(ImplItem {
ident: id,
vis: vis,
defaultness: defaultness,
attrs: attrs,
node: ImplItemKind::Type(ty),
})
));
named!(impl_item_macro -> ImplItem, do_parse!(
attrs: many0!(outer_attr) >>
what: path >>
punct!("!") >>
body: delimited >>
cond!(match body.delim {
DelimToken::Paren | DelimToken::Bracket => true,
DelimToken::Brace => false,
}, punct!(";")) >>
(ImplItem {
ident: Ident::new(""),
vis: Visibility::Inherited,
defaultness: Defaultness::Final,
attrs: attrs,
node: ImplItemKind::Macro(Mac {
path: what,
tts: vec![TokenTree::Delimited(body)],
}),
})
));
named!(impl_polarity -> ImplPolarity, alt!(
punct!("!") => { |_| ImplPolarity::Negative }
|
epsilon!() => { |_| ImplPolarity::Positive }
));
named!(constness -> Constness, alt!(
keyword!("const") => { |_| Constness::Const }
|
epsilon!() => { |_| Constness::NotConst }
));
named!(defaultness -> Defaultness, alt!(
keyword!("default") => { |_| Defaultness::Default }
|
epsilon!() => { |_| Defaultness::Final }
));
}
#[cfg(feature = "printing")]
mod printing {
use super::*;
use {Delimited, DelimToken, FunctionRetTy, TokenTree};
use attr::FilterAttrs;
use data::VariantData;
use quote::{Tokens, ToTokens};
impl ToTokens for Item {
fn to_tokens(&self, tokens: &mut Tokens) {
tokens.append_all(self.attrs.outer());
match self.node {
ItemKind::ExternCrate(ref original) => {
self.vis.to_tokens(tokens);
tokens.append("extern");
tokens.append("crate");
if let Some(ref original) = *original {
original.to_tokens(tokens);
tokens.append("as");
}
self.ident.to_tokens(tokens);
tokens.append(";");
}
ItemKind::Use(ref view_path) => {
self.vis.to_tokens(tokens);
tokens.append("use");
view_path.to_tokens(tokens);
tokens.append(";");
}
ItemKind::Static(ref ty, ref mutability, ref expr) => {
self.vis.to_tokens(tokens);
tokens.append("static");
mutability.to_tokens(tokens);
self.ident.to_tokens(tokens);
tokens.append(":");
ty.to_tokens(tokens);
tokens.append("=");
expr.to_tokens(tokens);
tokens.append(";");
}
ItemKind::Const(ref ty, ref expr) => {
self.vis.to_tokens(tokens);
tokens.append("const");
self.ident.to_tokens(tokens);
tokens.append(":");
ty.to_tokens(tokens);
tokens.append("=");
expr.to_tokens(tokens);
tokens.append(";");
}
ItemKind::Fn(ref decl, unsafety, constness, ref abi, ref generics, ref block) => {
self.vis.to_tokens(tokens);
constness.to_tokens(tokens);
unsafety.to_tokens(tokens);
abi.to_tokens(tokens);
tokens.append("fn");
self.ident.to_tokens(tokens);
generics.to_tokens(tokens);
tokens.append("(");
tokens.append_separated(&decl.inputs, ",");
tokens.append(")");
if let FunctionRetTy::Ty(ref ty) = decl.output {
tokens.append("->");
ty.to_tokens(tokens);
}
generics.where_clause.to_tokens(tokens);
tokens.append("{");
tokens.append_all(self.attrs.inner());
tokens.append_all(&block.stmts);
tokens.append("}");
}
ItemKind::Mod(ref items) => {
self.vis.to_tokens(tokens);
tokens.append("mod");
self.ident.to_tokens(tokens);
match *items {
Some(ref items) => {
tokens.append("{");
tokens.append_all(self.attrs.inner());
tokens.append_all(items);
tokens.append("}");
}
None => tokens.append(";"),
}
}
ItemKind::ForeignMod(ref foreign_mod) => {
self.vis.to_tokens(tokens);
foreign_mod.abi.to_tokens(tokens);
tokens.append("{");
tokens.append_all(&foreign_mod.items);
tokens.append("}");
}
ItemKind::Ty(ref ty, ref generics) => {
self.vis.to_tokens(tokens);
tokens.append("type");
self.ident.to_tokens(tokens);
generics.to_tokens(tokens);
generics.where_clause.to_tokens(tokens);
tokens.append("=");
ty.to_tokens(tokens);
tokens.append(";");
}
ItemKind::Enum(ref variants, ref generics) => {
self.vis.to_tokens(tokens);
tokens.append("enum");
self.ident.to_tokens(tokens);
generics.to_tokens(tokens);
generics.where_clause.to_tokens(tokens);
tokens.append("{");
for variant in variants {
variant.to_tokens(tokens);
tokens.append(",");
}
tokens.append("}");
}
ItemKind::Struct(ref variant_data, ref generics) => {
self.vis.to_tokens(tokens);
tokens.append("struct");
self.ident.to_tokens(tokens);
generics.to_tokens(tokens);
match *variant_data {
VariantData::Struct(_) => {
generics.where_clause.to_tokens(tokens);
variant_data.to_tokens(tokens);
// no semicolon
}
VariantData::Tuple(_) => {
variant_data.to_tokens(tokens);
generics.where_clause.to_tokens(tokens);
tokens.append(";");
}
VariantData::Unit => {
generics.where_clause.to_tokens(tokens);
tokens.append(";");
}
}
}
ItemKind::Union(ref variant_data, ref generics) => {
self.vis.to_tokens(tokens);
tokens.append("union");
self.ident.to_tokens(tokens);
generics.to_tokens(tokens);
generics.where_clause.to_tokens(tokens);
variant_data.to_tokens(tokens);
}
ItemKind::Trait(unsafety, ref generics, ref bound, ref items) => {
self.vis.to_tokens(tokens);
unsafety.to_tokens(tokens);
tokens.append("trait");
self.ident.to_tokens(tokens);
generics.to_tokens(tokens);
if !bound.is_empty() {
tokens.append(":");
tokens.append_separated(bound, "+");
}
generics.where_clause.to_tokens(tokens);
tokens.append("{");
tokens.append_all(items);
tokens.append("}");
}
ItemKind::DefaultImpl(unsafety, ref path) => {
unsafety.to_tokens(tokens);
tokens.append("impl");
path.to_tokens(tokens);
tokens.append("for");
tokens.append("..");
tokens.append("{");
tokens.append("}");
}
ItemKind::Impl(unsafety, polarity, ref generics, ref path, ref ty, ref items) => {
unsafety.to_tokens(tokens);
tokens.append("impl");
generics.to_tokens(tokens);
if let Some(ref path) = *path {
polarity.to_tokens(tokens);
path.to_tokens(tokens);
tokens.append("for");
}
ty.to_tokens(tokens);
generics.where_clause.to_tokens(tokens);
tokens.append("{");
tokens.append_all(items);
tokens.append("}");
}
ItemKind::Mac(ref mac) => {
mac.path.to_tokens(tokens);
tokens.append("!");
self.ident.to_tokens(tokens);
for tt in &mac.tts {
tt.to_tokens(tokens);
}
match mac.tts.last() {
Some(&TokenTree::Delimited(Delimited { delim: DelimToken::Brace, .. })) => {
// no semicolon
}
_ => tokens.append(";"),
}
}
}
}
}
impl ToTokens for ViewPath {
fn to_tokens(&self, tokens: &mut Tokens) {
match *self {
ViewPath::Simple(ref path, ref rename) => {
path.to_tokens(tokens);
if let Some(ref rename) = *rename {
tokens.append("as");
rename.to_tokens(tokens);
}
}
ViewPath::Glob(ref path) => {
path.to_tokens(tokens);
tokens.append("::");
tokens.append("*");
}
ViewPath::List(ref path, ref items) => {
path.to_tokens(tokens);
if path.global || !path.segments.is_empty() {
tokens.append("::");
}
tokens.append("{");
tokens.append_separated(items, ",");
tokens.append("}");
}
}
}
}
impl ToTokens for PathListItem {
fn to_tokens(&self, tokens: &mut Tokens) {
self.name.to_tokens(tokens);
if let Some(ref rename) = self.rename {
tokens.append("as");
rename.to_tokens(tokens);
}
}
}
impl ToTokens for TraitItem {
fn to_tokens(&self, tokens: &mut Tokens) {
tokens.append_all(self.attrs.outer());
match self.node {
TraitItemKind::Const(ref ty, ref expr) => {
tokens.append("const");
self.ident.to_tokens(tokens);
tokens.append(":");
ty.to_tokens(tokens);
if let Some(ref expr) = *expr {
tokens.append("=");
expr.to_tokens(tokens);
}
tokens.append(";");
}
TraitItemKind::Method(ref sig, ref block) => {
sig.constness.to_tokens(tokens);
sig.unsafety.to_tokens(tokens);
sig.abi.to_tokens(tokens);
tokens.append("fn");
self.ident.to_tokens(tokens);
sig.generics.to_tokens(tokens);
tokens.append("(");
tokens.append_separated(&sig.decl.inputs, ",");
tokens.append(")");
if let FunctionRetTy::Ty(ref ty) = sig.decl.output {
tokens.append("->");
ty.to_tokens(tokens);
}
sig.generics.where_clause.to_tokens(tokens);
match *block {
Some(ref block) => {
tokens.append("{");
tokens.append_all(self.attrs.inner());
tokens.append_all(&block.stmts);
tokens.append("}");
}
None => tokens.append(";"),
}
}
TraitItemKind::Type(ref bound, ref default) => {
tokens.append("type");
self.ident.to_tokens(tokens);
if !bound.is_empty() {
tokens.append(":");
tokens.append_separated(bound, "+");
}
if let Some(ref default) = *default {
tokens.append("=");
default.to_tokens(tokens);
}
tokens.append(";");
}
TraitItemKind::Macro(ref mac) => {
mac.to_tokens(tokens);
match mac.tts.last() {
Some(&TokenTree::Delimited(Delimited { delim: DelimToken::Brace, .. })) => {
// no semicolon
}
_ => tokens.append(";"),
}
}
}
}
}
impl ToTokens for ImplItem {
fn to_tokens(&self, tokens: &mut Tokens) {
tokens.append_all(self.attrs.outer());
match self.node {
ImplItemKind::Const(ref ty, ref expr) => {
self.vis.to_tokens(tokens);
self.defaultness.to_tokens(tokens);
tokens.append("const");
self.ident.to_tokens(tokens);
tokens.append(":");
ty.to_tokens(tokens);
tokens.append("=");
expr.to_tokens(tokens);
tokens.append(";");
}
ImplItemKind::Method(ref sig, ref block) => {
self.vis.to_tokens(tokens);
self.defaultness.to_tokens(tokens);
sig.constness.to_tokens(tokens);
sig.unsafety.to_tokens(tokens);
sig.abi.to_tokens(tokens);
tokens.append("fn");
self.ident.to_tokens(tokens);
sig.generics.to_tokens(tokens);
tokens.append("(");
tokens.append_separated(&sig.decl.inputs, ",");
tokens.append(")");
if let FunctionRetTy::Ty(ref ty) = sig.decl.output {
tokens.append("->");
ty.to_tokens(tokens);
}
sig.generics.where_clause.to_tokens(tokens);
tokens.append("{");
tokens.append_all(self.attrs.inner());
tokens.append_all(&block.stmts);
tokens.append("}");
}
ImplItemKind::Type(ref ty) => {
self.vis.to_tokens(tokens);
self.defaultness.to_tokens(tokens);
tokens.append("type");
self.ident.to_tokens(tokens);
tokens.append("=");
ty.to_tokens(tokens);
tokens.append(";");
}
ImplItemKind::Macro(ref mac) => {
mac.to_tokens(tokens);
match mac.tts.last() {
Some(&TokenTree::Delimited(Delimited { delim: DelimToken::Brace, .. })) => {
// no semicolon
}
_ => tokens.append(";"),
}
}
}
}
}
impl ToTokens for ForeignItem {
fn to_tokens(&self, tokens: &mut Tokens) {
tokens.append_all(self.attrs.outer());
match self.node {
ForeignItemKind::Fn(ref decl, ref generics) => {
self.vis.to_tokens(tokens);
tokens.append("fn");
self.ident.to_tokens(tokens);
generics.to_tokens(tokens);
tokens.append("(");
tokens.append_separated(&decl.inputs, ",");
if decl.variadic {
if !decl.inputs.is_empty() {
tokens.append(",");
}
tokens.append("...");
}
tokens.append(")");
if let FunctionRetTy::Ty(ref ty) = decl.output {
tokens.append("->");
ty.to_tokens(tokens);
}
generics.where_clause.to_tokens(tokens);
tokens.append(";");
}
ForeignItemKind::Static(ref ty, mutability) => {
self.vis.to_tokens(tokens);
tokens.append("static");
mutability.to_tokens(tokens);
self.ident.to_tokens(tokens);
tokens.append(":");
ty.to_tokens(tokens);
tokens.append(";");
}
}
}
}
impl ToTokens for FnArg {
fn to_tokens(&self, tokens: &mut Tokens) {
match *self {
FnArg::SelfRef(ref lifetime, mutability) => {
tokens.append("&");
lifetime.to_tokens(tokens);
mutability.to_tokens(tokens);
tokens.append("self");
}
FnArg::SelfValue(mutability) => {
mutability.to_tokens(tokens);
tokens.append("self");
}
FnArg::Captured(ref pat, ref ty) => {
pat.to_tokens(tokens);
tokens.append(":");
ty.to_tokens(tokens);
}
FnArg::Ignored(ref ty) => {
ty.to_tokens(tokens);
}
}
}
}
impl ToTokens for Constness {
fn to_tokens(&self, tokens: &mut Tokens) {
match *self {
Constness::Const => tokens.append("const"),
Constness::NotConst => {
// nothing
}
}
}
}
impl ToTokens for Defaultness {
fn to_tokens(&self, tokens: &mut Tokens) {
match *self {
Defaultness::Default => tokens.append("default"),
Defaultness::Final => {
// nothing
}
}
}
}
impl ToTokens for ImplPolarity {
fn to_tokens(&self, tokens: &mut Tokens) {
match *self {
ImplPolarity::Negative => tokens.append("!"),
ImplPolarity::Positive => {
// nothing
}
}
}
}
}