From 49f5fecf06a0c639b0cb33eacdbad977010b3382 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 9 Oct 2021 14:18:53 +0300 Subject: [PATCH] internal: move test --- crates/hir_def/src/macro_expansion_tests.rs | 52 +++++++++++++++++++-- crates/mbe/src/syntax_bridge.rs | 8 ---- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/crates/hir_def/src/macro_expansion_tests.rs b/crates/hir_def/src/macro_expansion_tests.rs index 8ecdbec7aef..c00795d34b1 100644 --- a/crates/hir_def/src/macro_expansion_tests.rs +++ b/crates/hir_def/src/macro_expansion_tests.rs @@ -9,13 +9,17 @@ //! write unit-tests (in fact, we used to do that), but that makes tests brittle //! and harder to understand. -use std::ops::Range; +use std::{iter, ops::Range}; use base_db::{fixture::WithFixture, SourceDatabase}; use expect_test::{expect, Expect}; use hir_expand::{db::AstDatabase, InFile, MacroFile}; use stdx::format_to; -use syntax::{ast, AstNode}; +use syntax::{ + ast, AstNode, + SyntaxKind::{self, IDENT}, + SyntaxNode, T, +}; use crate::{ db::DefDatabase, nameres::ModuleSource, resolver::HasResolver, test_db::TestDB, AsMacroCall, @@ -58,7 +62,8 @@ fn check(ra_fixture: &str, expect: Expect) { format_to!(expn_text, "/* error: {} */", err); } if let Some((parse, _token_map)) = exp.value { - format_to!(expn_text, "{}", parse.syntax_node()); + let pp = pretty_print_macro_expansion(parse.syntax_node()); + format_to!(expn_text, "{}", pp); } let range = call.syntax().text_range(); let range: Range = range.into(); @@ -68,6 +73,29 @@ fn check(ra_fixture: &str, expect: Expect) { expect.assert_eq(&expanded_text); } +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, + }; + + if needs_space { + res.push(' ') + } + prev_kind = curr_kind; + format_to!(res, "{}", token) + } + res +} + #[test] fn wrong_nesting_level() { check( @@ -105,3 +133,21 @@ fn f() { let _ = /* error: could not convert tokens */; } "#]], ) } + +#[test] +fn round_trips_compound_tokens() { + check( + r#" +macro_rules! m { + () => { type qual: ::T = qual::T; } +} +m!(); +"#, + expect![[r#" +macro_rules! m { + () => { type qual: ::T = qual::T; } +} +type qual: ::T = qual::T; + "#]], + ) +} diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs index 631eb82de7e..037881cef6e 100644 --- a/crates/mbe/src/syntax_bridge.rs +++ b/crates/mbe/src/syntax_bridge.rs @@ -822,14 +822,6 @@ mod tests { assert_eq!(tt.delimiter_kind(), Some(tt::DelimiterKind::Brace)); } - #[test] - fn test_token_tree_multi_char_punct() { - let source_file = ast::SourceFile::parse("struct Foo { a: x::Y }").ok().unwrap(); - let struct_def = source_file.syntax().descendants().find_map(ast::Struct::cast).unwrap(); - let tt = syntax_node_to_token_tree(struct_def.syntax()).0; - token_tree_to_syntax_node(&tt, ParserEntryPoint::Item).unwrap(); - } - #[test] fn test_missing_closing_delim() { let source_file = ast::SourceFile::parse("m!(x").tree();