Skip to content

Commit 3fb7658

Browse files
committed
make unwrapping work within nested function literals
1 parent 27ff3ff commit 3fb7658

File tree

3 files changed

+75
-14
lines changed

3 files changed

+75
-14
lines changed

compiler-core/src/language_server/code_action.rs

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7688,23 +7688,22 @@ impl<'a> UnwrapAnonymousFunction<'a> {
76887688
}
76897689
actions
76907690
}
7691-
}
76927691

7693-
impl<'ast> ast::visit::Visit<'ast> for UnwrapAnonymousFunction<'ast> {
7694-
fn visit_typed_expr_fn(
7692+
/// If an anonymous function can be unwrapped, save it to our list
7693+
///
7694+
/// We need to ensure our subjects:
7695+
/// - are anonymous function literals (not captures)
7696+
/// - only contain a single statement
7697+
/// - that statement is a function call
7698+
/// - that call's arguments exactly match the arguments of the enclosing
7699+
/// function
7700+
fn register_function(
76957701
&mut self,
7696-
location: &'ast SrcSpan,
7697-
_type_: &'ast Arc<Type>,
7698-
kind: &'ast FunctionLiteralKind,
7699-
arguments: &'ast [TypedArg],
7700-
body: &'ast Vec1<TypedStatement>,
7701-
_return_annotation: &'ast Option<ast::TypeAst>,
7702+
location: &'a SrcSpan,
7703+
kind: &'a FunctionLiteralKind,
7704+
arguments: &'a [TypedArg],
7705+
body: &'a Vec1<TypedStatement>,
77027706
) {
7703-
let function_range = src_span_to_lsp_range(*location, self.line_numbers);
7704-
if !overlaps(self.params.range, function_range) {
7705-
return;
7706-
}
7707-
77087707
match kind {
77097708
FunctionLiteralKind::Anonymous { .. } => (),
77107709
_ => return,
@@ -7758,3 +7757,26 @@ impl<'ast> ast::visit::Visit<'ast> for UnwrapAnonymousFunction<'ast> {
77587757
})
77597758
}
77607759
}
7760+
7761+
impl<'ast> ast::visit::Visit<'ast> for UnwrapAnonymousFunction<'ast> {
7762+
fn visit_typed_expr_fn(
7763+
&mut self,
7764+
location: &'ast SrcSpan,
7765+
_type: &'ast Arc<Type>,
7766+
kind: &'ast FunctionLiteralKind,
7767+
arguments: &'ast [TypedArg],
7768+
body: &'ast Vec1<TypedStatement>,
7769+
_return_annotation: &'ast Option<ast::TypeAst>,
7770+
) {
7771+
let function_range = src_span_to_lsp_range(*location, self.line_numbers);
7772+
if !overlaps(self.params.range, function_range) {
7773+
return;
7774+
}
7775+
7776+
self.register_function(location, kind, arguments, body);
7777+
7778+
for statement in body {
7779+
self.visit_typed_statement(statement);
7780+
}
7781+
}
7782+
}

compiler-core/src/language_server/tests/action.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9187,6 +9187,22 @@ fn op(i: Int) -> Int {
91879187
);
91889188
}
91899189

9190+
#[test]
9191+
fn unwrap_nested_anonymous_function() {
9192+
assert_code_action!(
9193+
UNWRAP_ANONYMOUS_FUNCTION,
9194+
"pub fn main() {
9195+
fn(do) { fn(re){ mi(re) }(do) }
9196+
}
9197+
9198+
fn mi(v) {
9199+
todo
9200+
}
9201+
",
9202+
find_position_of("fn(re)").to_selection()
9203+
);
9204+
}
9205+
91909206
#[test]
91919207
fn unwrap_anonymous_function_unavailable_when_args_discarded() {
91929208
assert_no_code_actions!(
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
source: compiler-core/src/language_server/tests/action.rs
3+
expression: "pub fn main() {\n fn(do) { fn(re){ mi(re) }(do) }\n}\n\nfn mi(v) {\n todo\n}\n"
4+
---
5+
----- BEFORE ACTION
6+
pub fn main() {
7+
fn(do) { fn(re){ mi(re) }(do) }
8+
9+
}
10+
11+
fn mi(v) {
12+
todo
13+
}
14+
15+
16+
----- AFTER ACTION
17+
pub fn main() {
18+
fn(do) { mi(do) }
19+
}
20+
21+
fn mi(v) {
22+
todo
23+
}

0 commit comments

Comments
 (0)