|
3 | 3 | //! `TokenStream`s represent syntactic objects before they are converted into ASTs.
|
4 | 4 | //! A `TokenStream` is, roughly speaking, a sequence of [`TokenTree`]s,
|
5 | 5 | //! which are themselves a single [`Token`] or a `Delimited` subsequence of tokens.
|
6 |
| -//! |
7 |
| -//! ## Ownership |
8 |
| -//! |
9 |
| -//! `TokenStream`s are persistent data structures constructed as ropes with reference |
10 |
| -//! counted-children. In general, this means that calling an operation on a `TokenStream` |
11 |
| -//! (such as `slice`) produces an entirely new `TokenStream` from the borrowed reference to |
12 |
| -//! the original. This essentially coerces `TokenStream`s into "views" of their subparts, |
13 |
| -//! and a borrowed `TokenStream` is sufficient to build an owned `TokenStream` without taking |
14 |
| -//! ownership of the original. |
15 | 6 |
|
16 | 7 | use std::borrow::Cow;
|
17 | 8 | use std::ops::Range;
|
@@ -99,17 +90,6 @@ impl TokenTree {
|
99 | 90 | }
|
100 | 91 | }
|
101 | 92 |
|
102 |
| -impl<CTX> HashStable<CTX> for TokenStream |
103 |
| -where |
104 |
| - CTX: crate::HashStableContext, |
105 |
| -{ |
106 |
| - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { |
107 |
| - for sub_tt in self.iter() { |
108 |
| - sub_tt.hash_stable(hcx, hasher); |
109 |
| - } |
110 |
| - } |
111 |
| -} |
112 |
| - |
113 | 93 | /// A lazy version of [`AttrTokenStream`], which defers creation of an actual
|
114 | 94 | /// `AttrTokenStream` until it is needed.
|
115 | 95 | #[derive(Clone)]
|
@@ -556,10 +536,6 @@ pub struct AttrsTarget {
|
556 | 536 | pub tokens: LazyAttrTokenStream,
|
557 | 537 | }
|
558 | 538 |
|
559 |
| -/// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s. |
560 |
| -#[derive(Clone, Debug, Default, Encodable, Decodable)] |
561 |
| -pub struct TokenStream(pub(crate) Arc<Vec<TokenTree>>); |
562 |
| - |
563 | 539 | /// Indicates whether a token can join with the following token to form a
|
564 | 540 | /// compound token. Used for conversions to `proc_macro::Spacing`. Also used to
|
565 | 541 | /// guide pretty-printing, which is where the `JointHidden` value (which isn't
|
@@ -620,58 +596,9 @@ pub enum Spacing {
|
620 | 596 | JointHidden,
|
621 | 597 | }
|
622 | 598 |
|
623 |
| -impl TokenStream { |
624 |
| - /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream` |
625 |
| - /// separating the two arguments with a comma for diagnostic suggestions. |
626 |
| - pub fn add_comma(&self) -> Option<(TokenStream, Span)> { |
627 |
| - // Used to suggest if a user writes `foo!(a b);` |
628 |
| - let mut suggestion = None; |
629 |
| - let mut iter = self.0.iter().enumerate().peekable(); |
630 |
| - while let Some((pos, ts)) = iter.next() { |
631 |
| - if let Some((_, next)) = iter.peek() { |
632 |
| - let sp = match (&ts, &next) { |
633 |
| - (_, TokenTree::Token(Token { kind: token::Comma, .. }, _)) => continue, |
634 |
| - ( |
635 |
| - TokenTree::Token(token_left, Spacing::Alone), |
636 |
| - TokenTree::Token(token_right, _), |
637 |
| - ) if (token_left.is_non_reserved_ident() || token_left.is_lit()) |
638 |
| - && (token_right.is_non_reserved_ident() || token_right.is_lit()) => |
639 |
| - { |
640 |
| - token_left.span |
641 |
| - } |
642 |
| - (TokenTree::Delimited(sp, ..), _) => sp.entire(), |
643 |
| - _ => continue, |
644 |
| - }; |
645 |
| - let sp = sp.shrink_to_hi(); |
646 |
| - let comma = TokenTree::token_alone(token::Comma, sp); |
647 |
| - suggestion = Some((pos, comma, sp)); |
648 |
| - } |
649 |
| - } |
650 |
| - if let Some((pos, comma, sp)) = suggestion { |
651 |
| - let mut new_stream = Vec::with_capacity(self.0.len() + 1); |
652 |
| - let parts = self.0.split_at(pos + 1); |
653 |
| - new_stream.extend_from_slice(parts.0); |
654 |
| - new_stream.push(comma); |
655 |
| - new_stream.extend_from_slice(parts.1); |
656 |
| - return Some((TokenStream::new(new_stream), sp)); |
657 |
| - } |
658 |
| - None |
659 |
| - } |
660 |
| -} |
661 |
| - |
662 |
| -impl FromIterator<TokenTree> for TokenStream { |
663 |
| - fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self { |
664 |
| - TokenStream::new(iter.into_iter().collect::<Vec<TokenTree>>()) |
665 |
| - } |
666 |
| -} |
667 |
| - |
668 |
| -impl Eq for TokenStream {} |
669 |
| - |
670 |
| -impl PartialEq<TokenStream> for TokenStream { |
671 |
| - fn eq(&self, other: &TokenStream) -> bool { |
672 |
| - self.iter().eq(other.iter()) |
673 |
| - } |
674 |
| -} |
| 599 | +/// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s. |
| 600 | +#[derive(Clone, Debug, Default, Encodable, Decodable)] |
| 601 | +pub struct TokenStream(pub(crate) Arc<Vec<TokenTree>>); |
675 | 602 |
|
676 | 603 | impl TokenStream {
|
677 | 604 | pub fn new(tts: Vec<TokenTree>) -> TokenStream {
|
@@ -847,6 +774,68 @@ impl TokenStream {
|
847 | 774 | }
|
848 | 775 | }
|
849 | 776 | }
|
| 777 | + |
| 778 | + /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream` |
| 779 | + /// separating the two arguments with a comma for diagnostic suggestions. |
| 780 | + pub fn add_comma(&self) -> Option<(TokenStream, Span)> { |
| 781 | + // Used to suggest if a user writes `foo!(a b);` |
| 782 | + let mut suggestion = None; |
| 783 | + let mut iter = self.0.iter().enumerate().peekable(); |
| 784 | + while let Some((pos, ts)) = iter.next() { |
| 785 | + if let Some((_, next)) = iter.peek() { |
| 786 | + let sp = match (&ts, &next) { |
| 787 | + (_, TokenTree::Token(Token { kind: token::Comma, .. }, _)) => continue, |
| 788 | + ( |
| 789 | + TokenTree::Token(token_left, Spacing::Alone), |
| 790 | + TokenTree::Token(token_right, _), |
| 791 | + ) if (token_left.is_non_reserved_ident() || token_left.is_lit()) |
| 792 | + && (token_right.is_non_reserved_ident() || token_right.is_lit()) => |
| 793 | + { |
| 794 | + token_left.span |
| 795 | + } |
| 796 | + (TokenTree::Delimited(sp, ..), _) => sp.entire(), |
| 797 | + _ => continue, |
| 798 | + }; |
| 799 | + let sp = sp.shrink_to_hi(); |
| 800 | + let comma = TokenTree::token_alone(token::Comma, sp); |
| 801 | + suggestion = Some((pos, comma, sp)); |
| 802 | + } |
| 803 | + } |
| 804 | + if let Some((pos, comma, sp)) = suggestion { |
| 805 | + let mut new_stream = Vec::with_capacity(self.0.len() + 1); |
| 806 | + let parts = self.0.split_at(pos + 1); |
| 807 | + new_stream.extend_from_slice(parts.0); |
| 808 | + new_stream.push(comma); |
| 809 | + new_stream.extend_from_slice(parts.1); |
| 810 | + return Some((TokenStream::new(new_stream), sp)); |
| 811 | + } |
| 812 | + None |
| 813 | + } |
| 814 | +} |
| 815 | + |
| 816 | +impl PartialEq<TokenStream> for TokenStream { |
| 817 | + fn eq(&self, other: &TokenStream) -> bool { |
| 818 | + self.iter().eq(other.iter()) |
| 819 | + } |
| 820 | +} |
| 821 | + |
| 822 | +impl Eq for TokenStream {} |
| 823 | + |
| 824 | +impl FromIterator<TokenTree> for TokenStream { |
| 825 | + fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self { |
| 826 | + TokenStream::new(iter.into_iter().collect::<Vec<TokenTree>>()) |
| 827 | + } |
| 828 | +} |
| 829 | + |
| 830 | +impl<CTX> HashStable<CTX> for TokenStream |
| 831 | +where |
| 832 | + CTX: crate::HashStableContext, |
| 833 | +{ |
| 834 | + fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { |
| 835 | + for sub_tt in self.iter() { |
| 836 | + sub_tt.hash_stable(hcx, hasher); |
| 837 | + } |
| 838 | + } |
850 | 839 | }
|
851 | 840 |
|
852 | 841 | #[derive(Clone)]
|
|
0 commit comments