]> git.lizzy.rs Git - rust.git/blobdiff - crates/tt/src/lib.rs
add expand log
[rust.git] / crates / tt / src / lib.rs
index 7c796f5645dc6531fb201852c0f3d60c68a891eb..9d9a01e30a9a2d821a0f1294cfc47a345d7ef80c 100644 (file)
@@ -1,10 +1,7 @@
 //! `tt` crate defines a `TokenTree` data structure: this is the interface (both
 //! input and output) of macros. It closely mirrors `proc_macro` crate's
 //! `TokenTree`.
-use std::{
-    fmt::{self, Debug},
-    panic::RefUnwindSafe,
-};
+use std::fmt;
 
 use stdx::impl_from;
 
@@ -139,7 +136,7 @@ fn print_debug_token(f: &mut fmt::Formatter<'_>, tkn: &TokenTree, level: usize)
     Ok(())
 }
 
-impl Debug for Subtree {
+impl fmt::Debug for Subtree {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         print_debug_subtree(f, self, 0)
     }
@@ -230,6 +227,53 @@ pub fn delimiter_kind(&self) -> Option<DelimiterKind> {
     }
 }
 
+impl Subtree {
+    /// 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 mut res = String::new();
+        res.push_str(delim.0);
+        let mut iter = self.token_trees.iter();
+        let mut last = None;
+        while let Some(child) = iter.next() {
+            let s = match child {
+                TokenTree::Leaf(it) => {
+                    let s = match it {
+                        Leaf::Literal(it) => it.text.to_string(),
+                        Leaf::Punct(it) => it.char.to_string(),
+                        Leaf::Ident(it) => it.text.to_string(),
+                    };
+                    match (it, last) {
+                        (Leaf::Ident(_), Some(&TokenTree::Leaf(Leaf::Ident(_)))) => {
+                            " ".to_string() + &s
+                        }
+                        (Leaf::Punct(_), Some(&TokenTree::Leaf(Leaf::Punct(punct)))) => {
+                            if punct.spacing == Spacing::Alone {
+                                " ".to_string() + &s
+                            } else {
+                                s
+                            }
+                        }
+                        _ => s,
+                    }
+                }
+                TokenTree::Subtree(it) => it.as_debug_string(),
+            };
+            res.push_str(&s);
+            last = Some(child);
+        }
+
+        res.push_str(delim.1);
+        res
+    }
+}
+
 pub mod buffer;
 
 #[derive(Debug, PartialEq, Eq, Clone)]
@@ -245,13 +289,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
             ExpansionError::IOError(e) => write!(f, "I/O error: {}", e),
             ExpansionError::JsonError(e) => write!(f, "JSON decoding error: {}", e),
-            ExpansionError::Unknown(e) => write!(f, "{}", e),
+            ExpansionError::Unknown(e) => e.fmt(f),
             ExpansionError::ExpansionError(e) => write!(f, "proc macro returned error: {}", e),
         }
     }
 }
-
-pub trait TokenExpander: Debug + Send + Sync + RefUnwindSafe {
-    fn expand(&self, subtree: &Subtree, attrs: Option<&Subtree>)
-        -> Result<Subtree, ExpansionError>;
-}