From f4ee0d736c6cc857c0941526452e73f2585f8398 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 9 Oct 2021 14:38:57 +0300 Subject: [PATCH] move tests --- crates/hir_def/src/macro_expansion_tests.rs | 79 +++++++++++++++++---- crates/mbe/src/syntax_bridge.rs | 79 --------------------- 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 8fa1f307f155..386bd4f1b561 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,10 +166,45 @@ 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( @@ -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 b6099b724da6..f3c9af1ccb4b 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)); - } -}