RPM build fix (reverted CI changes which will need to be un-reverted or made conditional) and vendor Rust dependencies to make builds much faster in any CI system.
This commit is contained in:
662
zeroidc/vendor/syn/src/attr.rs
vendored
Normal file
662
zeroidc/vendor/syn/src/attr.rs
vendored
Normal file
@@ -0,0 +1,662 @@
|
||||
use super::*;
|
||||
use crate::punctuated::Punctuated;
|
||||
use proc_macro2::TokenStream;
|
||||
use std::iter;
|
||||
use std::slice;
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
use crate::parse::{Parse, ParseBuffer, ParseStream, Parser, Result};
|
||||
#[cfg(feature = "parsing")]
|
||||
use crate::punctuated::Pair;
|
||||
|
||||
ast_struct! {
|
||||
/// An attribute like `#[repr(transparent)]`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
|
||||
/// feature.*
|
||||
///
|
||||
/// <br>
|
||||
///
|
||||
/// # Syntax
|
||||
///
|
||||
/// Rust has six types of attributes.
|
||||
///
|
||||
/// - Outer attributes like `#[repr(transparent)]`. These appear outside or
|
||||
/// in front of the item they describe.
|
||||
/// - Inner attributes like `#![feature(proc_macro)]`. These appear inside
|
||||
/// of the item they describe, usually a module.
|
||||
/// - Outer doc comments like `/// # Example`.
|
||||
/// - Inner doc comments like `//! Please file an issue`.
|
||||
/// - Outer block comments `/** # Example */`.
|
||||
/// - Inner block comments `/*! Please file an issue */`.
|
||||
///
|
||||
/// The `style` field of type `AttrStyle` distinguishes whether an attribute
|
||||
/// is outer or inner. Doc comments and block comments are promoted to
|
||||
/// attributes, as this is how they are processed by the compiler and by
|
||||
/// `macro_rules!` macros.
|
||||
///
|
||||
/// The `path` field gives the possibly colon-delimited path against which
|
||||
/// the attribute is resolved. It is equal to `"doc"` for desugared doc
|
||||
/// comments. The `tokens` field contains the rest of the attribute body as
|
||||
/// tokens.
|
||||
///
|
||||
/// ```text
|
||||
/// #[derive(Copy)] #[crate::precondition x < 5]
|
||||
/// ^^^^^^~~~~~~ ^^^^^^^^^^^^^^^^^^^ ~~~~~
|
||||
/// path tokens path tokens
|
||||
/// ```
|
||||
///
|
||||
/// <br>
|
||||
///
|
||||
/// # Parsing from tokens to Attribute
|
||||
///
|
||||
/// This type does not implement the [`Parse`] trait and thus cannot be
|
||||
/// parsed directly by [`ParseStream::parse`]. Instead use
|
||||
/// [`ParseStream::call`] with one of the two parser functions
|
||||
/// [`Attribute::parse_outer`] or [`Attribute::parse_inner`] depending on
|
||||
/// which you intend to parse.
|
||||
///
|
||||
/// [`Parse`]: parse::Parse
|
||||
/// [`ParseStream::parse`]: parse::ParseBuffer::parse
|
||||
/// [`ParseStream::call`]: parse::ParseBuffer::call
|
||||
///
|
||||
/// ```
|
||||
/// use syn::{Attribute, Ident, Result, Token};
|
||||
/// use syn::parse::{Parse, ParseStream};
|
||||
///
|
||||
/// // Parses a unit struct with attributes.
|
||||
/// //
|
||||
/// // #[path = "s.tmpl"]
|
||||
/// // struct S;
|
||||
/// struct UnitStruct {
|
||||
/// attrs: Vec<Attribute>,
|
||||
/// struct_token: Token![struct],
|
||||
/// name: Ident,
|
||||
/// semi_token: Token![;],
|
||||
/// }
|
||||
///
|
||||
/// impl Parse for UnitStruct {
|
||||
/// fn parse(input: ParseStream) -> Result<Self> {
|
||||
/// Ok(UnitStruct {
|
||||
/// attrs: input.call(Attribute::parse_outer)?,
|
||||
/// struct_token: input.parse()?,
|
||||
/// name: input.parse()?,
|
||||
/// semi_token: input.parse()?,
|
||||
/// })
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// <p><br></p>
|
||||
///
|
||||
/// # Parsing from Attribute to structured arguments
|
||||
///
|
||||
/// The grammar of attributes in Rust is very flexible, which makes the
|
||||
/// syntax tree not that useful on its own. In particular, arguments of the
|
||||
/// attribute are held in an arbitrary `tokens: TokenStream`. Macros are
|
||||
/// expected to check the `path` of the attribute, decide whether they
|
||||
/// recognize it, and then parse the remaining tokens according to whatever
|
||||
/// grammar they wish to require for that kind of attribute.
|
||||
///
|
||||
/// If the attribute you are parsing is expected to conform to the
|
||||
/// conventional structured form of attribute, use [`parse_meta()`] to
|
||||
/// obtain that structured representation. If the attribute follows some
|
||||
/// other grammar of its own, use [`parse_args()`] to parse that into the
|
||||
/// expected data structure.
|
||||
///
|
||||
/// [`parse_meta()`]: Attribute::parse_meta
|
||||
/// [`parse_args()`]: Attribute::parse_args
|
||||
///
|
||||
/// <p><br></p>
|
||||
///
|
||||
/// # Doc comments
|
||||
///
|
||||
/// The compiler transforms doc comments, such as `/// comment` and `/*!
|
||||
/// comment */`, into attributes before macros are expanded. Each comment is
|
||||
/// expanded into an attribute of the form `#[doc = r"comment"]`.
|
||||
///
|
||||
/// As an example, the following `mod` items are expanded identically:
|
||||
///
|
||||
/// ```
|
||||
/// # use syn::{ItemMod, parse_quote};
|
||||
/// let doc: ItemMod = parse_quote! {
|
||||
/// /// Single line doc comments
|
||||
/// /// We write so many!
|
||||
/// /**
|
||||
/// * Multi-line comments...
|
||||
/// * May span many lines
|
||||
/// */
|
||||
/// mod example {
|
||||
/// //! Of course, they can be inner too
|
||||
/// /*! And fit in a single line */
|
||||
/// }
|
||||
/// };
|
||||
/// let attr: ItemMod = parse_quote! {
|
||||
/// #[doc = r" Single line doc comments"]
|
||||
/// #[doc = r" We write so many!"]
|
||||
/// #[doc = r"
|
||||
/// * Multi-line comments...
|
||||
/// * May span many lines
|
||||
/// "]
|
||||
/// mod example {
|
||||
/// #![doc = r" Of course, they can be inner too"]
|
||||
/// #![doc = r" And fit in a single line "]
|
||||
/// }
|
||||
/// };
|
||||
/// assert_eq!(doc, attr);
|
||||
/// ```
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub struct Attribute {
|
||||
pub pound_token: Token![#],
|
||||
pub style: AttrStyle,
|
||||
pub bracket_token: token::Bracket,
|
||||
pub path: Path,
|
||||
pub tokens: TokenStream,
|
||||
}
|
||||
}
|
||||
|
||||
impl Attribute {
|
||||
/// Parses the content of the attribute, consisting of the path and tokens,
|
||||
/// as a [`Meta`] if possible.
|
||||
///
|
||||
/// *This function is available only if Syn is built with the `"parsing"`
|
||||
/// feature.*
|
||||
#[cfg(feature = "parsing")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
pub fn parse_meta(&self) -> Result<Meta> {
|
||||
fn clone_ident_segment(segment: &PathSegment) -> PathSegment {
|
||||
PathSegment {
|
||||
ident: segment.ident.clone(),
|
||||
arguments: PathArguments::None,
|
||||
}
|
||||
}
|
||||
|
||||
let path = Path {
|
||||
leading_colon: self
|
||||
.path
|
||||
.leading_colon
|
||||
.as_ref()
|
||||
.map(|colon| Token),
|
||||
segments: self
|
||||
.path
|
||||
.segments
|
||||
.pairs()
|
||||
.map(|pair| match pair {
|
||||
Pair::Punctuated(seg, punct) => {
|
||||
Pair::Punctuated(clone_ident_segment(seg), Token)
|
||||
}
|
||||
Pair::End(seg) => Pair::End(clone_ident_segment(seg)),
|
||||
})
|
||||
.collect(),
|
||||
};
|
||||
|
||||
let parser = |input: ParseStream| parsing::parse_meta_after_path(path, input);
|
||||
parse::Parser::parse2(parser, self.tokens.clone())
|
||||
}
|
||||
|
||||
/// Parse the arguments to the attribute as a syntax tree.
|
||||
///
|
||||
/// This is similar to `syn::parse2::<T>(attr.tokens)` except that:
|
||||
///
|
||||
/// - the surrounding delimiters are *not* included in the input to the
|
||||
/// parser; and
|
||||
/// - the error message has a more useful span when `tokens` is empty.
|
||||
///
|
||||
/// ```text
|
||||
/// #[my_attr(value < 5)]
|
||||
/// ^^^^^^^^^ what gets parsed
|
||||
/// ```
|
||||
///
|
||||
/// *This function is available only if Syn is built with the `"parsing"`
|
||||
/// feature.*
|
||||
#[cfg(feature = "parsing")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
pub fn parse_args<T: Parse>(&self) -> Result<T> {
|
||||
self.parse_args_with(T::parse)
|
||||
}
|
||||
|
||||
/// Parse the arguments to the attribute using the given parser.
|
||||
///
|
||||
/// *This function is available only if Syn is built with the `"parsing"`
|
||||
/// feature.*
|
||||
#[cfg(feature = "parsing")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
pub fn parse_args_with<F: Parser>(&self, parser: F) -> Result<F::Output> {
|
||||
let parser = |input: ParseStream| {
|
||||
let args = enter_args(self, input)?;
|
||||
parse::parse_stream(parser, &args)
|
||||
};
|
||||
parser.parse2(self.tokens.clone())
|
||||
}
|
||||
|
||||
/// Parses zero or more outer attributes from the stream.
|
||||
///
|
||||
/// *This function is available only if Syn is built with the `"parsing"`
|
||||
/// feature.*
|
||||
#[cfg(feature = "parsing")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
pub fn parse_outer(input: ParseStream) -> Result<Vec<Self>> {
|
||||
let mut attrs = Vec::new();
|
||||
while input.peek(Token![#]) {
|
||||
attrs.push(input.call(parsing::single_parse_outer)?);
|
||||
}
|
||||
Ok(attrs)
|
||||
}
|
||||
|
||||
/// Parses zero or more inner attributes from the stream.
|
||||
///
|
||||
/// *This function is available only if Syn is built with the `"parsing"`
|
||||
/// feature.*
|
||||
#[cfg(feature = "parsing")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
pub fn parse_inner(input: ParseStream) -> Result<Vec<Self>> {
|
||||
let mut attrs = Vec::new();
|
||||
parsing::parse_inner(input, &mut attrs)?;
|
||||
Ok(attrs)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
fn expected_parentheses(attr: &Attribute) -> String {
|
||||
let style = match attr.style {
|
||||
AttrStyle::Outer => "#",
|
||||
AttrStyle::Inner(_) => "#!",
|
||||
};
|
||||
|
||||
let mut path = String::new();
|
||||
for segment in &attr.path.segments {
|
||||
if !path.is_empty() || attr.path.leading_colon.is_some() {
|
||||
path += "::";
|
||||
}
|
||||
path += &segment.ident.to_string();
|
||||
}
|
||||
|
||||
format!("{}[{}(...)]", style, path)
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
fn enter_args<'a>(attr: &Attribute, input: ParseStream<'a>) -> Result<ParseBuffer<'a>> {
|
||||
if input.is_empty() {
|
||||
let expected = expected_parentheses(attr);
|
||||
let msg = format!("expected attribute arguments in parentheses: {}", expected);
|
||||
return Err(crate::error::new2(
|
||||
attr.pound_token.span,
|
||||
attr.bracket_token.span,
|
||||
msg,
|
||||
));
|
||||
} else if input.peek(Token![=]) {
|
||||
let expected = expected_parentheses(attr);
|
||||
let msg = format!("expected parentheses: {}", expected);
|
||||
return Err(input.error(msg));
|
||||
};
|
||||
|
||||
let content;
|
||||
if input.peek(token::Paren) {
|
||||
parenthesized!(content in input);
|
||||
} else if input.peek(token::Bracket) {
|
||||
bracketed!(content in input);
|
||||
} else if input.peek(token::Brace) {
|
||||
braced!(content in input);
|
||||
} else {
|
||||
return Err(input.error("unexpected token in attribute arguments"));
|
||||
}
|
||||
|
||||
if input.is_empty() {
|
||||
Ok(content)
|
||||
} else {
|
||||
Err(input.error("unexpected token in attribute arguments"))
|
||||
}
|
||||
}
|
||||
|
||||
ast_enum! {
|
||||
/// Distinguishes between attributes that decorate an item and attributes
|
||||
/// that are contained within an item.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
|
||||
/// feature.*
|
||||
///
|
||||
/// # Outer attributes
|
||||
///
|
||||
/// - `#[repr(transparent)]`
|
||||
/// - `/// # Example`
|
||||
/// - `/** Please file an issue */`
|
||||
///
|
||||
/// # Inner attributes
|
||||
///
|
||||
/// - `#![feature(proc_macro)]`
|
||||
/// - `//! # Example`
|
||||
/// - `/*! Please file an issue */`
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub enum AttrStyle {
|
||||
Outer,
|
||||
Inner(Token![!]),
|
||||
}
|
||||
}
|
||||
|
||||
ast_enum_of_structs! {
|
||||
/// Content of a compile-time structured attribute.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
|
||||
/// feature.*
|
||||
///
|
||||
/// ## Path
|
||||
///
|
||||
/// A meta path is like the `test` in `#[test]`.
|
||||
///
|
||||
/// ## List
|
||||
///
|
||||
/// A meta list is like the `derive(Copy)` in `#[derive(Copy)]`.
|
||||
///
|
||||
/// ## NameValue
|
||||
///
|
||||
/// A name-value meta is like the `path = "..."` in `#[path =
|
||||
/// "sys/windows.rs"]`.
|
||||
///
|
||||
/// # Syntax tree enum
|
||||
///
|
||||
/// This type is a [syntax tree enum].
|
||||
///
|
||||
/// [syntax tree enum]: Expr#syntax-tree-enums
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub enum Meta {
|
||||
Path(Path),
|
||||
|
||||
/// A structured list within an attribute, like `derive(Copy, Clone)`.
|
||||
List(MetaList),
|
||||
|
||||
/// A name-value pair within an attribute, like `feature = "nightly"`.
|
||||
NameValue(MetaNameValue),
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A structured list within an attribute, like `derive(Copy, Clone)`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or
|
||||
/// `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub struct MetaList {
|
||||
pub path: Path,
|
||||
pub paren_token: token::Paren,
|
||||
pub nested: Punctuated<NestedMeta, Token![,]>,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A name-value pair within an attribute, like `feature = "nightly"`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or
|
||||
/// `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub struct MetaNameValue {
|
||||
pub path: Path,
|
||||
pub eq_token: Token![=],
|
||||
pub lit: Lit,
|
||||
}
|
||||
}
|
||||
|
||||
impl Meta {
|
||||
/// Returns the identifier that begins this structured meta item.
|
||||
///
|
||||
/// For example this would return the `test` in `#[test]`, the `derive` in
|
||||
/// `#[derive(Copy)]`, and the `path` in `#[path = "sys/windows.rs"]`.
|
||||
pub fn path(&self) -> &Path {
|
||||
match self {
|
||||
Meta::Path(path) => path,
|
||||
Meta::List(meta) => &meta.path,
|
||||
Meta::NameValue(meta) => &meta.path,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ast_enum_of_structs! {
|
||||
/// Element of a compile-time attribute list.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
|
||||
/// feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub enum NestedMeta {
|
||||
/// A structured meta item, like the `Copy` in `#[derive(Copy)]` which
|
||||
/// would be a nested `Meta::Path`.
|
||||
Meta(Meta),
|
||||
|
||||
/// A Rust literal, like the `"new_name"` in `#[rename("new_name")]`.
|
||||
Lit(Lit),
|
||||
}
|
||||
}
|
||||
|
||||
/// Conventional argument type associated with an invocation of an attribute
|
||||
/// macro.
|
||||
///
|
||||
/// For example if we are developing an attribute macro that is intended to be
|
||||
/// invoked on function items as follows:
|
||||
///
|
||||
/// ```
|
||||
/// # const IGNORE: &str = stringify! {
|
||||
/// #[my_attribute(path = "/v1/refresh")]
|
||||
/// # };
|
||||
/// pub fn refresh() {
|
||||
/// /* ... */
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The implementation of this macro would want to parse its attribute arguments
|
||||
/// as type `AttributeArgs`.
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate proc_macro;
|
||||
/// #
|
||||
/// use proc_macro::TokenStream;
|
||||
/// use syn::{parse_macro_input, AttributeArgs, ItemFn};
|
||||
///
|
||||
/// # const IGNORE: &str = stringify! {
|
||||
/// #[proc_macro_attribute]
|
||||
/// # };
|
||||
/// pub fn my_attribute(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
/// let args = parse_macro_input!(args as AttributeArgs);
|
||||
/// let input = parse_macro_input!(input as ItemFn);
|
||||
///
|
||||
/// /* ... */
|
||||
/// # "".parse().unwrap()
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub type AttributeArgs = Vec<NestedMeta>;
|
||||
|
||||
pub trait FilterAttrs<'a> {
|
||||
type Ret: Iterator<Item = &'a Attribute>;
|
||||
|
||||
fn outer(self) -> Self::Ret;
|
||||
fn inner(self) -> Self::Ret;
|
||||
}
|
||||
|
||||
impl<'a> FilterAttrs<'a> for &'a [Attribute] {
|
||||
type Ret = iter::Filter<slice::Iter<'a, Attribute>, fn(&&Attribute) -> bool>;
|
||||
|
||||
fn outer(self) -> Self::Ret {
|
||||
fn is_outer(attr: &&Attribute) -> bool {
|
||||
match attr.style {
|
||||
AttrStyle::Outer => true,
|
||||
AttrStyle::Inner(_) => false,
|
||||
}
|
||||
}
|
||||
self.iter().filter(is_outer)
|
||||
}
|
||||
|
||||
fn inner(self) -> Self::Ret {
|
||||
fn is_inner(attr: &&Attribute) -> bool {
|
||||
match attr.style {
|
||||
AttrStyle::Inner(_) => true,
|
||||
AttrStyle::Outer => false,
|
||||
}
|
||||
}
|
||||
self.iter().filter(is_inner)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
pub mod parsing {
|
||||
use super::*;
|
||||
use crate::ext::IdentExt;
|
||||
use crate::parse::{Parse, ParseStream, Result};
|
||||
|
||||
pub fn parse_inner(input: ParseStream, attrs: &mut Vec<Attribute>) -> Result<()> {
|
||||
while input.peek(Token![#]) && input.peek2(Token![!]) {
|
||||
attrs.push(input.call(parsing::single_parse_inner)?);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn single_parse_inner(input: ParseStream) -> Result<Attribute> {
|
||||
let content;
|
||||
Ok(Attribute {
|
||||
pound_token: input.parse()?,
|
||||
style: AttrStyle::Inner(input.parse()?),
|
||||
bracket_token: bracketed!(content in input),
|
||||
path: content.call(Path::parse_mod_style)?,
|
||||
tokens: content.parse()?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn single_parse_outer(input: ParseStream) -> Result<Attribute> {
|
||||
let content;
|
||||
Ok(Attribute {
|
||||
pound_token: input.parse()?,
|
||||
style: AttrStyle::Outer,
|
||||
bracket_token: bracketed!(content in input),
|
||||
path: content.call(Path::parse_mod_style)?,
|
||||
tokens: content.parse()?,
|
||||
})
|
||||
}
|
||||
|
||||
// Like Path::parse_mod_style but accepts keywords in the path.
|
||||
fn parse_meta_path(input: ParseStream) -> Result<Path> {
|
||||
Ok(Path {
|
||||
leading_colon: input.parse()?,
|
||||
segments: {
|
||||
let mut segments = Punctuated::new();
|
||||
while input.peek(Ident::peek_any) {
|
||||
let ident = Ident::parse_any(input)?;
|
||||
segments.push_value(PathSegment::from(ident));
|
||||
if !input.peek(Token![::]) {
|
||||
break;
|
||||
}
|
||||
let punct = input.parse()?;
|
||||
segments.push_punct(punct);
|
||||
}
|
||||
if segments.is_empty() {
|
||||
return Err(input.error("expected path"));
|
||||
} else if segments.trailing_punct() {
|
||||
return Err(input.error("expected path segment"));
|
||||
}
|
||||
segments
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for Meta {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let path = input.call(parse_meta_path)?;
|
||||
parse_meta_after_path(path, input)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for MetaList {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let path = input.call(parse_meta_path)?;
|
||||
parse_meta_list_after_path(path, input)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for MetaNameValue {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let path = input.call(parse_meta_path)?;
|
||||
parse_meta_name_value_after_path(path, input)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for NestedMeta {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
if input.peek(Lit) && !(input.peek(LitBool) && input.peek2(Token![=])) {
|
||||
input.parse().map(NestedMeta::Lit)
|
||||
} else if input.peek(Ident::peek_any)
|
||||
|| input.peek(Token![::]) && input.peek3(Ident::peek_any)
|
||||
{
|
||||
input.parse().map(NestedMeta::Meta)
|
||||
} else {
|
||||
Err(input.error("expected identifier or literal"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_meta_after_path(path: Path, input: ParseStream) -> Result<Meta> {
|
||||
if input.peek(token::Paren) {
|
||||
parse_meta_list_after_path(path, input).map(Meta::List)
|
||||
} else if input.peek(Token![=]) {
|
||||
parse_meta_name_value_after_path(path, input).map(Meta::NameValue)
|
||||
} else {
|
||||
Ok(Meta::Path(path))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_meta_list_after_path(path: Path, input: ParseStream) -> Result<MetaList> {
|
||||
let content;
|
||||
Ok(MetaList {
|
||||
path,
|
||||
paren_token: parenthesized!(content in input),
|
||||
nested: content.parse_terminated(NestedMeta::parse)?,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_meta_name_value_after_path(path: Path, input: ParseStream) -> Result<MetaNameValue> {
|
||||
Ok(MetaNameValue {
|
||||
path,
|
||||
eq_token: input.parse()?,
|
||||
lit: input.parse()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "printing")]
|
||||
mod printing {
|
||||
use super::*;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::ToTokens;
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for Attribute {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.pound_token.to_tokens(tokens);
|
||||
if let AttrStyle::Inner(b) = &self.style {
|
||||
b.to_tokens(tokens);
|
||||
}
|
||||
self.bracket_token.surround(tokens, |tokens| {
|
||||
self.path.to_tokens(tokens);
|
||||
self.tokens.to_tokens(tokens);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for MetaList {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.path.to_tokens(tokens);
|
||||
self.paren_token.surround(tokens, |tokens| {
|
||||
self.nested.to_tokens(tokens);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for MetaNameValue {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.path.to_tokens(tokens);
|
||||
self.eq_token.to_tokens(tokens);
|
||||
self.lit.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
}
|
||||
2
zeroidc/vendor/syn/src/await.rs
vendored
Normal file
2
zeroidc/vendor/syn/src/await.rs
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
// See include!("await.rs") in token.rs.
|
||||
export_token_macro! {[await]}
|
||||
66
zeroidc/vendor/syn/src/bigint.rs
vendored
Normal file
66
zeroidc/vendor/syn/src/bigint.rs
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
use std::ops::{AddAssign, MulAssign};
|
||||
|
||||
// For implementing base10_digits() accessor on LitInt.
|
||||
pub struct BigInt {
|
||||
digits: Vec<u8>,
|
||||
}
|
||||
|
||||
impl BigInt {
|
||||
pub fn new() -> Self {
|
||||
BigInt { digits: Vec::new() }
|
||||
}
|
||||
|
||||
pub fn to_string(&self) -> String {
|
||||
let mut repr = String::with_capacity(self.digits.len());
|
||||
|
||||
let mut has_nonzero = false;
|
||||
for digit in self.digits.iter().rev() {
|
||||
has_nonzero |= *digit != 0;
|
||||
if has_nonzero {
|
||||
repr.push((*digit + b'0') as char);
|
||||
}
|
||||
}
|
||||
|
||||
if repr.is_empty() {
|
||||
repr.push('0');
|
||||
}
|
||||
|
||||
repr
|
||||
}
|
||||
|
||||
fn reserve_two_digits(&mut self) {
|
||||
let len = self.digits.len();
|
||||
let desired =
|
||||
len + !self.digits.ends_with(&[0, 0]) as usize + !self.digits.ends_with(&[0]) as usize;
|
||||
self.digits.resize(desired, 0);
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign<u8> for BigInt {
|
||||
// Assumes increment <16.
|
||||
fn add_assign(&mut self, mut increment: u8) {
|
||||
self.reserve_two_digits();
|
||||
|
||||
let mut i = 0;
|
||||
while increment > 0 {
|
||||
let sum = self.digits[i] + increment;
|
||||
self.digits[i] = sum % 10;
|
||||
increment = sum / 10;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign<u8> for BigInt {
|
||||
// Assumes base <=16.
|
||||
fn mul_assign(&mut self, base: u8) {
|
||||
self.reserve_two_digits();
|
||||
|
||||
let mut carry = 0;
|
||||
for digit in &mut self.digits {
|
||||
let prod = *digit * base + carry;
|
||||
*digit = prod % 10;
|
||||
carry = prod / 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
413
zeroidc/vendor/syn/src/buffer.rs
vendored
Normal file
413
zeroidc/vendor/syn/src/buffer.rs
vendored
Normal file
@@ -0,0 +1,413 @@
|
||||
//! A stably addressed token buffer supporting efficient traversal based on a
|
||||
//! cheaply copyable cursor.
|
||||
//!
|
||||
//! *This module is available only if Syn is built with the `"parsing"` feature.*
|
||||
|
||||
// This module is heavily commented as it contains most of the unsafe code in
|
||||
// Syn, and caution should be used when editing it. The public-facing interface
|
||||
// is 100% safe but the implementation is fragile internally.
|
||||
|
||||
#[cfg(all(
|
||||
not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
|
||||
feature = "proc-macro"
|
||||
))]
|
||||
use crate::proc_macro as pm;
|
||||
use crate::Lifetime;
|
||||
use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
|
||||
use std::marker::PhantomData;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
|
||||
/// Internal type which is used instead of `TokenTree` to represent a token tree
|
||||
/// within a `TokenBuffer`.
|
||||
enum Entry {
|
||||
// Mimicking types from proc-macro.
|
||||
Group(Group, TokenBuffer),
|
||||
Ident(Ident),
|
||||
Punct(Punct),
|
||||
Literal(Literal),
|
||||
// End entries contain a raw pointer to the entry from the containing
|
||||
// token tree, or null if this is the outermost level.
|
||||
End(*const Entry),
|
||||
}
|
||||
|
||||
/// A buffer that can be efficiently traversed multiple times, unlike
|
||||
/// `TokenStream` which requires a deep copy in order to traverse more than
|
||||
/// once.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"parsing"` feature.*
|
||||
pub struct TokenBuffer {
|
||||
// NOTE: Do not implement clone on this - there are raw pointers inside
|
||||
// these entries which will be messed up. Moving the `TokenBuffer` itself is
|
||||
// safe as the data pointed to won't be moved.
|
||||
ptr: *const Entry,
|
||||
len: usize,
|
||||
}
|
||||
|
||||
impl Drop for TokenBuffer {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let slice = slice::from_raw_parts_mut(self.ptr as *mut Entry, self.len);
|
||||
let _ = Box::from_raw(slice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TokenBuffer {
|
||||
// NOTE: Do not mutate the Vec returned from this function once it returns;
|
||||
// the address of its backing memory must remain stable.
|
||||
fn inner_new(stream: TokenStream, up: *const Entry) -> TokenBuffer {
|
||||
// Build up the entries list, recording the locations of any Groups
|
||||
// in the list to be processed later.
|
||||
let mut entries = Vec::new();
|
||||
let mut groups = Vec::new();
|
||||
for tt in stream {
|
||||
match tt {
|
||||
TokenTree::Ident(sym) => {
|
||||
entries.push(Entry::Ident(sym));
|
||||
}
|
||||
TokenTree::Punct(op) => {
|
||||
entries.push(Entry::Punct(op));
|
||||
}
|
||||
TokenTree::Literal(l) => {
|
||||
entries.push(Entry::Literal(l));
|
||||
}
|
||||
TokenTree::Group(g) => {
|
||||
// Record the index of the interesting entry, and store an
|
||||
// `End(null)` there temporarily.
|
||||
groups.push((entries.len(), g));
|
||||
entries.push(Entry::End(ptr::null()));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add an `End` entry to the end with a reference to the enclosing token
|
||||
// stream which was passed in.
|
||||
entries.push(Entry::End(up));
|
||||
|
||||
// NOTE: This is done to ensure that we don't accidentally modify the
|
||||
// length of the backing buffer. The backing buffer must remain at a
|
||||
// constant address after this point, as we are going to store a raw
|
||||
// pointer into it.
|
||||
let entries = entries.into_boxed_slice();
|
||||
let len = entries.len();
|
||||
// Convert boxed slice into a pointer to the first element early, to
|
||||
// avoid invalidating pointers into this slice when we move the Box.
|
||||
// See https://github.com/rust-lang/unsafe-code-guidelines/issues/326
|
||||
let entries = Box::into_raw(entries) as *mut Entry;
|
||||
for (idx, group) in groups {
|
||||
// We know that this index refers to one of the temporary
|
||||
// `End(null)` entries, and we know that the last entry is
|
||||
// `End(up)`, so the next index is also valid.
|
||||
let group_up = unsafe { entries.add(idx + 1) };
|
||||
|
||||
// The end entry stored at the end of this Entry::Group should
|
||||
// point to the Entry which follows the Group in the list.
|
||||
let inner = Self::inner_new(group.stream(), group_up);
|
||||
unsafe { *entries.add(idx) = Entry::Group(group, inner) };
|
||||
}
|
||||
|
||||
TokenBuffer { ptr: entries, len }
|
||||
}
|
||||
|
||||
/// Creates a `TokenBuffer` containing all the tokens from the input
|
||||
/// `proc_macro::TokenStream`.
|
||||
///
|
||||
/// *This method is available only if Syn is built with both the `"parsing"` and
|
||||
/// `"proc-macro"` features.*
|
||||
#[cfg(all(
|
||||
not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
|
||||
feature = "proc-macro"
|
||||
))]
|
||||
pub fn new(stream: pm::TokenStream) -> Self {
|
||||
Self::new2(stream.into())
|
||||
}
|
||||
|
||||
/// Creates a `TokenBuffer` containing all the tokens from the input
|
||||
/// `proc_macro2::TokenStream`.
|
||||
pub fn new2(stream: TokenStream) -> Self {
|
||||
Self::inner_new(stream, ptr::null())
|
||||
}
|
||||
|
||||
/// Creates a cursor referencing the first token in the buffer and able to
|
||||
/// traverse until the end of the buffer.
|
||||
pub fn begin(&self) -> Cursor {
|
||||
unsafe { Cursor::create(self.ptr, self.ptr.add(self.len - 1)) }
|
||||
}
|
||||
}
|
||||
|
||||
/// A cheaply copyable cursor into a `TokenBuffer`.
|
||||
///
|
||||
/// This cursor holds a shared reference into the immutable data which is used
|
||||
/// internally to represent a `TokenStream`, and can be efficiently manipulated
|
||||
/// and copied around.
|
||||
///
|
||||
/// An empty `Cursor` can be created directly, or one may create a `TokenBuffer`
|
||||
/// object and get a cursor to its first token with `begin()`.
|
||||
///
|
||||
/// Two cursors are equal if they have the same location in the same input
|
||||
/// stream, and have the same scope.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"parsing"` feature.*
|
||||
pub struct Cursor<'a> {
|
||||
// The current entry which the `Cursor` is pointing at.
|
||||
ptr: *const Entry,
|
||||
// This is the only `Entry::End(..)` object which this cursor is allowed to
|
||||
// point at. All other `End` objects are skipped over in `Cursor::create`.
|
||||
scope: *const Entry,
|
||||
// Cursor is covariant in 'a. This field ensures that our pointers are still
|
||||
// valid.
|
||||
marker: PhantomData<&'a Entry>,
|
||||
}
|
||||
|
||||
impl<'a> Cursor<'a> {
|
||||
/// Creates a cursor referencing a static empty TokenStream.
|
||||
pub fn empty() -> Self {
|
||||
// It's safe in this situation for us to put an `Entry` object in global
|
||||
// storage, despite it not actually being safe to send across threads
|
||||
// (`Ident` is a reference into a thread-local table). This is because
|
||||
// this entry never includes a `Ident` object.
|
||||
//
|
||||
// This wrapper struct allows us to break the rules and put a `Sync`
|
||||
// object in global storage.
|
||||
struct UnsafeSyncEntry(Entry);
|
||||
unsafe impl Sync for UnsafeSyncEntry {}
|
||||
static EMPTY_ENTRY: UnsafeSyncEntry = UnsafeSyncEntry(Entry::End(0 as *const Entry));
|
||||
|
||||
Cursor {
|
||||
ptr: &EMPTY_ENTRY.0,
|
||||
scope: &EMPTY_ENTRY.0,
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// This create method intelligently exits non-explicitly-entered
|
||||
/// `None`-delimited scopes when the cursor reaches the end of them,
|
||||
/// allowing for them to be treated transparently.
|
||||
unsafe fn create(mut ptr: *const Entry, scope: *const Entry) -> Self {
|
||||
// NOTE: If we're looking at a `End(..)`, we want to advance the cursor
|
||||
// past it, unless `ptr == scope`, which means that we're at the edge of
|
||||
// our cursor's scope. We should only have `ptr != scope` at the exit
|
||||
// from None-delimited groups entered with `ignore_none`.
|
||||
while let Entry::End(exit) = *ptr {
|
||||
if ptr == scope {
|
||||
break;
|
||||
}
|
||||
ptr = exit;
|
||||
}
|
||||
|
||||
Cursor {
|
||||
ptr,
|
||||
scope,
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the current entry.
|
||||
fn entry(self) -> &'a Entry {
|
||||
unsafe { &*self.ptr }
|
||||
}
|
||||
|
||||
/// Bump the cursor to point at the next token after the current one. This
|
||||
/// is undefined behavior if the cursor is currently looking at an
|
||||
/// `Entry::End`.
|
||||
unsafe fn bump(self) -> Cursor<'a> {
|
||||
Cursor::create(self.ptr.offset(1), self.scope)
|
||||
}
|
||||
|
||||
/// While the cursor is looking at a `None`-delimited group, move it to look
|
||||
/// at the first token inside instead. If the group is empty, this will move
|
||||
/// the cursor past the `None`-delimited group.
|
||||
///
|
||||
/// WARNING: This mutates its argument.
|
||||
fn ignore_none(&mut self) {
|
||||
while let Entry::Group(group, buf) = self.entry() {
|
||||
if group.delimiter() == Delimiter::None {
|
||||
// NOTE: We call `Cursor::create` here to make sure that
|
||||
// situations where we should immediately exit the span after
|
||||
// entering it are handled correctly.
|
||||
unsafe {
|
||||
*self = Cursor::create(buf.ptr, self.scope);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks whether the cursor is currently pointing at the end of its valid
|
||||
/// scope.
|
||||
pub fn eof(self) -> bool {
|
||||
// We're at eof if we're at the end of our scope.
|
||||
self.ptr == self.scope
|
||||
}
|
||||
|
||||
/// If the cursor is pointing at a `Group` with the given delimiter, returns
|
||||
/// a cursor into that group and one pointing to the next `TokenTree`.
|
||||
pub fn group(mut self, delim: Delimiter) -> Option<(Cursor<'a>, Span, Cursor<'a>)> {
|
||||
// If we're not trying to enter a none-delimited group, we want to
|
||||
// ignore them. We have to make sure to _not_ ignore them when we want
|
||||
// to enter them, of course. For obvious reasons.
|
||||
if delim != Delimiter::None {
|
||||
self.ignore_none();
|
||||
}
|
||||
|
||||
if let Entry::Group(group, buf) = self.entry() {
|
||||
if group.delimiter() == delim {
|
||||
return Some((buf.begin(), group.span(), unsafe { self.bump() }));
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// If the cursor is pointing at a `Ident`, returns it along with a cursor
|
||||
/// pointing at the next `TokenTree`.
|
||||
pub fn ident(mut self) -> Option<(Ident, Cursor<'a>)> {
|
||||
self.ignore_none();
|
||||
match self.entry() {
|
||||
Entry::Ident(ident) => Some((ident.clone(), unsafe { self.bump() })),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// If the cursor is pointing at a `Punct`, returns it along with a cursor
|
||||
/// pointing at the next `TokenTree`.
|
||||
pub fn punct(mut self) -> Option<(Punct, Cursor<'a>)> {
|
||||
self.ignore_none();
|
||||
match self.entry() {
|
||||
Entry::Punct(op) if op.as_char() != '\'' => Some((op.clone(), unsafe { self.bump() })),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// If the cursor is pointing at a `Literal`, return it along with a cursor
|
||||
/// pointing at the next `TokenTree`.
|
||||
pub fn literal(mut self) -> Option<(Literal, Cursor<'a>)> {
|
||||
self.ignore_none();
|
||||
match self.entry() {
|
||||
Entry::Literal(lit) => Some((lit.clone(), unsafe { self.bump() })),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// If the cursor is pointing at a `Lifetime`, returns it along with a
|
||||
/// cursor pointing at the next `TokenTree`.
|
||||
pub fn lifetime(mut self) -> Option<(Lifetime, Cursor<'a>)> {
|
||||
self.ignore_none();
|
||||
match self.entry() {
|
||||
Entry::Punct(op) if op.as_char() == '\'' && op.spacing() == Spacing::Joint => {
|
||||
let next = unsafe { self.bump() };
|
||||
match next.ident() {
|
||||
Some((ident, rest)) => {
|
||||
let lifetime = Lifetime {
|
||||
apostrophe: op.span(),
|
||||
ident,
|
||||
};
|
||||
Some((lifetime, rest))
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Copies all remaining tokens visible from this cursor into a
|
||||
/// `TokenStream`.
|
||||
pub fn token_stream(self) -> TokenStream {
|
||||
let mut tts = Vec::new();
|
||||
let mut cursor = self;
|
||||
while let Some((tt, rest)) = cursor.token_tree() {
|
||||
tts.push(tt);
|
||||
cursor = rest;
|
||||
}
|
||||
tts.into_iter().collect()
|
||||
}
|
||||
|
||||
/// If the cursor is pointing at a `TokenTree`, returns it along with a
|
||||
/// cursor pointing at the next `TokenTree`.
|
||||
///
|
||||
/// Returns `None` if the cursor has reached the end of its stream.
|
||||
///
|
||||
/// This method does not treat `None`-delimited groups as transparent, and
|
||||
/// will return a `Group(None, ..)` if the cursor is looking at one.
|
||||
pub fn token_tree(self) -> Option<(TokenTree, Cursor<'a>)> {
|
||||
let tree = match self.entry() {
|
||||
Entry::Group(group, _) => group.clone().into(),
|
||||
Entry::Literal(lit) => lit.clone().into(),
|
||||
Entry::Ident(ident) => ident.clone().into(),
|
||||
Entry::Punct(op) => op.clone().into(),
|
||||
Entry::End(..) => return None,
|
||||
};
|
||||
|
||||
Some((tree, unsafe { self.bump() }))
|
||||
}
|
||||
|
||||
/// Returns the `Span` of the current token, or `Span::call_site()` if this
|
||||
/// cursor points to eof.
|
||||
pub fn span(self) -> Span {
|
||||
match self.entry() {
|
||||
Entry::Group(group, _) => group.span(),
|
||||
Entry::Literal(l) => l.span(),
|
||||
Entry::Ident(t) => t.span(),
|
||||
Entry::Punct(o) => o.span(),
|
||||
Entry::End(..) => Span::call_site(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Skip over the next token without cloning it. Returns `None` if this
|
||||
/// cursor points to eof.
|
||||
///
|
||||
/// This method treats `'lifetimes` as a single token.
|
||||
pub(crate) fn skip(self) -> Option<Cursor<'a>> {
|
||||
match self.entry() {
|
||||
Entry::End(..) => None,
|
||||
|
||||
// Treat lifetimes as a single tt for the purposes of 'skip'.
|
||||
Entry::Punct(op) if op.as_char() == '\'' && op.spacing() == Spacing::Joint => {
|
||||
let next = unsafe { self.bump() };
|
||||
match next.entry() {
|
||||
Entry::Ident(_) => Some(unsafe { next.bump() }),
|
||||
_ => Some(next),
|
||||
}
|
||||
}
|
||||
_ => Some(unsafe { self.bump() }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Copy for Cursor<'a> {}
|
||||
|
||||
impl<'a> Clone for Cursor<'a> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Eq for Cursor<'a> {}
|
||||
|
||||
impl<'a> PartialEq for Cursor<'a> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
let Cursor { ptr, scope, marker } = self;
|
||||
let _ = marker;
|
||||
*ptr == other.ptr && *scope == other.scope
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn same_scope(a: Cursor, b: Cursor) -> bool {
|
||||
a.scope == b.scope
|
||||
}
|
||||
|
||||
pub(crate) fn open_span_of_group(cursor: Cursor) -> Span {
|
||||
match cursor.entry() {
|
||||
Entry::Group(group, _) => group.span_open(),
|
||||
_ => cursor.span(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn close_span_of_group(cursor: Cursor) -> Span {
|
||||
match cursor.entry() {
|
||||
Entry::Group(group, _) => group.span_close(),
|
||||
_ => cursor.span(),
|
||||
}
|
||||
}
|
||||
253
zeroidc/vendor/syn/src/custom_keyword.rs
vendored
Normal file
253
zeroidc/vendor/syn/src/custom_keyword.rs
vendored
Normal file
@@ -0,0 +1,253 @@
|
||||
/// Define a type that supports parsing and printing a given identifier as if it
|
||||
/// were a keyword.
|
||||
///
|
||||
/// # Usage
|
||||
///
|
||||
/// As a convention, it is recommended that this macro be invoked within a
|
||||
/// module called `kw` or `keyword` and that the resulting parser be invoked
|
||||
/// with a `kw::` or `keyword::` prefix.
|
||||
///
|
||||
/// ```
|
||||
/// mod kw {
|
||||
/// syn::custom_keyword!(whatever);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The generated syntax tree node supports the following operations just like
|
||||
/// any built-in keyword token.
|
||||
///
|
||||
/// - [Peeking] — `input.peek(kw::whatever)`
|
||||
///
|
||||
/// - [Parsing] — `input.parse::<kw::whatever>()?`
|
||||
///
|
||||
/// - [Printing] — `quote!( ... #whatever_token ... )`
|
||||
///
|
||||
/// - Construction from a [`Span`] — `let whatever_token = kw::whatever(sp)`
|
||||
///
|
||||
/// - Field access to its span — `let sp = whatever_token.span`
|
||||
///
|
||||
/// [Peeking]: crate::parse::ParseBuffer::peek
|
||||
/// [Parsing]: crate::parse::ParseBuffer::parse
|
||||
/// [Printing]: quote::ToTokens
|
||||
/// [`Span`]: proc_macro2::Span
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// This example parses input that looks like `bool = true` or `str = "value"`.
|
||||
/// The key must be either the identifier `bool` or the identifier `str`. If
|
||||
/// `bool`, the value may be either `true` or `false`. If `str`, the value may
|
||||
/// be any string literal.
|
||||
///
|
||||
/// The symbols `bool` and `str` are not reserved keywords in Rust so these are
|
||||
/// not considered keywords in the `syn::token` module. Like any other
|
||||
/// identifier that is not a keyword, these can be declared as custom keywords
|
||||
/// by crates that need to use them as such.
|
||||
///
|
||||
/// ```
|
||||
/// use syn::{LitBool, LitStr, Result, Token};
|
||||
/// use syn::parse::{Parse, ParseStream};
|
||||
///
|
||||
/// mod kw {
|
||||
/// syn::custom_keyword!(bool);
|
||||
/// syn::custom_keyword!(str);
|
||||
/// }
|
||||
///
|
||||
/// enum Argument {
|
||||
/// Bool {
|
||||
/// bool_token: kw::bool,
|
||||
/// eq_token: Token![=],
|
||||
/// value: LitBool,
|
||||
/// },
|
||||
/// Str {
|
||||
/// str_token: kw::str,
|
||||
/// eq_token: Token![=],
|
||||
/// value: LitStr,
|
||||
/// },
|
||||
/// }
|
||||
///
|
||||
/// impl Parse for Argument {
|
||||
/// fn parse(input: ParseStream) -> Result<Self> {
|
||||
/// let lookahead = input.lookahead1();
|
||||
/// if lookahead.peek(kw::bool) {
|
||||
/// Ok(Argument::Bool {
|
||||
/// bool_token: input.parse::<kw::bool>()?,
|
||||
/// eq_token: input.parse()?,
|
||||
/// value: input.parse()?,
|
||||
/// })
|
||||
/// } else if lookahead.peek(kw::str) {
|
||||
/// Ok(Argument::Str {
|
||||
/// str_token: input.parse::<kw::str>()?,
|
||||
/// eq_token: input.parse()?,
|
||||
/// value: input.parse()?,
|
||||
/// })
|
||||
/// } else {
|
||||
/// Err(lookahead.error())
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! custom_keyword {
|
||||
($ident:ident) => {
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct $ident {
|
||||
pub span: $crate::__private::Span,
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[allow(dead_code, non_snake_case)]
|
||||
pub fn $ident<__S: $crate::__private::IntoSpans<[$crate::__private::Span; 1]>>(
|
||||
span: __S,
|
||||
) -> $ident {
|
||||
$ident {
|
||||
span: $crate::__private::IntoSpans::into_spans(span)[0],
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::__private::Default for $ident {
|
||||
fn default() -> Self {
|
||||
$ident {
|
||||
span: $crate::__private::Span::call_site(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$crate::impl_parse_for_custom_keyword!($ident);
|
||||
$crate::impl_to_tokens_for_custom_keyword!($ident);
|
||||
$crate::impl_clone_for_custom_keyword!($ident);
|
||||
$crate::impl_extra_traits_for_custom_keyword!($ident);
|
||||
};
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[cfg(feature = "parsing")]
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_parse_for_custom_keyword {
|
||||
($ident:ident) => {
|
||||
// For peek.
|
||||
impl $crate::token::CustomToken for $ident {
|
||||
fn peek(cursor: $crate::buffer::Cursor) -> $crate::__private::bool {
|
||||
if let $crate::__private::Some((ident, _rest)) = cursor.ident() {
|
||||
ident == stringify!($ident)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn display() -> &'static $crate::__private::str {
|
||||
concat!("`", stringify!($ident), "`")
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::parse::Parse for $ident {
|
||||
fn parse(input: $crate::parse::ParseStream) -> $crate::parse::Result<$ident> {
|
||||
input.step(|cursor| {
|
||||
if let $crate::__private::Some((ident, rest)) = cursor.ident() {
|
||||
if ident == stringify!($ident) {
|
||||
return $crate::__private::Ok(($ident { span: ident.span() }, rest));
|
||||
}
|
||||
}
|
||||
$crate::__private::Err(cursor.error(concat!(
|
||||
"expected `",
|
||||
stringify!($ident),
|
||||
"`"
|
||||
)))
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[cfg(not(feature = "parsing"))]
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_parse_for_custom_keyword {
|
||||
($ident:ident) => {};
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[cfg(feature = "printing")]
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_to_tokens_for_custom_keyword {
|
||||
($ident:ident) => {
|
||||
impl $crate::__private::ToTokens for $ident {
|
||||
fn to_tokens(&self, tokens: &mut $crate::__private::TokenStream2) {
|
||||
let ident = $crate::Ident::new(stringify!($ident), self.span);
|
||||
$crate::__private::TokenStreamExt::append(tokens, ident);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[cfg(not(feature = "printing"))]
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_to_tokens_for_custom_keyword {
|
||||
($ident:ident) => {};
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[cfg(feature = "clone-impls")]
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_clone_for_custom_keyword {
|
||||
($ident:ident) => {
|
||||
impl $crate::__private::Copy for $ident {}
|
||||
|
||||
#[allow(clippy::expl_impl_clone_on_copy)]
|
||||
impl $crate::__private::Clone for $ident {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[cfg(not(feature = "clone-impls"))]
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_clone_for_custom_keyword {
|
||||
($ident:ident) => {};
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[cfg(feature = "extra-traits")]
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_extra_traits_for_custom_keyword {
|
||||
($ident:ident) => {
|
||||
impl $crate::__private::Debug for $ident {
|
||||
fn fmt(&self, f: &mut $crate::__private::Formatter) -> $crate::__private::fmt::Result {
|
||||
$crate::__private::Formatter::write_str(
|
||||
f,
|
||||
concat!("Keyword [", stringify!($ident), "]"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::__private::Eq for $ident {}
|
||||
|
||||
impl $crate::__private::PartialEq for $ident {
|
||||
fn eq(&self, _other: &Self) -> $crate::__private::bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::__private::Hash for $ident {
|
||||
fn hash<__H: $crate::__private::Hasher>(&self, _state: &mut __H) {}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[cfg(not(feature = "extra-traits"))]
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_extra_traits_for_custom_keyword {
|
||||
($ident:ident) => {};
|
||||
}
|
||||
300
zeroidc/vendor/syn/src/custom_punctuation.rs
vendored
Normal file
300
zeroidc/vendor/syn/src/custom_punctuation.rs
vendored
Normal file
@@ -0,0 +1,300 @@
|
||||
/// Define a type that supports parsing and printing a multi-character symbol
|
||||
/// as if it were a punctuation token.
|
||||
///
|
||||
/// # Usage
|
||||
///
|
||||
/// ```
|
||||
/// syn::custom_punctuation!(LeftRightArrow, <=>);
|
||||
/// ```
|
||||
///
|
||||
/// The generated syntax tree node supports the following operations just like
|
||||
/// any built-in punctuation token.
|
||||
///
|
||||
/// - [Peeking] — `input.peek(LeftRightArrow)`
|
||||
///
|
||||
/// - [Parsing] — `input.parse::<LeftRightArrow>()?`
|
||||
///
|
||||
/// - [Printing] — `quote!( ... #lrarrow ... )`
|
||||
///
|
||||
/// - Construction from a [`Span`] — `let lrarrow = LeftRightArrow(sp)`
|
||||
///
|
||||
/// - Construction from multiple [`Span`] — `let lrarrow = LeftRightArrow([sp, sp, sp])`
|
||||
///
|
||||
/// - Field access to its spans — `let spans = lrarrow.spans`
|
||||
///
|
||||
/// [Peeking]: crate::parse::ParseBuffer::peek
|
||||
/// [Parsing]: crate::parse::ParseBuffer::parse
|
||||
/// [Printing]: quote::ToTokens
|
||||
/// [`Span`]: proc_macro2::Span
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use proc_macro2::{TokenStream, TokenTree};
|
||||
/// use syn::parse::{Parse, ParseStream, Peek, Result};
|
||||
/// use syn::punctuated::Punctuated;
|
||||
/// use syn::Expr;
|
||||
///
|
||||
/// syn::custom_punctuation!(PathSeparator, </>);
|
||||
///
|
||||
/// // expr </> expr </> expr ...
|
||||
/// struct PathSegments {
|
||||
/// segments: Punctuated<Expr, PathSeparator>,
|
||||
/// }
|
||||
///
|
||||
/// impl Parse for PathSegments {
|
||||
/// fn parse(input: ParseStream) -> Result<Self> {
|
||||
/// let mut segments = Punctuated::new();
|
||||
///
|
||||
/// let first = parse_until(input, PathSeparator)?;
|
||||
/// segments.push_value(syn::parse2(first)?);
|
||||
///
|
||||
/// while input.peek(PathSeparator) {
|
||||
/// segments.push_punct(input.parse()?);
|
||||
///
|
||||
/// let next = parse_until(input, PathSeparator)?;
|
||||
/// segments.push_value(syn::parse2(next)?);
|
||||
/// }
|
||||
///
|
||||
/// Ok(PathSegments { segments })
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn parse_until<E: Peek>(input: ParseStream, end: E) -> Result<TokenStream> {
|
||||
/// let mut tokens = TokenStream::new();
|
||||
/// while !input.is_empty() && !input.peek(end) {
|
||||
/// let next: TokenTree = input.parse()?;
|
||||
/// tokens.extend(Some(next));
|
||||
/// }
|
||||
/// Ok(tokens)
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let input = r#" a::b </> c::d::e "#;
|
||||
/// let _: PathSegments = syn::parse_str(input).unwrap();
|
||||
/// }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! custom_punctuation {
|
||||
($ident:ident, $($tt:tt)+) => {
|
||||
pub struct $ident {
|
||||
pub spans: $crate::custom_punctuation_repr!($($tt)+),
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[allow(dead_code, non_snake_case)]
|
||||
pub fn $ident<__S: $crate::__private::IntoSpans<$crate::custom_punctuation_repr!($($tt)+)>>(
|
||||
spans: __S,
|
||||
) -> $ident {
|
||||
let _validate_len = 0 $(+ $crate::custom_punctuation_len!(strict, $tt))*;
|
||||
$ident {
|
||||
spans: $crate::__private::IntoSpans::into_spans(spans)
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::__private::Default for $ident {
|
||||
fn default() -> Self {
|
||||
$ident($crate::__private::Span::call_site())
|
||||
}
|
||||
}
|
||||
|
||||
$crate::impl_parse_for_custom_punctuation!($ident, $($tt)+);
|
||||
$crate::impl_to_tokens_for_custom_punctuation!($ident, $($tt)+);
|
||||
$crate::impl_clone_for_custom_punctuation!($ident, $($tt)+);
|
||||
$crate::impl_extra_traits_for_custom_punctuation!($ident, $($tt)+);
|
||||
};
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[cfg(feature = "parsing")]
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_parse_for_custom_punctuation {
|
||||
($ident:ident, $($tt:tt)+) => {
|
||||
impl $crate::token::CustomToken for $ident {
|
||||
fn peek(cursor: $crate::buffer::Cursor) -> bool {
|
||||
$crate::token::parsing::peek_punct(cursor, $crate::stringify_punct!($($tt)+))
|
||||
}
|
||||
|
||||
fn display() -> &'static $crate::__private::str {
|
||||
concat!("`", $crate::stringify_punct!($($tt)+), "`")
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::parse::Parse for $ident {
|
||||
fn parse(input: $crate::parse::ParseStream) -> $crate::parse::Result<$ident> {
|
||||
let spans: $crate::custom_punctuation_repr!($($tt)+) =
|
||||
$crate::token::parsing::punct(input, $crate::stringify_punct!($($tt)+))?;
|
||||
Ok($ident(spans))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[cfg(not(feature = "parsing"))]
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_parse_for_custom_punctuation {
|
||||
($ident:ident, $($tt:tt)+) => {};
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[cfg(feature = "printing")]
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_to_tokens_for_custom_punctuation {
|
||||
($ident:ident, $($tt:tt)+) => {
|
||||
impl $crate::__private::ToTokens for $ident {
|
||||
fn to_tokens(&self, tokens: &mut $crate::__private::TokenStream2) {
|
||||
$crate::token::printing::punct($crate::stringify_punct!($($tt)+), &self.spans, tokens)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[cfg(not(feature = "printing"))]
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_to_tokens_for_custom_punctuation {
|
||||
($ident:ident, $($tt:tt)+) => {};
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[cfg(feature = "clone-impls")]
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_clone_for_custom_punctuation {
|
||||
($ident:ident, $($tt:tt)+) => {
|
||||
impl $crate::__private::Copy for $ident {}
|
||||
|
||||
#[allow(clippy::expl_impl_clone_on_copy)]
|
||||
impl $crate::__private::Clone for $ident {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[cfg(not(feature = "clone-impls"))]
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_clone_for_custom_punctuation {
|
||||
($ident:ident, $($tt:tt)+) => {};
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[cfg(feature = "extra-traits")]
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_extra_traits_for_custom_punctuation {
|
||||
($ident:ident, $($tt:tt)+) => {
|
||||
impl $crate::__private::Debug for $ident {
|
||||
fn fmt(&self, f: &mut $crate::__private::Formatter) -> $crate::__private::fmt::Result {
|
||||
$crate::__private::Formatter::write_str(f, stringify!($ident))
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::__private::Eq for $ident {}
|
||||
|
||||
impl $crate::__private::PartialEq for $ident {
|
||||
fn eq(&self, _other: &Self) -> $crate::__private::bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::__private::Hash for $ident {
|
||||
fn hash<__H: $crate::__private::Hasher>(&self, _state: &mut __H) {}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[cfg(not(feature = "extra-traits"))]
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_extra_traits_for_custom_punctuation {
|
||||
($ident:ident, $($tt:tt)+) => {};
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! custom_punctuation_repr {
|
||||
($($tt:tt)+) => {
|
||||
[$crate::__private::Span; 0 $(+ $crate::custom_punctuation_len!(lenient, $tt))+]
|
||||
};
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
#[rustfmt::skip]
|
||||
macro_rules! custom_punctuation_len {
|
||||
($mode:ident, +) => { 1 };
|
||||
($mode:ident, +=) => { 2 };
|
||||
($mode:ident, &) => { 1 };
|
||||
($mode:ident, &&) => { 2 };
|
||||
($mode:ident, &=) => { 2 };
|
||||
($mode:ident, @) => { 1 };
|
||||
($mode:ident, !) => { 1 };
|
||||
($mode:ident, ^) => { 1 };
|
||||
($mode:ident, ^=) => { 2 };
|
||||
($mode:ident, :) => { 1 };
|
||||
($mode:ident, ::) => { 2 };
|
||||
($mode:ident, ,) => { 1 };
|
||||
($mode:ident, /) => { 1 };
|
||||
($mode:ident, /=) => { 2 };
|
||||
($mode:ident, .) => { 1 };
|
||||
($mode:ident, ..) => { 2 };
|
||||
($mode:ident, ...) => { 3 };
|
||||
($mode:ident, ..=) => { 3 };
|
||||
($mode:ident, =) => { 1 };
|
||||
($mode:ident, ==) => { 2 };
|
||||
($mode:ident, >=) => { 2 };
|
||||
($mode:ident, >) => { 1 };
|
||||
($mode:ident, <=) => { 2 };
|
||||
($mode:ident, <) => { 1 };
|
||||
($mode:ident, *=) => { 2 };
|
||||
($mode:ident, !=) => { 2 };
|
||||
($mode:ident, |) => { 1 };
|
||||
($mode:ident, |=) => { 2 };
|
||||
($mode:ident, ||) => { 2 };
|
||||
($mode:ident, #) => { 1 };
|
||||
($mode:ident, ?) => { 1 };
|
||||
($mode:ident, ->) => { 2 };
|
||||
($mode:ident, <-) => { 2 };
|
||||
($mode:ident, %) => { 1 };
|
||||
($mode:ident, %=) => { 2 };
|
||||
($mode:ident, =>) => { 2 };
|
||||
($mode:ident, ;) => { 1 };
|
||||
($mode:ident, <<) => { 2 };
|
||||
($mode:ident, <<=) => { 3 };
|
||||
($mode:ident, >>) => { 2 };
|
||||
($mode:ident, >>=) => { 3 };
|
||||
($mode:ident, *) => { 1 };
|
||||
($mode:ident, -) => { 1 };
|
||||
($mode:ident, -=) => { 2 };
|
||||
($mode:ident, ~) => { 1 };
|
||||
(lenient, $tt:tt) => { 0 };
|
||||
(strict, $tt:tt) => {{ $crate::custom_punctuation_unexpected!($tt); 0 }};
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! custom_punctuation_unexpected {
|
||||
() => {};
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! stringify_punct {
|
||||
($($tt:tt)+) => {
|
||||
concat!($(stringify!($tt)),+)
|
||||
};
|
||||
}
|
||||
493
zeroidc/vendor/syn/src/data.rs
vendored
Normal file
493
zeroidc/vendor/syn/src/data.rs
vendored
Normal file
@@ -0,0 +1,493 @@
|
||||
use super::*;
|
||||
use crate::punctuated::Punctuated;
|
||||
|
||||
ast_struct! {
|
||||
/// An enum variant.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
|
||||
/// feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub struct Variant {
|
||||
/// Attributes tagged on the variant.
|
||||
pub attrs: Vec<Attribute>,
|
||||
|
||||
/// Name of the variant.
|
||||
pub ident: Ident,
|
||||
|
||||
/// Content stored in the variant.
|
||||
pub fields: Fields,
|
||||
|
||||
/// Explicit discriminant: `Variant = 1`
|
||||
pub discriminant: Option<(Token![=], Expr)>,
|
||||
}
|
||||
}
|
||||
|
||||
ast_enum_of_structs! {
|
||||
/// Data stored within an enum variant or struct.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
|
||||
/// feature.*
|
||||
///
|
||||
/// # Syntax tree enum
|
||||
///
|
||||
/// This type is a [syntax tree enum].
|
||||
///
|
||||
/// [syntax tree enum]: Expr#syntax-tree-enums
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub enum Fields {
|
||||
/// Named fields of a struct or struct variant such as `Point { x: f64,
|
||||
/// y: f64 }`.
|
||||
Named(FieldsNamed),
|
||||
|
||||
/// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
|
||||
Unnamed(FieldsUnnamed),
|
||||
|
||||
/// Unit struct or unit variant such as `None`.
|
||||
Unit,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// Named fields of a struct or struct variant such as `Point { x: f64,
|
||||
/// y: f64 }`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or
|
||||
/// `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub struct FieldsNamed {
|
||||
pub brace_token: token::Brace,
|
||||
pub named: Punctuated<Field, Token![,]>,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or
|
||||
/// `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub struct FieldsUnnamed {
|
||||
pub paren_token: token::Paren,
|
||||
pub unnamed: Punctuated<Field, Token![,]>,
|
||||
}
|
||||
}
|
||||
|
||||
impl Fields {
|
||||
/// Get an iterator over the borrowed [`Field`] items in this object. This
|
||||
/// iterator can be used to iterate over a named or unnamed struct or
|
||||
/// variant's fields uniformly.
|
||||
pub fn iter(&self) -> punctuated::Iter<Field> {
|
||||
match self {
|
||||
Fields::Unit => crate::punctuated::empty_punctuated_iter(),
|
||||
Fields::Named(f) => f.named.iter(),
|
||||
Fields::Unnamed(f) => f.unnamed.iter(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get an iterator over the mutably borrowed [`Field`] items in this
|
||||
/// object. This iterator can be used to iterate over a named or unnamed
|
||||
/// struct or variant's fields uniformly.
|
||||
pub fn iter_mut(&mut self) -> punctuated::IterMut<Field> {
|
||||
match self {
|
||||
Fields::Unit => crate::punctuated::empty_punctuated_iter_mut(),
|
||||
Fields::Named(f) => f.named.iter_mut(),
|
||||
Fields::Unnamed(f) => f.unnamed.iter_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of fields.
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
Fields::Unit => 0,
|
||||
Fields::Named(f) => f.named.len(),
|
||||
Fields::Unnamed(f) => f.unnamed.len(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if there are zero fields.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
match self {
|
||||
Fields::Unit => true,
|
||||
Fields::Named(f) => f.named.is_empty(),
|
||||
Fields::Unnamed(f) => f.unnamed.is_empty(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for Fields {
|
||||
type Item = Field;
|
||||
type IntoIter = punctuated::IntoIter<Field>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
match self {
|
||||
Fields::Unit => Punctuated::<Field, ()>::new().into_iter(),
|
||||
Fields::Named(f) => f.named.into_iter(),
|
||||
Fields::Unnamed(f) => f.unnamed.into_iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a Fields {
|
||||
type Item = &'a Field;
|
||||
type IntoIter = punctuated::Iter<'a, Field>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a mut Fields {
|
||||
type Item = &'a mut Field;
|
||||
type IntoIter = punctuated::IterMut<'a, Field>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A field of a struct or enum variant.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
|
||||
/// feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub struct Field {
|
||||
/// Attributes tagged on the field.
|
||||
pub attrs: Vec<Attribute>,
|
||||
|
||||
/// Visibility of the field.
|
||||
pub vis: Visibility,
|
||||
|
||||
/// Name of the field, if any.
|
||||
///
|
||||
/// Fields of tuple structs have no names.
|
||||
pub ident: Option<Ident>,
|
||||
|
||||
pub colon_token: Option<Token![:]>,
|
||||
|
||||
/// Type of the field.
|
||||
pub ty: Type,
|
||||
}
|
||||
}
|
||||
|
||||
ast_enum_of_structs! {
|
||||
/// The visibility level of an item: inherited or `pub` or
|
||||
/// `pub(restricted)`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
|
||||
/// feature.*
|
||||
///
|
||||
/// # Syntax tree enum
|
||||
///
|
||||
/// This type is a [syntax tree enum].
|
||||
///
|
||||
/// [syntax tree enum]: Expr#syntax-tree-enums
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub enum Visibility {
|
||||
/// A public visibility level: `pub`.
|
||||
Public(VisPublic),
|
||||
|
||||
/// A crate-level visibility: `crate`.
|
||||
Crate(VisCrate),
|
||||
|
||||
/// A visibility level restricted to some path: `pub(self)` or
|
||||
/// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
|
||||
Restricted(VisRestricted),
|
||||
|
||||
/// An inherited visibility, which usually means private.
|
||||
Inherited,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A public visibility level: `pub`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or
|
||||
/// `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub struct VisPublic {
|
||||
pub pub_token: Token![pub],
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A crate-level visibility: `crate`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or
|
||||
/// `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub struct VisCrate {
|
||||
pub crate_token: Token![crate],
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A visibility level restricted to some path: `pub(self)` or
|
||||
/// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or
|
||||
/// `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub struct VisRestricted {
|
||||
pub pub_token: Token![pub],
|
||||
pub paren_token: token::Paren,
|
||||
pub in_token: Option<Token![in]>,
|
||||
pub path: Box<Path>,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
pub mod parsing {
|
||||
use super::*;
|
||||
use crate::ext::IdentExt;
|
||||
use crate::parse::discouraged::Speculative;
|
||||
use crate::parse::{Parse, ParseStream, Result};
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for Variant {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let attrs = input.call(Attribute::parse_outer)?;
|
||||
let _visibility: Visibility = input.parse()?;
|
||||
let ident: Ident = input.parse()?;
|
||||
let fields = if input.peek(token::Brace) {
|
||||
Fields::Named(input.parse()?)
|
||||
} else if input.peek(token::Paren) {
|
||||
Fields::Unnamed(input.parse()?)
|
||||
} else {
|
||||
Fields::Unit
|
||||
};
|
||||
let discriminant = if input.peek(Token![=]) {
|
||||
let eq_token: Token![=] = input.parse()?;
|
||||
let discriminant: Expr = input.parse()?;
|
||||
Some((eq_token, discriminant))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(Variant {
|
||||
attrs,
|
||||
ident,
|
||||
fields,
|
||||
discriminant,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for FieldsNamed {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let content;
|
||||
Ok(FieldsNamed {
|
||||
brace_token: braced!(content in input),
|
||||
named: content.parse_terminated(Field::parse_named)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for FieldsUnnamed {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let content;
|
||||
Ok(FieldsUnnamed {
|
||||
paren_token: parenthesized!(content in input),
|
||||
unnamed: content.parse_terminated(Field::parse_unnamed)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Field {
|
||||
/// Parses a named (braced struct) field.
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
pub fn parse_named(input: ParseStream) -> Result<Self> {
|
||||
Ok(Field {
|
||||
attrs: input.call(Attribute::parse_outer)?,
|
||||
vis: input.parse()?,
|
||||
ident: Some(if input.peek(Token![_]) {
|
||||
input.call(Ident::parse_any)
|
||||
} else {
|
||||
input.parse()
|
||||
}?),
|
||||
colon_token: Some(input.parse()?),
|
||||
ty: input.parse()?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Parses an unnamed (tuple struct) field.
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
pub fn parse_unnamed(input: ParseStream) -> Result<Self> {
|
||||
Ok(Field {
|
||||
attrs: input.call(Attribute::parse_outer)?,
|
||||
vis: input.parse()?,
|
||||
ident: None,
|
||||
colon_token: None,
|
||||
ty: input.parse()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for Visibility {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
// Recognize an empty None-delimited group, as produced by a $:vis
|
||||
// matcher that matched no tokens.
|
||||
if input.peek(token::Group) {
|
||||
let ahead = input.fork();
|
||||
let group = crate::group::parse_group(&ahead)?;
|
||||
if group.content.is_empty() {
|
||||
input.advance_to(&ahead);
|
||||
return Ok(Visibility::Inherited);
|
||||
}
|
||||
}
|
||||
|
||||
if input.peek(Token![pub]) {
|
||||
Self::parse_pub(input)
|
||||
} else if input.peek(Token![crate]) {
|
||||
Self::parse_crate(input)
|
||||
} else {
|
||||
Ok(Visibility::Inherited)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Visibility {
|
||||
fn parse_pub(input: ParseStream) -> Result<Self> {
|
||||
let pub_token = input.parse::<Token![pub]>()?;
|
||||
|
||||
if input.peek(token::Paren) {
|
||||
let ahead = input.fork();
|
||||
|
||||
let content;
|
||||
let paren_token = parenthesized!(content in ahead);
|
||||
if content.peek(Token![crate])
|
||||
|| content.peek(Token![self])
|
||||
|| content.peek(Token![super])
|
||||
{
|
||||
let path = content.call(Ident::parse_any)?;
|
||||
|
||||
// Ensure there are no additional tokens within `content`.
|
||||
// Without explicitly checking, we may misinterpret a tuple
|
||||
// field as a restricted visibility, causing a parse error.
|
||||
// e.g. `pub (crate::A, crate::B)` (Issue #720).
|
||||
if content.is_empty() {
|
||||
input.advance_to(&ahead);
|
||||
return Ok(Visibility::Restricted(VisRestricted {
|
||||
pub_token,
|
||||
paren_token,
|
||||
in_token: None,
|
||||
path: Box::new(Path::from(path)),
|
||||
}));
|
||||
}
|
||||
} else if content.peek(Token![in]) {
|
||||
let in_token: Token![in] = content.parse()?;
|
||||
let path = content.call(Path::parse_mod_style)?;
|
||||
|
||||
input.advance_to(&ahead);
|
||||
return Ok(Visibility::Restricted(VisRestricted {
|
||||
pub_token,
|
||||
paren_token,
|
||||
in_token: Some(in_token),
|
||||
path: Box::new(path),
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Visibility::Public(VisPublic { pub_token }))
|
||||
}
|
||||
|
||||
fn parse_crate(input: ParseStream) -> Result<Self> {
|
||||
if input.peek2(Token![::]) {
|
||||
Ok(Visibility::Inherited)
|
||||
} else {
|
||||
Ok(Visibility::Crate(VisCrate {
|
||||
crate_token: input.parse()?,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
pub(crate) fn is_some(&self) -> bool {
|
||||
match self {
|
||||
Visibility::Inherited => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "printing")]
|
||||
mod printing {
|
||||
use super::*;
|
||||
use crate::print::TokensOrDefault;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{ToTokens, TokenStreamExt};
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for Variant {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.append_all(&self.attrs);
|
||||
self.ident.to_tokens(tokens);
|
||||
self.fields.to_tokens(tokens);
|
||||
if let Some((eq_token, disc)) = &self.discriminant {
|
||||
eq_token.to_tokens(tokens);
|
||||
disc.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for FieldsNamed {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.brace_token.surround(tokens, |tokens| {
|
||||
self.named.to_tokens(tokens);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for FieldsUnnamed {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.paren_token.surround(tokens, |tokens| {
|
||||
self.unnamed.to_tokens(tokens);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for Field {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.append_all(&self.attrs);
|
||||
self.vis.to_tokens(tokens);
|
||||
if let Some(ident) = &self.ident {
|
||||
ident.to_tokens(tokens);
|
||||
TokensOrDefault(&self.colon_token).to_tokens(tokens);
|
||||
}
|
||||
self.ty.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for VisPublic {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.pub_token.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for VisCrate {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.crate_token.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for VisRestricted {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.pub_token.to_tokens(tokens);
|
||||
self.paren_token.surround(tokens, |tokens| {
|
||||
// TODO: If we have a path which is not "self" or "super" or
|
||||
// "crate", automatically add the "in" token.
|
||||
self.in_token.to_tokens(tokens);
|
||||
self.path.to_tokens(tokens);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
274
zeroidc/vendor/syn/src/derive.rs
vendored
Normal file
274
zeroidc/vendor/syn/src/derive.rs
vendored
Normal file
@@ -0,0 +1,274 @@
|
||||
use super::*;
|
||||
use crate::punctuated::Punctuated;
|
||||
|
||||
ast_struct! {
|
||||
/// Data structure sent to a `proc_macro_derive` macro.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
|
||||
pub struct DeriveInput {
|
||||
/// Attributes tagged on the whole struct or enum.
|
||||
pub attrs: Vec<Attribute>,
|
||||
|
||||
/// Visibility of the struct or enum.
|
||||
pub vis: Visibility,
|
||||
|
||||
/// Name of the struct or enum.
|
||||
pub ident: Ident,
|
||||
|
||||
/// Generics required to complete the definition.
|
||||
pub generics: Generics,
|
||||
|
||||
/// Data within the struct or enum.
|
||||
pub data: Data,
|
||||
}
|
||||
}
|
||||
|
||||
ast_enum_of_structs! {
|
||||
/// The storage of a struct, enum or union data structure.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` feature.*
|
||||
///
|
||||
/// # Syntax tree enum
|
||||
///
|
||||
/// This type is a [syntax tree enum].
|
||||
///
|
||||
/// [syntax tree enum]: Expr#syntax-tree-enums
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
|
||||
pub enum Data {
|
||||
/// A struct input to a `proc_macro_derive` macro.
|
||||
Struct(DataStruct),
|
||||
|
||||
/// An enum input to a `proc_macro_derive` macro.
|
||||
Enum(DataEnum),
|
||||
|
||||
/// An untagged union input to a `proc_macro_derive` macro.
|
||||
Union(DataUnion),
|
||||
}
|
||||
|
||||
do_not_generate_to_tokens
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A struct input to a `proc_macro_derive` macro.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"`
|
||||
/// feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
|
||||
pub struct DataStruct {
|
||||
pub struct_token: Token![struct],
|
||||
pub fields: Fields,
|
||||
pub semi_token: Option<Token![;]>,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// An enum input to a `proc_macro_derive` macro.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"`
|
||||
/// feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
|
||||
pub struct DataEnum {
|
||||
pub enum_token: Token![enum],
|
||||
pub brace_token: token::Brace,
|
||||
pub variants: Punctuated<Variant, Token![,]>,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// An untagged union input to a `proc_macro_derive` macro.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"`
|
||||
/// feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
|
||||
pub struct DataUnion {
|
||||
pub union_token: Token![union],
|
||||
pub fields: FieldsNamed,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
pub mod parsing {
|
||||
use super::*;
|
||||
use crate::parse::{Parse, ParseStream, Result};
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for DeriveInput {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let attrs = input.call(Attribute::parse_outer)?;
|
||||
let vis = input.parse::<Visibility>()?;
|
||||
|
||||
let lookahead = input.lookahead1();
|
||||
if lookahead.peek(Token![struct]) {
|
||||
let struct_token = input.parse::<Token![struct]>()?;
|
||||
let ident = input.parse::<Ident>()?;
|
||||
let generics = input.parse::<Generics>()?;
|
||||
let (where_clause, fields, semi) = data_struct(input)?;
|
||||
Ok(DeriveInput {
|
||||
attrs,
|
||||
vis,
|
||||
ident,
|
||||
generics: Generics {
|
||||
where_clause,
|
||||
..generics
|
||||
},
|
||||
data: Data::Struct(DataStruct {
|
||||
struct_token,
|
||||
fields,
|
||||
semi_token: semi,
|
||||
}),
|
||||
})
|
||||
} else if lookahead.peek(Token![enum]) {
|
||||
let enum_token = input.parse::<Token![enum]>()?;
|
||||
let ident = input.parse::<Ident>()?;
|
||||
let generics = input.parse::<Generics>()?;
|
||||
let (where_clause, brace, variants) = data_enum(input)?;
|
||||
Ok(DeriveInput {
|
||||
attrs,
|
||||
vis,
|
||||
ident,
|
||||
generics: Generics {
|
||||
where_clause,
|
||||
..generics
|
||||
},
|
||||
data: Data::Enum(DataEnum {
|
||||
enum_token,
|
||||
brace_token: brace,
|
||||
variants,
|
||||
}),
|
||||
})
|
||||
} else if lookahead.peek(Token![union]) {
|
||||
let union_token = input.parse::<Token![union]>()?;
|
||||
let ident = input.parse::<Ident>()?;
|
||||
let generics = input.parse::<Generics>()?;
|
||||
let (where_clause, fields) = data_union(input)?;
|
||||
Ok(DeriveInput {
|
||||
attrs,
|
||||
vis,
|
||||
ident,
|
||||
generics: Generics {
|
||||
where_clause,
|
||||
..generics
|
||||
},
|
||||
data: Data::Union(DataUnion {
|
||||
union_token,
|
||||
fields,
|
||||
}),
|
||||
})
|
||||
} else {
|
||||
Err(lookahead.error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn data_struct(
|
||||
input: ParseStream,
|
||||
) -> Result<(Option<WhereClause>, Fields, Option<Token![;]>)> {
|
||||
let mut lookahead = input.lookahead1();
|
||||
let mut where_clause = None;
|
||||
if lookahead.peek(Token![where]) {
|
||||
where_clause = Some(input.parse()?);
|
||||
lookahead = input.lookahead1();
|
||||
}
|
||||
|
||||
if where_clause.is_none() && lookahead.peek(token::Paren) {
|
||||
let fields = input.parse()?;
|
||||
|
||||
lookahead = input.lookahead1();
|
||||
if lookahead.peek(Token![where]) {
|
||||
where_clause = Some(input.parse()?);
|
||||
lookahead = input.lookahead1();
|
||||
}
|
||||
|
||||
if lookahead.peek(Token![;]) {
|
||||
let semi = input.parse()?;
|
||||
Ok((where_clause, Fields::Unnamed(fields), Some(semi)))
|
||||
} else {
|
||||
Err(lookahead.error())
|
||||
}
|
||||
} else if lookahead.peek(token::Brace) {
|
||||
let fields = input.parse()?;
|
||||
Ok((where_clause, Fields::Named(fields), None))
|
||||
} else if lookahead.peek(Token![;]) {
|
||||
let semi = input.parse()?;
|
||||
Ok((where_clause, Fields::Unit, Some(semi)))
|
||||
} else {
|
||||
Err(lookahead.error())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn data_enum(
|
||||
input: ParseStream,
|
||||
) -> Result<(
|
||||
Option<WhereClause>,
|
||||
token::Brace,
|
||||
Punctuated<Variant, Token![,]>,
|
||||
)> {
|
||||
let where_clause = input.parse()?;
|
||||
|
||||
let content;
|
||||
let brace = braced!(content in input);
|
||||
let variants = content.parse_terminated(Variant::parse)?;
|
||||
|
||||
Ok((where_clause, brace, variants))
|
||||
}
|
||||
|
||||
pub fn data_union(input: ParseStream) -> Result<(Option<WhereClause>, FieldsNamed)> {
|
||||
let where_clause = input.parse()?;
|
||||
let fields = input.parse()?;
|
||||
Ok((where_clause, fields))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "printing")]
|
||||
mod printing {
|
||||
use super::*;
|
||||
use crate::attr::FilterAttrs;
|
||||
use crate::print::TokensOrDefault;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::ToTokens;
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for DeriveInput {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
for attr in self.attrs.outer() {
|
||||
attr.to_tokens(tokens);
|
||||
}
|
||||
self.vis.to_tokens(tokens);
|
||||
match &self.data {
|
||||
Data::Struct(d) => d.struct_token.to_tokens(tokens),
|
||||
Data::Enum(d) => d.enum_token.to_tokens(tokens),
|
||||
Data::Union(d) => d.union_token.to_tokens(tokens),
|
||||
}
|
||||
self.ident.to_tokens(tokens);
|
||||
self.generics.to_tokens(tokens);
|
||||
match &self.data {
|
||||
Data::Struct(data) => match &data.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(&data.semi_token).to_tokens(tokens);
|
||||
}
|
||||
Fields::Unit => {
|
||||
self.generics.where_clause.to_tokens(tokens);
|
||||
TokensOrDefault(&data.semi_token).to_tokens(tokens);
|
||||
}
|
||||
},
|
||||
Data::Enum(data) => {
|
||||
self.generics.where_clause.to_tokens(tokens);
|
||||
data.brace_token.surround(tokens, |tokens| {
|
||||
data.variants.to_tokens(tokens);
|
||||
});
|
||||
}
|
||||
Data::Union(data) => {
|
||||
self.generics.where_clause.to_tokens(tokens);
|
||||
data.fields.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
194
zeroidc/vendor/syn/src/discouraged.rs
vendored
Normal file
194
zeroidc/vendor/syn/src/discouraged.rs
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
//! Extensions to the parsing API with niche applicability.
|
||||
|
||||
use super::*;
|
||||
|
||||
/// Extensions to the `ParseStream` API to support speculative parsing.
|
||||
pub trait Speculative {
|
||||
/// Advance this parse stream to the position of a forked parse stream.
|
||||
///
|
||||
/// This is the opposite operation to [`ParseStream::fork`]. You can fork a
|
||||
/// parse stream, perform some speculative parsing, then join the original
|
||||
/// stream to the fork to "commit" the parsing from the fork to the main
|
||||
/// stream.
|
||||
///
|
||||
/// If you can avoid doing this, you should, as it limits the ability to
|
||||
/// generate useful errors. That said, it is often the only way to parse
|
||||
/// syntax of the form `A* B*` for arbitrary syntax `A` and `B`. The problem
|
||||
/// is that when the fork fails to parse an `A`, it's impossible to tell
|
||||
/// whether that was because of a syntax error and the user meant to provide
|
||||
/// an `A`, or that the `A`s are finished and it's time to start parsing
|
||||
/// `B`s. Use with care.
|
||||
///
|
||||
/// Also note that if `A` is a subset of `B`, `A* B*` can be parsed by
|
||||
/// parsing `B*` and removing the leading members of `A` from the
|
||||
/// repetition, bypassing the need to involve the downsides associated with
|
||||
/// speculative parsing.
|
||||
///
|
||||
/// [`ParseStream::fork`]: ParseBuffer::fork
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// There has been chatter about the possibility of making the colons in the
|
||||
/// turbofish syntax like `path::to::<T>` no longer required by accepting
|
||||
/// `path::to<T>` in expression position. Specifically, according to [RFC
|
||||
/// 2544], [`PathSegment`] parsing should always try to consume a following
|
||||
/// `<` token as the start of generic arguments, and reset to the `<` if
|
||||
/// that fails (e.g. the token is acting as a less-than operator).
|
||||
///
|
||||
/// This is the exact kind of parsing behavior which requires the "fork,
|
||||
/// try, commit" behavior that [`ParseStream::fork`] discourages. With
|
||||
/// `advance_to`, we can avoid having to parse the speculatively parsed
|
||||
/// content a second time.
|
||||
///
|
||||
/// This change in behavior can be implemented in syn by replacing just the
|
||||
/// `Parse` implementation for `PathSegment`:
|
||||
///
|
||||
/// ```
|
||||
/// # use syn::ext::IdentExt;
|
||||
/// use syn::parse::discouraged::Speculative;
|
||||
/// # use syn::parse::{Parse, ParseStream};
|
||||
/// # use syn::{Ident, PathArguments, Result, Token};
|
||||
///
|
||||
/// pub struct PathSegment {
|
||||
/// pub ident: Ident,
|
||||
/// pub arguments: PathArguments,
|
||||
/// }
|
||||
/// #
|
||||
/// # impl<T> From<T> for PathSegment
|
||||
/// # where
|
||||
/// # T: Into<Ident>,
|
||||
/// # {
|
||||
/// # fn from(ident: T) -> Self {
|
||||
/// # PathSegment {
|
||||
/// # ident: ident.into(),
|
||||
/// # arguments: PathArguments::None,
|
||||
/// # }
|
||||
/// # }
|
||||
/// # }
|
||||
///
|
||||
/// impl Parse for PathSegment {
|
||||
/// fn parse(input: ParseStream) -> Result<Self> {
|
||||
/// if input.peek(Token![super])
|
||||
/// || input.peek(Token![self])
|
||||
/// || input.peek(Token![Self])
|
||||
/// || input.peek(Token![crate])
|
||||
/// {
|
||||
/// let ident = input.call(Ident::parse_any)?;
|
||||
/// return Ok(PathSegment::from(ident));
|
||||
/// }
|
||||
///
|
||||
/// let ident = input.parse()?;
|
||||
/// if input.peek(Token![::]) && input.peek3(Token![<]) {
|
||||
/// return Ok(PathSegment {
|
||||
/// ident,
|
||||
/// arguments: PathArguments::AngleBracketed(input.parse()?),
|
||||
/// });
|
||||
/// }
|
||||
/// if input.peek(Token![<]) && !input.peek(Token![<=]) {
|
||||
/// let fork = input.fork();
|
||||
/// if let Ok(arguments) = fork.parse() {
|
||||
/// input.advance_to(&fork);
|
||||
/// return Ok(PathSegment {
|
||||
/// ident,
|
||||
/// arguments: PathArguments::AngleBracketed(arguments),
|
||||
/// });
|
||||
/// }
|
||||
/// }
|
||||
/// Ok(PathSegment::from(ident))
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// # syn::parse_str::<PathSegment>("a<b,c>").unwrap();
|
||||
/// ```
|
||||
///
|
||||
/// # Drawbacks
|
||||
///
|
||||
/// The main drawback of this style of speculative parsing is in error
|
||||
/// presentation. Even if the lookahead is the "correct" parse, the error
|
||||
/// that is shown is that of the "fallback" parse. To use the same example
|
||||
/// as the turbofish above, take the following unfinished "turbofish":
|
||||
///
|
||||
/// ```text
|
||||
/// let _ = f<&'a fn(), for<'a> serde::>();
|
||||
/// ```
|
||||
///
|
||||
/// If this is parsed as generic arguments, we can provide the error message
|
||||
///
|
||||
/// ```text
|
||||
/// error: expected identifier
|
||||
/// --> src.rs:L:C
|
||||
/// |
|
||||
/// L | let _ = f<&'a fn(), for<'a> serde::>();
|
||||
/// | ^
|
||||
/// ```
|
||||
///
|
||||
/// but if parsed using the above speculative parsing, it falls back to
|
||||
/// assuming that the `<` is a less-than when it fails to parse the generic
|
||||
/// arguments, and tries to interpret the `&'a` as the start of a labelled
|
||||
/// loop, resulting in the much less helpful error
|
||||
///
|
||||
/// ```text
|
||||
/// error: expected `:`
|
||||
/// --> src.rs:L:C
|
||||
/// |
|
||||
/// L | let _ = f<&'a fn(), for<'a> serde::>();
|
||||
/// | ^^
|
||||
/// ```
|
||||
///
|
||||
/// This can be mitigated with various heuristics (two examples: show both
|
||||
/// forks' parse errors, or show the one that consumed more tokens), but
|
||||
/// when you can control the grammar, sticking to something that can be
|
||||
/// parsed LL(3) and without the LL(*) speculative parsing this makes
|
||||
/// possible, displaying reasonable errors becomes much more simple.
|
||||
///
|
||||
/// [RFC 2544]: https://github.com/rust-lang/rfcs/pull/2544
|
||||
/// [`PathSegment`]: crate::PathSegment
|
||||
///
|
||||
/// # Performance
|
||||
///
|
||||
/// This method performs a cheap fixed amount of work that does not depend
|
||||
/// on how far apart the two streams are positioned.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// The forked stream in the argument of `advance_to` must have been
|
||||
/// obtained by forking `self`. Attempting to advance to any other stream
|
||||
/// will cause a panic.
|
||||
fn advance_to(&self, fork: &Self);
|
||||
}
|
||||
|
||||
impl<'a> Speculative for ParseBuffer<'a> {
|
||||
fn advance_to(&self, fork: &Self) {
|
||||
if !crate::buffer::same_scope(self.cursor(), fork.cursor()) {
|
||||
panic!("Fork was not derived from the advancing parse stream");
|
||||
}
|
||||
|
||||
let (self_unexp, self_sp) = inner_unexpected(self);
|
||||
let (fork_unexp, fork_sp) = inner_unexpected(fork);
|
||||
if !Rc::ptr_eq(&self_unexp, &fork_unexp) {
|
||||
match (fork_sp, self_sp) {
|
||||
// Unexpected set on the fork, but not on `self`, copy it over.
|
||||
(Some(span), None) => {
|
||||
self_unexp.set(Unexpected::Some(span));
|
||||
}
|
||||
// Unexpected unset. Use chain to propagate errors from fork.
|
||||
(None, None) => {
|
||||
fork_unexp.set(Unexpected::Chain(self_unexp));
|
||||
|
||||
// Ensure toplevel 'unexpected' tokens from the fork don't
|
||||
// bubble up the chain by replacing the root `unexpected`
|
||||
// pointer, only 'unexpected' tokens from existing group
|
||||
// parsers should bubble.
|
||||
fork.unexpected
|
||||
.set(Some(Rc::new(Cell::new(Unexpected::None))));
|
||||
}
|
||||
// Unexpected has been set on `self`. No changes needed.
|
||||
(_, Some(_)) => {}
|
||||
}
|
||||
}
|
||||
|
||||
// See comment on `cell` in the struct definition.
|
||||
self.cell
|
||||
.set(unsafe { mem::transmute::<Cursor, Cursor<'static>>(fork.cursor()) });
|
||||
}
|
||||
}
|
||||
416
zeroidc/vendor/syn/src/error.rs
vendored
Normal file
416
zeroidc/vendor/syn/src/error.rs
vendored
Normal file
@@ -0,0 +1,416 @@
|
||||
#[cfg(feature = "parsing")]
|
||||
use crate::buffer::Cursor;
|
||||
use crate::thread::ThreadBound;
|
||||
use proc_macro2::{
|
||||
Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
|
||||
};
|
||||
#[cfg(feature = "printing")]
|
||||
use quote::ToTokens;
|
||||
use std::fmt::{self, Debug, Display};
|
||||
use std::iter::FromIterator;
|
||||
use std::slice;
|
||||
use std::vec;
|
||||
|
||||
/// The result of a Syn parser.
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// Error returned when a Syn parser cannot parse the input tokens.
|
||||
///
|
||||
/// # Error reporting in proc macros
|
||||
///
|
||||
/// The correct way to report errors back to the compiler from a procedural
|
||||
/// macro is by emitting an appropriately spanned invocation of
|
||||
/// [`compile_error!`] in the generated code. This produces a better diagnostic
|
||||
/// message than simply panicking the macro.
|
||||
///
|
||||
/// [`compile_error!`]: std::compile_error!
|
||||
///
|
||||
/// When parsing macro input, the [`parse_macro_input!`] macro handles the
|
||||
/// conversion to `compile_error!` automatically.
|
||||
///
|
||||
/// [`parse_macro_input!`]: crate::parse_macro_input!
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate proc_macro;
|
||||
/// #
|
||||
/// use proc_macro::TokenStream;
|
||||
/// use syn::{parse_macro_input, AttributeArgs, ItemFn};
|
||||
///
|
||||
/// # const IGNORE: &str = stringify! {
|
||||
/// #[proc_macro_attribute]
|
||||
/// # };
|
||||
/// pub fn my_attr(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
/// let args = parse_macro_input!(args as AttributeArgs);
|
||||
/// let input = parse_macro_input!(input as ItemFn);
|
||||
///
|
||||
/// /* ... */
|
||||
/// # TokenStream::new()
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// For errors that arise later than the initial parsing stage, the
|
||||
/// [`.to_compile_error()`] or [`.into_compile_error()`] methods can be used to
|
||||
/// perform an explicit conversion to `compile_error!`.
|
||||
///
|
||||
/// [`.to_compile_error()`]: Error::to_compile_error
|
||||
/// [`.into_compile_error()`]: Error::into_compile_error
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate proc_macro;
|
||||
/// #
|
||||
/// # use proc_macro::TokenStream;
|
||||
/// # use syn::{parse_macro_input, DeriveInput};
|
||||
/// #
|
||||
/// # const IGNORE: &str = stringify! {
|
||||
/// #[proc_macro_derive(MyDerive)]
|
||||
/// # };
|
||||
/// pub fn my_derive(input: TokenStream) -> TokenStream {
|
||||
/// let input = parse_macro_input!(input as DeriveInput);
|
||||
///
|
||||
/// // fn(DeriveInput) -> syn::Result<proc_macro2::TokenStream>
|
||||
/// expand::my_derive(input)
|
||||
/// .unwrap_or_else(syn::Error::into_compile_error)
|
||||
/// .into()
|
||||
/// }
|
||||
/// #
|
||||
/// # mod expand {
|
||||
/// # use proc_macro2::TokenStream;
|
||||
/// # use syn::{DeriveInput, Result};
|
||||
/// #
|
||||
/// # pub fn my_derive(input: DeriveInput) -> Result<TokenStream> {
|
||||
/// # unimplemented!()
|
||||
/// # }
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct Error {
|
||||
messages: Vec<ErrorMessage>,
|
||||
}
|
||||
|
||||
struct ErrorMessage {
|
||||
// Span is implemented as an index into a thread-local interner to keep the
|
||||
// size small. It is not safe to access from a different thread. We want
|
||||
// errors to be Send and Sync to play nicely with the Failure crate, so pin
|
||||
// the span we're given to its original thread and assume it is
|
||||
// Span::call_site if accessed from any other thread.
|
||||
start_span: ThreadBound<Span>,
|
||||
end_span: ThreadBound<Span>,
|
||||
message: String,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
struct _Test
|
||||
where
|
||||
Error: Send + Sync;
|
||||
|
||||
impl Error {
|
||||
/// Usually the [`ParseStream::error`] method will be used instead, which
|
||||
/// automatically uses the correct span from the current position of the
|
||||
/// parse stream.
|
||||
///
|
||||
/// Use `Error::new` when the error needs to be triggered on some span other
|
||||
/// than where the parse stream is currently positioned.
|
||||
///
|
||||
/// [`ParseStream::error`]: crate::parse::ParseBuffer::error
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use syn::{Error, Ident, LitStr, Result, Token};
|
||||
/// use syn::parse::ParseStream;
|
||||
///
|
||||
/// // Parses input that looks like `name = "string"` where the key must be
|
||||
/// // the identifier `name` and the value may be any string literal.
|
||||
/// // Returns the string literal.
|
||||
/// fn parse_name(input: ParseStream) -> Result<LitStr> {
|
||||
/// let name_token: Ident = input.parse()?;
|
||||
/// if name_token != "name" {
|
||||
/// // Trigger an error not on the current position of the stream,
|
||||
/// // but on the position of the unexpected identifier.
|
||||
/// return Err(Error::new(name_token.span(), "expected `name`"));
|
||||
/// }
|
||||
/// input.parse::<Token![=]>()?;
|
||||
/// let s: LitStr = input.parse()?;
|
||||
/// Ok(s)
|
||||
/// }
|
||||
/// ```
|
||||
pub fn new<T: Display>(span: Span, message: T) -> Self {
|
||||
Error {
|
||||
messages: vec![ErrorMessage {
|
||||
start_span: ThreadBound::new(span),
|
||||
end_span: ThreadBound::new(span),
|
||||
message: message.to_string(),
|
||||
}],
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an error with the specified message spanning the given syntax
|
||||
/// tree node.
|
||||
///
|
||||
/// Unlike the `Error::new` constructor, this constructor takes an argument
|
||||
/// `tokens` which is a syntax tree node. This allows the resulting `Error`
|
||||
/// to attempt to span all tokens inside of `tokens`. While you would
|
||||
/// typically be able to use the `Spanned` trait with the above `Error::new`
|
||||
/// constructor, implementation limitations today mean that
|
||||
/// `Error::new_spanned` may provide a higher-quality error message on
|
||||
/// stable Rust.
|
||||
///
|
||||
/// When in doubt it's recommended to stick to `Error::new` (or
|
||||
/// `ParseStream::error`)!
|
||||
#[cfg(feature = "printing")]
|
||||
pub fn new_spanned<T: ToTokens, U: Display>(tokens: T, message: U) -> Self {
|
||||
let mut iter = tokens.into_token_stream().into_iter();
|
||||
let start = iter.next().map_or_else(Span::call_site, |t| t.span());
|
||||
let end = iter.last().map_or(start, |t| t.span());
|
||||
Error {
|
||||
messages: vec![ErrorMessage {
|
||||
start_span: ThreadBound::new(start),
|
||||
end_span: ThreadBound::new(end),
|
||||
message: message.to_string(),
|
||||
}],
|
||||
}
|
||||
}
|
||||
|
||||
/// The source location of the error.
|
||||
///
|
||||
/// Spans are not thread-safe so this function returns `Span::call_site()`
|
||||
/// if called from a different thread than the one on which the `Error` was
|
||||
/// originally created.
|
||||
pub fn span(&self) -> Span {
|
||||
let start = match self.messages[0].start_span.get() {
|
||||
Some(span) => *span,
|
||||
None => return Span::call_site(),
|
||||
};
|
||||
let end = match self.messages[0].end_span.get() {
|
||||
Some(span) => *span,
|
||||
None => return Span::call_site(),
|
||||
};
|
||||
start.join(end).unwrap_or(start)
|
||||
}
|
||||
|
||||
/// Render the error as an invocation of [`compile_error!`].
|
||||
///
|
||||
/// The [`parse_macro_input!`] macro provides a convenient way to invoke
|
||||
/// this method correctly in a procedural macro.
|
||||
///
|
||||
/// [`compile_error!`]: std::compile_error!
|
||||
/// [`parse_macro_input!`]: crate::parse_macro_input!
|
||||
pub fn to_compile_error(&self) -> TokenStream {
|
||||
self.messages
|
||||
.iter()
|
||||
.map(ErrorMessage::to_compile_error)
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Render the error as an invocation of [`compile_error!`].
|
||||
///
|
||||
/// [`compile_error!`]: std::compile_error!
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate proc_macro;
|
||||
/// #
|
||||
/// use proc_macro::TokenStream;
|
||||
/// use syn::{parse_macro_input, DeriveInput, Error};
|
||||
///
|
||||
/// # const _: &str = stringify! {
|
||||
/// #[proc_macro_derive(MyTrait)]
|
||||
/// # };
|
||||
/// pub fn derive_my_trait(input: TokenStream) -> TokenStream {
|
||||
/// let input = parse_macro_input!(input as DeriveInput);
|
||||
/// my_trait::expand(input)
|
||||
/// .unwrap_or_else(Error::into_compile_error)
|
||||
/// .into()
|
||||
/// }
|
||||
///
|
||||
/// mod my_trait {
|
||||
/// use proc_macro2::TokenStream;
|
||||
/// use syn::{DeriveInput, Result};
|
||||
///
|
||||
/// pub(crate) fn expand(input: DeriveInput) -> Result<TokenStream> {
|
||||
/// /* ... */
|
||||
/// # unimplemented!()
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub fn into_compile_error(self) -> TokenStream {
|
||||
self.to_compile_error()
|
||||
}
|
||||
|
||||
/// Add another error message to self such that when `to_compile_error()` is
|
||||
/// called, both errors will be emitted together.
|
||||
pub fn combine(&mut self, another: Error) {
|
||||
self.messages.extend(another.messages);
|
||||
}
|
||||
}
|
||||
|
||||
impl ErrorMessage {
|
||||
fn to_compile_error(&self) -> TokenStream {
|
||||
let start = self
|
||||
.start_span
|
||||
.get()
|
||||
.cloned()
|
||||
.unwrap_or_else(Span::call_site);
|
||||
let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);
|
||||
|
||||
// compile_error!($message)
|
||||
TokenStream::from_iter(vec![
|
||||
TokenTree::Ident(Ident::new("compile_error", start)),
|
||||
TokenTree::Punct({
|
||||
let mut punct = Punct::new('!', Spacing::Alone);
|
||||
punct.set_span(start);
|
||||
punct
|
||||
}),
|
||||
TokenTree::Group({
|
||||
let mut group = Group::new(Delimiter::Brace, {
|
||||
TokenStream::from_iter(vec![TokenTree::Literal({
|
||||
let mut string = Literal::string(&self.message);
|
||||
string.set_span(end);
|
||||
string
|
||||
})])
|
||||
});
|
||||
group.set_span(end);
|
||||
group
|
||||
}),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
pub fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
|
||||
if cursor.eof() {
|
||||
Error::new(scope, format!("unexpected end of input, {}", message))
|
||||
} else {
|
||||
let span = crate::buffer::open_span_of_group(cursor);
|
||||
Error::new(span, message)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "parsing", any(feature = "full", feature = "derive")))]
|
||||
pub fn new2<T: Display>(start: Span, end: Span, message: T) -> Error {
|
||||
Error {
|
||||
messages: vec![ErrorMessage {
|
||||
start_span: ThreadBound::new(start),
|
||||
end_span: ThreadBound::new(end),
|
||||
message: message.to_string(),
|
||||
}],
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Error {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
if self.messages.len() == 1 {
|
||||
formatter
|
||||
.debug_tuple("Error")
|
||||
.field(&self.messages[0])
|
||||
.finish()
|
||||
} else {
|
||||
formatter
|
||||
.debug_tuple("Error")
|
||||
.field(&self.messages)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for ErrorMessage {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
Debug::fmt(&self.message, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str(&self.messages[0].message)
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Error {
|
||||
fn clone(&self) -> Self {
|
||||
Error {
|
||||
messages: self.messages.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for ErrorMessage {
|
||||
fn clone(&self) -> Self {
|
||||
let start = self
|
||||
.start_span
|
||||
.get()
|
||||
.cloned()
|
||||
.unwrap_or_else(Span::call_site);
|
||||
let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);
|
||||
ErrorMessage {
|
||||
start_span: ThreadBound::new(start),
|
||||
end_span: ThreadBound::new(end),
|
||||
message: self.message.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {}
|
||||
|
||||
impl From<LexError> for Error {
|
||||
fn from(err: LexError) -> Self {
|
||||
Error::new(err.span(), "lex error")
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for Error {
|
||||
type Item = Error;
|
||||
type IntoIter = IntoIter;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
IntoIter {
|
||||
messages: self.messages.into_iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IntoIter {
|
||||
messages: vec::IntoIter<ErrorMessage>,
|
||||
}
|
||||
|
||||
impl Iterator for IntoIter {
|
||||
type Item = Error;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
Some(Error {
|
||||
messages: vec![self.messages.next()?],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a Error {
|
||||
type Item = Error;
|
||||
type IntoIter = Iter<'a>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
Iter {
|
||||
messages: self.messages.iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Iter<'a> {
|
||||
messages: slice::Iter<'a, ErrorMessage>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Iter<'a> {
|
||||
type Item = Error;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
Some(Error {
|
||||
messages: vec![self.messages.next()?.clone()],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Extend<Error> for Error {
|
||||
fn extend<T: IntoIterator<Item = Error>>(&mut self, iter: T) {
|
||||
for err in iter {
|
||||
self.combine(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
36
zeroidc/vendor/syn/src/export.rs
vendored
Normal file
36
zeroidc/vendor/syn/src/export.rs
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
pub use std::clone::Clone;
|
||||
pub use std::cmp::{Eq, PartialEq};
|
||||
pub use std::default::Default;
|
||||
pub use std::fmt::{self, Debug, Formatter};
|
||||
pub use std::hash::{Hash, Hasher};
|
||||
pub use std::marker::Copy;
|
||||
pub use std::option::Option::{None, Some};
|
||||
pub use std::result::Result::{Err, Ok};
|
||||
|
||||
#[cfg(feature = "printing")]
|
||||
pub extern crate quote;
|
||||
|
||||
pub use proc_macro2::{Span, TokenStream as TokenStream2};
|
||||
|
||||
pub use crate::span::IntoSpans;
|
||||
|
||||
#[cfg(all(
|
||||
not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
|
||||
feature = "proc-macro"
|
||||
))]
|
||||
pub use proc_macro::TokenStream;
|
||||
|
||||
#[cfg(feature = "printing")]
|
||||
pub use quote::{ToTokens, TokenStreamExt};
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type bool = help::Bool;
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type str = help::Str;
|
||||
|
||||
mod help {
|
||||
pub type Bool = bool;
|
||||
pub type Str = str;
|
||||
}
|
||||
|
||||
pub struct private(pub(crate) ());
|
||||
3547
zeroidc/vendor/syn/src/expr.rs
vendored
Normal file
3547
zeroidc/vendor/syn/src/expr.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
139
zeroidc/vendor/syn/src/ext.rs
vendored
Normal file
139
zeroidc/vendor/syn/src/ext.rs
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
//! Extension traits to provide parsing methods on foreign types.
|
||||
//!
|
||||
//! *This module is available only if Syn is built with the `"parsing"` feature.*
|
||||
|
||||
use crate::buffer::Cursor;
|
||||
use crate::parse::Peek;
|
||||
use crate::parse::{ParseStream, Result};
|
||||
use crate::sealed::lookahead;
|
||||
use crate::token::CustomToken;
|
||||
use proc_macro2::Ident;
|
||||
|
||||
/// Additional methods for `Ident` not provided by proc-macro2 or libproc_macro.
|
||||
///
|
||||
/// This trait is sealed and cannot be implemented for types outside of Syn. It
|
||||
/// is implemented only for `proc_macro2::Ident`.
|
||||
///
|
||||
/// *This trait is available only if Syn is built with the `"parsing"` feature.*
|
||||
pub trait IdentExt: Sized + private::Sealed {
|
||||
/// Parses any identifier including keywords.
|
||||
///
|
||||
/// This is useful when parsing macro input which allows Rust keywords as
|
||||
/// identifiers.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use syn::{Error, Ident, Result, Token};
|
||||
/// use syn::ext::IdentExt;
|
||||
/// use syn::parse::ParseStream;
|
||||
///
|
||||
/// mod kw {
|
||||
/// syn::custom_keyword!(name);
|
||||
/// }
|
||||
///
|
||||
/// // Parses input that looks like `name = NAME` where `NAME` can be
|
||||
/// // any identifier.
|
||||
/// //
|
||||
/// // Examples:
|
||||
/// //
|
||||
/// // name = anything
|
||||
/// // name = impl
|
||||
/// fn parse_dsl(input: ParseStream) -> Result<Ident> {
|
||||
/// input.parse::<kw::name>()?;
|
||||
/// input.parse::<Token![=]>()?;
|
||||
/// let name = input.call(Ident::parse_any)?;
|
||||
/// Ok(name)
|
||||
/// }
|
||||
/// ```
|
||||
fn parse_any(input: ParseStream) -> Result<Self>;
|
||||
|
||||
/// Peeks any identifier including keywords. Usage:
|
||||
/// `input.peek(Ident::peek_any)`
|
||||
///
|
||||
/// This is different from `input.peek(Ident)` which only returns true in
|
||||
/// the case of an ident which is not a Rust keyword.
|
||||
#[allow(non_upper_case_globals)]
|
||||
const peek_any: private::PeekFn = private::PeekFn;
|
||||
|
||||
/// Strips the raw marker `r#`, if any, from the beginning of an ident.
|
||||
///
|
||||
/// - unraw(`x`) = `x`
|
||||
/// - unraw(`move`) = `move`
|
||||
/// - unraw(`r#move`) = `move`
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// In the case of interop with other languages like Python that have a
|
||||
/// different set of keywords than Rust, we might come across macro input
|
||||
/// that involves raw identifiers to refer to ordinary variables in the
|
||||
/// other language with a name that happens to be a Rust keyword.
|
||||
///
|
||||
/// The function below appends an identifier from the caller's input onto a
|
||||
/// fixed prefix. Without using `unraw()`, this would tend to produce
|
||||
/// invalid identifiers like `__pyo3_get_r#move`.
|
||||
///
|
||||
/// ```
|
||||
/// use proc_macro2::Span;
|
||||
/// use syn::Ident;
|
||||
/// use syn::ext::IdentExt;
|
||||
///
|
||||
/// fn ident_for_getter(variable: &Ident) -> Ident {
|
||||
/// let getter = format!("__pyo3_get_{}", variable.unraw());
|
||||
/// Ident::new(&getter, Span::call_site())
|
||||
/// }
|
||||
/// ```
|
||||
fn unraw(&self) -> Ident;
|
||||
}
|
||||
|
||||
impl IdentExt for Ident {
|
||||
fn parse_any(input: ParseStream) -> Result<Self> {
|
||||
input.step(|cursor| match cursor.ident() {
|
||||
Some((ident, rest)) => Ok((ident, rest)),
|
||||
None => Err(cursor.error("expected ident")),
|
||||
})
|
||||
}
|
||||
|
||||
fn unraw(&self) -> Ident {
|
||||
let string = self.to_string();
|
||||
if string.starts_with("r#") {
|
||||
Ident::new(&string[2..], self.span())
|
||||
} else {
|
||||
self.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Peek for private::PeekFn {
|
||||
type Token = private::IdentAny;
|
||||
}
|
||||
|
||||
impl CustomToken for private::IdentAny {
|
||||
fn peek(cursor: Cursor) -> bool {
|
||||
cursor.ident().is_some()
|
||||
}
|
||||
|
||||
fn display() -> &'static str {
|
||||
"identifier"
|
||||
}
|
||||
}
|
||||
|
||||
impl lookahead::Sealed for private::PeekFn {}
|
||||
|
||||
mod private {
|
||||
use proc_macro2::Ident;
|
||||
|
||||
pub trait Sealed {}
|
||||
|
||||
impl Sealed for Ident {}
|
||||
|
||||
pub struct PeekFn;
|
||||
pub struct IdentAny;
|
||||
|
||||
impl Copy for PeekFn {}
|
||||
impl Clone for PeekFn {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
}
|
||||
125
zeroidc/vendor/syn/src/file.rs
vendored
Normal file
125
zeroidc/vendor/syn/src/file.rs
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
use super::*;
|
||||
|
||||
ast_struct! {
|
||||
/// A complete file of Rust source code.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"full"` feature.*
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// Parse a Rust source file into a `syn::File` and print out a debug
|
||||
/// representation of the syntax tree.
|
||||
///
|
||||
/// ```
|
||||
/// use std::env;
|
||||
/// use std::fs::File;
|
||||
/// use std::io::Read;
|
||||
/// use std::process;
|
||||
///
|
||||
/// fn main() {
|
||||
/// # }
|
||||
/// #
|
||||
/// # fn fake_main() {
|
||||
/// let mut args = env::args();
|
||||
/// let _ = args.next(); // executable name
|
||||
///
|
||||
/// let filename = match (args.next(), args.next()) {
|
||||
/// (Some(filename), None) => filename,
|
||||
/// _ => {
|
||||
/// eprintln!("Usage: dump-syntax path/to/filename.rs");
|
||||
/// process::exit(1);
|
||||
/// }
|
||||
/// };
|
||||
///
|
||||
/// let mut file = File::open(&filename).expect("Unable to open file");
|
||||
///
|
||||
/// let mut src = String::new();
|
||||
/// file.read_to_string(&mut src).expect("Unable to read file");
|
||||
///
|
||||
/// let syntax = syn::parse_file(&src).expect("Unable to parse file");
|
||||
///
|
||||
/// // Debug impl is available if Syn is built with "extra-traits" feature.
|
||||
/// println!("{:#?}", syntax);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Running with its own source code as input, this program prints output
|
||||
/// that begins with:
|
||||
///
|
||||
/// ```text
|
||||
/// File {
|
||||
/// shebang: None,
|
||||
/// attrs: [],
|
||||
/// items: [
|
||||
/// Use(
|
||||
/// ItemUse {
|
||||
/// attrs: [],
|
||||
/// vis: Inherited,
|
||||
/// use_token: Use,
|
||||
/// leading_colon: None,
|
||||
/// tree: Path(
|
||||
/// UsePath {
|
||||
/// ident: Ident(
|
||||
/// std,
|
||||
/// ),
|
||||
/// colon2_token: Colon2,
|
||||
/// tree: Name(
|
||||
/// UseName {
|
||||
/// ident: Ident(
|
||||
/// env,
|
||||
/// ),
|
||||
/// },
|
||||
/// ),
|
||||
/// },
|
||||
/// ),
|
||||
/// semi_token: Semi,
|
||||
/// },
|
||||
/// ),
|
||||
/// ...
|
||||
/// ```
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
|
||||
pub struct File {
|
||||
pub shebang: Option<String>,
|
||||
pub attrs: Vec<Attribute>,
|
||||
pub items: Vec<Item>,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
pub mod parsing {
|
||||
use super::*;
|
||||
use crate::parse::{Parse, ParseStream, Result};
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for File {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
Ok(File {
|
||||
shebang: None,
|
||||
attrs: input.call(Attribute::parse_inner)?,
|
||||
items: {
|
||||
let mut items = Vec::new();
|
||||
while !input.is_empty() {
|
||||
items.push(input.parse()?);
|
||||
}
|
||||
items
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "printing")]
|
||||
mod printing {
|
||||
use super::*;
|
||||
use crate::attr::FilterAttrs;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{ToTokens, TokenStreamExt};
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for File {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.append_all(self.attrs.inner());
|
||||
tokens.append_all(&self.items);
|
||||
}
|
||||
}
|
||||
}
|
||||
2241
zeroidc/vendor/syn/src/gen/clone.rs
vendored
Normal file
2241
zeroidc/vendor/syn/src/gen/clone.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3042
zeroidc/vendor/syn/src/gen/debug.rs
vendored
Normal file
3042
zeroidc/vendor/syn/src/gen/debug.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2195
zeroidc/vendor/syn/src/gen/eq.rs
vendored
Normal file
2195
zeroidc/vendor/syn/src/gen/eq.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3341
zeroidc/vendor/syn/src/gen/fold.rs
vendored
Normal file
3341
zeroidc/vendor/syn/src/gen/fold.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2869
zeroidc/vendor/syn/src/gen/hash.rs
vendored
Normal file
2869
zeroidc/vendor/syn/src/gen/hash.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3786
zeroidc/vendor/syn/src/gen/visit.rs
vendored
Normal file
3786
zeroidc/vendor/syn/src/gen/visit.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3786
zeroidc/vendor/syn/src/gen/visit_mut.rs
vendored
Normal file
3786
zeroidc/vendor/syn/src/gen/visit_mut.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
154
zeroidc/vendor/syn/src/gen_helper.rs
vendored
Normal file
154
zeroidc/vendor/syn/src/gen_helper.rs
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
#[cfg(feature = "fold")]
|
||||
pub mod fold {
|
||||
use crate::fold::Fold;
|
||||
use crate::punctuated::{Pair, Punctuated};
|
||||
use proc_macro2::Span;
|
||||
|
||||
pub trait FoldHelper {
|
||||
type Item;
|
||||
fn lift<F>(self, f: F) -> Self
|
||||
where
|
||||
F: FnMut(Self::Item) -> Self::Item;
|
||||
}
|
||||
|
||||
impl<T> FoldHelper for Vec<T> {
|
||||
type Item = T;
|
||||
fn lift<F>(self, f: F) -> Self
|
||||
where
|
||||
F: FnMut(Self::Item) -> Self::Item,
|
||||
{
|
||||
self.into_iter().map(f).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> FoldHelper for Punctuated<T, U> {
|
||||
type Item = T;
|
||||
fn lift<F>(self, mut f: F) -> Self
|
||||
where
|
||||
F: FnMut(Self::Item) -> Self::Item,
|
||||
{
|
||||
self.into_pairs()
|
||||
.map(Pair::into_tuple)
|
||||
.map(|(t, u)| Pair::new(f(t), u))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tokens_helper<F: Fold + ?Sized, S: Spans>(folder: &mut F, spans: &S) -> S {
|
||||
spans.fold(folder)
|
||||
}
|
||||
|
||||
pub trait Spans {
|
||||
fn fold<F: Fold + ?Sized>(&self, folder: &mut F) -> Self;
|
||||
}
|
||||
|
||||
impl Spans for Span {
|
||||
fn fold<F: Fold + ?Sized>(&self, folder: &mut F) -> Self {
|
||||
folder.fold_span(*self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Spans for [Span; 1] {
|
||||
fn fold<F: Fold + ?Sized>(&self, folder: &mut F) -> Self {
|
||||
[folder.fold_span(self[0])]
|
||||
}
|
||||
}
|
||||
|
||||
impl Spans for [Span; 2] {
|
||||
fn fold<F: Fold + ?Sized>(&self, folder: &mut F) -> Self {
|
||||
[folder.fold_span(self[0]), folder.fold_span(self[1])]
|
||||
}
|
||||
}
|
||||
|
||||
impl Spans for [Span; 3] {
|
||||
fn fold<F: Fold + ?Sized>(&self, folder: &mut F) -> Self {
|
||||
[
|
||||
folder.fold_span(self[0]),
|
||||
folder.fold_span(self[1]),
|
||||
folder.fold_span(self[2]),
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "visit")]
|
||||
pub mod visit {
|
||||
use crate::visit::Visit;
|
||||
use proc_macro2::Span;
|
||||
|
||||
pub fn tokens_helper<'ast, V: Visit<'ast> + ?Sized, S: Spans>(visitor: &mut V, spans: &S) {
|
||||
spans.visit(visitor);
|
||||
}
|
||||
|
||||
pub trait Spans {
|
||||
fn visit<'ast, V: Visit<'ast> + ?Sized>(&self, visitor: &mut V);
|
||||
}
|
||||
|
||||
impl Spans for Span {
|
||||
fn visit<'ast, V: Visit<'ast> + ?Sized>(&self, visitor: &mut V) {
|
||||
visitor.visit_span(self);
|
||||
}
|
||||
}
|
||||
|
||||
impl Spans for [Span; 1] {
|
||||
fn visit<'ast, V: Visit<'ast> + ?Sized>(&self, visitor: &mut V) {
|
||||
visitor.visit_span(&self[0]);
|
||||
}
|
||||
}
|
||||
|
||||
impl Spans for [Span; 2] {
|
||||
fn visit<'ast, V: Visit<'ast> + ?Sized>(&self, visitor: &mut V) {
|
||||
visitor.visit_span(&self[0]);
|
||||
visitor.visit_span(&self[1]);
|
||||
}
|
||||
}
|
||||
|
||||
impl Spans for [Span; 3] {
|
||||
fn visit<'ast, V: Visit<'ast> + ?Sized>(&self, visitor: &mut V) {
|
||||
visitor.visit_span(&self[0]);
|
||||
visitor.visit_span(&self[1]);
|
||||
visitor.visit_span(&self[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "visit-mut")]
|
||||
pub mod visit_mut {
|
||||
use crate::visit_mut::VisitMut;
|
||||
use proc_macro2::Span;
|
||||
|
||||
pub fn tokens_helper<V: VisitMut + ?Sized, S: Spans>(visitor: &mut V, spans: &mut S) {
|
||||
spans.visit_mut(visitor);
|
||||
}
|
||||
|
||||
pub trait Spans {
|
||||
fn visit_mut<V: VisitMut + ?Sized>(&mut self, visitor: &mut V);
|
||||
}
|
||||
|
||||
impl Spans for Span {
|
||||
fn visit_mut<V: VisitMut + ?Sized>(&mut self, visitor: &mut V) {
|
||||
visitor.visit_span_mut(self);
|
||||
}
|
||||
}
|
||||
|
||||
impl Spans for [Span; 1] {
|
||||
fn visit_mut<V: VisitMut + ?Sized>(&mut self, visitor: &mut V) {
|
||||
visitor.visit_span_mut(&mut self[0]);
|
||||
}
|
||||
}
|
||||
|
||||
impl Spans for [Span; 2] {
|
||||
fn visit_mut<V: VisitMut + ?Sized>(&mut self, visitor: &mut V) {
|
||||
visitor.visit_span_mut(&mut self[0]);
|
||||
visitor.visit_span_mut(&mut self[1]);
|
||||
}
|
||||
}
|
||||
|
||||
impl Spans for [Span; 3] {
|
||||
fn visit_mut<V: VisitMut + ?Sized>(&mut self, visitor: &mut V) {
|
||||
visitor.visit_span_mut(&mut self[0]);
|
||||
visitor.visit_span_mut(&mut self[1]);
|
||||
visitor.visit_span_mut(&mut self[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
1337
zeroidc/vendor/syn/src/generics.rs
vendored
Normal file
1337
zeroidc/vendor/syn/src/generics.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
282
zeroidc/vendor/syn/src/group.rs
vendored
Normal file
282
zeroidc/vendor/syn/src/group.rs
vendored
Normal file
@@ -0,0 +1,282 @@
|
||||
use crate::error::Result;
|
||||
use crate::parse::ParseBuffer;
|
||||
use crate::token;
|
||||
use proc_macro2::{Delimiter, Span};
|
||||
|
||||
// Not public API.
|
||||
#[doc(hidden)]
|
||||
pub struct Parens<'a> {
|
||||
pub token: token::Paren,
|
||||
pub content: ParseBuffer<'a>,
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[doc(hidden)]
|
||||
pub struct Braces<'a> {
|
||||
pub token: token::Brace,
|
||||
pub content: ParseBuffer<'a>,
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[doc(hidden)]
|
||||
pub struct Brackets<'a> {
|
||||
pub token: token::Bracket,
|
||||
pub content: ParseBuffer<'a>,
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
#[doc(hidden)]
|
||||
pub struct Group<'a> {
|
||||
pub token: token::Group,
|
||||
pub content: ParseBuffer<'a>,
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[doc(hidden)]
|
||||
pub fn parse_parens<'a>(input: &ParseBuffer<'a>) -> Result<Parens<'a>> {
|
||||
parse_delimited(input, Delimiter::Parenthesis).map(|(span, content)| Parens {
|
||||
token: token::Paren(span),
|
||||
content,
|
||||
})
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[doc(hidden)]
|
||||
pub fn parse_braces<'a>(input: &ParseBuffer<'a>) -> Result<Braces<'a>> {
|
||||
parse_delimited(input, Delimiter::Brace).map(|(span, content)| Braces {
|
||||
token: token::Brace(span),
|
||||
content,
|
||||
})
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[doc(hidden)]
|
||||
pub fn parse_brackets<'a>(input: &ParseBuffer<'a>) -> Result<Brackets<'a>> {
|
||||
parse_delimited(input, Delimiter::Bracket).map(|(span, content)| Brackets {
|
||||
token: token::Bracket(span),
|
||||
content,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
pub(crate) fn parse_group<'a>(input: &ParseBuffer<'a>) -> Result<Group<'a>> {
|
||||
parse_delimited(input, Delimiter::None).map(|(span, content)| Group {
|
||||
token: token::Group(span),
|
||||
content,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_delimited<'a>(
|
||||
input: &ParseBuffer<'a>,
|
||||
delimiter: Delimiter,
|
||||
) -> Result<(Span, ParseBuffer<'a>)> {
|
||||
input.step(|cursor| {
|
||||
if let Some((content, span, rest)) = cursor.group(delimiter) {
|
||||
let scope = crate::buffer::close_span_of_group(*cursor);
|
||||
let nested = crate::parse::advance_step_cursor(cursor, content);
|
||||
let unexpected = crate::parse::get_unexpected(input);
|
||||
let content = crate::parse::new_parse_buffer(scope, nested, unexpected);
|
||||
Ok(((span, content), rest))
|
||||
} else {
|
||||
let message = match delimiter {
|
||||
Delimiter::Parenthesis => "expected parentheses",
|
||||
Delimiter::Brace => "expected curly braces",
|
||||
Delimiter::Bracket => "expected square brackets",
|
||||
Delimiter::None => "expected invisible group",
|
||||
};
|
||||
Err(cursor.error(message))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Parse a set of parentheses and expose their content to subsequent parsers.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use quote::quote;
|
||||
/// #
|
||||
/// use syn::{parenthesized, token, Ident, Result, Token, Type};
|
||||
/// use syn::parse::{Parse, ParseStream};
|
||||
/// use syn::punctuated::Punctuated;
|
||||
///
|
||||
/// // Parse a simplified tuple struct syntax like:
|
||||
/// //
|
||||
/// // struct S(A, B);
|
||||
/// struct TupleStruct {
|
||||
/// struct_token: Token![struct],
|
||||
/// ident: Ident,
|
||||
/// paren_token: token::Paren,
|
||||
/// fields: Punctuated<Type, Token![,]>,
|
||||
/// semi_token: Token![;],
|
||||
/// }
|
||||
///
|
||||
/// impl Parse for TupleStruct {
|
||||
/// fn parse(input: ParseStream) -> Result<Self> {
|
||||
/// let content;
|
||||
/// Ok(TupleStruct {
|
||||
/// struct_token: input.parse()?,
|
||||
/// ident: input.parse()?,
|
||||
/// paren_token: parenthesized!(content in input),
|
||||
/// fields: content.parse_terminated(Type::parse)?,
|
||||
/// semi_token: input.parse()?,
|
||||
/// })
|
||||
/// }
|
||||
/// }
|
||||
/// #
|
||||
/// # fn main() {
|
||||
/// # let input = quote! {
|
||||
/// # struct S(A, B);
|
||||
/// # };
|
||||
/// # syn::parse2::<TupleStruct>(input).unwrap();
|
||||
/// # }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
macro_rules! parenthesized {
|
||||
($content:ident in $cursor:expr) => {
|
||||
match $crate::group::parse_parens(&$cursor) {
|
||||
$crate::__private::Ok(parens) => {
|
||||
$content = parens.content;
|
||||
parens.token
|
||||
}
|
||||
$crate::__private::Err(error) => {
|
||||
return $crate::__private::Err(error);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Parse a set of curly braces and expose their content to subsequent parsers.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use quote::quote;
|
||||
/// #
|
||||
/// use syn::{braced, token, Ident, Result, Token, Type};
|
||||
/// use syn::parse::{Parse, ParseStream};
|
||||
/// use syn::punctuated::Punctuated;
|
||||
///
|
||||
/// // Parse a simplified struct syntax like:
|
||||
/// //
|
||||
/// // struct S {
|
||||
/// // a: A,
|
||||
/// // b: B,
|
||||
/// // }
|
||||
/// struct Struct {
|
||||
/// struct_token: Token![struct],
|
||||
/// ident: Ident,
|
||||
/// brace_token: token::Brace,
|
||||
/// fields: Punctuated<Field, Token![,]>,
|
||||
/// }
|
||||
///
|
||||
/// struct Field {
|
||||
/// name: Ident,
|
||||
/// colon_token: Token![:],
|
||||
/// ty: Type,
|
||||
/// }
|
||||
///
|
||||
/// impl Parse for Struct {
|
||||
/// fn parse(input: ParseStream) -> Result<Self> {
|
||||
/// let content;
|
||||
/// Ok(Struct {
|
||||
/// struct_token: input.parse()?,
|
||||
/// ident: input.parse()?,
|
||||
/// brace_token: braced!(content in input),
|
||||
/// fields: content.parse_terminated(Field::parse)?,
|
||||
/// })
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl Parse for Field {
|
||||
/// fn parse(input: ParseStream) -> Result<Self> {
|
||||
/// Ok(Field {
|
||||
/// name: input.parse()?,
|
||||
/// colon_token: input.parse()?,
|
||||
/// ty: input.parse()?,
|
||||
/// })
|
||||
/// }
|
||||
/// }
|
||||
/// #
|
||||
/// # fn main() {
|
||||
/// # let input = quote! {
|
||||
/// # struct S {
|
||||
/// # a: A,
|
||||
/// # b: B,
|
||||
/// # }
|
||||
/// # };
|
||||
/// # syn::parse2::<Struct>(input).unwrap();
|
||||
/// # }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
macro_rules! braced {
|
||||
($content:ident in $cursor:expr) => {
|
||||
match $crate::group::parse_braces(&$cursor) {
|
||||
$crate::__private::Ok(braces) => {
|
||||
$content = braces.content;
|
||||
braces.token
|
||||
}
|
||||
$crate::__private::Err(error) => {
|
||||
return $crate::__private::Err(error);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Parse a set of square brackets and expose their content to subsequent
|
||||
/// parsers.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use quote::quote;
|
||||
/// #
|
||||
/// use proc_macro2::TokenStream;
|
||||
/// use syn::{bracketed, token, Result, Token};
|
||||
/// use syn::parse::{Parse, ParseStream};
|
||||
///
|
||||
/// // Parse an outer attribute like:
|
||||
/// //
|
||||
/// // #[repr(C, packed)]
|
||||
/// struct OuterAttribute {
|
||||
/// pound_token: Token![#],
|
||||
/// bracket_token: token::Bracket,
|
||||
/// content: TokenStream,
|
||||
/// }
|
||||
///
|
||||
/// impl Parse for OuterAttribute {
|
||||
/// fn parse(input: ParseStream) -> Result<Self> {
|
||||
/// let content;
|
||||
/// Ok(OuterAttribute {
|
||||
/// pound_token: input.parse()?,
|
||||
/// bracket_token: bracketed!(content in input),
|
||||
/// content: content.parse()?,
|
||||
/// })
|
||||
/// }
|
||||
/// }
|
||||
/// #
|
||||
/// # fn main() {
|
||||
/// # let input = quote! {
|
||||
/// # #[repr(C, packed)]
|
||||
/// # };
|
||||
/// # syn::parse2::<OuterAttribute>(input).unwrap();
|
||||
/// # }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
macro_rules! bracketed {
|
||||
($content:ident in $cursor:expr) => {
|
||||
match $crate::group::parse_brackets(&$cursor) {
|
||||
$crate::__private::Ok(brackets) => {
|
||||
$content = brackets.content;
|
||||
brackets.token
|
||||
}
|
||||
$crate::__private::Err(error) => {
|
||||
return $crate::__private::Err(error);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
101
zeroidc/vendor/syn/src/ident.rs
vendored
Normal file
101
zeroidc/vendor/syn/src/ident.rs
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
#[cfg(feature = "parsing")]
|
||||
use crate::buffer::Cursor;
|
||||
#[cfg(feature = "parsing")]
|
||||
use crate::lookahead;
|
||||
#[cfg(feature = "parsing")]
|
||||
use crate::parse::{Parse, ParseStream, Result};
|
||||
#[cfg(feature = "parsing")]
|
||||
use crate::token::Token;
|
||||
|
||||
pub use proc_macro2::Ident;
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
#[doc(hidden)]
|
||||
#[allow(non_snake_case)]
|
||||
pub fn Ident(marker: lookahead::TokenMarker) -> Ident {
|
||||
match marker {}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
fn accept_as_ident(ident: &Ident) -> bool {
|
||||
match ident.to_string().as_str() {
|
||||
"_" |
|
||||
// Based on https://doc.rust-lang.org/grammar.html#keywords
|
||||
// and https://github.com/rust-lang/rfcs/blob/master/text/2421-unreservations-2018.md
|
||||
// and https://github.com/rust-lang/rfcs/blob/master/text/2420-unreserve-proc.md
|
||||
"abstract" | "as" | "become" | "box" | "break" | "const" | "continue" |
|
||||
"crate" | "do" | "else" | "enum" | "extern" | "false" | "final" | "fn" |
|
||||
"for" | "if" | "impl" | "in" | "let" | "loop" | "macro" | "match" |
|
||||
"mod" | "move" | "mut" | "override" | "priv" | "pub" | "ref" |
|
||||
"return" | "Self" | "self" | "static" | "struct" | "super" | "trait" |
|
||||
"true" | "type" | "typeof" | "unsafe" | "unsized" | "use" | "virtual" |
|
||||
"where" | "while" | "yield" => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for Ident {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
input.step(|cursor| {
|
||||
if let Some((ident, rest)) = cursor.ident() {
|
||||
if accept_as_ident(&ident) {
|
||||
return Ok((ident, rest));
|
||||
}
|
||||
}
|
||||
Err(cursor.error("expected identifier"))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
impl Token for Ident {
|
||||
fn peek(cursor: Cursor) -> bool {
|
||||
if let Some((ident, _rest)) = cursor.ident() {
|
||||
accept_as_ident(&ident)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn display() -> &'static str {
|
||||
"identifier"
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! ident_from_token {
|
||||
($token:ident) => {
|
||||
impl From<Token![$token]> for Ident {
|
||||
fn from(token: Token![$token]) -> Ident {
|
||||
Ident::new(stringify!($token), token.span)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
ident_from_token!(self);
|
||||
ident_from_token!(Self);
|
||||
ident_from_token!(super);
|
||||
ident_from_token!(crate);
|
||||
ident_from_token!(extern);
|
||||
|
||||
impl From<Token![_]> for Ident {
|
||||
fn from(token: Token![_]) -> Ident {
|
||||
Ident::new("_", token.span)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn xid_ok(symbol: &str) -> bool {
|
||||
let mut chars = symbol.chars();
|
||||
let first = chars.next().unwrap();
|
||||
if !(first == '_' || unicode_ident::is_xid_start(first)) {
|
||||
return false;
|
||||
}
|
||||
for ch in chars {
|
||||
if !unicode_ident::is_xid_continue(ch) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
3321
zeroidc/vendor/syn/src/item.rs
vendored
Normal file
3321
zeroidc/vendor/syn/src/item.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
989
zeroidc/vendor/syn/src/lib.rs
vendored
Normal file
989
zeroidc/vendor/syn/src/lib.rs
vendored
Normal file
@@ -0,0 +1,989 @@
|
||||
//! [![github]](https://github.com/dtolnay/syn) [![crates-io]](https://crates.io/crates/syn) [![docs-rs]](crate)
|
||||
//!
|
||||
//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
|
||||
//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
|
||||
//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K
|
||||
//!
|
||||
//! <br>
|
||||
//!
|
||||
//! Syn is a parsing library for parsing a stream of Rust tokens into a syntax
|
||||
//! tree of Rust source code.
|
||||
//!
|
||||
//! Currently this library is geared toward use in Rust procedural macros, but
|
||||
//! contains some APIs that may be useful more generally.
|
||||
//!
|
||||
//! - **Data structures** — Syn provides a complete syntax tree that can
|
||||
//! represent any valid Rust source code. The syntax tree is rooted at
|
||||
//! [`syn::File`] which represents a full source file, but there are other
|
||||
//! entry points that may be useful to procedural macros including
|
||||
//! [`syn::Item`], [`syn::Expr`] and [`syn::Type`].
|
||||
//!
|
||||
//! - **Derives** — Of particular interest to derive macros is
|
||||
//! [`syn::DeriveInput`] which is any of the three legal input items to a
|
||||
//! derive macro. An example below shows using this type in a library that can
|
||||
//! derive implementations of a user-defined trait.
|
||||
//!
|
||||
//! - **Parsing** — Parsing in Syn is built around [parser functions] with the
|
||||
//! signature `fn(ParseStream) -> Result<T>`. Every syntax tree node defined
|
||||
//! by Syn is individually parsable and may be used as a building block for
|
||||
//! custom syntaxes, or you may dream up your own brand new syntax without
|
||||
//! involving any of our syntax tree types.
|
||||
//!
|
||||
//! - **Location information** — Every token parsed by Syn is associated with a
|
||||
//! `Span` that tracks line and column information back to the source of that
|
||||
//! token. These spans allow a procedural macro to display detailed error
|
||||
//! messages pointing to all the right places in the user's code. There is an
|
||||
//! example of this below.
|
||||
//!
|
||||
//! - **Feature flags** — Functionality is aggressively feature gated so your
|
||||
//! procedural macros enable only what they need, and do not pay in compile
|
||||
//! time for all the rest.
|
||||
//!
|
||||
//! [`syn::File`]: File
|
||||
//! [`syn::Item`]: Item
|
||||
//! [`syn::Expr`]: Expr
|
||||
//! [`syn::Type`]: Type
|
||||
//! [`syn::DeriveInput`]: DeriveInput
|
||||
//! [parser functions]: mod@parse
|
||||
//!
|
||||
//! <br>
|
||||
//!
|
||||
//! # Example of a derive macro
|
||||
//!
|
||||
//! The canonical derive macro using Syn looks like this. We write an ordinary
|
||||
//! Rust function tagged with a `proc_macro_derive` attribute and the name of
|
||||
//! the trait we are deriving. Any time that derive appears in the user's code,
|
||||
//! the Rust compiler passes their data structure as tokens into our macro. We
|
||||
//! get to execute arbitrary Rust code to figure out what to do with those
|
||||
//! tokens, then hand some tokens back to the compiler to compile into the
|
||||
//! user's crate.
|
||||
//!
|
||||
//! [`TokenStream`]: proc_macro::TokenStream
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! syn = "1.0"
|
||||
//! quote = "1.0"
|
||||
//!
|
||||
//! [lib]
|
||||
//! proc-macro = true
|
||||
//! ```
|
||||
//!
|
||||
//! ```
|
||||
//! # extern crate proc_macro;
|
||||
//! #
|
||||
//! use proc_macro::TokenStream;
|
||||
//! use quote::quote;
|
||||
//! use syn::{parse_macro_input, DeriveInput};
|
||||
//!
|
||||
//! # const IGNORE_TOKENS: &str = stringify! {
|
||||
//! #[proc_macro_derive(MyMacro)]
|
||||
//! # };
|
||||
//! pub fn my_macro(input: TokenStream) -> TokenStream {
|
||||
//! // Parse the input tokens into a syntax tree
|
||||
//! let input = parse_macro_input!(input as DeriveInput);
|
||||
//!
|
||||
//! // Build the output, possibly using quasi-quotation
|
||||
//! let expanded = quote! {
|
||||
//! // ...
|
||||
//! };
|
||||
//!
|
||||
//! // Hand the output tokens back to the compiler
|
||||
//! TokenStream::from(expanded)
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! The [`heapsize`] example directory shows a complete working implementation
|
||||
//! of a derive macro. It works on any Rust compiler 1.31+. The example derives
|
||||
//! a `HeapSize` trait which computes an estimate of the amount of heap memory
|
||||
//! owned by a value.
|
||||
//!
|
||||
//! [`heapsize`]: https://github.com/dtolnay/syn/tree/master/examples/heapsize
|
||||
//!
|
||||
//! ```
|
||||
//! pub trait HeapSize {
|
||||
//! /// Total number of bytes of heap memory owned by `self`.
|
||||
//! fn heap_size_of_children(&self) -> usize;
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! The derive macro allows users to write `#[derive(HeapSize)]` on data
|
||||
//! structures in their program.
|
||||
//!
|
||||
//! ```
|
||||
//! # const IGNORE_TOKENS: &str = stringify! {
|
||||
//! #[derive(HeapSize)]
|
||||
//! # };
|
||||
//! struct Demo<'a, T: ?Sized> {
|
||||
//! a: Box<T>,
|
||||
//! b: u8,
|
||||
//! c: &'a str,
|
||||
//! d: String,
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! <p><br></p>
|
||||
//!
|
||||
//! # Spans and error reporting
|
||||
//!
|
||||
//! The token-based procedural macro API provides great control over where the
|
||||
//! compiler's error messages are displayed in user code. Consider the error the
|
||||
//! user sees if one of their field types does not implement `HeapSize`.
|
||||
//!
|
||||
//! ```
|
||||
//! # const IGNORE_TOKENS: &str = stringify! {
|
||||
//! #[derive(HeapSize)]
|
||||
//! # };
|
||||
//! struct Broken {
|
||||
//! ok: String,
|
||||
//! bad: std::thread::Thread,
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! By tracking span information all the way through the expansion of a
|
||||
//! procedural macro as shown in the `heapsize` example, token-based macros in
|
||||
//! Syn are able to trigger errors that directly pinpoint the source of the
|
||||
//! problem.
|
||||
//!
|
||||
//! ```text
|
||||
//! error[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied
|
||||
//! --> src/main.rs:7:5
|
||||
//! |
|
||||
//! 7 | bad: std::thread::Thread,
|
||||
//! | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HeapSize` is not implemented for `Thread`
|
||||
//! ```
|
||||
//!
|
||||
//! <br>
|
||||
//!
|
||||
//! # Parsing a custom syntax
|
||||
//!
|
||||
//! The [`lazy-static`] example directory shows the implementation of a
|
||||
//! `functionlike!(...)` procedural macro in which the input tokens are parsed
|
||||
//! using Syn's parsing API.
|
||||
//!
|
||||
//! [`lazy-static`]: https://github.com/dtolnay/syn/tree/master/examples/lazy-static
|
||||
//!
|
||||
//! The example reimplements the popular `lazy_static` crate from crates.io as a
|
||||
//! procedural macro.
|
||||
//!
|
||||
//! ```
|
||||
//! # macro_rules! lazy_static {
|
||||
//! # ($($tt:tt)*) => {}
|
||||
//! # }
|
||||
//! #
|
||||
//! lazy_static! {
|
||||
//! static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap();
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! The implementation shows how to trigger custom warnings and error messages
|
||||
//! on the macro input.
|
||||
//!
|
||||
//! ```text
|
||||
//! warning: come on, pick a more creative name
|
||||
//! --> src/main.rs:10:16
|
||||
//! |
|
||||
//! 10 | static ref FOO: String = "lazy_static".to_owned();
|
||||
//! | ^^^
|
||||
//! ```
|
||||
//!
|
||||
//! <br>
|
||||
//!
|
||||
//! # Testing
|
||||
//!
|
||||
//! When testing macros, we often care not just that the macro can be used
|
||||
//! successfully but also that when the macro is provided with invalid input it
|
||||
//! produces maximally helpful error messages. Consider using the [`trybuild`]
|
||||
//! crate to write tests for errors that are emitted by your macro or errors
|
||||
//! detected by the Rust compiler in the expanded code following misuse of the
|
||||
//! macro. Such tests help avoid regressions from later refactors that
|
||||
//! mistakenly make an error no longer trigger or be less helpful than it used
|
||||
//! to be.
|
||||
//!
|
||||
//! [`trybuild`]: https://github.com/dtolnay/trybuild
|
||||
//!
|
||||
//! <br>
|
||||
//!
|
||||
//! # Debugging
|
||||
//!
|
||||
//! When developing a procedural macro it can be helpful to look at what the
|
||||
//! generated code looks like. Use `cargo rustc -- -Zunstable-options
|
||||
//! --pretty=expanded` or the [`cargo expand`] subcommand.
|
||||
//!
|
||||
//! [`cargo expand`]: https://github.com/dtolnay/cargo-expand
|
||||
//!
|
||||
//! To show the expanded code for some crate that uses your procedural macro,
|
||||
//! run `cargo expand` from that crate. To show the expanded code for one of
|
||||
//! your own test cases, run `cargo expand --test the_test_case` where the last
|
||||
//! argument is the name of the test file without the `.rs` extension.
|
||||
//!
|
||||
//! This write-up by Brandon W Maister discusses debugging in more detail:
|
||||
//! [Debugging Rust's new Custom Derive system][debugging].
|
||||
//!
|
||||
//! [debugging]: https://quodlibetor.github.io/posts/debugging-rusts-new-custom-derive-system/
|
||||
//!
|
||||
//! <br>
|
||||
//!
|
||||
//! # Optional features
|
||||
//!
|
||||
//! Syn puts a lot of functionality behind optional features in order to
|
||||
//! optimize compile time for the most common use cases. The following features
|
||||
//! are available.
|
||||
//!
|
||||
//! - **`derive`** *(enabled by default)* — Data structures for representing the
|
||||
//! possible input to a derive macro, including structs and enums and types.
|
||||
//! - **`full`** — Data structures for representing the syntax tree of all valid
|
||||
//! Rust source code, including items and expressions.
|
||||
//! - **`parsing`** *(enabled by default)* — Ability to parse input tokens into
|
||||
//! a syntax tree node of a chosen type.
|
||||
//! - **`printing`** *(enabled by default)* — Ability to print a syntax tree
|
||||
//! node as tokens of Rust source code.
|
||||
//! - **`visit`** — Trait for traversing a syntax tree.
|
||||
//! - **`visit-mut`** — Trait for traversing and mutating in place a syntax
|
||||
//! tree.
|
||||
//! - **`fold`** — Trait for transforming an owned syntax tree.
|
||||
//! - **`clone-impls`** *(enabled by default)* — Clone impls for all syntax tree
|
||||
//! types.
|
||||
//! - **`extra-traits`** — Debug, Eq, PartialEq, Hash impls for all syntax tree
|
||||
//! types.
|
||||
//! - **`proc-macro`** *(enabled by default)* — Runtime dependency on the
|
||||
//! dynamic library libproc_macro from rustc toolchain.
|
||||
|
||||
// Syn types in rustdoc of other crates get linked to here.
|
||||
#![doc(html_root_url = "https://docs.rs/syn/1.0.96")]
|
||||
#![cfg_attr(doc_cfg, feature(doc_cfg))]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(
|
||||
clippy::cast_lossless,
|
||||
clippy::cast_possible_truncation,
|
||||
clippy::default_trait_access,
|
||||
clippy::doc_markdown,
|
||||
clippy::expl_impl_clone_on_copy,
|
||||
clippy::if_not_else,
|
||||
clippy::inherent_to_string,
|
||||
clippy::large_enum_variant,
|
||||
clippy::let_underscore_drop,
|
||||
clippy::manual_assert,
|
||||
clippy::match_on_vec_items,
|
||||
clippy::match_same_arms,
|
||||
clippy::match_wildcard_for_single_variants, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984
|
||||
clippy::missing_errors_doc,
|
||||
clippy::missing_panics_doc,
|
||||
clippy::module_name_repetitions,
|
||||
clippy::must_use_candidate,
|
||||
clippy::needless_doctest_main,
|
||||
clippy::needless_pass_by_value,
|
||||
clippy::never_loop,
|
||||
clippy::redundant_else,
|
||||
clippy::return_self_not_must_use,
|
||||
clippy::similar_names,
|
||||
clippy::single_match_else,
|
||||
clippy::too_many_arguments,
|
||||
clippy::too_many_lines,
|
||||
clippy::trivially_copy_pass_by_ref,
|
||||
clippy::unnecessary_unwrap,
|
||||
clippy::used_underscore_binding,
|
||||
clippy::wildcard_imports
|
||||
)]
|
||||
|
||||
#[cfg(all(
|
||||
not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
|
||||
feature = "proc-macro"
|
||||
))]
|
||||
extern crate proc_macro;
|
||||
extern crate proc_macro2;
|
||||
|
||||
#[cfg(feature = "printing")]
|
||||
extern crate quote;
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
// Not public API.
|
||||
#[cfg(feature = "parsing")]
|
||||
#[doc(hidden)]
|
||||
#[macro_use]
|
||||
pub mod group;
|
||||
|
||||
#[macro_use]
|
||||
pub mod token;
|
||||
|
||||
mod ident;
|
||||
pub use crate::ident::Ident;
|
||||
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
mod attr;
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
pub use crate::attr::{
|
||||
AttrStyle, Attribute, AttributeArgs, Meta, MetaList, MetaNameValue, NestedMeta,
|
||||
};
|
||||
|
||||
mod bigint;
|
||||
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
mod data;
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
pub use crate::data::{
|
||||
Field, Fields, FieldsNamed, FieldsUnnamed, Variant, VisCrate, VisPublic, VisRestricted,
|
||||
Visibility,
|
||||
};
|
||||
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
mod expr;
|
||||
#[cfg(feature = "full")]
|
||||
pub use crate::expr::{
|
||||
Arm, FieldValue, GenericMethodArgument, Label, MethodTurbofish, RangeLimits,
|
||||
};
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
pub use crate::expr::{
|
||||
Expr, ExprArray, ExprAssign, ExprAssignOp, ExprAsync, ExprAwait, ExprBinary, ExprBlock,
|
||||
ExprBox, ExprBreak, ExprCall, ExprCast, ExprClosure, ExprContinue, ExprField, ExprForLoop,
|
||||
ExprGroup, ExprIf, ExprIndex, ExprLet, ExprLit, ExprLoop, ExprMacro, ExprMatch, ExprMethodCall,
|
||||
ExprParen, ExprPath, ExprRange, ExprReference, ExprRepeat, ExprReturn, ExprStruct, ExprTry,
|
||||
ExprTryBlock, ExprTuple, ExprType, ExprUnary, ExprUnsafe, ExprWhile, ExprYield, Index, Member,
|
||||
};
|
||||
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
mod generics;
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
pub use crate::generics::{
|
||||
BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeDef, PredicateEq,
|
||||
PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound,
|
||||
WhereClause, WherePredicate,
|
||||
};
|
||||
#[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
|
||||
pub use crate::generics::{ImplGenerics, Turbofish, TypeGenerics};
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
mod item;
|
||||
#[cfg(feature = "full")]
|
||||
pub use crate::item::{
|
||||
FnArg, ForeignItem, ForeignItemFn, ForeignItemMacro, ForeignItemStatic, ForeignItemType,
|
||||
ImplItem, ImplItemConst, ImplItemMacro, ImplItemMethod, ImplItemType, Item, ItemConst,
|
||||
ItemEnum, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, ItemMacro, ItemMacro2, ItemMod,
|
||||
ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType, ItemUnion, ItemUse, Receiver,
|
||||
Signature, TraitItem, TraitItemConst, TraitItemMacro, TraitItemMethod, TraitItemType, UseGlob,
|
||||
UseGroup, UseName, UsePath, UseRename, UseTree,
|
||||
};
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
mod file;
|
||||
#[cfg(feature = "full")]
|
||||
pub use crate::file::File;
|
||||
|
||||
mod lifetime;
|
||||
pub use crate::lifetime::Lifetime;
|
||||
|
||||
mod lit;
|
||||
pub use crate::lit::{
|
||||
Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr, StrStyle,
|
||||
};
|
||||
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
mod mac;
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
pub use crate::mac::{Macro, MacroDelimiter};
|
||||
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
mod derive;
|
||||
#[cfg(feature = "derive")]
|
||||
pub use crate::derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput};
|
||||
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
mod op;
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
pub use crate::op::{BinOp, UnOp};
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
mod stmt;
|
||||
#[cfg(feature = "full")]
|
||||
pub use crate::stmt::{Block, Local, Stmt};
|
||||
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
mod ty;
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
pub use crate::ty::{
|
||||
Abi, BareFnArg, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup, TypeImplTrait, TypeInfer,
|
||||
TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference, TypeSlice, TypeTraitObject,
|
||||
TypeTuple, Variadic,
|
||||
};
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
mod pat;
|
||||
#[cfg(feature = "full")]
|
||||
pub use crate::pat::{
|
||||
FieldPat, Pat, PatBox, PatIdent, PatLit, PatMacro, PatOr, PatPath, PatRange, PatReference,
|
||||
PatRest, PatSlice, PatStruct, PatTuple, PatTupleStruct, PatType, PatWild,
|
||||
};
|
||||
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
mod path;
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
pub use crate::path::{
|
||||
AngleBracketedGenericArguments, Binding, Constraint, GenericArgument,
|
||||
ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf,
|
||||
};
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
pub mod buffer;
|
||||
#[cfg(feature = "parsing")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
pub mod ext;
|
||||
pub mod punctuated;
|
||||
#[cfg(all(any(feature = "full", feature = "derive"), feature = "extra-traits"))]
|
||||
mod tt;
|
||||
|
||||
// Not public API except the `parse_quote!` macro.
|
||||
#[cfg(feature = "parsing")]
|
||||
#[doc(hidden)]
|
||||
pub mod parse_quote;
|
||||
|
||||
// Not public API except the `parse_macro_input!` macro.
|
||||
#[cfg(all(
|
||||
not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
|
||||
feature = "parsing",
|
||||
feature = "proc-macro"
|
||||
))]
|
||||
#[doc(hidden)]
|
||||
pub mod parse_macro_input;
|
||||
|
||||
#[cfg(all(feature = "parsing", feature = "printing"))]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "printing"))))]
|
||||
pub mod spanned;
|
||||
|
||||
#[cfg(all(feature = "parsing", feature = "full"))]
|
||||
mod whitespace;
|
||||
|
||||
mod gen {
|
||||
/// Syntax tree traversal to walk a shared borrow of a syntax tree.
|
||||
///
|
||||
/// Each method of the [`Visit`] trait is a hook that can be overridden to
|
||||
/// customize the behavior when visiting the corresponding type of node. By
|
||||
/// default, every method recursively visits the substructure of the input
|
||||
/// by invoking the right visitor method of each of its fields.
|
||||
///
|
||||
/// [`Visit`]: visit::Visit
|
||||
///
|
||||
/// ```
|
||||
/// # use syn::{Attribute, BinOp, Expr, ExprBinary};
|
||||
/// #
|
||||
/// pub trait Visit<'ast> {
|
||||
/// /* ... */
|
||||
///
|
||||
/// fn visit_expr_binary(&mut self, node: &'ast ExprBinary) {
|
||||
/// visit_expr_binary(self, node);
|
||||
/// }
|
||||
///
|
||||
/// /* ... */
|
||||
/// # fn visit_attribute(&mut self, node: &'ast Attribute);
|
||||
/// # fn visit_expr(&mut self, node: &'ast Expr);
|
||||
/// # fn visit_bin_op(&mut self, node: &'ast BinOp);
|
||||
/// }
|
||||
///
|
||||
/// pub fn visit_expr_binary<'ast, V>(v: &mut V, node: &'ast ExprBinary)
|
||||
/// where
|
||||
/// V: Visit<'ast> + ?Sized,
|
||||
/// {
|
||||
/// for attr in &node.attrs {
|
||||
/// v.visit_attribute(attr);
|
||||
/// }
|
||||
/// v.visit_expr(&*node.left);
|
||||
/// v.visit_bin_op(&node.op);
|
||||
/// v.visit_expr(&*node.right);
|
||||
/// }
|
||||
///
|
||||
/// /* ... */
|
||||
/// ```
|
||||
///
|
||||
/// *This module is available only if Syn is built with the `"visit"` feature.*
|
||||
///
|
||||
/// <br>
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// This visitor will print the name of every freestanding function in the
|
||||
/// syntax tree, including nested functions.
|
||||
///
|
||||
/// ```
|
||||
/// // [dependencies]
|
||||
/// // quote = "1.0"
|
||||
/// // syn = { version = "1.0", features = ["full", "visit"] }
|
||||
///
|
||||
/// use quote::quote;
|
||||
/// use syn::visit::{self, Visit};
|
||||
/// use syn::{File, ItemFn};
|
||||
///
|
||||
/// struct FnVisitor;
|
||||
///
|
||||
/// impl<'ast> Visit<'ast> for FnVisitor {
|
||||
/// fn visit_item_fn(&mut self, node: &'ast ItemFn) {
|
||||
/// println!("Function with name={}", node.sig.ident);
|
||||
///
|
||||
/// // Delegate to the default impl to visit any nested functions.
|
||||
/// visit::visit_item_fn(self, node);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let code = quote! {
|
||||
/// pub fn f() {
|
||||
/// fn g() {}
|
||||
/// }
|
||||
/// };
|
||||
///
|
||||
/// let syntax_tree: File = syn::parse2(code).unwrap();
|
||||
/// FnVisitor.visit_file(&syntax_tree);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The `'ast` lifetime on the input references means that the syntax tree
|
||||
/// outlives the complete recursive visit call, so the visitor is allowed to
|
||||
/// hold on to references into the syntax tree.
|
||||
///
|
||||
/// ```
|
||||
/// use quote::quote;
|
||||
/// use syn::visit::{self, Visit};
|
||||
/// use syn::{File, ItemFn};
|
||||
///
|
||||
/// struct FnVisitor<'ast> {
|
||||
/// functions: Vec<&'ast ItemFn>,
|
||||
/// }
|
||||
///
|
||||
/// impl<'ast> Visit<'ast> for FnVisitor<'ast> {
|
||||
/// fn visit_item_fn(&mut self, node: &'ast ItemFn) {
|
||||
/// self.functions.push(node);
|
||||
/// visit::visit_item_fn(self, node);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let code = quote! {
|
||||
/// pub fn f() {
|
||||
/// fn g() {}
|
||||
/// }
|
||||
/// };
|
||||
///
|
||||
/// let syntax_tree: File = syn::parse2(code).unwrap();
|
||||
/// let mut visitor = FnVisitor { functions: Vec::new() };
|
||||
/// visitor.visit_file(&syntax_tree);
|
||||
/// for f in visitor.functions {
|
||||
/// println!("Function with name={}", f.sig.ident);
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg(feature = "visit")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "visit")))]
|
||||
#[rustfmt::skip]
|
||||
pub mod visit;
|
||||
|
||||
/// Syntax tree traversal to mutate an exclusive borrow of a syntax tree in
|
||||
/// place.
|
||||
///
|
||||
/// Each method of the [`VisitMut`] trait is a hook that can be overridden
|
||||
/// to customize the behavior when mutating the corresponding type of node.
|
||||
/// By default, every method recursively visits the substructure of the
|
||||
/// input by invoking the right visitor method of each of its fields.
|
||||
///
|
||||
/// [`VisitMut`]: visit_mut::VisitMut
|
||||
///
|
||||
/// ```
|
||||
/// # use syn::{Attribute, BinOp, Expr, ExprBinary};
|
||||
/// #
|
||||
/// pub trait VisitMut {
|
||||
/// /* ... */
|
||||
///
|
||||
/// fn visit_expr_binary_mut(&mut self, node: &mut ExprBinary) {
|
||||
/// visit_expr_binary_mut(self, node);
|
||||
/// }
|
||||
///
|
||||
/// /* ... */
|
||||
/// # fn visit_attribute_mut(&mut self, node: &mut Attribute);
|
||||
/// # fn visit_expr_mut(&mut self, node: &mut Expr);
|
||||
/// # fn visit_bin_op_mut(&mut self, node: &mut BinOp);
|
||||
/// }
|
||||
///
|
||||
/// pub fn visit_expr_binary_mut<V>(v: &mut V, node: &mut ExprBinary)
|
||||
/// where
|
||||
/// V: VisitMut + ?Sized,
|
||||
/// {
|
||||
/// for attr in &mut node.attrs {
|
||||
/// v.visit_attribute_mut(attr);
|
||||
/// }
|
||||
/// v.visit_expr_mut(&mut *node.left);
|
||||
/// v.visit_bin_op_mut(&mut node.op);
|
||||
/// v.visit_expr_mut(&mut *node.right);
|
||||
/// }
|
||||
///
|
||||
/// /* ... */
|
||||
/// ```
|
||||
///
|
||||
/// *This module is available only if Syn is built with the `"visit-mut"`
|
||||
/// feature.*
|
||||
///
|
||||
/// <br>
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// This mut visitor replace occurrences of u256 suffixed integer literals
|
||||
/// like `999u256` with a macro invocation `bigint::u256!(999)`.
|
||||
///
|
||||
/// ```
|
||||
/// // [dependencies]
|
||||
/// // quote = "1.0"
|
||||
/// // syn = { version = "1.0", features = ["full", "visit-mut"] }
|
||||
///
|
||||
/// use quote::quote;
|
||||
/// use syn::visit_mut::{self, VisitMut};
|
||||
/// use syn::{parse_quote, Expr, File, Lit, LitInt};
|
||||
///
|
||||
/// struct BigintReplace;
|
||||
///
|
||||
/// impl VisitMut for BigintReplace {
|
||||
/// fn visit_expr_mut(&mut self, node: &mut Expr) {
|
||||
/// if let Expr::Lit(expr) = &node {
|
||||
/// if let Lit::Int(int) = &expr.lit {
|
||||
/// if int.suffix() == "u256" {
|
||||
/// let digits = int.base10_digits();
|
||||
/// let unsuffixed: LitInt = syn::parse_str(digits).unwrap();
|
||||
/// *node = parse_quote!(bigint::u256!(#unsuffixed));
|
||||
/// return;
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // Delegate to the default impl to visit nested expressions.
|
||||
/// visit_mut::visit_expr_mut(self, node);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let code = quote! {
|
||||
/// fn main() {
|
||||
/// let _ = 999u256;
|
||||
/// }
|
||||
/// };
|
||||
///
|
||||
/// let mut syntax_tree: File = syn::parse2(code).unwrap();
|
||||
/// BigintReplace.visit_file_mut(&mut syntax_tree);
|
||||
/// println!("{}", quote!(#syntax_tree));
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg(feature = "visit-mut")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "visit-mut")))]
|
||||
#[rustfmt::skip]
|
||||
pub mod visit_mut;
|
||||
|
||||
/// Syntax tree traversal to transform the nodes of an owned syntax tree.
|
||||
///
|
||||
/// Each method of the [`Fold`] trait is a hook that can be overridden to
|
||||
/// customize the behavior when transforming the corresponding type of node.
|
||||
/// By default, every method recursively visits the substructure of the
|
||||
/// input by invoking the right visitor method of each of its fields.
|
||||
///
|
||||
/// [`Fold`]: fold::Fold
|
||||
///
|
||||
/// ```
|
||||
/// # use syn::{Attribute, BinOp, Expr, ExprBinary};
|
||||
/// #
|
||||
/// pub trait Fold {
|
||||
/// /* ... */
|
||||
///
|
||||
/// fn fold_expr_binary(&mut self, node: ExprBinary) -> ExprBinary {
|
||||
/// fold_expr_binary(self, node)
|
||||
/// }
|
||||
///
|
||||
/// /* ... */
|
||||
/// # fn fold_attribute(&mut self, node: Attribute) -> Attribute;
|
||||
/// # fn fold_expr(&mut self, node: Expr) -> Expr;
|
||||
/// # fn fold_bin_op(&mut self, node: BinOp) -> BinOp;
|
||||
/// }
|
||||
///
|
||||
/// pub fn fold_expr_binary<V>(v: &mut V, node: ExprBinary) -> ExprBinary
|
||||
/// where
|
||||
/// V: Fold + ?Sized,
|
||||
/// {
|
||||
/// ExprBinary {
|
||||
/// attrs: node
|
||||
/// .attrs
|
||||
/// .into_iter()
|
||||
/// .map(|attr| v.fold_attribute(attr))
|
||||
/// .collect(),
|
||||
/// left: Box::new(v.fold_expr(*node.left)),
|
||||
/// op: v.fold_bin_op(node.op),
|
||||
/// right: Box::new(v.fold_expr(*node.right)),
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// /* ... */
|
||||
/// ```
|
||||
///
|
||||
/// *This module is available only if Syn is built with the `"fold"` feature.*
|
||||
///
|
||||
/// <br>
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// This fold inserts parentheses to fully parenthesizes any expression.
|
||||
///
|
||||
/// ```
|
||||
/// // [dependencies]
|
||||
/// // quote = "1.0"
|
||||
/// // syn = { version = "1.0", features = ["fold", "full"] }
|
||||
///
|
||||
/// use quote::quote;
|
||||
/// use syn::fold::{fold_expr, Fold};
|
||||
/// use syn::{token, Expr, ExprParen};
|
||||
///
|
||||
/// struct ParenthesizeEveryExpr;
|
||||
///
|
||||
/// impl Fold for ParenthesizeEveryExpr {
|
||||
/// fn fold_expr(&mut self, expr: Expr) -> Expr {
|
||||
/// Expr::Paren(ExprParen {
|
||||
/// attrs: Vec::new(),
|
||||
/// expr: Box::new(fold_expr(self, expr)),
|
||||
/// paren_token: token::Paren::default(),
|
||||
/// })
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let code = quote! { a() + b(1) * c.d };
|
||||
/// let expr: Expr = syn::parse2(code).unwrap();
|
||||
/// let parenthesized = ParenthesizeEveryExpr.fold_expr(expr);
|
||||
/// println!("{}", quote!(#parenthesized));
|
||||
///
|
||||
/// // Output: (((a)()) + (((b)((1))) * ((c).d)))
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg(feature = "fold")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "fold")))]
|
||||
#[rustfmt::skip]
|
||||
pub mod fold;
|
||||
|
||||
#[cfg(feature = "clone-impls")]
|
||||
#[rustfmt::skip]
|
||||
mod clone;
|
||||
|
||||
#[cfg(feature = "extra-traits")]
|
||||
#[rustfmt::skip]
|
||||
mod eq;
|
||||
|
||||
#[cfg(feature = "extra-traits")]
|
||||
#[rustfmt::skip]
|
||||
mod hash;
|
||||
|
||||
#[cfg(feature = "extra-traits")]
|
||||
#[rustfmt::skip]
|
||||
mod debug;
|
||||
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
#[path = "../gen_helper.rs"]
|
||||
mod helper;
|
||||
}
|
||||
pub use crate::gen::*;
|
||||
|
||||
// Not public API.
|
||||
#[doc(hidden)]
|
||||
#[path = "export.rs"]
|
||||
pub mod __private;
|
||||
|
||||
mod custom_keyword;
|
||||
mod custom_punctuation;
|
||||
mod sealed;
|
||||
mod span;
|
||||
mod thread;
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
mod lookahead;
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
pub mod parse;
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
mod reserved;
|
||||
|
||||
#[cfg(all(any(feature = "full", feature = "derive"), feature = "parsing"))]
|
||||
mod verbatim;
|
||||
|
||||
#[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
|
||||
mod print;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// https://github.com/rust-lang/rust/issues/62830
|
||||
#[cfg(feature = "parsing")]
|
||||
mod rustdoc_workaround {
|
||||
pub use crate::parse::{self as parse_module};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
mod error;
|
||||
pub use crate::error::{Error, Result};
|
||||
|
||||
/// Parse tokens of source code into the chosen syntax tree node.
|
||||
///
|
||||
/// This is preferred over parsing a string because tokens are able to preserve
|
||||
/// information about where in the user's code they were originally written (the
|
||||
/// "span" of the token), possibly allowing the compiler to produce better error
|
||||
/// messages.
|
||||
///
|
||||
/// This function parses a `proc_macro::TokenStream` which is the type used for
|
||||
/// interop with the compiler in a procedural macro. To parse a
|
||||
/// `proc_macro2::TokenStream`, use [`syn::parse2`] instead.
|
||||
///
|
||||
/// [`syn::parse2`]: parse2
|
||||
///
|
||||
/// *This function is available only if Syn is built with both the `"parsing"` and
|
||||
/// `"proc-macro"` features.*
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate proc_macro;
|
||||
/// #
|
||||
/// use proc_macro::TokenStream;
|
||||
/// use quote::quote;
|
||||
/// use syn::DeriveInput;
|
||||
///
|
||||
/// # const IGNORE_TOKENS: &str = stringify! {
|
||||
/// #[proc_macro_derive(MyMacro)]
|
||||
/// # };
|
||||
/// pub fn my_macro(input: TokenStream) -> TokenStream {
|
||||
/// // Parse the tokens into a syntax tree
|
||||
/// let ast: DeriveInput = syn::parse(input).unwrap();
|
||||
///
|
||||
/// // Build the output, possibly using quasi-quotation
|
||||
/// let expanded = quote! {
|
||||
/// /* ... */
|
||||
/// };
|
||||
///
|
||||
/// // Convert into a token stream and return it
|
||||
/// expanded.into()
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg(all(
|
||||
not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
|
||||
feature = "parsing",
|
||||
feature = "proc-macro"
|
||||
))]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "proc-macro"))))]
|
||||
pub fn parse<T: parse::Parse>(tokens: proc_macro::TokenStream) -> Result<T> {
|
||||
parse::Parser::parse(T::parse, tokens)
|
||||
}
|
||||
|
||||
/// Parse a proc-macro2 token stream into the chosen syntax tree node.
|
||||
///
|
||||
/// This function will check that the input is fully parsed. If there are
|
||||
/// any unparsed tokens at the end of the stream, an error is returned.
|
||||
///
|
||||
/// This function parses a `proc_macro2::TokenStream` which is commonly useful
|
||||
/// when the input comes from a node of the Syn syntax tree, for example the
|
||||
/// body tokens of a [`Macro`] node. When in a procedural macro parsing the
|
||||
/// `proc_macro::TokenStream` provided by the compiler, use [`syn::parse`]
|
||||
/// instead.
|
||||
///
|
||||
/// [`syn::parse`]: parse()
|
||||
///
|
||||
/// *This function is available only if Syn is built with the `"parsing"` feature.*
|
||||
#[cfg(feature = "parsing")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
pub fn parse2<T: parse::Parse>(tokens: proc_macro2::TokenStream) -> Result<T> {
|
||||
parse::Parser::parse2(T::parse, tokens)
|
||||
}
|
||||
|
||||
/// Parse a string of Rust code into the chosen syntax tree node.
|
||||
///
|
||||
/// *This function is available only if Syn is built with the `"parsing"` feature.*
|
||||
///
|
||||
/// # Hygiene
|
||||
///
|
||||
/// Every span in the resulting syntax tree will be set to resolve at the macro
|
||||
/// call site.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use syn::{Expr, Result};
|
||||
///
|
||||
/// fn run() -> Result<()> {
|
||||
/// let code = "assert_eq!(u8::max_value(), 255)";
|
||||
/// let expr = syn::parse_str::<Expr>(code)?;
|
||||
/// println!("{:#?}", expr);
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// #
|
||||
/// # run().unwrap();
|
||||
/// ```
|
||||
#[cfg(feature = "parsing")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
pub fn parse_str<T: parse::Parse>(s: &str) -> Result<T> {
|
||||
parse::Parser::parse_str(T::parse, s)
|
||||
}
|
||||
|
||||
// FIXME the name parse_file makes it sound like you might pass in a path to a
|
||||
// file, rather than the content.
|
||||
/// Parse the content of a file of Rust code.
|
||||
///
|
||||
/// This is different from `syn::parse_str::<File>(content)` in two ways:
|
||||
///
|
||||
/// - It discards a leading byte order mark `\u{FEFF}` if the file has one.
|
||||
/// - It preserves the shebang line of the file, such as `#!/usr/bin/env rustx`.
|
||||
///
|
||||
/// If present, either of these would be an error using `from_str`.
|
||||
///
|
||||
/// *This function is available only if Syn is built with the `"parsing"` and
|
||||
/// `"full"` features.*
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::error::Error;
|
||||
/// use std::fs::File;
|
||||
/// use std::io::Read;
|
||||
///
|
||||
/// fn run() -> Result<(), Box<Error>> {
|
||||
/// let mut file = File::open("path/to/code.rs")?;
|
||||
/// let mut content = String::new();
|
||||
/// file.read_to_string(&mut content)?;
|
||||
///
|
||||
/// let ast = syn::parse_file(&content)?;
|
||||
/// if let Some(shebang) = ast.shebang {
|
||||
/// println!("{}", shebang);
|
||||
/// }
|
||||
/// println!("{} items", ast.items.len());
|
||||
///
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// #
|
||||
/// # run().unwrap();
|
||||
/// ```
|
||||
#[cfg(all(feature = "parsing", feature = "full"))]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "full"))))]
|
||||
pub fn parse_file(mut content: &str) -> Result<File> {
|
||||
// Strip the BOM if it is present
|
||||
const BOM: &str = "\u{feff}";
|
||||
if content.starts_with(BOM) {
|
||||
content = &content[BOM.len()..];
|
||||
}
|
||||
|
||||
let mut shebang = None;
|
||||
if content.starts_with("#!") {
|
||||
let rest = whitespace::skip(&content[2..]);
|
||||
if !rest.starts_with('[') {
|
||||
if let Some(idx) = content.find('\n') {
|
||||
shebang = Some(content[..idx].to_string());
|
||||
content = &content[idx..];
|
||||
} else {
|
||||
shebang = Some(content.to_string());
|
||||
content = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut file: File = parse_str(content)?;
|
||||
file.shebang = shebang;
|
||||
Ok(file)
|
||||
}
|
||||
154
zeroidc/vendor/syn/src/lifetime.rs
vendored
Normal file
154
zeroidc/vendor/syn/src/lifetime.rs
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
use proc_macro2::{Ident, Span};
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt::{self, Display};
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
use crate::lookahead;
|
||||
|
||||
/// A Rust lifetime: `'a`.
|
||||
///
|
||||
/// Lifetime names must conform to the following rules:
|
||||
///
|
||||
/// - Must start with an apostrophe.
|
||||
/// - Must not consist of just an apostrophe: `'`.
|
||||
/// - Character after the apostrophe must be `_` or a Unicode code point with
|
||||
/// the XID_Start property.
|
||||
/// - All following characters must be Unicode code points with the XID_Continue
|
||||
/// property.
|
||||
pub struct Lifetime {
|
||||
pub apostrophe: Span,
|
||||
pub ident: Ident,
|
||||
}
|
||||
|
||||
impl Lifetime {
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the lifetime does not conform to the bulleted rules above.
|
||||
///
|
||||
/// # Invocation
|
||||
///
|
||||
/// ```
|
||||
/// # use proc_macro2::Span;
|
||||
/// # use syn::Lifetime;
|
||||
/// #
|
||||
/// # fn f() -> Lifetime {
|
||||
/// Lifetime::new("'a", Span::call_site())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn new(symbol: &str, span: Span) -> Self {
|
||||
if !symbol.starts_with('\'') {
|
||||
panic!(
|
||||
"lifetime name must start with apostrophe as in \"'a\", got {:?}",
|
||||
symbol
|
||||
);
|
||||
}
|
||||
|
||||
if symbol == "'" {
|
||||
panic!("lifetime name must not be empty");
|
||||
}
|
||||
|
||||
if !crate::ident::xid_ok(&symbol[1..]) {
|
||||
panic!("{:?} is not a valid lifetime name", symbol);
|
||||
}
|
||||
|
||||
Lifetime {
|
||||
apostrophe: span,
|
||||
ident: Ident::new(&symbol[1..], span),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Span {
|
||||
self.apostrophe
|
||||
.join(self.ident.span())
|
||||
.unwrap_or(self.apostrophe)
|
||||
}
|
||||
|
||||
pub fn set_span(&mut self, span: Span) {
|
||||
self.apostrophe = span;
|
||||
self.ident.set_span(span);
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Lifetime {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
"'".fmt(formatter)?;
|
||||
self.ident.fmt(formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Lifetime {
|
||||
fn clone(&self) -> Self {
|
||||
Lifetime {
|
||||
apostrophe: self.apostrophe,
|
||||
ident: self.ident.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Lifetime {
|
||||
fn eq(&self, other: &Lifetime) -> bool {
|
||||
self.ident.eq(&other.ident)
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Lifetime {}
|
||||
|
||||
impl PartialOrd for Lifetime {
|
||||
fn partial_cmp(&self, other: &Lifetime) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Lifetime {
|
||||
fn cmp(&self, other: &Lifetime) -> Ordering {
|
||||
self.ident.cmp(&other.ident)
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Lifetime {
|
||||
fn hash<H: Hasher>(&self, h: &mut H) {
|
||||
self.ident.hash(h);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
#[doc(hidden)]
|
||||
#[allow(non_snake_case)]
|
||||
pub fn Lifetime(marker: lookahead::TokenMarker) -> Lifetime {
|
||||
match marker {}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
pub mod parsing {
|
||||
use super::*;
|
||||
use crate::parse::{Parse, ParseStream, Result};
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for Lifetime {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
input.step(|cursor| {
|
||||
cursor
|
||||
.lifetime()
|
||||
.ok_or_else(|| cursor.error("expected lifetime"))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "printing")]
|
||||
mod printing {
|
||||
use super::*;
|
||||
use proc_macro2::{Punct, Spacing, TokenStream};
|
||||
use quote::{ToTokens, TokenStreamExt};
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for Lifetime {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let mut apostrophe = Punct::new('\'', Spacing::Joint);
|
||||
apostrophe.set_span(self.apostrophe);
|
||||
tokens.append(apostrophe);
|
||||
self.ident.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
}
|
||||
1600
zeroidc/vendor/syn/src/lit.rs
vendored
Normal file
1600
zeroidc/vendor/syn/src/lit.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
169
zeroidc/vendor/syn/src/lookahead.rs
vendored
Normal file
169
zeroidc/vendor/syn/src/lookahead.rs
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
use crate::buffer::Cursor;
|
||||
use crate::error::{self, Error};
|
||||
use crate::sealed::lookahead::Sealed;
|
||||
use crate::span::IntoSpans;
|
||||
use crate::token::Token;
|
||||
use proc_macro2::{Delimiter, Span};
|
||||
use std::cell::RefCell;
|
||||
|
||||
/// Support for checking the next token in a stream to decide how to parse.
|
||||
///
|
||||
/// An important advantage over [`ParseStream::peek`] is that here we
|
||||
/// automatically construct an appropriate error message based on the token
|
||||
/// alternatives that get peeked. If you are producing your own error message,
|
||||
/// go ahead and use `ParseStream::peek` instead.
|
||||
///
|
||||
/// Use [`ParseStream::lookahead1`] to construct this object.
|
||||
///
|
||||
/// [`ParseStream::peek`]: crate::parse::ParseBuffer::peek
|
||||
/// [`ParseStream::lookahead1`]: crate::parse::ParseBuffer::lookahead1
|
||||
///
|
||||
/// Consuming tokens from the source stream after constructing a lookahead
|
||||
/// object does not also advance the lookahead object.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use syn::{ConstParam, Ident, Lifetime, LifetimeDef, Result, Token, TypeParam};
|
||||
/// use syn::parse::{Parse, ParseStream};
|
||||
///
|
||||
/// // A generic parameter, a single one of the comma-separated elements inside
|
||||
/// // angle brackets in:
|
||||
/// //
|
||||
/// // fn f<T: Clone, 'a, 'b: 'a, const N: usize>() { ... }
|
||||
/// //
|
||||
/// // On invalid input, lookahead gives us a reasonable error message.
|
||||
/// //
|
||||
/// // error: expected one of: identifier, lifetime, `const`
|
||||
/// // |
|
||||
/// // 5 | fn f<!Sized>() {}
|
||||
/// // | ^
|
||||
/// enum GenericParam {
|
||||
/// Type(TypeParam),
|
||||
/// Lifetime(LifetimeDef),
|
||||
/// Const(ConstParam),
|
||||
/// }
|
||||
///
|
||||
/// impl Parse for GenericParam {
|
||||
/// fn parse(input: ParseStream) -> Result<Self> {
|
||||
/// let lookahead = input.lookahead1();
|
||||
/// if lookahead.peek(Ident) {
|
||||
/// input.parse().map(GenericParam::Type)
|
||||
/// } else if lookahead.peek(Lifetime) {
|
||||
/// input.parse().map(GenericParam::Lifetime)
|
||||
/// } else if lookahead.peek(Token![const]) {
|
||||
/// input.parse().map(GenericParam::Const)
|
||||
/// } else {
|
||||
/// Err(lookahead.error())
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub struct Lookahead1<'a> {
|
||||
scope: Span,
|
||||
cursor: Cursor<'a>,
|
||||
comparisons: RefCell<Vec<&'static str>>,
|
||||
}
|
||||
|
||||
pub fn new(scope: Span, cursor: Cursor) -> Lookahead1 {
|
||||
Lookahead1 {
|
||||
scope,
|
||||
cursor,
|
||||
comparisons: RefCell::new(Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
fn peek_impl(
|
||||
lookahead: &Lookahead1,
|
||||
peek: fn(Cursor) -> bool,
|
||||
display: fn() -> &'static str,
|
||||
) -> bool {
|
||||
if peek(lookahead.cursor) {
|
||||
return true;
|
||||
}
|
||||
lookahead.comparisons.borrow_mut().push(display());
|
||||
false
|
||||
}
|
||||
|
||||
impl<'a> Lookahead1<'a> {
|
||||
/// Looks at the next token in the parse stream to determine whether it
|
||||
/// matches the requested type of token.
|
||||
///
|
||||
/// # Syntax
|
||||
///
|
||||
/// Note that this method does not use turbofish syntax. Pass the peek type
|
||||
/// inside of parentheses.
|
||||
///
|
||||
/// - `input.peek(Token![struct])`
|
||||
/// - `input.peek(Token![==])`
|
||||
/// - `input.peek(Ident)` *(does not accept keywords)*
|
||||
/// - `input.peek(Ident::peek_any)`
|
||||
/// - `input.peek(Lifetime)`
|
||||
/// - `input.peek(token::Brace)`
|
||||
pub fn peek<T: Peek>(&self, token: T) -> bool {
|
||||
let _ = token;
|
||||
peek_impl(self, T::Token::peek, T::Token::display)
|
||||
}
|
||||
|
||||
/// Triggers an error at the current position of the parse stream.
|
||||
///
|
||||
/// The error message will identify all of the expected token types that
|
||||
/// have been peeked against this lookahead instance.
|
||||
pub fn error(self) -> Error {
|
||||
let comparisons = self.comparisons.borrow();
|
||||
match comparisons.len() {
|
||||
0 => {
|
||||
if self.cursor.eof() {
|
||||
Error::new(self.scope, "unexpected end of input")
|
||||
} else {
|
||||
Error::new(self.cursor.span(), "unexpected token")
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
let message = format!("expected {}", comparisons[0]);
|
||||
error::new_at(self.scope, self.cursor, message)
|
||||
}
|
||||
2 => {
|
||||
let message = format!("expected {} or {}", comparisons[0], comparisons[1]);
|
||||
error::new_at(self.scope, self.cursor, message)
|
||||
}
|
||||
_ => {
|
||||
let join = comparisons.join(", ");
|
||||
let message = format!("expected one of: {}", join);
|
||||
error::new_at(self.scope, self.cursor, message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Types that can be parsed by looking at just one token.
|
||||
///
|
||||
/// Use [`ParseStream::peek`] to peek one of these types in a parse stream
|
||||
/// without consuming it from the stream.
|
||||
///
|
||||
/// This trait is sealed and cannot be implemented for types outside of Syn.
|
||||
///
|
||||
/// [`ParseStream::peek`]: crate::parse::ParseBuffer::peek
|
||||
pub trait Peek: Sealed {
|
||||
// Not public API.
|
||||
#[doc(hidden)]
|
||||
type Token: Token;
|
||||
}
|
||||
|
||||
impl<F: Copy + FnOnce(TokenMarker) -> T, T: Token> Peek for F {
|
||||
type Token = T;
|
||||
}
|
||||
|
||||
pub enum TokenMarker {}
|
||||
|
||||
impl<S> IntoSpans<S> for TokenMarker {
|
||||
fn into_spans(self) -> S {
|
||||
match self {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_delimiter(cursor: Cursor, delimiter: Delimiter) -> bool {
|
||||
cursor.group(delimiter).is_some()
|
||||
}
|
||||
|
||||
impl<F: Copy + FnOnce(TokenMarker) -> T, T: Token> Sealed for F {}
|
||||
219
zeroidc/vendor/syn/src/mac.rs
vendored
Normal file
219
zeroidc/vendor/syn/src/mac.rs
vendored
Normal file
@@ -0,0 +1,219 @@
|
||||
use super::*;
|
||||
use crate::token::{Brace, Bracket, Paren};
|
||||
use proc_macro2::TokenStream;
|
||||
#[cfg(feature = "parsing")]
|
||||
use proc_macro2::{Delimiter, Group, Span, TokenTree};
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
use crate::parse::{Parse, ParseStream, Parser, Result};
|
||||
|
||||
ast_struct! {
|
||||
/// A macro invocation: `println!("{}", mac)`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
|
||||
/// feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub struct Macro {
|
||||
pub path: Path,
|
||||
pub bang_token: Token![!],
|
||||
pub delimiter: MacroDelimiter,
|
||||
pub tokens: TokenStream,
|
||||
}
|
||||
}
|
||||
|
||||
ast_enum! {
|
||||
/// A grouping token that surrounds a macro body: `m!(...)` or `m!{...}` or `m![...]`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
|
||||
/// feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub enum MacroDelimiter {
|
||||
Paren(Paren),
|
||||
Brace(Brace),
|
||||
Bracket(Bracket),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
fn delimiter_span_close(macro_delimiter: &MacroDelimiter) -> Span {
|
||||
let delimiter = match macro_delimiter {
|
||||
MacroDelimiter::Paren(_) => Delimiter::Parenthesis,
|
||||
MacroDelimiter::Brace(_) => Delimiter::Brace,
|
||||
MacroDelimiter::Bracket(_) => Delimiter::Bracket,
|
||||
};
|
||||
let mut group = Group::new(delimiter, TokenStream::new());
|
||||
group.set_span(match macro_delimiter {
|
||||
MacroDelimiter::Paren(token) => token.span,
|
||||
MacroDelimiter::Brace(token) => token.span,
|
||||
MacroDelimiter::Bracket(token) => token.span,
|
||||
});
|
||||
group.span_close()
|
||||
}
|
||||
|
||||
impl Macro {
|
||||
/// Parse the tokens within the macro invocation's delimiters into a syntax
|
||||
/// tree.
|
||||
///
|
||||
/// This is equivalent to `syn::parse2::<T>(mac.tokens)` except that it
|
||||
/// produces a more useful span when `tokens` is empty.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use syn::{parse_quote, Expr, ExprLit, Ident, Lit, LitStr, Macro, Token};
|
||||
/// use syn::ext::IdentExt;
|
||||
/// use syn::parse::{Error, Parse, ParseStream, Result};
|
||||
/// use syn::punctuated::Punctuated;
|
||||
///
|
||||
/// // The arguments expected by libcore's format_args macro, and as a
|
||||
/// // result most other formatting and printing macros like println.
|
||||
/// //
|
||||
/// // println!("{} is {number:.prec$}", "x", prec=5, number=0.01)
|
||||
/// struct FormatArgs {
|
||||
/// format_string: Expr,
|
||||
/// positional_args: Vec<Expr>,
|
||||
/// named_args: Vec<(Ident, Expr)>,
|
||||
/// }
|
||||
///
|
||||
/// impl Parse for FormatArgs {
|
||||
/// fn parse(input: ParseStream) -> Result<Self> {
|
||||
/// let format_string: Expr;
|
||||
/// let mut positional_args = Vec::new();
|
||||
/// let mut named_args = Vec::new();
|
||||
///
|
||||
/// format_string = input.parse()?;
|
||||
/// while !input.is_empty() {
|
||||
/// input.parse::<Token![,]>()?;
|
||||
/// if input.is_empty() {
|
||||
/// break;
|
||||
/// }
|
||||
/// if input.peek(Ident::peek_any) && input.peek2(Token![=]) {
|
||||
/// while !input.is_empty() {
|
||||
/// let name: Ident = input.call(Ident::parse_any)?;
|
||||
/// input.parse::<Token![=]>()?;
|
||||
/// let value: Expr = input.parse()?;
|
||||
/// named_args.push((name, value));
|
||||
/// if input.is_empty() {
|
||||
/// break;
|
||||
/// }
|
||||
/// input.parse::<Token![,]>()?;
|
||||
/// }
|
||||
/// break;
|
||||
/// }
|
||||
/// positional_args.push(input.parse()?);
|
||||
/// }
|
||||
///
|
||||
/// Ok(FormatArgs {
|
||||
/// format_string,
|
||||
/// positional_args,
|
||||
/// named_args,
|
||||
/// })
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // Extract the first argument, the format string literal, from an
|
||||
/// // invocation of a formatting or printing macro.
|
||||
/// fn get_format_string(m: &Macro) -> Result<LitStr> {
|
||||
/// let args: FormatArgs = m.parse_body()?;
|
||||
/// match args.format_string {
|
||||
/// Expr::Lit(ExprLit { lit: Lit::Str(lit), .. }) => Ok(lit),
|
||||
/// other => {
|
||||
/// // First argument was not a string literal expression.
|
||||
/// // Maybe something like: println!(concat!(...), ...)
|
||||
/// Err(Error::new_spanned(other, "format string must be a string literal"))
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let invocation = parse_quote! {
|
||||
/// println!("{:?}", Instant::now())
|
||||
/// };
|
||||
/// let lit = get_format_string(&invocation).unwrap();
|
||||
/// assert_eq!(lit.value(), "{:?}");
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg(feature = "parsing")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
pub fn parse_body<T: Parse>(&self) -> Result<T> {
|
||||
self.parse_body_with(T::parse)
|
||||
}
|
||||
|
||||
/// Parse the tokens within the macro invocation's delimiters using the
|
||||
/// given parser.
|
||||
#[cfg(feature = "parsing")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
pub fn parse_body_with<F: Parser>(&self, parser: F) -> Result<F::Output> {
|
||||
let scope = delimiter_span_close(&self.delimiter);
|
||||
crate::parse::parse_scoped(parser, scope, self.tokens.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
pub fn parse_delimiter(input: ParseStream) -> Result<(MacroDelimiter, TokenStream)> {
|
||||
input.step(|cursor| {
|
||||
if let Some((TokenTree::Group(g), rest)) = cursor.token_tree() {
|
||||
let span = g.span();
|
||||
let delimiter = match g.delimiter() {
|
||||
Delimiter::Parenthesis => MacroDelimiter::Paren(Paren(span)),
|
||||
Delimiter::Brace => MacroDelimiter::Brace(Brace(span)),
|
||||
Delimiter::Bracket => MacroDelimiter::Bracket(Bracket(span)),
|
||||
Delimiter::None => {
|
||||
return Err(cursor.error("expected delimiter"));
|
||||
}
|
||||
};
|
||||
Ok(((delimiter, g.stream()), rest))
|
||||
} else {
|
||||
Err(cursor.error("expected delimiter"))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
pub mod parsing {
|
||||
use super::*;
|
||||
use crate::parse::{Parse, ParseStream, Result};
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for Macro {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let tokens;
|
||||
Ok(Macro {
|
||||
path: input.call(Path::parse_mod_style)?,
|
||||
bang_token: input.parse()?,
|
||||
delimiter: {
|
||||
let (delimiter, content) = parse_delimiter(input)?;
|
||||
tokens = content;
|
||||
delimiter
|
||||
},
|
||||
tokens,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "printing")]
|
||||
mod printing {
|
||||
use super::*;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::ToTokens;
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for Macro {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.path.to_tokens(tokens);
|
||||
self.bang_token.to_tokens(tokens);
|
||||
match &self.delimiter {
|
||||
MacroDelimiter::Paren(paren) => {
|
||||
paren.surround(tokens, |tokens| self.tokens.to_tokens(tokens));
|
||||
}
|
||||
MacroDelimiter::Brace(brace) => {
|
||||
brace.surround(tokens, |tokens| self.tokens.to_tokens(tokens));
|
||||
}
|
||||
MacroDelimiter::Bracket(bracket) => {
|
||||
bracket.surround(tokens, |tokens| self.tokens.to_tokens(tokens));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
177
zeroidc/vendor/syn/src/macros.rs
vendored
Normal file
177
zeroidc/vendor/syn/src/macros.rs
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
#[cfg_attr(
|
||||
not(any(feature = "full", feature = "derive")),
|
||||
allow(unknown_lints, unused_macro_rules)
|
||||
)]
|
||||
macro_rules! ast_struct {
|
||||
(
|
||||
[$($attrs_pub:tt)*]
|
||||
struct $name:ident #full $($rest:tt)*
|
||||
) => {
|
||||
#[cfg(feature = "full")]
|
||||
$($attrs_pub)* struct $name $($rest)*
|
||||
|
||||
#[cfg(not(feature = "full"))]
|
||||
$($attrs_pub)* struct $name {
|
||||
_noconstruct: ::std::marker::PhantomData<::proc_macro2::Span>,
|
||||
}
|
||||
|
||||
#[cfg(all(not(feature = "full"), feature = "printing"))]
|
||||
impl ::quote::ToTokens for $name {
|
||||
fn to_tokens(&self, _: &mut ::proc_macro2::TokenStream) {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
(
|
||||
[$($attrs_pub:tt)*]
|
||||
struct $name:ident $($rest:tt)*
|
||||
) => {
|
||||
$($attrs_pub)* struct $name $($rest)*
|
||||
};
|
||||
|
||||
($($t:tt)*) => {
|
||||
strip_attrs_pub!(ast_struct!($($t)*));
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! ast_enum {
|
||||
// Drop the `#no_visit` attribute, if present.
|
||||
(
|
||||
[$($attrs_pub:tt)*]
|
||||
enum $name:ident #no_visit $($rest:tt)*
|
||||
) => (
|
||||
ast_enum!([$($attrs_pub)*] enum $name $($rest)*);
|
||||
);
|
||||
|
||||
(
|
||||
[$($attrs_pub:tt)*]
|
||||
enum $name:ident $($rest:tt)*
|
||||
) => (
|
||||
$($attrs_pub)* enum $name $($rest)*
|
||||
);
|
||||
|
||||
($($t:tt)*) => {
|
||||
strip_attrs_pub!(ast_enum!($($t)*));
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! ast_enum_of_structs {
|
||||
(
|
||||
$(#[$enum_attr:meta])*
|
||||
$pub:ident $enum:ident $name:ident $body:tt
|
||||
$($remaining:tt)*
|
||||
) => {
|
||||
ast_enum!($(#[$enum_attr])* $pub $enum $name $body);
|
||||
ast_enum_of_structs_impl!($pub $enum $name $body $($remaining)*);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! ast_enum_of_structs_impl {
|
||||
(
|
||||
$pub:ident $enum:ident $name:ident {
|
||||
$(
|
||||
$(#[cfg $cfg_attr:tt])*
|
||||
$(#[doc $($doc_attr:tt)*])*
|
||||
$variant:ident $( ($($member:ident)::+) )*,
|
||||
)*
|
||||
}
|
||||
|
||||
$($remaining:tt)*
|
||||
) => {
|
||||
check_keyword_matches!(pub $pub);
|
||||
check_keyword_matches!(enum $enum);
|
||||
|
||||
$($(
|
||||
ast_enum_from_struct!($name::$variant, $($member)::+);
|
||||
)*)*
|
||||
|
||||
#[cfg(feature = "printing")]
|
||||
generate_to_tokens! {
|
||||
$($remaining)*
|
||||
()
|
||||
tokens
|
||||
$name {
|
||||
$(
|
||||
$(#[cfg $cfg_attr])*
|
||||
$(#[doc $($doc_attr)*])*
|
||||
$variant $($($member)::+)*,
|
||||
)*
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! ast_enum_from_struct {
|
||||
// No From<TokenStream> for verbatim variants.
|
||||
($name:ident::Verbatim, $member:ident) => {};
|
||||
|
||||
($name:ident::$variant:ident, $member:ident) => {
|
||||
impl From<$member> for $name {
|
||||
fn from(e: $member) -> $name {
|
||||
$name::$variant(e)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(feature = "printing")]
|
||||
#[cfg_attr(
|
||||
not(any(feature = "full", feature = "derive")),
|
||||
allow(unknown_lints, unused_macro_rules)
|
||||
)]
|
||||
macro_rules! generate_to_tokens {
|
||||
(do_not_generate_to_tokens $($foo:tt)*) => ();
|
||||
|
||||
(
|
||||
($($arms:tt)*) $tokens:ident $name:ident {
|
||||
$(#[cfg $cfg_attr:tt])*
|
||||
$(#[doc $($doc_attr:tt)*])*
|
||||
$variant:ident,
|
||||
$($next:tt)*
|
||||
}
|
||||
) => {
|
||||
generate_to_tokens!(
|
||||
($($arms)* $(#[cfg $cfg_attr])* $name::$variant => {})
|
||||
$tokens $name { $($next)* }
|
||||
);
|
||||
};
|
||||
|
||||
(
|
||||
($($arms:tt)*) $tokens:ident $name:ident {
|
||||
$(#[cfg $cfg_attr:tt])*
|
||||
$(#[doc $($doc_attr:tt)*])*
|
||||
$variant:ident $member:ident,
|
||||
$($next:tt)*
|
||||
}
|
||||
) => {
|
||||
generate_to_tokens!(
|
||||
($($arms)* $(#[cfg $cfg_attr])* $name::$variant(_e) => _e.to_tokens($tokens),)
|
||||
$tokens $name { $($next)* }
|
||||
);
|
||||
};
|
||||
|
||||
(($($arms:tt)*) $tokens:ident $name:ident {}) => {
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ::quote::ToTokens for $name {
|
||||
fn to_tokens(&self, $tokens: &mut ::proc_macro2::TokenStream) {
|
||||
match self {
|
||||
$($arms)*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! strip_attrs_pub {
|
||||
($mac:ident!($(#[$m:meta])* $pub:ident $($t:tt)*)) => {
|
||||
check_keyword_matches!(pub $pub);
|
||||
|
||||
$mac!([$(#[$m])* $pub] $($t)*);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! check_keyword_matches {
|
||||
(enum enum) => {};
|
||||
(pub pub) => {};
|
||||
}
|
||||
234
zeroidc/vendor/syn/src/op.rs
vendored
Normal file
234
zeroidc/vendor/syn/src/op.rs
vendored
Normal file
@@ -0,0 +1,234 @@
|
||||
ast_enum! {
|
||||
/// A binary operator: `+`, `+=`, `&`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
|
||||
/// feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub enum BinOp {
|
||||
/// The `+` operator (addition)
|
||||
Add(Token![+]),
|
||||
/// The `-` operator (subtraction)
|
||||
Sub(Token![-]),
|
||||
/// The `*` operator (multiplication)
|
||||
Mul(Token![*]),
|
||||
/// The `/` operator (division)
|
||||
Div(Token![/]),
|
||||
/// The `%` operator (modulus)
|
||||
Rem(Token![%]),
|
||||
/// The `&&` operator (logical and)
|
||||
And(Token![&&]),
|
||||
/// The `||` operator (logical or)
|
||||
Or(Token![||]),
|
||||
/// The `^` operator (bitwise xor)
|
||||
BitXor(Token![^]),
|
||||
/// The `&` operator (bitwise and)
|
||||
BitAnd(Token![&]),
|
||||
/// The `|` operator (bitwise or)
|
||||
BitOr(Token![|]),
|
||||
/// The `<<` operator (shift left)
|
||||
Shl(Token![<<]),
|
||||
/// The `>>` operator (shift right)
|
||||
Shr(Token![>>]),
|
||||
/// The `==` operator (equality)
|
||||
Eq(Token![==]),
|
||||
/// The `<` operator (less than)
|
||||
Lt(Token![<]),
|
||||
/// The `<=` operator (less than or equal to)
|
||||
Le(Token![<=]),
|
||||
/// The `!=` operator (not equal to)
|
||||
Ne(Token![!=]),
|
||||
/// The `>=` operator (greater than or equal to)
|
||||
Ge(Token![>=]),
|
||||
/// The `>` operator (greater than)
|
||||
Gt(Token![>]),
|
||||
/// The `+=` operator
|
||||
AddEq(Token![+=]),
|
||||
/// The `-=` operator
|
||||
SubEq(Token![-=]),
|
||||
/// The `*=` operator
|
||||
MulEq(Token![*=]),
|
||||
/// The `/=` operator
|
||||
DivEq(Token![/=]),
|
||||
/// The `%=` operator
|
||||
RemEq(Token![%=]),
|
||||
/// The `^=` operator
|
||||
BitXorEq(Token![^=]),
|
||||
/// The `&=` operator
|
||||
BitAndEq(Token![&=]),
|
||||
/// The `|=` operator
|
||||
BitOrEq(Token![|=]),
|
||||
/// The `<<=` operator
|
||||
ShlEq(Token![<<=]),
|
||||
/// The `>>=` operator
|
||||
ShrEq(Token![>>=]),
|
||||
}
|
||||
}
|
||||
|
||||
ast_enum! {
|
||||
/// A unary operator: `*`, `!`, `-`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
|
||||
/// feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub enum UnOp {
|
||||
/// The `*` operator for dereferencing
|
||||
Deref(Token![*]),
|
||||
/// The `!` operator for logical inversion
|
||||
Not(Token![!]),
|
||||
/// The `-` operator for negation
|
||||
Neg(Token![-]),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
pub mod parsing {
|
||||
use super::*;
|
||||
use crate::parse::{Parse, ParseStream, Result};
|
||||
|
||||
fn parse_binop(input: ParseStream) -> Result<BinOp> {
|
||||
if input.peek(Token![&&]) {
|
||||
input.parse().map(BinOp::And)
|
||||
} else if input.peek(Token![||]) {
|
||||
input.parse().map(BinOp::Or)
|
||||
} else if input.peek(Token![<<]) {
|
||||
input.parse().map(BinOp::Shl)
|
||||
} else if input.peek(Token![>>]) {
|
||||
input.parse().map(BinOp::Shr)
|
||||
} else if input.peek(Token![==]) {
|
||||
input.parse().map(BinOp::Eq)
|
||||
} else if input.peek(Token![<=]) {
|
||||
input.parse().map(BinOp::Le)
|
||||
} else if input.peek(Token![!=]) {
|
||||
input.parse().map(BinOp::Ne)
|
||||
} else if input.peek(Token![>=]) {
|
||||
input.parse().map(BinOp::Ge)
|
||||
} else if input.peek(Token![+]) {
|
||||
input.parse().map(BinOp::Add)
|
||||
} else if input.peek(Token![-]) {
|
||||
input.parse().map(BinOp::Sub)
|
||||
} else if input.peek(Token![*]) {
|
||||
input.parse().map(BinOp::Mul)
|
||||
} else if input.peek(Token![/]) {
|
||||
input.parse().map(BinOp::Div)
|
||||
} else if input.peek(Token![%]) {
|
||||
input.parse().map(BinOp::Rem)
|
||||
} else if input.peek(Token![^]) {
|
||||
input.parse().map(BinOp::BitXor)
|
||||
} else if input.peek(Token![&]) {
|
||||
input.parse().map(BinOp::BitAnd)
|
||||
} else if input.peek(Token![|]) {
|
||||
input.parse().map(BinOp::BitOr)
|
||||
} else if input.peek(Token![<]) {
|
||||
input.parse().map(BinOp::Lt)
|
||||
} else if input.peek(Token![>]) {
|
||||
input.parse().map(BinOp::Gt)
|
||||
} else {
|
||||
Err(input.error("expected binary operator"))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for BinOp {
|
||||
#[cfg(not(feature = "full"))]
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
parse_binop(input)
|
||||
}
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
if input.peek(Token![+=]) {
|
||||
input.parse().map(BinOp::AddEq)
|
||||
} else if input.peek(Token![-=]) {
|
||||
input.parse().map(BinOp::SubEq)
|
||||
} else if input.peek(Token![*=]) {
|
||||
input.parse().map(BinOp::MulEq)
|
||||
} else if input.peek(Token![/=]) {
|
||||
input.parse().map(BinOp::DivEq)
|
||||
} else if input.peek(Token![%=]) {
|
||||
input.parse().map(BinOp::RemEq)
|
||||
} else if input.peek(Token![^=]) {
|
||||
input.parse().map(BinOp::BitXorEq)
|
||||
} else if input.peek(Token![&=]) {
|
||||
input.parse().map(BinOp::BitAndEq)
|
||||
} else if input.peek(Token![|=]) {
|
||||
input.parse().map(BinOp::BitOrEq)
|
||||
} else if input.peek(Token![<<=]) {
|
||||
input.parse().map(BinOp::ShlEq)
|
||||
} else if input.peek(Token![>>=]) {
|
||||
input.parse().map(BinOp::ShrEq)
|
||||
} else {
|
||||
parse_binop(input)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for UnOp {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let lookahead = input.lookahead1();
|
||||
if lookahead.peek(Token![*]) {
|
||||
input.parse().map(UnOp::Deref)
|
||||
} else if lookahead.peek(Token![!]) {
|
||||
input.parse().map(UnOp::Not)
|
||||
} else if lookahead.peek(Token![-]) {
|
||||
input.parse().map(UnOp::Neg)
|
||||
} else {
|
||||
Err(lookahead.error())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "printing")]
|
||||
mod printing {
|
||||
use super::*;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::ToTokens;
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for BinOp {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
match self {
|
||||
BinOp::Add(t) => t.to_tokens(tokens),
|
||||
BinOp::Sub(t) => t.to_tokens(tokens),
|
||||
BinOp::Mul(t) => t.to_tokens(tokens),
|
||||
BinOp::Div(t) => t.to_tokens(tokens),
|
||||
BinOp::Rem(t) => t.to_tokens(tokens),
|
||||
BinOp::And(t) => t.to_tokens(tokens),
|
||||
BinOp::Or(t) => t.to_tokens(tokens),
|
||||
BinOp::BitXor(t) => t.to_tokens(tokens),
|
||||
BinOp::BitAnd(t) => t.to_tokens(tokens),
|
||||
BinOp::BitOr(t) => t.to_tokens(tokens),
|
||||
BinOp::Shl(t) => t.to_tokens(tokens),
|
||||
BinOp::Shr(t) => t.to_tokens(tokens),
|
||||
BinOp::Eq(t) => t.to_tokens(tokens),
|
||||
BinOp::Lt(t) => t.to_tokens(tokens),
|
||||
BinOp::Le(t) => t.to_tokens(tokens),
|
||||
BinOp::Ne(t) => t.to_tokens(tokens),
|
||||
BinOp::Ge(t) => t.to_tokens(tokens),
|
||||
BinOp::Gt(t) => t.to_tokens(tokens),
|
||||
BinOp::AddEq(t) => t.to_tokens(tokens),
|
||||
BinOp::SubEq(t) => t.to_tokens(tokens),
|
||||
BinOp::MulEq(t) => t.to_tokens(tokens),
|
||||
BinOp::DivEq(t) => t.to_tokens(tokens),
|
||||
BinOp::RemEq(t) => t.to_tokens(tokens),
|
||||
BinOp::BitXorEq(t) => t.to_tokens(tokens),
|
||||
BinOp::BitAndEq(t) => t.to_tokens(tokens),
|
||||
BinOp::BitOrEq(t) => t.to_tokens(tokens),
|
||||
BinOp::ShlEq(t) => t.to_tokens(tokens),
|
||||
BinOp::ShrEq(t) => t.to_tokens(tokens),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for UnOp {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
match self {
|
||||
UnOp::Deref(t) => t.to_tokens(tokens),
|
||||
UnOp::Not(t) => t.to_tokens(tokens),
|
||||
UnOp::Neg(t) => t.to_tokens(tokens),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1314
zeroidc/vendor/syn/src/parse.rs
vendored
Normal file
1314
zeroidc/vendor/syn/src/parse.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
179
zeroidc/vendor/syn/src/parse_macro_input.rs
vendored
Normal file
179
zeroidc/vendor/syn/src/parse_macro_input.rs
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
/// Parse the input TokenStream of a macro, triggering a compile error if the
|
||||
/// tokens fail to parse.
|
||||
///
|
||||
/// Refer to the [`parse` module] documentation for more details about parsing
|
||||
/// in Syn.
|
||||
///
|
||||
/// [`parse` module]: crate::rustdoc_workaround::parse_module
|
||||
///
|
||||
/// <br>
|
||||
///
|
||||
/// # Intended usage
|
||||
///
|
||||
/// This macro must be called from a function that returns
|
||||
/// `proc_macro::TokenStream`. Usually this will be your proc macro entry point,
|
||||
/// the function that has the #\[proc_macro\] / #\[proc_macro_derive\] /
|
||||
/// #\[proc_macro_attribute\] attribute.
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate proc_macro;
|
||||
/// #
|
||||
/// use proc_macro::TokenStream;
|
||||
/// use syn::{parse_macro_input, Result};
|
||||
/// use syn::parse::{Parse, ParseStream};
|
||||
///
|
||||
/// struct MyMacroInput {
|
||||
/// /* ... */
|
||||
/// }
|
||||
///
|
||||
/// impl Parse for MyMacroInput {
|
||||
/// fn parse(input: ParseStream) -> Result<Self> {
|
||||
/// /* ... */
|
||||
/// # Ok(MyMacroInput {})
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// # const IGNORE: &str = stringify! {
|
||||
/// #[proc_macro]
|
||||
/// # };
|
||||
/// pub fn my_macro(tokens: TokenStream) -> TokenStream {
|
||||
/// let input = parse_macro_input!(tokens as MyMacroInput);
|
||||
///
|
||||
/// /* ... */
|
||||
/// # "".parse().unwrap()
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// <br>
|
||||
///
|
||||
/// # Usage with Parser
|
||||
///
|
||||
/// This macro can also be used with the [`Parser` trait] for types that have
|
||||
/// multiple ways that they can be parsed.
|
||||
///
|
||||
/// [`Parser` trait]: crate::rustdoc_workaround::parse_module::Parser
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate proc_macro;
|
||||
/// #
|
||||
/// # use proc_macro::TokenStream;
|
||||
/// # use syn::{parse_macro_input, Result};
|
||||
/// # use syn::parse::ParseStream;
|
||||
/// #
|
||||
/// # struct MyMacroInput {}
|
||||
/// #
|
||||
/// impl MyMacroInput {
|
||||
/// fn parse_alternate(input: ParseStream) -> Result<Self> {
|
||||
/// /* ... */
|
||||
/// # Ok(MyMacroInput {})
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// # const IGNORE: &str = stringify! {
|
||||
/// #[proc_macro]
|
||||
/// # };
|
||||
/// pub fn my_macro(tokens: TokenStream) -> TokenStream {
|
||||
/// let input = parse_macro_input!(tokens with MyMacroInput::parse_alternate);
|
||||
///
|
||||
/// /* ... */
|
||||
/// # "".parse().unwrap()
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// <br>
|
||||
///
|
||||
/// # Expansion
|
||||
///
|
||||
/// `parse_macro_input!($variable as $Type)` expands to something like:
|
||||
///
|
||||
/// ```no_run
|
||||
/// # extern crate proc_macro;
|
||||
/// #
|
||||
/// # macro_rules! doc_test {
|
||||
/// # ($variable:ident as $Type:ty) => {
|
||||
/// match syn::parse::<$Type>($variable) {
|
||||
/// Ok(syntax_tree) => syntax_tree,
|
||||
/// Err(err) => return proc_macro::TokenStream::from(err.to_compile_error()),
|
||||
/// }
|
||||
/// # };
|
||||
/// # }
|
||||
/// #
|
||||
/// # fn test(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
/// # let _ = doc_test!(input as syn::Ident);
|
||||
/// # proc_macro::TokenStream::new()
|
||||
/// # }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "proc-macro"))))]
|
||||
macro_rules! parse_macro_input {
|
||||
($tokenstream:ident as $ty:ty) => {
|
||||
match $crate::parse_macro_input::parse::<$ty>($tokenstream) {
|
||||
$crate::__private::Ok(data) => data,
|
||||
$crate::__private::Err(err) => {
|
||||
return $crate::__private::TokenStream::from(err.to_compile_error());
|
||||
}
|
||||
}
|
||||
};
|
||||
($tokenstream:ident with $parser:path) => {
|
||||
match $crate::parse::Parser::parse($parser, $tokenstream) {
|
||||
$crate::__private::Ok(data) => data,
|
||||
$crate::__private::Err(err) => {
|
||||
return $crate::__private::TokenStream::from(err.to_compile_error());
|
||||
}
|
||||
}
|
||||
};
|
||||
($tokenstream:ident) => {
|
||||
$crate::parse_macro_input!($tokenstream as _)
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Can parse any type that implements Parse.
|
||||
|
||||
use crate::parse::{Parse, ParseStream, Parser, Result};
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
// Not public API.
|
||||
#[doc(hidden)]
|
||||
pub fn parse<T: ParseMacroInput>(token_stream: TokenStream) -> Result<T> {
|
||||
T::parse.parse(token_stream)
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[doc(hidden)]
|
||||
pub trait ParseMacroInput: Sized {
|
||||
fn parse(input: ParseStream) -> Result<Self>;
|
||||
}
|
||||
|
||||
impl<T: Parse> ParseMacroInput for T {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
<T as Parse>::parse(input)
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Any other types that we want `parse_macro_input!` to be able to parse.
|
||||
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
use crate::AttributeArgs;
|
||||
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
impl ParseMacroInput for AttributeArgs {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let mut metas = Vec::new();
|
||||
|
||||
loop {
|
||||
if input.is_empty() {
|
||||
break;
|
||||
}
|
||||
let value = input.parse()?;
|
||||
metas.push(value);
|
||||
if input.is_empty() {
|
||||
break;
|
||||
}
|
||||
input.parse::<Token![,]>()?;
|
||||
}
|
||||
|
||||
Ok(metas)
|
||||
}
|
||||
}
|
||||
167
zeroidc/vendor/syn/src/parse_quote.rs
vendored
Normal file
167
zeroidc/vendor/syn/src/parse_quote.rs
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
/// Quasi-quotation macro that accepts input like the [`quote!`] macro but uses
|
||||
/// type inference to figure out a return type for those tokens.
|
||||
///
|
||||
/// [`quote!`]: https://docs.rs/quote/1.0/quote/index.html
|
||||
///
|
||||
/// The return type can be any syntax tree node that implements the [`Parse`]
|
||||
/// trait.
|
||||
///
|
||||
/// [`Parse`]: crate::parse::Parse
|
||||
///
|
||||
/// ```
|
||||
/// use quote::quote;
|
||||
/// use syn::{parse_quote, Stmt};
|
||||
///
|
||||
/// fn main() {
|
||||
/// let name = quote!(v);
|
||||
/// let ty = quote!(u8);
|
||||
///
|
||||
/// let stmt: Stmt = parse_quote! {
|
||||
/// let #name: #ty = Default::default();
|
||||
/// };
|
||||
///
|
||||
/// println!("{:#?}", stmt);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// *This macro is available only if Syn is built with the `"parsing"` feature,
|
||||
/// although interpolation of syntax tree nodes into the quoted tokens is only
|
||||
/// supported if Syn is built with the `"printing"` feature as well.*
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// The following helper function adds a bound `T: HeapSize` to every type
|
||||
/// parameter `T` in the input generics.
|
||||
///
|
||||
/// ```
|
||||
/// use syn::{parse_quote, Generics, GenericParam};
|
||||
///
|
||||
/// // Add a bound `T: HeapSize` to every type parameter T.
|
||||
/// fn add_trait_bounds(mut generics: Generics) -> Generics {
|
||||
/// for param in &mut generics.params {
|
||||
/// if let GenericParam::Type(type_param) = param {
|
||||
/// type_param.bounds.push(parse_quote!(HeapSize));
|
||||
/// }
|
||||
/// }
|
||||
/// generics
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Special cases
|
||||
///
|
||||
/// This macro can parse the following additional types as a special case even
|
||||
/// though they do not implement the `Parse` trait.
|
||||
///
|
||||
/// - [`Attribute`] — parses one attribute, allowing either outer like `#[...]`
|
||||
/// or inner like `#![...]`
|
||||
/// - [`Punctuated<T, P>`] — parses zero or more `T` separated by punctuation
|
||||
/// `P` with optional trailing punctuation
|
||||
/// - [`Vec<Stmt>`] — parses the same as `Block::parse_within`
|
||||
///
|
||||
/// [`Vec<Stmt>`]: Block::parse_within
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the tokens fail to parse as the expected syntax tree type. The
|
||||
/// caller is responsible for ensuring that the input tokens are syntactically
|
||||
/// valid.
|
||||
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "printing"))))]
|
||||
#[macro_export]
|
||||
macro_rules! parse_quote {
|
||||
($($tt:tt)*) => {
|
||||
$crate::parse_quote::parse($crate::__private::quote::quote!($($tt)*))
|
||||
};
|
||||
}
|
||||
|
||||
/// This macro is [`parse_quote!`] + [`quote_spanned!`][quote::quote_spanned].
|
||||
///
|
||||
/// Please refer to each of their documentation.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use quote::{quote, quote_spanned};
|
||||
/// use syn::spanned::Spanned;
|
||||
/// use syn::{parse_quote_spanned, ReturnType, Signature};
|
||||
///
|
||||
/// // Changes `fn()` to `fn() -> Pin<Box<dyn Future<Output = ()>>>`,
|
||||
/// // and `fn() -> T` to `fn() -> Pin<Box<dyn Future<Output = T>>>`,
|
||||
/// // without introducing any call_site() spans.
|
||||
/// fn make_ret_pinned_future(sig: &mut Signature) {
|
||||
/// let ret = match &sig.output {
|
||||
/// ReturnType::Default => quote_spanned!(sig.paren_token.span=> ()),
|
||||
/// ReturnType::Type(_, ret) => quote!(#ret),
|
||||
/// };
|
||||
/// sig.output = parse_quote_spanned! {ret.span()=>
|
||||
/// -> ::std::pin::Pin<::std::boxed::Box<dyn ::std::future::Future<Output = #ret>>>
|
||||
/// };
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "printing"))))]
|
||||
#[macro_export]
|
||||
macro_rules! parse_quote_spanned {
|
||||
($span:expr=> $($tt:tt)*) => {
|
||||
$crate::parse_quote::parse($crate::__private::quote::quote_spanned!($span=> $($tt)*))
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Can parse any type that implements Parse.
|
||||
|
||||
use crate::parse::{Parse, ParseStream, Parser, Result};
|
||||
use proc_macro2::TokenStream;
|
||||
|
||||
// Not public API.
|
||||
#[doc(hidden)]
|
||||
pub fn parse<T: ParseQuote>(token_stream: TokenStream) -> T {
|
||||
let parser = T::parse;
|
||||
match parser.parse2(token_stream) {
|
||||
Ok(t) => t,
|
||||
Err(err) => panic!("{}", err),
|
||||
}
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[doc(hidden)]
|
||||
pub trait ParseQuote: Sized {
|
||||
fn parse(input: ParseStream) -> Result<Self>;
|
||||
}
|
||||
|
||||
impl<T: Parse> ParseQuote for T {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
<T as Parse>::parse(input)
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Any other types that we want `parse_quote!` to be able to parse.
|
||||
|
||||
use crate::punctuated::Punctuated;
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
use crate::{attr, Attribute};
|
||||
#[cfg(feature = "full")]
|
||||
use crate::{Block, Stmt};
|
||||
|
||||
#[cfg(any(feature = "full", feature = "derive"))]
|
||||
impl ParseQuote for Attribute {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
if input.peek(Token![#]) && input.peek2(Token![!]) {
|
||||
attr::parsing::single_parse_inner(input)
|
||||
} else {
|
||||
attr::parsing::single_parse_outer(input)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Parse, P: Parse> ParseQuote for Punctuated<T, P> {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
Self::parse_terminated(input)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
impl ParseQuote for Vec<Stmt> {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
Block::parse_within(input)
|
||||
}
|
||||
}
|
||||
924
zeroidc/vendor/syn/src/pat.rs
vendored
Normal file
924
zeroidc/vendor/syn/src/pat.rs
vendored
Normal file
@@ -0,0 +1,924 @@
|
||||
use super::*;
|
||||
use crate::punctuated::Punctuated;
|
||||
use proc_macro2::TokenStream;
|
||||
|
||||
ast_enum_of_structs! {
|
||||
/// A pattern in a local binding, function signature, match expression, or
|
||||
/// various other places.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"full"` feature.*
|
||||
///
|
||||
/// # Syntax tree enum
|
||||
///
|
||||
/// This type is a [syntax tree enum].
|
||||
///
|
||||
/// [syntax tree enum]: Expr#syntax-tree-enums
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
|
||||
#[cfg_attr(not(syn_no_non_exhaustive), non_exhaustive)]
|
||||
pub enum Pat {
|
||||
/// A box pattern: `box v`.
|
||||
Box(PatBox),
|
||||
|
||||
/// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
|
||||
Ident(PatIdent),
|
||||
|
||||
/// A literal pattern: `0`.
|
||||
///
|
||||
/// This holds an `Expr` rather than a `Lit` because negative numbers
|
||||
/// are represented as an `Expr::Unary`.
|
||||
Lit(PatLit),
|
||||
|
||||
/// A macro in pattern position.
|
||||
Macro(PatMacro),
|
||||
|
||||
/// A pattern that matches any one of a set of cases.
|
||||
Or(PatOr),
|
||||
|
||||
/// A path pattern like `Color::Red`, optionally qualified with a
|
||||
/// self-type.
|
||||
///
|
||||
/// Unqualified path patterns can legally refer to variants, structs,
|
||||
/// constants or associated constants. Qualified path patterns like
|
||||
/// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
|
||||
/// associated constants.
|
||||
Path(PatPath),
|
||||
|
||||
/// A range pattern: `1..=2`.
|
||||
Range(PatRange),
|
||||
|
||||
/// A reference pattern: `&mut var`.
|
||||
Reference(PatReference),
|
||||
|
||||
/// The dots in a tuple or slice pattern: `[0, 1, ..]`
|
||||
Rest(PatRest),
|
||||
|
||||
/// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`.
|
||||
Slice(PatSlice),
|
||||
|
||||
/// A struct or struct variant pattern: `Variant { x, y, .. }`.
|
||||
Struct(PatStruct),
|
||||
|
||||
/// A tuple pattern: `(a, b)`.
|
||||
Tuple(PatTuple),
|
||||
|
||||
/// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
|
||||
TupleStruct(PatTupleStruct),
|
||||
|
||||
/// A type ascription pattern: `foo: f64`.
|
||||
Type(PatType),
|
||||
|
||||
/// Tokens in pattern position not interpreted by Syn.
|
||||
Verbatim(TokenStream),
|
||||
|
||||
/// A pattern that matches any value: `_`.
|
||||
Wild(PatWild),
|
||||
|
||||
// Not public API.
|
||||
//
|
||||
// For testing exhaustiveness in downstream code, use the following idiom:
|
||||
//
|
||||
// match pat {
|
||||
// Pat::Box(pat) => {...}
|
||||
// Pat::Ident(pat) => {...}
|
||||
// ...
|
||||
// Pat::Wild(pat) => {...}
|
||||
//
|
||||
// #[cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
|
||||
// _ => { /* 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.
|
||||
#[cfg(syn_no_non_exhaustive)]
|
||||
#[doc(hidden)]
|
||||
__NonExhaustive,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A box pattern: `box v`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
|
||||
pub struct PatBox {
|
||||
pub attrs: Vec<Attribute>,
|
||||
pub box_token: Token![box],
|
||||
pub pat: Box<Pat>,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
|
||||
///
|
||||
/// It may also be a unit struct or struct variant (e.g. `None`), or a
|
||||
/// constant; these cannot be distinguished syntactically.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
|
||||
pub struct PatIdent {
|
||||
pub attrs: Vec<Attribute>,
|
||||
pub by_ref: Option<Token![ref]>,
|
||||
pub mutability: Option<Token![mut]>,
|
||||
pub ident: Ident,
|
||||
pub subpat: Option<(Token![@], Box<Pat>)>,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A literal pattern: `0`.
|
||||
///
|
||||
/// This holds an `Expr` rather than a `Lit` because negative numbers
|
||||
/// are represented as an `Expr::Unary`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
|
||||
pub struct PatLit {
|
||||
pub attrs: Vec<Attribute>,
|
||||
pub expr: Box<Expr>,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A macro in pattern position.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
|
||||
pub struct PatMacro {
|
||||
pub attrs: Vec<Attribute>,
|
||||
pub mac: Macro,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A pattern that matches any one of a set of cases.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
|
||||
pub struct PatOr {
|
||||
pub attrs: Vec<Attribute>,
|
||||
pub leading_vert: Option<Token![|]>,
|
||||
pub cases: Punctuated<Pat, Token![|]>,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A path pattern like `Color::Red`, optionally qualified with a
|
||||
/// self-type.
|
||||
///
|
||||
/// Unqualified path patterns can legally refer to variants, structs,
|
||||
/// constants or associated constants. Qualified path patterns like
|
||||
/// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
|
||||
/// associated constants.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
|
||||
pub struct PatPath {
|
||||
pub attrs: Vec<Attribute>,
|
||||
pub qself: Option<QSelf>,
|
||||
pub path: Path,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A range pattern: `1..=2`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
|
||||
pub struct PatRange {
|
||||
pub attrs: Vec<Attribute>,
|
||||
pub lo: Box<Expr>,
|
||||
pub limits: RangeLimits,
|
||||
pub hi: Box<Expr>,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A reference pattern: `&mut var`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
|
||||
pub struct PatReference {
|
||||
pub attrs: Vec<Attribute>,
|
||||
pub and_token: Token![&],
|
||||
pub mutability: Option<Token![mut]>,
|
||||
pub pat: Box<Pat>,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// The dots in a tuple or slice pattern: `[0, 1, ..]`
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
|
||||
pub struct PatRest {
|
||||
pub attrs: Vec<Attribute>,
|
||||
pub dot2_token: Token![..],
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
|
||||
pub struct PatSlice {
|
||||
pub attrs: Vec<Attribute>,
|
||||
pub bracket_token: token::Bracket,
|
||||
pub elems: Punctuated<Pat, Token![,]>,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A struct or struct variant pattern: `Variant { x, y, .. }`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
|
||||
pub struct PatStruct {
|
||||
pub attrs: Vec<Attribute>,
|
||||
pub path: Path,
|
||||
pub brace_token: token::Brace,
|
||||
pub fields: Punctuated<FieldPat, Token![,]>,
|
||||
pub dot2_token: Option<Token![..]>,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A tuple pattern: `(a, b)`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
|
||||
pub struct PatTuple {
|
||||
pub attrs: Vec<Attribute>,
|
||||
pub paren_token: token::Paren,
|
||||
pub elems: Punctuated<Pat, Token![,]>,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
|
||||
pub struct PatTupleStruct {
|
||||
pub attrs: Vec<Attribute>,
|
||||
pub path: Path,
|
||||
pub pat: PatTuple,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A type ascription pattern: `foo: f64`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
|
||||
pub struct PatType {
|
||||
pub attrs: Vec<Attribute>,
|
||||
pub pat: Box<Pat>,
|
||||
pub colon_token: Token![:],
|
||||
pub ty: Box<Type>,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A pattern that matches any value: `_`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
|
||||
pub struct PatWild {
|
||||
pub attrs: Vec<Attribute>,
|
||||
pub underscore_token: Token![_],
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A single field in a struct pattern.
|
||||
///
|
||||
/// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
|
||||
/// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
|
||||
pub struct FieldPat {
|
||||
pub attrs: Vec<Attribute>,
|
||||
pub member: Member,
|
||||
pub colon_token: Option<Token![:]>,
|
||||
pub pat: Box<Pat>,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
pub mod parsing {
|
||||
use super::*;
|
||||
use crate::ext::IdentExt;
|
||||
use crate::parse::{Parse, ParseBuffer, ParseStream, Result};
|
||||
use crate::path;
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for Pat {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let begin = input.fork();
|
||||
let lookahead = input.lookahead1();
|
||||
if {
|
||||
let ahead = input.fork();
|
||||
ahead.parse::<Option<Ident>>()?.is_some()
|
||||
&& (ahead.peek(Token![::])
|
||||
|| ahead.peek(Token![!])
|
||||
|| ahead.peek(token::Brace)
|
||||
|| ahead.peek(token::Paren)
|
||||
|| ahead.peek(Token![..])
|
||||
&& ahead.parse::<RangeLimits>().is_ok()
|
||||
&& !(ahead.is_empty() || ahead.peek(Token![,])))
|
||||
} || {
|
||||
let ahead = input.fork();
|
||||
ahead.parse::<Option<Token![self]>>()?.is_some() && ahead.peek(Token![::])
|
||||
} || lookahead.peek(Token![::])
|
||||
|| lookahead.peek(Token![<])
|
||||
|| input.peek(Token![Self])
|
||||
|| input.peek(Token![super])
|
||||
|| input.peek(Token![crate])
|
||||
{
|
||||
pat_path_or_macro_or_struct_or_range(input)
|
||||
} else if lookahead.peek(Token![_]) {
|
||||
input.call(pat_wild).map(Pat::Wild)
|
||||
} else if input.peek(Token![box]) {
|
||||
input.call(pat_box).map(Pat::Box)
|
||||
} else if input.peek(Token![-]) || lookahead.peek(Lit) || lookahead.peek(Token![const])
|
||||
{
|
||||
pat_lit_or_range(input)
|
||||
} else if lookahead.peek(Token![ref])
|
||||
|| lookahead.peek(Token![mut])
|
||||
|| input.peek(Token![self])
|
||||
|| input.peek(Ident)
|
||||
{
|
||||
input.call(pat_ident).map(Pat::Ident)
|
||||
} else if lookahead.peek(Token![&]) {
|
||||
input.call(pat_reference).map(Pat::Reference)
|
||||
} else if lookahead.peek(token::Paren) {
|
||||
input.call(pat_tuple).map(Pat::Tuple)
|
||||
} else if lookahead.peek(token::Bracket) {
|
||||
input.call(pat_slice).map(Pat::Slice)
|
||||
} else if lookahead.peek(Token![..]) && !input.peek(Token![...]) {
|
||||
pat_range_half_open(input, begin)
|
||||
} else if lookahead.peek(Token![const]) {
|
||||
input.call(pat_const).map(Pat::Verbatim)
|
||||
} else {
|
||||
Err(lookahead.error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> {
|
||||
let begin = input.fork();
|
||||
let (qself, path) = path::parsing::qpath(input, true)?;
|
||||
|
||||
if qself.is_none() && input.peek(Token![!]) && !input.peek(Token![!=]) {
|
||||
let mut contains_arguments = false;
|
||||
for segment in &path.segments {
|
||||
match segment.arguments {
|
||||
PathArguments::None => {}
|
||||
PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
|
||||
contains_arguments = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !contains_arguments {
|
||||
let bang_token: Token![!] = input.parse()?;
|
||||
let (delimiter, tokens) = mac::parse_delimiter(input)?;
|
||||
return Ok(Pat::Macro(PatMacro {
|
||||
attrs: Vec::new(),
|
||||
mac: Macro {
|
||||
path,
|
||||
bang_token,
|
||||
delimiter,
|
||||
tokens,
|
||||
},
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
if input.peek(token::Brace) {
|
||||
let pat = pat_struct(input, path)?;
|
||||
if qself.is_some() {
|
||||
Ok(Pat::Verbatim(verbatim::between(begin, input)))
|
||||
} else {
|
||||
Ok(Pat::Struct(pat))
|
||||
}
|
||||
} else if input.peek(token::Paren) {
|
||||
let pat = pat_tuple_struct(input, path)?;
|
||||
if qself.is_some() {
|
||||
Ok(Pat::Verbatim(verbatim::between(begin, input)))
|
||||
} else {
|
||||
Ok(Pat::TupleStruct(pat))
|
||||
}
|
||||
} else if input.peek(Token![..]) {
|
||||
pat_range(input, begin, qself, path)
|
||||
} else {
|
||||
Ok(Pat::Path(PatPath {
|
||||
attrs: Vec::new(),
|
||||
qself,
|
||||
path,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
fn pat_wild(input: ParseStream) -> Result<PatWild> {
|
||||
Ok(PatWild {
|
||||
attrs: Vec::new(),
|
||||
underscore_token: input.parse()?,
|
||||
})
|
||||
}
|
||||
|
||||
fn pat_box(input: ParseStream) -> Result<PatBox> {
|
||||
Ok(PatBox {
|
||||
attrs: Vec::new(),
|
||||
box_token: input.parse()?,
|
||||
pat: input.parse()?,
|
||||
})
|
||||
}
|
||||
|
||||
fn pat_ident(input: ParseStream) -> Result<PatIdent> {
|
||||
Ok(PatIdent {
|
||||
attrs: Vec::new(),
|
||||
by_ref: input.parse()?,
|
||||
mutability: input.parse()?,
|
||||
ident: input.call(Ident::parse_any)?,
|
||||
subpat: {
|
||||
if input.peek(Token![@]) {
|
||||
let at_token: Token![@] = input.parse()?;
|
||||
let subpat: Pat = input.parse()?;
|
||||
Some((at_token, Box::new(subpat)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
fn pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct> {
|
||||
Ok(PatTupleStruct {
|
||||
attrs: Vec::new(),
|
||||
path,
|
||||
pat: input.call(pat_tuple)?,
|
||||
})
|
||||
}
|
||||
|
||||
fn pat_struct(input: ParseStream, path: Path) -> Result<PatStruct> {
|
||||
let content;
|
||||
let brace_token = braced!(content in input);
|
||||
|
||||
let mut fields = Punctuated::new();
|
||||
while !content.is_empty() && !content.peek(Token![..]) {
|
||||
let value = content.call(field_pat)?;
|
||||
fields.push_value(value);
|
||||
if content.is_empty() {
|
||||
break;
|
||||
}
|
||||
let punct: Token![,] = content.parse()?;
|
||||
fields.push_punct(punct);
|
||||
}
|
||||
|
||||
let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
|
||||
Some(content.parse()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(PatStruct {
|
||||
attrs: Vec::new(),
|
||||
path,
|
||||
brace_token,
|
||||
fields,
|
||||
dot2_token,
|
||||
})
|
||||
}
|
||||
|
||||
impl Member {
|
||||
fn is_unnamed(&self) -> bool {
|
||||
match *self {
|
||||
Member::Named(_) => false,
|
||||
Member::Unnamed(_) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn field_pat(input: ParseStream) -> Result<FieldPat> {
|
||||
let attrs = input.call(Attribute::parse_outer)?;
|
||||
let boxed: Option<Token![box]> = input.parse()?;
|
||||
let by_ref: Option<Token![ref]> = input.parse()?;
|
||||
let mutability: Option<Token![mut]> = input.parse()?;
|
||||
let member: Member = input.parse()?;
|
||||
|
||||
if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
|
||||
|| member.is_unnamed()
|
||||
{
|
||||
return Ok(FieldPat {
|
||||
attrs,
|
||||
member,
|
||||
colon_token: input.parse()?,
|
||||
pat: Box::new(multi_pat_with_leading_vert(input)?),
|
||||
});
|
||||
}
|
||||
|
||||
let ident = match member {
|
||||
Member::Named(ident) => ident,
|
||||
Member::Unnamed(_) => unreachable!(),
|
||||
};
|
||||
|
||||
let mut pat = Pat::Ident(PatIdent {
|
||||
attrs: Vec::new(),
|
||||
by_ref,
|
||||
mutability,
|
||||
ident: ident.clone(),
|
||||
subpat: None,
|
||||
});
|
||||
|
||||
if let Some(boxed) = boxed {
|
||||
pat = Pat::Box(PatBox {
|
||||
attrs: Vec::new(),
|
||||
box_token: boxed,
|
||||
pat: Box::new(pat),
|
||||
});
|
||||
}
|
||||
|
||||
Ok(FieldPat {
|
||||
attrs,
|
||||
member: Member::Named(ident),
|
||||
colon_token: None,
|
||||
pat: Box::new(pat),
|
||||
})
|
||||
}
|
||||
|
||||
fn pat_range(
|
||||
input: ParseStream,
|
||||
begin: ParseBuffer,
|
||||
qself: Option<QSelf>,
|
||||
path: Path,
|
||||
) -> Result<Pat> {
|
||||
let limits: RangeLimits = input.parse()?;
|
||||
let hi = input.call(pat_lit_expr)?;
|
||||
if let Some(hi) = hi {
|
||||
Ok(Pat::Range(PatRange {
|
||||
attrs: Vec::new(),
|
||||
lo: Box::new(Expr::Path(ExprPath {
|
||||
attrs: Vec::new(),
|
||||
qself,
|
||||
path,
|
||||
})),
|
||||
limits,
|
||||
hi,
|
||||
}))
|
||||
} else {
|
||||
Ok(Pat::Verbatim(verbatim::between(begin, input)))
|
||||
}
|
||||
}
|
||||
|
||||
fn pat_range_half_open(input: ParseStream, begin: ParseBuffer) -> Result<Pat> {
|
||||
let limits: RangeLimits = input.parse()?;
|
||||
let hi = input.call(pat_lit_expr)?;
|
||||
if hi.is_some() {
|
||||
Ok(Pat::Verbatim(verbatim::between(begin, input)))
|
||||
} else {
|
||||
match limits {
|
||||
RangeLimits::HalfOpen(dot2_token) => Ok(Pat::Rest(PatRest {
|
||||
attrs: Vec::new(),
|
||||
dot2_token,
|
||||
})),
|
||||
RangeLimits::Closed(_) => Err(input.error("expected range upper bound")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn pat_tuple(input: ParseStream) -> Result<PatTuple> {
|
||||
let content;
|
||||
let paren_token = parenthesized!(content in input);
|
||||
|
||||
let mut elems = Punctuated::new();
|
||||
while !content.is_empty() {
|
||||
let value = multi_pat_with_leading_vert(&content)?;
|
||||
elems.push_value(value);
|
||||
if content.is_empty() {
|
||||
break;
|
||||
}
|
||||
let punct = content.parse()?;
|
||||
elems.push_punct(punct);
|
||||
}
|
||||
|
||||
Ok(PatTuple {
|
||||
attrs: Vec::new(),
|
||||
paren_token,
|
||||
elems,
|
||||
})
|
||||
}
|
||||
|
||||
fn pat_reference(input: ParseStream) -> Result<PatReference> {
|
||||
Ok(PatReference {
|
||||
attrs: Vec::new(),
|
||||
and_token: input.parse()?,
|
||||
mutability: input.parse()?,
|
||||
pat: input.parse()?,
|
||||
})
|
||||
}
|
||||
|
||||
fn pat_lit_or_range(input: ParseStream) -> Result<Pat> {
|
||||
let begin = input.fork();
|
||||
let lo = input.call(pat_lit_expr)?.unwrap();
|
||||
if input.peek(Token![..]) {
|
||||
let limits: RangeLimits = input.parse()?;
|
||||
let hi = input.call(pat_lit_expr)?;
|
||||
if let Some(hi) = hi {
|
||||
Ok(Pat::Range(PatRange {
|
||||
attrs: Vec::new(),
|
||||
lo,
|
||||
limits,
|
||||
hi,
|
||||
}))
|
||||
} else {
|
||||
Ok(Pat::Verbatim(verbatim::between(begin, input)))
|
||||
}
|
||||
} else if let Expr::Verbatim(verbatim) = *lo {
|
||||
Ok(Pat::Verbatim(verbatim))
|
||||
} else {
|
||||
Ok(Pat::Lit(PatLit {
|
||||
attrs: Vec::new(),
|
||||
expr: lo,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
fn pat_lit_expr(input: ParseStream) -> Result<Option<Box<Expr>>> {
|
||||
if input.is_empty()
|
||||
|| input.peek(Token![|])
|
||||
|| input.peek(Token![=])
|
||||
|| input.peek(Token![:]) && !input.peek(Token![::])
|
||||
|| input.peek(Token![,])
|
||||
|| input.peek(Token![;])
|
||||
{
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let neg: Option<Token![-]> = input.parse()?;
|
||||
|
||||
let lookahead = input.lookahead1();
|
||||
let expr = if lookahead.peek(Lit) {
|
||||
Expr::Lit(input.parse()?)
|
||||
} else if lookahead.peek(Ident)
|
||||
|| lookahead.peek(Token![::])
|
||||
|| lookahead.peek(Token![<])
|
||||
|| lookahead.peek(Token![self])
|
||||
|| lookahead.peek(Token![Self])
|
||||
|| lookahead.peek(Token![super])
|
||||
|| lookahead.peek(Token![crate])
|
||||
{
|
||||
Expr::Path(input.parse()?)
|
||||
} else if lookahead.peek(Token![const]) {
|
||||
Expr::Verbatim(input.call(expr::parsing::expr_const)?)
|
||||
} else {
|
||||
return Err(lookahead.error());
|
||||
};
|
||||
|
||||
Ok(Some(Box::new(if let Some(neg) = neg {
|
||||
Expr::Unary(ExprUnary {
|
||||
attrs: Vec::new(),
|
||||
op: UnOp::Neg(neg),
|
||||
expr: Box::new(expr),
|
||||
})
|
||||
} else {
|
||||
expr
|
||||
})))
|
||||
}
|
||||
|
||||
fn pat_slice(input: ParseStream) -> Result<PatSlice> {
|
||||
let content;
|
||||
let bracket_token = bracketed!(content in input);
|
||||
|
||||
let mut elems = Punctuated::new();
|
||||
while !content.is_empty() {
|
||||
let value = multi_pat_with_leading_vert(&content)?;
|
||||
elems.push_value(value);
|
||||
if content.is_empty() {
|
||||
break;
|
||||
}
|
||||
let punct = content.parse()?;
|
||||
elems.push_punct(punct);
|
||||
}
|
||||
|
||||
Ok(PatSlice {
|
||||
attrs: Vec::new(),
|
||||
bracket_token,
|
||||
elems,
|
||||
})
|
||||
}
|
||||
|
||||
fn pat_const(input: ParseStream) -> Result<TokenStream> {
|
||||
let begin = input.fork();
|
||||
input.parse::<Token![const]>()?;
|
||||
|
||||
let content;
|
||||
braced!(content in input);
|
||||
content.call(Attribute::parse_inner)?;
|
||||
content.call(Block::parse_within)?;
|
||||
|
||||
Ok(verbatim::between(begin, input))
|
||||
}
|
||||
|
||||
pub fn multi_pat(input: ParseStream) -> Result<Pat> {
|
||||
multi_pat_impl(input, None)
|
||||
}
|
||||
|
||||
pub fn multi_pat_with_leading_vert(input: ParseStream) -> Result<Pat> {
|
||||
let leading_vert: Option<Token![|]> = input.parse()?;
|
||||
multi_pat_impl(input, leading_vert)
|
||||
}
|
||||
|
||||
fn multi_pat_impl(input: ParseStream, leading_vert: Option<Token![|]>) -> Result<Pat> {
|
||||
let mut pat: Pat = input.parse()?;
|
||||
if leading_vert.is_some()
|
||||
|| input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=])
|
||||
{
|
||||
let mut cases = Punctuated::new();
|
||||
cases.push_value(pat);
|
||||
while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
|
||||
let punct = input.parse()?;
|
||||
cases.push_punct(punct);
|
||||
let pat: Pat = input.parse()?;
|
||||
cases.push_value(pat);
|
||||
}
|
||||
pat = Pat::Or(PatOr {
|
||||
attrs: Vec::new(),
|
||||
leading_vert,
|
||||
cases,
|
||||
});
|
||||
}
|
||||
Ok(pat)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "printing")]
|
||||
mod printing {
|
||||
use super::*;
|
||||
use crate::attr::FilterAttrs;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{ToTokens, TokenStreamExt};
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for PatWild {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.append_all(self.attrs.outer());
|
||||
self.underscore_token.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for PatIdent {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.append_all(self.attrs.outer());
|
||||
self.by_ref.to_tokens(tokens);
|
||||
self.mutability.to_tokens(tokens);
|
||||
self.ident.to_tokens(tokens);
|
||||
if let Some((at_token, subpat)) = &self.subpat {
|
||||
at_token.to_tokens(tokens);
|
||||
subpat.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for PatStruct {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.append_all(self.attrs.outer());
|
||||
self.path.to_tokens(tokens);
|
||||
self.brace_token.surround(tokens, |tokens| {
|
||||
self.fields.to_tokens(tokens);
|
||||
// NOTE: We need a comma before the dot2 token if it is present.
|
||||
if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
|
||||
<Token![,]>::default().to_tokens(tokens);
|
||||
}
|
||||
self.dot2_token.to_tokens(tokens);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for PatTupleStruct {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.append_all(self.attrs.outer());
|
||||
self.path.to_tokens(tokens);
|
||||
self.pat.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for PatType {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.append_all(self.attrs.outer());
|
||||
self.pat.to_tokens(tokens);
|
||||
self.colon_token.to_tokens(tokens);
|
||||
self.ty.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for PatPath {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.append_all(self.attrs.outer());
|
||||
path::printing::print_path(tokens, &self.qself, &self.path);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for PatTuple {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.append_all(self.attrs.outer());
|
||||
self.paren_token.surround(tokens, |tokens| {
|
||||
self.elems.to_tokens(tokens);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for PatBox {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.append_all(self.attrs.outer());
|
||||
self.box_token.to_tokens(tokens);
|
||||
self.pat.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for PatReference {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.append_all(self.attrs.outer());
|
||||
self.and_token.to_tokens(tokens);
|
||||
self.mutability.to_tokens(tokens);
|
||||
self.pat.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for PatRest {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.append_all(self.attrs.outer());
|
||||
self.dot2_token.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for PatLit {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.append_all(self.attrs.outer());
|
||||
self.expr.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for PatRange {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.append_all(self.attrs.outer());
|
||||
self.lo.to_tokens(tokens);
|
||||
self.limits.to_tokens(tokens);
|
||||
self.hi.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for PatSlice {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.append_all(self.attrs.outer());
|
||||
self.bracket_token.surround(tokens, |tokens| {
|
||||
self.elems.to_tokens(tokens);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for PatMacro {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.append_all(self.attrs.outer());
|
||||
self.mac.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for PatOr {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.append_all(self.attrs.outer());
|
||||
self.leading_vert.to_tokens(tokens);
|
||||
self.cases.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for FieldPat {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.append_all(self.attrs.outer());
|
||||
if let Some(colon_token) = &self.colon_token {
|
||||
self.member.to_tokens(tokens);
|
||||
colon_token.to_tokens(tokens);
|
||||
}
|
||||
self.pat.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
}
|
||||
871
zeroidc/vendor/syn/src/path.rs
vendored
Normal file
871
zeroidc/vendor/syn/src/path.rs
vendored
Normal file
@@ -0,0 +1,871 @@
|
||||
use super::*;
|
||||
use crate::punctuated::Punctuated;
|
||||
|
||||
ast_struct! {
|
||||
/// A path at which a named item is exported (e.g. `std::collections::HashMap`).
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
|
||||
/// feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub struct Path {
|
||||
pub leading_colon: Option<Token![::]>,
|
||||
pub segments: Punctuated<PathSegment, Token![::]>,
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for Path
|
||||
where
|
||||
T: Into<PathSegment>,
|
||||
{
|
||||
fn from(segment: T) -> Self {
|
||||
let mut path = Path {
|
||||
leading_colon: None,
|
||||
segments: Punctuated::new(),
|
||||
};
|
||||
path.segments.push_value(segment.into());
|
||||
path
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A segment of a path together with any path arguments on that segment.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
|
||||
/// feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub struct PathSegment {
|
||||
pub ident: Ident,
|
||||
pub arguments: PathArguments,
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for PathSegment
|
||||
where
|
||||
T: Into<Ident>,
|
||||
{
|
||||
fn from(ident: T) -> Self {
|
||||
PathSegment {
|
||||
ident: ident.into(),
|
||||
arguments: PathArguments::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ast_enum! {
|
||||
/// Angle bracketed or parenthesized arguments of a path segment.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
|
||||
/// feature.*
|
||||
///
|
||||
/// ## Angle bracketed
|
||||
///
|
||||
/// The `<'a, T>` in `std::slice::iter<'a, T>`.
|
||||
///
|
||||
/// ## Parenthesized
|
||||
///
|
||||
/// The `(A, B) -> C` in `Fn(A, B) -> C`.
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub enum PathArguments {
|
||||
None,
|
||||
/// The `<'a, T>` in `std::slice::iter<'a, T>`.
|
||||
AngleBracketed(AngleBracketedGenericArguments),
|
||||
/// The `(A, B) -> C` in `Fn(A, B) -> C`.
|
||||
Parenthesized(ParenthesizedGenericArguments),
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PathArguments {
|
||||
fn default() -> Self {
|
||||
PathArguments::None
|
||||
}
|
||||
}
|
||||
|
||||
impl PathArguments {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
match self {
|
||||
PathArguments::None => true,
|
||||
PathArguments::AngleBracketed(bracketed) => bracketed.args.is_empty(),
|
||||
PathArguments::Parenthesized(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
fn is_none(&self) -> bool {
|
||||
match *self {
|
||||
PathArguments::None => true,
|
||||
PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ast_enum! {
|
||||
/// An individual generic argument, like `'a`, `T`, or `Item = T`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
|
||||
/// feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub enum GenericArgument {
|
||||
/// A lifetime argument.
|
||||
Lifetime(Lifetime),
|
||||
/// A type argument.
|
||||
Type(Type),
|
||||
/// A binding (equality constraint) on an associated type: the `Item =
|
||||
/// u8` in `Iterator<Item = u8>`.
|
||||
Binding(Binding),
|
||||
/// An associated type bound: `Iterator<Item: Display>`.
|
||||
Constraint(Constraint),
|
||||
/// A const expression. Must be inside of a block.
|
||||
///
|
||||
/// NOTE: Identity expressions are represented as Type arguments, as
|
||||
/// they are indistinguishable syntactically.
|
||||
Const(Expr),
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// Angle bracketed arguments of a path segment: the `<K, V>` in `HashMap<K,
|
||||
/// V>`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
|
||||
/// feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub struct AngleBracketedGenericArguments {
|
||||
pub colon2_token: Option<Token![::]>,
|
||||
pub lt_token: Token![<],
|
||||
pub args: Punctuated<GenericArgument, Token![,]>,
|
||||
pub gt_token: Token![>],
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A binding (equality constraint) on an associated type: `Item = u8`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
|
||||
/// feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub struct Binding {
|
||||
pub ident: Ident,
|
||||
pub eq_token: Token![=],
|
||||
pub ty: Type,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// An associated type bound: `Iterator<Item: Display>`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
|
||||
/// feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub struct Constraint {
|
||||
pub ident: Ident,
|
||||
pub colon_token: Token![:],
|
||||
pub bounds: Punctuated<TypeParamBound, Token![+]>,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// Arguments of a function path segment: the `(A, B) -> C` in `Fn(A,B) ->
|
||||
/// C`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
|
||||
/// feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub struct ParenthesizedGenericArguments {
|
||||
pub paren_token: token::Paren,
|
||||
/// `(A, B)`
|
||||
pub inputs: Punctuated<Type, Token![,]>,
|
||||
/// `C`
|
||||
pub output: ReturnType,
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// The explicit Self type in a qualified path: the `T` in `<T as
|
||||
/// Display>::fmt`.
|
||||
///
|
||||
/// The actual path, including the trait and the associated item, is stored
|
||||
/// separately. The `position` field represents the index of the associated
|
||||
/// item qualified with this Self type.
|
||||
///
|
||||
/// ```text
|
||||
/// <Vec<T> as a::b::Trait>::AssociatedItem
|
||||
/// ^~~~~~ ~~~~~~~~~~~~~~^
|
||||
/// ty position = 3
|
||||
///
|
||||
/// <Vec<T>>::AssociatedItem
|
||||
/// ^~~~~~ ^
|
||||
/// ty position = 0
|
||||
/// ```
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
|
||||
/// feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
|
||||
pub struct QSelf {
|
||||
pub lt_token: Token![<],
|
||||
pub ty: Box<Type>,
|
||||
pub position: usize,
|
||||
pub as_token: Option<Token![as]>,
|
||||
pub gt_token: Token![>],
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
pub mod parsing {
|
||||
use super::*;
|
||||
|
||||
use crate::ext::IdentExt;
|
||||
use crate::parse::{Parse, ParseStream, Result};
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for Path {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
Self::parse_helper(input, false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for GenericArgument {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
if input.peek(Lifetime) && !input.peek2(Token![+]) {
|
||||
return Ok(GenericArgument::Lifetime(input.parse()?));
|
||||
}
|
||||
|
||||
if input.peek(Ident) && input.peek2(Token![=]) {
|
||||
let ident: Ident = input.parse()?;
|
||||
let eq_token: Token![=] = input.parse()?;
|
||||
|
||||
let ty = if input.peek(Lit) {
|
||||
let begin = input.fork();
|
||||
input.parse::<Lit>()?;
|
||||
Type::Verbatim(verbatim::between(begin, input))
|
||||
} else if input.peek(token::Brace) {
|
||||
let begin = input.fork();
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
{
|
||||
input.parse::<ExprBlock>()?;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "full"))]
|
||||
{
|
||||
let content;
|
||||
braced!(content in input);
|
||||
content.parse::<Expr>()?;
|
||||
}
|
||||
|
||||
Type::Verbatim(verbatim::between(begin, input))
|
||||
} else {
|
||||
input.parse()?
|
||||
};
|
||||
|
||||
return Ok(GenericArgument::Binding(Binding {
|
||||
ident,
|
||||
eq_token,
|
||||
ty,
|
||||
}));
|
||||
}
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
{
|
||||
if input.peek(Ident) && input.peek2(Token![:]) && !input.peek2(Token![::]) {
|
||||
return Ok(GenericArgument::Constraint(input.parse()?));
|
||||
}
|
||||
}
|
||||
|
||||
if input.peek(Lit) || input.peek(token::Brace) {
|
||||
return const_argument(input).map(GenericArgument::Const);
|
||||
}
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
let begin = input.fork();
|
||||
|
||||
let argument: Type = input.parse()?;
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
{
|
||||
if match &argument {
|
||||
Type::Path(argument)
|
||||
if argument.qself.is_none()
|
||||
&& argument.path.leading_colon.is_none()
|
||||
&& argument.path.segments.len() == 1 =>
|
||||
{
|
||||
match argument.path.segments[0].arguments {
|
||||
PathArguments::AngleBracketed(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
} && if input.peek(Token![=]) {
|
||||
input.parse::<Token![=]>()?;
|
||||
input.parse::<Type>()?;
|
||||
true
|
||||
} else if input.peek(Token![:]) {
|
||||
input.parse::<Token![:]>()?;
|
||||
input.call(constraint_bounds)?;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
} {
|
||||
let verbatim = verbatim::between(begin, input);
|
||||
return Ok(GenericArgument::Type(Type::Verbatim(verbatim)));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(GenericArgument::Type(argument))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn const_argument(input: ParseStream) -> Result<Expr> {
|
||||
let lookahead = input.lookahead1();
|
||||
|
||||
if input.peek(Lit) {
|
||||
let lit = input.parse()?;
|
||||
return Ok(Expr::Lit(lit));
|
||||
}
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
{
|
||||
if input.peek(Ident) {
|
||||
let ident: Ident = input.parse()?;
|
||||
return Ok(Expr::Path(ExprPath {
|
||||
attrs: Vec::new(),
|
||||
qself: None,
|
||||
path: Path::from(ident),
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
if input.peek(token::Brace) {
|
||||
#[cfg(feature = "full")]
|
||||
{
|
||||
let block: ExprBlock = input.parse()?;
|
||||
return Ok(Expr::Block(block));
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "full"))]
|
||||
{
|
||||
let begin = input.fork();
|
||||
let content;
|
||||
braced!(content in input);
|
||||
content.parse::<Expr>()?;
|
||||
let verbatim = verbatim::between(begin, input);
|
||||
return Ok(Expr::Verbatim(verbatim));
|
||||
}
|
||||
}
|
||||
|
||||
Err(lookahead.error())
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for AngleBracketedGenericArguments {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
Ok(AngleBracketedGenericArguments {
|
||||
colon2_token: input.parse()?,
|
||||
lt_token: input.parse()?,
|
||||
args: {
|
||||
let mut args = Punctuated::new();
|
||||
loop {
|
||||
if input.peek(Token![>]) {
|
||||
break;
|
||||
}
|
||||
let value = input.parse()?;
|
||||
args.push_value(value);
|
||||
if input.peek(Token![>]) {
|
||||
break;
|
||||
}
|
||||
let punct = input.parse()?;
|
||||
args.push_punct(punct);
|
||||
}
|
||||
args
|
||||
},
|
||||
gt_token: input.parse()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for ParenthesizedGenericArguments {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let content;
|
||||
Ok(ParenthesizedGenericArguments {
|
||||
paren_token: parenthesized!(content in input),
|
||||
inputs: content.parse_terminated(Type::parse)?,
|
||||
output: input.call(ReturnType::without_plus)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for PathSegment {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
Self::parse_helper(input, false)
|
||||
}
|
||||
}
|
||||
|
||||
impl PathSegment {
|
||||
fn parse_helper(input: ParseStream, expr_style: bool) -> Result<Self> {
|
||||
if input.peek(Token![super]) || input.peek(Token![self]) || input.peek(Token![crate]) {
|
||||
let ident = input.call(Ident::parse_any)?;
|
||||
return Ok(PathSegment::from(ident));
|
||||
}
|
||||
|
||||
let ident = if input.peek(Token![Self]) {
|
||||
input.call(Ident::parse_any)?
|
||||
} else {
|
||||
input.parse()?
|
||||
};
|
||||
|
||||
if !expr_style && input.peek(Token![<]) && !input.peek(Token![<=])
|
||||
|| input.peek(Token![::]) && input.peek3(Token![<])
|
||||
{
|
||||
Ok(PathSegment {
|
||||
ident,
|
||||
arguments: PathArguments::AngleBracketed(input.parse()?),
|
||||
})
|
||||
} else {
|
||||
Ok(PathSegment::from(ident))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for Binding {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
Ok(Binding {
|
||||
ident: input.parse()?,
|
||||
eq_token: input.parse()?,
|
||||
ty: input.parse()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for Constraint {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
Ok(Constraint {
|
||||
ident: input.parse()?,
|
||||
colon_token: input.parse()?,
|
||||
bounds: constraint_bounds(input)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
fn constraint_bounds(input: ParseStream) -> Result<Punctuated<TypeParamBound, Token![+]>> {
|
||||
let mut bounds = Punctuated::new();
|
||||
loop {
|
||||
if input.peek(Token![,]) || input.peek(Token![>]) {
|
||||
break;
|
||||
}
|
||||
let value = input.parse()?;
|
||||
bounds.push_value(value);
|
||||
if !input.peek(Token![+]) {
|
||||
break;
|
||||
}
|
||||
let punct = input.parse()?;
|
||||
bounds.push_punct(punct);
|
||||
}
|
||||
Ok(bounds)
|
||||
}
|
||||
|
||||
impl Path {
|
||||
/// Parse a `Path` containing no path arguments on any of its segments.
|
||||
///
|
||||
/// *This function is available only if Syn is built with the `"parsing"`
|
||||
/// feature.*
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use syn::{Path, Result, Token};
|
||||
/// use syn::parse::{Parse, ParseStream};
|
||||
///
|
||||
/// // A simplified single `use` statement like:
|
||||
/// //
|
||||
/// // use std::collections::HashMap;
|
||||
/// //
|
||||
/// // Note that generic parameters are not allowed in a `use` statement
|
||||
/// // so the following must not be accepted.
|
||||
/// //
|
||||
/// // use a::<b>::c;
|
||||
/// struct SingleUse {
|
||||
/// use_token: Token![use],
|
||||
/// path: Path,
|
||||
/// }
|
||||
///
|
||||
/// impl Parse for SingleUse {
|
||||
/// fn parse(input: ParseStream) -> Result<Self> {
|
||||
/// Ok(SingleUse {
|
||||
/// use_token: input.parse()?,
|
||||
/// path: input.call(Path::parse_mod_style)?,
|
||||
/// })
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
pub fn parse_mod_style(input: ParseStream) -> Result<Self> {
|
||||
Ok(Path {
|
||||
leading_colon: input.parse()?,
|
||||
segments: {
|
||||
let mut segments = Punctuated::new();
|
||||
loop {
|
||||
if !input.peek(Ident)
|
||||
&& !input.peek(Token![super])
|
||||
&& !input.peek(Token![self])
|
||||
&& !input.peek(Token![Self])
|
||||
&& !input.peek(Token![crate])
|
||||
{
|
||||
break;
|
||||
}
|
||||
let ident = Ident::parse_any(input)?;
|
||||
segments.push_value(PathSegment::from(ident));
|
||||
if !input.peek(Token![::]) {
|
||||
break;
|
||||
}
|
||||
let punct = input.parse()?;
|
||||
segments.push_punct(punct);
|
||||
}
|
||||
if segments.is_empty() {
|
||||
return Err(input.error("expected path"));
|
||||
} else if segments.trailing_punct() {
|
||||
return Err(input.error("expected path segment"));
|
||||
}
|
||||
segments
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/// Determines whether this is a path of length 1 equal to the given
|
||||
/// ident.
|
||||
///
|
||||
/// For them to compare equal, it must be the case that:
|
||||
///
|
||||
/// - the path has no leading colon,
|
||||
/// - the number of path segments is 1,
|
||||
/// - the first path segment has no angle bracketed or parenthesized
|
||||
/// path arguments, and
|
||||
/// - the ident of the first path segment is equal to the given one.
|
||||
///
|
||||
/// *This function is available only if Syn is built with the `"parsing"`
|
||||
/// feature.*
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use syn::{Attribute, Error, Meta, NestedMeta, Result};
|
||||
/// # use std::iter::FromIterator;
|
||||
///
|
||||
/// fn get_serde_meta_items(attr: &Attribute) -> Result<Vec<NestedMeta>> {
|
||||
/// if attr.path.is_ident("serde") {
|
||||
/// match attr.parse_meta()? {
|
||||
/// Meta::List(meta) => Ok(Vec::from_iter(meta.nested)),
|
||||
/// bad => Err(Error::new_spanned(bad, "unrecognized attribute")),
|
||||
/// }
|
||||
/// } else {
|
||||
/// Ok(Vec::new())
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
pub fn is_ident<I: ?Sized>(&self, ident: &I) -> bool
|
||||
where
|
||||
Ident: PartialEq<I>,
|
||||
{
|
||||
match self.get_ident() {
|
||||
Some(id) => id == ident,
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// If this path consists of a single ident, returns the ident.
|
||||
///
|
||||
/// A path is considered an ident if:
|
||||
///
|
||||
/// - the path has no leading colon,
|
||||
/// - the number of path segments is 1, and
|
||||
/// - the first path segment has no angle bracketed or parenthesized
|
||||
/// path arguments.
|
||||
///
|
||||
/// *This function is available only if Syn is built with the `"parsing"`
|
||||
/// feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
pub fn get_ident(&self) -> Option<&Ident> {
|
||||
if self.leading_colon.is_none()
|
||||
&& self.segments.len() == 1
|
||||
&& self.segments[0].arguments.is_none()
|
||||
{
|
||||
Some(&self.segments[0].ident)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn parse_helper(input: ParseStream, expr_style: bool) -> Result<Self> {
|
||||
let mut path = Path {
|
||||
leading_colon: input.parse()?,
|
||||
segments: {
|
||||
let mut segments = Punctuated::new();
|
||||
let value = PathSegment::parse_helper(input, expr_style)?;
|
||||
segments.push_value(value);
|
||||
segments
|
||||
},
|
||||
};
|
||||
Path::parse_rest(input, &mut path, expr_style)?;
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
pub(crate) fn parse_rest(
|
||||
input: ParseStream,
|
||||
path: &mut Self,
|
||||
expr_style: bool,
|
||||
) -> Result<()> {
|
||||
while input.peek(Token![::]) && !input.peek3(token::Paren) {
|
||||
let punct: Token![::] = input.parse()?;
|
||||
path.segments.push_punct(punct);
|
||||
let value = PathSegment::parse_helper(input, expr_style)?;
|
||||
path.segments.push_value(value);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn qpath(input: ParseStream, expr_style: bool) -> Result<(Option<QSelf>, Path)> {
|
||||
if input.peek(Token![<]) {
|
||||
let lt_token: Token![<] = input.parse()?;
|
||||
let this: Type = input.parse()?;
|
||||
let path = if input.peek(Token![as]) {
|
||||
let as_token: Token![as] = input.parse()?;
|
||||
let path: Path = input.parse()?;
|
||||
Some((as_token, path))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let gt_token: Token![>] = input.parse()?;
|
||||
let colon2_token: Token![::] = input.parse()?;
|
||||
let mut rest = Punctuated::new();
|
||||
loop {
|
||||
let path = PathSegment::parse_helper(input, expr_style)?;
|
||||
rest.push_value(path);
|
||||
if !input.peek(Token![::]) {
|
||||
break;
|
||||
}
|
||||
let punct: Token![::] = input.parse()?;
|
||||
rest.push_punct(punct);
|
||||
}
|
||||
let (position, as_token, path) = match path {
|
||||
Some((as_token, mut path)) => {
|
||||
let pos = path.segments.len();
|
||||
path.segments.push_punct(colon2_token);
|
||||
path.segments.extend(rest.into_pairs());
|
||||
(pos, Some(as_token), path)
|
||||
}
|
||||
None => {
|
||||
let path = Path {
|
||||
leading_colon: Some(colon2_token),
|
||||
segments: rest,
|
||||
};
|
||||
(0, None, path)
|
||||
}
|
||||
};
|
||||
let qself = QSelf {
|
||||
lt_token,
|
||||
ty: Box::new(this),
|
||||
position,
|
||||
as_token,
|
||||
gt_token,
|
||||
};
|
||||
Ok((Some(qself), path))
|
||||
} else {
|
||||
let path = Path::parse_helper(input, expr_style)?;
|
||||
Ok((None, path))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "printing")]
|
||||
pub(crate) mod printing {
|
||||
use super::*;
|
||||
use crate::print::TokensOrDefault;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::ToTokens;
|
||||
use std::cmp;
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for Path {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.leading_colon.to_tokens(tokens);
|
||||
self.segments.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for PathSegment {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.ident.to_tokens(tokens);
|
||||
self.arguments.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for PathArguments {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
match self {
|
||||
PathArguments::None => {}
|
||||
PathArguments::AngleBracketed(arguments) => {
|
||||
arguments.to_tokens(tokens);
|
||||
}
|
||||
PathArguments::Parenthesized(arguments) => {
|
||||
arguments.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for GenericArgument {
|
||||
#[allow(clippy::match_same_arms)]
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
match self {
|
||||
GenericArgument::Lifetime(lt) => lt.to_tokens(tokens),
|
||||
GenericArgument::Type(ty) => ty.to_tokens(tokens),
|
||||
GenericArgument::Binding(tb) => tb.to_tokens(tokens),
|
||||
GenericArgument::Constraint(tc) => tc.to_tokens(tokens),
|
||||
GenericArgument::Const(e) => match *e {
|
||||
Expr::Lit(_) => e.to_tokens(tokens),
|
||||
|
||||
// NOTE: We should probably support parsing blocks with only
|
||||
// expressions in them without the full feature for const
|
||||
// generics.
|
||||
#[cfg(feature = "full")]
|
||||
Expr::Block(_) => e.to_tokens(tokens),
|
||||
|
||||
// ERROR CORRECTION: Add braces to make sure that the
|
||||
// generated code is valid.
|
||||
_ => token::Brace::default().surround(tokens, |tokens| {
|
||||
e.to_tokens(tokens);
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for AngleBracketedGenericArguments {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.colon2_token.to_tokens(tokens);
|
||||
self.lt_token.to_tokens(tokens);
|
||||
|
||||
// Print lifetimes before types and consts, all before bindings,
|
||||
// regardless of their order in self.args.
|
||||
//
|
||||
// TODO: ordering rules for const arguments vs type arguments have
|
||||
// not been settled yet. https://github.com/rust-lang/rust/issues/44580
|
||||
let mut trailing_or_empty = true;
|
||||
for param in self.args.pairs() {
|
||||
match **param.value() {
|
||||
GenericArgument::Lifetime(_) => {
|
||||
param.to_tokens(tokens);
|
||||
trailing_or_empty = param.punct().is_some();
|
||||
}
|
||||
GenericArgument::Type(_)
|
||||
| GenericArgument::Binding(_)
|
||||
| GenericArgument::Constraint(_)
|
||||
| GenericArgument::Const(_) => {}
|
||||
}
|
||||
}
|
||||
for param in self.args.pairs() {
|
||||
match **param.value() {
|
||||
GenericArgument::Type(_) | GenericArgument::Const(_) => {
|
||||
if !trailing_or_empty {
|
||||
<Token![,]>::default().to_tokens(tokens);
|
||||
}
|
||||
param.to_tokens(tokens);
|
||||
trailing_or_empty = param.punct().is_some();
|
||||
}
|
||||
GenericArgument::Lifetime(_)
|
||||
| GenericArgument::Binding(_)
|
||||
| GenericArgument::Constraint(_) => {}
|
||||
}
|
||||
}
|
||||
for param in self.args.pairs() {
|
||||
match **param.value() {
|
||||
GenericArgument::Binding(_) | GenericArgument::Constraint(_) => {
|
||||
if !trailing_or_empty {
|
||||
<Token![,]>::default().to_tokens(tokens);
|
||||
}
|
||||
param.to_tokens(tokens);
|
||||
trailing_or_empty = param.punct().is_some();
|
||||
}
|
||||
GenericArgument::Lifetime(_)
|
||||
| GenericArgument::Type(_)
|
||||
| GenericArgument::Const(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
self.gt_token.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for Binding {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.ident.to_tokens(tokens);
|
||||
self.eq_token.to_tokens(tokens);
|
||||
self.ty.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for Constraint {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.ident.to_tokens(tokens);
|
||||
self.colon_token.to_tokens(tokens);
|
||||
self.bounds.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for ParenthesizedGenericArguments {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.paren_token.surround(tokens, |tokens| {
|
||||
self.inputs.to_tokens(tokens);
|
||||
});
|
||||
self.output.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn print_path(tokens: &mut TokenStream, qself: &Option<QSelf>, path: &Path) {
|
||||
let qself = match qself {
|
||||
Some(qself) => qself,
|
||||
None => {
|
||||
path.to_tokens(tokens);
|
||||
return;
|
||||
}
|
||||
};
|
||||
qself.lt_token.to_tokens(tokens);
|
||||
qself.ty.to_tokens(tokens);
|
||||
|
||||
let pos = cmp::min(qself.position, path.segments.len());
|
||||
let mut segments = path.segments.pairs();
|
||||
if pos > 0 {
|
||||
TokensOrDefault(&qself.as_token).to_tokens(tokens);
|
||||
path.leading_colon.to_tokens(tokens);
|
||||
for (i, segment) in segments.by_ref().take(pos).enumerate() {
|
||||
if i + 1 == pos {
|
||||
segment.value().to_tokens(tokens);
|
||||
qself.gt_token.to_tokens(tokens);
|
||||
segment.punct().to_tokens(tokens);
|
||||
} else {
|
||||
segment.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qself.gt_token.to_tokens(tokens);
|
||||
path.leading_colon.to_tokens(tokens);
|
||||
}
|
||||
for segment in segments {
|
||||
segment.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
}
|
||||
16
zeroidc/vendor/syn/src/print.rs
vendored
Normal file
16
zeroidc/vendor/syn/src/print.rs
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::ToTokens;
|
||||
|
||||
pub struct TokensOrDefault<'a, T: 'a>(pub &'a Option<T>);
|
||||
|
||||
impl<'a, T> ToTokens for TokensOrDefault<'a, T>
|
||||
where
|
||||
T: ToTokens + Default,
|
||||
{
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
match self.0 {
|
||||
Some(t) => t.to_tokens(tokens),
|
||||
None => T::default().to_tokens(tokens),
|
||||
}
|
||||
}
|
||||
}
|
||||
1068
zeroidc/vendor/syn/src/punctuated.rs
vendored
Normal file
1068
zeroidc/vendor/syn/src/punctuated.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
44
zeroidc/vendor/syn/src/reserved.rs
vendored
Normal file
44
zeroidc/vendor/syn/src/reserved.rs
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
// Type for a syntax tree node that is reserved for future use.
|
||||
//
|
||||
// For example ExprReference contains a field `raw` of type Reserved. If `&raw
|
||||
// place` syntax becomes a thing as per https://github.com/rust-lang/rfcs/pull/2582,
|
||||
// we can backward compatibly change `raw`'s type to Option<Token![raw]> without
|
||||
// the possibility of breaking any code.
|
||||
|
||||
use proc_macro2::Span;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
#[cfg(feature = "extra-traits")]
|
||||
use std::fmt::{self, Debug};
|
||||
|
||||
ast_struct! {
|
||||
pub struct Reserved {
|
||||
_private: PhantomData<Span>,
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Reserved {
|
||||
fn default() -> Self {
|
||||
Reserved {
|
||||
_private: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "clone-impls")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
|
||||
impl Clone for Reserved {
|
||||
fn clone(&self) -> Self {
|
||||
Reserved {
|
||||
_private: self._private,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "extra-traits")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
|
||||
impl Debug for Reserved {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.debug_struct("Reserved").finish()
|
||||
}
|
||||
}
|
||||
4
zeroidc/vendor/syn/src/sealed.rs
vendored
Normal file
4
zeroidc/vendor/syn/src/sealed.rs
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
#[cfg(feature = "parsing")]
|
||||
pub mod lookahead {
|
||||
pub trait Sealed: Copy {}
|
||||
}
|
||||
67
zeroidc/vendor/syn/src/span.rs
vendored
Normal file
67
zeroidc/vendor/syn/src/span.rs
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
use proc_macro2::Span;
|
||||
|
||||
pub trait IntoSpans<S> {
|
||||
fn into_spans(self) -> S;
|
||||
}
|
||||
|
||||
impl IntoSpans<[Span; 1]> for Span {
|
||||
fn into_spans(self) -> [Span; 1] {
|
||||
[self]
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoSpans<[Span; 2]> for Span {
|
||||
fn into_spans(self) -> [Span; 2] {
|
||||
[self, self]
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoSpans<[Span; 3]> for Span {
|
||||
fn into_spans(self) -> [Span; 3] {
|
||||
[self, self, self]
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoSpans<[Span; 1]> for [Span; 1] {
|
||||
fn into_spans(self) -> [Span; 1] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoSpans<[Span; 2]> for [Span; 2] {
|
||||
fn into_spans(self) -> [Span; 2] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoSpans<[Span; 3]> for [Span; 3] {
|
||||
fn into_spans(self) -> [Span; 3] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
pub trait FromSpans: Sized {
|
||||
fn from_spans(spans: &[Span]) -> Self;
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
impl FromSpans for [Span; 1] {
|
||||
fn from_spans(spans: &[Span]) -> Self {
|
||||
[spans[0]]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
impl FromSpans for [Span; 2] {
|
||||
fn from_spans(spans: &[Span]) -> Self {
|
||||
[spans[0], spans[1]]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
impl FromSpans for [Span; 3] {
|
||||
fn from_spans(spans: &[Span]) -> Self {
|
||||
[spans[0], spans[1], spans[2]]
|
||||
}
|
||||
}
|
||||
114
zeroidc/vendor/syn/src/spanned.rs
vendored
Normal file
114
zeroidc/vendor/syn/src/spanned.rs
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
//! A trait that can provide the `Span` of the complete contents of a syntax
|
||||
//! tree node.
|
||||
//!
|
||||
//! *This module is available only if Syn is built with both the `"parsing"` and
|
||||
//! `"printing"` features.*
|
||||
//!
|
||||
//! <br>
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! Suppose in a procedural macro we have a [`Type`] that we want to assert
|
||||
//! implements the [`Sync`] trait. Maybe this is the type of one of the fields
|
||||
//! of a struct for which we are deriving a trait implementation, and we need to
|
||||
//! be able to pass a reference to one of those fields across threads.
|
||||
//!
|
||||
//! [`Type`]: crate::Type
|
||||
//! [`Sync`]: std::marker::Sync
|
||||
//!
|
||||
//! If the field type does *not* implement `Sync` as required, we want the
|
||||
//! compiler to report an error pointing out exactly which type it was.
|
||||
//!
|
||||
//! The following macro code takes a variable `ty` of type `Type` and produces a
|
||||
//! static assertion that `Sync` is implemented for that type.
|
||||
//!
|
||||
//! ```
|
||||
//! # extern crate proc_macro;
|
||||
//! #
|
||||
//! use proc_macro::TokenStream;
|
||||
//! use proc_macro2::Span;
|
||||
//! use quote::quote_spanned;
|
||||
//! use syn::Type;
|
||||
//! use syn::spanned::Spanned;
|
||||
//!
|
||||
//! # const IGNORE_TOKENS: &str = stringify! {
|
||||
//! #[proc_macro_derive(MyMacro)]
|
||||
//! # };
|
||||
//! pub fn my_macro(input: TokenStream) -> TokenStream {
|
||||
//! # let ty = get_a_type();
|
||||
//! /* ... */
|
||||
//!
|
||||
//! let assert_sync = quote_spanned! {ty.span()=>
|
||||
//! struct _AssertSync where #ty: Sync;
|
||||
//! };
|
||||
//!
|
||||
//! /* ... */
|
||||
//! # input
|
||||
//! }
|
||||
//! #
|
||||
//! # fn get_a_type() -> Type {
|
||||
//! # unimplemented!()
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! By inserting this `assert_sync` fragment into the output code generated by
|
||||
//! our macro, the user's code will fail to compile if `ty` does not implement
|
||||
//! `Sync`. The errors they would see look like the following.
|
||||
//!
|
||||
//! ```text
|
||||
//! error[E0277]: the trait bound `*const i32: std::marker::Sync` is not satisfied
|
||||
//! --> src/main.rs:10:21
|
||||
//! |
|
||||
//! 10 | bad_field: *const i32,
|
||||
//! | ^^^^^^^^^^ `*const i32` cannot be shared between threads safely
|
||||
//! ```
|
||||
//!
|
||||
//! In this technique, using the `Type`'s span for the error message makes the
|
||||
//! error appear in the correct place underlining the right type.
|
||||
//!
|
||||
//! <br>
|
||||
//!
|
||||
//! # Limitations
|
||||
//!
|
||||
//! The underlying [`proc_macro::Span::join`] method is nightly-only. When
|
||||
//! called from within a procedural macro in a nightly compiler, `Spanned` will
|
||||
//! use `join` to produce the intended span. When not using a nightly compiler,
|
||||
//! only the span of the *first token* of the syntax tree node is returned.
|
||||
//!
|
||||
//! In the common case of wanting to use the joined span as the span of a
|
||||
//! `syn::Error`, consider instead using [`syn::Error::new_spanned`] which is
|
||||
//! able to span the error correctly under the complete syntax tree node without
|
||||
//! needing the unstable `join`.
|
||||
//!
|
||||
//! [`syn::Error::new_spanned`]: crate::Error::new_spanned
|
||||
|
||||
use proc_macro2::Span;
|
||||
use quote::spanned::Spanned as ToTokens;
|
||||
|
||||
/// A trait that can provide the `Span` of the complete contents of a syntax
|
||||
/// tree node.
|
||||
///
|
||||
/// This trait is automatically implemented for all types that implement
|
||||
/// [`ToTokens`] from the `quote` crate, as well as for `Span` itself.
|
||||
///
|
||||
/// [`ToTokens`]: quote::ToTokens
|
||||
///
|
||||
/// See the [module documentation] for an example.
|
||||
///
|
||||
/// [module documentation]: self
|
||||
///
|
||||
/// *This trait is available only if Syn is built with both the `"parsing"` and
|
||||
/// `"printing"` features.*
|
||||
pub trait Spanned {
|
||||
/// Returns a `Span` covering the complete contents of this syntax tree
|
||||
/// node, or [`Span::call_site()`] if this node is empty.
|
||||
///
|
||||
/// [`Span::call_site()`]: proc_macro2::Span::call_site
|
||||
fn span(&self) -> Span;
|
||||
}
|
||||
|
||||
impl<T: ?Sized + ToTokens> Spanned for T {
|
||||
fn span(&self) -> Span {
|
||||
self.__span()
|
||||
}
|
||||
}
|
||||
345
zeroidc/vendor/syn/src/stmt.rs
vendored
Normal file
345
zeroidc/vendor/syn/src/stmt.rs
vendored
Normal file
@@ -0,0 +1,345 @@
|
||||
use super::*;
|
||||
|
||||
ast_struct! {
|
||||
/// A braced block containing Rust statements.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
|
||||
pub struct Block {
|
||||
pub brace_token: token::Brace,
|
||||
/// Statements in a block
|
||||
pub stmts: Vec<Stmt>,
|
||||
}
|
||||
}
|
||||
|
||||
ast_enum! {
|
||||
/// A statement, usually ending in a semicolon.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
|
||||
pub enum Stmt {
|
||||
/// A local (let) binding.
|
||||
Local(Local),
|
||||
|
||||
/// An item definition.
|
||||
Item(Item),
|
||||
|
||||
/// Expr without trailing semicolon.
|
||||
Expr(Expr),
|
||||
|
||||
/// Expression with trailing semicolon.
|
||||
Semi(Expr, Token![;]),
|
||||
}
|
||||
}
|
||||
|
||||
ast_struct! {
|
||||
/// A local `let` binding: `let x: u64 = s.parse()?`.
|
||||
///
|
||||
/// *This type is available only if Syn is built with the `"full"` feature.*
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
|
||||
pub struct Local {
|
||||
pub attrs: Vec<Attribute>,
|
||||
pub let_token: Token![let],
|
||||
pub pat: Pat,
|
||||
pub init: Option<(Token![=], Box<Expr>)>,
|
||||
pub semi_token: Token![;],
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
pub mod parsing {
|
||||
use super::*;
|
||||
use crate::parse::discouraged::Speculative;
|
||||
use crate::parse::{Parse, ParseBuffer, ParseStream, Result};
|
||||
use proc_macro2::TokenStream;
|
||||
|
||||
impl Block {
|
||||
/// Parse the body of a block as zero or more statements, possibly
|
||||
/// including one trailing expression.
|
||||
///
|
||||
/// *This function is available only if Syn is built with the `"parsing"`
|
||||
/// feature.*
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use syn::{braced, token, Attribute, Block, Ident, Result, Stmt, Token};
|
||||
/// use syn::parse::{Parse, ParseStream};
|
||||
///
|
||||
/// // Parse a function with no generics or parameter list.
|
||||
/// //
|
||||
/// // fn playground {
|
||||
/// // let mut x = 1;
|
||||
/// // x += 1;
|
||||
/// // println!("{}", x);
|
||||
/// // }
|
||||
/// struct MiniFunction {
|
||||
/// attrs: Vec<Attribute>,
|
||||
/// fn_token: Token![fn],
|
||||
/// name: Ident,
|
||||
/// brace_token: token::Brace,
|
||||
/// stmts: Vec<Stmt>,
|
||||
/// }
|
||||
///
|
||||
/// impl Parse for MiniFunction {
|
||||
/// fn parse(input: ParseStream) -> Result<Self> {
|
||||
/// let outer_attrs = input.call(Attribute::parse_outer)?;
|
||||
/// let fn_token: Token![fn] = input.parse()?;
|
||||
/// let name: Ident = input.parse()?;
|
||||
///
|
||||
/// let content;
|
||||
/// let brace_token = braced!(content in input);
|
||||
/// let inner_attrs = content.call(Attribute::parse_inner)?;
|
||||
/// let stmts = content.call(Block::parse_within)?;
|
||||
///
|
||||
/// Ok(MiniFunction {
|
||||
/// attrs: {
|
||||
/// let mut attrs = outer_attrs;
|
||||
/// attrs.extend(inner_attrs);
|
||||
/// attrs
|
||||
/// },
|
||||
/// fn_token,
|
||||
/// name,
|
||||
/// brace_token,
|
||||
/// stmts,
|
||||
/// })
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
|
||||
let mut stmts = Vec::new();
|
||||
loop {
|
||||
while let Some(semi) = input.parse::<Option<Token![;]>>()? {
|
||||
stmts.push(Stmt::Semi(Expr::Verbatim(TokenStream::new()), semi));
|
||||
}
|
||||
if input.is_empty() {
|
||||
break;
|
||||
}
|
||||
let s = parse_stmt(input, true)?;
|
||||
let requires_semicolon = if let Stmt::Expr(s) = &s {
|
||||
expr::requires_terminator(s)
|
||||
} else {
|
||||
false
|
||||
};
|
||||
stmts.push(s);
|
||||
if input.is_empty() {
|
||||
break;
|
||||
} else if requires_semicolon {
|
||||
return Err(input.error("unexpected token"));
|
||||
}
|
||||
}
|
||||
Ok(stmts)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for Block {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let content;
|
||||
Ok(Block {
|
||||
brace_token: braced!(content in input),
|
||||
stmts: content.call(Block::parse_within)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
|
||||
impl Parse for Stmt {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
parse_stmt(input, false)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
|
||||
let begin = input.fork();
|
||||
let mut attrs = input.call(Attribute::parse_outer)?;
|
||||
|
||||
// brace-style macros; paren and bracket macros get parsed as
|
||||
// expression statements.
|
||||
let ahead = input.fork();
|
||||
if let Ok(path) = ahead.call(Path::parse_mod_style) {
|
||||
if ahead.peek(Token![!])
|
||||
&& (ahead.peek2(token::Brace)
|
||||
&& !(ahead.peek3(Token![.]) || ahead.peek3(Token![?]))
|
||||
|| ahead.peek2(Ident))
|
||||
{
|
||||
input.advance_to(&ahead);
|
||||
return stmt_mac(input, attrs, path);
|
||||
}
|
||||
}
|
||||
|
||||
if input.peek(Token![let]) {
|
||||
stmt_local(input, attrs, begin)
|
||||
} else if input.peek(Token![pub])
|
||||
|| input.peek(Token![crate]) && !input.peek2(Token![::])
|
||||
|| input.peek(Token![extern])
|
||||
|| input.peek(Token![use])
|
||||
|| input.peek(Token![static]) && (input.peek2(Token![mut]) || input.peek2(Ident))
|
||||
|| input.peek(Token![const]) && !input.peek2(token::Brace)
|
||||
|| input.peek(Token![unsafe]) && !input.peek2(token::Brace)
|
||||
|| input.peek(Token![async])
|
||||
&& (input.peek2(Token![unsafe])
|
||||
|| input.peek2(Token![extern])
|
||||
|| input.peek2(Token![fn]))
|
||||
|| input.peek(Token![fn])
|
||||
|| input.peek(Token![mod])
|
||||
|| input.peek(Token![type])
|
||||
|| input.peek(Token![struct])
|
||||
|| input.peek(Token![enum])
|
||||
|| input.peek(Token![union]) && input.peek2(Ident)
|
||||
|| input.peek(Token![auto]) && input.peek2(Token![trait])
|
||||
|| input.peek(Token![trait])
|
||||
|| input.peek(Token![default])
|
||||
&& (input.peek2(Token![unsafe]) || input.peek2(Token![impl]))
|
||||
|| input.peek(Token![impl])
|
||||
|| input.peek(Token![macro])
|
||||
{
|
||||
let mut item: Item = input.parse()?;
|
||||
attrs.extend(item.replace_attrs(Vec::new()));
|
||||
item.replace_attrs(attrs);
|
||||
Ok(Stmt::Item(item))
|
||||
} else {
|
||||
stmt_expr(input, allow_nosemi, attrs)
|
||||
}
|
||||
}
|
||||
|
||||
fn stmt_mac(input: ParseStream, attrs: Vec<Attribute>, path: Path) -> Result<Stmt> {
|
||||
let bang_token: Token![!] = input.parse()?;
|
||||
let ident: Option<Ident> = input.parse()?;
|
||||
let (delimiter, tokens) = mac::parse_delimiter(input)?;
|
||||
let semi_token: Option<Token![;]> = input.parse()?;
|
||||
|
||||
Ok(Stmt::Item(Item::Macro(ItemMacro {
|
||||
attrs,
|
||||
ident,
|
||||
mac: Macro {
|
||||
path,
|
||||
bang_token,
|
||||
delimiter,
|
||||
tokens,
|
||||
},
|
||||
semi_token,
|
||||
})))
|
||||
}
|
||||
|
||||
fn stmt_local(input: ParseStream, attrs: Vec<Attribute>, begin: ParseBuffer) -> Result<Stmt> {
|
||||
let let_token: Token![let] = input.parse()?;
|
||||
|
||||
let mut pat: Pat = pat::parsing::multi_pat_with_leading_vert(input)?;
|
||||
if input.peek(Token![:]) {
|
||||
let colon_token: Token![:] = input.parse()?;
|
||||
let ty: Type = input.parse()?;
|
||||
pat = Pat::Type(PatType {
|
||||
attrs: Vec::new(),
|
||||
pat: Box::new(pat),
|
||||
colon_token,
|
||||
ty: Box::new(ty),
|
||||
});
|
||||
}
|
||||
|
||||
let init = if input.peek(Token![=]) {
|
||||
let eq_token: Token![=] = input.parse()?;
|
||||
let init: Expr = input.parse()?;
|
||||
|
||||
if input.peek(Token![else]) {
|
||||
input.parse::<Token![else]>()?;
|
||||
let content;
|
||||
braced!(content in input);
|
||||
content.call(Block::parse_within)?;
|
||||
let verbatim = Expr::Verbatim(verbatim::between(begin, input));
|
||||
let semi_token: Token![;] = input.parse()?;
|
||||
return Ok(Stmt::Semi(verbatim, semi_token));
|
||||
}
|
||||
|
||||
Some((eq_token, Box::new(init)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let semi_token: Token![;] = input.parse()?;
|
||||
|
||||
Ok(Stmt::Local(Local {
|
||||
attrs,
|
||||
let_token,
|
||||
pat,
|
||||
init,
|
||||
semi_token,
|
||||
}))
|
||||
}
|
||||
|
||||
fn stmt_expr(
|
||||
input: ParseStream,
|
||||
allow_nosemi: bool,
|
||||
mut attrs: Vec<Attribute>,
|
||||
) -> Result<Stmt> {
|
||||
let mut e = expr::parsing::expr_early(input)?;
|
||||
|
||||
let mut attr_target = &mut e;
|
||||
loop {
|
||||
attr_target = match attr_target {
|
||||
Expr::Assign(e) => &mut e.left,
|
||||
Expr::AssignOp(e) => &mut e.left,
|
||||
Expr::Binary(e) => &mut e.left,
|
||||
_ => break,
|
||||
};
|
||||
}
|
||||
attrs.extend(attr_target.replace_attrs(Vec::new()));
|
||||
attr_target.replace_attrs(attrs);
|
||||
|
||||
if input.peek(Token![;]) {
|
||||
return Ok(Stmt::Semi(e, input.parse()?));
|
||||
}
|
||||
|
||||
if allow_nosemi || !expr::requires_terminator(&e) {
|
||||
Ok(Stmt::Expr(e))
|
||||
} else {
|
||||
Err(input.error("expected semicolon"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "printing")]
|
||||
mod printing {
|
||||
use super::*;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{ToTokens, TokenStreamExt};
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for Block {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.brace_token.surround(tokens, |tokens| {
|
||||
tokens.append_all(&self.stmts);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for Stmt {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
match self {
|
||||
Stmt::Local(local) => local.to_tokens(tokens),
|
||||
Stmt::Item(item) => item.to_tokens(tokens),
|
||||
Stmt::Expr(expr) => expr.to_tokens(tokens),
|
||||
Stmt::Semi(expr, semi) => {
|
||||
expr.to_tokens(tokens);
|
||||
semi.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for Local {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
expr::printing::outer_attrs_to_tokens(&self.attrs, tokens);
|
||||
self.let_token.to_tokens(tokens);
|
||||
self.pat.to_tokens(tokens);
|
||||
if let Some((eq_token, init)) = &self.init {
|
||||
eq_token.to_tokens(tokens);
|
||||
init.to_tokens(tokens);
|
||||
}
|
||||
self.semi_token.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
}
|
||||
41
zeroidc/vendor/syn/src/thread.rs
vendored
Normal file
41
zeroidc/vendor/syn/src/thread.rs
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
use std::fmt::{self, Debug};
|
||||
use std::thread::{self, ThreadId};
|
||||
|
||||
/// ThreadBound is a Sync-maker and Send-maker that allows accessing a value
|
||||
/// of type T only from the original thread on which the ThreadBound was
|
||||
/// constructed.
|
||||
pub struct ThreadBound<T> {
|
||||
value: T,
|
||||
thread_id: ThreadId,
|
||||
}
|
||||
|
||||
unsafe impl<T> Sync for ThreadBound<T> {}
|
||||
|
||||
// Send bound requires Copy, as otherwise Drop could run in the wrong place.
|
||||
unsafe impl<T: Copy> Send for ThreadBound<T> {}
|
||||
|
||||
impl<T> ThreadBound<T> {
|
||||
pub fn new(value: T) -> Self {
|
||||
ThreadBound {
|
||||
value,
|
||||
thread_id: thread::current().id(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self) -> Option<&T> {
|
||||
if thread::current().id() == self.thread_id {
|
||||
Some(&self.value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Debug> Debug for ThreadBound<T> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self.get() {
|
||||
Some(value) => Debug::fmt(value, formatter),
|
||||
None => formatter.write_str("unknown"),
|
||||
}
|
||||
}
|
||||
}
|
||||
1013
zeroidc/vendor/syn/src/token.rs
vendored
Normal file
1013
zeroidc/vendor/syn/src/token.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
107
zeroidc/vendor/syn/src/tt.rs
vendored
Normal file
107
zeroidc/vendor/syn/src/tt.rs
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
use proc_macro2::{Delimiter, TokenStream, TokenTree};
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
pub struct TokenTreeHelper<'a>(pub &'a TokenTree);
|
||||
|
||||
impl<'a> PartialEq for TokenTreeHelper<'a> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
use proc_macro2::Spacing;
|
||||
|
||||
match (self.0, other.0) {
|
||||
(TokenTree::Group(g1), TokenTree::Group(g2)) => {
|
||||
match (g1.delimiter(), g2.delimiter()) {
|
||||
(Delimiter::Parenthesis, Delimiter::Parenthesis)
|
||||
| (Delimiter::Brace, Delimiter::Brace)
|
||||
| (Delimiter::Bracket, Delimiter::Bracket)
|
||||
| (Delimiter::None, Delimiter::None) => {}
|
||||
_ => return false,
|
||||
}
|
||||
|
||||
let s1 = g1.stream().into_iter();
|
||||
let mut s2 = g2.stream().into_iter();
|
||||
|
||||
for item1 in s1 {
|
||||
let item2 = match s2.next() {
|
||||
Some(item) => item,
|
||||
None => return false,
|
||||
};
|
||||
if TokenTreeHelper(&item1) != TokenTreeHelper(&item2) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
s2.next().is_none()
|
||||
}
|
||||
(TokenTree::Punct(o1), TokenTree::Punct(o2)) => {
|
||||
o1.as_char() == o2.as_char()
|
||||
&& match (o1.spacing(), o2.spacing()) {
|
||||
(Spacing::Alone, Spacing::Alone) | (Spacing::Joint, Spacing::Joint) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
(TokenTree::Literal(l1), TokenTree::Literal(l2)) => l1.to_string() == l2.to_string(),
|
||||
(TokenTree::Ident(s1), TokenTree::Ident(s2)) => s1 == s2,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Hash for TokenTreeHelper<'a> {
|
||||
fn hash<H: Hasher>(&self, h: &mut H) {
|
||||
use proc_macro2::Spacing;
|
||||
|
||||
match self.0 {
|
||||
TokenTree::Group(g) => {
|
||||
0u8.hash(h);
|
||||
match g.delimiter() {
|
||||
Delimiter::Parenthesis => 0u8.hash(h),
|
||||
Delimiter::Brace => 1u8.hash(h),
|
||||
Delimiter::Bracket => 2u8.hash(h),
|
||||
Delimiter::None => 3u8.hash(h),
|
||||
}
|
||||
|
||||
for item in g.stream() {
|
||||
TokenTreeHelper(&item).hash(h);
|
||||
}
|
||||
0xffu8.hash(h); // terminator w/ a variant we don't normally hash
|
||||
}
|
||||
TokenTree::Punct(op) => {
|
||||
1u8.hash(h);
|
||||
op.as_char().hash(h);
|
||||
match op.spacing() {
|
||||
Spacing::Alone => 0u8.hash(h),
|
||||
Spacing::Joint => 1u8.hash(h),
|
||||
}
|
||||
}
|
||||
TokenTree::Literal(lit) => (2u8, lit.to_string()).hash(h),
|
||||
TokenTree::Ident(word) => (3u8, word).hash(h),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TokenStreamHelper<'a>(pub &'a TokenStream);
|
||||
|
||||
impl<'a> PartialEq for TokenStreamHelper<'a> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
let left = self.0.clone().into_iter().collect::<Vec<_>>();
|
||||
let right = other.0.clone().into_iter().collect::<Vec<_>>();
|
||||
if left.len() != right.len() {
|
||||
return false;
|
||||
}
|
||||
for (a, b) in left.into_iter().zip(right) {
|
||||
if TokenTreeHelper(&a) != TokenTreeHelper(&b) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Hash for TokenStreamHelper<'a> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
let tts = self.0.clone().into_iter().collect::<Vec<_>>();
|
||||
tts.len().hash(state);
|
||||
for tt in tts {
|
||||
TokenTreeHelper(&tt).hash(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
1255
zeroidc/vendor/syn/src/ty.rs
vendored
Normal file
1255
zeroidc/vendor/syn/src/ty.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
15
zeroidc/vendor/syn/src/verbatim.rs
vendored
Normal file
15
zeroidc/vendor/syn/src/verbatim.rs
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
use crate::parse::{ParseBuffer, ParseStream};
|
||||
use proc_macro2::TokenStream;
|
||||
use std::iter;
|
||||
|
||||
pub fn between<'a>(begin: ParseBuffer<'a>, end: ParseStream<'a>) -> TokenStream {
|
||||
let end = end.cursor();
|
||||
let mut cursor = begin.cursor();
|
||||
let mut tokens = TokenStream::new();
|
||||
while cursor != end {
|
||||
let (tt, next) = cursor.token_tree().unwrap();
|
||||
tokens.extend(iter::once(tt));
|
||||
cursor = next;
|
||||
}
|
||||
tokens
|
||||
}
|
||||
65
zeroidc/vendor/syn/src/whitespace.rs
vendored
Normal file
65
zeroidc/vendor/syn/src/whitespace.rs
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
pub fn skip(mut s: &str) -> &str {
|
||||
'skip: while !s.is_empty() {
|
||||
let byte = s.as_bytes()[0];
|
||||
if byte == b'/' {
|
||||
if s.starts_with("//")
|
||||
&& (!s.starts_with("///") || s.starts_with("////"))
|
||||
&& !s.starts_with("//!")
|
||||
{
|
||||
if let Some(i) = s.find('\n') {
|
||||
s = &s[i + 1..];
|
||||
continue;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
} else if s.starts_with("/**/") {
|
||||
s = &s[4..];
|
||||
continue;
|
||||
} else if s.starts_with("/*")
|
||||
&& (!s.starts_with("/**") || s.starts_with("/***"))
|
||||
&& !s.starts_with("/*!")
|
||||
{
|
||||
let mut depth = 0;
|
||||
let bytes = s.as_bytes();
|
||||
let mut i = 0;
|
||||
let upper = bytes.len() - 1;
|
||||
while i < upper {
|
||||
if bytes[i] == b'/' && bytes[i + 1] == b'*' {
|
||||
depth += 1;
|
||||
i += 1; // eat '*'
|
||||
} else if bytes[i] == b'*' && bytes[i + 1] == b'/' {
|
||||
depth -= 1;
|
||||
if depth == 0 {
|
||||
s = &s[i + 2..];
|
||||
continue 'skip;
|
||||
}
|
||||
i += 1; // eat '/'
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
match byte {
|
||||
b' ' | 0x09..=0x0d => {
|
||||
s = &s[1..];
|
||||
continue;
|
||||
}
|
||||
b if b <= 0x7f => {}
|
||||
_ => {
|
||||
let ch = s.chars().next().unwrap();
|
||||
if is_whitespace(ch) {
|
||||
s = &s[ch.len_utf8()..];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
s
|
||||
}
|
||||
|
||||
fn is_whitespace(ch: char) -> bool {
|
||||
// Rust treats left-to-right mark and right-to-left mark as whitespace
|
||||
ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}'
|
||||
}
|
||||
Reference in New Issue
Block a user