about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir_def/src/macro_expansion_tests.rs79
-rw-r--r--crates/mbe/src/syntax_bridge.rs79
2 files changed, 66 insertions, 92 deletions
diff --git a/crates/hir_def/src/macro_expansion_tests.rs b/crates/hir_def/src/macro_expansion_tests.rs
index 8fa1f307f15..386bd4f1b56 100644
--- a/crates/hir_def/src/macro_expansion_tests.rs
+++ b/crates/hir_def/src/macro_expansion_tests.rs
@@ -16,7 +16,8 @@ use expect_test::{expect, Expect};
 use hir_expand::{db::AstDatabase, InFile, MacroFile};
 use stdx::format_to;
 use syntax::{
-    ast, AstNode,
+    ast::{self, edit::IndentLevel},
+    AstNode,
     SyntaxKind::{self, IDENT},
     SyntaxNode, T,
 };
@@ -63,6 +64,8 @@ fn check(ra_fixture: &str, expect: Expect) {
         }
         if let Some((parse, _token_map)) = exp.value {
             let pp = pretty_print_macro_expansion(parse.syntax_node());
+            let indent = IndentLevel::from_node(call.syntax());
+            let pp = reindent(indent, pp);
             format_to!(expn_text, "{}", pp);
         }
         let range = call.syntax().text_range();
@@ -73,23 +76,38 @@ fn check(ra_fixture: &str, expect: Expect) {
     expect.assert_eq(&expanded_text);
 }
 
+fn reindent(indent: IndentLevel, pp: String) -> String {
+    if !pp.contains('\n') {
+        return pp;
+    }
+    let mut lines = pp.split_inclusive('\n');
+    let mut res = lines.next().unwrap().to_string();
+    for line in lines {
+        if line.trim().is_empty() {
+            res.push_str(&line)
+        } else {
+            format_to!(res, "{}{}", indent, line)
+        }
+    }
+    res
+}
+
 fn pretty_print_macro_expansion(expn: SyntaxNode) -> String {
     let mut res = String::new();
     let mut prev_kind = SyntaxKind::EOF;
     for token in iter::successors(expn.first_token(), |t| t.next_token()) {
         let curr_kind = token.kind();
-        let needs_space = match (prev_kind, curr_kind) {
-            _ if prev_kind.is_trivia() || curr_kind.is_trivia() => false,
-            (T![=], _) | (_, T![=]) => true,
-            (IDENT, IDENT) => true,
-            (IDENT, _) => curr_kind.is_keyword(),
-            (_, IDENT) => prev_kind.is_keyword(),
-            _ => false,
+        let space = match (prev_kind, curr_kind) {
+            _ if prev_kind.is_trivia() || curr_kind.is_trivia() => "",
+            (T![=], _) | (_, T![=]) => " ",
+            (T![;], _) => "\n",
+            (IDENT, IDENT) => " ",
+            (IDENT, _) if curr_kind.is_keyword() => " ",
+            (_, IDENT) if prev_kind.is_keyword() => " ",
+            _ => "",
         };
 
-        if needs_space {
-            res.push(' ')
-        }
+        res.push_str(space);
         prev_kind = curr_kind;
         format_to!(res, "{}", token)
     }
@@ -148,11 +166,46 @@ macro_rules! m {
     () => { type qual: ::T = qual::T; }
 }
 type qual: ::T = qual::T;
-        "#]],
+"#]],
     )
 }
 
 #[test]
+fn round_trips_literals() {
+    check(
+        r#"
+macro_rules! m {
+    () => {
+        let _ = 'c';
+        let _ = 1000;
+        let _ = 12E+99_f64;
+        let _ = "rust1";
+    }
+}
+fn f() {
+    m!()
+}
+"#,
+        expect![[r#"
+macro_rules! m {
+    () => {
+        let _ = 'c';
+        let _ = 1000;
+        let _ = 12E+99_f64;
+        let _ = "rust1";
+    }
+}
+fn f() {
+    let_ = 'c';
+    let_ = 1000;
+    let_ = 12E+99_f64;
+    let_ = "rust1";
+}
+"#]],
+    );
+}
+
+#[test]
 fn broken_parenthesis_sequence() {
     check(
         r#"
@@ -168,6 +221,6 @@ macro_rules! m2 { ($x:ident) => {} }
 
 /* error: Failed to find macro definition */
 /* error: Failed to lower macro args to token tree */
-        "#]],
+"#]],
     )
 }
diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs
index b6099b724da..f3c9af1ccb4 100644
--- a/crates/mbe/src/syntax_bridge.rs
+++ b/crates/mbe/src/syntax_bridge.rs
@@ -743,82 +743,3 @@ impl<'a> TreeSink for TtTreeSink<'a> {
         self.inner.error(error, self.text_pos)
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use crate::tests::parse_macro;
-    use parser::TokenSource;
-    use syntax::{
-        ast::{make, AstNode},
-        ted,
-    };
-    use test_utils::assert_eq_text;
-
-    #[test]
-    fn convert_tt_token_source() {
-        let expansion = parse_macro(
-            r#"
-            macro_rules! literals {
-                ($i:ident) => {
-                    {
-                        let a = 'c';
-                        let c = 1000;
-                        let f = 12E+99_f64;
-                        let s = "rust1";
-                    }
-                }
-            }
-            "#,
-        )
-        .expand_tt("literals!(foo);");
-        let tts = &[expansion.into()];
-        let buffer = tt::buffer::TokenBuffer::from_tokens(tts);
-        let mut tt_src = SubtreeTokenSource::new(&buffer);
-        let mut tokens = vec![];
-        while tt_src.current().kind != EOF {
-            tokens.push((tt_src.current().kind, tt_src.text()));
-            tt_src.bump();
-        }
-
-        // [${]
-        // [let] [a] [=] ['c'] [;]
-        assert_eq!(tokens[2 + 3].1, "'c'");
-        assert_eq!(tokens[2 + 3].0, CHAR);
-        // [let] [c] [=] [1000] [;]
-        assert_eq!(tokens[2 + 5 + 3].1, "1000");
-        assert_eq!(tokens[2 + 5 + 3].0, INT_NUMBER);
-        // [let] [f] [=] [12E+99_f64] [;]
-        assert_eq!(tokens[2 + 10 + 3].1, "12E+99_f64");
-        assert_eq!(tokens[2 + 10 + 3].0, FLOAT_NUMBER);
-
-        // [let] [s] [=] ["rust1"] [;]
-        assert_eq!(tokens[2 + 15 + 3].1, "\"rust1\"");
-        assert_eq!(tokens[2 + 15 + 3].0, STRING);
-    }
-
-    #[test]
-    fn test_token_tree_last_child_is_white_space() {
-        let source_file = ast::SourceFile::parse("f!{}").ok().unwrap();
-        let macro_call = source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
-        let token_tree = macro_call.token_tree().unwrap();
-
-        // Token Tree now is :
-        // TokenTree
-        // - TokenTree
-        //   - T!['{']
-        //   - T!['}']
-
-        let token_tree = token_tree.clone_for_update();
-        ted::append_child(token_tree.syntax(), make::tokens::single_space());
-        let token_tree = token_tree.clone_subtree();
-        // Token Tree now is :
-        // TokenTree
-        // - T!['{']
-        // - T!['}']
-        // - WHITE_SPACE
-
-        let tt = syntax_node_to_token_tree(token_tree.syntax()).0;
-        assert_eq!(tt.delimiter_kind(), Some(tt::DelimiterKind::Brace));
-    }
-}