1 use crate::parse::{self, 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     pub(crate) span: Span,
40 }
41 
42 impl LexError {
span(&self) -> Span43     pub(crate) fn span(&self) -> Span {
44         self.span
45     }
46 }
47 
48 impl TokenStream {
new() -> TokenStream49     pub fn new() -> TokenStream {
50         TokenStream { inner: Vec::new() }
51     }
52 
is_empty(&self) -> bool53     pub fn is_empty(&self) -> bool {
54         self.inner.len() == 0
55     }
56 
take_inner(&mut self) -> Vec<TokenTree>57     fn take_inner(&mut self) -> Vec<TokenTree> {
58         mem::replace(&mut self.inner, Vec::new())
59     }
60 
push_token(&mut self, token: TokenTree)61     fn push_token(&mut self, token: TokenTree) {
62         // https://github.com/alexcrichton/proc-macro2/issues/235
63         match token {
64             #[cfg(not(no_bind_by_move_pattern_guard))]
65             TokenTree::Literal(crate::Literal {
66                 #[cfg(wrap_proc_macro)]
67                     inner: crate::imp::Literal::Fallback(literal),
68                 #[cfg(not(wrap_proc_macro))]
69                     inner: literal,
70                 ..
71             }) if literal.text.starts_with('-') => {
72                 push_negative_literal(self, literal);
73             }
74             #[cfg(no_bind_by_move_pattern_guard)]
75             TokenTree::Literal(crate::Literal {
76                 #[cfg(wrap_proc_macro)]
77                     inner: crate::imp::Literal::Fallback(literal),
78                 #[cfg(not(wrap_proc_macro))]
79                     inner: literal,
80                 ..
81             }) => {
82                 if literal.text.starts_with('-') {
83                     push_negative_literal(self, literal);
84                 } else {
85                     self.inner
86                         .push(TokenTree::Literal(crate::Literal::_new_stable(literal)));
87                 }
88             }
89             _ => self.inner.push(token),
90         }
91 
92         #[cold]
93         fn push_negative_literal(stream: &mut TokenStream, mut literal: Literal) {
94             literal.text.remove(0);
95             let mut punct = crate::Punct::new('-', Spacing::Alone);
96             punct.set_span(crate::Span::_new_stable(literal.span));
97             stream.inner.push(TokenTree::Punct(punct));
98             stream
99                 .inner
100                 .push(TokenTree::Literal(crate::Literal::_new_stable(literal)));
101         }
102     }
103 }
104 
105 // Nonrecursive to prevent stack overflow.
106 impl Drop for TokenStream {
drop(&mut self)107     fn drop(&mut self) {
108         while let Some(token) = self.inner.pop() {
109             let group = match token {
110                 TokenTree::Group(group) => group.inner,
111                 _ => continue,
112             };
113             #[cfg(wrap_proc_macro)]
114             let group = match group {
115                 crate::imp::Group::Fallback(group) => group,
116                 _ => continue,
117             };
118             let mut group = group;
119             self.inner.extend(group.stream.take_inner());
120         }
121     }
122 }
123 
124 #[cfg(span_locations)]
get_cursor(src: &str) -> Cursor125 fn get_cursor(src: &str) -> Cursor {
126     // Create a dummy file & add it to the source map
127     SOURCE_MAP.with(|cm| {
128         let mut cm = cm.borrow_mut();
129         let name = format!("<parsed string {}>", cm.files.len());
130         let span = cm.add_file(&name, src);
131         Cursor {
132             rest: src,
133             off: span.lo,
134         }
135     })
136 }
137 
138 #[cfg(not(span_locations))]
get_cursor(src: &str) -> Cursor139 fn get_cursor(src: &str) -> Cursor {
140     Cursor { rest: src }
141 }
142 
143 impl FromStr for TokenStream {
144     type Err = LexError;
145 
from_str(src: &str) -> Result<TokenStream, LexError>146     fn from_str(src: &str) -> Result<TokenStream, LexError> {
147         // Create a dummy file & add it to the source map
148         let cursor = get_cursor(src);
149 
150         parse::token_stream(cursor)
151     }
152 }
153 
154 impl Display for LexError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result155     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
156         f.write_str("cannot parse string into token stream")
157     }
158 }
159 
160 impl Display for TokenStream {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result161     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
162         let mut joint = false;
163         for (i, tt) in self.inner.iter().enumerate() {
164             if i != 0 && !joint {
165                 write!(f, " ")?;
166             }
167             joint = false;
168             match tt {
169                 TokenTree::Group(tt) => Display::fmt(tt, f),
170                 TokenTree::Ident(tt) => Display::fmt(tt, f),
171                 TokenTree::Punct(tt) => {
172                     joint = tt.spacing() == Spacing::Joint;
173                     Display::fmt(tt, f)
174                 }
175                 TokenTree::Literal(tt) => Display::fmt(tt, f),
176             }?
177         }
178 
179         Ok(())
180     }
181 }
182 
183 impl Debug for TokenStream {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result184     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
185         f.write_str("TokenStream ")?;
186         f.debug_list().entries(self.clone()).finish()
187     }
188 }
189 
190 #[cfg(use_proc_macro)]
191 impl From<proc_macro::TokenStream> for TokenStream {
from(inner: proc_macro::TokenStream) -> TokenStream192     fn from(inner: proc_macro::TokenStream) -> TokenStream {
193         inner
194             .to_string()
195             .parse()
196             .expect("compiler token stream parse failed")
197     }
198 }
199 
200 #[cfg(use_proc_macro)]
201 impl From<TokenStream> for proc_macro::TokenStream {
from(inner: TokenStream) -> proc_macro::TokenStream202     fn from(inner: TokenStream) -> proc_macro::TokenStream {
203         inner
204             .to_string()
205             .parse()
206             .expect("failed to parse to compiler tokens")
207     }
208 }
209 
210 impl From<TokenTree> for TokenStream {
from(tree: TokenTree) -> TokenStream211     fn from(tree: TokenTree) -> TokenStream {
212         let mut stream = TokenStream::new();
213         stream.push_token(tree);
214         stream
215     }
216 }
217 
218 impl FromIterator<TokenTree> for TokenStream {
from_iter<I: IntoIterator<Item = TokenTree>>(tokens: I) -> Self219     fn from_iter<I: IntoIterator<Item = TokenTree>>(tokens: I) -> Self {
220         let mut stream = TokenStream::new();
221         stream.extend(tokens);
222         stream
223     }
224 }
225 
226 impl FromIterator<TokenStream> for TokenStream {
from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self227     fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
228         let mut v = Vec::new();
229 
230         for mut stream in streams {
231             v.extend(stream.take_inner());
232         }
233 
234         TokenStream { inner: v }
235     }
236 }
237 
238 impl Extend<TokenTree> for TokenStream {
extend<I: IntoIterator<Item = TokenTree>>(&mut self, tokens: I)239     fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, tokens: I) {
240         tokens.into_iter().for_each(|token| self.push_token(token));
241     }
242 }
243 
244 impl Extend<TokenStream> for TokenStream {
extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I)245     fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
246         self.inner.extend(streams.into_iter().flatten());
247     }
248 }
249 
250 pub(crate) type TokenTreeIter = vec::IntoIter<TokenTree>;
251 
252 impl IntoIterator for TokenStream {
253     type Item = TokenTree;
254     type IntoIter = TokenTreeIter;
255 
into_iter(mut self) -> TokenTreeIter256     fn into_iter(mut self) -> TokenTreeIter {
257         self.take_inner().into_iter()
258     }
259 }
260 
261 #[derive(Clone, PartialEq, Eq)]
262 pub(crate) struct SourceFile {
263     path: PathBuf,
264 }
265 
266 impl SourceFile {
267     /// Get the path to this source file as a string.
path(&self) -> PathBuf268     pub fn path(&self) -> PathBuf {
269         self.path.clone()
270     }
271 
is_real(&self) -> bool272     pub fn is_real(&self) -> bool {
273         // XXX(nika): Support real files in the future?
274         false
275     }
276 }
277 
278 impl Debug for SourceFile {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result279     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
280         f.debug_struct("SourceFile")
281             .field("path", &self.path())
282             .field("is_real", &self.is_real())
283             .finish()
284     }
285 }
286 
287 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
288 pub(crate) struct LineColumn {
289     pub line: usize,
290     pub column: usize,
291 }
292 
293 #[cfg(span_locations)]
294 thread_local! {
295     static SOURCE_MAP: RefCell<SourceMap> = RefCell::new(SourceMap {
296         // NOTE: We start with a single dummy file which all call_site() and
297         // def_site() spans reference.
298         files: vec![FileInfo {
299             #[cfg(procmacro2_semver_exempt)]
300             name: "<unspecified>".to_owned(),
301             span: Span { lo: 0, hi: 0 },
302             lines: vec![0],
303         }],
304     });
305 }
306 
307 #[cfg(span_locations)]
308 struct FileInfo {
309     #[cfg(procmacro2_semver_exempt)]
310     name: String,
311     span: Span,
312     lines: Vec<usize>,
313 }
314 
315 #[cfg(span_locations)]
316 impl FileInfo {
offset_line_column(&self, offset: usize) -> LineColumn317     fn offset_line_column(&self, offset: usize) -> LineColumn {
318         assert!(self.span_within(Span {
319             lo: offset as u32,
320             hi: offset as u32
321         }));
322         let offset = offset - self.span.lo as usize;
323         match self.lines.binary_search(&offset) {
324             Ok(found) => LineColumn {
325                 line: found + 1,
326                 column: 0,
327             },
328             Err(idx) => LineColumn {
329                 line: idx,
330                 column: offset - self.lines[idx - 1],
331             },
332         }
333     }
334 
span_within(&self, span: Span) -> bool335     fn span_within(&self, span: Span) -> bool {
336         span.lo >= self.span.lo && span.hi <= self.span.hi
337     }
338 }
339 
340 /// Computes the offsets of each line in the given source string
341 /// and the total number of characters
342 #[cfg(span_locations)]
lines_offsets(s: &str) -> (usize, Vec<usize>)343 fn lines_offsets(s: &str) -> (usize, Vec<usize>) {
344     let mut lines = vec![0];
345     let mut total = 0;
346 
347     for ch in s.chars() {
348         total += 1;
349         if ch == '\n' {
350             lines.push(total);
351         }
352     }
353 
354     (total, lines)
355 }
356 
357 #[cfg(span_locations)]
358 struct SourceMap {
359     files: Vec<FileInfo>,
360 }
361 
362 #[cfg(span_locations)]
363 impl SourceMap {
next_start_pos(&self) -> u32364     fn next_start_pos(&self) -> u32 {
365         // Add 1 so there's always space between files.
366         //
367         // We'll always have at least 1 file, as we initialize our files list
368         // with a dummy file.
369         self.files.last().unwrap().span.hi + 1
370     }
371 
add_file(&mut self, name: &str, src: &str) -> Span372     fn add_file(&mut self, name: &str, src: &str) -> Span {
373         let (len, lines) = lines_offsets(src);
374         let lo = self.next_start_pos();
375         // XXX(nika): Shouild we bother doing a checked cast or checked add here?
376         let span = Span {
377             lo,
378             hi: lo + (len as u32),
379         };
380 
381         self.files.push(FileInfo {
382             #[cfg(procmacro2_semver_exempt)]
383             name: name.to_owned(),
384             span,
385             lines,
386         });
387 
388         #[cfg(not(procmacro2_semver_exempt))]
389         let _ = name;
390 
391         span
392     }
393 
fileinfo(&self, span: Span) -> &FileInfo394     fn fileinfo(&self, span: Span) -> &FileInfo {
395         for file in &self.files {
396             if file.span_within(span) {
397                 return file;
398             }
399         }
400         panic!("Invalid span with no related FileInfo!");
401     }
402 }
403 
404 #[derive(Clone, Copy, PartialEq, Eq)]
405 pub(crate) struct Span {
406     #[cfg(span_locations)]
407     pub(crate) lo: u32,
408     #[cfg(span_locations)]
409     pub(crate) hi: u32,
410 }
411 
412 impl Span {
413     #[cfg(not(span_locations))]
call_site() -> Span414     pub fn call_site() -> Span {
415         Span {}
416     }
417 
418     #[cfg(span_locations)]
call_site() -> Span419     pub fn call_site() -> Span {
420         Span { lo: 0, hi: 0 }
421     }
422 
423     #[cfg(hygiene)]
mixed_site() -> Span424     pub fn mixed_site() -> Span {
425         Span::call_site()
426     }
427 
428     #[cfg(procmacro2_semver_exempt)]
def_site() -> Span429     pub fn def_site() -> Span {
430         Span::call_site()
431     }
432 
resolved_at(&self, _other: Span) -> Span433     pub fn resolved_at(&self, _other: Span) -> Span {
434         // Stable spans consist only of line/column information, so
435         // `resolved_at` and `located_at` only select which span the
436         // caller wants line/column information from.
437         *self
438     }
439 
located_at(&self, other: Span) -> Span440     pub fn located_at(&self, other: Span) -> Span {
441         other
442     }
443 
444     #[cfg(procmacro2_semver_exempt)]
source_file(&self) -> SourceFile445     pub fn source_file(&self) -> SourceFile {
446         SOURCE_MAP.with(|cm| {
447             let cm = cm.borrow();
448             let fi = cm.fileinfo(*self);
449             SourceFile {
450                 path: Path::new(&fi.name).to_owned(),
451             }
452         })
453     }
454 
455     #[cfg(span_locations)]
start(&self) -> LineColumn456     pub fn start(&self) -> LineColumn {
457         SOURCE_MAP.with(|cm| {
458             let cm = cm.borrow();
459             let fi = cm.fileinfo(*self);
460             fi.offset_line_column(self.lo as usize)
461         })
462     }
463 
464     #[cfg(span_locations)]
end(&self) -> LineColumn465     pub fn end(&self) -> LineColumn {
466         SOURCE_MAP.with(|cm| {
467             let cm = cm.borrow();
468             let fi = cm.fileinfo(*self);
469             fi.offset_line_column(self.hi as usize)
470         })
471     }
472 
473     #[cfg(not(span_locations))]
join(&self, _other: Span) -> Option<Span>474     pub fn join(&self, _other: Span) -> Option<Span> {
475         Some(Span {})
476     }
477 
478     #[cfg(span_locations)]
join(&self, other: Span) -> Option<Span>479     pub fn join(&self, other: Span) -> Option<Span> {
480         SOURCE_MAP.with(|cm| {
481             let cm = cm.borrow();
482             // If `other` is not within the same FileInfo as us, return None.
483             if !cm.fileinfo(*self).span_within(other) {
484                 return None;
485             }
486             Some(Span {
487                 lo: cmp::min(self.lo, other.lo),
488                 hi: cmp::max(self.hi, other.hi),
489             })
490         })
491     }
492 
493     #[cfg(not(span_locations))]
first_byte(self) -> Self494     fn first_byte(self) -> Self {
495         self
496     }
497 
498     #[cfg(span_locations)]
first_byte(self) -> Self499     fn first_byte(self) -> Self {
500         Span {
501             lo: self.lo,
502             hi: cmp::min(self.lo.saturating_add(1), self.hi),
503         }
504     }
505 
506     #[cfg(not(span_locations))]
last_byte(self) -> Self507     fn last_byte(self) -> Self {
508         self
509     }
510 
511     #[cfg(span_locations)]
last_byte(self) -> Self512     fn last_byte(self) -> Self {
513         Span {
514             lo: cmp::max(self.hi.saturating_sub(1), self.lo),
515             hi: self.hi,
516         }
517     }
518 }
519 
520 impl Debug for Span {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result521     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
522         #[cfg(span_locations)]
523         return write!(f, "bytes({}..{})", self.lo, self.hi);
524 
525         #[cfg(not(span_locations))]
526         write!(f, "Span")
527     }
528 }
529 
debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span)530 pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) {
531     #[cfg(span_locations)]
532     {
533         if span.lo == 0 && span.hi == 0 {
534             return;
535         }
536     }
537 
538     if cfg!(span_locations) {
539         debug.field("span", &span);
540     }
541 }
542 
543 #[derive(Clone)]
544 pub(crate) struct Group {
545     delimiter: Delimiter,
546     stream: TokenStream,
547     span: Span,
548 }
549 
550 impl Group {
new(delimiter: Delimiter, stream: TokenStream) -> Group551     pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group {
552         Group {
553             delimiter,
554             stream,
555             span: Span::call_site(),
556         }
557     }
558 
delimiter(&self) -> Delimiter559     pub fn delimiter(&self) -> Delimiter {
560         self.delimiter
561     }
562 
stream(&self) -> TokenStream563     pub fn stream(&self) -> TokenStream {
564         self.stream.clone()
565     }
566 
span(&self) -> Span567     pub fn span(&self) -> Span {
568         self.span
569     }
570 
span_open(&self) -> Span571     pub fn span_open(&self) -> Span {
572         self.span.first_byte()
573     }
574 
span_close(&self) -> Span575     pub fn span_close(&self) -> Span {
576         self.span.last_byte()
577     }
578 
set_span(&mut self, span: Span)579     pub fn set_span(&mut self, span: Span) {
580         self.span = span;
581     }
582 }
583 
584 impl Display for Group {
585     // We attempt to match libproc_macro's formatting.
586     // Empty parens: ()
587     // Nonempty parens: (...)
588     // Empty brackets: []
589     // Nonempty brackets: [...]
590     // Empty braces: { }
591     // Nonempty braces: { ... }
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result592     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
593         let (open, close) = match self.delimiter {
594             Delimiter::Parenthesis => ("(", ")"),
595             Delimiter::Brace => ("{ ", "}"),
596             Delimiter::Bracket => ("[", "]"),
597             Delimiter::None => ("", ""),
598         };
599 
600         f.write_str(open)?;
601         Display::fmt(&self.stream, f)?;
602         if self.delimiter == Delimiter::Brace && !self.stream.inner.is_empty() {
603             f.write_str(" ")?;
604         }
605         f.write_str(close)?;
606 
607         Ok(())
608     }
609 }
610 
611 impl Debug for Group {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result612     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
613         let mut debug = fmt.debug_struct("Group");
614         debug.field("delimiter", &self.delimiter);
615         debug.field("stream", &self.stream);
616         debug_span_field_if_nontrivial(&mut debug, self.span);
617         debug.finish()
618     }
619 }
620 
621 #[derive(Clone)]
622 pub(crate) struct Ident {
623     sym: String,
624     span: Span,
625     raw: bool,
626 }
627 
628 impl Ident {
_new(string: &str, raw: bool, span: Span) -> Ident629     fn _new(string: &str, raw: bool, span: Span) -> Ident {
630         validate_ident(string);
631 
632         Ident {
633             sym: string.to_owned(),
634             span,
635             raw,
636         }
637     }
638 
new(string: &str, span: Span) -> Ident639     pub fn new(string: &str, span: Span) -> Ident {
640         Ident::_new(string, false, span)
641     }
642 
new_raw(string: &str, span: Span) -> Ident643     pub fn new_raw(string: &str, span: Span) -> Ident {
644         Ident::_new(string, true, span)
645     }
646 
span(&self) -> Span647     pub fn span(&self) -> Span {
648         self.span
649     }
650 
set_span(&mut self, span: Span)651     pub fn set_span(&mut self, span: Span) {
652         self.span = span;
653     }
654 }
655 
is_ident_start(c: char) -> bool656 pub(crate) fn is_ident_start(c: char) -> bool {
657     ('a' <= c && c <= 'z')
658         || ('A' <= c && c <= 'Z')
659         || c == '_'
660         || (c > '\x7f' && UnicodeXID::is_xid_start(c))
661 }
662 
is_ident_continue(c: char) -> bool663 pub(crate) fn is_ident_continue(c: char) -> bool {
664     ('a' <= c && c <= 'z')
665         || ('A' <= c && c <= 'Z')
666         || c == '_'
667         || ('0' <= c && c <= '9')
668         || (c > '\x7f' && UnicodeXID::is_xid_continue(c))
669 }
670 
validate_ident(string: &str)671 fn validate_ident(string: &str) {
672     let validate = string;
673     if validate.is_empty() {
674         panic!("Ident is not allowed to be empty; use Option<Ident>");
675     }
676 
677     if validate.bytes().all(|digit| digit >= b'0' && digit <= b'9') {
678         panic!("Ident cannot be a number; use Literal instead");
679     }
680 
681     fn ident_ok(string: &str) -> bool {
682         let mut chars = string.chars();
683         let first = chars.next().unwrap();
684         if !is_ident_start(first) {
685             return false;
686         }
687         for ch in chars {
688             if !is_ident_continue(ch) {
689                 return false;
690             }
691         }
692         true
693     }
694 
695     if !ident_ok(validate) {
696         panic!("{:?} is not a valid Ident", string);
697     }
698 }
699 
700 impl PartialEq for Ident {
eq(&self, other: &Ident) -> bool701     fn eq(&self, other: &Ident) -> bool {
702         self.sym == other.sym && self.raw == other.raw
703     }
704 }
705 
706 impl<T> PartialEq<T> for Ident
707 where
708     T: ?Sized + AsRef<str>,
709 {
eq(&self, other: &T) -> bool710     fn eq(&self, other: &T) -> bool {
711         let other = other.as_ref();
712         if self.raw {
713             other.starts_with("r#") && self.sym == other[2..]
714         } else {
715             self.sym == other
716         }
717     }
718 }
719 
720 impl Display for Ident {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result721     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
722         if self.raw {
723             f.write_str("r#")?;
724         }
725         Display::fmt(&self.sym, f)
726     }
727 }
728 
729 impl Debug for Ident {
730     // Ident(proc_macro), Ident(r#union)
731     #[cfg(not(span_locations))]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result732     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
733         let mut debug = f.debug_tuple("Ident");
734         debug.field(&format_args!("{}", self));
735         debug.finish()
736     }
737 
738     // Ident {
739     //     sym: proc_macro,
740     //     span: bytes(128..138)
741     // }
742     #[cfg(span_locations)]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result743     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
744         let mut debug = f.debug_struct("Ident");
745         debug.field("sym", &format_args!("{}", self));
746         debug_span_field_if_nontrivial(&mut debug, self.span);
747         debug.finish()
748     }
749 }
750 
751 #[derive(Clone)]
752 pub(crate) struct Literal {
753     text: String,
754     span: Span,
755 }
756 
757 macro_rules! suffixed_numbers {
758     ($($name:ident => $kind:ident,)*) => ($(
759         pub fn $name(n: $kind) -> Literal {
760             Literal::_new(format!(concat!("{}", stringify!($kind)), n))
761         }
762     )*)
763 }
764 
765 macro_rules! unsuffixed_numbers {
766     ($($name:ident => $kind:ident,)*) => ($(
767         pub fn $name(n: $kind) -> Literal {
768             Literal::_new(n.to_string())
769         }
770     )*)
771 }
772 
773 impl Literal {
_new(text: String) -> Literal774     pub(crate) fn _new(text: String) -> Literal {
775         Literal {
776             text,
777             span: Span::call_site(),
778         }
779     }
780 
781     suffixed_numbers! {
782         u8_suffixed => u8,
783         u16_suffixed => u16,
784         u32_suffixed => u32,
785         u64_suffixed => u64,
786         u128_suffixed => u128,
787         usize_suffixed => usize,
788         i8_suffixed => i8,
789         i16_suffixed => i16,
790         i32_suffixed => i32,
791         i64_suffixed => i64,
792         i128_suffixed => i128,
793         isize_suffixed => isize,
794 
795         f32_suffixed => f32,
796         f64_suffixed => f64,
797     }
798 
799     unsuffixed_numbers! {
800         u8_unsuffixed => u8,
801         u16_unsuffixed => u16,
802         u32_unsuffixed => u32,
803         u64_unsuffixed => u64,
804         u128_unsuffixed => u128,
805         usize_unsuffixed => usize,
806         i8_unsuffixed => i8,
807         i16_unsuffixed => i16,
808         i32_unsuffixed => i32,
809         i64_unsuffixed => i64,
810         i128_unsuffixed => i128,
811         isize_unsuffixed => isize,
812     }
813 
f32_unsuffixed(f: f32) -> Literal814     pub fn f32_unsuffixed(f: f32) -> Literal {
815         let mut s = f.to_string();
816         if !s.contains('.') {
817             s.push_str(".0");
818         }
819         Literal::_new(s)
820     }
821 
f64_unsuffixed(f: f64) -> Literal822     pub fn f64_unsuffixed(f: f64) -> Literal {
823         let mut s = f.to_string();
824         if !s.contains('.') {
825             s.push_str(".0");
826         }
827         Literal::_new(s)
828     }
829 
string(t: &str) -> Literal830     pub fn string(t: &str) -> Literal {
831         let mut text = String::with_capacity(t.len() + 2);
832         text.push('"');
833         for c in t.chars() {
834             if c == '\'' {
835                 // escape_debug turns this into "\'" which is unnecessary.
836                 text.push(c);
837             } else {
838                 text.extend(c.escape_debug());
839             }
840         }
841         text.push('"');
842         Literal::_new(text)
843     }
844 
character(t: char) -> Literal845     pub fn character(t: char) -> Literal {
846         let mut text = String::new();
847         text.push('\'');
848         if t == '"' {
849             // escape_debug turns this into '\"' which is unnecessary.
850             text.push(t);
851         } else {
852             text.extend(t.escape_debug());
853         }
854         text.push('\'');
855         Literal::_new(text)
856     }
857 
byte_string(bytes: &[u8]) -> Literal858     pub fn byte_string(bytes: &[u8]) -> Literal {
859         let mut escaped = "b\"".to_string();
860         for b in bytes {
861             #[allow(clippy::match_overlapping_arm)]
862             match *b {
863                 b'\0' => escaped.push_str(r"\0"),
864                 b'\t' => escaped.push_str(r"\t"),
865                 b'\n' => escaped.push_str(r"\n"),
866                 b'\r' => escaped.push_str(r"\r"),
867                 b'"' => escaped.push_str("\\\""),
868                 b'\\' => escaped.push_str("\\\\"),
869                 b'\x20'..=b'\x7E' => escaped.push(*b as char),
870                 _ => escaped.push_str(&format!("\\x{:02X}", b)),
871             }
872         }
873         escaped.push('"');
874         Literal::_new(escaped)
875     }
876 
span(&self) -> Span877     pub fn span(&self) -> Span {
878         self.span
879     }
880 
set_span(&mut self, span: Span)881     pub fn set_span(&mut self, span: Span) {
882         self.span = span;
883     }
884 
subspan<R: RangeBounds<usize>>(&self, _range: R) -> Option<Span>885     pub fn subspan<R: RangeBounds<usize>>(&self, _range: R) -> Option<Span> {
886         None
887     }
888 }
889 
890 impl Display for Literal {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result891     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
892         Display::fmt(&self.text, f)
893     }
894 }
895 
896 impl Debug for Literal {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result897     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
898         let mut debug = fmt.debug_struct("Literal");
899         debug.field("lit", &format_args!("{}", self.text));
900         debug_span_field_if_nontrivial(&mut debug, self.span);
901         debug.finish()
902     }
903 }
904