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 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
call_site() -> Self47 fn call_site() -> Self {
48 LexError {
49 span: Span::call_site(),
50 }
51 }
52 }
53
54 impl TokenStream {
new() -> Self55 pub fn new() -> Self {
56 TokenStream { inner: Vec::new() }
57 }
58
is_empty(&self) -> bool59 pub fn is_empty(&self) -> bool {
60 self.inner.len() == 0
61 }
62
take_inner(&mut self) -> Vec<TokenTree>63 fn take_inner(&mut self) -> Vec<TokenTree> {
64 mem::replace(&mut self.inner, Vec::new())
65 }
66
push_token(&mut self, token: TokenTree)67 fn push_token(&mut self, token: TokenTree) {
68 // https://github.com/dtolnay/proc-macro2/issues/235
69 match token {
70 #[cfg(not(no_bind_by_move_pattern_guard))]
71 TokenTree::Literal(crate::Literal {
72 #[cfg(wrap_proc_macro)]
73 inner: crate::imp::Literal::Fallback(literal),
74 #[cfg(not(wrap_proc_macro))]
75 inner: literal,
76 ..
77 }) if literal.repr.starts_with('-') => {
78 push_negative_literal(self, literal);
79 }
80 #[cfg(no_bind_by_move_pattern_guard)]
81 TokenTree::Literal(crate::Literal {
82 #[cfg(wrap_proc_macro)]
83 inner: crate::imp::Literal::Fallback(literal),
84 #[cfg(not(wrap_proc_macro))]
85 inner: literal,
86 ..
87 }) => {
88 if literal.repr.starts_with('-') {
89 push_negative_literal(self, literal);
90 } else {
91 self.inner
92 .push(TokenTree::Literal(crate::Literal::_new_stable(literal)));
93 }
94 }
95 _ => self.inner.push(token),
96 }
97
98 #[cold]
99 fn push_negative_literal(stream: &mut TokenStream, mut literal: Literal) {
100 literal.repr.remove(0);
101 let mut punct = crate::Punct::new('-', Spacing::Alone);
102 punct.set_span(crate::Span::_new_stable(literal.span));
103 stream.inner.push(TokenTree::Punct(punct));
104 stream
105 .inner
106 .push(TokenTree::Literal(crate::Literal::_new_stable(literal)));
107 }
108 }
109 }
110
111 impl From<Vec<TokenTree>> for TokenStream {
from(inner: Vec<TokenTree>) -> Self112 fn from(inner: Vec<TokenTree>) -> Self {
113 TokenStream { inner }
114 }
115 }
116
117 // Nonrecursive to prevent stack overflow.
118 impl Drop for TokenStream {
drop(&mut self)119 fn drop(&mut self) {
120 while let Some(token) = self.inner.pop() {
121 let group = match token {
122 TokenTree::Group(group) => group.inner,
123 _ => continue,
124 };
125 #[cfg(wrap_proc_macro)]
126 let group = match group {
127 crate::imp::Group::Fallback(group) => group,
128 crate::imp::Group::Compiler(_) => continue,
129 };
130 let mut group = group;
131 self.inner.extend(group.stream.take_inner());
132 }
133 }
134 }
135
136 #[cfg(span_locations)]
get_cursor(src: &str) -> Cursor137 fn get_cursor(src: &str) -> Cursor {
138 // Create a dummy file & add it to the source map
139 SOURCE_MAP.with(|cm| {
140 let mut cm = cm.borrow_mut();
141 let name = format!("<parsed string {}>", cm.files.len());
142 let span = cm.add_file(&name, src);
143 Cursor {
144 rest: src,
145 off: span.lo,
146 }
147 })
148 }
149
150 #[cfg(not(span_locations))]
get_cursor(src: &str) -> Cursor151 fn get_cursor(src: &str) -> Cursor {
152 Cursor { rest: src }
153 }
154
155 impl FromStr for TokenStream {
156 type Err = LexError;
157
from_str(src: &str) -> Result<TokenStream, LexError>158 fn from_str(src: &str) -> Result<TokenStream, LexError> {
159 // Create a dummy file & add it to the source map
160 let cursor = get_cursor(src);
161
162 parse::token_stream(cursor)
163 }
164 }
165
166 impl Display for LexError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result167 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
168 f.write_str("cannot parse string into token stream")
169 }
170 }
171
172 impl Display for TokenStream {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result173 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
174 let mut joint = false;
175 for (i, tt) in self.inner.iter().enumerate() {
176 if i != 0 && !joint {
177 write!(f, " ")?;
178 }
179 joint = false;
180 match tt {
181 TokenTree::Group(tt) => Display::fmt(tt, f),
182 TokenTree::Ident(tt) => Display::fmt(tt, f),
183 TokenTree::Punct(tt) => {
184 joint = tt.spacing() == Spacing::Joint;
185 Display::fmt(tt, f)
186 }
187 TokenTree::Literal(tt) => Display::fmt(tt, f),
188 }?;
189 }
190
191 Ok(())
192 }
193 }
194
195 impl Debug for TokenStream {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result196 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
197 f.write_str("TokenStream ")?;
198 f.debug_list().entries(self.clone()).finish()
199 }
200 }
201
202 #[cfg(use_proc_macro)]
203 impl From<proc_macro::TokenStream> for TokenStream {
from(inner: proc_macro::TokenStream) -> TokenStream204 fn from(inner: proc_macro::TokenStream) -> TokenStream {
205 inner
206 .to_string()
207 .parse()
208 .expect("compiler token stream parse failed")
209 }
210 }
211
212 #[cfg(use_proc_macro)]
213 impl From<TokenStream> for proc_macro::TokenStream {
from(inner: TokenStream) -> proc_macro::TokenStream214 fn from(inner: TokenStream) -> proc_macro::TokenStream {
215 inner
216 .to_string()
217 .parse()
218 .expect("failed to parse to compiler tokens")
219 }
220 }
221
222 impl From<TokenTree> for TokenStream {
from(tree: TokenTree) -> TokenStream223 fn from(tree: TokenTree) -> TokenStream {
224 let mut stream = TokenStream::new();
225 stream.push_token(tree);
226 stream
227 }
228 }
229
230 impl FromIterator<TokenTree> for TokenStream {
from_iter<I: IntoIterator<Item = TokenTree>>(tokens: I) -> Self231 fn from_iter<I: IntoIterator<Item = TokenTree>>(tokens: I) -> Self {
232 let mut stream = TokenStream::new();
233 stream.extend(tokens);
234 stream
235 }
236 }
237
238 impl FromIterator<TokenStream> for TokenStream {
from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self239 fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
240 let mut v = Vec::new();
241
242 for mut stream in streams {
243 v.extend(stream.take_inner());
244 }
245
246 TokenStream { inner: v }
247 }
248 }
249
250 impl Extend<TokenTree> for TokenStream {
extend<I: IntoIterator<Item = TokenTree>>(&mut self, tokens: I)251 fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, tokens: I) {
252 tokens.into_iter().for_each(|token| self.push_token(token));
253 }
254 }
255
256 impl Extend<TokenStream> for TokenStream {
extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I)257 fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
258 self.inner.extend(streams.into_iter().flatten());
259 }
260 }
261
262 pub(crate) type TokenTreeIter = vec::IntoIter<TokenTree>;
263
264 impl IntoIterator for TokenStream {
265 type Item = TokenTree;
266 type IntoIter = TokenTreeIter;
267
into_iter(mut self) -> TokenTreeIter268 fn into_iter(mut self) -> TokenTreeIter {
269 self.take_inner().into_iter()
270 }
271 }
272
273 #[derive(Clone, PartialEq, Eq)]
274 pub(crate) struct SourceFile {
275 path: PathBuf,
276 }
277
278 impl SourceFile {
279 /// Get the path to this source file as a string.
path(&self) -> PathBuf280 pub fn path(&self) -> PathBuf {
281 self.path.clone()
282 }
283
is_real(&self) -> bool284 pub fn is_real(&self) -> bool {
285 // XXX(nika): Support real files in the future?
286 false
287 }
288 }
289
290 impl Debug for SourceFile {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result291 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
292 f.debug_struct("SourceFile")
293 .field("path", &self.path())
294 .field("is_real", &self.is_real())
295 .finish()
296 }
297 }
298
299 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
300 pub(crate) struct LineColumn {
301 pub line: usize,
302 pub column: usize,
303 }
304
305 #[cfg(span_locations)]
306 thread_local! {
307 static SOURCE_MAP: RefCell<SourceMap> = RefCell::new(SourceMap {
308 // NOTE: We start with a single dummy file which all call_site() and
309 // def_site() spans reference.
310 files: vec![FileInfo {
311 #[cfg(procmacro2_semver_exempt)]
312 name: "<unspecified>".to_owned(),
313 span: Span { lo: 0, hi: 0 },
314 lines: vec![0],
315 }],
316 });
317 }
318
319 #[cfg(span_locations)]
320 struct FileInfo {
321 #[cfg(procmacro2_semver_exempt)]
322 name: String,
323 span: Span,
324 lines: Vec<usize>,
325 }
326
327 #[cfg(span_locations)]
328 impl FileInfo {
offset_line_column(&self, offset: usize) -> LineColumn329 fn offset_line_column(&self, offset: usize) -> LineColumn {
330 assert!(self.span_within(Span {
331 lo: offset as u32,
332 hi: offset as u32
333 }));
334 let offset = offset - self.span.lo as usize;
335 match self.lines.binary_search(&offset) {
336 Ok(found) => LineColumn {
337 line: found + 1,
338 column: 0,
339 },
340 Err(idx) => LineColumn {
341 line: idx,
342 column: offset - self.lines[idx - 1],
343 },
344 }
345 }
346
span_within(&self, span: Span) -> bool347 fn span_within(&self, span: Span) -> bool {
348 span.lo >= self.span.lo && span.hi <= self.span.hi
349 }
350 }
351
352 /// Computes the offsets of each line in the given source string
353 /// and the total number of characters
354 #[cfg(span_locations)]
lines_offsets(s: &str) -> (usize, Vec<usize>)355 fn lines_offsets(s: &str) -> (usize, Vec<usize>) {
356 let mut lines = vec![0];
357 let mut total = 0;
358
359 for ch in s.chars() {
360 total += 1;
361 if ch == '\n' {
362 lines.push(total);
363 }
364 }
365
366 (total, lines)
367 }
368
369 #[cfg(span_locations)]
370 struct SourceMap {
371 files: Vec<FileInfo>,
372 }
373
374 #[cfg(span_locations)]
375 impl SourceMap {
next_start_pos(&self) -> u32376 fn next_start_pos(&self) -> u32 {
377 // Add 1 so there's always space between files.
378 //
379 // We'll always have at least 1 file, as we initialize our files list
380 // with a dummy file.
381 self.files.last().unwrap().span.hi + 1
382 }
383
add_file(&mut self, name: &str, src: &str) -> Span384 fn add_file(&mut self, name: &str, src: &str) -> Span {
385 let (len, lines) = lines_offsets(src);
386 let lo = self.next_start_pos();
387 // XXX(nika): Shouild we bother doing a checked cast or checked add here?
388 let span = Span {
389 lo,
390 hi: lo + (len as u32),
391 };
392
393 self.files.push(FileInfo {
394 #[cfg(procmacro2_semver_exempt)]
395 name: name.to_owned(),
396 span,
397 lines,
398 });
399
400 #[cfg(not(procmacro2_semver_exempt))]
401 let _ = name;
402
403 span
404 }
405
fileinfo(&self, span: Span) -> &FileInfo406 fn fileinfo(&self, span: Span) -> &FileInfo {
407 for file in &self.files {
408 if file.span_within(span) {
409 return file;
410 }
411 }
412 panic!("Invalid span with no related FileInfo!");
413 }
414 }
415
416 #[derive(Clone, Copy, PartialEq, Eq)]
417 pub(crate) struct Span {
418 #[cfg(span_locations)]
419 pub(crate) lo: u32,
420 #[cfg(span_locations)]
421 pub(crate) hi: u32,
422 }
423
424 impl Span {
425 #[cfg(not(span_locations))]
call_site() -> Self426 pub fn call_site() -> Self {
427 Span {}
428 }
429
430 #[cfg(span_locations)]
call_site() -> Self431 pub fn call_site() -> Self {
432 Span { lo: 0, hi: 0 }
433 }
434
435 #[cfg(not(no_hygiene))]
mixed_site() -> Self436 pub fn mixed_site() -> Self {
437 Span::call_site()
438 }
439
440 #[cfg(procmacro2_semver_exempt)]
def_site() -> Self441 pub fn def_site() -> Self {
442 Span::call_site()
443 }
444
resolved_at(&self, _other: Span) -> Span445 pub fn resolved_at(&self, _other: Span) -> Span {
446 // Stable spans consist only of line/column information, so
447 // `resolved_at` and `located_at` only select which span the
448 // caller wants line/column information from.
449 *self
450 }
451
located_at(&self, other: Span) -> Span452 pub fn located_at(&self, other: Span) -> Span {
453 other
454 }
455
456 #[cfg(procmacro2_semver_exempt)]
source_file(&self) -> SourceFile457 pub fn source_file(&self) -> SourceFile {
458 SOURCE_MAP.with(|cm| {
459 let cm = cm.borrow();
460 let fi = cm.fileinfo(*self);
461 SourceFile {
462 path: Path::new(&fi.name).to_owned(),
463 }
464 })
465 }
466
467 #[cfg(span_locations)]
start(&self) -> LineColumn468 pub fn start(&self) -> LineColumn {
469 SOURCE_MAP.with(|cm| {
470 let cm = cm.borrow();
471 let fi = cm.fileinfo(*self);
472 fi.offset_line_column(self.lo as usize)
473 })
474 }
475
476 #[cfg(span_locations)]
end(&self) -> LineColumn477 pub fn end(&self) -> LineColumn {
478 SOURCE_MAP.with(|cm| {
479 let cm = cm.borrow();
480 let fi = cm.fileinfo(*self);
481 fi.offset_line_column(self.hi as usize)
482 })
483 }
484
485 #[cfg(not(span_locations))]
join(&self, _other: Span) -> Option<Span>486 pub fn join(&self, _other: Span) -> Option<Span> {
487 Some(Span {})
488 }
489
490 #[cfg(span_locations)]
join(&self, other: Span) -> Option<Span>491 pub fn join(&self, other: Span) -> Option<Span> {
492 SOURCE_MAP.with(|cm| {
493 let cm = cm.borrow();
494 // If `other` is not within the same FileInfo as us, return None.
495 if !cm.fileinfo(*self).span_within(other) {
496 return None;
497 }
498 Some(Span {
499 lo: cmp::min(self.lo, other.lo),
500 hi: cmp::max(self.hi, other.hi),
501 })
502 })
503 }
504
505 #[cfg(not(span_locations))]
first_byte(self) -> Self506 fn first_byte(self) -> Self {
507 self
508 }
509
510 #[cfg(span_locations)]
first_byte(self) -> Self511 fn first_byte(self) -> Self {
512 Span {
513 lo: self.lo,
514 hi: cmp::min(self.lo.saturating_add(1), self.hi),
515 }
516 }
517
518 #[cfg(not(span_locations))]
last_byte(self) -> Self519 fn last_byte(self) -> Self {
520 self
521 }
522
523 #[cfg(span_locations)]
last_byte(self) -> Self524 fn last_byte(self) -> Self {
525 Span {
526 lo: cmp::max(self.hi.saturating_sub(1), self.lo),
527 hi: self.hi,
528 }
529 }
530 }
531
532 impl Debug for Span {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result533 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
534 #[cfg(span_locations)]
535 return write!(f, "bytes({}..{})", self.lo, self.hi);
536
537 #[cfg(not(span_locations))]
538 write!(f, "Span")
539 }
540 }
541
debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span)542 pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) {
543 #[cfg(span_locations)]
544 {
545 if span.lo == 0 && span.hi == 0 {
546 return;
547 }
548 }
549
550 if cfg!(span_locations) {
551 debug.field("span", &span);
552 }
553 }
554
555 #[derive(Clone)]
556 pub(crate) struct Group {
557 delimiter: Delimiter,
558 stream: TokenStream,
559 span: Span,
560 }
561
562 impl Group {
new(delimiter: Delimiter, stream: TokenStream) -> Self563 pub fn new(delimiter: Delimiter, stream: TokenStream) -> Self {
564 Group {
565 delimiter,
566 stream,
567 span: Span::call_site(),
568 }
569 }
570
delimiter(&self) -> Delimiter571 pub fn delimiter(&self) -> Delimiter {
572 self.delimiter
573 }
574
stream(&self) -> TokenStream575 pub fn stream(&self) -> TokenStream {
576 self.stream.clone()
577 }
578
span(&self) -> Span579 pub fn span(&self) -> Span {
580 self.span
581 }
582
span_open(&self) -> Span583 pub fn span_open(&self) -> Span {
584 self.span.first_byte()
585 }
586
span_close(&self) -> Span587 pub fn span_close(&self) -> Span {
588 self.span.last_byte()
589 }
590
set_span(&mut self, span: Span)591 pub fn set_span(&mut self, span: Span) {
592 self.span = span;
593 }
594 }
595
596 impl Display for Group {
597 // We attempt to match libproc_macro's formatting.
598 // Empty parens: ()
599 // Nonempty parens: (...)
600 // Empty brackets: []
601 // Nonempty brackets: [...]
602 // Empty braces: { }
603 // Nonempty braces: { ... }
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result604 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
605 let (open, close) = match self.delimiter {
606 Delimiter::Parenthesis => ("(", ")"),
607 Delimiter::Brace => ("{ ", "}"),
608 Delimiter::Bracket => ("[", "]"),
609 Delimiter::None => ("", ""),
610 };
611
612 f.write_str(open)?;
613 Display::fmt(&self.stream, f)?;
614 if self.delimiter == Delimiter::Brace && !self.stream.inner.is_empty() {
615 f.write_str(" ")?;
616 }
617 f.write_str(close)?;
618
619 Ok(())
620 }
621 }
622
623 impl Debug for Group {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result624 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
625 let mut debug = fmt.debug_struct("Group");
626 debug.field("delimiter", &self.delimiter);
627 debug.field("stream", &self.stream);
628 debug_span_field_if_nontrivial(&mut debug, self.span);
629 debug.finish()
630 }
631 }
632
633 #[derive(Clone)]
634 pub(crate) struct Ident {
635 sym: String,
636 span: Span,
637 raw: bool,
638 }
639
640 impl Ident {
_new(string: &str, raw: bool, span: Span) -> Self641 fn _new(string: &str, raw: bool, span: Span) -> Self {
642 validate_ident(string);
643
644 Ident {
645 sym: string.to_owned(),
646 span,
647 raw,
648 }
649 }
650
new(string: &str, span: Span) -> Self651 pub fn new(string: &str, span: Span) -> Self {
652 Ident::_new(string, false, span)
653 }
654
new_raw(string: &str, span: Span) -> Self655 pub fn new_raw(string: &str, span: Span) -> Self {
656 Ident::_new(string, true, span)
657 }
658
span(&self) -> Span659 pub fn span(&self) -> Span {
660 self.span
661 }
662
set_span(&mut self, span: Span)663 pub fn set_span(&mut self, span: Span) {
664 self.span = span;
665 }
666 }
667
is_ident_start(c: char) -> bool668 pub(crate) fn is_ident_start(c: char) -> bool {
669 ('a' <= c && c <= 'z')
670 || ('A' <= c && c <= 'Z')
671 || c == '_'
672 || (c > '\x7f' && UnicodeXID::is_xid_start(c))
673 }
674
is_ident_continue(c: char) -> bool675 pub(crate) fn is_ident_continue(c: char) -> bool {
676 ('a' <= c && c <= 'z')
677 || ('A' <= c && c <= 'Z')
678 || c == '_'
679 || ('0' <= c && c <= '9')
680 || (c > '\x7f' && UnicodeXID::is_xid_continue(c))
681 }
682
validate_ident(string: &str)683 fn validate_ident(string: &str) {
684 let validate = string;
685 if validate.is_empty() {
686 panic!("Ident is not allowed to be empty; use Option<Ident>");
687 }
688
689 if validate.bytes().all(|digit| digit >= b'0' && digit <= b'9') {
690 panic!("Ident cannot be a number; use Literal instead");
691 }
692
693 fn ident_ok(string: &str) -> bool {
694 let mut chars = string.chars();
695 let first = chars.next().unwrap();
696 if !is_ident_start(first) {
697 return false;
698 }
699 for ch in chars {
700 if !is_ident_continue(ch) {
701 return false;
702 }
703 }
704 true
705 }
706
707 if !ident_ok(validate) {
708 panic!("{:?} is not a valid Ident", string);
709 }
710 }
711
712 impl PartialEq for Ident {
eq(&self, other: &Ident) -> bool713 fn eq(&self, other: &Ident) -> bool {
714 self.sym == other.sym && self.raw == other.raw
715 }
716 }
717
718 impl<T> PartialEq<T> for Ident
719 where
720 T: ?Sized + AsRef<str>,
721 {
eq(&self, other: &T) -> bool722 fn eq(&self, other: &T) -> bool {
723 let other = other.as_ref();
724 if self.raw {
725 other.starts_with("r#") && self.sym == other[2..]
726 } else {
727 self.sym == other
728 }
729 }
730 }
731
732 impl Display for Ident {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result733 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
734 if self.raw {
735 f.write_str("r#")?;
736 }
737 Display::fmt(&self.sym, f)
738 }
739 }
740
741 impl Debug for Ident {
742 // Ident(proc_macro), Ident(r#union)
743 #[cfg(not(span_locations))]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result744 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
745 let mut debug = f.debug_tuple("Ident");
746 debug.field(&format_args!("{}", self));
747 debug.finish()
748 }
749
750 // Ident {
751 // sym: proc_macro,
752 // span: bytes(128..138)
753 // }
754 #[cfg(span_locations)]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result755 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
756 let mut debug = f.debug_struct("Ident");
757 debug.field("sym", &format_args!("{}", self));
758 debug_span_field_if_nontrivial(&mut debug, self.span);
759 debug.finish()
760 }
761 }
762
763 #[derive(Clone)]
764 pub(crate) struct Literal {
765 repr: String,
766 span: Span,
767 }
768
769 macro_rules! suffixed_numbers {
770 ($($name:ident => $kind:ident,)*) => ($(
771 pub fn $name(n: $kind) -> Literal {
772 Literal::_new(format!(concat!("{}", stringify!($kind)), n))
773 }
774 )*)
775 }
776
777 macro_rules! unsuffixed_numbers {
778 ($($name:ident => $kind:ident,)*) => ($(
779 pub fn $name(n: $kind) -> Literal {
780 Literal::_new(n.to_string())
781 }
782 )*)
783 }
784
785 impl Literal {
_new(repr: String) -> Self786 pub(crate) fn _new(repr: String) -> Self {
787 Literal {
788 repr,
789 span: Span::call_site(),
790 }
791 }
792
from_str_unchecked(repr: &str) -> Self793 pub(crate) unsafe fn from_str_unchecked(repr: &str) -> Self {
794 Literal::_new(repr.to_owned())
795 }
796
797 suffixed_numbers! {
798 u8_suffixed => u8,
799 u16_suffixed => u16,
800 u32_suffixed => u32,
801 u64_suffixed => u64,
802 u128_suffixed => u128,
803 usize_suffixed => usize,
804 i8_suffixed => i8,
805 i16_suffixed => i16,
806 i32_suffixed => i32,
807 i64_suffixed => i64,
808 i128_suffixed => i128,
809 isize_suffixed => isize,
810
811 f32_suffixed => f32,
812 f64_suffixed => f64,
813 }
814
815 unsuffixed_numbers! {
816 u8_unsuffixed => u8,
817 u16_unsuffixed => u16,
818 u32_unsuffixed => u32,
819 u64_unsuffixed => u64,
820 u128_unsuffixed => u128,
821 usize_unsuffixed => usize,
822 i8_unsuffixed => i8,
823 i16_unsuffixed => i16,
824 i32_unsuffixed => i32,
825 i64_unsuffixed => i64,
826 i128_unsuffixed => i128,
827 isize_unsuffixed => isize,
828 }
829
f32_unsuffixed(f: f32) -> Literal830 pub fn f32_unsuffixed(f: f32) -> Literal {
831 let mut s = f.to_string();
832 if !s.contains('.') {
833 s.push_str(".0");
834 }
835 Literal::_new(s)
836 }
837
f64_unsuffixed(f: f64) -> Literal838 pub fn f64_unsuffixed(f: f64) -> Literal {
839 let mut s = f.to_string();
840 if !s.contains('.') {
841 s.push_str(".0");
842 }
843 Literal::_new(s)
844 }
845
string(t: &str) -> Literal846 pub fn string(t: &str) -> Literal {
847 let mut repr = String::with_capacity(t.len() + 2);
848 repr.push('"');
849 for c in t.chars() {
850 if c == '\'' {
851 // escape_debug turns this into "\'" which is unnecessary.
852 repr.push(c);
853 } else {
854 repr.extend(c.escape_debug());
855 }
856 }
857 repr.push('"');
858 Literal::_new(repr)
859 }
860
character(t: char) -> Literal861 pub fn character(t: char) -> Literal {
862 let mut repr = String::new();
863 repr.push('\'');
864 if t == '"' {
865 // escape_debug turns this into '\"' which is unnecessary.
866 repr.push(t);
867 } else {
868 repr.extend(t.escape_debug());
869 }
870 repr.push('\'');
871 Literal::_new(repr)
872 }
873
byte_string(bytes: &[u8]) -> Literal874 pub fn byte_string(bytes: &[u8]) -> Literal {
875 let mut escaped = "b\"".to_string();
876 for b in bytes {
877 #[allow(clippy::match_overlapping_arm)]
878 match *b {
879 b'\0' => escaped.push_str(r"\0"),
880 b'\t' => escaped.push_str(r"\t"),
881 b'\n' => escaped.push_str(r"\n"),
882 b'\r' => escaped.push_str(r"\r"),
883 b'"' => escaped.push_str("\\\""),
884 b'\\' => escaped.push_str("\\\\"),
885 b'\x20'..=b'\x7E' => escaped.push(*b as char),
886 _ => escaped.push_str(&format!("\\x{:02X}", b)),
887 }
888 }
889 escaped.push('"');
890 Literal::_new(escaped)
891 }
892
span(&self) -> Span893 pub fn span(&self) -> Span {
894 self.span
895 }
896
set_span(&mut self, span: Span)897 pub fn set_span(&mut self, span: Span) {
898 self.span = span;
899 }
900
subspan<R: RangeBounds<usize>>(&self, _range: R) -> Option<Span>901 pub fn subspan<R: RangeBounds<usize>>(&self, _range: R) -> Option<Span> {
902 None
903 }
904 }
905
906 impl FromStr for Literal {
907 type Err = LexError;
908
from_str(mut repr: &str) -> Result<Self, Self::Err>909 fn from_str(mut repr: &str) -> Result<Self, Self::Err> {
910 let negative = repr.starts_with('-');
911 if negative {
912 repr = &repr[1..];
913 if !repr.starts_with(|ch: char| ch.is_ascii_digit()) {
914 return Err(LexError::call_site());
915 }
916 }
917 let cursor = get_cursor(repr);
918 if let Ok((_rest, mut literal)) = parse::literal(cursor) {
919 if literal.repr.len() == repr.len() {
920 if negative {
921 literal.repr.insert(0, '-');
922 }
923 return Ok(literal);
924 }
925 }
926 Err(LexError::call_site())
927 }
928 }
929
930 impl Display for Literal {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result931 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
932 Display::fmt(&self.repr, f)
933 }
934 }
935
936 impl Debug for Literal {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result937 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
938 let mut debug = fmt.debug_struct("Literal");
939 debug.field("lit", &format_args!("{}", self.repr));
940 debug_span_field_if_nontrivial(&mut debug, self.span);
941 debug.finish()
942 }
943 }
944