Group function definition parameters with return type annotations (#6410)

## Summary

This PR removes the group around function definition parameters, instead
grouping the parameters with the type parameters and return type
annotation.

This increases Zulip's similarity score from 0.99385 to 0.99699, so it's
a meaningful improvement. However, there's at least one stability error
that I'm working on, and I'm really just looking for high-level feedback
at this point, because I'm not happy with the solution.

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

## Test Plan

Before:

- `zulip`: 0.99396
- `django`: 0.99784
- `warehouse`: 0.99578
- `build`: 0.75436
- `transformers`: 0.99407
- `cpython`: 0.75987
- `typeshed`: 0.74432

After:

- `zulip`: 0.99702
- `django`: 0.99784
- `warehouse`: 0.99585
- `build`: 0.75623
- `transformers`: 0.99470
- `cpython`: 0.75988
- `typeshed`: 0.74853
This commit is contained in:
Charlie Marsh 2023-08-09 08:13:58 -04:00 committed by GitHub
parent eaada0345c
commit 3bf1c66cda
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 147 additions and 27 deletions

View file

@ -409,3 +409,29 @@ def double(a: int) -> ( # Hello
def double(a: int) -> ( # Hello def double(a: int) -> ( # Hello
): ):
return 2*a return 2*a
# Breaking over parameters and return types. (Black adds a trailing comma when the
# function arguments break here with a single argument; we do not.)
def f(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
...
def f(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, a) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
...
def f(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) -> a:
...
def f(a) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
...
def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]() -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
...
def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]() -> a:
...
def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa](aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
...
def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa](aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) -> a:
...

View file

@ -7,14 +7,15 @@ use ruff_python_trivia::{SimpleToken, SimpleTokenKind, SimpleTokenizer};
use ruff_text_size::{TextRange, TextSize}; use ruff_text_size::{TextRange, TextSize};
use crate::comments::{ use crate::comments::{
leading_comments, leading_node_comments, trailing_comments, CommentLinePosition, SourceComment, dangling_open_parenthesis_comments, leading_comments, leading_node_comments, trailing_comments,
CommentLinePosition, SourceComment,
}; };
use crate::context::{NodeLevel, WithNodeLevel}; use crate::context::{NodeLevel, WithNodeLevel};
use crate::expression::parentheses::{empty_parenthesized, parenthesized}; use crate::expression::parentheses::empty_parenthesized;
use crate::prelude::*; use crate::prelude::*;
use crate::FormatNodeRule; use crate::FormatNodeRule;
#[derive(Eq, PartialEq, Debug, Default)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
pub enum ParametersParentheses { pub enum ParametersParentheses {
/// By default, parameters will always preserve their surrounding parentheses. /// By default, parameters will always preserve their surrounding parentheses.
#[default] #[default]
@ -246,10 +247,17 @@ impl FormatNodeRule<Parameters> for FormatParameters {
// No parameters, format any dangling comments between `()` // No parameters, format any dangling comments between `()`
write!(f, [empty_parenthesized("(", dangling, ")")]) write!(f, [empty_parenthesized("(", dangling, ")")])
} else { } else {
// Intentionally avoid `parenthesized`, which groups the entire formatted contents.
// We want parameters to be grouped alongside return types, one level up, so we
// format them "inline" here.
write!( write!(
f, f,
[parenthesized("(", &group(&format_inner), ")") [
.with_dangling_comments(parenthesis_dangling)] text("("),
dangling_open_parenthesis_comments(parenthesis_dangling),
soft_block_indent(&group(&format_inner)),
text(")")
]
) )
} }
} }

View file

@ -58,24 +58,28 @@ impl FormatNodeRule<StmtFunctionDef> for FormatStmtFunctionDef {
write!(f, [type_params.format()])?; write!(f, [type_params.format()])?;
} }
write!(f, [item.parameters.format()])?; let format_inner = format_with(|f: &mut PyFormatter| {
write!(f, [item.parameters.format()])?;
if let Some(return_annotation) = item.returns.as_ref() { if let Some(return_annotation) = item.returns.as_ref() {
write!(f, [space(), text("->"), space()])?; write!(f, [space(), text("->"), space()])?;
if return_annotation.is_tuple_expr() { if return_annotation.is_tuple_expr() {
write!( write!(
f, f,
[return_annotation.format().with_options(Parentheses::Never)] [return_annotation.format().with_options(Parentheses::Never)]
)?; )?;
} else { } else {
write!( write!(
f, f,
[optional_parentheses( [optional_parentheses(
&return_annotation.format().with_options(Parentheses::Never), &return_annotation.format().with_options(Parentheses::Never),
)] )]
)?; )?;
}
} }
} Ok(())
});
write!(f, [group(&format_inner)])?;
write!( write!(
f, f,

View file

@ -100,18 +100,20 @@ def foo() -> tuple[int, int, int,]:
```diff ```diff
--- Black --- Black
+++ Ruff +++ Ruff
@@ -26,7 +26,9 @@ @@ -26,7 +26,11 @@
return 2 * a return 2 * a
-def double(a: int) -> int: # Hello -def double(a: int) -> int: # Hello
+def double(a: int) -> ( +def double(
+ a: int
+) -> (
+ int # Hello + int # Hello
+): +):
return 2 * a return 2 * a
@@ -54,7 +56,9 @@ @@ -54,7 +58,9 @@
a: int, a: int,
b: int, b: int,
c: int, c: int,
@ -155,7 +157,9 @@ def double(a: int) -> int: # Hello
return 2 * a return 2 * a
def double(a: int) -> ( def double(
a: int
) -> (
int # Hello int # Hello
): ):
return 2 * a return 2 * a

View file

@ -415,6 +415,32 @@ def double(a: int) -> ( # Hello
def double(a: int) -> ( # Hello def double(a: int) -> ( # Hello
): ):
return 2*a return 2*a
# Breaking over parameters and return types. (Black adds a trailing comma when the
# function arguments break here with a single argument; we do not.)
def f(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
...
def f(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, a) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
...
def f(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) -> a:
...
def f(a) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
...
def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]() -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
...
def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]() -> a:
...
def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa](aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
...
def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa](aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) -> a:
...
``` ```
## Output ## Output
@ -1023,9 +1049,61 @@ def double(a: int) -> int: # Hello
return 2 * a return 2 * a
def double(a: int) -> ( # Hello def double(
a: int
) -> ( # Hello
): ):
return 2 * a return 2 * a
# Breaking over parameters and return types. (Black adds a trailing comma when the
# function arguments break here with a single argument; we do not.)
def f(
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
...
def f(
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, a
) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
...
def f(
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
) -> a:
...
def f(
a
) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
...
def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]() -> (
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
):
...
def f[
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
]() -> a:
...
def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa](
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
) -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
...
def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa](
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
) -> a:
...
``` ```