• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     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 {
_new(string: &str, raw: bool, span: Span) -> Self758     fn _new(string: &str, raw: bool, span: Span) -> Self {
759         validate_ident(string, raw);
760 
761         Ident {
762             sym: string.to_owned(),
763             span,
764             raw,
765         }
766     }
767 
new(string: &str, span: Span) -> Self768     pub fn new(string: &str, span: Span) -> Self {
769         Ident::_new(string, false, span)
770     }
771 
new_raw(string: &str, span: Span) -> Self772     pub fn new_raw(string: &str, span: Span) -> Self {
773         Ident::_new(string, true, span)
774     }
775 
span(&self) -> Span776     pub fn span(&self) -> Span {
777         self.span
778     }
779 
set_span(&mut self, span: Span)780     pub fn set_span(&mut self, span: Span) {
781         self.span = span;
782     }
783 }
784 
is_ident_start(c: char) -> bool785 pub(crate) fn is_ident_start(c: char) -> bool {
786     c == '_' || unicode_ident::is_xid_start(c)
787 }
788 
is_ident_continue(c: char) -> bool789 pub(crate) fn is_ident_continue(c: char) -> bool {
790     unicode_ident::is_xid_continue(c)
791 }
792 
validate_ident(string: &str, raw: bool)793 fn validate_ident(string: &str, raw: bool) {
794     if string.is_empty() {
795         panic!("Ident is not allowed to be empty; use Option<Ident>");
796     }
797 
798     if string.bytes().all(|digit| b'0' <= digit && digit <= b'9') {
799         panic!("Ident cannot be a number; use Literal instead");
800     }
801 
802     fn ident_ok(string: &str) -> bool {
803         let mut chars = string.chars();
804         let first = chars.next().unwrap();
805         if !is_ident_start(first) {
806             return false;
807         }
808         for ch in chars {
809             if !is_ident_continue(ch) {
810                 return false;
811             }
812         }
813         true
814     }
815 
816     if !ident_ok(string) {
817         panic!("{:?} is not a valid Ident", string);
818     }
819 
820     if raw {
821         match string {
822             "_" | "super" | "self" | "Self" | "crate" => {
823                 panic!("`r#{}` cannot be a raw identifier", string);
824             }
825             _ => {}
826         }
827     }
828 }
829 
830 impl PartialEq for Ident {
eq(&self, other: &Ident) -> bool831     fn eq(&self, other: &Ident) -> bool {
832         self.sym == other.sym && self.raw == other.raw
833     }
834 }
835 
836 impl<T> PartialEq<T> for Ident
837 where
838     T: ?Sized + AsRef<str>,
839 {
eq(&self, other: &T) -> bool840     fn eq(&self, other: &T) -> bool {
841         let other = other.as_ref();
842         if self.raw {
843             other.starts_with("r#") && self.sym == other[2..]
844         } else {
845             self.sym == other
846         }
847     }
848 }
849 
850 impl Display for Ident {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result851     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
852         if self.raw {
853             f.write_str("r#")?;
854         }
855         Display::fmt(&self.sym, f)
856     }
857 }
858 
859 #[allow(clippy::missing_fields_in_debug)]
860 impl Debug for Ident {
861     // Ident(proc_macro), Ident(r#union)
862     #[cfg(not(span_locations))]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result863     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
864         let mut debug = f.debug_tuple("Ident");
865         debug.field(&format_args!("{}", self));
866         debug.finish()
867     }
868 
869     // Ident {
870     //     sym: proc_macro,
871     //     span: bytes(128..138)
872     // }
873     #[cfg(span_locations)]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result874     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
875         let mut debug = f.debug_struct("Ident");
876         debug.field("sym", &format_args!("{}", self));
877         debug_span_field_if_nontrivial(&mut debug, self.span);
878         debug.finish()
879     }
880 }
881 
882 #[derive(Clone)]
883 pub(crate) struct Literal {
884     repr: String,
885     span: Span,
886 }
887 
888 macro_rules! suffixed_numbers {
889     ($($name:ident => $kind:ident,)*) => ($(
890         pub fn $name(n: $kind) -> Literal {
891             Literal::_new(format!(concat!("{}", stringify!($kind)), n))
892         }
893     )*)
894 }
895 
896 macro_rules! unsuffixed_numbers {
897     ($($name:ident => $kind:ident,)*) => ($(
898         pub fn $name(n: $kind) -> Literal {
899             Literal::_new(n.to_string())
900         }
901     )*)
902 }
903 
904 impl Literal {
_new(repr: String) -> Self905     pub(crate) fn _new(repr: String) -> Self {
906         Literal {
907             repr,
908             span: Span::call_site(),
909         }
910     }
911 
from_str_unchecked(repr: &str) -> Self912     pub(crate) unsafe fn from_str_unchecked(repr: &str) -> Self {
913         Literal::_new(repr.to_owned())
914     }
915 
916     suffixed_numbers! {
917         u8_suffixed => u8,
918         u16_suffixed => u16,
919         u32_suffixed => u32,
920         u64_suffixed => u64,
921         u128_suffixed => u128,
922         usize_suffixed => usize,
923         i8_suffixed => i8,
924         i16_suffixed => i16,
925         i32_suffixed => i32,
926         i64_suffixed => i64,
927         i128_suffixed => i128,
928         isize_suffixed => isize,
929 
930         f32_suffixed => f32,
931         f64_suffixed => f64,
932     }
933 
934     unsuffixed_numbers! {
935         u8_unsuffixed => u8,
936         u16_unsuffixed => u16,
937         u32_unsuffixed => u32,
938         u64_unsuffixed => u64,
939         u128_unsuffixed => u128,
940         usize_unsuffixed => usize,
941         i8_unsuffixed => i8,
942         i16_unsuffixed => i16,
943         i32_unsuffixed => i32,
944         i64_unsuffixed => i64,
945         i128_unsuffixed => i128,
946         isize_unsuffixed => isize,
947     }
948 
f32_unsuffixed(f: f32) -> Literal949     pub fn f32_unsuffixed(f: f32) -> Literal {
950         let mut s = f.to_string();
951         if !s.contains('.') {
952             s.push_str(".0");
953         }
954         Literal::_new(s)
955     }
956 
f64_unsuffixed(f: f64) -> Literal957     pub fn f64_unsuffixed(f: f64) -> Literal {
958         let mut s = f.to_string();
959         if !s.contains('.') {
960             s.push_str(".0");
961         }
962         Literal::_new(s)
963     }
964 
string(t: &str) -> Literal965     pub fn string(t: &str) -> Literal {
966         let mut repr = String::with_capacity(t.len() + 2);
967         repr.push('"');
968         let mut chars = t.chars();
969         while let Some(ch) = chars.next() {
970             if ch == '\0' {
971                 repr.push_str(
972                     if chars
973                         .as_str()
974                         .starts_with(|next| '0' <= next && next <= '7')
975                     {
976                         // circumvent clippy::octal_escapes lint
977                         "\\x00"
978                     } else {
979                         "\\0"
980                     },
981                 );
982             } else if ch == '\'' {
983                 // escape_debug turns this into "\'" which is unnecessary.
984                 repr.push(ch);
985             } else {
986                 repr.extend(ch.escape_debug());
987             }
988         }
989         repr.push('"');
990         Literal::_new(repr)
991     }
992 
character(t: char) -> Literal993     pub fn character(t: char) -> Literal {
994         let mut repr = String::new();
995         repr.push('\'');
996         if t == '"' {
997             // escape_debug turns this into '\"' which is unnecessary.
998             repr.push(t);
999         } else {
1000             repr.extend(t.escape_debug());
1001         }
1002         repr.push('\'');
1003         Literal::_new(repr)
1004     }
1005 
byte_string(bytes: &[u8]) -> Literal1006     pub fn byte_string(bytes: &[u8]) -> Literal {
1007         let mut escaped = "b\"".to_string();
1008         let mut bytes = bytes.iter();
1009         while let Some(&b) = bytes.next() {
1010             #[allow(clippy::match_overlapping_arm)]
1011             match b {
1012                 b'\0' => escaped.push_str(match bytes.as_slice().first() {
1013                     // circumvent clippy::octal_escapes lint
1014                     Some(b'0'..=b'7') => r"\x00",
1015                     _ => r"\0",
1016                 }),
1017                 b'\t' => escaped.push_str(r"\t"),
1018                 b'\n' => escaped.push_str(r"\n"),
1019                 b'\r' => escaped.push_str(r"\r"),
1020                 b'"' => escaped.push_str("\\\""),
1021                 b'\\' => escaped.push_str("\\\\"),
1022                 b'\x20'..=b'\x7E' => escaped.push(b as char),
1023                 _ => {
1024                     let _ = write!(escaped, "\\x{:02X}", b);
1025                 }
1026             }
1027         }
1028         escaped.push('"');
1029         Literal::_new(escaped)
1030     }
1031 
span(&self) -> Span1032     pub fn span(&self) -> Span {
1033         self.span
1034     }
1035 
set_span(&mut self, span: Span)1036     pub fn set_span(&mut self, span: Span) {
1037         self.span = span;
1038     }
1039 
subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span>1040     pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> {
1041         #[cfg(not(span_locations))]
1042         {
1043             let _ = range;
1044             None
1045         }
1046 
1047         #[cfg(span_locations)]
1048         {
1049             use core::ops::Bound;
1050 
1051             let lo = match range.start_bound() {
1052                 Bound::Included(start) => {
1053                     let start = u32::try_from(*start).ok()?;
1054                     self.span.lo.checked_add(start)?
1055                 }
1056                 Bound::Excluded(start) => {
1057                     let start = u32::try_from(*start).ok()?;
1058                     self.span.lo.checked_add(start)?.checked_add(1)?
1059                 }
1060                 Bound::Unbounded => self.span.lo,
1061             };
1062             let hi = match range.end_bound() {
1063                 Bound::Included(end) => {
1064                     let end = u32::try_from(*end).ok()?;
1065                     self.span.lo.checked_add(end)?.checked_add(1)?
1066                 }
1067                 Bound::Excluded(end) => {
1068                     let end = u32::try_from(*end).ok()?;
1069                     self.span.lo.checked_add(end)?
1070                 }
1071                 Bound::Unbounded => self.span.hi,
1072             };
1073             if lo <= hi && hi <= self.span.hi {
1074                 Some(Span { lo, hi })
1075             } else {
1076                 None
1077             }
1078         }
1079     }
1080 }
1081 
1082 impl FromStr for Literal {
1083     type Err = LexError;
1084 
from_str(repr: &str) -> Result<Self, Self::Err>1085     fn from_str(repr: &str) -> Result<Self, Self::Err> {
1086         let mut cursor = get_cursor(repr);
1087         #[cfg(span_locations)]
1088         let lo = cursor.off;
1089 
1090         let negative = cursor.starts_with_char('-');
1091         if negative {
1092             cursor = cursor.advance(1);
1093             if !cursor.starts_with_fn(|ch| ch.is_ascii_digit()) {
1094                 return Err(LexError::call_site());
1095             }
1096         }
1097 
1098         if let Ok((rest, mut literal)) = parse::literal(cursor) {
1099             if rest.is_empty() {
1100                 if negative {
1101                     literal.repr.insert(0, '-');
1102                 }
1103                 literal.span = Span {
1104                     #[cfg(span_locations)]
1105                     lo,
1106                     #[cfg(span_locations)]
1107                     hi: rest.off,
1108                 };
1109                 return Ok(literal);
1110             }
1111         }
1112         Err(LexError::call_site())
1113     }
1114 }
1115 
1116 impl Display for Literal {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1117     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1118         Display::fmt(&self.repr, f)
1119     }
1120 }
1121 
1122 impl Debug for Literal {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1123     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1124         let mut debug = fmt.debug_struct("Literal");
1125         debug.field("lit", &format_args!("{}", self.repr));
1126         debug_span_field_if_nontrivial(&mut debug, self.span);
1127         debug.finish()
1128     }
1129 }
1130