3493 lines
119 KiB
Rust
3493 lines
119 KiB
Rust
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
|
|
use crate::attr::Attribute;
|
|
use crate::data::{Fields, FieldsNamed, Variant};
|
|
use crate::derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput};
|
|
use crate::expr::Expr;
|
|
use crate::generics::{Generics, TypeParamBound};
|
|
use crate::ident::Ident;
|
|
use crate::lifetime::Lifetime;
|
|
use crate::mac::Macro;
|
|
use crate::pat::{Pat, PatType};
|
|
use crate::path::Path;
|
|
use crate::punctuated::Punctuated;
|
|
use crate::restriction::Visibility;
|
|
use crate::stmt::Block;
|
|
use crate::token;
|
|
use crate::ty::{Abi, ReturnType, Type};
|
|
use proc_macro2::TokenStream;
|
|
#[cfg(feature = "parsing")]
|
|
use std::mem;
|
|
|
|
ast_enum_of_structs! {
|
|
/// Things that can appear directly inside of a module or scope.
|
|
///
|
|
/// # 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 = "full")))]
|
|
#[non_exhaustive]
|
|
pub enum Item {
|
|
/// A constant item: `const MAX: u16 = 65535`.
|
|
Const(ItemConst),
|
|
|
|
/// An enum definition: `enum Foo<A, B> { A(A), B(B) }`.
|
|
Enum(ItemEnum),
|
|
|
|
/// An `extern crate` item: `extern crate serde`.
|
|
ExternCrate(ItemExternCrate),
|
|
|
|
/// A free-standing function: `fn process(n: usize) -> Result<()> { ...
|
|
/// }`.
|
|
Fn(ItemFn),
|
|
|
|
/// A block of foreign items: `extern "C" { ... }`.
|
|
ForeignMod(ItemForeignMod),
|
|
|
|
/// An impl block providing trait or associated items: `impl<A> Trait
|
|
/// for Data<A> { ... }`.
|
|
Impl(ItemImpl),
|
|
|
|
/// A macro invocation, which includes `macro_rules!` definitions.
|
|
Macro(ItemMacro),
|
|
|
|
/// A module or module declaration: `mod m` or `mod m { ... }`.
|
|
Mod(ItemMod),
|
|
|
|
/// A static item: `static BIKE: Shed = Shed(42)`.
|
|
Static(ItemStatic),
|
|
|
|
/// A struct definition: `struct Foo<A> { x: A }`.
|
|
Struct(ItemStruct),
|
|
|
|
/// A trait definition: `pub trait Iterator { ... }`.
|
|
Trait(ItemTrait),
|
|
|
|
/// A trait alias: `pub trait SharableIterator = Iterator + Sync`.
|
|
TraitAlias(ItemTraitAlias),
|
|
|
|
/// A type alias: `type Result<T> = std::result::Result<T, MyError>`.
|
|
Type(ItemType),
|
|
|
|
/// A union definition: `union Foo<A, B> { x: A, y: B }`.
|
|
Union(ItemUnion),
|
|
|
|
/// A use declaration: `use std::collections::HashMap`.
|
|
Use(ItemUse),
|
|
|
|
/// Tokens forming an item not interpreted by Syn.
|
|
Verbatim(TokenStream),
|
|
|
|
// For testing exhaustiveness in downstream code, use the following idiom:
|
|
//
|
|
// match item {
|
|
// #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
|
|
//
|
|
// Item::Const(item) => {...}
|
|
// Item::Enum(item) => {...}
|
|
// ...
|
|
// Item::Verbatim(item) => {...}
|
|
//
|
|
// _ => { /* some sane fallback */ }
|
|
// }
|
|
//
|
|
// This way we fail your tests but don't break your library when adding
|
|
// a variant. You will be notified by a test failure when a variant is
|
|
// added, so that you can add code to handle it, but your library will
|
|
// continue to compile and work for downstream users in the interim.
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// A constant item: `const MAX: u16 = 65535`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ItemConst {
|
|
pub attrs: Vec<Attribute>,
|
|
pub vis: Visibility,
|
|
pub const_token: Token![const],
|
|
pub ident: Ident,
|
|
pub generics: Generics,
|
|
pub colon_token: Token![:],
|
|
pub ty: Box<Type>,
|
|
pub eq_token: Token![=],
|
|
pub expr: Box<Expr>,
|
|
pub semi_token: Token![;],
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// An enum definition: `enum Foo<A, B> { A(A), B(B) }`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ItemEnum {
|
|
pub attrs: Vec<Attribute>,
|
|
pub vis: Visibility,
|
|
pub enum_token: Token![enum],
|
|
pub ident: Ident,
|
|
pub generics: Generics,
|
|
pub brace_token: token::Brace,
|
|
pub variants: Punctuated<Variant, Token![,]>,
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// An `extern crate` item: `extern crate serde`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ItemExternCrate {
|
|
pub attrs: Vec<Attribute>,
|
|
pub vis: Visibility,
|
|
pub extern_token: Token![extern],
|
|
pub crate_token: Token![crate],
|
|
pub ident: Ident,
|
|
pub rename: Option<(Token![as], Ident)>,
|
|
pub semi_token: Token![;],
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// A free-standing function: `fn process(n: usize) -> Result<()> { ... }`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ItemFn {
|
|
pub attrs: Vec<Attribute>,
|
|
pub vis: Visibility,
|
|
pub sig: Signature,
|
|
pub block: Box<Block>,
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// A block of foreign items: `extern "C" { ... }`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ItemForeignMod {
|
|
pub attrs: Vec<Attribute>,
|
|
pub unsafety: Option<Token![unsafe]>,
|
|
pub abi: Abi,
|
|
pub brace_token: token::Brace,
|
|
pub items: Vec<ForeignItem>,
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// An impl block providing trait or associated items: `impl<A> Trait
|
|
/// for Data<A> { ... }`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ItemImpl {
|
|
pub attrs: Vec<Attribute>,
|
|
pub defaultness: Option<Token![default]>,
|
|
pub unsafety: Option<Token![unsafe]>,
|
|
pub impl_token: Token![impl],
|
|
pub generics: Generics,
|
|
/// Trait this impl implements.
|
|
pub trait_: Option<(Option<Token![!]>, Path, Token![for])>,
|
|
/// The Self type of the impl.
|
|
pub self_ty: Box<Type>,
|
|
pub brace_token: token::Brace,
|
|
pub items: Vec<ImplItem>,
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// A macro invocation, which includes `macro_rules!` definitions.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ItemMacro {
|
|
pub attrs: Vec<Attribute>,
|
|
/// The `example` in `macro_rules! example { ... }`.
|
|
pub ident: Option<Ident>,
|
|
pub mac: Macro,
|
|
pub semi_token: Option<Token![;]>,
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// A module or module declaration: `mod m` or `mod m { ... }`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ItemMod {
|
|
pub attrs: Vec<Attribute>,
|
|
pub vis: Visibility,
|
|
pub unsafety: Option<Token![unsafe]>,
|
|
pub mod_token: Token![mod],
|
|
pub ident: Ident,
|
|
pub content: Option<(token::Brace, Vec<Item>)>,
|
|
pub semi: Option<Token![;]>,
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// A static item: `static BIKE: Shed = Shed(42)`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ItemStatic {
|
|
pub attrs: Vec<Attribute>,
|
|
pub vis: Visibility,
|
|
pub static_token: Token![static],
|
|
pub mutability: StaticMutability,
|
|
pub ident: Ident,
|
|
pub colon_token: Token![:],
|
|
pub ty: Box<Type>,
|
|
pub eq_token: Token![=],
|
|
pub expr: Box<Expr>,
|
|
pub semi_token: Token![;],
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// A struct definition: `struct Foo<A> { x: A }`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ItemStruct {
|
|
pub attrs: Vec<Attribute>,
|
|
pub vis: Visibility,
|
|
pub struct_token: Token![struct],
|
|
pub ident: Ident,
|
|
pub generics: Generics,
|
|
pub fields: Fields,
|
|
pub semi_token: Option<Token![;]>,
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// A trait definition: `pub trait Iterator { ... }`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ItemTrait {
|
|
pub attrs: Vec<Attribute>,
|
|
pub vis: Visibility,
|
|
pub unsafety: Option<Token![unsafe]>,
|
|
pub auto_token: Option<Token![auto]>,
|
|
pub restriction: Option<ImplRestriction>,
|
|
pub trait_token: Token![trait],
|
|
pub ident: Ident,
|
|
pub generics: Generics,
|
|
pub colon_token: Option<Token![:]>,
|
|
pub supertraits: Punctuated<TypeParamBound, Token![+]>,
|
|
pub brace_token: token::Brace,
|
|
pub items: Vec<TraitItem>,
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// A trait alias: `pub trait SharableIterator = Iterator + Sync`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ItemTraitAlias {
|
|
pub attrs: Vec<Attribute>,
|
|
pub vis: Visibility,
|
|
pub trait_token: Token![trait],
|
|
pub ident: Ident,
|
|
pub generics: Generics,
|
|
pub eq_token: Token![=],
|
|
pub bounds: Punctuated<TypeParamBound, Token![+]>,
|
|
pub semi_token: Token![;],
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// A type alias: `type Result<T> = std::result::Result<T, MyError>`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ItemType {
|
|
pub attrs: Vec<Attribute>,
|
|
pub vis: Visibility,
|
|
pub type_token: Token![type],
|
|
pub ident: Ident,
|
|
pub generics: Generics,
|
|
pub eq_token: Token![=],
|
|
pub ty: Box<Type>,
|
|
pub semi_token: Token![;],
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// A union definition: `union Foo<A, B> { x: A, y: B }`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ItemUnion {
|
|
pub attrs: Vec<Attribute>,
|
|
pub vis: Visibility,
|
|
pub union_token: Token![union],
|
|
pub ident: Ident,
|
|
pub generics: Generics,
|
|
pub fields: FieldsNamed,
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// A use declaration: `use std::collections::HashMap`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ItemUse {
|
|
pub attrs: Vec<Attribute>,
|
|
pub vis: Visibility,
|
|
pub use_token: Token![use],
|
|
pub leading_colon: Option<Token![::]>,
|
|
pub tree: UseTree,
|
|
pub semi_token: Token![;],
|
|
}
|
|
}
|
|
|
|
impl Item {
|
|
#[cfg(feature = "parsing")]
|
|
pub(crate) fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
|
|
match self {
|
|
Item::Const(ItemConst { attrs, .. })
|
|
| Item::Enum(ItemEnum { attrs, .. })
|
|
| Item::ExternCrate(ItemExternCrate { attrs, .. })
|
|
| Item::Fn(ItemFn { attrs, .. })
|
|
| Item::ForeignMod(ItemForeignMod { attrs, .. })
|
|
| Item::Impl(ItemImpl { attrs, .. })
|
|
| Item::Macro(ItemMacro { attrs, .. })
|
|
| Item::Mod(ItemMod { attrs, .. })
|
|
| Item::Static(ItemStatic { attrs, .. })
|
|
| Item::Struct(ItemStruct { attrs, .. })
|
|
| Item::Trait(ItemTrait { attrs, .. })
|
|
| Item::TraitAlias(ItemTraitAlias { attrs, .. })
|
|
| Item::Type(ItemType { attrs, .. })
|
|
| Item::Union(ItemUnion { attrs, .. })
|
|
| Item::Use(ItemUse { attrs, .. }) => mem::replace(attrs, new),
|
|
Item::Verbatim(_) => Vec::new(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<DeriveInput> for Item {
|
|
fn from(input: DeriveInput) -> Item {
|
|
match input.data {
|
|
Data::Struct(data) => Item::Struct(ItemStruct {
|
|
attrs: input.attrs,
|
|
vis: input.vis,
|
|
struct_token: data.struct_token,
|
|
ident: input.ident,
|
|
generics: input.generics,
|
|
fields: data.fields,
|
|
semi_token: data.semi_token,
|
|
}),
|
|
Data::Enum(data) => Item::Enum(ItemEnum {
|
|
attrs: input.attrs,
|
|
vis: input.vis,
|
|
enum_token: data.enum_token,
|
|
ident: input.ident,
|
|
generics: input.generics,
|
|
brace_token: data.brace_token,
|
|
variants: data.variants,
|
|
}),
|
|
Data::Union(data) => Item::Union(ItemUnion {
|
|
attrs: input.attrs,
|
|
vis: input.vis,
|
|
union_token: data.union_token,
|
|
ident: input.ident,
|
|
generics: input.generics,
|
|
fields: data.fields,
|
|
}),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<ItemStruct> for DeriveInput {
|
|
fn from(input: ItemStruct) -> DeriveInput {
|
|
DeriveInput {
|
|
attrs: input.attrs,
|
|
vis: input.vis,
|
|
ident: input.ident,
|
|
generics: input.generics,
|
|
data: Data::Struct(DataStruct {
|
|
struct_token: input.struct_token,
|
|
fields: input.fields,
|
|
semi_token: input.semi_token,
|
|
}),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<ItemEnum> for DeriveInput {
|
|
fn from(input: ItemEnum) -> DeriveInput {
|
|
DeriveInput {
|
|
attrs: input.attrs,
|
|
vis: input.vis,
|
|
ident: input.ident,
|
|
generics: input.generics,
|
|
data: Data::Enum(DataEnum {
|
|
enum_token: input.enum_token,
|
|
brace_token: input.brace_token,
|
|
variants: input.variants,
|
|
}),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<ItemUnion> for DeriveInput {
|
|
fn from(input: ItemUnion) -> DeriveInput {
|
|
DeriveInput {
|
|
attrs: input.attrs,
|
|
vis: input.vis,
|
|
ident: input.ident,
|
|
generics: input.generics,
|
|
data: Data::Union(DataUnion {
|
|
union_token: input.union_token,
|
|
fields: input.fields,
|
|
}),
|
|
}
|
|
}
|
|
}
|
|
|
|
ast_enum_of_structs! {
|
|
/// A suffix of an import tree in a `use` item: `Type as Renamed` or `*`.
|
|
///
|
|
/// # 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 = "full")))]
|
|
pub enum UseTree {
|
|
/// A path prefix of imports in a `use` item: `std::...`.
|
|
Path(UsePath),
|
|
|
|
/// An identifier imported by a `use` item: `HashMap`.
|
|
Name(UseName),
|
|
|
|
/// An renamed identifier imported by a `use` item: `HashMap as Map`.
|
|
Rename(UseRename),
|
|
|
|
/// A glob import in a `use` item: `*`.
|
|
Glob(UseGlob),
|
|
|
|
/// A braced group of imports in a `use` item: `{A, B, C}`.
|
|
Group(UseGroup),
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// A path prefix of imports in a `use` item: `std::...`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct UsePath {
|
|
pub ident: Ident,
|
|
pub colon2_token: Token![::],
|
|
pub tree: Box<UseTree>,
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// An identifier imported by a `use` item: `HashMap`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct UseName {
|
|
pub ident: Ident,
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// An renamed identifier imported by a `use` item: `HashMap as Map`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct UseRename {
|
|
pub ident: Ident,
|
|
pub as_token: Token![as],
|
|
pub rename: Ident,
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// A glob import in a `use` item: `*`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct UseGlob {
|
|
pub star_token: Token![*],
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// A braced group of imports in a `use` item: `{A, B, C}`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct UseGroup {
|
|
pub brace_token: token::Brace,
|
|
pub items: Punctuated<UseTree, Token![,]>,
|
|
}
|
|
}
|
|
|
|
ast_enum_of_structs! {
|
|
/// An item within an `extern` block.
|
|
///
|
|
/// # 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 = "full")))]
|
|
#[non_exhaustive]
|
|
pub enum ForeignItem {
|
|
/// A foreign function in an `extern` block.
|
|
Fn(ForeignItemFn),
|
|
|
|
/// A foreign static item in an `extern` block: `static ext: u8`.
|
|
Static(ForeignItemStatic),
|
|
|
|
/// A foreign type in an `extern` block: `type void`.
|
|
Type(ForeignItemType),
|
|
|
|
/// A macro invocation within an extern block.
|
|
Macro(ForeignItemMacro),
|
|
|
|
/// Tokens in an `extern` block not interpreted by Syn.
|
|
Verbatim(TokenStream),
|
|
|
|
// For testing exhaustiveness in downstream code, use the following idiom:
|
|
//
|
|
// match item {
|
|
// #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
|
|
//
|
|
// ForeignItem::Fn(item) => {...}
|
|
// ForeignItem::Static(item) => {...}
|
|
// ...
|
|
// ForeignItem::Verbatim(item) => {...}
|
|
//
|
|
// _ => { /* some sane fallback */ }
|
|
// }
|
|
//
|
|
// This way we fail your tests but don't break your library when adding
|
|
// a variant. You will be notified by a test failure when a variant is
|
|
// added, so that you can add code to handle it, but your library will
|
|
// continue to compile and work for downstream users in the interim.
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// A foreign function in an `extern` block.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ForeignItemFn {
|
|
pub attrs: Vec<Attribute>,
|
|
pub vis: Visibility,
|
|
pub sig: Signature,
|
|
pub semi_token: Token![;],
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// A foreign static item in an `extern` block: `static ext: u8`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ForeignItemStatic {
|
|
pub attrs: Vec<Attribute>,
|
|
pub vis: Visibility,
|
|
pub static_token: Token![static],
|
|
pub mutability: StaticMutability,
|
|
pub ident: Ident,
|
|
pub colon_token: Token![:],
|
|
pub ty: Box<Type>,
|
|
pub semi_token: Token![;],
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// A foreign type in an `extern` block: `type void`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ForeignItemType {
|
|
pub attrs: Vec<Attribute>,
|
|
pub vis: Visibility,
|
|
pub type_token: Token![type],
|
|
pub ident: Ident,
|
|
pub generics: Generics,
|
|
pub semi_token: Token![;],
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// A macro invocation within an extern block.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ForeignItemMacro {
|
|
pub attrs: Vec<Attribute>,
|
|
pub mac: Macro,
|
|
pub semi_token: Option<Token![;]>,
|
|
}
|
|
}
|
|
|
|
ast_enum_of_structs! {
|
|
/// An item declaration within the definition of a trait.
|
|
///
|
|
/// # 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 = "full")))]
|
|
#[non_exhaustive]
|
|
pub enum TraitItem {
|
|
/// An associated constant within the definition of a trait.
|
|
Const(TraitItemConst),
|
|
|
|
/// An associated function within the definition of a trait.
|
|
Fn(TraitItemFn),
|
|
|
|
/// An associated type within the definition of a trait.
|
|
Type(TraitItemType),
|
|
|
|
/// A macro invocation within the definition of a trait.
|
|
Macro(TraitItemMacro),
|
|
|
|
/// Tokens within the definition of a trait not interpreted by Syn.
|
|
Verbatim(TokenStream),
|
|
|
|
// For testing exhaustiveness in downstream code, use the following idiom:
|
|
//
|
|
// match item {
|
|
// #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
|
|
//
|
|
// TraitItem::Const(item) => {...}
|
|
// TraitItem::Fn(item) => {...}
|
|
// ...
|
|
// TraitItem::Verbatim(item) => {...}
|
|
//
|
|
// _ => { /* some sane fallback */ }
|
|
// }
|
|
//
|
|
// This way we fail your tests but don't break your library when adding
|
|
// a variant. You will be notified by a test failure when a variant is
|
|
// added, so that you can add code to handle it, but your library will
|
|
// continue to compile and work for downstream users in the interim.
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// An associated constant within the definition of a trait.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct TraitItemConst {
|
|
pub attrs: Vec<Attribute>,
|
|
pub const_token: Token![const],
|
|
pub ident: Ident,
|
|
pub generics: Generics,
|
|
pub colon_token: Token![:],
|
|
pub ty: Type,
|
|
pub default: Option<(Token![=], Expr)>,
|
|
pub semi_token: Token![;],
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// An associated function within the definition of a trait.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct TraitItemFn {
|
|
pub attrs: Vec<Attribute>,
|
|
pub sig: Signature,
|
|
pub default: Option<Block>,
|
|
pub semi_token: Option<Token![;]>,
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// An associated type within the definition of a trait.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct TraitItemType {
|
|
pub attrs: Vec<Attribute>,
|
|
pub type_token: Token![type],
|
|
pub ident: Ident,
|
|
pub generics: Generics,
|
|
pub colon_token: Option<Token![:]>,
|
|
pub bounds: Punctuated<TypeParamBound, Token![+]>,
|
|
pub default: Option<(Token![=], Type)>,
|
|
pub semi_token: Token![;],
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// A macro invocation within the definition of a trait.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct TraitItemMacro {
|
|
pub attrs: Vec<Attribute>,
|
|
pub mac: Macro,
|
|
pub semi_token: Option<Token![;]>,
|
|
}
|
|
}
|
|
|
|
ast_enum_of_structs! {
|
|
/// An item within an impl block.
|
|
///
|
|
/// # 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 = "full")))]
|
|
#[non_exhaustive]
|
|
pub enum ImplItem {
|
|
/// An associated constant within an impl block.
|
|
Const(ImplItemConst),
|
|
|
|
/// An associated function within an impl block.
|
|
Fn(ImplItemFn),
|
|
|
|
/// An associated type within an impl block.
|
|
Type(ImplItemType),
|
|
|
|
/// A macro invocation within an impl block.
|
|
Macro(ImplItemMacro),
|
|
|
|
/// Tokens within an impl block not interpreted by Syn.
|
|
Verbatim(TokenStream),
|
|
|
|
// For testing exhaustiveness in downstream code, use the following idiom:
|
|
//
|
|
// match item {
|
|
// #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
|
|
//
|
|
// ImplItem::Const(item) => {...}
|
|
// ImplItem::Fn(item) => {...}
|
|
// ...
|
|
// ImplItem::Verbatim(item) => {...}
|
|
//
|
|
// _ => { /* some sane fallback */ }
|
|
// }
|
|
//
|
|
// This way we fail your tests but don't break your library when adding
|
|
// a variant. You will be notified by a test failure when a variant is
|
|
// added, so that you can add code to handle it, but your library will
|
|
// continue to compile and work for downstream users in the interim.
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// An associated constant within an impl block.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ImplItemConst {
|
|
pub attrs: Vec<Attribute>,
|
|
pub vis: Visibility,
|
|
pub defaultness: Option<Token![default]>,
|
|
pub const_token: Token![const],
|
|
pub ident: Ident,
|
|
pub generics: Generics,
|
|
pub colon_token: Token![:],
|
|
pub ty: Type,
|
|
pub eq_token: Token![=],
|
|
pub expr: Expr,
|
|
pub semi_token: Token![;],
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// An associated function within an impl block.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ImplItemFn {
|
|
pub attrs: Vec<Attribute>,
|
|
pub vis: Visibility,
|
|
pub defaultness: Option<Token![default]>,
|
|
pub sig: Signature,
|
|
pub block: Block,
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// An associated type within an impl block.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ImplItemType {
|
|
pub attrs: Vec<Attribute>,
|
|
pub vis: Visibility,
|
|
pub defaultness: Option<Token![default]>,
|
|
pub type_token: Token![type],
|
|
pub ident: Ident,
|
|
pub generics: Generics,
|
|
pub eq_token: Token![=],
|
|
pub ty: Type,
|
|
pub semi_token: Token![;],
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// A macro invocation within an impl block.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct ImplItemMacro {
|
|
pub attrs: Vec<Attribute>,
|
|
pub mac: Macro,
|
|
pub semi_token: Option<Token![;]>,
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// A function signature in a trait or implementation: `unsafe fn
|
|
/// initialize(&self)`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct Signature {
|
|
pub constness: Option<Token![const]>,
|
|
pub asyncness: Option<Token![async]>,
|
|
pub unsafety: Option<Token![unsafe]>,
|
|
pub abi: Option<Abi>,
|
|
pub fn_token: Token![fn],
|
|
pub ident: Ident,
|
|
pub generics: Generics,
|
|
pub paren_token: token::Paren,
|
|
pub inputs: Punctuated<FnArg, Token![,]>,
|
|
pub variadic: Option<Variadic>,
|
|
pub output: ReturnType,
|
|
}
|
|
}
|
|
|
|
impl Signature {
|
|
/// A method's `self` receiver, such as `&self` or `self: Box<Self>`.
|
|
pub fn receiver(&self) -> Option<&Receiver> {
|
|
let arg = self.inputs.first()?;
|
|
match arg {
|
|
FnArg::Receiver(receiver) => Some(receiver),
|
|
FnArg::Typed(_) => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
ast_enum_of_structs! {
|
|
/// An argument in a function signature: the `n: usize` in `fn f(n: usize)`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub enum FnArg {
|
|
/// The `self` argument of an associated method.
|
|
Receiver(Receiver),
|
|
|
|
/// A function argument accepted by pattern and type.
|
|
Typed(PatType),
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// The `self` argument of an associated method.
|
|
///
|
|
/// If `colon_token` is present, the receiver is written with an explicit
|
|
/// type such as `self: Box<Self>`. If `colon_token` is absent, the receiver
|
|
/// is written in shorthand such as `self` or `&self` or `&mut self`. In the
|
|
/// shorthand case, the type in `ty` is reconstructed as one of `Self`,
|
|
/// `&Self`, or `&mut Self`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct Receiver {
|
|
pub attrs: Vec<Attribute>,
|
|
pub reference: Option<(Token![&], Option<Lifetime>)>,
|
|
pub mutability: Option<Token![mut]>,
|
|
pub self_token: Token![self],
|
|
pub colon_token: Option<Token![:]>,
|
|
pub ty: Box<Type>,
|
|
}
|
|
}
|
|
|
|
impl Receiver {
|
|
pub fn lifetime(&self) -> Option<&Lifetime> {
|
|
self.reference.as_ref()?.1.as_ref()
|
|
}
|
|
}
|
|
|
|
ast_struct! {
|
|
/// The variadic argument of a foreign function.
|
|
///
|
|
/// ```rust
|
|
/// # struct c_char;
|
|
/// # struct c_int;
|
|
/// #
|
|
/// extern "C" {
|
|
/// fn printf(format: *const c_char, ...) -> c_int;
|
|
/// // ^^^
|
|
/// }
|
|
/// ```
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
pub struct Variadic {
|
|
pub attrs: Vec<Attribute>,
|
|
pub pat: Option<(Box<Pat>, Token![:])>,
|
|
pub dots: Token![...],
|
|
pub comma: Option<Token![,]>,
|
|
}
|
|
}
|
|
|
|
ast_enum! {
|
|
/// The mutability of an `Item::Static` or `ForeignItem::Static`.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
#[non_exhaustive]
|
|
pub enum StaticMutability {
|
|
Mut(Token![mut]),
|
|
None,
|
|
}
|
|
}
|
|
|
|
ast_enum! {
|
|
/// Unused, but reserved for RFC 3323 restrictions.
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
#[non_exhaustive]
|
|
pub enum ImplRestriction {}
|
|
|
|
|
|
// TODO: https://rust-lang.github.io/rfcs/3323-restrictions.html
|
|
//
|
|
// pub struct ImplRestriction {
|
|
// pub impl_token: Token![impl],
|
|
// pub paren_token: token::Paren,
|
|
// pub in_token: Option<Token![in]>,
|
|
// pub path: Box<Path>,
|
|
// }
|
|
}
|
|
|
|
#[cfg(feature = "parsing")]
|
|
pub(crate) mod parsing {
|
|
use crate::attr::{self, Attribute};
|
|
use crate::derive;
|
|
use crate::error::{Error, Result};
|
|
use crate::expr::Expr;
|
|
use crate::ext::IdentExt as _;
|
|
use crate::generics::{self, Generics, TypeParamBound};
|
|
use crate::ident::Ident;
|
|
use crate::item::{
|
|
FnArg, ForeignItem, ForeignItemFn, ForeignItemMacro, ForeignItemStatic, ForeignItemType,
|
|
ImplItem, ImplItemConst, ImplItemFn, ImplItemMacro, ImplItemType, Item, ItemConst,
|
|
ItemEnum, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, ItemMacro, ItemMod,
|
|
ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType, ItemUnion, ItemUse, Receiver,
|
|
Signature, StaticMutability, TraitItem, TraitItemConst, TraitItemFn, TraitItemMacro,
|
|
TraitItemType, UseGlob, UseGroup, UseName, UsePath, UseRename, UseTree, Variadic,
|
|
};
|
|
use crate::lifetime::Lifetime;
|
|
use crate::lit::LitStr;
|
|
use crate::mac::{self, Macro};
|
|
use crate::parse::discouraged::Speculative as _;
|
|
use crate::parse::{Parse, ParseBuffer, ParseStream};
|
|
use crate::pat::{Pat, PatType, PatWild};
|
|
use crate::path::Path;
|
|
use crate::punctuated::Punctuated;
|
|
use crate::restriction::Visibility;
|
|
use crate::stmt::Block;
|
|
use crate::token;
|
|
use crate::ty::{Abi, ReturnType, Type, TypePath, TypeReference};
|
|
use crate::verbatim;
|
|
use proc_macro2::TokenStream;
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for Item {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let begin = input.fork();
|
|
let attrs = input.call(Attribute::parse_outer)?;
|
|
parse_rest_of_item(begin, attrs, input)
|
|
}
|
|
}
|
|
|
|
pub(crate) fn parse_rest_of_item(
|
|
begin: ParseBuffer,
|
|
mut attrs: Vec<Attribute>,
|
|
input: ParseStream,
|
|
) -> Result<Item> {
|
|
let ahead = input.fork();
|
|
let vis: Visibility = ahead.parse()?;
|
|
|
|
let lookahead = ahead.lookahead1();
|
|
let allow_safe = false;
|
|
let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead, allow_safe) {
|
|
let vis: Visibility = input.parse()?;
|
|
let sig: Signature = input.parse()?;
|
|
if input.peek(Token![;]) {
|
|
input.parse::<Token![;]>()?;
|
|
Ok(Item::Verbatim(verbatim::between(&begin, input)))
|
|
} else {
|
|
parse_rest_of_fn(input, Vec::new(), vis, sig).map(Item::Fn)
|
|
}
|
|
} else if lookahead.peek(Token![extern]) {
|
|
ahead.parse::<Token![extern]>()?;
|
|
let lookahead = ahead.lookahead1();
|
|
if lookahead.peek(Token![crate]) {
|
|
input.parse().map(Item::ExternCrate)
|
|
} else if lookahead.peek(token::Brace) {
|
|
input.parse().map(Item::ForeignMod)
|
|
} else if lookahead.peek(LitStr) {
|
|
ahead.parse::<LitStr>()?;
|
|
let lookahead = ahead.lookahead1();
|
|
if lookahead.peek(token::Brace) {
|
|
input.parse().map(Item::ForeignMod)
|
|
} else {
|
|
Err(lookahead.error())
|
|
}
|
|
} else {
|
|
Err(lookahead.error())
|
|
}
|
|
} else if lookahead.peek(Token![use]) {
|
|
let allow_crate_root_in_path = true;
|
|
match parse_item_use(input, allow_crate_root_in_path)? {
|
|
Some(item_use) => Ok(Item::Use(item_use)),
|
|
None => Ok(Item::Verbatim(verbatim::between(&begin, input))),
|
|
}
|
|
} else if lookahead.peek(Token![static]) {
|
|
let vis = input.parse()?;
|
|
let static_token = input.parse()?;
|
|
let mutability = input.parse()?;
|
|
let ident = input.parse()?;
|
|
if input.peek(Token![=]) {
|
|
input.parse::<Token![=]>()?;
|
|
input.parse::<Expr>()?;
|
|
input.parse::<Token![;]>()?;
|
|
Ok(Item::Verbatim(verbatim::between(&begin, input)))
|
|
} else {
|
|
let colon_token = input.parse()?;
|
|
let ty = input.parse()?;
|
|
if input.peek(Token![;]) {
|
|
input.parse::<Token![;]>()?;
|
|
Ok(Item::Verbatim(verbatim::between(&begin, input)))
|
|
} else {
|
|
Ok(Item::Static(ItemStatic {
|
|
attrs: Vec::new(),
|
|
vis,
|
|
static_token,
|
|
mutability,
|
|
ident,
|
|
colon_token,
|
|
ty,
|
|
eq_token: input.parse()?,
|
|
expr: input.parse()?,
|
|
semi_token: input.parse()?,
|
|
}))
|
|
}
|
|
}
|
|
} else if lookahead.peek(Token![const]) {
|
|
let vis = input.parse()?;
|
|
let const_token: Token![const] = input.parse()?;
|
|
let lookahead = input.lookahead1();
|
|
let ident = if lookahead.peek(Ident) || lookahead.peek(Token![_]) {
|
|
input.call(Ident::parse_any)?
|
|
} else {
|
|
return Err(lookahead.error());
|
|
};
|
|
let mut generics: Generics = input.parse()?;
|
|
let colon_token = input.parse()?;
|
|
let ty = input.parse()?;
|
|
let value = if let Some(eq_token) = input.parse::<Option<Token![=]>>()? {
|
|
let expr: Expr = input.parse()?;
|
|
Some((eq_token, expr))
|
|
} else {
|
|
None
|
|
};
|
|
generics.where_clause = input.parse()?;
|
|
let semi_token: Token![;] = input.parse()?;
|
|
match value {
|
|
Some((eq_token, expr))
|
|
if generics.lt_token.is_none() && generics.where_clause.is_none() =>
|
|
{
|
|
Ok(Item::Const(ItemConst {
|
|
attrs: Vec::new(),
|
|
vis,
|
|
const_token,
|
|
ident,
|
|
generics,
|
|
colon_token,
|
|
ty,
|
|
eq_token,
|
|
expr: Box::new(expr),
|
|
semi_token,
|
|
}))
|
|
}
|
|
_ => Ok(Item::Verbatim(verbatim::between(&begin, input))),
|
|
}
|
|
} else if lookahead.peek(Token![unsafe]) {
|
|
ahead.parse::<Token![unsafe]>()?;
|
|
let lookahead = ahead.lookahead1();
|
|
if lookahead.peek(Token![trait])
|
|
|| lookahead.peek(Token![auto]) && ahead.peek2(Token![trait])
|
|
{
|
|
input.parse().map(Item::Trait)
|
|
} else if lookahead.peek(Token![impl]) {
|
|
let allow_verbatim_impl = true;
|
|
if let Some(item) = parse_impl(input, allow_verbatim_impl)? {
|
|
Ok(Item::Impl(item))
|
|
} else {
|
|
Ok(Item::Verbatim(verbatim::between(&begin, input)))
|
|
}
|
|
} else if lookahead.peek(Token![extern]) {
|
|
input.parse().map(Item::ForeignMod)
|
|
} else if lookahead.peek(Token![mod]) {
|
|
input.parse().map(Item::Mod)
|
|
} else {
|
|
Err(lookahead.error())
|
|
}
|
|
} else if lookahead.peek(Token![mod]) {
|
|
input.parse().map(Item::Mod)
|
|
} else if lookahead.peek(Token![type]) {
|
|
parse_item_type(begin, input)
|
|
} else if lookahead.peek(Token![struct]) {
|
|
input.parse().map(Item::Struct)
|
|
} else if lookahead.peek(Token![enum]) {
|
|
input.parse().map(Item::Enum)
|
|
} else if lookahead.peek(Token![union]) && ahead.peek2(Ident) {
|
|
input.parse().map(Item::Union)
|
|
} else if lookahead.peek(Token![trait]) {
|
|
input.call(parse_trait_or_trait_alias)
|
|
} else if lookahead.peek(Token![auto]) && ahead.peek2(Token![trait]) {
|
|
input.parse().map(Item::Trait)
|
|
} else if lookahead.peek(Token![impl])
|
|
|| lookahead.peek(Token![default]) && !ahead.peek2(Token![!])
|
|
{
|
|
let allow_verbatim_impl = true;
|
|
if let Some(item) = parse_impl(input, allow_verbatim_impl)? {
|
|
Ok(Item::Impl(item))
|
|
} else {
|
|
Ok(Item::Verbatim(verbatim::between(&begin, input)))
|
|
}
|
|
} else if lookahead.peek(Token![macro]) {
|
|
input.advance_to(&ahead);
|
|
parse_macro2(begin, vis, input)
|
|
} else if vis.is_inherited()
|
|
&& (lookahead.peek(Ident)
|
|
|| lookahead.peek(Token![self])
|
|
|| lookahead.peek(Token![super])
|
|
|| lookahead.peek(Token![crate])
|
|
|| lookahead.peek(Token![::]))
|
|
{
|
|
input.parse().map(Item::Macro)
|
|
} else {
|
|
Err(lookahead.error())
|
|
}?;
|
|
|
|
attrs.extend(item.replace_attrs(Vec::new()));
|
|
item.replace_attrs(attrs);
|
|
Ok(item)
|
|
}
|
|
|
|
struct FlexibleItemType {
|
|
vis: Visibility,
|
|
defaultness: Option<Token![default]>,
|
|
type_token: Token![type],
|
|
ident: Ident,
|
|
generics: Generics,
|
|
colon_token: Option<Token![:]>,
|
|
bounds: Punctuated<TypeParamBound, Token![+]>,
|
|
ty: Option<(Token![=], Type)>,
|
|
semi_token: Token![;],
|
|
}
|
|
|
|
enum TypeDefaultness {
|
|
Optional,
|
|
Disallowed,
|
|
}
|
|
|
|
enum WhereClauseLocation {
|
|
// type Ty<T> where T: 'static = T;
|
|
BeforeEq,
|
|
// type Ty<T> = T where T: 'static;
|
|
AfterEq,
|
|
// TODO: goes away once the migration period on rust-lang/rust#89122 is over
|
|
Both,
|
|
}
|
|
|
|
impl FlexibleItemType {
|
|
fn parse(
|
|
input: ParseStream,
|
|
allow_defaultness: TypeDefaultness,
|
|
where_clause_location: WhereClauseLocation,
|
|
) -> Result<Self> {
|
|
let vis: Visibility = input.parse()?;
|
|
let defaultness: Option<Token![default]> = match allow_defaultness {
|
|
TypeDefaultness::Optional => input.parse()?,
|
|
TypeDefaultness::Disallowed => None,
|
|
};
|
|
let type_token: Token![type] = input.parse()?;
|
|
let ident: Ident = input.parse()?;
|
|
let mut generics: Generics = input.parse()?;
|
|
let (colon_token, bounds) = Self::parse_optional_bounds(input)?;
|
|
|
|
match where_clause_location {
|
|
WhereClauseLocation::BeforeEq | WhereClauseLocation::Both => {
|
|
generics.where_clause = input.parse()?;
|
|
}
|
|
WhereClauseLocation::AfterEq => {}
|
|
}
|
|
|
|
let ty = Self::parse_optional_definition(input)?;
|
|
|
|
match where_clause_location {
|
|
WhereClauseLocation::AfterEq | WhereClauseLocation::Both
|
|
if generics.where_clause.is_none() =>
|
|
{
|
|
generics.where_clause = input.parse()?;
|
|
}
|
|
_ => {}
|
|
}
|
|
|
|
let semi_token: Token![;] = input.parse()?;
|
|
|
|
Ok(FlexibleItemType {
|
|
vis,
|
|
defaultness,
|
|
type_token,
|
|
ident,
|
|
generics,
|
|
colon_token,
|
|
bounds,
|
|
ty,
|
|
semi_token,
|
|
})
|
|
}
|
|
|
|
fn parse_optional_bounds(
|
|
input: ParseStream,
|
|
) -> Result<(Option<Token![:]>, Punctuated<TypeParamBound, Token![+]>)> {
|
|
let colon_token: Option<Token![:]> = input.parse()?;
|
|
|
|
let mut bounds = Punctuated::new();
|
|
if colon_token.is_some() {
|
|
loop {
|
|
if input.peek(Token![where]) || input.peek(Token![=]) || input.peek(Token![;]) {
|
|
break;
|
|
}
|
|
bounds.push_value({
|
|
let allow_precise_capture = false;
|
|
let allow_const = true;
|
|
TypeParamBound::parse_single(input, allow_precise_capture, allow_const)?
|
|
});
|
|
if input.peek(Token![where]) || input.peek(Token![=]) || input.peek(Token![;]) {
|
|
break;
|
|
}
|
|
bounds.push_punct(input.parse::<Token![+]>()?);
|
|
}
|
|
}
|
|
|
|
Ok((colon_token, bounds))
|
|
}
|
|
|
|
fn parse_optional_definition(input: ParseStream) -> Result<Option<(Token![=], Type)>> {
|
|
let eq_token: Option<Token![=]> = input.parse()?;
|
|
if let Some(eq_token) = eq_token {
|
|
let definition: Type = input.parse()?;
|
|
Ok(Some((eq_token, definition)))
|
|
} else {
|
|
Ok(None)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ItemMacro {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let attrs = input.call(Attribute::parse_outer)?;
|
|
let path = input.call(Path::parse_mod_style)?;
|
|
let bang_token: Token![!] = input.parse()?;
|
|
let ident: Option<Ident> = if input.peek(Token![try]) {
|
|
input.call(Ident::parse_any).map(Some)
|
|
} else {
|
|
input.parse()
|
|
}?;
|
|
let (delimiter, tokens) = input.call(mac::parse_delimiter)?;
|
|
let semi_token: Option<Token![;]> = if !delimiter.is_brace() {
|
|
Some(input.parse()?)
|
|
} else {
|
|
None
|
|
};
|
|
Ok(ItemMacro {
|
|
attrs,
|
|
ident,
|
|
mac: Macro {
|
|
path,
|
|
bang_token,
|
|
delimiter,
|
|
tokens,
|
|
},
|
|
semi_token,
|
|
})
|
|
}
|
|
}
|
|
|
|
fn parse_macro2(begin: ParseBuffer, _vis: Visibility, input: ParseStream) -> Result<Item> {
|
|
input.parse::<Token![macro]>()?;
|
|
input.parse::<Ident>()?;
|
|
|
|
let mut lookahead = input.lookahead1();
|
|
if lookahead.peek(token::Paren) {
|
|
let paren_content;
|
|
parenthesized!(paren_content in input);
|
|
paren_content.parse::<TokenStream>()?;
|
|
lookahead = input.lookahead1();
|
|
}
|
|
|
|
if lookahead.peek(token::Brace) {
|
|
let brace_content;
|
|
braced!(brace_content in input);
|
|
brace_content.parse::<TokenStream>()?;
|
|
} else {
|
|
return Err(lookahead.error());
|
|
}
|
|
|
|
Ok(Item::Verbatim(verbatim::between(&begin, input)))
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ItemExternCrate {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
Ok(ItemExternCrate {
|
|
attrs: input.call(Attribute::parse_outer)?,
|
|
vis: input.parse()?,
|
|
extern_token: input.parse()?,
|
|
crate_token: input.parse()?,
|
|
ident: {
|
|
if input.peek(Token![self]) {
|
|
input.call(Ident::parse_any)?
|
|
} else {
|
|
input.parse()?
|
|
}
|
|
},
|
|
rename: {
|
|
if input.peek(Token![as]) {
|
|
let as_token: Token![as] = input.parse()?;
|
|
let rename: Ident = if input.peek(Token![_]) {
|
|
Ident::from(input.parse::<Token![_]>()?)
|
|
} else {
|
|
input.parse()?
|
|
};
|
|
Some((as_token, rename))
|
|
} else {
|
|
None
|
|
}
|
|
},
|
|
semi_token: input.parse()?,
|
|
})
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ItemUse {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let allow_crate_root_in_path = false;
|
|
parse_item_use(input, allow_crate_root_in_path).map(Option::unwrap)
|
|
}
|
|
}
|
|
|
|
fn parse_item_use(
|
|
input: ParseStream,
|
|
allow_crate_root_in_path: bool,
|
|
) -> Result<Option<ItemUse>> {
|
|
let attrs = input.call(Attribute::parse_outer)?;
|
|
let vis: Visibility = input.parse()?;
|
|
let use_token: Token![use] = input.parse()?;
|
|
let leading_colon: Option<Token![::]> = input.parse()?;
|
|
let tree = parse_use_tree(input, allow_crate_root_in_path && leading_colon.is_none())?;
|
|
let semi_token: Token![;] = input.parse()?;
|
|
|
|
let tree = match tree {
|
|
Some(tree) => tree,
|
|
None => return Ok(None),
|
|
};
|
|
|
|
Ok(Some(ItemUse {
|
|
attrs,
|
|
vis,
|
|
use_token,
|
|
leading_colon,
|
|
tree,
|
|
semi_token,
|
|
}))
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for UseTree {
|
|
fn parse(input: ParseStream) -> Result<UseTree> {
|
|
let allow_crate_root_in_path = false;
|
|
parse_use_tree(input, allow_crate_root_in_path).map(Option::unwrap)
|
|
}
|
|
}
|
|
|
|
fn parse_use_tree(
|
|
input: ParseStream,
|
|
allow_crate_root_in_path: bool,
|
|
) -> Result<Option<UseTree>> {
|
|
let lookahead = input.lookahead1();
|
|
if lookahead.peek(Ident)
|
|
|| lookahead.peek(Token![self])
|
|
|| lookahead.peek(Token![super])
|
|
|| lookahead.peek(Token![crate])
|
|
|| lookahead.peek(Token![try])
|
|
{
|
|
let ident = input.call(Ident::parse_any)?;
|
|
if input.peek(Token![::]) {
|
|
Ok(Some(UseTree::Path(UsePath {
|
|
ident,
|
|
colon2_token: input.parse()?,
|
|
tree: Box::new(input.parse()?),
|
|
})))
|
|
} else if input.peek(Token![as]) {
|
|
Ok(Some(UseTree::Rename(UseRename {
|
|
ident,
|
|
as_token: input.parse()?,
|
|
rename: {
|
|
if input.peek(Ident) {
|
|
input.parse()?
|
|
} else if input.peek(Token![_]) {
|
|
Ident::from(input.parse::<Token![_]>()?)
|
|
} else {
|
|
return Err(input.error("expected identifier or underscore"));
|
|
}
|
|
},
|
|
})))
|
|
} else {
|
|
Ok(Some(UseTree::Name(UseName { ident })))
|
|
}
|
|
} else if lookahead.peek(Token![*]) {
|
|
Ok(Some(UseTree::Glob(UseGlob {
|
|
star_token: input.parse()?,
|
|
})))
|
|
} else if lookahead.peek(token::Brace) {
|
|
let content;
|
|
let brace_token = braced!(content in input);
|
|
let mut items = Punctuated::new();
|
|
let mut has_any_crate_root_in_path = false;
|
|
loop {
|
|
if content.is_empty() {
|
|
break;
|
|
}
|
|
let this_tree_starts_with_crate_root =
|
|
allow_crate_root_in_path && content.parse::<Option<Token![::]>>()?.is_some();
|
|
has_any_crate_root_in_path |= this_tree_starts_with_crate_root;
|
|
match parse_use_tree(
|
|
&content,
|
|
allow_crate_root_in_path && !this_tree_starts_with_crate_root,
|
|
)? {
|
|
Some(tree) if !has_any_crate_root_in_path => items.push_value(tree),
|
|
_ => has_any_crate_root_in_path = true,
|
|
}
|
|
if content.is_empty() {
|
|
break;
|
|
}
|
|
let comma: Token![,] = content.parse()?;
|
|
if !has_any_crate_root_in_path {
|
|
items.push_punct(comma);
|
|
}
|
|
}
|
|
if has_any_crate_root_in_path {
|
|
Ok(None)
|
|
} else {
|
|
Ok(Some(UseTree::Group(UseGroup { brace_token, items })))
|
|
}
|
|
} else {
|
|
Err(lookahead.error())
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ItemStatic {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
Ok(ItemStatic {
|
|
attrs: input.call(Attribute::parse_outer)?,
|
|
vis: input.parse()?,
|
|
static_token: input.parse()?,
|
|
mutability: input.parse()?,
|
|
ident: input.parse()?,
|
|
colon_token: input.parse()?,
|
|
ty: input.parse()?,
|
|
eq_token: input.parse()?,
|
|
expr: input.parse()?,
|
|
semi_token: input.parse()?,
|
|
})
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ItemConst {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let attrs = input.call(Attribute::parse_outer)?;
|
|
let vis: Visibility = input.parse()?;
|
|
let const_token: Token![const] = input.parse()?;
|
|
|
|
let lookahead = input.lookahead1();
|
|
let ident = if lookahead.peek(Ident) || lookahead.peek(Token![_]) {
|
|
input.call(Ident::parse_any)?
|
|
} else {
|
|
return Err(lookahead.error());
|
|
};
|
|
|
|
let colon_token: Token![:] = input.parse()?;
|
|
let ty: Type = input.parse()?;
|
|
let eq_token: Token![=] = input.parse()?;
|
|
let expr: Expr = input.parse()?;
|
|
let semi_token: Token![;] = input.parse()?;
|
|
|
|
Ok(ItemConst {
|
|
attrs,
|
|
vis,
|
|
const_token,
|
|
ident,
|
|
generics: Generics::default(),
|
|
colon_token,
|
|
ty: Box::new(ty),
|
|
eq_token,
|
|
expr: Box::new(expr),
|
|
semi_token,
|
|
})
|
|
}
|
|
}
|
|
|
|
fn peek_signature(input: ParseStream, allow_safe: bool) -> bool {
|
|
let fork = input.fork();
|
|
fork.parse::<Option<Token![const]>>().is_ok()
|
|
&& fork.parse::<Option<Token![async]>>().is_ok()
|
|
&& ((allow_safe
|
|
&& token::parsing::peek_keyword(fork.cursor(), "safe")
|
|
&& token::parsing::keyword(&fork, "safe").is_ok())
|
|
|| fork.parse::<Option<Token![unsafe]>>().is_ok())
|
|
&& fork.parse::<Option<Abi>>().is_ok()
|
|
&& fork.peek(Token![fn])
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for Signature {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let allow_safe = false;
|
|
parse_signature(input, allow_safe).map(Option::unwrap)
|
|
}
|
|
}
|
|
|
|
fn parse_signature(input: ParseStream, allow_safe: bool) -> Result<Option<Signature>> {
|
|
let constness: Option<Token![const]> = input.parse()?;
|
|
let asyncness: Option<Token![async]> = input.parse()?;
|
|
let unsafety: Option<Token![unsafe]> = input.parse()?;
|
|
let safe = allow_safe
|
|
&& unsafety.is_none()
|
|
&& token::parsing::peek_keyword(input.cursor(), "safe");
|
|
if safe {
|
|
token::parsing::keyword(input, "safe")?;
|
|
}
|
|
let abi: Option<Abi> = input.parse()?;
|
|
let fn_token: Token![fn] = input.parse()?;
|
|
let ident: Ident = input.parse()?;
|
|
let mut generics: Generics = input.parse()?;
|
|
|
|
let content;
|
|
let paren_token = parenthesized!(content in input);
|
|
let (inputs, variadic) = parse_fn_args(&content)?;
|
|
|
|
let output: ReturnType = input.parse()?;
|
|
generics.where_clause = input.parse()?;
|
|
|
|
Ok(if safe {
|
|
None
|
|
} else {
|
|
Some(Signature {
|
|
constness,
|
|
asyncness,
|
|
unsafety,
|
|
abi,
|
|
fn_token,
|
|
ident,
|
|
generics,
|
|
paren_token,
|
|
inputs,
|
|
variadic,
|
|
output,
|
|
})
|
|
})
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ItemFn {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let outer_attrs = input.call(Attribute::parse_outer)?;
|
|
let vis: Visibility = input.parse()?;
|
|
let sig: Signature = input.parse()?;
|
|
parse_rest_of_fn(input, outer_attrs, vis, sig)
|
|
}
|
|
}
|
|
|
|
fn parse_rest_of_fn(
|
|
input: ParseStream,
|
|
mut attrs: Vec<Attribute>,
|
|
vis: Visibility,
|
|
sig: Signature,
|
|
) -> Result<ItemFn> {
|
|
let content;
|
|
let brace_token = braced!(content in input);
|
|
attr::parsing::parse_inner(&content, &mut attrs)?;
|
|
let stmts = content.call(Block::parse_within)?;
|
|
|
|
Ok(ItemFn {
|
|
attrs,
|
|
vis,
|
|
sig,
|
|
block: Box::new(Block { brace_token, stmts }),
|
|
})
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for FnArg {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let allow_variadic = false;
|
|
let attrs = input.call(Attribute::parse_outer)?;
|
|
match parse_fn_arg_or_variadic(input, attrs, allow_variadic)? {
|
|
FnArgOrVariadic::FnArg(arg) => Ok(arg),
|
|
FnArgOrVariadic::Variadic(_) => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
enum FnArgOrVariadic {
|
|
FnArg(FnArg),
|
|
Variadic(Variadic),
|
|
}
|
|
|
|
fn parse_fn_arg_or_variadic(
|
|
input: ParseStream,
|
|
attrs: Vec<Attribute>,
|
|
allow_variadic: bool,
|
|
) -> Result<FnArgOrVariadic> {
|
|
let ahead = input.fork();
|
|
if let Ok(mut receiver) = ahead.parse::<Receiver>() {
|
|
input.advance_to(&ahead);
|
|
receiver.attrs = attrs;
|
|
return Ok(FnArgOrVariadic::FnArg(FnArg::Receiver(receiver)));
|
|
}
|
|
|
|
// Hack to parse pre-2018 syntax in
|
|
// test/ui/rfc-2565-param-attrs/param-attrs-pretty.rs
|
|
// because the rest of the test case is valuable.
|
|
if input.peek(Ident) && input.peek2(Token![<]) {
|
|
let span = input.span();
|
|
return Ok(FnArgOrVariadic::FnArg(FnArg::Typed(PatType {
|
|
attrs,
|
|
pat: Box::new(Pat::Wild(PatWild {
|
|
attrs: Vec::new(),
|
|
underscore_token: Token,
|
|
})),
|
|
colon_token: Token,
|
|
ty: input.parse()?,
|
|
})));
|
|
}
|
|
|
|
let pat = Box::new(Pat::parse_single(input)?);
|
|
let colon_token: Token![:] = input.parse()?;
|
|
|
|
if allow_variadic {
|
|
if let Some(dots) = input.parse::<Option<Token![...]>>()? {
|
|
return Ok(FnArgOrVariadic::Variadic(Variadic {
|
|
attrs,
|
|
pat: Some((pat, colon_token)),
|
|
dots,
|
|
comma: None,
|
|
}));
|
|
}
|
|
}
|
|
|
|
Ok(FnArgOrVariadic::FnArg(FnArg::Typed(PatType {
|
|
attrs,
|
|
pat,
|
|
colon_token,
|
|
ty: input.parse()?,
|
|
})))
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for Receiver {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let reference = if input.peek(Token![&]) {
|
|
let ampersand: Token![&] = input.parse()?;
|
|
let lifetime: Option<Lifetime> = input.parse()?;
|
|
Some((ampersand, lifetime))
|
|
} else {
|
|
None
|
|
};
|
|
let mutability: Option<Token![mut]> = input.parse()?;
|
|
let self_token: Token![self] = input.parse()?;
|
|
let colon_token: Option<Token![:]> = if reference.is_some() {
|
|
None
|
|
} else {
|
|
input.parse()?
|
|
};
|
|
let ty: Type = if colon_token.is_some() {
|
|
input.parse()?
|
|
} else {
|
|
let mut ty = Type::Path(TypePath {
|
|
qself: None,
|
|
path: Path::from(Ident::new("Self", self_token.span)),
|
|
});
|
|
if let Some((ampersand, lifetime)) = reference.as_ref() {
|
|
ty = Type::Reference(TypeReference {
|
|
and_token: Token,
|
|
lifetime: lifetime.clone(),
|
|
mutability: mutability.as_ref().map(|m| Token),
|
|
elem: Box::new(ty),
|
|
});
|
|
}
|
|
ty
|
|
};
|
|
Ok(Receiver {
|
|
attrs: Vec::new(),
|
|
reference,
|
|
mutability,
|
|
self_token,
|
|
colon_token,
|
|
ty: Box::new(ty),
|
|
})
|
|
}
|
|
}
|
|
|
|
fn parse_fn_args(
|
|
input: ParseStream,
|
|
) -> Result<(Punctuated<FnArg, Token![,]>, Option<Variadic>)> {
|
|
let mut args = Punctuated::new();
|
|
let mut variadic = None;
|
|
let mut has_receiver = false;
|
|
|
|
while !input.is_empty() {
|
|
let attrs = input.call(Attribute::parse_outer)?;
|
|
|
|
if let Some(dots) = input.parse::<Option<Token![...]>>()? {
|
|
variadic = Some(Variadic {
|
|
attrs,
|
|
pat: None,
|
|
dots,
|
|
comma: if input.is_empty() {
|
|
None
|
|
} else {
|
|
Some(input.parse()?)
|
|
},
|
|
});
|
|
break;
|
|
}
|
|
|
|
let allow_variadic = true;
|
|
let arg = match parse_fn_arg_or_variadic(input, attrs, allow_variadic)? {
|
|
FnArgOrVariadic::FnArg(arg) => arg,
|
|
FnArgOrVariadic::Variadic(arg) => {
|
|
variadic = Some(Variadic {
|
|
comma: if input.is_empty() {
|
|
None
|
|
} else {
|
|
Some(input.parse()?)
|
|
},
|
|
..arg
|
|
});
|
|
break;
|
|
}
|
|
};
|
|
|
|
match &arg {
|
|
FnArg::Receiver(receiver) if has_receiver => {
|
|
return Err(Error::new(
|
|
receiver.self_token.span,
|
|
"unexpected second method receiver",
|
|
));
|
|
}
|
|
FnArg::Receiver(receiver) if !args.is_empty() => {
|
|
return Err(Error::new(
|
|
receiver.self_token.span,
|
|
"unexpected method receiver",
|
|
));
|
|
}
|
|
FnArg::Receiver(_) => has_receiver = true,
|
|
FnArg::Typed(_) => {}
|
|
}
|
|
args.push_value(arg);
|
|
|
|
if input.is_empty() {
|
|
break;
|
|
}
|
|
|
|
let comma: Token![,] = input.parse()?;
|
|
args.push_punct(comma);
|
|
}
|
|
|
|
Ok((args, variadic))
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ItemMod {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let mut attrs = input.call(Attribute::parse_outer)?;
|
|
let vis: Visibility = input.parse()?;
|
|
let unsafety: Option<Token![unsafe]> = input.parse()?;
|
|
let mod_token: Token![mod] = input.parse()?;
|
|
let ident: Ident = if input.peek(Token![try]) {
|
|
input.call(Ident::parse_any)
|
|
} else {
|
|
input.parse()
|
|
}?;
|
|
|
|
let lookahead = input.lookahead1();
|
|
if lookahead.peek(Token![;]) {
|
|
Ok(ItemMod {
|
|
attrs,
|
|
vis,
|
|
unsafety,
|
|
mod_token,
|
|
ident,
|
|
content: None,
|
|
semi: Some(input.parse()?),
|
|
})
|
|
} else if lookahead.peek(token::Brace) {
|
|
let content;
|
|
let brace_token = braced!(content in input);
|
|
attr::parsing::parse_inner(&content, &mut attrs)?;
|
|
|
|
let mut items = Vec::new();
|
|
while !content.is_empty() {
|
|
items.push(content.parse()?);
|
|
}
|
|
|
|
Ok(ItemMod {
|
|
attrs,
|
|
vis,
|
|
unsafety,
|
|
mod_token,
|
|
ident,
|
|
content: Some((brace_token, items)),
|
|
semi: None,
|
|
})
|
|
} else {
|
|
Err(lookahead.error())
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ItemForeignMod {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let mut attrs = input.call(Attribute::parse_outer)?;
|
|
let unsafety: Option<Token![unsafe]> = input.parse()?;
|
|
let abi: Abi = input.parse()?;
|
|
|
|
let content;
|
|
let brace_token = braced!(content in input);
|
|
attr::parsing::parse_inner(&content, &mut attrs)?;
|
|
let mut items = Vec::new();
|
|
while !content.is_empty() {
|
|
items.push(content.parse()?);
|
|
}
|
|
|
|
Ok(ItemForeignMod {
|
|
attrs,
|
|
unsafety,
|
|
abi,
|
|
brace_token,
|
|
items,
|
|
})
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ForeignItem {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let begin = input.fork();
|
|
let mut attrs = input.call(Attribute::parse_outer)?;
|
|
let ahead = input.fork();
|
|
let vis: Visibility = ahead.parse()?;
|
|
|
|
let lookahead = ahead.lookahead1();
|
|
let allow_safe = true;
|
|
let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead, allow_safe) {
|
|
let vis: Visibility = input.parse()?;
|
|
let sig = parse_signature(input, allow_safe)?;
|
|
let has_safe = sig.is_none();
|
|
let has_body = input.peek(token::Brace);
|
|
let semi_token: Option<Token![;]> = if has_body {
|
|
let content;
|
|
braced!(content in input);
|
|
content.call(Attribute::parse_inner)?;
|
|
content.call(Block::parse_within)?;
|
|
None
|
|
} else {
|
|
Some(input.parse()?)
|
|
};
|
|
if has_safe || has_body {
|
|
Ok(ForeignItem::Verbatim(verbatim::between(&begin, input)))
|
|
} else {
|
|
Ok(ForeignItem::Fn(ForeignItemFn {
|
|
attrs: Vec::new(),
|
|
vis,
|
|
sig: sig.unwrap(),
|
|
semi_token: semi_token.unwrap(),
|
|
}))
|
|
}
|
|
} else if lookahead.peek(Token![static])
|
|
|| ((ahead.peek(Token![unsafe])
|
|
|| token::parsing::peek_keyword(ahead.cursor(), "safe"))
|
|
&& ahead.peek2(Token![static]))
|
|
{
|
|
let vis = input.parse()?;
|
|
let unsafety: Option<Token![unsafe]> = input.parse()?;
|
|
let safe =
|
|
unsafety.is_none() && token::parsing::peek_keyword(input.cursor(), "safe");
|
|
if safe {
|
|
token::parsing::keyword(input, "safe")?;
|
|
}
|
|
let static_token = input.parse()?;
|
|
let mutability = input.parse()?;
|
|
let ident = input.parse()?;
|
|
let colon_token = input.parse()?;
|
|
let ty = input.parse()?;
|
|
let has_value = input.peek(Token![=]);
|
|
if has_value {
|
|
input.parse::<Token![=]>()?;
|
|
input.parse::<Expr>()?;
|
|
}
|
|
let semi_token: Token![;] = input.parse()?;
|
|
if unsafety.is_some() || safe || has_value {
|
|
Ok(ForeignItem::Verbatim(verbatim::between(&begin, input)))
|
|
} else {
|
|
Ok(ForeignItem::Static(ForeignItemStatic {
|
|
attrs: Vec::new(),
|
|
vis,
|
|
static_token,
|
|
mutability,
|
|
ident,
|
|
colon_token,
|
|
ty,
|
|
semi_token,
|
|
}))
|
|
}
|
|
} else if lookahead.peek(Token![type]) {
|
|
parse_foreign_item_type(begin, input)
|
|
} else if vis.is_inherited()
|
|
&& (lookahead.peek(Ident)
|
|
|| lookahead.peek(Token![self])
|
|
|| lookahead.peek(Token![super])
|
|
|| lookahead.peek(Token![crate])
|
|
|| lookahead.peek(Token![::]))
|
|
{
|
|
input.parse().map(ForeignItem::Macro)
|
|
} else {
|
|
Err(lookahead.error())
|
|
}?;
|
|
|
|
let item_attrs = match &mut item {
|
|
ForeignItem::Fn(item) => &mut item.attrs,
|
|
ForeignItem::Static(item) => &mut item.attrs,
|
|
ForeignItem::Type(item) => &mut item.attrs,
|
|
ForeignItem::Macro(item) => &mut item.attrs,
|
|
ForeignItem::Verbatim(_) => return Ok(item),
|
|
};
|
|
attrs.append(item_attrs);
|
|
*item_attrs = attrs;
|
|
|
|
Ok(item)
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ForeignItemFn {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let attrs = input.call(Attribute::parse_outer)?;
|
|
let vis: Visibility = input.parse()?;
|
|
let sig: Signature = input.parse()?;
|
|
let semi_token: Token![;] = input.parse()?;
|
|
Ok(ForeignItemFn {
|
|
attrs,
|
|
vis,
|
|
sig,
|
|
semi_token,
|
|
})
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ForeignItemStatic {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
Ok(ForeignItemStatic {
|
|
attrs: input.call(Attribute::parse_outer)?,
|
|
vis: input.parse()?,
|
|
static_token: input.parse()?,
|
|
mutability: input.parse()?,
|
|
ident: input.parse()?,
|
|
colon_token: input.parse()?,
|
|
ty: input.parse()?,
|
|
semi_token: input.parse()?,
|
|
})
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ForeignItemType {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
Ok(ForeignItemType {
|
|
attrs: input.call(Attribute::parse_outer)?,
|
|
vis: input.parse()?,
|
|
type_token: input.parse()?,
|
|
ident: input.parse()?,
|
|
generics: {
|
|
let mut generics: Generics = input.parse()?;
|
|
generics.where_clause = input.parse()?;
|
|
generics
|
|
},
|
|
semi_token: input.parse()?,
|
|
})
|
|
}
|
|
}
|
|
|
|
fn parse_foreign_item_type(begin: ParseBuffer, input: ParseStream) -> Result<ForeignItem> {
|
|
let FlexibleItemType {
|
|
vis,
|
|
defaultness: _,
|
|
type_token,
|
|
ident,
|
|
generics,
|
|
colon_token,
|
|
bounds: _,
|
|
ty,
|
|
semi_token,
|
|
} = FlexibleItemType::parse(
|
|
input,
|
|
TypeDefaultness::Disallowed,
|
|
WhereClauseLocation::Both,
|
|
)?;
|
|
|
|
if colon_token.is_some() || ty.is_some() {
|
|
Ok(ForeignItem::Verbatim(verbatim::between(&begin, input)))
|
|
} else {
|
|
Ok(ForeignItem::Type(ForeignItemType {
|
|
attrs: Vec::new(),
|
|
vis,
|
|
type_token,
|
|
ident,
|
|
generics,
|
|
semi_token,
|
|
}))
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ForeignItemMacro {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let attrs = input.call(Attribute::parse_outer)?;
|
|
let mac: Macro = input.parse()?;
|
|
let semi_token: Option<Token![;]> = if mac.delimiter.is_brace() {
|
|
None
|
|
} else {
|
|
Some(input.parse()?)
|
|
};
|
|
Ok(ForeignItemMacro {
|
|
attrs,
|
|
mac,
|
|
semi_token,
|
|
})
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ItemType {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
Ok(ItemType {
|
|
attrs: input.call(Attribute::parse_outer)?,
|
|
vis: input.parse()?,
|
|
type_token: input.parse()?,
|
|
ident: input.parse()?,
|
|
generics: {
|
|
let mut generics: Generics = input.parse()?;
|
|
generics.where_clause = input.parse()?;
|
|
generics
|
|
},
|
|
eq_token: input.parse()?,
|
|
ty: input.parse()?,
|
|
semi_token: input.parse()?,
|
|
})
|
|
}
|
|
}
|
|
|
|
fn parse_item_type(begin: ParseBuffer, input: ParseStream) -> Result<Item> {
|
|
let FlexibleItemType {
|
|
vis,
|
|
defaultness: _,
|
|
type_token,
|
|
ident,
|
|
generics,
|
|
colon_token,
|
|
bounds: _,
|
|
ty,
|
|
semi_token,
|
|
} = FlexibleItemType::parse(
|
|
input,
|
|
TypeDefaultness::Disallowed,
|
|
WhereClauseLocation::BeforeEq,
|
|
)?;
|
|
|
|
let (eq_token, ty) = match ty {
|
|
Some(ty) if colon_token.is_none() => ty,
|
|
_ => return Ok(Item::Verbatim(verbatim::between(&begin, input))),
|
|
};
|
|
|
|
Ok(Item::Type(ItemType {
|
|
attrs: Vec::new(),
|
|
vis,
|
|
type_token,
|
|
ident,
|
|
generics,
|
|
eq_token,
|
|
ty: Box::new(ty),
|
|
semi_token,
|
|
}))
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ItemStruct {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let attrs = input.call(Attribute::parse_outer)?;
|
|
let vis = input.parse::<Visibility>()?;
|
|
let struct_token = input.parse::<Token![struct]>()?;
|
|
let ident = input.parse::<Ident>()?;
|
|
let generics = input.parse::<Generics>()?;
|
|
let (where_clause, fields, semi_token) = derive::parsing::data_struct(input)?;
|
|
Ok(ItemStruct {
|
|
attrs,
|
|
vis,
|
|
struct_token,
|
|
ident,
|
|
generics: Generics {
|
|
where_clause,
|
|
..generics
|
|
},
|
|
fields,
|
|
semi_token,
|
|
})
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ItemEnum {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let attrs = input.call(Attribute::parse_outer)?;
|
|
let vis = input.parse::<Visibility>()?;
|
|
let enum_token = input.parse::<Token![enum]>()?;
|
|
let ident = input.parse::<Ident>()?;
|
|
let generics = input.parse::<Generics>()?;
|
|
let (where_clause, brace_token, variants) = derive::parsing::data_enum(input)?;
|
|
Ok(ItemEnum {
|
|
attrs,
|
|
vis,
|
|
enum_token,
|
|
ident,
|
|
generics: Generics {
|
|
where_clause,
|
|
..generics
|
|
},
|
|
brace_token,
|
|
variants,
|
|
})
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ItemUnion {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let attrs = input.call(Attribute::parse_outer)?;
|
|
let vis = input.parse::<Visibility>()?;
|
|
let union_token = input.parse::<Token![union]>()?;
|
|
let ident = input.parse::<Ident>()?;
|
|
let generics = input.parse::<Generics>()?;
|
|
let (where_clause, fields) = derive::parsing::data_union(input)?;
|
|
Ok(ItemUnion {
|
|
attrs,
|
|
vis,
|
|
union_token,
|
|
ident,
|
|
generics: Generics {
|
|
where_clause,
|
|
..generics
|
|
},
|
|
fields,
|
|
})
|
|
}
|
|
}
|
|
|
|
fn parse_trait_or_trait_alias(input: ParseStream) -> Result<Item> {
|
|
let (attrs, vis, trait_token, ident, generics) = parse_start_of_trait_alias(input)?;
|
|
let lookahead = input.lookahead1();
|
|
if lookahead.peek(token::Brace)
|
|
|| lookahead.peek(Token![:])
|
|
|| lookahead.peek(Token![where])
|
|
{
|
|
let unsafety = None;
|
|
let auto_token = None;
|
|
parse_rest_of_trait(
|
|
input,
|
|
attrs,
|
|
vis,
|
|
unsafety,
|
|
auto_token,
|
|
trait_token,
|
|
ident,
|
|
generics,
|
|
)
|
|
.map(Item::Trait)
|
|
} else if lookahead.peek(Token![=]) {
|
|
parse_rest_of_trait_alias(input, attrs, vis, trait_token, ident, generics)
|
|
.map(Item::TraitAlias)
|
|
} else {
|
|
Err(lookahead.error())
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ItemTrait {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let outer_attrs = input.call(Attribute::parse_outer)?;
|
|
let vis: Visibility = input.parse()?;
|
|
let unsafety: Option<Token![unsafe]> = input.parse()?;
|
|
let auto_token: Option<Token![auto]> = input.parse()?;
|
|
let trait_token: Token![trait] = input.parse()?;
|
|
let ident: Ident = input.parse()?;
|
|
let generics: Generics = input.parse()?;
|
|
parse_rest_of_trait(
|
|
input,
|
|
outer_attrs,
|
|
vis,
|
|
unsafety,
|
|
auto_token,
|
|
trait_token,
|
|
ident,
|
|
generics,
|
|
)
|
|
}
|
|
}
|
|
|
|
fn parse_rest_of_trait(
|
|
input: ParseStream,
|
|
mut attrs: Vec<Attribute>,
|
|
vis: Visibility,
|
|
unsafety: Option<Token![unsafe]>,
|
|
auto_token: Option<Token![auto]>,
|
|
trait_token: Token![trait],
|
|
ident: Ident,
|
|
mut generics: Generics,
|
|
) -> Result<ItemTrait> {
|
|
let colon_token: Option<Token![:]> = input.parse()?;
|
|
|
|
let mut supertraits = Punctuated::new();
|
|
if colon_token.is_some() {
|
|
loop {
|
|
if input.peek(Token![where]) || input.peek(token::Brace) {
|
|
break;
|
|
}
|
|
supertraits.push_value({
|
|
let allow_precise_capture = false;
|
|
let allow_const = true;
|
|
TypeParamBound::parse_single(input, allow_precise_capture, allow_const)?
|
|
});
|
|
if input.peek(Token![where]) || input.peek(token::Brace) {
|
|
break;
|
|
}
|
|
supertraits.push_punct(input.parse()?);
|
|
}
|
|
}
|
|
|
|
generics.where_clause = input.parse()?;
|
|
|
|
let content;
|
|
let brace_token = braced!(content in input);
|
|
attr::parsing::parse_inner(&content, &mut attrs)?;
|
|
let mut items = Vec::new();
|
|
while !content.is_empty() {
|
|
items.push(content.parse()?);
|
|
}
|
|
|
|
Ok(ItemTrait {
|
|
attrs,
|
|
vis,
|
|
unsafety,
|
|
auto_token,
|
|
restriction: None,
|
|
trait_token,
|
|
ident,
|
|
generics,
|
|
colon_token,
|
|
supertraits,
|
|
brace_token,
|
|
items,
|
|
})
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ItemTraitAlias {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let (attrs, vis, trait_token, ident, generics) = parse_start_of_trait_alias(input)?;
|
|
parse_rest_of_trait_alias(input, attrs, vis, trait_token, ident, generics)
|
|
}
|
|
}
|
|
|
|
fn parse_start_of_trait_alias(
|
|
input: ParseStream,
|
|
) -> Result<(Vec<Attribute>, Visibility, Token![trait], Ident, Generics)> {
|
|
let attrs = input.call(Attribute::parse_outer)?;
|
|
let vis: Visibility = input.parse()?;
|
|
let trait_token: Token![trait] = input.parse()?;
|
|
let ident: Ident = input.parse()?;
|
|
let generics: Generics = input.parse()?;
|
|
Ok((attrs, vis, trait_token, ident, generics))
|
|
}
|
|
|
|
fn parse_rest_of_trait_alias(
|
|
input: ParseStream,
|
|
attrs: Vec<Attribute>,
|
|
vis: Visibility,
|
|
trait_token: Token![trait],
|
|
ident: Ident,
|
|
mut generics: Generics,
|
|
) -> Result<ItemTraitAlias> {
|
|
let eq_token: Token![=] = input.parse()?;
|
|
|
|
let mut bounds = Punctuated::new();
|
|
loop {
|
|
if input.peek(Token![where]) || input.peek(Token![;]) {
|
|
break;
|
|
}
|
|
bounds.push_value({
|
|
let allow_precise_capture = false;
|
|
let allow_const = false;
|
|
TypeParamBound::parse_single(input, allow_precise_capture, allow_const)?
|
|
});
|
|
if input.peek(Token![where]) || input.peek(Token![;]) {
|
|
break;
|
|
}
|
|
bounds.push_punct(input.parse()?);
|
|
}
|
|
|
|
generics.where_clause = input.parse()?;
|
|
let semi_token: Token![;] = input.parse()?;
|
|
|
|
Ok(ItemTraitAlias {
|
|
attrs,
|
|
vis,
|
|
trait_token,
|
|
ident,
|
|
generics,
|
|
eq_token,
|
|
bounds,
|
|
semi_token,
|
|
})
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for TraitItem {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let begin = input.fork();
|
|
let mut attrs = input.call(Attribute::parse_outer)?;
|
|
let vis: Visibility = input.parse()?;
|
|
let defaultness: Option<Token![default]> = input.parse()?;
|
|
let ahead = input.fork();
|
|
|
|
let lookahead = ahead.lookahead1();
|
|
let allow_safe = false;
|
|
let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead, allow_safe) {
|
|
input.parse().map(TraitItem::Fn)
|
|
} else if lookahead.peek(Token![const]) {
|
|
let const_token: Token![const] = ahead.parse()?;
|
|
let lookahead = ahead.lookahead1();
|
|
if lookahead.peek(Ident) || lookahead.peek(Token![_]) {
|
|
input.advance_to(&ahead);
|
|
let ident = input.call(Ident::parse_any)?;
|
|
let mut generics: Generics = input.parse()?;
|
|
let colon_token: Token![:] = input.parse()?;
|
|
let ty: Type = input.parse()?;
|
|
let default = if let Some(eq_token) = input.parse::<Option<Token![=]>>()? {
|
|
let expr: Expr = input.parse()?;
|
|
Some((eq_token, expr))
|
|
} else {
|
|
None
|
|
};
|
|
generics.where_clause = input.parse()?;
|
|
let semi_token: Token![;] = input.parse()?;
|
|
if generics.lt_token.is_none() && generics.where_clause.is_none() {
|
|
Ok(TraitItem::Const(TraitItemConst {
|
|
attrs: Vec::new(),
|
|
const_token,
|
|
ident,
|
|
generics,
|
|
colon_token,
|
|
ty,
|
|
default,
|
|
semi_token,
|
|
}))
|
|
} else {
|
|
return Ok(TraitItem::Verbatim(verbatim::between(&begin, input)));
|
|
}
|
|
} else if lookahead.peek(Token![async])
|
|
|| lookahead.peek(Token![unsafe])
|
|
|| lookahead.peek(Token![extern])
|
|
|| lookahead.peek(Token![fn])
|
|
{
|
|
input.parse().map(TraitItem::Fn)
|
|
} else {
|
|
Err(lookahead.error())
|
|
}
|
|
} else if lookahead.peek(Token![type]) {
|
|
parse_trait_item_type(begin.fork(), input)
|
|
} else if vis.is_inherited()
|
|
&& defaultness.is_none()
|
|
&& (lookahead.peek(Ident)
|
|
|| lookahead.peek(Token![self])
|
|
|| lookahead.peek(Token![super])
|
|
|| lookahead.peek(Token![crate])
|
|
|| lookahead.peek(Token![::]))
|
|
{
|
|
input.parse().map(TraitItem::Macro)
|
|
} else {
|
|
Err(lookahead.error())
|
|
}?;
|
|
|
|
match (vis, defaultness) {
|
|
(Visibility::Inherited, None) => {}
|
|
_ => return Ok(TraitItem::Verbatim(verbatim::between(&begin, input))),
|
|
}
|
|
|
|
let item_attrs = match &mut item {
|
|
TraitItem::Const(item) => &mut item.attrs,
|
|
TraitItem::Fn(item) => &mut item.attrs,
|
|
TraitItem::Type(item) => &mut item.attrs,
|
|
TraitItem::Macro(item) => &mut item.attrs,
|
|
TraitItem::Verbatim(_) => unreachable!(),
|
|
};
|
|
attrs.append(item_attrs);
|
|
*item_attrs = attrs;
|
|
Ok(item)
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for TraitItemConst {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let attrs = input.call(Attribute::parse_outer)?;
|
|
let const_token: Token![const] = input.parse()?;
|
|
|
|
let lookahead = input.lookahead1();
|
|
let ident = if lookahead.peek(Ident) || lookahead.peek(Token![_]) {
|
|
input.call(Ident::parse_any)?
|
|
} else {
|
|
return Err(lookahead.error());
|
|
};
|
|
|
|
let colon_token: Token![:] = input.parse()?;
|
|
let ty: Type = input.parse()?;
|
|
let default = if input.peek(Token![=]) {
|
|
let eq_token: Token![=] = input.parse()?;
|
|
let default: Expr = input.parse()?;
|
|
Some((eq_token, default))
|
|
} else {
|
|
None
|
|
};
|
|
let semi_token: Token![;] = input.parse()?;
|
|
|
|
Ok(TraitItemConst {
|
|
attrs,
|
|
const_token,
|
|
ident,
|
|
generics: Generics::default(),
|
|
colon_token,
|
|
ty,
|
|
default,
|
|
semi_token,
|
|
})
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for TraitItemFn {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let mut attrs = input.call(Attribute::parse_outer)?;
|
|
let sig: Signature = input.parse()?;
|
|
|
|
let lookahead = input.lookahead1();
|
|
let (brace_token, stmts, semi_token) = if lookahead.peek(token::Brace) {
|
|
let content;
|
|
let brace_token = braced!(content in input);
|
|
attr::parsing::parse_inner(&content, &mut attrs)?;
|
|
let stmts = content.call(Block::parse_within)?;
|
|
(Some(brace_token), stmts, None)
|
|
} else if lookahead.peek(Token![;]) {
|
|
let semi_token: Token![;] = input.parse()?;
|
|
(None, Vec::new(), Some(semi_token))
|
|
} else {
|
|
return Err(lookahead.error());
|
|
};
|
|
|
|
Ok(TraitItemFn {
|
|
attrs,
|
|
sig,
|
|
default: brace_token.map(|brace_token| Block { brace_token, stmts }),
|
|
semi_token,
|
|
})
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for TraitItemType {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let attrs = input.call(Attribute::parse_outer)?;
|
|
let type_token: Token![type] = input.parse()?;
|
|
let ident: Ident = input.parse()?;
|
|
let mut generics: Generics = input.parse()?;
|
|
let (colon_token, bounds) = FlexibleItemType::parse_optional_bounds(input)?;
|
|
let default = FlexibleItemType::parse_optional_definition(input)?;
|
|
generics.where_clause = input.parse()?;
|
|
let semi_token: Token![;] = input.parse()?;
|
|
Ok(TraitItemType {
|
|
attrs,
|
|
type_token,
|
|
ident,
|
|
generics,
|
|
colon_token,
|
|
bounds,
|
|
default,
|
|
semi_token,
|
|
})
|
|
}
|
|
}
|
|
|
|
fn parse_trait_item_type(begin: ParseBuffer, input: ParseStream) -> Result<TraitItem> {
|
|
let FlexibleItemType {
|
|
vis,
|
|
defaultness: _,
|
|
type_token,
|
|
ident,
|
|
generics,
|
|
colon_token,
|
|
bounds,
|
|
ty,
|
|
semi_token,
|
|
} = FlexibleItemType::parse(
|
|
input,
|
|
TypeDefaultness::Disallowed,
|
|
WhereClauseLocation::AfterEq,
|
|
)?;
|
|
|
|
if vis.is_some() {
|
|
Ok(TraitItem::Verbatim(verbatim::between(&begin, input)))
|
|
} else {
|
|
Ok(TraitItem::Type(TraitItemType {
|
|
attrs: Vec::new(),
|
|
type_token,
|
|
ident,
|
|
generics,
|
|
colon_token,
|
|
bounds,
|
|
default: ty,
|
|
semi_token,
|
|
}))
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for TraitItemMacro {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let attrs = input.call(Attribute::parse_outer)?;
|
|
let mac: Macro = input.parse()?;
|
|
let semi_token: Option<Token![;]> = if mac.delimiter.is_brace() {
|
|
None
|
|
} else {
|
|
Some(input.parse()?)
|
|
};
|
|
Ok(TraitItemMacro {
|
|
attrs,
|
|
mac,
|
|
semi_token,
|
|
})
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ItemImpl {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let allow_verbatim_impl = false;
|
|
parse_impl(input, allow_verbatim_impl).map(Option::unwrap)
|
|
}
|
|
}
|
|
|
|
fn parse_impl(input: ParseStream, allow_verbatim_impl: bool) -> Result<Option<ItemImpl>> {
|
|
let mut attrs = input.call(Attribute::parse_outer)?;
|
|
let has_visibility = allow_verbatim_impl && input.parse::<Visibility>()?.is_some();
|
|
let defaultness: Option<Token![default]> = input.parse()?;
|
|
let unsafety: Option<Token![unsafe]> = input.parse()?;
|
|
let impl_token: Token![impl] = input.parse()?;
|
|
|
|
let has_generics = generics::parsing::choose_generics_over_qpath(input);
|
|
let mut generics: Generics = if has_generics {
|
|
input.parse()?
|
|
} else {
|
|
Generics::default()
|
|
};
|
|
|
|
let is_const_impl = allow_verbatim_impl
|
|
&& (input.peek(Token![const]) || input.peek(Token![?]) && input.peek2(Token![const]));
|
|
if is_const_impl {
|
|
input.parse::<Option<Token![?]>>()?;
|
|
input.parse::<Token![const]>()?;
|
|
}
|
|
|
|
let polarity = if input.peek(Token![!]) && !input.peek2(token::Brace) {
|
|
Some(input.parse::<Token![!]>()?)
|
|
} else {
|
|
None
|
|
};
|
|
|
|
#[cfg(not(feature = "printing"))]
|
|
let first_ty_span = input.span();
|
|
let mut first_ty: Type = input.parse()?;
|
|
let self_ty: Type;
|
|
let trait_;
|
|
|
|
let is_impl_for = input.peek(Token![for]);
|
|
if is_impl_for {
|
|
let for_token: Token![for] = input.parse()?;
|
|
let mut first_ty_ref = &first_ty;
|
|
while let Type::Group(ty) = first_ty_ref {
|
|
first_ty_ref = &ty.elem;
|
|
}
|
|
if let Type::Path(TypePath { qself: None, .. }) = first_ty_ref {
|
|
while let Type::Group(ty) = first_ty {
|
|
first_ty = *ty.elem;
|
|
}
|
|
if let Type::Path(TypePath { qself: None, path }) = first_ty {
|
|
trait_ = Some((polarity, path, for_token));
|
|
} else {
|
|
unreachable!();
|
|
}
|
|
} else if !allow_verbatim_impl {
|
|
#[cfg(feature = "printing")]
|
|
return Err(Error::new_spanned(first_ty_ref, "expected trait path"));
|
|
#[cfg(not(feature = "printing"))]
|
|
return Err(Error::new(first_ty_span, "expected trait path"));
|
|
} else {
|
|
trait_ = None;
|
|
}
|
|
self_ty = input.parse()?;
|
|
} else if let Some(polarity) = polarity {
|
|
return Err(Error::new(
|
|
polarity.span,
|
|
"inherent impls cannot be negative",
|
|
));
|
|
} else {
|
|
trait_ = None;
|
|
self_ty = first_ty;
|
|
}
|
|
|
|
generics.where_clause = input.parse()?;
|
|
|
|
let content;
|
|
let brace_token = braced!(content in input);
|
|
attr::parsing::parse_inner(&content, &mut attrs)?;
|
|
|
|
let mut items = Vec::new();
|
|
while !content.is_empty() {
|
|
items.push(content.parse()?);
|
|
}
|
|
|
|
if has_visibility || is_const_impl || is_impl_for && trait_.is_none() {
|
|
Ok(None)
|
|
} else {
|
|
Ok(Some(ItemImpl {
|
|
attrs,
|
|
defaultness,
|
|
unsafety,
|
|
impl_token,
|
|
generics,
|
|
trait_,
|
|
self_ty: Box::new(self_ty),
|
|
brace_token,
|
|
items,
|
|
}))
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ImplItem {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let begin = input.fork();
|
|
let mut attrs = input.call(Attribute::parse_outer)?;
|
|
let ahead = input.fork();
|
|
let vis: Visibility = ahead.parse()?;
|
|
|
|
let mut lookahead = ahead.lookahead1();
|
|
let defaultness = if lookahead.peek(Token![default]) && !ahead.peek2(Token![!]) {
|
|
let defaultness: Token![default] = ahead.parse()?;
|
|
lookahead = ahead.lookahead1();
|
|
Some(defaultness)
|
|
} else {
|
|
None
|
|
};
|
|
|
|
let allow_safe = false;
|
|
let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead, allow_safe) {
|
|
let allow_omitted_body = true;
|
|
if let Some(item) = parse_impl_item_fn(input, allow_omitted_body)? {
|
|
Ok(ImplItem::Fn(item))
|
|
} else {
|
|
Ok(ImplItem::Verbatim(verbatim::between(&begin, input)))
|
|
}
|
|
} else if lookahead.peek(Token![const]) {
|
|
input.advance_to(&ahead);
|
|
let const_token: Token![const] = input.parse()?;
|
|
let lookahead = input.lookahead1();
|
|
let ident = if lookahead.peek(Ident) || lookahead.peek(Token![_]) {
|
|
input.call(Ident::parse_any)?
|
|
} else {
|
|
return Err(lookahead.error());
|
|
};
|
|
let mut generics: Generics = input.parse()?;
|
|
let colon_token: Token![:] = input.parse()?;
|
|
let ty: Type = input.parse()?;
|
|
let value = if let Some(eq_token) = input.parse::<Option<Token![=]>>()? {
|
|
let expr: Expr = input.parse()?;
|
|
Some((eq_token, expr))
|
|
} else {
|
|
None
|
|
};
|
|
generics.where_clause = input.parse()?;
|
|
let semi_token: Token![;] = input.parse()?;
|
|
return match value {
|
|
Some((eq_token, expr))
|
|
if generics.lt_token.is_none() && generics.where_clause.is_none() =>
|
|
{
|
|
Ok(ImplItem::Const(ImplItemConst {
|
|
attrs,
|
|
vis,
|
|
defaultness,
|
|
const_token,
|
|
ident,
|
|
generics,
|
|
colon_token,
|
|
ty,
|
|
eq_token,
|
|
expr,
|
|
semi_token,
|
|
}))
|
|
}
|
|
_ => Ok(ImplItem::Verbatim(verbatim::between(&begin, input))),
|
|
};
|
|
} else if lookahead.peek(Token![type]) {
|
|
parse_impl_item_type(begin, input)
|
|
} else if vis.is_inherited()
|
|
&& defaultness.is_none()
|
|
&& (lookahead.peek(Ident)
|
|
|| lookahead.peek(Token![self])
|
|
|| lookahead.peek(Token![super])
|
|
|| lookahead.peek(Token![crate])
|
|
|| lookahead.peek(Token![::]))
|
|
{
|
|
input.parse().map(ImplItem::Macro)
|
|
} else {
|
|
Err(lookahead.error())
|
|
}?;
|
|
|
|
{
|
|
let item_attrs = match &mut item {
|
|
ImplItem::Const(item) => &mut item.attrs,
|
|
ImplItem::Fn(item) => &mut item.attrs,
|
|
ImplItem::Type(item) => &mut item.attrs,
|
|
ImplItem::Macro(item) => &mut item.attrs,
|
|
ImplItem::Verbatim(_) => return Ok(item),
|
|
};
|
|
attrs.append(item_attrs);
|
|
*item_attrs = attrs;
|
|
}
|
|
|
|
Ok(item)
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ImplItemConst {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let attrs = input.call(Attribute::parse_outer)?;
|
|
let vis: Visibility = input.parse()?;
|
|
let defaultness: Option<Token![default]> = input.parse()?;
|
|
let const_token: Token![const] = input.parse()?;
|
|
|
|
let lookahead = input.lookahead1();
|
|
let ident = if lookahead.peek(Ident) || lookahead.peek(Token![_]) {
|
|
input.call(Ident::parse_any)?
|
|
} else {
|
|
return Err(lookahead.error());
|
|
};
|
|
|
|
let colon_token: Token![:] = input.parse()?;
|
|
let ty: Type = input.parse()?;
|
|
let eq_token: Token![=] = input.parse()?;
|
|
let expr: Expr = input.parse()?;
|
|
let semi_token: Token![;] = input.parse()?;
|
|
|
|
Ok(ImplItemConst {
|
|
attrs,
|
|
vis,
|
|
defaultness,
|
|
const_token,
|
|
ident,
|
|
generics: Generics::default(),
|
|
colon_token,
|
|
ty,
|
|
eq_token,
|
|
expr,
|
|
semi_token,
|
|
})
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ImplItemFn {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let allow_omitted_body = false;
|
|
parse_impl_item_fn(input, allow_omitted_body).map(Option::unwrap)
|
|
}
|
|
}
|
|
|
|
fn parse_impl_item_fn(
|
|
input: ParseStream,
|
|
allow_omitted_body: bool,
|
|
) -> Result<Option<ImplItemFn>> {
|
|
let mut attrs = input.call(Attribute::parse_outer)?;
|
|
let vis: Visibility = input.parse()?;
|
|
let defaultness: Option<Token![default]> = input.parse()?;
|
|
let sig: Signature = input.parse()?;
|
|
|
|
// Accept functions without a body in an impl block because rustc's
|
|
// *parser* does not reject them (the compilation error is emitted later
|
|
// than parsing) and it can be useful for macro DSLs.
|
|
if allow_omitted_body && input.parse::<Option<Token![;]>>()?.is_some() {
|
|
return Ok(None);
|
|
}
|
|
|
|
let content;
|
|
let brace_token = braced!(content in input);
|
|
attrs.extend(content.call(Attribute::parse_inner)?);
|
|
let block = Block {
|
|
brace_token,
|
|
stmts: content.call(Block::parse_within)?,
|
|
};
|
|
|
|
Ok(Some(ImplItemFn {
|
|
attrs,
|
|
vis,
|
|
defaultness,
|
|
sig,
|
|
block,
|
|
}))
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ImplItemType {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let attrs = input.call(Attribute::parse_outer)?;
|
|
let vis: Visibility = input.parse()?;
|
|
let defaultness: Option<Token![default]> = input.parse()?;
|
|
let type_token: Token![type] = input.parse()?;
|
|
let ident: Ident = input.parse()?;
|
|
let mut generics: Generics = input.parse()?;
|
|
let eq_token: Token![=] = input.parse()?;
|
|
let ty: Type = input.parse()?;
|
|
generics.where_clause = input.parse()?;
|
|
let semi_token: Token![;] = input.parse()?;
|
|
Ok(ImplItemType {
|
|
attrs,
|
|
vis,
|
|
defaultness,
|
|
type_token,
|
|
ident,
|
|
generics,
|
|
eq_token,
|
|
ty,
|
|
semi_token,
|
|
})
|
|
}
|
|
}
|
|
|
|
fn parse_impl_item_type(begin: ParseBuffer, input: ParseStream) -> Result<ImplItem> {
|
|
let FlexibleItemType {
|
|
vis,
|
|
defaultness,
|
|
type_token,
|
|
ident,
|
|
generics,
|
|
colon_token,
|
|
bounds: _,
|
|
ty,
|
|
semi_token,
|
|
} = FlexibleItemType::parse(
|
|
input,
|
|
TypeDefaultness::Optional,
|
|
WhereClauseLocation::AfterEq,
|
|
)?;
|
|
|
|
let (eq_token, ty) = match ty {
|
|
Some(ty) if colon_token.is_none() => ty,
|
|
_ => return Ok(ImplItem::Verbatim(verbatim::between(&begin, input))),
|
|
};
|
|
|
|
Ok(ImplItem::Type(ImplItemType {
|
|
attrs: Vec::new(),
|
|
vis,
|
|
defaultness,
|
|
type_token,
|
|
ident,
|
|
generics,
|
|
eq_token,
|
|
ty,
|
|
semi_token,
|
|
}))
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for ImplItemMacro {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let attrs = input.call(Attribute::parse_outer)?;
|
|
let mac: Macro = input.parse()?;
|
|
let semi_token: Option<Token![;]> = if mac.delimiter.is_brace() {
|
|
None
|
|
} else {
|
|
Some(input.parse()?)
|
|
};
|
|
Ok(ImplItemMacro {
|
|
attrs,
|
|
mac,
|
|
semi_token,
|
|
})
|
|
}
|
|
}
|
|
|
|
impl Visibility {
|
|
fn is_inherited(&self) -> bool {
|
|
match self {
|
|
Visibility::Inherited => true,
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
|
|
impl Parse for StaticMutability {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let mut_token: Option<Token![mut]> = input.parse()?;
|
|
Ok(mut_token.map_or(StaticMutability::None, StaticMutability::Mut))
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "printing")]
|
|
mod printing {
|
|
use crate::attr::FilterAttrs;
|
|
use crate::data::Fields;
|
|
use crate::item::{
|
|
ForeignItemFn, ForeignItemMacro, ForeignItemStatic, ForeignItemType, ImplItemConst,
|
|
ImplItemFn, ImplItemMacro, ImplItemType, ItemConst, ItemEnum, ItemExternCrate, ItemFn,
|
|
ItemForeignMod, ItemImpl, ItemMacro, ItemMod, ItemStatic, ItemStruct, ItemTrait,
|
|
ItemTraitAlias, ItemType, ItemUnion, ItemUse, Receiver, Signature, StaticMutability,
|
|
TraitItemConst, TraitItemFn, TraitItemMacro, TraitItemType, UseGlob, UseGroup, UseName,
|
|
UsePath, UseRename, Variadic,
|
|
};
|
|
use crate::mac::MacroDelimiter;
|
|
use crate::path;
|
|
use crate::path::printing::PathStyle;
|
|
use crate::print::TokensOrDefault;
|
|
use crate::ty::Type;
|
|
use proc_macro2::TokenStream;
|
|
use quote::{ToTokens, TokenStreamExt};
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ItemExternCrate {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.vis.to_tokens(tokens);
|
|
self.extern_token.to_tokens(tokens);
|
|
self.crate_token.to_tokens(tokens);
|
|
self.ident.to_tokens(tokens);
|
|
if let Some((as_token, rename)) = &self.rename {
|
|
as_token.to_tokens(tokens);
|
|
rename.to_tokens(tokens);
|
|
}
|
|
self.semi_token.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ItemUse {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.vis.to_tokens(tokens);
|
|
self.use_token.to_tokens(tokens);
|
|
self.leading_colon.to_tokens(tokens);
|
|
self.tree.to_tokens(tokens);
|
|
self.semi_token.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ItemStatic {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.vis.to_tokens(tokens);
|
|
self.static_token.to_tokens(tokens);
|
|
self.mutability.to_tokens(tokens);
|
|
self.ident.to_tokens(tokens);
|
|
self.colon_token.to_tokens(tokens);
|
|
self.ty.to_tokens(tokens);
|
|
self.eq_token.to_tokens(tokens);
|
|
self.expr.to_tokens(tokens);
|
|
self.semi_token.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ItemConst {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.vis.to_tokens(tokens);
|
|
self.const_token.to_tokens(tokens);
|
|
self.ident.to_tokens(tokens);
|
|
self.colon_token.to_tokens(tokens);
|
|
self.ty.to_tokens(tokens);
|
|
self.eq_token.to_tokens(tokens);
|
|
self.expr.to_tokens(tokens);
|
|
self.semi_token.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ItemFn {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.vis.to_tokens(tokens);
|
|
self.sig.to_tokens(tokens);
|
|
self.block.brace_token.surround(tokens, |tokens| {
|
|
tokens.append_all(self.attrs.inner());
|
|
tokens.append_all(&self.block.stmts);
|
|
});
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ItemMod {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.vis.to_tokens(tokens);
|
|
self.unsafety.to_tokens(tokens);
|
|
self.mod_token.to_tokens(tokens);
|
|
self.ident.to_tokens(tokens);
|
|
if let Some((brace, items)) = &self.content {
|
|
brace.surround(tokens, |tokens| {
|
|
tokens.append_all(self.attrs.inner());
|
|
tokens.append_all(items);
|
|
});
|
|
} else {
|
|
TokensOrDefault(&self.semi).to_tokens(tokens);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ItemForeignMod {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.unsafety.to_tokens(tokens);
|
|
self.abi.to_tokens(tokens);
|
|
self.brace_token.surround(tokens, |tokens| {
|
|
tokens.append_all(self.attrs.inner());
|
|
tokens.append_all(&self.items);
|
|
});
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ItemType {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.vis.to_tokens(tokens);
|
|
self.type_token.to_tokens(tokens);
|
|
self.ident.to_tokens(tokens);
|
|
self.generics.to_tokens(tokens);
|
|
self.generics.where_clause.to_tokens(tokens);
|
|
self.eq_token.to_tokens(tokens);
|
|
self.ty.to_tokens(tokens);
|
|
self.semi_token.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ItemEnum {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.vis.to_tokens(tokens);
|
|
self.enum_token.to_tokens(tokens);
|
|
self.ident.to_tokens(tokens);
|
|
self.generics.to_tokens(tokens);
|
|
self.generics.where_clause.to_tokens(tokens);
|
|
self.brace_token.surround(tokens, |tokens| {
|
|
self.variants.to_tokens(tokens);
|
|
});
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ItemStruct {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.vis.to_tokens(tokens);
|
|
self.struct_token.to_tokens(tokens);
|
|
self.ident.to_tokens(tokens);
|
|
self.generics.to_tokens(tokens);
|
|
match &self.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(&self.semi_token).to_tokens(tokens);
|
|
}
|
|
Fields::Unit => {
|
|
self.generics.where_clause.to_tokens(tokens);
|
|
TokensOrDefault(&self.semi_token).to_tokens(tokens);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ItemUnion {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.vis.to_tokens(tokens);
|
|
self.union_token.to_tokens(tokens);
|
|
self.ident.to_tokens(tokens);
|
|
self.generics.to_tokens(tokens);
|
|
self.generics.where_clause.to_tokens(tokens);
|
|
self.fields.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ItemTrait {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.vis.to_tokens(tokens);
|
|
self.unsafety.to_tokens(tokens);
|
|
self.auto_token.to_tokens(tokens);
|
|
self.trait_token.to_tokens(tokens);
|
|
self.ident.to_tokens(tokens);
|
|
self.generics.to_tokens(tokens);
|
|
if !self.supertraits.is_empty() {
|
|
TokensOrDefault(&self.colon_token).to_tokens(tokens);
|
|
self.supertraits.to_tokens(tokens);
|
|
}
|
|
self.generics.where_clause.to_tokens(tokens);
|
|
self.brace_token.surround(tokens, |tokens| {
|
|
tokens.append_all(self.attrs.inner());
|
|
tokens.append_all(&self.items);
|
|
});
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ItemTraitAlias {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.vis.to_tokens(tokens);
|
|
self.trait_token.to_tokens(tokens);
|
|
self.ident.to_tokens(tokens);
|
|
self.generics.to_tokens(tokens);
|
|
self.eq_token.to_tokens(tokens);
|
|
self.bounds.to_tokens(tokens);
|
|
self.generics.where_clause.to_tokens(tokens);
|
|
self.semi_token.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ItemImpl {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.defaultness.to_tokens(tokens);
|
|
self.unsafety.to_tokens(tokens);
|
|
self.impl_token.to_tokens(tokens);
|
|
self.generics.to_tokens(tokens);
|
|
if let Some((polarity, path, for_token)) = &self.trait_ {
|
|
polarity.to_tokens(tokens);
|
|
path.to_tokens(tokens);
|
|
for_token.to_tokens(tokens);
|
|
}
|
|
self.self_ty.to_tokens(tokens);
|
|
self.generics.where_clause.to_tokens(tokens);
|
|
self.brace_token.surround(tokens, |tokens| {
|
|
tokens.append_all(self.attrs.inner());
|
|
tokens.append_all(&self.items);
|
|
});
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ItemMacro {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
path::printing::print_path(tokens, &self.mac.path, PathStyle::Mod);
|
|
self.mac.bang_token.to_tokens(tokens);
|
|
self.ident.to_tokens(tokens);
|
|
match &self.mac.delimiter {
|
|
MacroDelimiter::Paren(paren) => {
|
|
paren.surround(tokens, |tokens| self.mac.tokens.to_tokens(tokens));
|
|
}
|
|
MacroDelimiter::Brace(brace) => {
|
|
brace.surround(tokens, |tokens| self.mac.tokens.to_tokens(tokens));
|
|
}
|
|
MacroDelimiter::Bracket(bracket) => {
|
|
bracket.surround(tokens, |tokens| self.mac.tokens.to_tokens(tokens));
|
|
}
|
|
}
|
|
self.semi_token.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for UsePath {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
self.ident.to_tokens(tokens);
|
|
self.colon2_token.to_tokens(tokens);
|
|
self.tree.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for UseName {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
self.ident.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for UseRename {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
self.ident.to_tokens(tokens);
|
|
self.as_token.to_tokens(tokens);
|
|
self.rename.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for UseGlob {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
self.star_token.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for UseGroup {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
self.brace_token.surround(tokens, |tokens| {
|
|
self.items.to_tokens(tokens);
|
|
});
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for TraitItemConst {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.const_token.to_tokens(tokens);
|
|
self.ident.to_tokens(tokens);
|
|
self.colon_token.to_tokens(tokens);
|
|
self.ty.to_tokens(tokens);
|
|
if let Some((eq_token, default)) = &self.default {
|
|
eq_token.to_tokens(tokens);
|
|
default.to_tokens(tokens);
|
|
}
|
|
self.semi_token.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for TraitItemFn {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.sig.to_tokens(tokens);
|
|
match &self.default {
|
|
Some(block) => {
|
|
block.brace_token.surround(tokens, |tokens| {
|
|
tokens.append_all(self.attrs.inner());
|
|
tokens.append_all(&block.stmts);
|
|
});
|
|
}
|
|
None => {
|
|
TokensOrDefault(&self.semi_token).to_tokens(tokens);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for TraitItemType {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.type_token.to_tokens(tokens);
|
|
self.ident.to_tokens(tokens);
|
|
self.generics.to_tokens(tokens);
|
|
if !self.bounds.is_empty() {
|
|
TokensOrDefault(&self.colon_token).to_tokens(tokens);
|
|
self.bounds.to_tokens(tokens);
|
|
}
|
|
if let Some((eq_token, default)) = &self.default {
|
|
eq_token.to_tokens(tokens);
|
|
default.to_tokens(tokens);
|
|
}
|
|
self.generics.where_clause.to_tokens(tokens);
|
|
self.semi_token.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for TraitItemMacro {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.mac.to_tokens(tokens);
|
|
self.semi_token.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ImplItemConst {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.vis.to_tokens(tokens);
|
|
self.defaultness.to_tokens(tokens);
|
|
self.const_token.to_tokens(tokens);
|
|
self.ident.to_tokens(tokens);
|
|
self.colon_token.to_tokens(tokens);
|
|
self.ty.to_tokens(tokens);
|
|
self.eq_token.to_tokens(tokens);
|
|
self.expr.to_tokens(tokens);
|
|
self.semi_token.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ImplItemFn {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.vis.to_tokens(tokens);
|
|
self.defaultness.to_tokens(tokens);
|
|
self.sig.to_tokens(tokens);
|
|
self.block.brace_token.surround(tokens, |tokens| {
|
|
tokens.append_all(self.attrs.inner());
|
|
tokens.append_all(&self.block.stmts);
|
|
});
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ImplItemType {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.vis.to_tokens(tokens);
|
|
self.defaultness.to_tokens(tokens);
|
|
self.type_token.to_tokens(tokens);
|
|
self.ident.to_tokens(tokens);
|
|
self.generics.to_tokens(tokens);
|
|
self.eq_token.to_tokens(tokens);
|
|
self.ty.to_tokens(tokens);
|
|
self.generics.where_clause.to_tokens(tokens);
|
|
self.semi_token.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ImplItemMacro {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.mac.to_tokens(tokens);
|
|
self.semi_token.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ForeignItemFn {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.vis.to_tokens(tokens);
|
|
self.sig.to_tokens(tokens);
|
|
self.semi_token.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ForeignItemStatic {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.vis.to_tokens(tokens);
|
|
self.static_token.to_tokens(tokens);
|
|
self.mutability.to_tokens(tokens);
|
|
self.ident.to_tokens(tokens);
|
|
self.colon_token.to_tokens(tokens);
|
|
self.ty.to_tokens(tokens);
|
|
self.semi_token.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ForeignItemType {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.vis.to_tokens(tokens);
|
|
self.type_token.to_tokens(tokens);
|
|
self.ident.to_tokens(tokens);
|
|
self.generics.to_tokens(tokens);
|
|
self.generics.where_clause.to_tokens(tokens);
|
|
self.semi_token.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for ForeignItemMacro {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
self.mac.to_tokens(tokens);
|
|
self.semi_token.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for Signature {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
self.constness.to_tokens(tokens);
|
|
self.asyncness.to_tokens(tokens);
|
|
self.unsafety.to_tokens(tokens);
|
|
self.abi.to_tokens(tokens);
|
|
self.fn_token.to_tokens(tokens);
|
|
self.ident.to_tokens(tokens);
|
|
self.generics.to_tokens(tokens);
|
|
self.paren_token.surround(tokens, |tokens| {
|
|
self.inputs.to_tokens(tokens);
|
|
if let Some(variadic) = &self.variadic {
|
|
if !self.inputs.empty_or_trailing() {
|
|
<Token![,]>::default().to_tokens(tokens);
|
|
}
|
|
variadic.to_tokens(tokens);
|
|
}
|
|
});
|
|
self.output.to_tokens(tokens);
|
|
self.generics.where_clause.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for Receiver {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
if let Some((ampersand, lifetime)) = &self.reference {
|
|
ampersand.to_tokens(tokens);
|
|
lifetime.to_tokens(tokens);
|
|
}
|
|
self.mutability.to_tokens(tokens);
|
|
self.self_token.to_tokens(tokens);
|
|
if let Some(colon_token) = &self.colon_token {
|
|
colon_token.to_tokens(tokens);
|
|
self.ty.to_tokens(tokens);
|
|
} else {
|
|
let consistent = match (&self.reference, &self.mutability, &*self.ty) {
|
|
(Some(_), mutability, Type::Reference(ty)) => {
|
|
mutability.is_some() == ty.mutability.is_some()
|
|
&& match &*ty.elem {
|
|
Type::Path(ty) => ty.qself.is_none() && ty.path.is_ident("Self"),
|
|
_ => false,
|
|
}
|
|
}
|
|
(None, _, Type::Path(ty)) => ty.qself.is_none() && ty.path.is_ident("Self"),
|
|
_ => false,
|
|
};
|
|
if !consistent {
|
|
<Token![:]>::default().to_tokens(tokens);
|
|
self.ty.to_tokens(tokens);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for Variadic {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
tokens.append_all(self.attrs.outer());
|
|
if let Some((pat, colon)) = &self.pat {
|
|
pat.to_tokens(tokens);
|
|
colon.to_tokens(tokens);
|
|
}
|
|
self.dots.to_tokens(tokens);
|
|
self.comma.to_tokens(tokens);
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
|
|
impl ToTokens for StaticMutability {
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
match self {
|
|
StaticMutability::None => {}
|
|
StaticMutability::Mut(mut_token) => mut_token.to_tokens(tokens),
|
|
}
|
|
}
|
|
}
|
|
}
|