@@ -529,7 +529,7 @@ impl<'ast> IntoFormat<PyFormatContext<'ast>> for Expr {
529
529
///
530
530
/// This mimics Black's [`_maybe_split_omitting_optional_parens`](https://github.com/psf/black/blob/d1248ca9beaf0ba526d265f4108836d89cf551b7/src/black/linegen.py#L746-L820)
531
531
#[ allow( clippy:: if_same_then_else) ]
532
- fn can_omit_optional_parentheses ( expr : & Expr , context : & PyFormatContext ) -> bool {
532
+ pub ( crate ) fn can_omit_optional_parentheses ( expr : & Expr , context : & PyFormatContext ) -> bool {
533
533
let mut visitor = CanOmitOptionalParenthesesVisitor :: new ( context) ;
534
534
visitor. visit_subexpression ( expr) ;
535
535
@@ -1195,3 +1195,75 @@ impl From<Operator> for OperatorPrecedence {
1195
1195
}
1196
1196
}
1197
1197
}
1198
+
1199
+ /// Returns `true` if `expr` is an expression that can be split into multiple lines.
1200
+ ///
1201
+ /// Returns `false` for expressions that are guaranteed to never split.
1202
+ pub ( crate ) fn is_splittable_expression ( expr : & Expr , context : & PyFormatContext ) -> bool {
1203
+ match expr {
1204
+ // Single token expressions. They never have any split points.
1205
+ Expr :: NamedExpr ( _)
1206
+ | Expr :: Name ( _)
1207
+ | Expr :: NumberLiteral ( _)
1208
+ | Expr :: BooleanLiteral ( _)
1209
+ | Expr :: NoneLiteral ( _)
1210
+ | Expr :: EllipsisLiteral ( _)
1211
+ | Expr :: Slice ( _)
1212
+ | Expr :: IpyEscapeCommand ( _) => false ,
1213
+
1214
+ // Expressions that insert split points when parenthesized.
1215
+ Expr :: Compare ( _)
1216
+ | Expr :: BinOp ( _)
1217
+ | Expr :: BoolOp ( _)
1218
+ | Expr :: IfExp ( _)
1219
+ | Expr :: GeneratorExp ( _)
1220
+ | Expr :: Subscript ( _)
1221
+ | Expr :: Await ( _)
1222
+ | Expr :: ListComp ( _)
1223
+ | Expr :: SetComp ( _)
1224
+ | Expr :: DictComp ( _)
1225
+ | Expr :: YieldFrom ( _) => true ,
1226
+
1227
+ // Sequence types can split if they contain at least one element.
1228
+ Expr :: Tuple ( tuple) => !tuple. elts . is_empty ( ) ,
1229
+ Expr :: Dict ( dict) => !dict. values . is_empty ( ) ,
1230
+ Expr :: Set ( set) => !set. elts . is_empty ( ) ,
1231
+ Expr :: List ( list) => !list. elts . is_empty ( ) ,
1232
+
1233
+ Expr :: UnaryOp ( unary) => is_splittable_expression ( unary. operand . as_ref ( ) , context) ,
1234
+ Expr :: Yield ( ast:: ExprYield { value, .. } ) => value. is_some ( ) ,
1235
+
1236
+ Expr :: Call ( ast:: ExprCall {
1237
+ arguments, func, ..
1238
+ } ) => {
1239
+ !arguments. is_empty ( )
1240
+ || is_expression_parenthesized (
1241
+ func. as_ref ( ) . into ( ) ,
1242
+ context. comments ( ) . ranges ( ) ,
1243
+ context. source ( ) ,
1244
+ )
1245
+ }
1246
+
1247
+ // String like literals can expand if they are implicit concatenated.
1248
+ Expr :: FString ( fstring) => fstring. value . is_implicit_concatenated ( ) ,
1249
+ Expr :: StringLiteral ( string) => string. value . is_implicit_concatenated ( ) ,
1250
+ Expr :: BytesLiteral ( bytes) => bytes. value . is_implicit_concatenated ( ) ,
1251
+
1252
+ // Expressions that have no split points per se, but they contain nested sub expressions that might expand.
1253
+ Expr :: Lambda ( ast:: ExprLambda {
1254
+ body : expression, ..
1255
+ } )
1256
+ | Expr :: Starred ( ast:: ExprStarred {
1257
+ value : expression, ..
1258
+ } )
1259
+ | Expr :: Attribute ( ast:: ExprAttribute {
1260
+ value : expression, ..
1261
+ } ) => {
1262
+ is_expression_parenthesized (
1263
+ expression. into ( ) ,
1264
+ context. comments ( ) . ranges ( ) ,
1265
+ context. source ( ) ,
1266
+ ) || is_splittable_expression ( expression. as_ref ( ) , context)
1267
+ }
1268
+ }
1269
+ }
0 commit comments