Avoid expanding single-element tuple patterns (#7683)

## Summary

The formatting for tuple patterns is now intended to match that of `for`
loops:

- Always parenthesize single-element tuples.
- Don't break on the trailing comma in single-element tuples.
- For other tuples, preserve the parentheses, and insert if-breaks.

Closes https://github.com/astral-sh/ruff/issues/7681.

## Test Plan

`cargo test`
This commit is contained in:
Charlie Marsh 2023-09-27 19:57:18 -04:00 committed by GitHub
parent c8360a1333
commit 58b50a6290
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 88 additions and 8 deletions

View file

@ -501,3 +501,24 @@ match pattern_match_or:
# own line
):
...
# Single-element tuples.
match pattern:
case (a,):
pass
case (a, b):
pass
case (a, b,):
pass
case a,:
pass
case a, b:
pass
case a, b,:
pass

View file

@ -1,4 +1,4 @@
use ruff_formatter::{Format, FormatResult};
use ruff_formatter::{format_args, Format, FormatResult};
use ruff_python_ast::node::AnyNodeRef;
use ruff_python_ast::PatternMatchSequence;
use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer};
@ -20,14 +20,25 @@ impl FormatNodeRule<PatternMatchSequence> for FormatPatternMatchSequence {
let dangling = comments.dangling(item);
let sequence_type = SequenceType::from_pattern(item, f.context().source());
if patterns.is_empty() {
return match sequence_type {
SequenceType::List => empty_parenthesized("[", dangling, "]").fmt(f),
SequenceType::Tuple | SequenceType::TupleNoParens => {
empty_parenthesized("(", dangling, ")").fmt(f)
}
};
match (patterns.as_slice(), sequence_type) {
// If the sequence is empty, the parentheses with any dangling comments.
([], SequenceType::Tuple | SequenceType::TupleNoParens) => {
return empty_parenthesized("(", dangling, ")").fmt(f)
}
([], SequenceType::List) => return empty_parenthesized("[", dangling, "]").fmt(f),
// A single-element tuple should always be parenthesized, and the trailing comma
// should never cause it to expand.
([elt], SequenceType::Tuple | SequenceType::TupleNoParens) => {
return parenthesized("(", &format_args![elt.format(), token(",")], ")")
.with_dangling_comments(dangling)
.fmt(f)
}
_ => {}
}
let items = format_with(|f| {
f.join_comma_separated(range.end())
.nodes(patterns.iter())

View file

@ -507,6 +507,27 @@ match pattern_match_or:
# own line
):
...
# Single-element tuples.
match pattern:
case (a,):
pass
case (a, b):
pass
case (a, b,):
pass
case a,:
pass
case a, b:
pass
case a, b,:
pass
```
## Output
@ -1038,6 +1059,33 @@ match pattern_match_or:
# own line
):
...
# Single-element tuples.
match pattern:
case (a,):
pass
case (a, b):
pass
case (
a,
b,
):
pass
case (a,):
pass
case a, b:
pass
case (
a,
b,
):
pass
```