|
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