| 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 |
| } |
| } |
| } |
| } |
| } |