158 lines · 3.8 KB · Rust
RawDownload
// SPDX-License-Identifier: Apache-2.0 OR MIT #[cfg(feature = "parsing")]use crate::lookahead;use proc_macro2::{Ident, Span};use std::cmp::Ordering;use std::fmt::{self, Display};use std::hash::{Hash, Hasher}; /// 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")]pub_if_not_doc! {    #[doc(hidden)]    #[allow(non_snake_case)]    pub fn Lifetime(marker: lookahead::TokenMarker) -> Lifetime {        match marker {}    }} #[cfg(feature = "parsing")]pub(crate) mod parsing {    use crate::error::Result;    use crate::lifetime::Lifetime;    use crate::parse::{Parse, ParseStream};     #[cfg_attr(docsrs, 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 crate::lifetime::Lifetime;    use proc_macro2::{Punct, Spacing, TokenStream};    use quote::{ToTokens, TokenStreamExt};     #[cfg_attr(docsrs, 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);        }    }}