@@ -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
@@ -1250,7 +1273,7 @@ impl<'ast> ast::visit::Visit<'ast> for AddAnnotations<'_> {
1250
1273
let location = match kind {
1251
1274
// Function captures don't need any type annotations
1252
1275
FunctionLiteralKind :: Capture { .. } => return ,
1253
- FunctionLiteralKind :: Anonymous { head } => head,
1276
+ FunctionLiteralKind :: Anonymous { head, .. } => head,
1254
1277
FunctionLiteralKind :: Use { location } => location,
1255
1278
} ;
1256
1279
@@ -5172,6 +5195,7 @@ impl<'ast> ast::visit::Visit<'ast> for GenerateFunction<'ast> {
5172
5195
type_ : & ' ast Arc < Type > ,
5173
5196
fun : & ' ast TypedExpr ,
5174
5197
arguments : & ' ast [ TypedCallArg ] ,
5198
+ arguments_start : & ' ast Option < u32 > ,
5175
5199
) {
5176
5200
// If the function being called is invalid we need to generate a
5177
5201
// function that has the proper labels.
@@ -5182,7 +5206,14 @@ impl<'ast> ast::visit::Visit<'ast> for GenerateFunction<'ast> {
5182
5206
self . try_save_function_to_generate ( fun. location ( ) , & fun. type_ ( ) , Some ( arguments) ) ;
5183
5207
}
5184
5208
} else {
5185
- ast:: visit:: visit_typed_expr_call ( self , location, type_, fun, arguments) ;
5209
+ ast:: visit:: visit_typed_expr_call (
5210
+ self ,
5211
+ location,
5212
+ type_,
5213
+ fun,
5214
+ arguments,
5215
+ arguments_start,
5216
+ ) ;
5186
5217
}
5187
5218
}
5188
5219
}
@@ -5502,6 +5533,7 @@ where
5502
5533
type_ : & ' ast Arc < Type > ,
5503
5534
fun : & ' ast TypedExpr ,
5504
5535
arguments : & ' ast [ TypedCallArg ] ,
5536
+ arguments_start : & ' ast Option < u32 > ,
5505
5537
) {
5506
5538
// If the function being called is invalid we need to generate a
5507
5539
// function that has the proper labels.
@@ -5515,7 +5547,14 @@ where
5515
5547
) ;
5516
5548
}
5517
5549
} else {
5518
- ast:: visit:: visit_typed_expr_call ( self , location, type_, fun, arguments) ;
5550
+ ast:: visit:: visit_typed_expr_call (
5551
+ self ,
5552
+ location,
5553
+ type_,
5554
+ fun,
5555
+ arguments,
5556
+ arguments_start,
5557
+ ) ;
5519
5558
}
5520
5559
}
5521
5560
@@ -5973,12 +6012,7 @@ impl<'a> InlineVariable<'a> {
5973
6012
}
5974
6013
5975
6014
let mut location = assignment. location ;
5976
-
5977
- let mut chars = self . module . code [ location. end as usize ..] . chars ( ) ;
5978
- // Delete any whitespace after the removed statement
5979
- while chars. next ( ) . is_some_and ( char:: is_whitespace) {
5980
- location. end += 1 ;
5981
- }
6015
+ location. end = next_nonwhitespace ( & self . module . code , location. end ) ;
5982
6016
5983
6017
self . edits . delete ( location) ;
5984
6018
@@ -6205,6 +6239,7 @@ impl<'ast> ast::visit::Visit<'ast> for ConvertToPipe<'ast> {
6205
6239
_type_ : & ' ast Arc < Type > ,
6206
6240
fun : & ' ast TypedExpr ,
6207
6241
arguments : & ' ast [ TypedCallArg ] ,
6242
+ _arguments_start : & ' ast Option < u32 > ,
6208
6243
) {
6209
6244
if arguments. iter ( ) . any ( |arg| arg. is_capture_hole ( ) ) {
6210
6245
return ;
@@ -7616,6 +7651,7 @@ impl<'ast> ast::visit::Visit<'ast> for WrapInAnonymousFunction<'ast> {
7616
7651
_type : & ' ast Arc < Type > ,
7617
7652
fun : & ' ast TypedExpr ,
7618
7653
arguments : & ' ast [ TypedCallArg ] ,
7654
+ _arguments_start : & ' ast Option < u32 > ,
7619
7655
) {
7620
7656
// We only need to do this interception for explicit calls, so if any
7621
7657
// of our arguments are explicit we re-enter the visitor as usual.
@@ -7658,11 +7694,15 @@ pub struct UnwrapAnonymousFunction<'a> {
7658
7694
7659
7695
/// Helper struct, a target for [UnwrapAnonymousFunction]
7660
7696
struct FunctionToUnwrap {
7661
- /// Location of the anonymous function to apply the action to
7697
+ /// Location of the anonymous function to apply the action to.
7662
7698
outer_function : SrcSpan ,
7699
+ /// Location of the opening brace of the anonymous function.
7700
+ outer_function_body_start : u32 ,
7663
7701
/// Location of the function being called inside the anonymous function.
7664
7702
/// This will be all that's left after the action, plus any comments.
7665
7703
inner_function : SrcSpan ,
7704
+ // Location of the opening parenthesis of the inner function's argument list.
7705
+ inner_function_arguments_start : u32 ,
7666
7706
}
7667
7707
7668
7708
impl < ' a > UnwrapAnonymousFunction < ' a > {
@@ -7686,25 +7726,29 @@ impl<'a> UnwrapAnonymousFunction<'a> {
7686
7726
for function in & self . functions {
7687
7727
let mut edits = TextEdits :: new ( self . line_numbers ) ;
7688
7728
7689
- // We need to delete the anonymous function's head but preserve
7690
- // comments between it and the inner function call.
7691
- edits. delete ( self . span_until_comment ( SrcSpan {
7729
+ // We need to delete the anonymous function's head and the opening
7730
+ // brace but preserve comments between it and the inner function call.
7731
+ // We set our endpoint at the start of the function body, and move
7732
+ // it on through any whitespace.
7733
+ let head_deletion_end =
7734
+ next_nonwhitespace ( & self . module . code , function. outer_function_body_start + 1 ) ;
7735
+ edits. delete ( SrcSpan {
7692
7736
start : function. outer_function . start ,
7693
- end : function. inner_function . start ,
7694
- } ) ) ;
7695
-
7696
- // Now we need to delete the inner function call's arguments,
7697
- // preserving comments before the outer function tail.
7698
- edits. delete ( self . span_until_comment ( SrcSpan {
7699
- start : function. inner_function . end ,
7700
- end : function. outer_function . end - 1 ,
7701
- } ) ) ;
7702
-
7703
- // To delete the tail we nip one character to make sure we get the
7704
- // `}`. This could be redundant with the above if there were no
7705
- // comments, but that's fine.
7737
+ end : head_deletion_end,
7738
+ } ) ;
7739
+
7740
+ // Delete the inner function call's arguments.
7706
7741
edits. delete ( SrcSpan {
7707
- start : function. outer_function . end - 1 ,
7742
+ start : function. inner_function_arguments_start ,
7743
+ end : function. inner_function . end ,
7744
+ } ) ;
7745
+
7746
+ // To delete the tail we remove the function end (the '}') and any
7747
+ // whitespace before it.
7748
+ let tail_deletion_start =
7749
+ previous_nonwhitespace ( & self . module . code , function. outer_function . end - 1 ) ;
7750
+ edits. delete ( SrcSpan {
7751
+ start : tail_deletion_start,
7708
7752
end : function. outer_function . end ,
7709
7753
} ) ;
7710
7754
@@ -7716,24 +7760,6 @@ impl<'a> UnwrapAnonymousFunction<'a> {
7716
7760
actions
7717
7761
}
7718
7762
7719
- // Returns the given span, but with the end point adjusted to the start
7720
- // of the first comment in the span, if any.
7721
- fn span_until_comment ( & self , span : SrcSpan ) -> SrcSpan {
7722
- let SrcSpan { start, end } = span;
7723
- let adjusted_end = self
7724
- . module
7725
- . extra
7726
- . first_comment_between ( start, end)
7727
- // The above will return the start of the comment's text, so we need
7728
- // to step backwards a bit to get the `//`.
7729
- . map ( |comment| comment. start - 2 )
7730
- . unwrap_or ( end) ;
7731
- SrcSpan {
7732
- start,
7733
- end : adjusted_end,
7734
- }
7735
- }
7736
-
7737
7763
/// If an anonymous function can be unwrapped, save it to our list
7738
7764
///
7739
7765
/// We need to ensure our subjects:
@@ -7749,16 +7775,17 @@ impl<'a> UnwrapAnonymousFunction<'a> {
7749
7775
arguments : & ' a [ TypedArg ] ,
7750
7776
body : & ' a Vec1 < TypedStatement > ,
7751
7777
) {
7752
- match kind {
7753
- FunctionLiteralKind :: Anonymous { .. } => ( ) ,
7778
+ let outer_body = match kind {
7779
+ FunctionLiteralKind :: Anonymous { body , .. } => body ,
7754
7780
_ => return ,
7755
- }
7781
+ } ;
7756
7782
7757
7783
// We can only apply to anonymous functions containing a single function call
7758
7784
let [
7759
7785
TypedStatement :: Expression ( TypedExpr :: Call {
7760
- fun : called_function ,
7786
+ location : call_location ,
7761
7787
arguments : call_arguments,
7788
+ arguments_start : Some ( arguments_start) ,
7762
7789
..
7763
7790
} ) ,
7764
7791
] = body. as_slice ( )
@@ -7793,7 +7820,9 @@ impl<'a> UnwrapAnonymousFunction<'a> {
7793
7820
7794
7821
self . functions . push ( FunctionToUnwrap {
7795
7822
outer_function : * location,
7796
- inner_function : called_function. location ( ) ,
7823
+ outer_function_body_start : outer_body. start ,
7824
+ inner_function : * call_location,
7825
+ inner_function_arguments_start : * arguments_start,
7797
7826
} )
7798
7827
}
7799
7828
}
0 commit comments