@@ -102,6 +102,28 @@ fn count_indentation(code: &str, line_numbers: &LineNumbers, line: u32) -> usize
102
102
indent_size
103
103
}
104
104
105
+ // Given a string and a position in it, if the position points to whitespace,
106
+ // this function returns the next position which doesn't.
107
+ fn next_nonwhitespace ( string : & EcoString , position : u32 ) -> u32 {
108
+ let mut n = position;
109
+ let mut chars = string[ position as usize ..] . chars ( ) ;
110
+ while chars. next ( ) . is_some_and ( char:: is_whitespace) {
111
+ n += 1 ;
112
+ }
113
+ n
114
+ }
115
+
116
+ // Given a string and a position in it, if the position points after whitespace,
117
+ // this function returns the previous position which doesn't.
118
+ fn previous_nonwhitespace ( string : & EcoString , position : u32 ) -> u32 {
119
+ let mut n = position;
120
+ let mut chars = string[ ..position as usize ] . chars ( ) ;
121
+ while chars. next_back ( ) . is_some_and ( char:: is_whitespace) {
122
+ n -= 1 ;
123
+ }
124
+ n
125
+ }
126
+
105
127
/// Code action to remove literal tuples in case subjects, essentially making
106
128
/// the elements of the tuples into the case's subjects.
107
129
///
@@ -842,6 +864,7 @@ impl<'ast> ast::visit::Visit<'ast> for FillInMissingLabelledArgs<'ast> {
842
864
type_ : & ' ast Arc < Type > ,
843
865
fun : & ' ast TypedExpr ,
844
866
arguments : & ' ast [ TypedCallArg ] ,
867
+ arguments_start : & ' ast Option < u32 > ,
845
868
) {
846
869
let call_range = self . edits . src_span_to_lsp_range ( * location) ;
847
870
if !within ( self . params . range , call_range) {
@@ -864,7 +887,7 @@ impl<'ast> ast::visit::Visit<'ast> for FillInMissingLabelledArgs<'ast> {
864
887
// we're inside a nested call.
865
888
let previous = self . use_right_hand_side_location ;
866
889
self . use_right_hand_side_location = None ;
867
- ast:: visit:: visit_typed_expr_call ( self , location, type_, fun, arguments) ;
890
+ ast:: visit:: visit_typed_expr_call ( self , location, type_, fun, arguments, arguments_start ) ;
868
891
self . use_right_hand_side_location = previous;
869
892
}
870
893
@@ -1263,7 +1286,7 @@ impl<'ast> ast::visit::Visit<'ast> for AddAnnotations<'_> {
1263
1286
let location = match kind {
1264
1287
// Function captures don't need any type annotations
1265
1288
FunctionLiteralKind :: Capture { .. } => return ,
1266
- FunctionLiteralKind :: Anonymous { head } => head,
1289
+ FunctionLiteralKind :: Anonymous { head, .. } => head,
1267
1290
FunctionLiteralKind :: Use { location } => location,
1268
1291
} ;
1269
1292
@@ -5269,6 +5292,7 @@ impl<'ast> ast::visit::Visit<'ast> for GenerateFunction<'ast> {
5269
5292
type_ : & ' ast Arc < Type > ,
5270
5293
fun : & ' ast TypedExpr ,
5271
5294
arguments : & ' ast [ TypedCallArg ] ,
5295
+ arguments_start : & ' ast Option < u32 > ,
5272
5296
) {
5273
5297
// If the function being called is invalid we need to generate a
5274
5298
// function that has the proper labels.
@@ -5302,8 +5326,7 @@ impl<'ast> ast::visit::Visit<'ast> for GenerateFunction<'ast> {
5302
5326
_ => { }
5303
5327
}
5304
5328
}
5305
-
5306
- ast:: visit:: visit_typed_expr_call ( self , location, type_, fun, arguments) ;
5329
+ ast:: visit:: visit_typed_expr_call ( self , location, type_, fun, arguments, arguments_start) ;
5307
5330
}
5308
5331
}
5309
5332
@@ -5626,6 +5649,7 @@ where
5626
5649
type_ : & ' ast Arc < Type > ,
5627
5650
fun : & ' ast TypedExpr ,
5628
5651
arguments : & ' ast [ TypedCallArg ] ,
5652
+ arguments_start : & ' ast Option < u32 > ,
5629
5653
) {
5630
5654
// If the function being called is invalid we need to generate a
5631
5655
// function that has the proper labels.
@@ -5639,7 +5663,14 @@ where
5639
5663
) ;
5640
5664
}
5641
5665
} else {
5642
- ast:: visit:: visit_typed_expr_call ( self , location, type_, fun, arguments) ;
5666
+ ast:: visit:: visit_typed_expr_call (
5667
+ self ,
5668
+ location,
5669
+ type_,
5670
+ fun,
5671
+ arguments,
5672
+ arguments_start,
5673
+ ) ;
5643
5674
}
5644
5675
}
5645
5676
@@ -6102,12 +6133,7 @@ impl<'a> InlineVariable<'a> {
6102
6133
}
6103
6134
6104
6135
let mut location = assignment. location ;
6105
-
6106
- let mut chars = self . module . code [ location. end as usize ..] . chars ( ) ;
6107
- // Delete any whitespace after the removed statement
6108
- while chars. next ( ) . is_some_and ( char:: is_whitespace) {
6109
- location. end += 1 ;
6110
- }
6136
+ location. end = next_nonwhitespace ( & self . module . code , location. end ) ;
6111
6137
6112
6138
self . edits . delete ( location) ;
6113
6139
@@ -6336,6 +6362,7 @@ impl<'ast> ast::visit::Visit<'ast> for ConvertToPipe<'ast> {
6336
6362
_type_ : & ' ast Arc < Type > ,
6337
6363
fun : & ' ast TypedExpr ,
6338
6364
arguments : & ' ast [ TypedCallArg ] ,
6365
+ _arguments_start : & ' ast Option < u32 > ,
6339
6366
) {
6340
6367
if arguments. iter ( ) . any ( |arg| arg. is_capture_hole ( ) ) {
6341
6368
return ;
@@ -8313,6 +8340,7 @@ impl<'ast> ast::visit::Visit<'ast> for WrapInAnonymousFunction<'ast> {
8313
8340
_type : & ' ast Arc < Type > ,
8314
8341
fun : & ' ast TypedExpr ,
8315
8342
arguments : & ' ast [ TypedCallArg ] ,
8343
+ _arguments_start : & ' ast Option < u32 > ,
8316
8344
) {
8317
8345
// We only need to do this interception for explicit calls, so if any
8318
8346
// of our arguments are explicit we re-enter the visitor as usual.
@@ -8355,11 +8383,15 @@ pub struct UnwrapAnonymousFunction<'a> {
8355
8383
8356
8384
/// Helper struct, a target for [UnwrapAnonymousFunction]
8357
8385
struct FunctionToUnwrap {
8358
- /// Location of the anonymous function to apply the action to
8386
+ /// Location of the anonymous function to apply the action to.
8359
8387
outer_function : SrcSpan ,
8388
+ /// Location of the opening brace of the anonymous function.
8389
+ outer_function_body_start : u32 ,
8360
8390
/// Location of the function being called inside the anonymous function.
8361
8391
/// This will be all that's left after the action, plus any comments.
8362
8392
inner_function : SrcSpan ,
8393
+ // Location of the opening parenthesis of the inner function's argument list.
8394
+ inner_function_arguments_start : u32 ,
8363
8395
}
8364
8396
8365
8397
impl < ' a > UnwrapAnonymousFunction < ' a > {
@@ -8383,25 +8415,29 @@ impl<'a> UnwrapAnonymousFunction<'a> {
8383
8415
for function in & self . functions {
8384
8416
let mut edits = TextEdits :: new ( self . line_numbers ) ;
8385
8417
8386
- // We need to delete the anonymous function's head but preserve
8387
- // comments between it and the inner function call.
8388
- edits. delete ( self . span_until_comment ( SrcSpan {
8418
+ // We need to delete the anonymous function's head and the opening
8419
+ // brace but preserve comments between it and the inner function call.
8420
+ // We set our endpoint at the start of the function body, and move
8421
+ // it on through any whitespace.
8422
+ let head_deletion_end =
8423
+ next_nonwhitespace ( & self . module . code , function. outer_function_body_start + 1 ) ;
8424
+ edits. delete ( SrcSpan {
8389
8425
start : function. outer_function . start ,
8390
- end : function . inner_function . start ,
8391
- } ) ) ;
8392
-
8393
- // Now we need to delete the inner function call's arguments,
8394
- // preserving comments before the outer function tail.
8395
- edits . delete ( self . span_until_comment ( SrcSpan {
8396
- start : function. inner_function . end ,
8397
- end : function . outer_function . end - 1 ,
8398
- } ) ) ;
8399
-
8400
- // To delete the tail we nip one character to make sure we get the
8401
- // `}`. This could be redundant with the above if there were no
8402
- // comments, but that's fine.
8426
+ end : head_deletion_end ,
8427
+ } ) ;
8428
+
8429
+ // Delete the inner function call's arguments.
8430
+ edits . delete ( SrcSpan {
8431
+ start : function . inner_function_arguments_start ,
8432
+ end : function. inner_function . end ,
8433
+ } ) ;
8434
+
8435
+ // To delete the tail we remove the function end (the '}') and any
8436
+ // whitespace before it.
8437
+ let tail_deletion_start =
8438
+ previous_nonwhitespace ( & self . module . code , function . outer_function . end - 1 ) ;
8403
8439
edits. delete ( SrcSpan {
8404
- start : function . outer_function . end - 1 ,
8440
+ start : tail_deletion_start ,
8405
8441
end : function. outer_function . end ,
8406
8442
} ) ;
8407
8443
@@ -8413,24 +8449,6 @@ impl<'a> UnwrapAnonymousFunction<'a> {
8413
8449
actions
8414
8450
}
8415
8451
8416
- // Returns the given span, but with the end point adjusted to the start
8417
- // of the first comment in the span, if any.
8418
- fn span_until_comment ( & self , span : SrcSpan ) -> SrcSpan {
8419
- let SrcSpan { start, end } = span;
8420
- let adjusted_end = self
8421
- . module
8422
- . extra
8423
- . first_comment_between ( start, end)
8424
- // The above will return the start of the comment's text, so we need
8425
- // to step backwards a bit to get the `//`.
8426
- . map ( |comment| comment. start - 2 )
8427
- . unwrap_or ( end) ;
8428
- SrcSpan {
8429
- start,
8430
- end : adjusted_end,
8431
- }
8432
- }
8433
-
8434
8452
/// If an anonymous function can be unwrapped, save it to our list
8435
8453
///
8436
8454
/// We need to ensure our subjects:
@@ -8446,16 +8464,17 @@ impl<'a> UnwrapAnonymousFunction<'a> {
8446
8464
arguments : & ' a [ TypedArg ] ,
8447
8465
body : & ' a Vec1 < TypedStatement > ,
8448
8466
) {
8449
- match kind {
8450
- FunctionLiteralKind :: Anonymous { .. } => ( ) ,
8467
+ let outer_body = match kind {
8468
+ FunctionLiteralKind :: Anonymous { body , .. } => body ,
8451
8469
_ => return ,
8452
- }
8470
+ } ;
8453
8471
8454
8472
// We can only apply to anonymous functions containing a single function call
8455
8473
let [
8456
8474
TypedStatement :: Expression ( TypedExpr :: Call {
8457
- fun : called_function ,
8475
+ location : call_location ,
8458
8476
arguments : call_arguments,
8477
+ arguments_start : Some ( arguments_start) ,
8459
8478
..
8460
8479
} ) ,
8461
8480
] = body. as_slice ( )
@@ -8490,7 +8509,9 @@ impl<'a> UnwrapAnonymousFunction<'a> {
8490
8509
8491
8510
self . functions . push ( FunctionToUnwrap {
8492
8511
outer_function : * location,
8493
- inner_function : called_function. location ( ) ,
8512
+ outer_function_body_start : outer_body. start ,
8513
+ inner_function : * call_location,
8514
+ inner_function_arguments_start : * arguments_start,
8494
8515
} )
8495
8516
}
8496
8517
}
0 commit comments