1 //! `tt` crate defines a `TokenTree` data structure: this is the interface (both
2 //! input and output) of macros. It closely mirrors `proc_macro` crate's
5 #![warn(rust_2018_idioms, unused_lifetimes)]
11 pub use smol_str
::SmolStr
;
12 pub use text_size
::{TextRange, TextSize}
;
14 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
15 pub struct SpanData
<Anchor
, Ctx
> {
16 /// The text range of this span, relative to the anchor.
17 /// We need the anchor for incrementality, as storing absolute ranges will require
18 /// recomputation on every change in a file at all times.
21 /// The syntax context of the span.
25 impl<Anchor
: SpanAnchor
, Ctx
: SyntaxContext
> Span
for SpanData
<Anchor
, Ctx
> {
27 const DUMMY
: Self = SpanData
{
28 range
: TextRange
::empty(TextSize
::new(0)),
29 anchor
: Anchor
::DUMMY
,
34 pub trait Span
: std
::fmt
::Debug
+ Copy
+ Sized
+ Eq
{
35 // FIXME: Should not exist. Dummy spans will always be wrong if they leak somewhere. Instead,
36 // the call site or def site spans should be used in relevant places, its just that we don't
37 // expose those everywhere in the yet.
41 // FIXME: Should not exist
43 std
::fmt
::Debug
+ Copy
+ Sized
+ Eq
+ Copy
+ fmt
::Debug
+ std
::hash
::Hash
45 #[deprecated(note = "this should not exist")]
49 // FIXME: Should not exist
50 pub trait SyntaxContext
: std
::fmt
::Debug
+ Copy
+ Sized
+ Eq
{
51 #[deprecated(note = "this should not exist")]
55 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
56 pub enum TokenTree
<S
> {
60 impl_from
!(Leaf
<S
>, Subtree
<S
> for TokenTree
);
61 impl<S
: Span
> TokenTree
<S
> {
62 pub const fn empty(span
: S
) -> Self {
63 Self::Subtree(Subtree
{
64 delimiter
: Delimiter
::invisible_spanned(span
),
69 pub fn subtree_or_wrap(self) -> Subtree
<S
> {
71 TokenTree
::Leaf(_
) => {
72 Subtree { delimiter: Delimiter::DUMMY_INVISIBLE, token_trees: vec![self] }
74 TokenTree
::Subtree(s
) => s
,
77 pub fn subtree_or_wrap2(self, span
: DelimSpan
<S
>) -> Subtree
<S
> {
79 TokenTree
::Leaf(_
) => Subtree
{
80 delimiter
: Delimiter
::invisible_delim_spanned(span
),
81 token_trees
: vec
![self],
83 TokenTree
::Subtree(s
) => s
,
88 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
96 pub fn span(&self) -> &S
{
98 Leaf
::Literal(it
) => &it
.span
,
99 Leaf
::Punct(it
) => &it
.span
,
100 Leaf
::Ident(it
) => &it
.span
,
104 impl_from
!(Literal
<S
>, Punct
<S
>, Ident
<S
> for Leaf
);
106 #[derive(Clone, PartialEq, Eq, Hash)]
107 pub struct Subtree
<S
> {
108 pub delimiter
: Delimiter
<S
>,
109 pub token_trees
: Vec
<TokenTree
<S
>>,
112 impl<S
: Span
> Subtree
<S
> {
113 pub const fn empty(span
: DelimSpan
<S
>) -> Self {
114 Subtree { delimiter: Delimiter::invisible_delim_spanned(span), token_trees: vec![] }
117 pub fn visit_ids(&mut self, f
: &mut impl FnMut(S
) -> S
) {
118 self.delimiter
.open
= f(self.delimiter
.open
);
119 self.delimiter
.close
= f(self.delimiter
.close
);
120 self.token_trees
.iter_mut().for_each(|tt
| match tt
{
121 crate::TokenTree
::Leaf(leaf
) => match leaf
{
122 crate::Leaf
::Literal(it
) => it
.span
= f(it
.span
),
123 crate::Leaf
::Punct(it
) => it
.span
= f(it
.span
),
124 crate::Leaf
::Ident(it
) => it
.span
= f(it
.span
),
126 crate::TokenTree
::Subtree(s
) => s
.visit_ids(f
),
131 #[derive(Debug, Copy, Clone, PartialEq)]
132 pub struct DelimSpan
<S
> {
137 impl<S
: Span
> DelimSpan
<S
> {
138 // FIXME should not exist
139 pub const DUMMY
: Self = Self { open: S::DUMMY, close: S::DUMMY }
;
142 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
143 pub struct Delimiter
<S
> {
146 pub kind
: DelimiterKind
,
149 impl<S
: Span
> Delimiter
<S
> {
150 // FIXME should not exist
151 pub const DUMMY_INVISIBLE
: Self =
152 Self { open: S::DUMMY, close: S::DUMMY, kind: DelimiterKind::Invisible }
;
154 // FIXME should not exist
155 pub const fn dummy_invisible() -> Self {
156 Self::DUMMY_INVISIBLE
159 pub const fn invisible_spanned(span
: S
) -> Self {
160 Delimiter { open: span, close: span, kind: DelimiterKind::Invisible }
163 pub const fn invisible_delim_spanned(span
: DelimSpan
<S
>) -> Self {
164 Delimiter { open: span.open, close: span.close, kind: DelimiterKind::Invisible }
167 pub fn delim_span(&self) -> DelimSpan
<S
> {
168 DelimSpan { open: self.open, close: self.close }
172 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
173 pub enum DelimiterKind
{
180 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
181 pub struct Literal
<S
> {
186 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
187 pub struct Punct
<S
> {
189 pub spacing
: Spacing
,
193 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
199 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
200 /// Identifier or keyword. Unlike rustc, we keep "r#" prefix when it represents a raw identifier.
201 pub struct Ident
<S
> {
207 pub fn new(text
: impl Into
<SmolStr
>, span
: S
) -> Self {
208 Ident { text: text.into(), span }
212 fn print_debug_subtree
<S
: fmt
::Debug
>(
213 f
: &mut fmt
::Formatter
<'_
>,
214 subtree
: &Subtree
<S
>,
217 let align
= " ".repeat(level
);
219 let Delimiter { kind, open, close }
= &subtree
.delimiter
;
220 let aux
= match kind
{
221 DelimiterKind
::Invisible
=> format
!("$$ {:?} {:?}", open
, close
),
222 DelimiterKind
::Parenthesis
=> format
!("() {:?} {:?}", open
, close
),
223 DelimiterKind
::Brace
=> format
!("{{}} {:?} {:?}", open
, close
),
224 DelimiterKind
::Bracket
=> format
!("[] {:?} {:?}", open
, close
),
227 if subtree
.token_trees
.is_empty() {
228 write
!(f
, "{align}SUBTREE {aux}")?
;
230 writeln
!(f
, "{align}SUBTREE {aux}")?
;
231 for (idx
, child
) in subtree
.token_trees
.iter().enumerate() {
232 print_debug_token(f
, child
, level
+ 1)?
;
233 if idx
!= subtree
.token_trees
.len() - 1 {
242 fn print_debug_token
<S
: fmt
::Debug
>(
243 f
: &mut fmt
::Formatter
<'_
>,
247 let align
= " ".repeat(level
);
250 TokenTree
::Leaf(leaf
) => match leaf
{
251 Leaf
::Literal(lit
) => write
!(f
, "{}LITERAL {} {:?}", align
, lit
.text
, lit
.span
)?
,
252 Leaf
::Punct(punct
) => write
!(
254 "{}PUNCH {} [{}] {:?}",
257 if punct
.spacing
== Spacing
::Alone { "alone" }
else { "joint" }
,
260 Leaf
::Ident(ident
) => write
!(f
, "{}IDENT {} {:?}", align
, ident
.text
, ident
.span
)?
,
262 TokenTree
::Subtree(subtree
) => {
263 print_debug_subtree(f
, subtree
, level
)?
;
270 impl<S
: fmt
::Debug
> fmt
::Debug
for Subtree
<S
> {
271 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
272 print_debug_subtree(f
, self, 0)
276 impl<S
> fmt
::Display
for TokenTree
<S
> {
277 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
279 TokenTree
::Leaf(it
) => fmt
::Display
::fmt(it
, f
),
280 TokenTree
::Subtree(it
) => fmt
::Display
::fmt(it
, f
),
285 impl<S
> fmt
::Display
for Subtree
<S
> {
286 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
287 let (l
, r
) = match self.delimiter
.kind
{
288 DelimiterKind
::Parenthesis
=> ("(", ")"),
289 DelimiterKind
::Brace
=> ("{", "}"),
290 DelimiterKind
::Bracket
=> ("[", "]"),
291 DelimiterKind
::Invisible
=> ("", ""),
294 let mut needs_space
= false;
295 for tt
in &self.token_trees
{
301 TokenTree
::Leaf(Leaf
::Punct(p
)) => {
302 needs_space
= p
.spacing
== Spacing
::Alone
;
303 fmt
::Display
::fmt(p
, f
)?
;
305 tt
=> fmt
::Display
::fmt(tt
, f
)?
,
313 impl<S
> fmt
::Display
for Leaf
<S
> {
314 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
316 Leaf
::Ident(it
) => fmt
::Display
::fmt(it
, f
),
317 Leaf
::Literal(it
) => fmt
::Display
::fmt(it
, f
),
318 Leaf
::Punct(it
) => fmt
::Display
::fmt(it
, f
),
323 impl<S
> fmt
::Display
for Ident
<S
> {
324 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
325 fmt
::Display
::fmt(&self.text
, f
)
329 impl<S
> fmt
::Display
for Literal
<S
> {
330 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
331 fmt
::Display
::fmt(&self.text
, f
)
335 impl<S
> fmt
::Display
for Punct
<S
> {
336 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
337 fmt
::Display
::fmt(&self.char, f
)
342 /// Count the number of tokens recursively
343 pub fn count(&self) -> usize {
344 let children_count
= self
348 TokenTree
::Subtree(c
) => c
.count(),
349 TokenTree
::Leaf(_
) => 0,
353 self.token_trees
.len() + children_count
358 /// A simple line string used for debugging
359 pub fn as_debug_string(&self) -> String
{
360 let delim
= match self.delimiter
.kind
{
361 DelimiterKind
::Brace
=> ("{", "}"),
362 DelimiterKind
::Bracket
=> ("[", "]"),
363 DelimiterKind
::Parenthesis
=> ("(", ")"),
364 DelimiterKind
::Invisible
=> ("$", "$"),
367 let mut res
= String
::new();
368 res
.push_str(delim
.0);
370 for child
in &self.token_trees
{
371 let s
= match child
{
372 TokenTree
::Leaf(it
) => {
374 Leaf
::Literal(it
) => it
.text
.to_string(),
375 Leaf
::Punct(it
) => it
.char.to_string(),
376 Leaf
::Ident(it
) => it
.text
.to_string(),
379 (Leaf
::Ident(_
), Some(&TokenTree
::Leaf(Leaf
::Ident(_
)))) => {
382 (Leaf
::Punct(_
), Some(TokenTree
::Leaf(Leaf
::Punct(punct
)))) => {
383 if punct
.spacing
== Spacing
::Alone
{
392 TokenTree
::Subtree(it
) => it
.as_debug_string(),
398 res
.push_str(delim
.1);
405 pub fn pretty
<S
>(tkns
: &[TokenTree
<S
>]) -> String
{
406 fn tokentree_to_text
<S
>(tkn
: &TokenTree
<S
>) -> String
{
408 TokenTree
::Leaf(Leaf
::Ident(ident
)) => ident
.text
.clone().into(),
409 TokenTree
::Leaf(Leaf
::Literal(literal
)) => literal
.text
.clone().into(),
410 TokenTree
::Leaf(Leaf
::Punct(punct
)) => format
!("{}", punct
.char),
411 TokenTree
::Subtree(subtree
) => {
412 let content
= pretty(&subtree
.token_trees
);
413 let (open
, close
) = match subtree
.delimiter
.kind
{
414 DelimiterKind
::Brace
=> ("{", "}"),
415 DelimiterKind
::Bracket
=> ("[", "]"),
416 DelimiterKind
::Parenthesis
=> ("(", ")"),
417 DelimiterKind
::Invisible
=> ("", ""),
419 format
!("{open}{content}{close}")
425 .fold((String
::new(), true), |(last
, last_to_joint
), tkn
| {
426 let s
= [last
, tokentree_to_text(tkn
)].join(if last_to_joint { "" }
else { " " }
);
427 let mut is_joint
= false;
428 if let TokenTree
::Leaf(Leaf
::Punct(punct
)) = tkn
{
429 if punct
.spacing
== Spacing
::Joint
{