@@ -1423,104 +1423,111 @@ fn parse_array_expr<'a>(node: &'a ArrayLit, context: &mut Context<'a>) -> PrintI
1423
1423
}
1424
1424
1425
1425
fn parse_arrow_func_expr < ' a > ( node : & ' a ArrowExpr , context : & mut Context < ' a > ) -> PrintItems {
1426
- let mut items = PrintItems :: new ( ) ;
1427
- let header_start_info = Info :: new ( "arrowFunctionExpressionHeaderStart" ) ;
1428
- let should_use_parens = get_should_use_parens ( & node, context) ;
1429
-
1430
- items. push_info ( header_start_info) ;
1431
- if node. is_async ( ) {
1432
- items. push_str ( "async " ) ;
1433
- }
1434
- if let Some ( type_params) = node. type_params {
1435
- items. extend ( parse_node ( type_params. into ( ) , context) ) ;
1436
- }
1426
+ let items = parse_inner ( node, context) ;
1427
+ return if should_add_parens_around_expr ( node. into ( ) , context) {
1428
+ surround_with_parens ( items)
1429
+ } else {
1430
+ items
1431
+ } ;
1437
1432
1438
- if should_use_parens {
1439
- // need to check if there are parens because parse_parameters_or_arguments depends on the parens existing
1440
- if has_parens ( node, context) {
1441
- items. extend ( parse_parameters_or_arguments (
1442
- ParseParametersOrArgumentsOptions {
1443
- node : node. into ( ) ,
1444
- span : node. get_parameters_span ( context) ,
1445
- nodes : node. params . iter ( ) . map ( |node| node. into ( ) ) . collect ( ) ,
1446
- custom_close_paren : |context| {
1447
- Some ( parse_close_paren_with_type (
1448
- ParseCloseParenWithTypeOptions {
1449
- start_info : header_start_info,
1450
- type_node : node. return_type . map ( |x| x. into ( ) ) ,
1451
- type_node_separator : None ,
1452
- param_count : node. params . len ( ) ,
1453
- } ,
1454
- context,
1455
- ) )
1433
+ fn parse_inner < ' a > ( node : & ' a ArrowExpr , context : & mut Context < ' a > ) -> PrintItems {
1434
+ let mut items = PrintItems :: new ( ) ;
1435
+ let header_start_info = Info :: new ( "arrowFunctionExpressionHeaderStart" ) ;
1436
+ let should_use_parens = get_should_use_parens ( & node, context) ;
1437
+
1438
+ items. push_info ( header_start_info) ;
1439
+ if node. is_async ( ) {
1440
+ items. push_str ( "async " ) ;
1441
+ }
1442
+ if let Some ( type_params) = node. type_params {
1443
+ items. extend ( parse_node ( type_params. into ( ) , context) ) ;
1444
+ }
1445
+
1446
+ if should_use_parens {
1447
+ // need to check if there are parens because parse_parameters_or_arguments depends on the parens existing
1448
+ if has_parens ( node, context) {
1449
+ items. extend ( parse_parameters_or_arguments (
1450
+ ParseParametersOrArgumentsOptions {
1451
+ node : node. into ( ) ,
1452
+ span : node. get_parameters_span ( context) ,
1453
+ nodes : node. params . iter ( ) . map ( |node| node. into ( ) ) . collect ( ) ,
1454
+ custom_close_paren : |context| {
1455
+ Some ( parse_close_paren_with_type (
1456
+ ParseCloseParenWithTypeOptions {
1457
+ start_info : header_start_info,
1458
+ type_node : node. return_type . map ( |x| x. into ( ) ) ,
1459
+ type_node_separator : None ,
1460
+ param_count : node. params . len ( ) ,
1461
+ } ,
1462
+ context,
1463
+ ) )
1464
+ } ,
1465
+ is_parameters : true ,
1456
1466
} ,
1457
- is_parameters : true ,
1458
- } ,
1459
- context,
1460
- ) ) ;
1467
+ context,
1468
+ ) ) ;
1469
+ } else {
1470
+ // todo: this should probably use more of the same logic as in parse_parameters_or_arguments
1471
+ // there will only be one param in this case
1472
+ items. extend ( surround_with_parens ( parse_node ( node. params . first ( ) . unwrap ( ) . into ( ) , context) ) ) ;
1473
+ }
1461
1474
} else {
1462
- // todo: this should probably use more of the same logic as in parse_parameters_or_arguments
1463
- // there will only be one param in this case
1464
- items. push_str ( "(" ) ;
1465
1475
items. extend ( parse_node ( node. params . first ( ) . unwrap ( ) . into ( ) , context) ) ;
1466
- items. push_str ( ")" ) ;
1467
1476
}
1468
- } else {
1469
- items. extend ( parse_node ( node. params . first ( ) . unwrap ( ) . into ( ) , context) ) ;
1470
- }
1471
1477
1472
- items. push_str ( " =>" ) ;
1478
+ items. push_str ( " =>" ) ;
1473
1479
1474
- let parsed_body = parse_node ( node. body . into ( ) , context) ;
1475
- let parsed_body = if use_new_line_group_for_arrow_body ( node, context) {
1476
- new_line_group ( parsed_body)
1477
- } else {
1478
- parsed_body
1479
- }
1480
- . into_rc_path ( ) ;
1481
- let open_brace_token = match & node. body {
1482
- BlockStmtOrExpr :: BlockStmt ( stmt) => context. token_finder . get_first_open_brace_token_within ( stmt) ,
1483
- _ => None ,
1484
- } ;
1485
-
1486
- if open_brace_token. is_some ( ) {
1487
- items. extend ( parse_brace_separator (
1488
- ParseBraceSeparatorOptions {
1489
- brace_position : context. config . arrow_function_brace_position ,
1490
- open_brace_token,
1491
- start_header_info : Some ( header_start_info) ,
1492
- } ,
1493
- context,
1494
- ) ) ;
1480
+ let parsed_body = parse_node ( node. body . into ( ) , context) ;
1481
+ let parsed_body = if use_new_line_group_for_arrow_body ( node, context) {
1482
+ new_line_group ( parsed_body)
1483
+ } else {
1484
+ parsed_body
1485
+ }
1486
+ . into_rc_path ( ) ;
1487
+ let open_brace_token = match & node. body {
1488
+ BlockStmtOrExpr :: BlockStmt ( stmt) => context. token_finder . get_first_open_brace_token_within ( stmt) ,
1489
+ _ => None ,
1490
+ } ;
1495
1491
1496
- items. extend ( parsed_body. into ( ) ) ;
1497
- } else {
1498
- let start_body_info = Info :: new ( "startBody" ) ;
1499
- let end_body_info = Info :: new ( "endBody" ) ;
1500
- items. push_info ( start_body_info) ;
1492
+ if open_brace_token. is_some ( ) {
1493
+ items. extend ( parse_brace_separator (
1494
+ ParseBraceSeparatorOptions {
1495
+ brace_position : context. config . arrow_function_brace_position ,
1496
+ open_brace_token,
1497
+ start_header_info : Some ( header_start_info) ,
1498
+ } ,
1499
+ context,
1500
+ ) ) ;
1501
1501
1502
- if should_not_newline_after_arrow ( & node. body , context) {
1503
- items. push_str ( " " ) ;
1502
+ items. extend ( parsed_body. into ( ) ) ;
1504
1503
} else {
1505
- items. push_condition ( conditions:: if_above_width_or (
1506
- context. config . indent_width ,
1507
- if_true_or (
1508
- "newlineOrSpace" ,
1509
- move |context| condition_resolvers:: is_multiple_lines ( context, & start_body_info, & end_body_info) ,
1510
- Signal :: NewLine . into ( ) ,
1511
- Signal :: SpaceOrNewLine . into ( ) ,
1512
- )
1513
- . into ( ) ,
1514
- " " . into ( ) ,
1515
- ) ) ;
1504
+ let start_body_info = Info :: new ( "startBody" ) ;
1505
+ let end_body_info = Info :: new ( "endBody" ) ;
1506
+ items. push_info ( start_body_info) ;
1507
+
1508
+ if should_not_newline_after_arrow ( & node. body , context) {
1509
+ items. push_str ( " " ) ;
1510
+ } else {
1511
+ items. push_condition ( conditions:: if_above_width_or (
1512
+ context. config . indent_width ,
1513
+ if_true_or (
1514
+ "newlineOrSpace" ,
1515
+ move |context| condition_resolvers:: is_multiple_lines ( context, & start_body_info, & end_body_info) ,
1516
+ Signal :: NewLine . into ( ) ,
1517
+ Signal :: SpaceOrNewLine . into ( ) ,
1518
+ )
1519
+ . into ( ) ,
1520
+ " " . into ( ) ,
1521
+ ) ) ;
1522
+ }
1523
+
1524
+ items. push_condition ( conditions:: indent_if_start_of_line ( parsed_body. into ( ) ) ) ;
1525
+ items. push_info ( end_body_info) ;
1516
1526
}
1517
1527
1518
- items. push_condition ( conditions:: indent_if_start_of_line ( parsed_body. into ( ) ) ) ;
1519
- items. push_info ( end_body_info) ;
1528
+ items
1520
1529
}
1521
1530
1522
- return items;
1523
-
1524
1531
fn should_not_newline_after_arrow ( body : & BlockStmtOrExpr , context : & Context ) -> bool {
1525
1532
match body {
1526
1533
BlockStmtOrExpr :: BlockStmt ( _) => true ,
@@ -1898,17 +1905,15 @@ fn parse_call_expr<'a>(node: &'a CallExpr, context: &mut Context<'a>) -> PrintIt
1898
1905
1899
1906
fn parse_test_library_arguments < ' a > ( args : & [ & ' a ExprOrSpread ] , context : & mut Context < ' a > ) -> PrintItems {
1900
1907
let mut items = PrintItems :: new ( ) ;
1901
- items. push_str ( "(" ) ;
1902
1908
items. extend ( parse_node_with_inner_parse ( args[ 0 ] . into ( ) , context, |items, _| {
1903
1909
let mut new_items = parser_helpers:: with_no_new_lines ( items) ;
1904
1910
new_items. push_str ( "," ) ;
1905
1911
new_items
1906
1912
} ) ) ;
1907
1913
items. push_str ( " " ) ;
1908
1914
items. extend ( parse_node ( args[ 1 ] . into ( ) , context) ) ;
1909
- items. push_str ( ")" ) ;
1910
1915
1911
- items
1916
+ surround_with_parens ( items)
1912
1917
}
1913
1918
}
1914
1919
}
@@ -2161,7 +2166,7 @@ fn parse_expr_with_type_args<'a>(node: &'a TsExprWithTypeArgs, context: &mut Con
2161
2166
}
2162
2167
2163
2168
fn parse_fn_expr < ' a > ( node : & ' a FnExpr , context : & mut Context < ' a > ) -> PrintItems {
2164
- parse_function_decl_or_expr (
2169
+ let items = parse_function_decl_or_expr (
2165
2170
FunctionDeclOrExprNode {
2166
2171
node : node. into ( ) ,
2167
2172
is_func_decl : false ,
@@ -2170,7 +2175,55 @@ fn parse_fn_expr<'a>(node: &'a FnExpr, context: &mut Context<'a>) -> PrintItems
2170
2175
func : & node. function ,
2171
2176
} ,
2172
2177
context,
2173
- )
2178
+ ) ;
2179
+
2180
+ if should_add_parens_around_expr ( node. into ( ) , context) {
2181
+ surround_with_parens ( items)
2182
+ } else {
2183
+ items
2184
+ }
2185
+ }
2186
+
2187
+ fn should_add_parens_around_expr ( node : Node , context : & Context ) -> bool {
2188
+ let original_node = node;
2189
+ for node in node. ancestors ( ) {
2190
+ match node {
2191
+ Node :: ParenExpr ( paren_expr) => {
2192
+ if !should_skip_paren_expr ( paren_expr, context) {
2193
+ return false ;
2194
+ }
2195
+ }
2196
+ Node :: CallExpr ( call_expr) => {
2197
+ if !call_expr. callee . span ( ) . contains ( original_node. span ( ) ) {
2198
+ // it's in an argument, so don't add parens
2199
+ return false ;
2200
+ }
2201
+ }
2202
+ Node :: NewExpr ( new_expr) => {
2203
+ if !new_expr. callee . span ( ) . contains ( original_node. span ( ) ) {
2204
+ // it's in an argument, so don't add parens
2205
+ return false ;
2206
+ }
2207
+ }
2208
+ Node :: ExprStmt ( _) => return true ,
2209
+ Node :: MemberExpr ( expr) => {
2210
+ if expr. computed ( ) && expr. prop . span ( ) . contains ( original_node. span ( ) ) {
2211
+ return false ;
2212
+ }
2213
+ }
2214
+ Node :: CondExpr ( cond_expr) => {
2215
+ return cond_expr. test . span ( ) . contains ( original_node. span ( ) ) ;
2216
+ }
2217
+ Node :: OptChainExpr ( _) | Node :: BinExpr ( _) => {
2218
+ // continue searching
2219
+ }
2220
+ _ => {
2221
+ return false ;
2222
+ }
2223
+ }
2224
+ }
2225
+
2226
+ false
2174
2227
}
2175
2228
2176
2229
fn parse_getter_prop < ' a > ( node : & ' a GetterProp , context : & mut Context < ' a > ) -> PrintItems {
@@ -2270,7 +2323,7 @@ fn parse_object_lit<'a>(node: &'a ObjectLit, context: &mut Context<'a>) -> Print
2270
2323
}
2271
2324
2272
2325
fn parse_paren_expr < ' a > ( node : & ' a ParenExpr , context : & mut Context < ' a > ) -> PrintItems {
2273
- if skip_paren_expr ( node, context) {
2326
+ if should_skip_paren_expr ( node, context) {
2274
2327
return parse_node ( node. expr . into ( ) , context) ;
2275
2328
}
2276
2329
@@ -2299,35 +2352,51 @@ fn parse_paren_expr<'a>(node: &'a ParenExpr, context: &mut Context<'a>) -> Print
2299
2352
true
2300
2353
}
2301
2354
}
2355
+ }
2302
2356
2303
- fn skip_paren_expr ( node : & ParenExpr , context : & Context ) -> bool {
2304
- if has_surrounding_comments ( & node. expr . into ( ) , context) {
2305
- return false ;
2306
- }
2357
+ fn should_skip_paren_expr ( node : & ParenExpr , context : & Context ) -> bool {
2358
+ if has_surrounding_comments ( & node. expr . into ( ) , context) {
2359
+ return false ;
2360
+ }
2307
2361
2308
- // skip over any paren exprs within paren exprs and needless paren exprs
2309
- let parent = node. parent ( ) ;
2310
- if matches ! (
2311
- parent. kind( ) ,
2312
- NodeKind :: ParenExpr | NodeKind :: ExprStmt | NodeKind :: JSXElement | NodeKind :: JSXFragment | NodeKind :: JSXExprContainer
2313
- ) {
2362
+ if matches ! ( node. expr. kind( ) , NodeKind :: ArrayLit ) {
2363
+ return true ;
2364
+ }
2365
+
2366
+ // skip over any paren exprs within paren exprs and needless paren exprs
2367
+ let parent = node. parent ( ) ;
2368
+ if matches ! (
2369
+ parent. kind( ) ,
2370
+ NodeKind :: ParenExpr | NodeKind :: ExprStmt | NodeKind :: JSXElement | NodeKind :: JSXFragment | NodeKind :: JSXExprContainer | NodeKind :: UpdateExpr
2371
+ ) {
2372
+ return true ;
2373
+ }
2374
+
2375
+ if let Node :: AssignExpr ( assign_expr) = parent {
2376
+ if assign_expr. right . span ( ) . contains ( node. span ( ) ) {
2314
2377
return true ;
2315
2378
}
2379
+ }
2316
2380
2317
- // skip over an expr or spread if not a spread
2318
- if let Some ( expr_or_spread) = parent. to :: < ExprOrSpread > ( ) {
2319
- // these should only appear in these nodes
2320
- let is_known_parent = matches ! ( expr_or_spread. parent( ) . kind( ) , NodeKind :: NewExpr | NodeKind :: ArrayLit | NodeKind :: CallExpr ) ;
2321
- debug_assert ! ( is_known_parent) ;
2322
- if is_known_parent && expr_or_spread. spread ( ) . is_none ( ) {
2323
- return true ;
2324
- }
2381
+ // skip over an expr or spread if not a spread
2382
+ if let Some ( expr_or_spread) = parent. to :: < ExprOrSpread > ( ) {
2383
+ // these should only appear in these nodes
2384
+ let is_known_parent = matches ! ( expr_or_spread. parent( ) . kind( ) , NodeKind :: NewExpr | NodeKind :: ArrayLit | NodeKind :: CallExpr ) ;
2385
+ debug_assert ! ( is_known_parent) ;
2386
+ if is_known_parent && expr_or_spread. spread ( ) . is_none ( ) {
2387
+ return true ;
2325
2388
}
2389
+ }
2326
2390
2327
- // skip explicitly parsing this as a paren expr as that will be handled
2328
- // in the JSX element/fragment and it might collapse back to not having a paren expr
2329
- is_jsx_paren_expr_handled_node ( & node. expr . into ( ) , context)
2391
+ if let Node :: MemberExpr ( member_expr) = parent {
2392
+ if member_expr. computed ( ) && member_expr. prop . span ( ) . contains ( node. span ( ) ) {
2393
+ return true ;
2394
+ }
2330
2395
}
2396
+
2397
+ // skip explicitly parsing this as a paren expr as that will be handled
2398
+ // in the JSX element/fragment and it might collapse back to not having a paren expr
2399
+ is_jsx_paren_expr_handled_node ( & node. expr . into ( ) , context)
2331
2400
}
2332
2401
2333
2402
fn parse_sequence_expr < ' a > ( node : & ' a SeqExpr , context : & mut Context < ' a > ) -> PrintItems {
@@ -2962,13 +3031,7 @@ fn handle_jsx_surrounding_parens<'a>(inner_items: PrintItems, context: &mut Cont
2962
3031
}
2963
3032
condition_resolvers:: is_multiple_lines ( context, & start_info, & end_info)
2964
3033
} ,
2965
- {
2966
- let mut items = PrintItems :: new ( ) ;
2967
- items. push_str ( "(" ) ;
2968
- items. extend ( surround_with_new_lines ( with_indent ( inner_items_rc. into ( ) ) ) ) ;
2969
- items. push_str ( ")" ) ;
2970
- items
2971
- } ,
3034
+ surround_with_parens ( surround_with_new_lines ( with_indent ( inner_items_rc. into ( ) ) ) ) ,
2972
3035
{
2973
3036
let mut items = PrintItems :: new ( ) ;
2974
3037
items. push_signal ( Signal :: PossibleNewLine ) ;
@@ -8254,6 +8317,14 @@ fn use_new_line_group_for_arrow_body(arrow_expr: &ArrowExpr, context: &Context)
8254
8317
}
8255
8318
}
8256
8319
8320
+ fn surround_with_parens ( items : PrintItems ) -> PrintItems {
8321
+ let mut new_items = PrintItems :: new ( ) ;
8322
+ new_items. push_str ( "(" ) ;
8323
+ new_items. extend ( items) ;
8324
+ new_items. push_str ( ")" ) ;
8325
+ new_items
8326
+ }
8327
+
8257
8328
/* is/has functions */
8258
8329
8259
8330
fn is_arrow_function_with_expr_body ( node : & Node ) -> bool {
0 commit comments