]>
Commit | Line | Data |
---|---|---|
29967ef6 | 1 | use proc_macro2::{Ident, Span}; |
e74abb32 XL |
2 | use std::cmp::Ordering; |
3 | use std::fmt::{self, Display}; | |
4 | use std::hash::{Hash, Hasher}; | |
5 | ||
e74abb32 XL |
6 | #[cfg(feature = "parsing")] |
7 | use crate::lookahead; | |
8 | ||
9 | /// A Rust lifetime: `'a`. | |
10 | /// | |
11 | /// Lifetime names must conform to the following rules: | |
12 | /// | |
13 | /// - Must start with an apostrophe. | |
14 | /// - Must not consist of just an apostrophe: `'`. | |
15 | /// - Character after the apostrophe must be `_` or a Unicode code point with | |
16 | /// the XID_Start property. | |
17 | /// - All following characters must be Unicode code points with the XID_Continue | |
18 | /// property. | |
e74abb32 XL |
19 | pub struct Lifetime { |
20 | pub apostrophe: Span, | |
21 | pub ident: Ident, | |
22 | } | |
23 | ||
24 | impl Lifetime { | |
25 | /// # Panics | |
26 | /// | |
27 | /// Panics if the lifetime does not conform to the bulleted rules above. | |
28 | /// | |
29 | /// # Invocation | |
30 | /// | |
31 | /// ``` | |
32 | /// # use proc_macro2::Span; | |
33 | /// # use syn::Lifetime; | |
34 | /// # | |
35 | /// # fn f() -> Lifetime { | |
36 | /// Lifetime::new("'a", Span::call_site()) | |
37 | /// # } | |
38 | /// ``` | |
39 | pub fn new(symbol: &str, span: Span) -> Self { | |
40 | if !symbol.starts_with('\'') { | |
41 | panic!( | |
42 | "lifetime name must start with apostrophe as in \"'a\", got {:?}", | |
43 | symbol | |
44 | ); | |
45 | } | |
46 | ||
47 | if symbol == "'" { | |
48 | panic!("lifetime name must not be empty"); | |
49 | } | |
50 | ||
51 | if !crate::ident::xid_ok(&symbol[1..]) { | |
52 | panic!("{:?} is not a valid lifetime name", symbol); | |
53 | } | |
54 | ||
55 | Lifetime { | |
56 | apostrophe: span, | |
57 | ident: Ident::new(&symbol[1..], span), | |
58 | } | |
59 | } | |
6a06907d XL |
60 | |
61 | pub fn span(&self) -> Span { | |
62 | self.apostrophe | |
63 | .join(self.ident.span()) | |
64 | .unwrap_or(self.apostrophe) | |
65 | } | |
66 | ||
67 | pub fn set_span(&mut self, span: Span) { | |
68 | self.apostrophe = span; | |
69 | self.ident.set_span(span); | |
70 | } | |
e74abb32 XL |
71 | } |
72 | ||
73 | impl Display for Lifetime { | |
74 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
75 | "'".fmt(formatter)?; | |
76 | self.ident.fmt(formatter) | |
77 | } | |
78 | } | |
79 | ||
1b1a35ee XL |
80 | impl Clone for Lifetime { |
81 | fn clone(&self) -> Self { | |
82 | Lifetime { | |
83 | apostrophe: self.apostrophe, | |
84 | ident: self.ident.clone(), | |
85 | } | |
86 | } | |
87 | } | |
88 | ||
e74abb32 XL |
89 | impl PartialEq for Lifetime { |
90 | fn eq(&self, other: &Lifetime) -> bool { | |
91 | self.ident.eq(&other.ident) | |
92 | } | |
93 | } | |
94 | ||
95 | impl Eq for Lifetime {} | |
96 | ||
97 | impl PartialOrd for Lifetime { | |
98 | fn partial_cmp(&self, other: &Lifetime) -> Option<Ordering> { | |
99 | Some(self.cmp(other)) | |
100 | } | |
101 | } | |
102 | ||
103 | impl Ord for Lifetime { | |
104 | fn cmp(&self, other: &Lifetime) -> Ordering { | |
105 | self.ident.cmp(&other.ident) | |
106 | } | |
107 | } | |
108 | ||
109 | impl Hash for Lifetime { | |
110 | fn hash<H: Hasher>(&self, h: &mut H) { | |
136023e0 | 111 | self.ident.hash(h); |
e74abb32 XL |
112 | } |
113 | } | |
114 | ||
115 | #[cfg(feature = "parsing")] | |
116 | #[doc(hidden)] | |
117 | #[allow(non_snake_case)] | |
118 | pub fn Lifetime(marker: lookahead::TokenMarker) -> Lifetime { | |
119 | match marker {} | |
120 | } | |
121 | ||
122 | #[cfg(feature = "parsing")] | |
123 | pub mod parsing { | |
124 | use super::*; | |
e74abb32 XL |
125 | use crate::parse::{Parse, ParseStream, Result}; |
126 | ||
5869c6ff | 127 | #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] |
e74abb32 XL |
128 | impl Parse for Lifetime { |
129 | fn parse(input: ParseStream) -> Result<Self> { | |
130 | input.step(|cursor| { | |
131 | cursor | |
132 | .lifetime() | |
133 | .ok_or_else(|| cursor.error("expected lifetime")) | |
134 | }) | |
135 | } | |
136 | } | |
137 | } | |
138 | ||
139 | #[cfg(feature = "printing")] | |
140 | mod printing { | |
141 | use super::*; | |
e74abb32 XL |
142 | use proc_macro2::{Punct, Spacing, TokenStream}; |
143 | use quote::{ToTokens, TokenStreamExt}; | |
144 | ||
5869c6ff | 145 | #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] |
e74abb32 XL |
146 | impl ToTokens for Lifetime { |
147 | fn to_tokens(&self, tokens: &mut TokenStream) { | |
148 | let mut apostrophe = Punct::new('\'', Spacing::Joint); | |
149 | apostrophe.set_span(self.apostrophe); | |
150 | tokens.append(apostrophe); | |
151 | self.ident.to_tokens(tokens); | |
152 | } | |
153 | } | |
154 | } |