]>
Commit | Line | Data |
---|---|---|
c30ab7b3 | 1 | //! A support library for macro authors when defining new macros. |
9e0c209e | 2 | //! |
c30ab7b3 | 3 | //! This library, provided by the standard distribution, provides the types |
94b46f34 | 4 | //! consumed in the interfaces of procedurally defined macro definitions such as |
b7449926 | 5 | //! function-like macros `#[proc_macro]`, macro attributes `#[proc_macro_attribute]` and |
94b46f34 | 6 | //! custom derive attributes`#[proc_macro_derive]`. |
9e0c209e | 7 | //! |
9fa01778 XL |
8 | //! See [the book] for more. |
9 | //! | |
10 | //! [the book]: ../book/ch19-06-macros.html#procedural-macros-for-generating-code-from-attributes | |
9e0c209e | 11 | |
476ff2be | 12 | #![stable(feature = "proc_macro_lib", since = "1.15.0")] |
c30ab7b3 | 13 | #![deny(missing_docs)] |
dfeec247 XL |
14 | #![doc( |
15 | html_root_url = "https://doc.rust-lang.org/nightly/", | |
16 | html_playground_url = "https://play.rust-lang.org/", | |
17 | issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", | |
18 | test(no_crate_inject, attr(deny(warnings))), | |
19 | test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))) | |
20 | )] | |
0bf4aa26 | 21 | #![feature(nll)] |
c30ab7b3 | 22 | #![feature(staged_api)] |
e1599b0c | 23 | #![feature(allow_internal_unstable)] |
e1599b0c | 24 | #![feature(decl_macro)] |
a1dfa0c6 XL |
25 | #![feature(extern_types)] |
26 | #![feature(in_band_lifetimes)] | |
0531ce1d | 27 | #![feature(optin_builtin_traits)] |
e1599b0c | 28 | #![feature(rustc_attrs)] |
a1dfa0c6 | 29 | #![feature(specialization)] |
dfeec247 | 30 | #![recursion_limit = "256"] |
94b46f34 | 31 | |
8faf50e0 XL |
32 | #[unstable(feature = "proc_macro_internals", issue = "27812")] |
33 | #[doc(hidden)] | |
a1dfa0c6 | 34 | pub mod bridge; |
8faf50e0 | 35 | |
ea8adc8c XL |
36 | mod diagnostic; |
37 | ||
b7449926 | 38 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] |
0bf4aa26 | 39 | pub use diagnostic::{Diagnostic, Level, MultiSpan}; |
9e0c209e | 40 | |
a1dfa0c6 | 41 | use std::ops::{Bound, RangeBounds}; |
8faf50e0 | 42 | use std::path::PathBuf; |
c30ab7b3 | 43 | use std::str::FromStr; |
dfeec247 | 44 | use std::{fmt, iter, mem}; |
c30ab7b3 | 45 | |
c30ab7b3 | 46 | /// The main type provided by this crate, representing an abstract stream of |
94b46f34 XL |
47 | /// tokens, or, more specifically, a sequence of token trees. |
48 | /// The type provide interfaces for iterating over those token trees and, conversely, | |
49 | /// collecting a number of token trees into one stream. | |
c30ab7b3 | 50 | /// |
94b46f34 XL |
51 | /// This is both the input and output of `#[proc_macro]`, `#[proc_macro_attribute]` |
52 | /// and `#[proc_macro_derive]` definitions. | |
476ff2be | 53 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] |
83c7162d | 54 | #[derive(Clone)] |
a1dfa0c6 | 55 | pub struct TokenStream(bridge::client::TokenStream); |
c30ab7b3 | 56 | |
94b46f34 | 57 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] |
83c7162d | 58 | impl !Send for TokenStream {} |
94b46f34 | 59 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] |
83c7162d XL |
60 | impl !Sync for TokenStream {} |
61 | ||
c30ab7b3 | 62 | /// Error returned from `TokenStream::from_str`. |
476ff2be | 63 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] |
041b39d2 | 64 | #[derive(Debug)] |
c30ab7b3 SL |
65 | pub struct LexError { |
66 | _inner: (), | |
67 | } | |
68 | ||
94b46f34 | 69 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] |
83c7162d | 70 | impl !Send for LexError {} |
94b46f34 | 71 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] |
83c7162d XL |
72 | impl !Sync for LexError {} |
73 | ||
74 | impl TokenStream { | |
94b46f34 | 75 | /// Returns an empty `TokenStream` containing no token trees. |
8faf50e0 | 76 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
94b46f34 | 77 | pub fn new() -> TokenStream { |
a1dfa0c6 | 78 | TokenStream(bridge::client::TokenStream::new()) |
83c7162d XL |
79 | } |
80 | ||
81 | /// Checks if this `TokenStream` is empty. | |
8faf50e0 | 82 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
83 | pub fn is_empty(&self) -> bool { |
84 | self.0.is_empty() | |
85 | } | |
86 | } | |
87 | ||
94b46f34 XL |
88 | /// Attempts to break the string into tokens and parse those tokens into a token stream. |
89 | /// May fail for a number of reasons, for example, if the string contains unbalanced delimiters | |
90 | /// or characters not existing in the language. | |
8faf50e0 | 91 | /// All tokens in the parsed stream get `Span::call_site()` spans. |
94b46f34 | 92 | /// |
9fa01778 | 93 | /// NOTE: some errors may cause panics instead of returning `LexError`. We reserve the right to |
94b46f34 | 94 | /// change these errors into `LexError`s later. |
041b39d2 XL |
95 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] |
96 | impl FromStr for TokenStream { | |
97 | type Err = LexError; | |
98 | ||
99 | fn from_str(src: &str) -> Result<TokenStream, LexError> { | |
a1dfa0c6 XL |
100 | Ok(TokenStream(bridge::client::TokenStream::from_str(src))) |
101 | } | |
102 | } | |
103 | ||
0731742a | 104 | // N.B., the bridge only provides `to_string`, implement `fmt::Display` |
a1dfa0c6 XL |
105 | // based on it (the reverse of the usual relationship between the two). |
106 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] | |
107 | impl ToString for TokenStream { | |
108 | fn to_string(&self) -> String { | |
109 | self.0.to_string() | |
041b39d2 XL |
110 | } |
111 | } | |
112 | ||
94b46f34 XL |
113 | /// Prints the token stream as a string that is supposed to be losslessly convertible back |
114 | /// into the same token stream (modulo spans), except for possibly `TokenTree::Group`s | |
115 | /// with `Delimiter::None` delimiters and negative numeric literals. | |
041b39d2 XL |
116 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] |
117 | impl fmt::Display for TokenStream { | |
9fa01778 | 118 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
a1dfa0c6 | 119 | f.write_str(&self.to_string()) |
041b39d2 XL |
120 | } |
121 | } | |
122 | ||
94b46f34 | 123 | /// Prints token in a form convenient for debugging. |
83c7162d XL |
124 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] |
125 | impl fmt::Debug for TokenStream { | |
9fa01778 | 126 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
83c7162d XL |
127 | f.write_str("TokenStream ")?; |
128 | f.debug_list().entries(self.clone()).finish() | |
129 | } | |
130 | } | |
041b39d2 | 131 | |
0bf4aa26 | 132 | #[unstable(feature = "proc_macro_quote", issue = "54722")] |
8faf50e0 XL |
133 | pub use quote::{quote, quote_span}; |
134 | ||
94b46f34 | 135 | /// Creates a token stream containing a single token tree. |
dfeec247 | 136 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 XL |
137 | impl From<TokenTree> for TokenStream { |
138 | fn from(tree: TokenTree) -> TokenStream { | |
a1dfa0c6 XL |
139 | TokenStream(bridge::client::TokenStream::from_token_tree(match tree { |
140 | TokenTree::Group(tt) => bridge::TokenTree::Group(tt.0), | |
141 | TokenTree::Punct(tt) => bridge::TokenTree::Punct(tt.0), | |
142 | TokenTree::Ident(tt) => bridge::TokenTree::Ident(tt.0), | |
dfeec247 | 143 | TokenTree::Literal(tt) => bridge::TokenTree::Literal(tt.0), |
a1dfa0c6 | 144 | })) |
041b39d2 XL |
145 | } |
146 | } | |
147 | ||
94b46f34 | 148 | /// Collects a number of token trees into a single stream. |
dfeec247 | 149 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
150 | impl iter::FromIterator<TokenTree> for TokenStream { |
151 | fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self { | |
152 | trees.into_iter().map(TokenStream::from).collect() | |
041b39d2 XL |
153 | } |
154 | } | |
155 | ||
94b46f34 XL |
156 | /// A "flattening" operation on token streams, collects token trees |
157 | /// from multiple token streams into a single stream. | |
158 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] | |
83c7162d XL |
159 | impl iter::FromIterator<TokenStream> for TokenStream { |
160 | fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self { | |
a1dfa0c6 | 161 | let mut builder = bridge::client::TokenStreamBuilder::new(); |
532ac7d7 | 162 | streams.into_iter().for_each(|stream| builder.push(stream.0)); |
041b39d2 XL |
163 | TokenStream(builder.build()) |
164 | } | |
165 | } | |
166 | ||
b7449926 XL |
167 | #[stable(feature = "token_stream_extend", since = "1.30.0")] |
168 | impl Extend<TokenTree> for TokenStream { | |
169 | fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, trees: I) { | |
170 | self.extend(trees.into_iter().map(TokenStream::from)); | |
171 | } | |
172 | } | |
173 | ||
174 | #[stable(feature = "token_stream_extend", since = "1.30.0")] | |
175 | impl Extend<TokenStream> for TokenStream { | |
176 | fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) { | |
a1dfa0c6 XL |
177 | // FIXME(eddyb) Use an optimized implementation if/when possible. |
178 | *self = iter::once(mem::replace(self, Self::new())).chain(streams).collect(); | |
b7449926 XL |
179 | } |
180 | } | |
181 | ||
94b46f34 | 182 | /// Public implementation details for the `TokenStream` type, such as iterators. |
8faf50e0 | 183 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 184 | pub mod token_stream { |
dfeec247 | 185 | use crate::{bridge, Group, Ident, Literal, Punct, TokenStream, TokenTree}; |
041b39d2 | 186 | |
94b46f34 | 187 | /// An iterator over `TokenStream`'s `TokenTree`s. |
0731742a | 188 | /// The iteration is "shallow", e.g., the iterator doesn't recurse into delimited groups, |
94b46f34 | 189 | /// and returns whole groups as token trees. |
83c7162d | 190 | #[derive(Clone)] |
8faf50e0 | 191 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
a1dfa0c6 | 192 | pub struct IntoIter(bridge::client::TokenStreamIter); |
041b39d2 | 193 | |
8faf50e0 | 194 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
195 | impl Iterator for IntoIter { |
196 | type Item = TokenTree; | |
197 | ||
198 | fn next(&mut self) -> Option<TokenTree> { | |
a1dfa0c6 XL |
199 | self.0.next().map(|tree| match tree { |
200 | bridge::TokenTree::Group(tt) => TokenTree::Group(Group(tt)), | |
201 | bridge::TokenTree::Punct(tt) => TokenTree::Punct(Punct(tt)), | |
202 | bridge::TokenTree::Ident(tt) => TokenTree::Ident(Ident(tt)), | |
203 | bridge::TokenTree::Literal(tt) => TokenTree::Literal(Literal(tt)), | |
204 | }) | |
83c7162d | 205 | } |
041b39d2 XL |
206 | } |
207 | ||
8faf50e0 | 208 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
209 | impl IntoIterator for TokenStream { |
210 | type Item = TokenTree; | |
211 | type IntoIter = IntoIter; | |
212 | ||
213 | fn into_iter(self) -> IntoIter { | |
a1dfa0c6 | 214 | IntoIter(self.0.into_iter()) |
83c7162d | 215 | } |
041b39d2 XL |
216 | } |
217 | } | |
218 | ||
83c7162d XL |
219 | /// `quote!(..)` accepts arbitrary tokens and expands into a `TokenStream` describing the input. |
220 | /// For example, `quote!(a + b)` will produce a expression, that, when evaluated, constructs | |
94b46f34 | 221 | /// the `TokenStream` `[Ident("a"), Punct('+', Alone), Ident("b")]`. |
83c7162d XL |
222 | /// |
223 | /// Unquoting is done with `$`, and works by taking the single next ident as the unquoted term. | |
224 | /// To quote `$` itself, use `$$`. | |
0bf4aa26 | 225 | #[unstable(feature = "proc_macro_quote", issue = "54722")] |
e1599b0c | 226 | #[allow_internal_unstable(proc_macro_def_site)] |
e74abb32 | 227 | #[rustc_builtin_macro] |
dfeec247 XL |
228 | pub macro quote($($t:tt)*) { |
229 | /* compiler built-in */ | |
230 | } | |
041b39d2 | 231 | |
83c7162d XL |
232 | #[unstable(feature = "proc_macro_internals", issue = "27812")] |
233 | #[doc(hidden)] | |
234 | mod quote; | |
041b39d2 | 235 | |
83c7162d | 236 | /// A region of source code, along with macro expansion information. |
8faf50e0 | 237 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 238 | #[derive(Copy, Clone)] |
a1dfa0c6 | 239 | pub struct Span(bridge::client::Span); |
83c7162d | 240 | |
8faf50e0 | 241 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 242 | impl !Send for Span {} |
8faf50e0 | 243 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
244 | impl !Sync for Span {} |
245 | ||
ea8adc8c XL |
246 | macro_rules! diagnostic_method { |
247 | ($name:ident, $level:expr) => ( | |
9fa01778 | 248 | /// Creates a new `Diagnostic` with the given `message` at the span |
ea8adc8c | 249 | /// `self`. |
b7449926 | 250 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] |
ea8adc8c XL |
251 | pub fn $name<T: Into<String>>(self, message: T) -> Diagnostic { |
252 | Diagnostic::spanned(self, $level, message) | |
253 | } | |
254 | ) | |
255 | } | |
256 | ||
041b39d2 | 257 | impl Span { |
83c7162d | 258 | /// A span that resolves at the macro definition site. |
0bf4aa26 | 259 | #[unstable(feature = "proc_macro_def_site", issue = "54724")] |
83c7162d | 260 | pub fn def_site() -> Span { |
a1dfa0c6 | 261 | Span(bridge::client::Span::def_site()) |
83c7162d XL |
262 | } |
263 | ||
041b39d2 | 264 | /// The span of the invocation of the current procedural macro. |
94b46f34 XL |
265 | /// Identifiers created with this span will be resolved as if they were written |
266 | /// directly at the macro call location (call-site hygiene) and other code | |
267 | /// at the macro call site will be able to refer to them as well. | |
8faf50e0 | 268 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 | 269 | pub fn call_site() -> Span { |
a1dfa0c6 | 270 | Span(bridge::client::Span::call_site()) |
041b39d2 | 271 | } |
ea8adc8c | 272 | |
e74abb32 XL |
273 | /// A span that represents `macro_rules` hygiene, and sometimes resolves at the macro |
274 | /// definition site (local variables, labels, `$crate`) and sometimes at the macro | |
275 | /// call site (everything else). | |
276 | /// The span location is taken from the call-site. | |
277 | #[unstable(feature = "proc_macro_mixed_site", issue = "65049")] | |
278 | pub fn mixed_site() -> Span { | |
279 | Span(bridge::client::Span::mixed_site()) | |
280 | } | |
281 | ||
ea8adc8c | 282 | /// The original source file into which this span points. |
0bf4aa26 | 283 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
ea8adc8c | 284 | pub fn source_file(&self) -> SourceFile { |
a1dfa0c6 | 285 | SourceFile(self.0.source_file()) |
ea8adc8c XL |
286 | } |
287 | ||
2c00a5a8 XL |
288 | /// The `Span` for the tokens in the previous macro expansion from which |
289 | /// `self` was generated from, if any. | |
0bf4aa26 | 290 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
2c00a5a8 | 291 | pub fn parent(&self) -> Option<Span> { |
83c7162d | 292 | self.0.parent().map(Span) |
2c00a5a8 XL |
293 | } |
294 | ||
295 | /// The span for the origin source code that `self` was generated from. If | |
296 | /// this `Span` wasn't generated from other macro expansions then the return | |
297 | /// value is the same as `*self`. | |
0bf4aa26 | 298 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
2c00a5a8 | 299 | pub fn source(&self) -> Span { |
a1dfa0c6 | 300 | Span(self.0.source()) |
2c00a5a8 XL |
301 | } |
302 | ||
9fa01778 | 303 | /// Gets the starting line/column in the source file for this span. |
0bf4aa26 | 304 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
ea8adc8c | 305 | pub fn start(&self) -> LineColumn { |
a1dfa0c6 | 306 | self.0.start() |
ea8adc8c XL |
307 | } |
308 | ||
9fa01778 | 309 | /// Gets the ending line/column in the source file for this span. |
0bf4aa26 | 310 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
ea8adc8c | 311 | pub fn end(&self) -> LineColumn { |
a1dfa0c6 | 312 | self.0.end() |
ea8adc8c XL |
313 | } |
314 | ||
9fa01778 | 315 | /// Creates a new span encompassing `self` and `other`. |
ea8adc8c XL |
316 | /// |
317 | /// Returns `None` if `self` and `other` are from different files. | |
0bf4aa26 | 318 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
ea8adc8c | 319 | pub fn join(&self, other: Span) -> Option<Span> { |
a1dfa0c6 | 320 | self.0.join(other.0).map(Span) |
ea8adc8c XL |
321 | } |
322 | ||
2c00a5a8 XL |
323 | /// Creates a new span with the same line/column information as `self` but |
324 | /// that resolves symbols as though it were at `other`. | |
0bf4aa26 | 325 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
2c00a5a8 | 326 | pub fn resolved_at(&self, other: Span) -> Span { |
a1dfa0c6 | 327 | Span(self.0.resolved_at(other.0)) |
2c00a5a8 XL |
328 | } |
329 | ||
330 | /// Creates a new span with the same name resolution behavior as `self` but | |
331 | /// with the line/column information of `other`. | |
0bf4aa26 | 332 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
2c00a5a8 XL |
333 | pub fn located_at(&self, other: Span) -> Span { |
334 | other.resolved_at(*self) | |
335 | } | |
336 | ||
83c7162d | 337 | /// Compares to spans to see if they're equal. |
0bf4aa26 | 338 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
83c7162d XL |
339 | pub fn eq(&self, other: &Span) -> bool { |
340 | self.0 == other.0 | |
341 | } | |
342 | ||
532ac7d7 XL |
343 | /// Returns the source text behind a span. This preserves the original source |
344 | /// code, including spaces and comments. It only returns a result if the span | |
345 | /// corresponds to real source code. | |
346 | /// | |
347 | /// Note: The observable result of a macro should only rely on the tokens and | |
348 | /// not on this source text. The result of this function is a best effort to | |
349 | /// be used for diagnostics only. | |
350 | #[unstable(feature = "proc_macro_span", issue = "54725")] | |
351 | pub fn source_text(&self) -> Option<String> { | |
352 | self.0.source_text() | |
353 | } | |
354 | ||
ea8adc8c XL |
355 | diagnostic_method!(error, Level::Error); |
356 | diagnostic_method!(warning, Level::Warning); | |
357 | diagnostic_method!(note, Level::Note); | |
358 | diagnostic_method!(help, Level::Help); | |
359 | } | |
360 | ||
94b46f34 | 361 | /// Prints a span in a form convenient for debugging. |
8faf50e0 | 362 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 363 | impl fmt::Debug for Span { |
9fa01778 | 364 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
a1dfa0c6 | 365 | self.0.fmt(f) |
83c7162d XL |
366 | } |
367 | } | |
368 | ||
ea8adc8c | 369 | /// A line-column pair representing the start or end of a `Span`. |
0bf4aa26 | 370 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
ea8adc8c XL |
371 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
372 | pub struct LineColumn { | |
373 | /// The 1-indexed line in the source file on which the span starts or ends (inclusive). | |
0bf4aa26 | 374 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
ff7c6d11 | 375 | pub line: usize, |
ea8adc8c XL |
376 | /// The 0-indexed column (in UTF-8 characters) in the source file on which |
377 | /// the span starts or ends (inclusive). | |
0bf4aa26 | 378 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
dfeec247 | 379 | pub column: usize, |
ea8adc8c XL |
380 | } |
381 | ||
0bf4aa26 | 382 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
83c7162d | 383 | impl !Send for LineColumn {} |
0bf4aa26 | 384 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
83c7162d XL |
385 | impl !Sync for LineColumn {} |
386 | ||
ea8adc8c | 387 | /// The source file of a given `Span`. |
0bf4aa26 | 388 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
ea8adc8c | 389 | #[derive(Clone)] |
a1dfa0c6 | 390 | pub struct SourceFile(bridge::client::SourceFile); |
0531ce1d | 391 | |
ea8adc8c | 392 | impl SourceFile { |
9fa01778 | 393 | /// Gets the path to this source file. |
ea8adc8c XL |
394 | /// |
395 | /// ### Note | |
396 | /// If the code span associated with this `SourceFile` was generated by an external macro, this | |
b7449926 | 397 | /// macro, this may not be an actual path on the filesystem. Use [`is_real`] to check. |
ea8adc8c | 398 | /// |
0531ce1d | 399 | /// Also note that even if `is_real` returns `true`, if `--remap-path-prefix` was passed on |
ea8adc8c XL |
400 | /// the command line, the path as given may not actually be valid. |
401 | /// | |
402 | /// [`is_real`]: #method.is_real | |
0bf4aa26 | 403 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
8faf50e0 | 404 | pub fn path(&self) -> PathBuf { |
a1dfa0c6 | 405 | PathBuf::from(self.0.path()) |
ea8adc8c XL |
406 | } |
407 | ||
408 | /// Returns `true` if this source file is a real source file, and not generated by an external | |
409 | /// macro's expansion. | |
0bf4aa26 | 410 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
ea8adc8c XL |
411 | pub fn is_real(&self) -> bool { |
412 | // This is a hack until intercrate spans are implemented and we can have real source files | |
413 | // for spans generated in external macros. | |
414 | // https://github.com/rust-lang/rust/pull/43604#issuecomment-333334368 | |
a1dfa0c6 | 415 | self.0.is_real() |
ea8adc8c XL |
416 | } |
417 | } | |
418 | ||
0bf4aa26 | 419 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
ea8adc8c | 420 | impl fmt::Debug for SourceFile { |
9fa01778 | 421 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
ea8adc8c | 422 | f.debug_struct("SourceFile") |
8faf50e0 | 423 | .field("path", &self.path()) |
ea8adc8c XL |
424 | .field("is_real", &self.is_real()) |
425 | .finish() | |
426 | } | |
427 | } | |
428 | ||
0bf4aa26 | 429 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
ea8adc8c XL |
430 | impl PartialEq for SourceFile { |
431 | fn eq(&self, other: &Self) -> bool { | |
a1dfa0c6 | 432 | self.0.eq(&other.0) |
ea8adc8c XL |
433 | } |
434 | } | |
435 | ||
0bf4aa26 | 436 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
ea8adc8c XL |
437 | impl Eq for SourceFile {} |
438 | ||
0731742a | 439 | /// A single token or a delimited sequence of token trees (e.g., `[1, (), ..]`). |
8faf50e0 | 440 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
441 | #[derive(Clone)] |
442 | pub enum TokenTree { | |
94b46f34 | 443 | /// A token stream surrounded by bracket delimiters. |
8faf50e0 | 444 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
dfeec247 | 445 | Group(#[stable(feature = "proc_macro_lib2", since = "1.29.0")] Group), |
94b46f34 | 446 | /// An identifier. |
8faf50e0 | 447 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
dfeec247 | 448 | Ident(#[stable(feature = "proc_macro_lib2", since = "1.29.0")] Ident), |
94b46f34 | 449 | /// A single punctuation character (`+`, `,`, `$`, etc.). |
8faf50e0 | 450 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
dfeec247 | 451 | Punct(#[stable(feature = "proc_macro_lib2", since = "1.29.0")] Punct), |
83c7162d | 452 | /// A literal character (`'a'`), string (`"hello"`), number (`2.3`), etc. |
8faf50e0 | 453 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
dfeec247 | 454 | Literal(#[stable(feature = "proc_macro_lib2", since = "1.29.0")] Literal), |
041b39d2 XL |
455 | } |
456 | ||
8faf50e0 | 457 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 458 | impl !Send for TokenTree {} |
8faf50e0 | 459 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
460 | impl !Sync for TokenTree {} |
461 | ||
462 | impl TokenTree { | |
94b46f34 XL |
463 | /// Returns the span of this tree, delegating to the `span` method of |
464 | /// the contained token or a delimited stream. | |
8faf50e0 | 465 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
466 | pub fn span(&self) -> Span { |
467 | match *self { | |
468 | TokenTree::Group(ref t) => t.span(), | |
94b46f34 XL |
469 | TokenTree::Ident(ref t) => t.span(), |
470 | TokenTree::Punct(ref t) => t.span(), | |
83c7162d XL |
471 | TokenTree::Literal(ref t) => t.span(), |
472 | } | |
473 | } | |
474 | ||
475 | /// Configures the span for *only this token*. | |
476 | /// | |
477 | /// Note that if this token is a `Group` then this method will not configure | |
478 | /// the span of each of the internal tokens, this will simply delegate to | |
479 | /// the `set_span` method of each variant. | |
8faf50e0 | 480 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
481 | pub fn set_span(&mut self, span: Span) { |
482 | match *self { | |
483 | TokenTree::Group(ref mut t) => t.set_span(span), | |
94b46f34 XL |
484 | TokenTree::Ident(ref mut t) => t.set_span(span), |
485 | TokenTree::Punct(ref mut t) => t.set_span(span), | |
83c7162d XL |
486 | TokenTree::Literal(ref mut t) => t.set_span(span), |
487 | } | |
488 | } | |
489 | } | |
490 | ||
a1dfa0c6 | 491 | /// Prints token tree in a form convenient for debugging. |
8faf50e0 | 492 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 493 | impl fmt::Debug for TokenTree { |
9fa01778 | 494 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
83c7162d XL |
495 | // Each of these has the name in the struct type in the derived debug, |
496 | // so don't bother with an extra layer of indirection | |
497 | match *self { | |
498 | TokenTree::Group(ref tt) => tt.fmt(f), | |
94b46f34 XL |
499 | TokenTree::Ident(ref tt) => tt.fmt(f), |
500 | TokenTree::Punct(ref tt) => tt.fmt(f), | |
83c7162d XL |
501 | TokenTree::Literal(ref tt) => tt.fmt(f), |
502 | } | |
503 | } | |
504 | } | |
505 | ||
8faf50e0 | 506 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
507 | impl From<Group> for TokenTree { |
508 | fn from(g: Group) -> TokenTree { | |
509 | TokenTree::Group(g) | |
510 | } | |
511 | } | |
512 | ||
8faf50e0 | 513 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
94b46f34 XL |
514 | impl From<Ident> for TokenTree { |
515 | fn from(g: Ident) -> TokenTree { | |
516 | TokenTree::Ident(g) | |
83c7162d XL |
517 | } |
518 | } | |
519 | ||
8faf50e0 | 520 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
94b46f34 XL |
521 | impl From<Punct> for TokenTree { |
522 | fn from(g: Punct) -> TokenTree { | |
523 | TokenTree::Punct(g) | |
83c7162d XL |
524 | } |
525 | } | |
526 | ||
8faf50e0 | 527 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
528 | impl From<Literal> for TokenTree { |
529 | fn from(g: Literal) -> TokenTree { | |
530 | TokenTree::Literal(g) | |
041b39d2 XL |
531 | } |
532 | } | |
533 | ||
0731742a | 534 | // N.B., the bridge only provides `to_string`, implement `fmt::Display` |
a1dfa0c6 XL |
535 | // based on it (the reverse of the usual relationship between the two). |
536 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] | |
537 | impl ToString for TokenTree { | |
538 | fn to_string(&self) -> String { | |
539 | match *self { | |
540 | TokenTree::Group(ref t) => t.to_string(), | |
541 | TokenTree::Ident(ref t) => t.to_string(), | |
542 | TokenTree::Punct(ref t) => t.to_string(), | |
543 | TokenTree::Literal(ref t) => t.to_string(), | |
544 | } | |
545 | } | |
546 | } | |
547 | ||
94b46f34 XL |
548 | /// Prints the token tree as a string that is supposed to be losslessly convertible back |
549 | /// into the same token tree (modulo spans), except for possibly `TokenTree::Group`s | |
550 | /// with `Delimiter::None` delimiters and negative numeric literals. | |
8faf50e0 | 551 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 | 552 | impl fmt::Display for TokenTree { |
9fa01778 | 553 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
a1dfa0c6 | 554 | f.write_str(&self.to_string()) |
041b39d2 XL |
555 | } |
556 | } | |
557 | ||
94b46f34 | 558 | /// A delimited token stream. |
83c7162d | 559 | /// |
94b46f34 | 560 | /// A `Group` internally contains a `TokenStream` which is surrounded by `Delimiter`s. |
8faf50e0 XL |
561 | #[derive(Clone)] |
562 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] | |
a1dfa0c6 | 563 | pub struct Group(bridge::client::Group); |
041b39d2 | 564 | |
8faf50e0 | 565 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 566 | impl !Send for Group {} |
8faf50e0 | 567 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
568 | impl !Sync for Group {} |
569 | ||
041b39d2 | 570 | /// Describes how a sequence of token trees is delimited. |
3b2f2976 | 571 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
8faf50e0 | 572 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 XL |
573 | pub enum Delimiter { |
574 | /// `( ... )` | |
8faf50e0 | 575 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 | 576 | Parenthesis, |
041b39d2 | 577 | /// `{ ... }` |
8faf50e0 | 578 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
3b2f2976 XL |
579 | Brace, |
580 | /// `[ ... ]` | |
8faf50e0 | 581 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 | 582 | Bracket, |
94b46f34 XL |
583 | /// `Ø ... Ø` |
584 | /// An implicit delimiter, that may, for example, appear around tokens coming from a | |
585 | /// "macro variable" `$var`. It is important to preserve operator priorities in cases like | |
586 | /// `$var * 3` where `$var` is `1 + 2`. | |
587 | /// Implicit delimiters may not survive roundtrip of a token stream through a string. | |
8faf50e0 | 588 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 XL |
589 | None, |
590 | } | |
591 | ||
83c7162d | 592 | impl Group { |
94b46f34 | 593 | /// Creates a new `Group` with the given delimiter and token stream. |
83c7162d XL |
594 | /// |
595 | /// This constructor will set the span for this group to | |
596 | /// `Span::call_site()`. To change the span you can use the `set_span` | |
597 | /// method below. | |
8faf50e0 | 598 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 599 | pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group { |
a1dfa0c6 | 600 | Group(bridge::client::Group::new(delimiter, stream.0)) |
83c7162d | 601 | } |
041b39d2 | 602 | |
83c7162d | 603 | /// Returns the delimiter of this `Group` |
8faf50e0 | 604 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 605 | pub fn delimiter(&self) -> Delimiter { |
a1dfa0c6 | 606 | self.0.delimiter() |
041b39d2 XL |
607 | } |
608 | ||
83c7162d XL |
609 | /// Returns the `TokenStream` of tokens that are delimited in this `Group`. |
610 | /// | |
611 | /// Note that the returned token stream does not include the delimiter | |
612 | /// returned above. | |
8faf50e0 | 613 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 614 | pub fn stream(&self) -> TokenStream { |
a1dfa0c6 | 615 | TokenStream(self.0.stream()) |
83c7162d XL |
616 | } |
617 | ||
618 | /// Returns the span for the delimiters of this token stream, spanning the | |
619 | /// entire `Group`. | |
b7449926 XL |
620 | /// |
621 | /// ```text | |
622 | /// pub fn span(&self) -> Span { | |
623 | /// ^^^^^^^ | |
624 | /// ``` | |
8faf50e0 | 625 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 626 | pub fn span(&self) -> Span { |
a1dfa0c6 | 627 | Span(self.0.span()) |
b7449926 XL |
628 | } |
629 | ||
630 | /// Returns the span pointing to the opening delimiter of this group. | |
631 | /// | |
632 | /// ```text | |
633 | /// pub fn span_open(&self) -> Span { | |
634 | /// ^ | |
635 | /// ``` | |
0bf4aa26 | 636 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
b7449926 | 637 | pub fn span_open(&self) -> Span { |
a1dfa0c6 | 638 | Span(self.0.span_open()) |
b7449926 XL |
639 | } |
640 | ||
641 | /// Returns the span pointing to the closing delimiter of this group. | |
642 | /// | |
643 | /// ```text | |
644 | /// pub fn span_close(&self) -> Span { | |
645 | /// ^ | |
646 | /// ``` | |
0bf4aa26 | 647 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
b7449926 | 648 | pub fn span_close(&self) -> Span { |
a1dfa0c6 | 649 | Span(self.0.span_close()) |
83c7162d XL |
650 | } |
651 | ||
652 | /// Configures the span for this `Group`'s delimiters, but not its internal | |
653 | /// tokens. | |
654 | /// | |
655 | /// This method will **not** set the span of all the internal tokens spanned | |
656 | /// by this group, but rather it will only set the span of the delimiter | |
657 | /// tokens at the level of the `Group`. | |
8faf50e0 | 658 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 659 | pub fn set_span(&mut self, span: Span) { |
a1dfa0c6 XL |
660 | self.0.set_span(span.0); |
661 | } | |
662 | } | |
663 | ||
0731742a | 664 | // N.B., the bridge only provides `to_string`, implement `fmt::Display` |
a1dfa0c6 XL |
665 | // based on it (the reverse of the usual relationship between the two). |
666 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] | |
667 | impl ToString for Group { | |
668 | fn to_string(&self) -> String { | |
669 | TokenStream::from(TokenTree::from(self.clone())).to_string() | |
83c7162d XL |
670 | } |
671 | } | |
672 | ||
94b46f34 XL |
673 | /// Prints the group as a string that should be losslessly convertible back |
674 | /// into the same group (modulo spans), except for possibly `TokenTree::Group`s | |
675 | /// with `Delimiter::None` delimiters. | |
8faf50e0 | 676 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 677 | impl fmt::Display for Group { |
9fa01778 | 678 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
a1dfa0c6 | 679 | f.write_str(&self.to_string()) |
041b39d2 XL |
680 | } |
681 | } | |
682 | ||
8faf50e0 XL |
683 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
684 | impl fmt::Debug for Group { | |
9fa01778 | 685 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
8faf50e0 XL |
686 | f.debug_struct("Group") |
687 | .field("delimiter", &self.delimiter()) | |
688 | .field("stream", &self.stream()) | |
689 | .field("span", &self.span()) | |
690 | .finish() | |
691 | } | |
692 | } | |
693 | ||
94b46f34 | 694 | /// An `Punct` is an single punctuation character like `+`, `-` or `#`. |
83c7162d | 695 | /// |
a1dfa0c6 | 696 | /// Multi-character operators like `+=` are represented as two instances of `Punct` with different |
83c7162d | 697 | /// forms of `Spacing` returned. |
8faf50e0 XL |
698 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
699 | #[derive(Clone)] | |
a1dfa0c6 | 700 | pub struct Punct(bridge::client::Punct); |
83c7162d | 701 | |
8faf50e0 | 702 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
94b46f34 | 703 | impl !Send for Punct {} |
8faf50e0 | 704 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
94b46f34 | 705 | impl !Sync for Punct {} |
83c7162d | 706 | |
94b46f34 XL |
707 | /// Whether an `Punct` is followed immediately by another `Punct` or |
708 | /// followed by another token or whitespace. | |
3b2f2976 | 709 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
8faf50e0 | 710 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 | 711 | pub enum Spacing { |
0731742a | 712 | /// e.g., `+` is `Alone` in `+ =`, `+ident` or `+()`. |
8faf50e0 | 713 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 | 714 | Alone, |
0731742a | 715 | /// e.g., `+` is `Joint` in `+=` or `'#`. |
94b46f34 | 716 | /// Additionally, single quote `'` can join with identifiers to form lifetimes `'ident`. |
8faf50e0 | 717 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 XL |
718 | Joint, |
719 | } | |
720 | ||
94b46f34 XL |
721 | impl Punct { |
722 | /// Creates a new `Punct` from the given character and spacing. | |
723 | /// The `ch` argument must be a valid punctuation character permitted by the language, | |
724 | /// otherwise the function will panic. | |
83c7162d | 725 | /// |
94b46f34 | 726 | /// The returned `Punct` will have the default span of `Span::call_site()` |
83c7162d | 727 | /// which can be further configured with the `set_span` method below. |
8faf50e0 | 728 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
94b46f34 | 729 | pub fn new(ch: char, spacing: Spacing) -> Punct { |
a1dfa0c6 | 730 | Punct(bridge::client::Punct::new(ch, spacing)) |
83c7162d XL |
731 | } |
732 | ||
94b46f34 | 733 | /// Returns the value of this punctuation character as `char`. |
8faf50e0 | 734 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
94b46f34 | 735 | pub fn as_char(&self) -> char { |
a1dfa0c6 | 736 | self.0.as_char() |
83c7162d XL |
737 | } |
738 | ||
94b46f34 XL |
739 | /// Returns the spacing of this punctuation character, indicating whether it's immediately |
740 | /// followed by another `Punct` in the token stream, so they can potentially be combined into | |
a1dfa0c6 | 741 | /// a multi-character operator (`Joint`), or it's followed by some other token or whitespace |
94b46f34 | 742 | /// (`Alone`) so the operator has certainly ended. |
8faf50e0 | 743 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 744 | pub fn spacing(&self) -> Spacing { |
a1dfa0c6 | 745 | self.0.spacing() |
83c7162d XL |
746 | } |
747 | ||
94b46f34 | 748 | /// Returns the span for this punctuation character. |
8faf50e0 | 749 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 750 | pub fn span(&self) -> Span { |
a1dfa0c6 | 751 | Span(self.0.span()) |
83c7162d XL |
752 | } |
753 | ||
94b46f34 | 754 | /// Configure the span for this punctuation character. |
8faf50e0 | 755 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 756 | pub fn set_span(&mut self, span: Span) { |
a1dfa0c6 XL |
757 | self.0 = self.0.with_span(span.0); |
758 | } | |
759 | } | |
760 | ||
0731742a | 761 | // N.B., the bridge only provides `to_string`, implement `fmt::Display` |
a1dfa0c6 XL |
762 | // based on it (the reverse of the usual relationship between the two). |
763 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] | |
764 | impl ToString for Punct { | |
765 | fn to_string(&self) -> String { | |
766 | TokenStream::from(TokenTree::from(self.clone())).to_string() | |
83c7162d XL |
767 | } |
768 | } | |
769 | ||
94b46f34 XL |
770 | /// Prints the punctuation character as a string that should be losslessly convertible |
771 | /// back into the same character. | |
8faf50e0 | 772 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
94b46f34 | 773 | impl fmt::Display for Punct { |
9fa01778 | 774 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
a1dfa0c6 | 775 | f.write_str(&self.to_string()) |
83c7162d XL |
776 | } |
777 | } | |
041b39d2 | 778 | |
8faf50e0 XL |
779 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
780 | impl fmt::Debug for Punct { | |
9fa01778 | 781 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
8faf50e0 XL |
782 | f.debug_struct("Punct") |
783 | .field("ch", &self.as_char()) | |
784 | .field("spacing", &self.spacing()) | |
785 | .field("span", &self.span()) | |
786 | .finish() | |
787 | } | |
788 | } | |
789 | ||
94b46f34 | 790 | /// An identifier (`ident`). |
8faf50e0 XL |
791 | #[derive(Clone)] |
792 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] | |
a1dfa0c6 | 793 | pub struct Ident(bridge::client::Ident); |
83c7162d | 794 | |
94b46f34 XL |
795 | impl Ident { |
796 | /// Creates a new `Ident` with the given `string` as well as the specified | |
83c7162d | 797 | /// `span`. |
94b46f34 XL |
798 | /// The `string` argument must be a valid identifier permitted by the |
799 | /// language, otherwise the function will panic. | |
83c7162d XL |
800 | /// |
801 | /// Note that `span`, currently in rustc, configures the hygiene information | |
94b46f34 XL |
802 | /// for this identifier. |
803 | /// | |
804 | /// As of this time `Span::call_site()` explicitly opts-in to "call-site" hygiene | |
805 | /// meaning that identifiers created with this span will be resolved as if they were written | |
806 | /// directly at the location of the macro call, and other code at the macro call site will be | |
807 | /// able to refer to them as well. | |
808 | /// | |
809 | /// Later spans like `Span::def_site()` will allow to opt-in to "definition-site" hygiene | |
810 | /// meaning that identifiers created with this span will be resolved at the location of the | |
811 | /// macro definition and other code at the macro call site will not be able to refer to them. | |
83c7162d XL |
812 | /// |
813 | /// Due to the current importance of hygiene this constructor, unlike other | |
814 | /// tokens, requires a `Span` to be specified at construction. | |
8faf50e0 | 815 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
94b46f34 | 816 | pub fn new(string: &str, span: Span) -> Ident { |
a1dfa0c6 | 817 | Ident(bridge::client::Ident::new(string, span.0, false)) |
83c7162d XL |
818 | } |
819 | ||
94b46f34 | 820 | /// Same as `Ident::new`, but creates a raw identifier (`r#ident`). |
0bf4aa26 | 821 | #[unstable(feature = "proc_macro_raw_ident", issue = "54723")] |
94b46f34 | 822 | pub fn new_raw(string: &str, span: Span) -> Ident { |
a1dfa0c6 | 823 | Ident(bridge::client::Ident::new(string, span.0, true)) |
83c7162d XL |
824 | } |
825 | ||
94b46f34 | 826 | /// Returns the span of this `Ident`, encompassing the entire string returned |
83c7162d | 827 | /// by `as_str`. |
8faf50e0 | 828 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 829 | pub fn span(&self) -> Span { |
a1dfa0c6 | 830 | Span(self.0.span()) |
83c7162d XL |
831 | } |
832 | ||
94b46f34 | 833 | /// Configures the span of this `Ident`, possibly changing its hygiene context. |
8faf50e0 | 834 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 835 | pub fn set_span(&mut self, span: Span) { |
a1dfa0c6 XL |
836 | self.0 = self.0.with_span(span.0); |
837 | } | |
838 | } | |
839 | ||
0731742a | 840 | // N.B., the bridge only provides `to_string`, implement `fmt::Display` |
a1dfa0c6 XL |
841 | // based on it (the reverse of the usual relationship between the two). |
842 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] | |
843 | impl ToString for Ident { | |
844 | fn to_string(&self) -> String { | |
845 | TokenStream::from(TokenTree::from(self.clone())).to_string() | |
83c7162d XL |
846 | } |
847 | } | |
848 | ||
94b46f34 XL |
849 | /// Prints the identifier as a string that should be losslessly convertible |
850 | /// back into the same identifier. | |
8faf50e0 | 851 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
94b46f34 | 852 | impl fmt::Display for Ident { |
9fa01778 | 853 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
a1dfa0c6 | 854 | f.write_str(&self.to_string()) |
8faf50e0 XL |
855 | } |
856 | } | |
857 | ||
858 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] | |
859 | impl fmt::Debug for Ident { | |
9fa01778 | 860 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
8faf50e0 XL |
861 | f.debug_struct("Ident") |
862 | .field("ident", &self.to_string()) | |
863 | .field("span", &self.span()) | |
864 | .finish() | |
041b39d2 XL |
865 | } |
866 | } | |
867 | ||
94b46f34 XL |
868 | /// A literal string (`"hello"`), byte string (`b"hello"`), |
869 | /// character (`'a'`), byte character (`b'a'`), an integer or floating point number | |
870 | /// with or without a suffix (`1`, `1u8`, `2.3`, `2.3f32`). | |
871 | /// Boolean literals like `true` and `false` do not belong here, they are `Ident`s. | |
a1dfa0c6 | 872 | #[derive(Clone)] |
8faf50e0 | 873 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
a1dfa0c6 | 874 | pub struct Literal(bridge::client::Literal); |
83c7162d XL |
875 | |
876 | macro_rules! suffixed_int_literals { | |
877 | ($($name:ident => $kind:ident,)*) => ($( | |
878 | /// Creates a new suffixed integer literal with the specified value. | |
879 | /// | |
880 | /// This function will create an integer like `1u32` where the integer | |
881 | /// value specified is the first part of the token and the integral is | |
882 | /// also suffixed at the end. | |
a1dfa0c6 | 883 | /// Literals created from negative numbers may not survive round-trips through |
94b46f34 | 884 | /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). |
83c7162d XL |
885 | /// |
886 | /// Literals created through this method have the `Span::call_site()` | |
887 | /// span by default, which can be configured with the `set_span` method | |
888 | /// below. | |
8faf50e0 | 889 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 890 | pub fn $name(n: $kind) -> Literal { |
a1dfa0c6 | 891 | Literal(bridge::client::Literal::typed_integer(&n.to_string(), stringify!($kind))) |
041b39d2 | 892 | } |
83c7162d XL |
893 | )*) |
894 | } | |
895 | ||
896 | macro_rules! unsuffixed_int_literals { | |
897 | ($($name:ident => $kind:ident,)*) => ($( | |
898 | /// Creates a new unsuffixed integer literal with the specified value. | |
899 | /// | |
900 | /// This function will create an integer like `1` where the integer | |
901 | /// value specified is the first part of the token. No suffix is | |
902 | /// specified on this token, meaning that invocations like | |
903 | /// `Literal::i8_unsuffixed(1)` are equivalent to | |
904 | /// `Literal::u32_unsuffixed(1)`. | |
94b46f34 XL |
905 | /// Literals created from negative numbers may not survive rountrips through |
906 | /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). | |
83c7162d XL |
907 | /// |
908 | /// Literals created through this method have the `Span::call_site()` | |
909 | /// span by default, which can be configured with the `set_span` method | |
910 | /// below. | |
8faf50e0 | 911 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 912 | pub fn $name(n: $kind) -> Literal { |
a1dfa0c6 | 913 | Literal(bridge::client::Literal::integer(&n.to_string())) |
83c7162d XL |
914 | } |
915 | )*) | |
041b39d2 XL |
916 | } |
917 | ||
918 | impl Literal { | |
83c7162d XL |
919 | suffixed_int_literals! { |
920 | u8_suffixed => u8, | |
921 | u16_suffixed => u16, | |
922 | u32_suffixed => u32, | |
923 | u64_suffixed => u64, | |
924 | u128_suffixed => u128, | |
925 | usize_suffixed => usize, | |
926 | i8_suffixed => i8, | |
927 | i16_suffixed => i16, | |
928 | i32_suffixed => i32, | |
929 | i64_suffixed => i64, | |
930 | i128_suffixed => i128, | |
931 | isize_suffixed => isize, | |
932 | } | |
933 | ||
934 | unsuffixed_int_literals! { | |
935 | u8_unsuffixed => u8, | |
936 | u16_unsuffixed => u16, | |
937 | u32_unsuffixed => u32, | |
938 | u64_unsuffixed => u64, | |
939 | u128_unsuffixed => u128, | |
940 | usize_unsuffixed => usize, | |
941 | i8_unsuffixed => i8, | |
942 | i16_unsuffixed => i16, | |
943 | i32_unsuffixed => i32, | |
944 | i64_unsuffixed => i64, | |
945 | i128_unsuffixed => i128, | |
946 | isize_unsuffixed => isize, | |
041b39d2 XL |
947 | } |
948 | ||
83c7162d XL |
949 | /// Creates a new unsuffixed floating-point literal. |
950 | /// | |
951 | /// This constructor is similar to those like `Literal::i8_unsuffixed` where | |
952 | /// the float's value is emitted directly into the token but no suffix is | |
953 | /// used, so it may be inferred to be a `f64` later in the compiler. | |
94b46f34 XL |
954 | /// Literals created from negative numbers may not survive rountrips through |
955 | /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). | |
83c7162d XL |
956 | /// |
957 | /// # Panics | |
958 | /// | |
959 | /// This function requires that the specified float is finite, for | |
960 | /// example if it is infinity or NaN this function will panic. | |
8faf50e0 | 961 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
962 | pub fn f32_unsuffixed(n: f32) -> Literal { |
963 | if !n.is_finite() { | |
964 | panic!("Invalid float literal {}", n); | |
965 | } | |
a1dfa0c6 | 966 | Literal(bridge::client::Literal::float(&n.to_string())) |
041b39d2 XL |
967 | } |
968 | ||
83c7162d XL |
969 | /// Creates a new suffixed floating-point literal. |
970 | /// | |
a1dfa0c6 | 971 | /// This constructor will create a literal like `1.0f32` where the value |
83c7162d XL |
972 | /// specified is the preceding part of the token and `f32` is the suffix of |
973 | /// the token. This token will always be inferred to be an `f32` in the | |
974 | /// compiler. | |
94b46f34 XL |
975 | /// Literals created from negative numbers may not survive rountrips through |
976 | /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). | |
83c7162d XL |
977 | /// |
978 | /// # Panics | |
979 | /// | |
980 | /// This function requires that the specified float is finite, for | |
981 | /// example if it is infinity or NaN this function will panic. | |
8faf50e0 | 982 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 983 | pub fn f32_suffixed(n: f32) -> Literal { |
041b39d2 XL |
984 | if !n.is_finite() { |
985 | panic!("Invalid float literal {}", n); | |
986 | } | |
a1dfa0c6 | 987 | Literal(bridge::client::Literal::f32(&n.to_string())) |
041b39d2 XL |
988 | } |
989 | ||
83c7162d XL |
990 | /// Creates a new unsuffixed floating-point literal. |
991 | /// | |
992 | /// This constructor is similar to those like `Literal::i8_unsuffixed` where | |
993 | /// the float's value is emitted directly into the token but no suffix is | |
994 | /// used, so it may be inferred to be a `f64` later in the compiler. | |
94b46f34 XL |
995 | /// Literals created from negative numbers may not survive rountrips through |
996 | /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). | |
83c7162d XL |
997 | /// |
998 | /// # Panics | |
999 | /// | |
1000 | /// This function requires that the specified float is finite, for | |
1001 | /// example if it is infinity or NaN this function will panic. | |
8faf50e0 | 1002 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 1003 | pub fn f64_unsuffixed(n: f64) -> Literal { |
041b39d2 | 1004 | if !n.is_finite() { |
83c7162d XL |
1005 | panic!("Invalid float literal {}", n); |
1006 | } | |
a1dfa0c6 | 1007 | Literal(bridge::client::Literal::float(&n.to_string())) |
041b39d2 XL |
1008 | } |
1009 | ||
83c7162d XL |
1010 | /// Creates a new suffixed floating-point literal. |
1011 | /// | |
a1dfa0c6 | 1012 | /// This constructor will create a literal like `1.0f64` where the value |
83c7162d XL |
1013 | /// specified is the preceding part of the token and `f64` is the suffix of |
1014 | /// the token. This token will always be inferred to be an `f64` in the | |
1015 | /// compiler. | |
94b46f34 XL |
1016 | /// Literals created from negative numbers may not survive rountrips through |
1017 | /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). | |
83c7162d XL |
1018 | /// |
1019 | /// # Panics | |
1020 | /// | |
1021 | /// This function requires that the specified float is finite, for | |
1022 | /// example if it is infinity or NaN this function will panic. | |
8faf50e0 | 1023 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 1024 | pub fn f64_suffixed(n: f64) -> Literal { |
041b39d2 | 1025 | if !n.is_finite() { |
83c7162d XL |
1026 | panic!("Invalid float literal {}", n); |
1027 | } | |
a1dfa0c6 | 1028 | Literal(bridge::client::Literal::f64(&n.to_string())) |
041b39d2 XL |
1029 | } |
1030 | ||
1031 | /// String literal. | |
8faf50e0 | 1032 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 | 1033 | pub fn string(string: &str) -> Literal { |
a1dfa0c6 | 1034 | Literal(bridge::client::Literal::string(string)) |
041b39d2 XL |
1035 | } |
1036 | ||
1037 | /// Character literal. | |
8faf50e0 | 1038 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 | 1039 | pub fn character(ch: char) -> Literal { |
a1dfa0c6 | 1040 | Literal(bridge::client::Literal::character(ch)) |
041b39d2 XL |
1041 | } |
1042 | ||
1043 | /// Byte string literal. | |
8faf50e0 | 1044 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 | 1045 | pub fn byte_string(bytes: &[u8]) -> Literal { |
a1dfa0c6 | 1046 | Literal(bridge::client::Literal::byte_string(bytes)) |
041b39d2 | 1047 | } |
041b39d2 | 1048 | |
83c7162d | 1049 | /// Returns the span encompassing this literal. |
8faf50e0 | 1050 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 1051 | pub fn span(&self) -> Span { |
a1dfa0c6 | 1052 | Span(self.0.span()) |
83c7162d XL |
1053 | } |
1054 | ||
1055 | /// Configures the span associated for this literal. | |
8faf50e0 | 1056 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 1057 | pub fn set_span(&mut self, span: Span) { |
a1dfa0c6 XL |
1058 | self.0.set_span(span.0); |
1059 | } | |
1060 | ||
1061 | /// Returns a `Span` that is a subset of `self.span()` containing only the | |
1062 | /// source bytes in range `range`. Returns `None` if the would-be trimmed | |
1063 | /// span is outside the bounds of `self`. | |
1064 | // FIXME(SergioBenitez): check that the byte range starts and ends at a | |
1065 | // UTF-8 boundary of the source. otherwise, it's likely that a panic will | |
1066 | // occur elsewhere when the source text is printed. | |
1067 | // FIXME(SergioBenitez): there is no way for the user to know what | |
1068 | // `self.span()` actually maps to, so this method can currently only be | |
1069 | // called blindly. For example, `to_string()` for the character 'c' returns | |
1070 | // "'\u{63}'"; there is no way for the user to know whether the source text | |
1071 | // was 'c' or whether it was '\u{63}'. | |
1072 | #[unstable(feature = "proc_macro_span", issue = "54725")] | |
1073 | pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> { | |
1074 | // HACK(eddyb) something akin to `Option::cloned`, but for `Bound<&T>`. | |
1075 | fn cloned_bound<T: Clone>(bound: Bound<&T>) -> Bound<T> { | |
1076 | match bound { | |
1077 | Bound::Included(x) => Bound::Included(x.clone()), | |
1078 | Bound::Excluded(x) => Bound::Excluded(x.clone()), | |
1079 | Bound::Unbounded => Bound::Unbounded, | |
1080 | } | |
1081 | } | |
1082 | ||
dfeec247 | 1083 | self.0.subspan(cloned_bound(range.start_bound()), cloned_bound(range.end_bound())).map(Span) |
a1dfa0c6 XL |
1084 | } |
1085 | } | |
1086 | ||
0731742a | 1087 | // N.B., the bridge only provides `to_string`, implement `fmt::Display` |
a1dfa0c6 XL |
1088 | // based on it (the reverse of the usual relationship between the two). |
1089 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] | |
1090 | impl ToString for Literal { | |
1091 | fn to_string(&self) -> String { | |
1092 | TokenStream::from(TokenTree::from(self.clone())).to_string() | |
83c7162d | 1093 | } |
041b39d2 XL |
1094 | } |
1095 | ||
94b46f34 XL |
1096 | /// Prints the literal as a string that should be losslessly convertible |
1097 | /// back into the same literal (except for possible rounding for floating point literals). | |
8faf50e0 | 1098 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 1099 | impl fmt::Display for Literal { |
9fa01778 | 1100 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
a1dfa0c6 | 1101 | f.write_str(&self.to_string()) |
041b39d2 XL |
1102 | } |
1103 | } | |
1104 | ||
a1dfa0c6 XL |
1105 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
1106 | impl fmt::Debug for Literal { | |
9fa01778 | 1107 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
a1dfa0c6 XL |
1108 | // FIXME(eddyb) `Literal` should not expose internal `Debug` impls. |
1109 | self.0.fmt(f) | |
c30ab7b3 SL |
1110 | } |
1111 | } |