1 #[cfg(span_locations)]
2 use crate::location::LineColumn;
3 use crate::parse::{self, Cursor};
4 use crate::rcvec::{RcVec, RcVecBuilder, RcVecIntoIter, RcVecMut};
5 use crate::{Delimiter, Spacing, TokenTree};
6 #[cfg(all(span_locations, not(fuzzing)))]
7 use alloc::collections::BTreeMap;
8 #[cfg(all(span_locations, not(fuzzing)))]
9 use core::cell::RefCell;
10 #[cfg(span_locations)]
11 use core::cmp;
12 use core::fmt::{self, Debug, Display, Write};
13 use core::mem::ManuallyDrop;
14 use core::ops::RangeBounds;
15 use core::ptr;
16 use core::str::FromStr;
17 use std::path::PathBuf;
18 
19 /// Force use of proc-macro2's fallback implementation of the API for now, even
20 /// if the compiler's implementation is available.
force()21 pub fn force() {
22     #[cfg(wrap_proc_macro)]
23     crate::detection::force_fallback();
24 }
25 
26 /// Resume using the compiler's implementation of the proc macro API if it is
27 /// available.
unforce()28 pub fn unforce() {
29     #[cfg(wrap_proc_macro)]
30     crate::detection::unforce_fallback();
31 }
32 
33 #[derive(Clone)]
34 pub(crate) struct TokenStream {
35     inner: RcVec<TokenTree>,
36 }
37 
38 #[derive(Debug)]
39 pub(crate) struct LexError {
40     pub(crate) span: Span,
41 }
42 
43 impl LexError {
span(&self) -> Span44     pub(crate) fn span(&self) -> Span {
45         self.span
46     }
47 
call_site() -> Self48     pub(crate) fn call_site() -> Self {
49         LexError {
50             span: Span::call_site(),
51         }
52     }
53 }
54 
55 impl TokenStream {
new() -> Self56     pub fn new() -> Self {
57         TokenStream {
58             inner: RcVecBuilder::new().build(),
59         }
60     }
61 
is_empty(&self) -> bool62     pub fn is_empty(&self) -> bool {
63         self.inner.len() == 0
64     }
65 
take_inner(self) -> RcVecBuilder<TokenTree>66     fn take_inner(self) -> RcVecBuilder<TokenTree> {
67         let nodrop = ManuallyDrop::new(self);
68         unsafe { ptr::read(&nodrop.inner) }.make_owned()
69     }
70 }
71 
push_token_from_proc_macro(mut vec: RcVecMut<TokenTree>, token: TokenTree)72 fn push_token_from_proc_macro(mut vec: RcVecMut<TokenTree>, token: TokenTree) {
73     // https://github.com/dtolnay/proc-macro2/issues/235
74     match token {
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         }) if literal.repr.starts_with('-') => {
82             push_negative_literal(vec, literal);
83         }
84         _ => vec.push(token),
85     }
86 
87     #[cold]
88     fn push_negative_literal(mut vec: RcVecMut<TokenTree>, mut literal: Literal) {
89         literal.repr.remove(0);
90         let mut punct = crate::Punct::new('-', Spacing::Alone);
91         punct.set_span(crate::Span::_new_fallback(literal.span));
92         vec.push(TokenTree::Punct(punct));
93         vec.push(TokenTree::Literal(crate::Literal::_new_fallback(literal)));
94     }
95 }
96 
97 // Nonrecursive to prevent stack overflow.
98 impl Drop for TokenStream {
drop(&mut self)99     fn drop(&mut self) {
100         let mut inner = match self.inner.get_mut() {
101             Some(inner) => inner,
102             None => return,
103         };
104         while let Some(token) = inner.pop() {
105             let group = match token {
106                 TokenTree::Group(group) => group.inner,
107                 _ => continue,
108             };
109             #[cfg(wrap_proc_macro)]
110             let group = match group {
111                 crate::imp::Group::Fallback(group) => group,
112                 crate::imp::Group::Compiler(_) => continue,
113             };
114             inner.extend(group.stream.take_inner());
115         }
116     }
117 }
118 
119 pub(crate) struct TokenStreamBuilder {
120     inner: RcVecBuilder<TokenTree>,
121 }
122 
123 impl TokenStreamBuilder {
new() -> Self124     pub fn new() -> Self {
125         TokenStreamBuilder {
126             inner: RcVecBuilder::new(),
127         }
128     }
129 
with_capacity(cap: usize) -> Self130     pub fn with_capacity(cap: usize) -> Self {
131         TokenStreamBuilder {
132             inner: RcVecBuilder::with_capacity(cap),
133         }
134     }
135 
push_token_from_parser(&mut self, tt: TokenTree)136     pub fn push_token_from_parser(&mut self, tt: TokenTree) {
137         self.inner.push(tt);
138     }
139 
build(self) -> TokenStream140     pub fn build(self) -> TokenStream {
141         TokenStream {
142             inner: self.inner.build(),
143         }
144     }
145 }
146 
147 #[cfg(span_locations)]
get_cursor(src: &str) -> Cursor148 fn get_cursor(src: &str) -> Cursor {
149     #[cfg(fuzzing)]
150     return Cursor { rest: src, off: 1 };
151 
152     // Create a dummy file & add it to the source map
153     #[cfg(not(fuzzing))]
154     SOURCE_MAP.with(|cm| {
155         let mut cm = cm.borrow_mut();
156         let span = cm.add_file(src);
157         Cursor {
158             rest: src,
159             off: span.lo,
160         }
161     })
162 }
163 
164 #[cfg(not(span_locations))]
get_cursor(src: &str) -> Cursor165 fn get_cursor(src: &str) -> Cursor {
166     Cursor { rest: src }
167 }
168 
169 impl FromStr for TokenStream {
170     type Err = LexError;
171 
from_str(src: &str) -> Result<TokenStream, LexError>172     fn from_str(src: &str) -> Result<TokenStream, LexError> {
173         // Create a dummy file & add it to the source map
174         let mut cursor = get_cursor(src);
175 
176         // Strip a byte order mark if present
177         const BYTE_ORDER_MARK: &str = "\u{feff}";
178         if cursor.starts_with(BYTE_ORDER_MARK) {
179             cursor = cursor.advance(BYTE_ORDER_MARK.len());
180         }
181 
182         parse::token_stream(cursor)
183     }
184 }
185 
186 impl Display for LexError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result187     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
188         f.write_str("cannot parse string into token stream")
189     }
190 }
191 
192 impl Display for TokenStream {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result193     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
194         let mut joint = false;
195         for (i, tt) in self.inner.iter().enumerate() {
196             if i != 0 && !joint {
197                 write!(f, " ")?;
198             }
199             joint = false;
200             match tt {
201                 TokenTree::Group(tt) => Display::fmt(tt, f),
202                 TokenTree::Ident(tt) => Display::fmt(tt, f),
203                 TokenTree::Punct(tt) => {
204                     joint = tt.spacing() == Spacing::Joint;
205                     Display::fmt(tt, f)
206                 }
207                 TokenTree::Literal(tt) => Display::fmt(tt, f),
208             }?;
209         }
210 
211         Ok(())
212     }
213 }
214 
215 impl Debug for TokenStream {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result216     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
217         f.write_str("TokenStream ")?;
218         f.debug_list().entries(self.clone()).finish()
219     }
220 }
221 
222 #[cfg(feature = "proc-macro")]
223 impl From<proc_macro::TokenStream> for TokenStream {
from(inner: proc_macro::TokenStream) -> Self224     fn from(inner: proc_macro::TokenStream) -> Self {
225         inner
226             .to_string()
227             .parse()
228             .expect("compiler token stream parse failed")
229     }
230 }
231 
232 #[cfg(feature = "proc-macro")]
233 impl From<TokenStream> for proc_macro::TokenStream {
from(inner: TokenStream) -> Self234     fn from(inner: TokenStream) -> Self {
235         inner
236             .to_string()
237             .parse()
238             .expect("failed to parse to compiler tokens")
239     }
240 }
241 
242 impl From<TokenTree> for TokenStream {
from(tree: TokenTree) -> Self243     fn from(tree: TokenTree) -> Self {
244         let mut stream = RcVecBuilder::new();
245         push_token_from_proc_macro(stream.as_mut(), tree);
246         TokenStream {
247             inner: stream.build(),
248         }
249     }
250 }
251 
252 impl FromIterator<TokenTree> for TokenStream {
from_iter<I: IntoIterator<Item = TokenTree>>(tokens: I) -> Self253     fn from_iter<I: IntoIterator<Item = TokenTree>>(tokens: I) -> Self {
254         let mut stream = TokenStream::new();
255         stream.extend(tokens);
256         stream
257     }
258 }
259 
260 impl FromIterator<TokenStream> for TokenStream {
from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self261     fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
262         let mut v = RcVecBuilder::new();
263 
264         for stream in streams {
265             v.extend(stream.take_inner());
266         }
267 
268         TokenStream { inner: v.build() }
269     }
270 }
271 
272 impl Extend<TokenTree> for TokenStream {
extend<I: IntoIterator<Item = TokenTree>>(&mut self, tokens: I)273     fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, tokens: I) {
274         let mut vec = self.inner.make_mut();
275         tokens
276             .into_iter()
277             .for_each(|token| push_token_from_proc_macro(vec.as_mut(), token));
278     }
279 }
280 
281 impl Extend<TokenStream> for TokenStream {
extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I)282     fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
283         self.inner.make_mut().extend(streams.into_iter().flatten());
284     }
285 }
286 
287 pub(crate) type TokenTreeIter = RcVecIntoIter<TokenTree>;
288 
289 impl IntoIterator for TokenStream {
290     type Item = TokenTree;
291     type IntoIter = TokenTreeIter;
292 
into_iter(self) -> TokenTreeIter293     fn into_iter(self) -> TokenTreeIter {
294         self.take_inner().into_iter()
295     }
296 }
297 
298 #[derive(Clone, PartialEq, Eq)]
299 pub(crate) struct SourceFile {
300     path: PathBuf,
301 }
302 
303 impl SourceFile {
304     /// Get the path to this source file as a string.
path(&self) -> PathBuf305     pub fn path(&self) -> PathBuf {
306         self.path.clone()
307     }
308 
is_real(&self) -> bool309     pub fn is_real(&self) -> bool {
310         false
311     }
312 }
313 
314 impl Debug for SourceFile {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result315     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
316         f.debug_struct("SourceFile")
317             .field("path", &self.path())
318             .field("is_real", &self.is_real())
319             .finish()
320     }
321 }
322 
323 #[cfg(all(span_locations, not(fuzzing)))]
324 thread_local! {
325     static SOURCE_MAP: RefCell<SourceMap> = RefCell::new(SourceMap {
326         // Start with a single dummy file which all call_site() and def_site()
327         // spans reference.
328         files: vec![FileInfo {
329             source_text: String::new(),
330             span: Span { lo: 0, hi: 0 },
331             lines: vec![0],
332             char_index_to_byte_offset: BTreeMap::new(),
333         }],
334     });
335 }
336 
337 #[cfg(all(span_locations, not(fuzzing)))]
338 struct FileInfo {
339     source_text: String,
340     span: Span,
341     lines: Vec<usize>,
342     char_index_to_byte_offset: BTreeMap<usize, usize>,
343 }
344 
345 #[cfg(all(span_locations, not(fuzzing)))]
346 impl FileInfo {
offset_line_column(&self, offset: usize) -> LineColumn347     fn offset_line_column(&self, offset: usize) -> LineColumn {
348         assert!(self.span_within(Span {
349             lo: offset as u32,
350             hi: offset as u32,
351         }));
352         let offset = offset - self.span.lo as usize;
353         match self.lines.binary_search(&offset) {
354             Ok(found) => LineColumn {
355                 line: found + 1,
356                 column: 0,
357             },
358             Err(idx) => LineColumn {
359                 line: idx,
360                 column: offset - self.lines[idx - 1],
361             },
362         }
363     }
364 
span_within(&self, span: Span) -> bool365     fn span_within(&self, span: Span) -> bool {
366         span.lo >= self.span.lo && span.hi <= self.span.hi
367     }
368 
source_text(&mut self, span: Span) -> String369     fn source_text(&mut self, span: Span) -> String {
370         let lo_char = (span.lo - self.span.lo) as usize;
371 
372         // Look up offset of the largest already-computed char index that is
373         // less than or equal to the current requested one. We resume counting
374         // chars from that point.
375         let (&last_char_index, &last_byte_offset) = self
376             .char_index_to_byte_offset
377             .range(..=lo_char)
378             .next_back()
379             .unwrap_or((&0, &0));
380 
381         let lo_byte = if last_char_index == lo_char {
382             last_byte_offset
383         } else {
384             let total_byte_offset = match self.source_text[last_byte_offset..]
385                 .char_indices()
386                 .nth(lo_char - last_char_index)
387             {
388                 Some((additional_offset, _ch)) => last_byte_offset + additional_offset,
389                 None => self.source_text.len(),
390             };
391             self.char_index_to_byte_offset
392                 .insert(lo_char, total_byte_offset);
393             total_byte_offset
394         };
395 
396         let trunc_lo = &self.source_text[lo_byte..];
397         let char_len = (span.hi - span.lo) as usize;
398         let source_text = match trunc_lo.char_indices().nth(char_len) {
399             Some((offset, _ch)) => &trunc_lo[..offset],
400             None => trunc_lo,
401         };
402         source_text.to_owned()
403     }
404 }
405 
406 /// Computes the offsets of each line in the given source string
407 /// and the total number of characters
408 #[cfg(all(span_locations, not(fuzzing)))]
lines_offsets(s: &str) -> (usize, Vec<usize>)409 fn lines_offsets(s: &str) -> (usize, Vec<usize>) {
410     let mut lines = vec![0];
411     let mut total = 0;
412 
413     for ch in s.chars() {
414         total += 1;
415         if ch == '\n' {
416             lines.push(total);
417         }
418     }
419 
420     (total, lines)
421 }
422 
423 #[cfg(all(span_locations, not(fuzzing)))]
424 struct SourceMap {
425     files: Vec<FileInfo>,
426 }
427 
428 #[cfg(all(span_locations, not(fuzzing)))]
429 impl SourceMap {
next_start_pos(&self) -> u32430     fn next_start_pos(&self) -> u32 {
431         // Add 1 so there's always space between files.
432         //
433         // We'll always have at least 1 file, as we initialize our files list
434         // with a dummy file.
435         self.files.last().unwrap().span.hi + 1
436     }
437 
add_file(&mut self, src: &str) -> Span438     fn add_file(&mut self, src: &str) -> Span {
439         let (len, lines) = lines_offsets(src);
440         let lo = self.next_start_pos();
441         let span = Span {
442             lo,
443             hi: lo + (len as u32),
444         };
445 
446         self.files.push(FileInfo {
447             source_text: src.to_owned(),
448             span,
449             lines,
450             // Populated lazily by source_text().
451             char_index_to_byte_offset: BTreeMap::new(),
452         });
453 
454         span
455     }
456 
457     #[cfg(procmacro2_semver_exempt)]
filepath(&self, span: Span) -> PathBuf458     fn filepath(&self, span: Span) -> PathBuf {
459         for (i, file) in self.files.iter().enumerate() {
460             if file.span_within(span) {
461                 return PathBuf::from(if i == 0 {
462                     "<unspecified>".to_owned()
463                 } else {
464                     format!("<parsed string {}>", i)
465                 });
466             }
467         }
468         unreachable!("Invalid span with no related FileInfo!");
469     }
470 
fileinfo(&self, span: Span) -> &FileInfo471     fn fileinfo(&self, span: Span) -> &FileInfo {
472         for file in &self.files {
473             if file.span_within(span) {
474                 return file;
475             }
476         }
477         unreachable!("Invalid span with no related FileInfo!");
478     }
479 
fileinfo_mut(&mut self, span: Span) -> &mut FileInfo480     fn fileinfo_mut(&mut self, span: Span) -> &mut FileInfo {
481         for file in &mut self.files {
482             if file.span_within(span) {
483                 return file;
484             }
485         }
486         unreachable!("Invalid span with no related FileInfo!");
487     }
488 }
489 
490 #[derive(Clone, Copy, PartialEq, Eq)]
491 pub(crate) struct Span {
492     #[cfg(span_locations)]
493     pub(crate) lo: u32,
494     #[cfg(span_locations)]
495     pub(crate) hi: u32,
496 }
497 
498 impl Span {
499     #[cfg(not(span_locations))]
call_site() -> Self500     pub fn call_site() -> Self {
501         Span {}
502     }
503 
504     #[cfg(span_locations)]
call_site() -> Self505     pub fn call_site() -> Self {
506         Span { lo: 0, hi: 0 }
507     }
508 
mixed_site() -> Self509     pub fn mixed_site() -> Self {
510         Span::call_site()
511     }
512 
513     #[cfg(procmacro2_semver_exempt)]
def_site() -> Self514     pub fn def_site() -> Self {
515         Span::call_site()
516     }
517 
resolved_at(&self, _other: Span) -> Span518     pub fn resolved_at(&self, _other: Span) -> Span {
519         // Stable spans consist only of line/column information, so
520         // `resolved_at` and `located_at` only select which span the
521         // caller wants line/column information from.
522         *self
523     }
524 
located_at(&self, other: Span) -> Span525     pub fn located_at(&self, other: Span) -> Span {
526         other
527     }
528 
529     #[cfg(procmacro2_semver_exempt)]
source_file(&self) -> SourceFile530     pub fn source_file(&self) -> SourceFile {
531         #[cfg(fuzzing)]
532         return SourceFile {
533             path: PathBuf::from("<unspecified>"),
534         };
535 
536         #[cfg(not(fuzzing))]
537         SOURCE_MAP.with(|cm| {
538             let cm = cm.borrow();
539             let path = cm.filepath(*self);
540             SourceFile { path }
541         })
542     }
543 
544     #[cfg(span_locations)]
start(&self) -> LineColumn545     pub fn start(&self) -> LineColumn {
546         #[cfg(fuzzing)]
547         return LineColumn { line: 0, column: 0 };
548 
549         #[cfg(not(fuzzing))]
550         SOURCE_MAP.with(|cm| {
551             let cm = cm.borrow();
552             let fi = cm.fileinfo(*self);
553             fi.offset_line_column(self.lo as usize)
554         })
555     }
556 
557     #[cfg(span_locations)]
end(&self) -> LineColumn558     pub fn end(&self) -> LineColumn {
559         #[cfg(fuzzing)]
560         return LineColumn { line: 0, column: 0 };
561 
562         #[cfg(not(fuzzing))]
563         SOURCE_MAP.with(|cm| {
564             let cm = cm.borrow();
565             let fi = cm.fileinfo(*self);
566             fi.offset_line_column(self.hi as usize)
567         })
568     }
569 
570     #[cfg(not(span_locations))]
join(&self, _other: Span) -> Option<Span>571     pub fn join(&self, _other: Span) -> Option<Span> {
572         Some(Span {})
573     }
574 
575     #[cfg(span_locations)]
join(&self, other: Span) -> Option<Span>576     pub fn join(&self, other: Span) -> Option<Span> {
577         #[cfg(fuzzing)]
578         return {
579             let _ = other;
580             None
581         };
582 
583         #[cfg(not(fuzzing))]
584         SOURCE_MAP.with(|cm| {
585             let cm = cm.borrow();
586             // If `other` is not within the same FileInfo as us, return None.
587             if !cm.fileinfo(*self).span_within(other) {
588                 return None;
589             }
590             Some(Span {
591                 lo: cmp::min(self.lo, other.lo),
592                 hi: cmp::max(self.hi, other.hi),
593             })
594         })
595     }
596 
597     #[cfg(not(span_locations))]
source_text(&self) -> Option<String>598     pub fn source_text(&self) -> Option<String> {
599         None
600     }
601 
602     #[cfg(span_locations)]
source_text(&self) -> Option<String>603     pub fn source_text(&self) -> Option<String> {
604         #[cfg(fuzzing)]
605         return None;
606 
607         #[cfg(not(fuzzing))]
608         {
609             if self.is_call_site() {
610                 None
611             } else {
612                 Some(SOURCE_MAP.with(|cm| cm.borrow_mut().fileinfo_mut(*self).source_text(*self)))
613             }
614         }
615     }
616 
617     #[cfg(not(span_locations))]
first_byte(self) -> Self618     pub(crate) fn first_byte(self) -> Self {
619         self
620     }
621 
622     #[cfg(span_locations)]
first_byte(self) -> Self623     pub(crate) fn first_byte(self) -> Self {
624         Span {
625             lo: self.lo,
626             hi: cmp::min(self.lo.saturating_add(1), self.hi),
627         }
628     }
629 
630     #[cfg(not(span_locations))]
last_byte(self) -> Self631     pub(crate) fn last_byte(self) -> Self {
632         self
633     }
634 
635     #[cfg(span_locations)]
last_byte(self) -> Self636     pub(crate) fn last_byte(self) -> Self {
637         Span {
638             lo: cmp::max(self.hi.saturating_sub(1), self.lo),
639             hi: self.hi,
640         }
641     }
642 
643     #[cfg(span_locations)]
is_call_site(&self) -> bool644     fn is_call_site(&self) -> bool {
645         self.lo == 0 && self.hi == 0
646     }
647 }
648 
649 impl Debug for Span {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result650     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
651         #[cfg(span_locations)]
652         return write!(f, "bytes({}..{})", self.lo, self.hi);
653 
654         #[cfg(not(span_locations))]
655         write!(f, "Span")
656     }
657 }
658 
debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span)659 pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) {
660     #[cfg(span_locations)]
661     {
662         if span.is_call_site() {
663             return;
664         }
665     }
666 
667     if cfg!(span_locations) {
668         debug.field("span", &span);
669     }
670 }
671 
672 #[derive(Clone)]
673 pub(crate) struct Group {
674     delimiter: Delimiter,
675     stream: TokenStream,
676     span: Span,
677 }
678 
679 impl Group {
new(delimiter: Delimiter, stream: TokenStream) -> Self680     pub fn new(delimiter: Delimiter, stream: TokenStream) -> Self {
681         Group {
682             delimiter,
683             stream,
684             span: Span::call_site(),
685         }
686     }
687 
delimiter(&self) -> Delimiter688     pub fn delimiter(&self) -> Delimiter {
689         self.delimiter
690     }
691 
stream(&self) -> TokenStream692     pub fn stream(&self) -> TokenStream {
693         self.stream.clone()
694     }
695 
span(&self) -> Span696     pub fn span(&self) -> Span {
697         self.span
698     }
699 
span_open(&self) -> Span700     pub fn span_open(&self) -> Span {
701         self.span.first_byte()
702     }
703 
span_close(&self) -> Span704     pub fn span_close(&self) -> Span {
705         self.span.last_byte()
706     }
707 
set_span(&mut self, span: Span)708     pub fn set_span(&mut self, span: Span) {
709         self.span = span;
710     }
711 }
712 
713 impl Display for Group {
714     // We attempt to match libproc_macro's formatting.
715     // Empty parens: ()
716     // Nonempty parens: (...)
717     // Empty brackets: []
718     // Nonempty brackets: [...]
719     // Empty braces: { }
720     // Nonempty braces: { ... }
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result721     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
722         let (open, close) = match self.delimiter {
723             Delimiter::Parenthesis => ("(", ")"),
724             Delimiter::Brace => ("{ ", "}"),
725             Delimiter::Bracket => ("[", "]"),
726             Delimiter::None => ("", ""),
727         };
728 
729         f.write_str(open)?;
730         Display::fmt(&self.stream, f)?;
731         if self.delimiter == Delimiter::Brace && !self.stream.inner.is_empty() {
732             f.write_str(" ")?;
733         }
734         f.write_str(close)?;
735 
736         Ok(())
737     }
738 }
739 
740 impl Debug for Group {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result741     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
742         let mut debug = fmt.debug_struct("Group");
743         debug.field("delimiter", &self.delimiter);
744         debug.field("stream", &self.stream);
745         debug_span_field_if_nontrivial(&mut debug, self.span);
746         debug.finish()
747     }
748 }
749 
750 #[derive(Clone)]
751 pub(crate) struct Ident {
752     sym: String,
753     span: Span,
754     raw: bool,
755 }
756 
757 impl Ident {
758     #[track_caller]
new_checked(string: &str, span: Span) -> Self759     pub fn new_checked(string: &str, span: Span) -> Self {
760         validate_ident(string);
761         Ident::new_unchecked(string, span)
762     }
763 
new_unchecked(string: &str, span: Span) -> Self764     pub fn new_unchecked(string: &str, span: Span) -> Self {
765         Ident {
766             sym: string.to_owned(),
767             span,
768             raw: false,
769         }
770     }
771 
772     #[track_caller]
new_raw_checked(string: &str, span: Span) -> Self773     pub fn new_raw_checked(string: &str, span: Span) -> Self {
774         validate_ident_raw(string);
775         Ident::new_raw_unchecked(string, span)
776     }
777 
new_raw_unchecked(string: &str, span: Span) -> Self778     pub fn new_raw_unchecked(string: &str, span: Span) -> Self {
779         Ident {
780             sym: string.to_owned(),
781             span,
782             raw: true,
783         }
784     }
785 
span(&self) -> Span786     pub fn span(&self) -> Span {
787         self.span
788     }
789 
set_span(&mut self, span: Span)790     pub fn set_span(&mut self, span: Span) {
791         self.span = span;
792     }
793 }
794 
is_ident_start(c: char) -> bool795 pub(crate) fn is_ident_start(c: char) -> bool {
796     c == '_' || unicode_ident::is_xid_start(c)
797 }
798 
is_ident_continue(c: char) -> bool799 pub(crate) fn is_ident_continue(c: char) -> bool {
800     unicode_ident::is_xid_continue(c)
801 }
802 
803 #[track_caller]
validate_ident(string: &str)804 fn validate_ident(string: &str) {
805     if string.is_empty() {
806         panic!("Ident is not allowed to be empty; use Option<Ident>");
807     }
808 
809     if string.bytes().all(|digit| b'0' <= digit && digit <= b'9') {
810         panic!("Ident cannot be a number; use Literal instead");
811     }
812 
813     fn ident_ok(string: &str) -> bool {
814         let mut chars = string.chars();
815         let first = chars.next().unwrap();
816         if !is_ident_start(first) {
817             return false;
818         }
819         for ch in chars {
820             if !is_ident_continue(ch) {
821                 return false;
822             }
823         }
824         true
825     }
826 
827     if !ident_ok(string) {
828         panic!("{:?} is not a valid Ident", string);
829     }
830 }
831 
832 #[track_caller]
validate_ident_raw(string: &str)833 fn validate_ident_raw(string: &str) {
834     validate_ident(string);
835 
836     match string {
837         "_" | "super" | "self" | "Self" | "crate" => {
838             panic!("`r#{}` cannot be a raw identifier", string);
839         }
840         _ => {}
841     }
842 }
843 
844 impl PartialEq for Ident {
eq(&self, other: &Ident) -> bool845     fn eq(&self, other: &Ident) -> bool {
846         self.sym == other.sym && self.raw == other.raw
847     }
848 }
849 
850 impl<T> PartialEq<T> for Ident
851 where
852     T: ?Sized + AsRef<str>,
853 {
eq(&self, other: &T) -> bool854     fn eq(&self, other: &T) -> bool {
855         let other = other.as_ref();
856         if self.raw {
857             other.starts_with("r#") && self.sym == other[2..]
858         } else {
859             self.sym == other
860         }
861     }
862 }
863 
864 impl Display for Ident {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result865     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
866         if self.raw {
867             f.write_str("r#")?;
868         }
869         Display::fmt(&self.sym, f)
870     }
871 }
872 
873 #[allow(clippy::missing_fields_in_debug)]
874 impl Debug for Ident {
875     // Ident(proc_macro), Ident(r#union)
876     #[cfg(not(span_locations))]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result877     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
878         let mut debug = f.debug_tuple("Ident");
879         debug.field(&format_args!("{}", self));
880         debug.finish()
881     }
882 
883     // Ident {
884     //     sym: proc_macro,
885     //     span: bytes(128..138)
886     // }
887     #[cfg(span_locations)]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result888     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
889         let mut debug = f.debug_struct("Ident");
890         debug.field("sym", &format_args!("{}", self));
891         debug_span_field_if_nontrivial(&mut debug, self.span);
892         debug.finish()
893     }
894 }
895 
896 #[derive(Clone)]
897 pub(crate) struct Literal {
898     repr: String,
899     span: Span,
900 }
901 
902 macro_rules! suffixed_numbers {
903     ($($name:ident => $kind:ident,)*) => ($(
904         pub fn $name(n: $kind) -> Literal {
905             Literal::_new(format!(concat!("{}", stringify!($kind)), n))
906         }
907     )*)
908 }
909 
910 macro_rules! unsuffixed_numbers {
911     ($($name:ident => $kind:ident,)*) => ($(
912         pub fn $name(n: $kind) -> Literal {
913             Literal::_new(n.to_string())
914         }
915     )*)
916 }
917 
918 impl Literal {
_new(repr: String) -> Self919     pub(crate) fn _new(repr: String) -> Self {
920         Literal {
921             repr,
922             span: Span::call_site(),
923         }
924     }
925 
from_str_unchecked(repr: &str) -> Self926     pub(crate) unsafe fn from_str_unchecked(repr: &str) -> Self {
927         Literal::_new(repr.to_owned())
928     }
929 
930     suffixed_numbers! {
931         u8_suffixed => u8,
932         u16_suffixed => u16,
933         u32_suffixed => u32,
934         u64_suffixed => u64,
935         u128_suffixed => u128,
936         usize_suffixed => usize,
937         i8_suffixed => i8,
938         i16_suffixed => i16,
939         i32_suffixed => i32,
940         i64_suffixed => i64,
941         i128_suffixed => i128,
942         isize_suffixed => isize,
943 
944         f32_suffixed => f32,
945         f64_suffixed => f64,
946     }
947 
948     unsuffixed_numbers! {
949         u8_unsuffixed => u8,
950         u16_unsuffixed => u16,
951         u32_unsuffixed => u32,
952         u64_unsuffixed => u64,
953         u128_unsuffixed => u128,
954         usize_unsuffixed => usize,
955         i8_unsuffixed => i8,
956         i16_unsuffixed => i16,
957         i32_unsuffixed => i32,
958         i64_unsuffixed => i64,
959         i128_unsuffixed => i128,
960         isize_unsuffixed => isize,
961     }
962 
f32_unsuffixed(f: f32) -> Literal963     pub fn f32_unsuffixed(f: f32) -> Literal {
964         let mut s = f.to_string();
965         if !s.contains('.') {
966             s.push_str(".0");
967         }
968         Literal::_new(s)
969     }
970 
f64_unsuffixed(f: f64) -> Literal971     pub fn f64_unsuffixed(f: f64) -> Literal {
972         let mut s = f.to_string();
973         if !s.contains('.') {
974             s.push_str(".0");
975         }
976         Literal::_new(s)
977     }
978 
string(t: &str) -> Literal979     pub fn string(t: &str) -> Literal {
980         let mut repr = String::with_capacity(t.len() + 2);
981         repr.push('"');
982         let mut chars = t.chars();
983         while let Some(ch) = chars.next() {
984             if ch == '\0' {
985                 repr.push_str(
986                     if chars
987                         .as_str()
988                         .starts_with(|next| '0' <= next && next <= '7')
989                     {
990                         // circumvent clippy::octal_escapes lint
991                         "\\x00"
992                     } else {
993                         "\\0"
994                     },
995                 );
996             } else if ch == '\'' {
997                 // escape_debug turns this into "\'" which is unnecessary.
998                 repr.push(ch);
999             } else {
1000                 repr.extend(ch.escape_debug());
1001             }
1002         }
1003         repr.push('"');
1004         Literal::_new(repr)
1005     }
1006 
character(t: char) -> Literal1007     pub fn character(t: char) -> Literal {
1008         let mut repr = String::new();
1009         repr.push('\'');
1010         if t == '"' {
1011             // escape_debug turns this into '\"' which is unnecessary.
1012             repr.push(t);
1013         } else {
1014             repr.extend(t.escape_debug());
1015         }
1016         repr.push('\'');
1017         Literal::_new(repr)
1018     }
1019 
byte_string(bytes: &[u8]) -> Literal1020     pub fn byte_string(bytes: &[u8]) -> Literal {
1021         let mut escaped = "b\"".to_string();
1022         let mut bytes = bytes.iter();
1023         while let Some(&b) = bytes.next() {
1024             #[allow(clippy::match_overlapping_arm)]
1025             match b {
1026                 b'\0' => escaped.push_str(match bytes.as_slice().first() {
1027                     // circumvent clippy::octal_escapes lint
1028                     Some(b'0'..=b'7') => r"\x00",
1029                     _ => r"\0",
1030                 }),
1031                 b'\t' => escaped.push_str(r"\t"),
1032                 b'\n' => escaped.push_str(r"\n"),
1033                 b'\r' => escaped.push_str(r"\r"),
1034                 b'"' => escaped.push_str("\\\""),
1035                 b'\\' => escaped.push_str("\\\\"),
1036                 b'\x20'..=b'\x7E' => escaped.push(b as char),
1037                 _ => {
1038                     let _ = write!(escaped, "\\x{:02X}", b);
1039                 }
1040             }
1041         }
1042         escaped.push('"');
1043         Literal::_new(escaped)
1044     }
1045 
span(&self) -> Span1046     pub fn span(&self) -> Span {
1047         self.span
1048     }
1049 
set_span(&mut self, span: Span)1050     pub fn set_span(&mut self, span: Span) {
1051         self.span = span;
1052     }
1053 
subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span>1054     pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> {
1055         #[cfg(not(span_locations))]
1056         {
1057             let _ = range;
1058             None
1059         }
1060 
1061         #[cfg(span_locations)]
1062         {
1063             use core::ops::Bound;
1064 
1065             let lo = match range.start_bound() {
1066                 Bound::Included(start) => {
1067                     let start = u32::try_from(*start).ok()?;
1068                     self.span.lo.checked_add(start)?
1069                 }
1070                 Bound::Excluded(start) => {
1071                     let start = u32::try_from(*start).ok()?;
1072                     self.span.lo.checked_add(start)?.checked_add(1)?
1073                 }
1074                 Bound::Unbounded => self.span.lo,
1075             };
1076             let hi = match range.end_bound() {
1077                 Bound::Included(end) => {
1078                     let end = u32::try_from(*end).ok()?;
1079                     self.span.lo.checked_add(end)?.checked_add(1)?
1080                 }
1081                 Bound::Excluded(end) => {
1082                     let end = u32::try_from(*end).ok()?;
1083                     self.span.lo.checked_add(end)?
1084                 }
1085                 Bound::Unbounded => self.span.hi,
1086             };
1087             if lo <= hi && hi <= self.span.hi {
1088                 Some(Span { lo, hi })
1089             } else {
1090                 None
1091             }
1092         }
1093     }
1094 }
1095 
1096 impl FromStr for Literal {
1097     type Err = LexError;
1098 
from_str(repr: &str) -> Result<Self, Self::Err>1099     fn from_str(repr: &str) -> Result<Self, Self::Err> {
1100         let mut cursor = get_cursor(repr);
1101         #[cfg(span_locations)]
1102         let lo = cursor.off;
1103 
1104         let negative = cursor.starts_with_char('-');
1105         if negative {
1106             cursor = cursor.advance(1);
1107             if !cursor.starts_with_fn(|ch| ch.is_ascii_digit()) {
1108                 return Err(LexError::call_site());
1109             }
1110         }
1111 
1112         if let Ok((rest, mut literal)) = parse::literal(cursor) {
1113             if rest.is_empty() {
1114                 if negative {
1115                     literal.repr.insert(0, '-');
1116                 }
1117                 literal.span = Span {
1118                     #[cfg(span_locations)]
1119                     lo,
1120                     #[cfg(span_locations)]
1121                     hi: rest.off,
1122                 };
1123                 return Ok(literal);
1124             }
1125         }
1126         Err(LexError::call_site())
1127     }
1128 }
1129 
1130 impl Display for Literal {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1131     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1132         Display::fmt(&self.repr, f)
1133     }
1134 }
1135 
1136 impl Debug for Literal {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1137     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1138         let mut debug = fmt.debug_struct("Literal");
1139         debug.field("lit", &format_args!("{}", self.repr));
1140         debug_span_field_if_nontrivial(&mut debug, self.span);
1141         debug.finish()
1142     }
1143 }
1144