summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/tt
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/rust-analyzer/crates/tt')
-rw-r--r--src/tools/rust-analyzer/crates/tt/Cargo.toml10
-rw-r--r--src/tools/rust-analyzer/crates/tt/src/buffer.rs105
-rw-r--r--src/tools/rust-analyzer/crates/tt/src/lib.rs228
3 files changed, 206 insertions, 137 deletions
diff --git a/src/tools/rust-analyzer/crates/tt/Cargo.toml b/src/tools/rust-analyzer/crates/tt/Cargo.toml
index 4f2103f3a..b84693831 100644
--- a/src/tools/rust-analyzer/crates/tt/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/tt/Cargo.toml
@@ -2,9 +2,11 @@
name = "tt"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
@@ -12,4 +14,4 @@ doctest = false
[dependencies]
smol_str = "0.1.23"
-stdx = { path = "../stdx", version = "0.0.0" }
+stdx.workspace = true
diff --git a/src/tools/rust-analyzer/crates/tt/src/buffer.rs b/src/tools/rust-analyzer/crates/tt/src/buffer.rs
index d27a7aa0d..0615a3763 100644
--- a/src/tools/rust-analyzer/crates/tt/src/buffer.rs
+++ b/src/tools/rust-analyzer/crates/tt/src/buffer.rs
@@ -7,33 +7,43 @@ use crate::{Leaf, Subtree, TokenTree};
struct EntryId(usize);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-struct EntryPtr(EntryId, usize);
+struct EntryPtr(
+ /// The index of the buffer containing the entry.
+ EntryId,
+ /// The index of the entry within the buffer.
+ usize,
+);
/// Internal type which is used instead of `TokenTree` to represent a token tree
/// within a `TokenBuffer`.
#[derive(Debug)]
-enum Entry<'t> {
+enum Entry<'t, Span> {
// Mimicking types from proc-macro.
- Subtree(Option<&'t TokenTree>, &'t Subtree, EntryId),
- Leaf(&'t TokenTree),
- // End entries contain a pointer to the entry from the containing
- // token tree, or None if this is the outermost level.
+ Subtree(Option<&'t TokenTree<Span>>, &'t Subtree<Span>, EntryId),
+ Leaf(&'t TokenTree<Span>),
+ /// End entries contain a pointer to the entry from the containing
+ /// token tree, or [`None`] if this is the outermost level.
End(Option<EntryPtr>),
}
/// A token tree buffer
/// The safe version of `syn` [`TokenBuffer`](https://github.com/dtolnay/syn/blob/6533607f91686545cb034d2838beea338d9d0742/src/buffer.rs#L41)
#[derive(Debug)]
-pub struct TokenBuffer<'t> {
- buffers: Vec<Box<[Entry<'t>]>>,
+pub struct TokenBuffer<'t, Span> {
+ buffers: Vec<Box<[Entry<'t, Span>]>>,
}
-trait TokenList<'a> {
- fn entries(&self) -> (Vec<(usize, (&'a Subtree, Option<&'a TokenTree>))>, Vec<Entry<'a>>);
+trait TokenList<'a, Span> {
+ fn entries(
+ &self,
+ ) -> (Vec<(usize, (&'a Subtree<Span>, Option<&'a TokenTree<Span>>))>, Vec<Entry<'a, Span>>);
}
-impl<'a> TokenList<'a> for &'a [TokenTree] {
- fn entries(&self) -> (Vec<(usize, (&'a Subtree, Option<&'a TokenTree>))>, Vec<Entry<'a>>) {
+impl<'a, Span> TokenList<'a, Span> for &'a [TokenTree<Span>] {
+ fn entries(
+ &self,
+ ) -> (Vec<(usize, (&'a Subtree<Span>, Option<&'a TokenTree<Span>>))>, Vec<Entry<'a, Span>>)
+ {
// Must contain everything in tokens and then the Entry::End
let start_capacity = self.len() + 1;
let mut entries = Vec::with_capacity(start_capacity);
@@ -53,8 +63,11 @@ impl<'a> TokenList<'a> for &'a [TokenTree] {
}
}
-impl<'a> TokenList<'a> for &'a Subtree {
- fn entries(&self) -> (Vec<(usize, (&'a Subtree, Option<&'a TokenTree>))>, Vec<Entry<'a>>) {
+impl<'a, Span> TokenList<'a, Span> for &'a Subtree<Span> {
+ fn entries(
+ &self,
+ ) -> (Vec<(usize, (&'a Subtree<Span>, Option<&'a TokenTree<Span>>))>, Vec<Entry<'a, Span>>)
+ {
// Must contain everything in tokens and then the Entry::End
let mut entries = vec![];
let mut children = vec![];
@@ -64,25 +77,25 @@ impl<'a> TokenList<'a> for &'a Subtree {
}
}
-impl<'t> TokenBuffer<'t> {
- pub fn from_tokens(tokens: &'t [TokenTree]) -> TokenBuffer<'t> {
+impl<'t, Span> TokenBuffer<'t, Span> {
+ pub fn from_tokens(tokens: &'t [TokenTree<Span>]) -> TokenBuffer<'t, Span> {
Self::new(tokens)
}
- pub fn from_subtree(subtree: &'t Subtree) -> TokenBuffer<'t> {
+ pub fn from_subtree(subtree: &'t Subtree<Span>) -> TokenBuffer<'t, Span> {
Self::new(subtree)
}
- fn new<T: TokenList<'t>>(tokens: T) -> TokenBuffer<'t> {
+ fn new<T: TokenList<'t, Span>>(tokens: T) -> TokenBuffer<'t, Span> {
let mut buffers = vec![];
let idx = TokenBuffer::new_inner(tokens, &mut buffers, None);
assert_eq!(idx, 0);
TokenBuffer { buffers }
}
- fn new_inner<T: TokenList<'t>>(
+ fn new_inner<T: TokenList<'t, Span>>(
tokens: T,
- buffers: &mut Vec<Box<[Entry<'t>]>>,
+ buffers: &mut Vec<Box<[Entry<'t, Span>]>>,
next: Option<EntryPtr>,
) -> usize {
let (children, mut entries) = tokens.entries();
@@ -105,25 +118,25 @@ impl<'t> TokenBuffer<'t> {
/// Creates a cursor referencing the first token in the buffer and able to
/// traverse until the end of the buffer.
- pub fn begin(&self) -> Cursor<'_> {
+ pub fn begin(&self) -> Cursor<'_, Span> {
Cursor::create(self, EntryPtr(EntryId(0), 0))
}
- fn entry(&self, ptr: &EntryPtr) -> Option<&Entry<'_>> {
+ fn entry(&self, ptr: &EntryPtr) -> Option<&Entry<'_, Span>> {
let id = ptr.0;
self.buffers[id.0].get(ptr.1)
}
}
#[derive(Debug)]
-pub enum TokenTreeRef<'a> {
- Subtree(&'a Subtree, Option<&'a TokenTree>),
- Leaf(&'a Leaf, &'a TokenTree),
+pub enum TokenTreeRef<'a, Span> {
+ Subtree(&'a Subtree<Span>, Option<&'a TokenTree<Span>>),
+ Leaf(&'a Leaf<Span>, &'a TokenTree<Span>),
}
-impl<'a> TokenTreeRef<'a> {
- pub fn cloned(&self) -> TokenTree {
- match &self {
+impl<'a, Span: Clone> TokenTreeRef<'a, Span> {
+ pub fn cloned(&self) -> TokenTree<Span> {
+ match self {
TokenTreeRef::Subtree(subtree, tt) => match tt {
Some(it) => (*it).clone(),
None => (*subtree).clone().into(),
@@ -135,20 +148,20 @@ impl<'a> TokenTreeRef<'a> {
/// A safe version of `Cursor` from `syn` crate <https://github.com/dtolnay/syn/blob/6533607f91686545cb034d2838beea338d9d0742/src/buffer.rs#L125>
#[derive(Copy, Clone, Debug)]
-pub struct Cursor<'a> {
- buffer: &'a TokenBuffer<'a>,
+pub struct Cursor<'a, Span> {
+ buffer: &'a TokenBuffer<'a, Span>,
ptr: EntryPtr,
}
-impl<'a> PartialEq for Cursor<'a> {
- fn eq(&self, other: &Cursor<'_>) -> bool {
+impl<'a, Span> PartialEq for Cursor<'a, Span> {
+ fn eq(&self, other: &Cursor<'_, Span>) -> bool {
self.ptr == other.ptr && std::ptr::eq(self.buffer, other.buffer)
}
}
-impl<'a> Eq for Cursor<'a> {}
+impl<'a, Span> Eq for Cursor<'a, Span> {}
-impl<'a> Cursor<'a> {
+impl<'a, Span> Cursor<'a, Span> {
/// Check whether it is eof
pub fn eof(self) -> bool {
matches!(self.buffer.entry(&self.ptr), None | Some(Entry::End(None)))
@@ -156,7 +169,7 @@ impl<'a> Cursor<'a> {
/// If the cursor is pointing at the end of a subtree, returns
/// the parent subtree
- pub fn end(self) -> Option<&'a Subtree> {
+ pub fn end(self) -> Option<&'a Subtree<Span>> {
match self.entry() {
Some(Entry::End(Some(ptr))) => {
let idx = ptr.1;
@@ -171,13 +184,13 @@ impl<'a> Cursor<'a> {
}
}
- fn entry(self) -> Option<&'a Entry<'a>> {
+ fn entry(&self) -> Option<&'a Entry<'a, Span>> {
self.buffer.entry(&self.ptr)
}
/// If the cursor is pointing at a `Subtree`, returns
/// a cursor into that subtree
- pub fn subtree(self) -> Option<Cursor<'a>> {
+ pub fn subtree(self) -> Option<Cursor<'a, Span>> {
match self.entry() {
Some(Entry::Subtree(_, _, entry_id)) => {
Some(Cursor::create(self.buffer, EntryPtr(*entry_id, 0)))
@@ -187,7 +200,7 @@ impl<'a> Cursor<'a> {
}
/// If the cursor is pointing at a `TokenTree`, returns it
- pub fn token_tree(self) -> Option<TokenTreeRef<'a>> {
+ pub fn token_tree(self) -> Option<TokenTreeRef<'a, Span>> {
match self.entry() {
Some(Entry::Leaf(tt)) => match tt {
TokenTree::Leaf(leaf) => Some(TokenTreeRef::Leaf(leaf, tt)),
@@ -198,12 +211,12 @@ impl<'a> Cursor<'a> {
}
}
- fn create(buffer: &'a TokenBuffer<'_>, ptr: EntryPtr) -> Cursor<'a> {
+ fn create(buffer: &'a TokenBuffer<'_, Span>, ptr: EntryPtr) -> Cursor<'a, Span> {
Cursor { buffer, ptr }
}
/// Bump the cursor
- pub fn bump(self) -> Cursor<'a> {
+ pub fn bump(self) -> Cursor<'a, Span> {
if let Some(Entry::End(exit)) = self.buffer.entry(&self.ptr) {
match exit {
Some(exit) => Cursor::create(self.buffer, *exit),
@@ -216,10 +229,16 @@ impl<'a> Cursor<'a> {
/// Bump the cursor, if it is a subtree, returns
/// a cursor into that subtree
- pub fn bump_subtree(self) -> Cursor<'a> {
+ pub fn bump_subtree(self) -> Cursor<'a, Span> {
match self.entry() {
- Some(Entry::Subtree(_, _, _)) => self.subtree().unwrap(),
- _ => self.bump(),
+ Some(&Entry::Subtree(_, _, entry_id)) => {
+ Cursor::create(self.buffer, EntryPtr(entry_id, 0))
+ }
+ Some(Entry::End(exit)) => match exit {
+ Some(exit) => Cursor::create(self.buffer, *exit),
+ None => self,
+ },
+ _ => Cursor::create(self.buffer, EntryPtr(self.ptr.0, self.ptr.1 + 1)),
}
}
diff --git a/src/tools/rust-analyzer/crates/tt/src/lib.rs b/src/tools/rust-analyzer/crates/tt/src/lib.rs
index 353b09fd8..b7dbc82e1 100644
--- a/src/tools/rust-analyzer/crates/tt/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/tt/src/lib.rs
@@ -16,45 +16,106 @@ pub use smol_str::SmolStr;
/// which source tokens. We do it by assigning an distinct identity to each
/// source token and making sure that identities are preserved during macro
/// expansion.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct TokenId(pub u32);
+impl fmt::Debug for TokenId {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
impl TokenId {
+ pub const UNSPECIFIED: TokenId = TokenId(!0);
pub const fn unspecified() -> TokenId {
- TokenId(!0)
+ Self::UNSPECIFIED
}
}
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum TokenTree {
- Leaf(Leaf),
- Subtree(Subtree),
-}
-impl_from!(Leaf, Subtree for TokenTree);
+pub mod token_id {
+ pub use crate::{DelimiterKind, Spacing, TokenId};
+ pub type Span = crate::TokenId;
+ pub type Subtree = crate::Subtree<Span>;
+ pub type Punct = crate::Punct<Span>;
+ pub type Delimiter = crate::Delimiter<Span>;
+ pub type Leaf = crate::Leaf<Span>;
+ pub type Ident = crate::Ident<Span>;
+ pub type Literal = crate::Literal<Span>;
+ pub type TokenTree = crate::TokenTree<Span>;
+ pub mod buffer {
+ pub type TokenBuffer<'a> = crate::buffer::TokenBuffer<'a, super::Span>;
+ pub type Cursor<'a> = crate::buffer::Cursor<'a, super::Span>;
+ pub type TokenTreeRef<'a> = crate::buffer::TokenTreeRef<'a, super::Span>;
+ }
-impl TokenTree {
- pub fn empty() -> Self {
- TokenTree::Subtree(Subtree::default())
+ impl Delimiter {
+ pub const UNSPECIFIED: Self = Self {
+ open: TokenId::UNSPECIFIED,
+ close: TokenId::UNSPECIFIED,
+ kind: DelimiterKind::Invisible,
+ };
+ pub const fn unspecified() -> Self {
+ Self::UNSPECIFIED
+ }
+ }
+ impl Subtree {
+ pub const fn empty() -> Self {
+ Subtree { delimiter: Delimiter::unspecified(), token_trees: vec![] }
+ }
+ }
+ impl TokenTree {
+ pub const fn empty() -> Self {
+ Self::Subtree(Subtree { delimiter: Delimiter::unspecified(), token_trees: vec![] })
+ }
}
}
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct SyntaxContext(pub u32);
+
+// #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+// pub struct Span {
+// pub id: TokenId,
+// pub ctx: SyntaxContext,
+// }
+// pub type Span = (TokenId, SyntaxContext);
+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum Leaf {
- Literal(Literal),
- Punct(Punct),
- Ident(Ident),
+pub enum TokenTree<Span> {
+ Leaf(Leaf<Span>),
+ Subtree(Subtree<Span>),
}
-impl_from!(Literal, Punct, Ident for Leaf);
+impl_from!(Leaf<Span>, Subtree<Span> for TokenTree);
-#[derive(Clone, PartialEq, Eq, Hash, Default)]
-pub struct Subtree {
- pub delimiter: Option<Delimiter>,
- pub token_trees: Vec<TokenTree>,
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum Leaf<Span> {
+ Literal(Literal<Span>),
+ Punct(Punct<Span>),
+ Ident(Ident<Span>),
+}
+
+impl<Span> Leaf<Span> {
+ pub fn span(&self) -> &Span {
+ match self {
+ Leaf::Literal(it) => &it.span,
+ Leaf::Punct(it) => &it.span,
+ Leaf::Ident(it) => &it.span,
+ }
+ }
+}
+impl_from!(Literal<Span>, Punct<Span>, Ident<Span> for Leaf);
+
+#[derive(Clone, PartialEq, Eq, Hash)]
+pub struct Subtree<Span> {
+ // FIXME, this should not be Option
+ pub delimiter: Delimiter<Span>,
+ pub token_trees: Vec<TokenTree<Span>>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub struct Delimiter {
- pub id: TokenId,
+pub struct Delimiter<Span> {
+ pub open: Span,
+ pub close: Span,
pub kind: DelimiterKind,
}
@@ -63,19 +124,20 @@ pub enum DelimiterKind {
Parenthesis,
Brace,
Bracket,
+ Invisible,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Literal {
+pub struct Literal<Span> {
pub text: SmolStr,
- pub id: TokenId,
+ pub span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct Punct {
+pub struct Punct<Span> {
pub char: char,
pub spacing: Spacing,
- pub id: TokenId,
+ pub span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -85,39 +147,25 @@ pub enum Spacing {
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Ident {
- /// Identifier or keyword. Unlike rustc, we keep "r#" prefix when it represents a raw identifier.
+/// Identifier or keyword. Unlike rustc, we keep "r#" prefix when it represents a raw identifier.
+pub struct Ident<Span> {
pub text: SmolStr,
- pub id: TokenId,
+ pub span: Span,
}
-impl Ident {
- /// Constructor intended to be used only by proc macro server. `text` should not contain raw
- /// identifier prefix.
- pub fn new_with_is_raw(text: SmolStr, id: TokenId, is_raw: bool) -> Self {
- let text = if is_raw { SmolStr::from_iter(["r#", &text]) } else { text };
- Ident { text, id }
- }
-}
-
-impl Leaf {
- pub fn id(&self) -> TokenId {
- match self {
- Leaf::Literal(l) => l.id,
- Leaf::Punct(p) => p.id,
- Leaf::Ident(i) => i.id,
- }
- }
-}
-
-fn print_debug_subtree(f: &mut fmt::Formatter<'_>, subtree: &Subtree, level: usize) -> fmt::Result {
+fn print_debug_subtree<Span: fmt::Debug>(
+ f: &mut fmt::Formatter<'_>,
+ subtree: &Subtree<Span>,
+ level: usize,
+) -> fmt::Result {
let align = " ".repeat(level);
- let aux = match subtree.delimiter.map(|it| (it.kind, it.id.0)) {
- None => "$".to_string(),
- Some((DelimiterKind::Parenthesis, id)) => format!("() {id}"),
- Some((DelimiterKind::Brace, id)) => format!("{{}} {id}"),
- Some((DelimiterKind::Bracket, id)) => format!("[] {id}"),
+ let Delimiter { kind, open, close } = &subtree.delimiter;
+ let aux = match kind {
+ DelimiterKind::Invisible => format!("$$ {:?} {:?}", open, close),
+ DelimiterKind::Parenthesis => format!("() {:?} {:?}", open, close),
+ DelimiterKind::Brace => format!("{{}} {:?} {:?}", open, close),
+ DelimiterKind::Bracket => format!("[] {:?} {:?}", open, close),
};
if subtree.token_trees.is_empty() {
@@ -135,21 +183,25 @@ fn print_debug_subtree(f: &mut fmt::Formatter<'_>, subtree: &Subtree, level: usi
Ok(())
}
-fn print_debug_token(f: &mut fmt::Formatter<'_>, tkn: &TokenTree, level: usize) -> fmt::Result {
+fn print_debug_token<Span: fmt::Debug>(
+ f: &mut fmt::Formatter<'_>,
+ tkn: &TokenTree<Span>,
+ level: usize,
+) -> fmt::Result {
let align = " ".repeat(level);
match tkn {
TokenTree::Leaf(leaf) => match leaf {
- Leaf::Literal(lit) => write!(f, "{align}LITERAL {} {}", lit.text, lit.id.0)?,
+ Leaf::Literal(lit) => write!(f, "{}LITERAL {} {:?}", align, lit.text, lit.span)?,
Leaf::Punct(punct) => write!(
f,
- "{}PUNCH {} [{}] {}",
+ "{}PUNCH {} [{}] {:?}",
align,
punct.char,
if punct.spacing == Spacing::Alone { "alone" } else { "joint" },
- punct.id.0
+ punct.span
)?,
- Leaf::Ident(ident) => write!(f, "{align}IDENT {} {}", ident.text, ident.id.0)?,
+ Leaf::Ident(ident) => write!(f, "{}IDENT {} {:?}", align, ident.text, ident.span)?,
},
TokenTree::Subtree(subtree) => {
print_debug_subtree(f, subtree, level)?;
@@ -159,13 +211,13 @@ fn print_debug_token(f: &mut fmt::Formatter<'_>, tkn: &TokenTree, level: usize)
Ok(())
}
-impl fmt::Debug for Subtree {
+impl<Span: fmt::Debug> fmt::Debug for Subtree<Span> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
print_debug_subtree(f, self, 0)
}
}
-impl fmt::Display for TokenTree {
+impl<Span> fmt::Display for TokenTree<Span> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TokenTree::Leaf(it) => fmt::Display::fmt(it, f),
@@ -174,13 +226,13 @@ impl fmt::Display for TokenTree {
}
}
-impl fmt::Display for Subtree {
+impl<Span> fmt::Display for Subtree<Span> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let (l, r) = match self.delimiter_kind() {
- Some(DelimiterKind::Parenthesis) => ("(", ")"),
- Some(DelimiterKind::Brace) => ("{", "}"),
- Some(DelimiterKind::Bracket) => ("[", "]"),
- None => ("", ""),
+ let (l, r) = match self.delimiter.kind {
+ DelimiterKind::Parenthesis => ("(", ")"),
+ DelimiterKind::Brace => ("{", "}"),
+ DelimiterKind::Bracket => ("[", "]"),
+ DelimiterKind::Invisible => ("", ""),
};
f.write_str(l)?;
let mut needs_space = false;
@@ -202,7 +254,7 @@ impl fmt::Display for Subtree {
}
}
-impl fmt::Display for Leaf {
+impl<Span> fmt::Display for Leaf<Span> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Leaf::Ident(it) => fmt::Display::fmt(it, f),
@@ -212,25 +264,25 @@ impl fmt::Display for Leaf {
}
}
-impl fmt::Display for Ident {
+impl<Span> fmt::Display for Ident<Span> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.text, f)
}
}
-impl fmt::Display for Literal {
+impl<Span> fmt::Display for Literal<Span> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.text, f)
}
}
-impl fmt::Display for Punct {
+impl<Span> fmt::Display for Punct<Span> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.char, f)
}
}
-impl Subtree {
+impl<Span> Subtree<Span> {
/// Count the number of tokens recursively
pub fn count(&self) -> usize {
let children_count = self
@@ -244,20 +296,16 @@ impl Subtree {
self.token_trees.len() + children_count
}
-
- pub fn delimiter_kind(&self) -> Option<DelimiterKind> {
- self.delimiter.map(|it| it.kind)
- }
}
-impl Subtree {
+impl<Span> Subtree<Span> {
/// A simple line string used for debugging
pub fn as_debug_string(&self) -> String {
- let delim = match self.delimiter_kind() {
- Some(DelimiterKind::Brace) => ("{", "}"),
- Some(DelimiterKind::Bracket) => ("[", "]"),
- Some(DelimiterKind::Parenthesis) => ("(", ")"),
- None => (" ", " "),
+ let delim = match self.delimiter.kind {
+ DelimiterKind::Brace => ("{", "}"),
+ DelimiterKind::Bracket => ("[", "]"),
+ DelimiterKind::Parenthesis => ("(", ")"),
+ DelimiterKind::Invisible => ("$", "$"),
};
let mut res = String::new();
@@ -275,7 +323,7 @@ impl Subtree {
(Leaf::Ident(_), Some(&TokenTree::Leaf(Leaf::Ident(_)))) => {
" ".to_string() + &s
}
- (Leaf::Punct(_), Some(&TokenTree::Leaf(Leaf::Punct(punct)))) => {
+ (Leaf::Punct(_), Some(TokenTree::Leaf(Leaf::Punct(punct)))) => {
if punct.spacing == Spacing::Alone {
" ".to_string() + &s
} else {
@@ -298,19 +346,19 @@ impl Subtree {
pub mod buffer;
-pub fn pretty(tkns: &[TokenTree]) -> String {
- fn tokentree_to_text(tkn: &TokenTree) -> String {
+pub fn pretty<Span>(tkns: &[TokenTree<Span>]) -> String {
+ fn tokentree_to_text<Span>(tkn: &TokenTree<Span>) -> String {
match tkn {
TokenTree::Leaf(Leaf::Ident(ident)) => ident.text.clone().into(),
TokenTree::Leaf(Leaf::Literal(literal)) => literal.text.clone().into(),
TokenTree::Leaf(Leaf::Punct(punct)) => format!("{}", punct.char),
TokenTree::Subtree(subtree) => {
let content = pretty(&subtree.token_trees);
- let (open, close) = match subtree.delimiter.map(|it| it.kind) {
- None => ("", ""),
- Some(DelimiterKind::Brace) => ("{", "}"),
- Some(DelimiterKind::Parenthesis) => ("(", ")"),
- Some(DelimiterKind::Bracket) => ("[", "]"),
+ let (open, close) = match subtree.delimiter.kind {
+ DelimiterKind::Brace => ("{", "}"),
+ DelimiterKind::Bracket => ("[", "]"),
+ DelimiterKind::Parenthesis => ("(", ")"),
+ DelimiterKind::Invisible => ("", ""),
};
format!("{open}{content}{close}")
}