1098 lines · 35.6 KB · Rust
RawDownload
// SPDX-License-Identifier: Apache-2.0 OR MIT //! Tokens representing Rust punctuation, keywords, and delimiters.//!//! The type names in this module can be difficult to keep straight, so we//! prefer to use the [`Token!`] macro instead. This is a type-macro that//! expands to the token type of the given token.//!//! [`Token!`]: crate::Token//!//! # Example//!//! The [`ItemStatic`] syntax tree node is defined like this.//!//! [`ItemStatic`]: crate::ItemStatic//!//! ```//! # use syn::{Attribute, Expr, Ident, Token, Type, Visibility};//! #//! pub struct ItemStatic {//!     pub attrs: Vec<Attribute>,//!     pub vis: Visibility,//!     pub static_token: Token![static],//!     pub mutability: Option<Token![mut]>,//!     pub ident: Ident,//!     pub colon_token: Token![:],//!     pub ty: Box<Type>,//!     pub eq_token: Token![=],//!     pub expr: Box<Expr>,//!     pub semi_token: Token![;],//! }//! ```//!//! # Parsing//!//! Keywords and punctuation can be parsed through the [`ParseStream::parse`]//! method. Delimiter tokens are parsed using the [`parenthesized!`],//! [`bracketed!`] and [`braced!`] macros.//!//! [`ParseStream::parse`]: crate::parse::ParseBuffer::parse()//! [`parenthesized!`]: crate::parenthesized!//! [`bracketed!`]: crate::bracketed!//! [`braced!`]: crate::braced!//!//! ```//! use syn::{Attribute, Result};//! use syn::parse::{Parse, ParseStream};//! #//! # enum ItemStatic {}//!//! // Parse the ItemStatic struct shown above.//! impl Parse for ItemStatic {//!     fn parse(input: ParseStream) -> Result<Self> {//!         # use syn::ItemStatic;//!         # fn parse(input: ParseStream) -> Result<ItemStatic> {//!         Ok(ItemStatic {//!             attrs: input.call(Attribute::parse_outer)?,//!             vis: input.parse()?,//!             static_token: input.parse()?,//!             mutability: input.parse()?,//!             ident: input.parse()?,//!             colon_token: input.parse()?,//!             ty: input.parse()?,//!             eq_token: input.parse()?,//!             expr: input.parse()?,//!             semi_token: input.parse()?,//!         })//!         # }//!         # unimplemented!()//!     }//! }//! ```//!//! # Other operations//!//! Every keyword and punctuation token supports the following operations.//!//! - [Peeking] — `input.peek(Token![...])`//!//! - [Parsing] — `input.parse::<Token![...]>()?`//!//! - [Printing] — `quote!( ... #the_token ... )`//!//! - Construction from a [`Span`] — `let the_token = Token![...](sp)`//!//! - Field access to its span — `let sp = the_token.span`//!//! [Peeking]: crate::parse::ParseBuffer::peek()//! [Parsing]: crate::parse::ParseBuffer::parse()//! [Printing]: https://docs.rs/quote/1.0/quote/trait.ToTokens.html//! [`Span`]: https://docs.rs/proc-macro2/1.0/proc_macro2/struct.Span.html #[cfg(feature = "parsing")]pub(crate) use self::private::CustomToken;use self::private::WithSpan;#[cfg(feature = "parsing")]use crate::buffer::Cursor;#[cfg(feature = "parsing")]use crate::error::Result;#[cfg(feature = "parsing")]use crate::lifetime::Lifetime;#[cfg(feature = "parsing")]use crate::parse::{Parse, ParseStream};use crate::span::IntoSpans;use proc_macro2::extra::DelimSpan;use proc_macro2::Span;#[cfg(feature = "printing")]use proc_macro2::TokenStream;#[cfg(any(feature = "parsing", feature = "printing"))]use proc_macro2::{Delimiter, Ident};#[cfg(feature = "parsing")]use proc_macro2::{Literal, Punct, TokenTree};#[cfg(feature = "printing")]use quote::{ToTokens, TokenStreamExt};#[cfg(feature = "extra-traits")]use std::cmp;#[cfg(feature = "extra-traits")]use std::fmt::{self, Debug};#[cfg(feature = "extra-traits")]use std::hash::{Hash, Hasher};use std::ops::{Deref, DerefMut}; /// Marker trait for types that represent single tokens.////// This trait is sealed and cannot be implemented for types outside of Syn.#[cfg(feature = "parsing")]pub trait Token: private::Sealed {    // Not public API.    #[doc(hidden)]    fn peek(cursor: Cursor) -> bool;     // Not public API.    #[doc(hidden)]    fn display() -> &'static str;} pub(crate) mod private {    #[cfg(feature = "parsing")]    use crate::buffer::Cursor;    use proc_macro2::Span;     #[cfg(feature = "parsing")]    pub trait Sealed {}     /// Support writing `token.span` rather than `token.spans[0]` on tokens that    /// hold a single span.    #[repr(transparent)]    #[allow(unknown_lints, repr_transparent_external_private_fields)] // False positive: https://github.com/rust-lang/rust/issues/78586#issuecomment-1722680482    pub struct WithSpan {        pub span: Span,    }     // Not public API.    #[doc(hidden)]    #[cfg(feature = "parsing")]    pub trait CustomToken {        fn peek(cursor: Cursor) -> bool;        fn display() -> &'static str;    }} #[cfg(feature = "parsing")]impl private::Sealed for Ident {} macro_rules! impl_low_level_token {    ($display:literal $($path:ident)::+ $get:ident) => {        #[cfg(feature = "parsing")]        impl Token for $($path)::+ {            fn peek(cursor: Cursor) -> bool {                cursor.$get().is_some()            }             fn display() -> &'static str {                $display            }        }         #[cfg(feature = "parsing")]        impl private::Sealed for $($path)::+ {}    };} impl_low_level_token!("punctuation token" Punct punct);impl_low_level_token!("literal" Literal literal);impl_low_level_token!("token" TokenTree token_tree);impl_low_level_token!("group token" proc_macro2::Group any_group);impl_low_level_token!("lifetime" Lifetime lifetime); #[cfg(feature = "parsing")]impl<T: CustomToken> private::Sealed for T {} #[cfg(feature = "parsing")]impl<T: CustomToken> Token for T {    fn peek(cursor: Cursor) -> bool {        <Self as CustomToken>::peek(cursor)    }     fn display() -> &'static str {        <Self as CustomToken>::display()    }} macro_rules! define_keywords {    ($($token:literal pub struct $name:ident)*) => {        $(            #[doc = concat!('`', $token, '`')]            ///            /// Don't try to remember the name of this type &mdash; use the            /// [`Token!`] macro instead.            ///            /// [`Token!`]: crate::token            pub struct $name {                pub span: Span,            }             #[doc(hidden)]            #[allow(non_snake_case)]            pub fn $name<S: IntoSpans<Span>>(span: S) -> $name {                $name {                    span: span.into_spans(),                }            }             impl std::default::Default for $name {                fn default() -> Self {                    $name {                        span: Span::call_site(),                    }                }            }             #[cfg(feature = "clone-impls")]            #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]            impl Copy for $name {}             #[cfg(feature = "clone-impls")]            #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]            impl Clone for $name {                fn clone(&self) -> Self {                    *self                }            }             #[cfg(feature = "extra-traits")]            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]            impl Debug for $name {                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {                    f.write_str(stringify!($name))                }            }             #[cfg(feature = "extra-traits")]            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]            impl cmp::Eq for $name {}             #[cfg(feature = "extra-traits")]            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]            impl PartialEq for $name {                fn eq(&self, _other: &$name) -> bool {                    true                }            }             #[cfg(feature = "extra-traits")]            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]            impl Hash for $name {                fn hash<H: Hasher>(&self, _state: &mut H) {}            }             #[cfg(feature = "printing")]            #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]            impl ToTokens for $name {                fn to_tokens(&self, tokens: &mut TokenStream) {                    printing::keyword($token, self.span, tokens);                }            }             #[cfg(feature = "parsing")]            #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]            impl Parse for $name {                fn parse(input: ParseStream) -> Result<Self> {                    Ok($name {                        span: parsing::keyword(input, $token)?,                    })                }            }             #[cfg(feature = "parsing")]            impl Token for $name {                fn peek(cursor: Cursor) -> bool {                    parsing::peek_keyword(cursor, $token)                }                 fn display() -> &'static str {                    concat!("`", $token, "`")                }            }             #[cfg(feature = "parsing")]            impl private::Sealed for $name {}        )*    };} macro_rules! impl_deref_if_len_is_1 {    ($name:ident/1) => {        impl Deref for $name {            type Target = WithSpan;             fn deref(&self) -> &Self::Target {                unsafe { &*(self as *const Self).cast::<WithSpan>() }            }        }         impl DerefMut for $name {            fn deref_mut(&mut self) -> &mut Self::Target {                unsafe { &mut *(self as *mut Self).cast::<WithSpan>() }            }        }    };     ($name:ident/$len:literal) => {};} macro_rules! define_punctuation_structs {    ($($token:literal pub struct $name:ident/$len:tt #[doc = $usage:literal])*) => {        $(            #[cfg_attr(not(doc), repr(transparent))]            #[allow(unknown_lints, repr_transparent_external_private_fields)] // False positive: https://github.com/rust-lang/rust/issues/78586#issuecomment-1722680482            #[doc = concat!('`', $token, '`')]            ///            /// Usage:            #[doc = concat!($usage, '.')]            ///            /// Don't try to remember the name of this type &mdash; use the            /// [`Token!`] macro instead.            ///            /// [`Token!`]: crate::token            pub struct $name {                pub spans: [Span; $len],            }             #[doc(hidden)]            #[allow(non_snake_case)]            pub fn $name<S: IntoSpans<[Span; $len]>>(spans: S) -> $name {                $name {                    spans: spans.into_spans(),                }            }             impl std::default::Default for $name {                fn default() -> Self {                    $name {                        spans: [Span::call_site(); $len],                    }                }            }             #[cfg(feature = "clone-impls")]            #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]            impl Copy for $name {}             #[cfg(feature = "clone-impls")]            #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]            impl Clone for $name {                fn clone(&self) -> Self {                    *self                }            }             #[cfg(feature = "extra-traits")]            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]            impl Debug for $name {                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {                    f.write_str(stringify!($name))                }            }             #[cfg(feature = "extra-traits")]            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]            impl cmp::Eq for $name {}             #[cfg(feature = "extra-traits")]            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]            impl PartialEq for $name {                fn eq(&self, _other: &$name) -> bool {                    true                }            }             #[cfg(feature = "extra-traits")]            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]            impl Hash for $name {                fn hash<H: Hasher>(&self, _state: &mut H) {}            }             impl_deref_if_len_is_1!($name/$len);        )*    };} macro_rules! define_punctuation {    ($($token:literal pub struct $name:ident/$len:tt #[doc = $usage:literal])*) => {        $(            define_punctuation_structs! {                $token pub struct $name/$len #[doc = $usage]            }             #[cfg(feature = "printing")]            #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]            impl ToTokens for $name {                fn to_tokens(&self, tokens: &mut TokenStream) {                    printing::punct($token, &self.spans, tokens);                }            }             #[cfg(feature = "parsing")]            #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]            impl Parse for $name {                fn parse(input: ParseStream) -> Result<Self> {                    Ok($name {                        spans: parsing::punct(input, $token)?,                    })                }            }             #[cfg(feature = "parsing")]            impl Token for $name {                fn peek(cursor: Cursor) -> bool {                    parsing::peek_punct(cursor, $token)                }                 fn display() -> &'static str {                    concat!("`", $token, "`")                }            }             #[cfg(feature = "parsing")]            impl private::Sealed for $name {}        )*    };} macro_rules! define_delimiters {    ($($delim:ident pub struct $name:ident #[$doc:meta])*) => {        $(            #[$doc]            pub struct $name {                pub span: DelimSpan,            }             #[doc(hidden)]            #[allow(non_snake_case)]            pub fn $name<S: IntoSpans<DelimSpan>>(span: S) -> $name {                $name {                    span: span.into_spans(),                }            }             impl std::default::Default for $name {                fn default() -> Self {                    $name(Span::call_site())                }            }             #[cfg(feature = "clone-impls")]            #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]            impl Copy for $name {}             #[cfg(feature = "clone-impls")]            #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]            impl Clone for $name {                fn clone(&self) -> Self {                    *self                }            }             #[cfg(feature = "extra-traits")]            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]            impl Debug for $name {                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {                    f.write_str(stringify!($name))                }            }             #[cfg(feature = "extra-traits")]            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]            impl cmp::Eq for $name {}             #[cfg(feature = "extra-traits")]            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]            impl PartialEq for $name {                fn eq(&self, _other: &$name) -> bool {                    true                }            }             #[cfg(feature = "extra-traits")]            #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]            impl Hash for $name {

Lines 1–500 of 1098.