@@ -34,7 +34,7 @@ pub(crate) fn convert_nested_function_to_closure(
34
34
let name = ctx. find_node_at_offset :: < ast:: Name > ( ) ?;
35
35
let function = name. syntax ( ) . parent ( ) . and_then ( ast:: Fn :: cast) ?;
36
36
37
- if !is_nested_function ( & function) || is_generic ( & function) {
37
+ if !is_nested_function ( & function) || is_generic ( & function) || has_modifiers ( & function ) {
38
38
return None ;
39
39
}
40
40
@@ -43,21 +43,21 @@ pub(crate) fn convert_nested_function_to_closure(
43
43
let name = function. name ( ) ?;
44
44
let params = function. param_list ( ) ?;
45
45
46
+ let params_text = params. syntax ( ) . text ( ) . to_string ( ) ;
47
+ let closure_params = params_text. strip_prefix ( "(" ) . and_then ( |p| p. strip_suffix ( ")" ) ) ?;
48
+
46
49
acc. add (
47
50
AssistId ( "convert_nested_function_to_closure" , AssistKind :: RefactorRewrite ) ,
48
51
"Convert nested function to closure" ,
49
52
target,
50
53
|edit| {
51
54
let has_semicolon = has_semicolon ( & function) ;
52
- let params_text = params. syntax ( ) . text ( ) . to_string ( ) ;
53
- let params_text_trimmed =
54
- params_text. strip_prefix ( "(" ) . and_then ( |p| p. strip_suffix ( ")" ) ) ;
55
-
56
- if let Some ( closure_params) = params_text_trimmed {
57
- let body = body. to_string ( ) ;
58
- let body = if has_semicolon { body } else { format ! ( "{};" , body) } ;
59
- edit. replace ( target, format ! ( "let {} = |{}| {}" , name, closure_params, body) ) ;
55
+
56
+ let mut body = body. to_string ( ) ;
57
+ if !has_semicolon {
58
+ body. push ( ';' ) ;
60
59
}
60
+ edit. replace ( target, format ! ( "let {} = |{}| {}" , name, closure_params, body) ) ;
61
61
} ,
62
62
)
63
63
}
@@ -77,6 +77,17 @@ fn is_generic(function: &ast::Fn) -> bool {
77
77
function. generic_param_list ( ) . is_some ( )
78
78
}
79
79
80
+ /// Returns whether the given nested function has any modifiers:
81
+ ///
82
+ /// - `async`,
83
+ /// - `const` or
84
+ /// - `unsafe`
85
+ fn has_modifiers ( function : & ast:: Fn ) -> bool {
86
+ function. async_token ( ) . is_some ( )
87
+ || function. const_token ( ) . is_some ( )
88
+ || function. unsafe_token ( ) . is_some ( )
89
+ }
90
+
80
91
/// Returns whether the given nested function has a trailing semicolon.
81
92
fn has_semicolon ( function : & ast:: Fn ) -> bool {
82
93
function
@@ -143,7 +154,7 @@ fn main() {
143
154
}
144
155
145
156
#[ test]
146
- fn convert_nested_function_to_closure_does_not_work_on_top_level_function ( ) {
157
+ fn convert_nested_function_to_closure_is_not_suggested_on_top_level_function ( ) {
147
158
check_assist_not_applicable (
148
159
convert_nested_function_to_closure,
149
160
r#"
@@ -153,14 +164,14 @@ fn ma$0in() {}
153
164
}
154
165
155
166
#[ test]
156
- fn convert_nested_function_to_closure_does_not_work_when_cursor_off_name ( ) {
167
+ fn convert_nested_function_to_closure_is_not_suggested_when_cursor_off_name ( ) {
157
168
check_assist_not_applicable (
158
169
convert_nested_function_to_closure,
159
170
r#"
160
171
fn main() {
161
172
fn foo(a: u64, $0b: u64) -> u64 {
162
173
2 * (a + b)
163
- };
174
+ }
164
175
165
176
_ = foo(3, 4);
166
177
}
@@ -169,14 +180,30 @@ fn main() {
169
180
}
170
181
171
182
#[ test]
172
- fn convert_nested_function_to_closure_does_not_work_if_function_has_generic_params ( ) {
183
+ fn convert_nested_function_to_closure_is_not_suggested_if_function_has_generic_params ( ) {
173
184
check_assist_not_applicable (
174
185
convert_nested_function_to_closure,
175
186
r#"
176
187
fn main() {
177
188
fn fo$0o<S: Into<String>>(s: S) -> String {
178
189
s.into()
179
- };
190
+ }
191
+
192
+ _ = foo("hello");
193
+ }
194
+ "# ,
195
+ ) ;
196
+ }
197
+
198
+ #[ test]
199
+ fn convert_nested_function_to_closure_is_not_suggested_if_function_has_modifier ( ) {
200
+ check_assist_not_applicable (
201
+ convert_nested_function_to_closure,
202
+ r#"
203
+ fn main() {
204
+ const fn fo$0o(s: String) -> String {
205
+ s
206
+ }
180
207
181
208
_ = foo("hello");
182
209
}
0 commit comments