1 use crate::parse::{token_stream, Cursor};
2 use crate::{Delimiter, Spacing, TokenTree};
3 #[cfg(span_locations)]
4 use std::cell::RefCell;
5 #[cfg(span_locations)]
6 use std::cmp;
7 use std::fmt::{self, Debug, Display};
8 use std::iter::FromIterator;
9 use std::mem;
10 use std::ops::RangeBounds;
11 #[cfg(procmacro2_semver_exempt)]
12 use std::path::Path;
13 use std::path::PathBuf;
14 use std::str::FromStr;
15 use std::vec;
16 use unicode_xid::UnicodeXID;
17 
18 /// Force use of proc-macro2's fallback implementation of the API for now, even
19 /// if the compiler's implementation is available.
force()20 pub fn force() {
21     #[cfg(wrap_proc_macro)]
22     crate::detection::force_fallback();
23 }
24 
25 /// Resume using the compiler's implementation of the proc macro API if it is
26 /// available.
unforce()27 pub fn unforce() {
28     #[cfg(wrap_proc_macro)]
29     crate::detection::unforce_fallback();
30 }
31 
32 #[derive(Clone)]
33 pub(crate) struct TokenStream {
34     pub(crate) inner: Vec<TokenTree>,
35 }
36 
37 #[derive(Debug)]
38 pub(crate) struct LexError;
39 
40 impl TokenStream {
new() -> TokenStream41     pub fn new() -> TokenStream {
42         TokenStream { inner: Vec::new() }
43     }
44 
is_empty(&self) -> bool45     pub fn is_empty(&self) -> bool {
46         self.inner.len() == 0
47     }
48 
take_inner(&mut self) -> Vec<TokenTree>49     fn take_inner(&mut self) -> Vec<TokenTree> {
50         mem::replace(&mut self.inner, Vec::new())
51     }
52 
push_token(&mut self, token: TokenTree)53     fn push_token(&mut self, token: TokenTree) {
54         // https://github.com/alexcrichton/proc-macro2/issues/235
55         match token {
56             #[cfg(not(no_bind_by_move_pattern_guard))]
57             TokenTree::Literal(crate::Literal {
58                 #[cfg(wrap_proc_macro)]
59                     inner: crate::imp::Literal::Fallback(literal),
60                 #[cfg(not(wrap_proc_macro))]
61                     inner: literal,
62                 ..
63             }) if literal.text.starts_with('-') => {
64                 push_negative_literal(self, literal);
65             }
66             #[cfg(no_bind_by_move_pattern_guard)]
67             TokenTree::Literal(crate::Literal {
68                 #[cfg(wrap_proc_macro)]
69                     inner: crate::imp::Literal::Fallback(literal),
70                 #[cfg(not(wrap_proc_macro))]
71                     inner: literal,
72                 ..
73             }) => {
74                 if literal.text.starts_with('-') {
75                     push_negative_literal(self, literal);
76                 } else {
77                     self.inner
78                         .push(TokenTree::Literal(crate::Literal::_new_stable(literal)));
79                 }
80             }
81             _ => self.inner.push(token),
82         }
83 
84         #[cold]
85         fn push_negative_literal(stream: &mut TokenStream, mut literal: Literal) {
86             literal.text.remove(0);
87             let mut punct = crate::Punct::new('-', Spacing::Alone);
88             punct.set_span(crate::Span::_new_stable(literal.span));
89             stream.inner.push(TokenTree::Punct(punct));
90             stream
91                 .inner
92                 .push(TokenTree::Literal(crate::Literal::_new_stable(literal)));
93         }
94     }
95 }
96 
97 // Nonrecursive to prevent stack overflow.
98 impl Drop for TokenStream {
drop(&mut self)99     fn drop(&mut self) {
100         while let Some(token) = self.inner.pop() {
101             let group = match token {
102                 TokenTree::Group(group) => group.inner,
103                 _ => continue,
104             };
105             #[cfg(wrap_proc_macro)]
106             let group = match group {
107                 crate::imp::Group::Fallback(group) => group,
108                 _ => continue,
109             };
110             let mut group = group;
111             self.inner.extend(group.stream.take_inner());
112         }
113     }
114 }
115 
116 #[cfg(span_locations)]
get_cursor(src: &str) -> Cursor117 fn get_cursor(src: &str) -> Cursor {
118     // Create a dummy file & add it to the source map
119     SOURCE_MAP.with(|cm| {
120         let mut cm = cm.borrow_mut();
121         let name = format!("<parsed string {}>", cm.files.len());
122         let span = cm.add_file(&name, src);
123         Cursor {
124             rest: src,
125             off: span.lo,
126         }
127     })
128 }
129 
130 #[cfg(not(span_locations))]
get_cursor(src: &str) -> Cursor131 fn get_cursor(src: &str) -> Cursor {
132     Cursor { rest: src }
133 }
134 
135 impl FromStr for TokenStream {
136     type Err = LexError;
137 
from_str(src: &str) -> Result<TokenStream, LexError>138     fn from_str(src: &str) -> Result<TokenStream, LexError> {
139         // Create a dummy file & add it to the source map
140         let cursor = get_cursor(src);
141 
142         let (rest, tokens) = token_stream(cursor)?;
143         if rest.is_empty() {
144             Ok(tokens)
145         } else {
146             Err(LexError)
147         }
148     }
149 }
150 
151 impl Display for LexError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result152     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
153         f.write_str("cannot parse string into token stream")
154     }
155 }
156 
157 impl Display for TokenStream {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result158     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
159         let mut joint = false;
160         for (i, tt) in self.inner.iter().enumerate() {
161             if i != 0 && !joint {
162                 write!(f, " ")?;
163             }
164             joint = false;
165             match tt {
166                 TokenTree::Group(tt) => Display::fmt(tt, f),
167                 TokenTree::Ident(tt) => Display::fmt(tt, f),
168                 TokenTree::Punct(tt) => {
169                     joint = tt.spacing() == Spacing::Joint;
170                     Display::fmt(tt, f)
171                 }
172                 TokenTree::Literal(tt) => Display::fmt(tt, f),
173             }?
174         }
175 
176         Ok(())
177     }
178 }
179 
180 impl Debug for TokenStream {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result181     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
182         f.write_str("TokenStream ")?;
183         f.debug_list().entries(self.clone()).finish()
184     }
185 }
186 
187 #[cfg(use_proc_macro)]
188 impl From<proc_macro::TokenStream> for TokenStream {
from(inner: proc_macro::TokenStream) -> TokenStream189     fn from(inner: proc_macro::TokenStream) -> TokenStream {
190         inner
191             .to_string()
192             .parse()
193             .expect("compiler token stream parse failed")
194     }
195 }
196 
197 #[cfg(use_proc_macro)]
198 impl From<TokenStream> for proc_macro::TokenStream {
from(inner: TokenStream) -> proc_macro::TokenStream199     fn from(inner: TokenStream) -> proc_macro::TokenStream {
200         inner
201             .to_string()
202             .parse()
203             .expect("failed to parse to compiler tokens")
204     }
205 }
206 
207 impl From<TokenTree> for TokenStream {
from(tree: TokenTree) -> TokenStream208     fn from(tree: TokenTree) -> TokenStream {
209         let mut stream = TokenStream::new();
210         stream.push_token(tree);
211         stream
212     }
213 }
214 
215 impl FromIterator<TokenTree> for TokenStream {
from_iter<I: IntoIterator<Item = TokenTree>>(tokens: I) -> Self216     fn from_iter<I: IntoIterator<Item = TokenTree>>(tokens: I) -> Self {
217         let mut stream = TokenStream::new();
218         stream.extend(tokens);
219         stream
220     }
221 }
222 
223 impl FromIterator<TokenStream> for TokenStream {
from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self224     fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
225         let mut v = Vec::new();
226 
227         for mut stream in streams {
228             v.extend(stream.take_inner());
229         }
230 
231         TokenStream { inner: v }
232     }
233 }
234 
235 impl Extend<TokenTree> for TokenStream {
extend<I: IntoIterator<Item = TokenTree>>(&mut self, tokens: I)236     fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, tokens: I) {
237         tokens.into_iter().for_each(|token| self.push_token(token));
238     }
239 }
240 
241 impl Extend<TokenStream> for TokenStream {
extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I)242     fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
243         self.inner.extend(streams.into_iter().flatten());
244     }
245 }
246 
247 pub(crate) type TokenTreeIter = vec::IntoIter<TokenTree>;
248 
249 impl IntoIterator for TokenStream {
250     type Item = TokenTree;
251     type IntoIter = TokenTreeIter;
252 
into_iter(mut self) -> TokenTreeIter253     fn into_iter(mut self) -> TokenTreeIter {
254         self.take_inner().into_iter()
255     }
256 }
257 
258 #[derive(Clone, PartialEq, Eq)]
259 pub(crate) struct SourceFile {
260     path: PathBuf,
261 }
262 
263 impl SourceFile {
264     /// Get the path to this source file as a string.
path(&self) -> PathBuf265     pub fn path(&self) -> PathBuf {
266         self.path.clone()
267     }
268 
is_real(&self) -> bool269     pub fn is_real(&self) -> bool {
270         // XXX(nika): Support real files in the future?
271         false
272     }
273 }
274 
275 impl Debug for SourceFile {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result276     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
277         f.debug_struct("SourceFile")
278             .field("path", &self.path())
279             .field("is_real", &self.is_real())
280             .finish()
281     }
282 }
283 
284 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
285 pub(crate) struct LineColumn {
286     pub line: usize,
287     pub column: usize,
288 }
289 
290 #[cfg(span_locations)]
291 thread_local! {
292     static SOURCE_MAP: RefCell<SourceMap> = RefCell::new(SourceMap {
293         // NOTE: We start with a single dummy file which all call_site() and
294         // def_site() spans reference.
295         files: vec![FileInfo {
296             #[cfg(procmacro2_semver_exempt)]
297             name: "<unspecified>".to_owned(),
298             span: Span { lo: 0, hi: 0 },
299             lines: vec![0],
300         }],
301     });
302 }
303 
304 #[cfg(span_locations)]
305 struct FileInfo {
306     #[cfg(procmacro2_semver_exempt)]
307     name: String,
308     span: Span,
309     lines: Vec<usize>,
310 }
311 
312 #[cfg(span_locations)]
313 impl FileInfo {
offset_line_column(&self, offset: usize) -> LineColumn314     fn offset_line_column(&self, offset: usize) -> LineColumn {
315         assert!(self.span_within(Span {
316             lo: offset as u32,
317             hi: offset as u32
318         }));
319         let offset = offset - self.span.lo as usize;
320         match self.lines.binary_search(&offset) {
321             Ok(found) => LineColumn {
322                 line: found + 1,
323                 column: 0,
324             },
325             Err(idx) => LineColumn {
326                 line: idx,
327                 column: offset - self.lines[idx - 1],
328             },
329         }
330     }
331 
span_within(&self, span: Span) -> bool332     fn span_within(&self, span: Span) -> bool {
333         span.lo >= self.span.lo && span.hi <= self.span.hi
334     }
335 }
336 
337 /// Computes the offsets of each line in the given source string
338 /// and the total number of characters
339 #[cfg(span_locations)]
lines_offsets(s: &str) -> (usize, Vec<usize>)340 fn lines_offsets(s: &str) -> (usize, Vec<usize>) {
341     let mut lines = vec![0];
342     let mut total = 0;
343 
344     for ch in s.chars() {
345         total += 1;
346         if ch == '\n' {
347             lines.push(total);
348         }
349     }
350 
351     (total, lines)
352 }
353 
354 #[cfg(span_locations)]
355 struct SourceMap {
356     files: Vec<FileInfo>,
357 }
358 
359 #[cfg(span_locations)]
360 impl SourceMap {
next_start_pos(&self) -> u32361     fn next_start_pos(&self) -> u32 {
362         // Add 1 so there's always space between files.
363         //
364         // We'll always have at least 1 file, as we initialize our files list
365         // with a dummy file.
366         self.files.last().unwrap().span.hi + 1
367     }
368 
add_file(&mut self, name: &str, src: &str) -> Span369     fn add_file(&mut self, name: &str, src: &str) -> Span {
370         let (len, lines) = lines_offsets(src);
371         let lo = self.next_start_pos();
372         // XXX(nika): Shouild we bother doing a checked cast or checked add here?
373         let span = Span {
374             lo,
375             hi: lo + (len as u32),
376         };
377 
378         self.files.push(FileInfo {
379             #[cfg(procmacro2_semver_exempt)]
380             name: name.to_owned(),
381             span,
382             lines,
383         });
384 
385         #[cfg(not(procmacro2_semver_exempt))]
386         let _ = name;
387 
388         span
389     }
390 
fileinfo(&self, span: Span) -> &FileInfo391     fn fileinfo(&self, span: Span) -> &FileInfo {
392         for file in &self.files {
393             if file.span_within(span) {
394                 return file;
395             }
396         }
397         panic!("Invalid span with no related FileInfo!");
398     }
399 }
400 
401 #[derive(Clone, Copy, PartialEq, Eq)]
402 pub(crate) struct Span {
403     #[cfg(span_locations)]
404     pub(crate) lo: u32,
405     #[cfg(span_locations)]
406     pub(crate) hi: u32,
407 }
408 
409 impl Span {
410     #[cfg(not(span_locations))]
call_site() -> Span411     pub fn call_site() -> Span {
412         Span {}
413     }
414 
415     #[cfg(span_locations)]
call_site() -> Span416     pub fn call_site() -> Span {
417         Span { lo: 0, hi: 0 }
418     }
419 
420     #[cfg(hygiene)]
mixed_site() -> Span421     pub fn mixed_site() -> Span {
422         Span::call_site()
423     }
424 
425     #[cfg(procmacro2_semver_exempt)]
def_site() -> Span426     pub fn def_site() -> Span {
427         Span::call_site()
428     }
429 
resolved_at(&self, _other: Span) -> Span430     pub fn resolved_at(&self, _other: Span) -> Span {
431         // Stable spans consist only of line/column information, so
432         // `resolved_at` and `located_at` only select which span the
433         // caller wants line/column information from.
434         *self
435     }
436 
located_at(&self, other: Span) -> Span437     pub fn located_at(&self, other: Span) -> Span {
438         other
439     }
440 
441     #[cfg(procmacro2_semver_exempt)]
source_file(&self) -> SourceFile442     pub fn source_file(&self) -> SourceFile {
443         SOURCE_MAP.with(|cm| {
444             let cm = cm.borrow();
445             let fi = cm.fileinfo(*self);
446             SourceFile {
447                 path: Path::new(&fi.name).to_owned(),
448             }
449         })
450     }
451 
452     #[cfg(span_locations)]
start(&self) -> LineColumn453     pub fn start(&self) -> LineColumn {
454         SOURCE_MAP.with(|cm| {
455             let cm = cm.borrow();
456             let fi = cm.fileinfo(*self);
457             fi.offset_line_column(self.lo as usize)
458         })
459     }
460 
461     #[cfg(span_locations)]
end(&self) -> LineColumn462     pub fn end(&self) -> LineColumn {
463         SOURCE_MAP.with(|cm| {
464             let cm = cm.borrow();
465             let fi = cm.fileinfo(*self);
466             fi.offset_line_column(self.hi as usize)
467         })
468     }
469 
470     #[cfg(not(span_locations))]
join(&self, _other: Span) -> Option<Span>471     pub fn join(&self, _other: Span) -> Option<Span> {
472         Some(Span {})
473     }
474 
475     #[cfg(span_locations)]
join(&self, other: Span) -> Option<Span>476     pub fn join(&self, other: Span) -> Option<Span> {
477         SOURCE_MAP.with(|cm| {
478             let cm = cm.borrow();
479             // If `other` is not within the same FileInfo as us, return None.
480             if !cm.fileinfo(*self).span_within(other) {
481                 return None;
482             }
483             Some(Span {
484                 lo: cmp::min(self.lo, other.lo),
485                 hi: cmp::max(self.hi, other.hi),
486             })
487         })
488     }
489 
490     #[cfg(not(span_locations))]
first_byte(self) -> Self491     fn first_byte(self) -> Self {
492         self
493     }
494 
495     #[cfg(span_locations)]
first_byte(self) -> Self496     fn first_byte(self) -> Self {
497         Span {
498             lo: self.lo,
499             hi: cmp::min(self.lo.saturating_add(1), self.hi),
500         }
501     }
502 
503     #[cfg(not(span_locations))]
last_byte(self) -> Self504     fn last_byte(self) -> Self {
505         self
506     }
507 
508     #[cfg(span_locations)]
last_byte(self) -> Self509     fn last_byte(self) -> Self {
510         Span {
511             lo: cmp::max(self.hi.saturating_sub(1), self.lo),
512             hi: self.hi,
513         }
514     }
515 }
516 
517 impl Debug for Span {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result518     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
519         #[cfg(span_locations)]
520         return write!(f, "bytes({}..{})", self.lo, self.hi);
521 
522         #[cfg(not(span_locations))]
523         write!(f, "Span")
524     }
525 }
526 
debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span)527 pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) {
528     #[cfg(span_locations)]
529     {
530         if span.lo == 0 && span.hi == 0 {
531             return;
532         }
533     }
534 
535     if cfg!(span_locations) {
536         debug.field("span", &span);
537     }
538 }
539 
540 #[derive(Clone)]
541 pub(crate) struct Group {
542     delimiter: Delimiter,
543     stream: TokenStream,
544     span: Span,
545 }
546 
547 impl Group {
new(delimiter: Delimiter, stream: TokenStream) -> Group548     pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group {
549         Group {
550             delimiter,
551             stream,
552             span: Span::call_site(),
553         }
554     }
555 
delimiter(&self) -> Delimiter556     pub fn delimiter(&self) -> Delimiter {
557         self.delimiter
558     }
559 
stream(&self) -> TokenStream560     pub fn stream(&self) -> TokenStream {
561         self.stream.clone()
562     }
563 
span(&self) -> Span564     pub fn span(&self) -> Span {
565         self.span
566     }
567 
span_open(&self) -> Span568     pub fn span_open(&self) -> Span {
569         self.span.first_byte()
570     }
571 
span_close(&self) -> Span572     pub fn span_close(&self) -> Span {
573         self.span.last_byte()
574     }
575 
set_span(&mut self, span: Span)576     pub fn set_span(&mut self, span: Span) {
577         self.span = span;
578     }
579 }
580 
581 impl Display for Group {
582     // We attempt to match libproc_macro's formatting.
583     // Empty parens: ()
584     // Nonempty parens: (...)
585     // Empty brackets: []
586     // Nonempty brackets: [...]
587     // Empty braces: { }
588     // Nonempty braces: { ... }
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result589     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
590         let (open, close) = match self.delimiter {
591             Delimiter::Parenthesis => ("(", ")"),
592             Delimiter::Brace => ("{ ", "}"),
593             Delimiter::Bracket => ("[", "]"),
594             Delimiter::None => ("", ""),
595         };
596 
597         f.write_str(open)?;
598         Display::fmt(&self.stream, f)?;
599         if self.delimiter == Delimiter::Brace && !self.stream.inner.is_empty() {
600             f.write_str(" ")?;
601         }
602         f.write_str(close)?;
603 
604         Ok(())
605     }
606 }
607 
608 impl Debug for Group {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result609     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
610         let mut debug = fmt.debug_struct("Group");
611         debug.field("delimiter", &self.delimiter);
612         debug.field("stream", &self.stream);
613         debug_span_field_if_nontrivial(&mut debug, self.span);
614         debug.finish()
615     }
616 }
617 
618 #[derive(Clone)]
619 pub(crate) struct Ident {
620     sym: String,
621     span: Span,
622     raw: bool,
623 }
624 
625 impl Ident {
_new(string: &str, raw: bool, span: Span) -> Ident626     fn _new(string: &str, raw: bool, span: Span) -> Ident {
627         validate_ident(string);
628 
629         Ident {
630             sym: string.to_owned(),
631             span,
632             raw,
633         }
634     }
635 
new(string: &str, span: Span) -> Ident636     pub fn new(string: &str, span: Span) -> Ident {
637         Ident::_new(string, false, span)
638     }
639 
new_raw(string: &str, span: Span) -> Ident640     pub fn new_raw(string: &str, span: Span) -> Ident {
641         Ident::_new(string, true, span)
642     }
643 
span(&self) -> Span644     pub fn span(&self) -> Span {
645         self.span
646     }
647 
set_span(&mut self, span: Span)648     pub fn set_span(&mut self, span: Span) {
649         self.span = span;
650     }
651 }
652 
is_ident_start(c: char) -> bool653 pub(crate) fn is_ident_start(c: char) -> bool {
654     ('a' <= c && c <= 'z')
655         || ('A' <= c && c <= 'Z')
656         || c == '_'
657         || (c > '\x7f' && UnicodeXID::is_xid_start(c))
658 }
659 
is_ident_continue(c: char) -> bool660 pub(crate) fn is_ident_continue(c: char) -> bool {
661     ('a' <= c && c <= 'z')
662         || ('A' <= c && c <= 'Z')
663         || c == '_'
664         || ('0' <= c && c <= '9')
665         || (c > '\x7f' && UnicodeXID::is_xid_continue(c))
666 }
667 
validate_ident(string: &str)668 fn validate_ident(string: &str) {
669     let validate = string;
670     if validate.is_empty() {
671         panic!("Ident is not allowed to be empty; use Option<Ident>");
672     }
673 
674     if validate.bytes().all(|digit| digit >= b'0' && digit <= b'9') {
675         panic!("Ident cannot be a number; use Literal instead");
676     }
677 
678     fn ident_ok(string: &str) -> bool {
679         let mut chars = string.chars();
680         let first = chars.next().unwrap();
681         if !is_ident_start(first) {
682             return false;
683         }
684         for ch in chars {
685             if !is_ident_continue(ch) {
686                 return false;
687             }
688         }
689         true
690     }
691 
692     if !ident_ok(validate) {
693         panic!("{:?} is not a valid Ident", string);
694     }
695 }
696 
697 impl PartialEq for Ident {
eq(&self, other: &Ident) -> bool698     fn eq(&self, other: &Ident) -> bool {
699         self.sym == other.sym && self.raw == other.raw
700     }
701 }
702 
703 impl<T> PartialEq<T> for Ident
704 where
705     T: ?Sized + AsRef<str>,
706 {
eq(&self, other: &T) -> bool707     fn eq(&self, other: &T) -> bool {
708         let other = other.as_ref();
709         if self.raw {
710             other.starts_with("r#") && self.sym == other[2..]
711         } else {
712             self.sym == other
713         }
714     }
715 }
716 
717 impl Display for Ident {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result718     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
719         if self.raw {
720             f.write_str("r#")?;
721         }
722         Display::fmt(&self.sym, f)
723     }
724 }
725 
726 impl Debug for Ident {
727     // Ident(proc_macro), Ident(r#union)
728     #[cfg(not(span_locations))]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result729     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
730         let mut debug = f.debug_tuple("Ident");
731         debug.field(&format_args!("{}", self));
732         debug.finish()
733     }
734 
735     // Ident {
736     //     sym: proc_macro,
737     //     span: bytes(128..138)
738     // }
739     #[cfg(span_locations)]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result740     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
741         let mut debug = f.debug_struct("Ident");
742         debug.field("sym", &format_args!("{}", self));
743         debug_span_field_if_nontrivial(&mut debug, self.span);
744         debug.finish()
745     }
746 }
747 
748 #[derive(Clone)]
749 pub(crate) struct Literal {
750     text: String,
751     span: Span,
752 }
753 
754 macro_rules! suffixed_numbers {
755     ($($name:ident => $kind:ident,)*) => ($(
756         pub fn $name(n: $kind) -> Literal {
757             Literal::_new(format!(concat!("{}", stringify!($kind)), n))
758         }
759     )*)
760 }
761 
762 macro_rules! unsuffixed_numbers {
763     ($($name:ident => $kind:ident,)*) => ($(
764         pub fn $name(n: $kind) -> Literal {
765             Literal::_new(n.to_string())
766         }
767     )*)
768 }
769 
770 impl Literal {
_new(text: String) -> Literal771     pub(crate) fn _new(text: String) -> Literal {
772         Literal {
773             text,
774             span: Span::call_site(),
775         }
776     }
777 
778     suffixed_numbers! {
779         u8_suffixed => u8,
780         u16_suffixed => u16,
781         u32_suffixed => u32,
782         u64_suffixed => u64,
783         u128_suffixed => u128,
784         usize_suffixed => usize,
785         i8_suffixed => i8,
786         i16_suffixed => i16,
787         i32_suffixed => i32,
788         i64_suffixed => i64,
789         i128_suffixed => i128,
790         isize_suffixed => isize,
791 
792         f32_suffixed => f32,
793         f64_suffixed => f64,
794     }
795 
796     unsuffixed_numbers! {
797         u8_unsuffixed => u8,
798         u16_unsuffixed => u16,
799         u32_unsuffixed => u32,
800         u64_unsuffixed => u64,
801         u128_unsuffixed => u128,
802         usize_unsuffixed => usize,
803         i8_unsuffixed => i8,
804         i16_unsuffixed => i16,
805         i32_unsuffixed => i32,
806         i64_unsuffixed => i64,
807         i128_unsuffixed => i128,
808         isize_unsuffixed => isize,
809     }
810 
f32_unsuffixed(f: f32) -> Literal811     pub fn f32_unsuffixed(f: f32) -> Literal {
812         let mut s = f.to_string();
813         if !s.contains('.') {
814             s.push_str(".0");
815         }
816         Literal::_new(s)
817     }
818 
f64_unsuffixed(f: f64) -> Literal819     pub fn f64_unsuffixed(f: f64) -> Literal {
820         let mut s = f.to_string();
821         if !s.contains('.') {
822             s.push_str(".0");
823         }
824         Literal::_new(s)
825     }
826 
string(t: &str) -> Literal827     pub fn string(t: &str) -> Literal {
828         let mut text = String::with_capacity(t.len() + 2);
829         text.push('"');
830         for c in t.chars() {
831             if c == '\'' {
832                 // escape_debug turns this into "\'" which is unnecessary.
833                 text.push(c);
834             } else {
835                 text.extend(c.escape_debug());
836             }
837         }
838         text.push('"');
839         Literal::_new(text)
840     }
841 
character(t: char) -> Literal842     pub fn character(t: char) -> Literal {
843         let mut text = String::new();
844         text.push('\'');
845         if t == '"' {
846             // escape_debug turns this into '\"' which is unnecessary.
847             text.push(t);
848         } else {
849             text.extend(t.escape_debug());
850         }
851         text.push('\'');
852         Literal::_new(text)
853     }
854 
byte_string(bytes: &[u8]) -> Literal855     pub fn byte_string(bytes: &[u8]) -> Literal {
856         let mut escaped = "b\"".to_string();
857         for b in bytes {
858             #[allow(clippy::match_overlapping_arm)]
859             match *b {
860                 b'\0' => escaped.push_str(r"\0"),
861                 b'\t' => escaped.push_str(r"\t"),
862                 b'\n' => escaped.push_str(r"\n"),
863                 b'\r' => escaped.push_str(r"\r"),
864                 b'"' => escaped.push_str("\\\""),
865                 b'\\' => escaped.push_str("\\\\"),
866                 b'\x20'..=b'\x7E' => escaped.push(*b as char),
867                 _ => escaped.push_str(&format!("\\x{:02X}", b)),
868             }
869         }
870         escaped.push('"');
871         Literal::_new(escaped)
872     }
873 
span(&self) -> Span874     pub fn span(&self) -> Span {
875         self.span
876     }
877 
set_span(&mut self, span: Span)878     pub fn set_span(&mut self, span: Span) {
879         self.span = span;
880     }
881 
subspan<R: RangeBounds<usize>>(&self, _range: R) -> Option<Span>882     pub fn subspan<R: RangeBounds<usize>>(&self, _range: R) -> Option<Span> {
883         None
884     }
885 }
886 
887 impl Display for Literal {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result888     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
889         Display::fmt(&self.text, f)
890     }
891 }
892 
893 impl Debug for Literal {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result894     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
895         let mut debug = fmt.debug_struct("Literal");
896         debug.field("lit", &format_args!("{}", self.text));
897         debug_span_field_if_nontrivial(&mut debug, self.span);
898         debug.finish()
899     }
900 }
901