Clarify space_between.

To avoid `!matches!(...)`, which is hard to think about. Instead every
case now uses direct pattern matching and returns true or false.

Also add a couple of cases to the `stringify.rs` test that currently
print badly.
This commit is contained in:
Nicholas Nethercote 2023-10-31 11:25:13 +11:00
parent 9bd71afb90
commit 783d4b8b26
2 changed files with 44 additions and 30 deletions

View File

@ -146,37 +146,49 @@ pub fn print_crate<'a>(
s.s.eof() s.s.eof()
} }
/// This makes printed token streams look slightly nicer, /// Should two consecutive tokens be printed with a space between them?
/// and also addresses some specific regressions described in #63896 and #73345. ///
fn space_between(prev: &TokenTree, curr: &TokenTree) -> bool { /// Note: some old proc macros parse pretty-printed output, so changes here can
if let TokenTree::Token(token, _) = prev { /// break old code. For example:
// No space after these tokens, e.g. `x.y`, `$e` /// - #63896: `#[allow(unused,` must be printed rather than `#[allow(unused ,`
// (The carets point to `prev`.) ^ ^ /// - #73345: `#[allow(unused)] must be printed rather than `# [allow(unused)]
if matches!(token.kind, token::Dot | token::Dollar) { ///
return false; fn space_between(tt1: &TokenTree, tt2: &TokenTree) -> bool {
} use token::*;
if let token::DocComment(comment_kind, ..) = token.kind { use Delimiter::*;
return comment_kind != CommentKind::Line; use TokenTree::Delimited as Del;
} use TokenTree::Token as Tok;
}
match curr { // Each match arm has one or more examples in comments. The default is to
// No space before these tokens, e.g. `foo,`, `println!`, `x.y` // insert space between adjacent tokens, except for the cases listed in
// (The carets point to `curr`.) ^ ^ ^ // this match.
match (tt1, tt2) {
// No space after line doc comments.
(Tok(Token { kind: DocComment(CommentKind::Line, ..), .. }, _), _) => false,
// `.` + ANYTHING: `x.y`, `tup.0`
// `$` + ANYTHING: `$e`
(Tok(Token { kind: Dot | Dollar, .. }, _), _) => false,
// ANYTHING + `,`: `foo,`
// ANYTHING + `.`: `x.y`, `tup.0`
// ANYTHING + `!`: `foo! { ... }`
// //
// FIXME: having `Not` here works well for macro invocations like // FIXME: Incorrect cases:
// `println!()`, but is bad when `!` means "logical not" or "the never // - Logical not: `x =! y`, `if! x { f(); }`
// type", where the lack of space causes ugliness like this: // - Never type: `Fn() ->!`
// `Fn() ->!`, `x =! y`, `if! x { f(); }`. (_, Tok(Token { kind: Comma | Dot | Not, .. }, _)) => false,
TokenTree::Token(token, _) => !matches!(token.kind, token::Comma | token::Not | token::Dot),
// No space before parentheses if preceded by these tokens, e.g. `foo(...)` // IDENT + `(`: `f(3)`
TokenTree::Delimited(_, Delimiter::Parenthesis, _) => { //
!matches!(prev, TokenTree::Token(Token { kind: token::Ident(..), .. }, _)) // FIXME: Incorrect cases:
} // - Let: `let(a, b) = (1, 2)`
// No space before brackets if preceded by these tokens, e.g. `#[...]` (Tok(Token { kind: Ident(..), .. }, _), Del(_, Parenthesis, _)) => false,
TokenTree::Delimited(_, Delimiter::Bracket, _) => {
!matches!(prev, TokenTree::Token(Token { kind: token::Pound, .. }, _)) // `#` + `[`: `#[attr]`
} (Tok(Token { kind: Pound, .. }, _), Del(_, Bracket, _)) => false,
TokenTree::Delimited(..) => true,
_ => true,
} }
} }

View File

@ -115,6 +115,7 @@ fn test_expr() {
"a + b * c - d + -1 * -2 - -3", "a + b * c - d + -1 * -2 - -3",
"a + b * c - d + - 1 * - 2 - - 3" "a + b * c - d + - 1 * - 2 - - 3"
); );
c2!(expr, [ x = !y ], "x = !y", "x =! y"); // FIXME
// ExprKind::Unary // ExprKind::Unary
c2!(expr, [ *expr ], "*expr", "* expr"); c2!(expr, [ *expr ], "*expr", "* expr");
@ -137,6 +138,7 @@ fn test_expr() {
// ExprKind::If // ExprKind::If
c1!(expr, [ if true {} ], "if true {}"); c1!(expr, [ if true {} ], "if true {}");
c2!(expr, [ if !true {} ], "if !true {}", "if! true {}"); // FIXME
c2!(expr, c2!(expr,
[ if ::std::blah() { } else { } ], [ if ::std::blah() { } else { } ],
"if ::std::blah() {} else {}", "if ::std::blah() {} else {}",