@@ -2,9 +2,13 @@ use ruff_formatter::write;
2
2
use ruff_python_ast:: StmtAnnAssign ;
3
3
4
4
use crate :: comments:: { SourceComment , SuppressionKind } ;
5
- use crate :: expression:: has_parentheses;
5
+ use crate :: expression:: parentheses:: { Parentheses , Parenthesize } ;
6
+ use crate :: expression:: { has_parentheses, is_splittable_expression, maybe_parenthesize_expression} ;
6
7
use crate :: prelude:: * ;
7
- use crate :: preview:: is_prefer_splitting_right_hand_side_of_assignments_enabled;
8
+ use crate :: preview:: {
9
+ is_parenthesize_long_type_hints_enabled,
10
+ is_prefer_splitting_right_hand_side_of_assignments_enabled,
11
+ } ;
8
12
use crate :: statement:: stmt_assign:: {
9
13
AnyAssignmentOperator , AnyBeforeOperator , FormatStatementsLastExpression ,
10
14
} ;
@@ -27,7 +31,11 @@ impl FormatNodeRule<StmtAnnAssign> for FormatStmtAnnAssign {
27
31
28
32
if let Some ( value) = value {
29
33
if is_prefer_splitting_right_hand_side_of_assignments_enabled ( f. context ( ) )
30
- && has_parentheses ( annotation, f. context ( ) ) . is_some ( )
34
+ // The `has_parentheses` check can be removed when stabilizing `is_parenthesize_long_type_hints`.
35
+ // because `is_splittable_expression` covers both.
36
+ && ( has_parentheses ( annotation, f. context ( ) ) . is_some ( )
37
+ || ( is_parenthesize_long_type_hints_enabled ( f. context ( ) )
38
+ && is_splittable_expression ( annotation, f. context ( ) ) ) )
31
39
{
32
40
FormatStatementsLastExpression :: RightToLeft {
33
41
before_operator : AnyBeforeOperator :: Expression ( annotation) ,
@@ -37,10 +45,28 @@ impl FormatNodeRule<StmtAnnAssign> for FormatStmtAnnAssign {
37
45
}
38
46
. fmt ( f) ?;
39
47
} else {
48
+ // Remove unnecessary parentheses around the annotation if the parenthesize long type hints preview style is enabled.
49
+ // Ensure we keep the parentheses if the annotation has any comments.
50
+ if is_parenthesize_long_type_hints_enabled ( f. context ( ) ) {
51
+ if f. context ( ) . comments ( ) . has_leading ( annotation. as_ref ( ) )
52
+ || f. context ( ) . comments ( ) . has_trailing ( annotation. as_ref ( ) )
53
+ {
54
+ annotation
55
+ . format ( )
56
+ . with_options ( Parentheses :: Always )
57
+ . fmt ( f) ?;
58
+ } else {
59
+ annotation
60
+ . format ( )
61
+ . with_options ( Parentheses :: Never )
62
+ . fmt ( f) ?;
63
+ }
64
+ } else {
65
+ annotation. format ( ) . fmt ( f) ?;
66
+ }
40
67
write ! (
41
68
f,
42
69
[
43
- annotation. format( ) ,
44
70
space( ) ,
45
71
token( "=" ) ,
46
72
space( ) ,
@@ -49,7 +75,19 @@ impl FormatNodeRule<StmtAnnAssign> for FormatStmtAnnAssign {
49
75
) ?;
50
76
}
51
77
} else {
52
- annotation. format ( ) . fmt ( f) ?;
78
+ // Parenthesize the value and inline the comment if it is a "simple" type annotation, similar
79
+ // to what we do with the value.
80
+ // ```python
81
+ // class Test:
82
+ // safe_age: (
83
+ // Decimal # the user's age, used to determine if it's safe for them to use ruff
84
+ // )
85
+ // ```
86
+ if is_parenthesize_long_type_hints_enabled ( f. context ( ) ) {
87
+ FormatStatementsLastExpression :: left_to_right ( annotation, item) . fmt ( f) ?;
88
+ } else {
89
+ annotation. format ( ) . fmt ( f) ?;
90
+ }
53
91
}
54
92
55
93
if f. options ( ) . source_type ( ) . is_ipynb ( )
0 commit comments