Skip to content

Commit 8f84282

Browse files
GearsDatapackslpil
authored andcommitted
Implement extract function for statements also
1 parent b6398fd commit 8f84282

File tree

3 files changed

+95
-5
lines changed

3 files changed

+95
-5
lines changed

compiler-core/src/language_server/code_action.rs

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8496,7 +8496,38 @@ impl<'a> ExtractFunction<'a> {
84968496
}
84978497

84988498
fn extract_statements(&mut self, statements: Vec<&TypedStatement>, function_end: u32) {
8499-
todo!("Implement for statements")
8499+
let Some(first) = statements.first() else {
8500+
return;
8501+
};
8502+
let Some(last) = statements.last() else {
8503+
return;
8504+
};
8505+
8506+
let location = SrcSpan::new(first.location().start, last.location().end);
8507+
8508+
let referenced_variables = referenced_variables_for_statements(&statements);
8509+
8510+
let code = code_at(self.module, location);
8511+
8512+
let arguments = referenced_variables.iter().map(|(name, _)| name).join(", ");
8513+
let call = format!("function({arguments})");
8514+
self.edits.replace(location, call);
8515+
8516+
let mut printer = Printer::new(&self.module.ast.names);
8517+
8518+
let parameters = referenced_variables
8519+
.iter()
8520+
.map(|(name, type_)| eco_format!("{name}: {}", printer.print_type(type_)))
8521+
.join(", ");
8522+
let return_type = printer.print_type(&last.type_());
8523+
8524+
let function = format!(
8525+
"\n\nfn function({parameters}) -> {return_type} {{
8526+
{code}
8527+
}}"
8528+
);
8529+
8530+
self.edits.insert(function_end, function);
85008531
}
85018532
}
85028533

@@ -8551,20 +8582,34 @@ impl<'ast> ast::visit::Visit<'ast> for ExtractFunction<'ast> {
85518582
}
85528583

85538584
fn referenced_variables(expression: &TypedExpr) -> Vec<(EcoString, Arc<Type>)> {
8554-
let mut references = ReferencedVariables {
8555-
variables: Vec::new(),
8556-
defined_variables: HashSet::new(),
8557-
};
8585+
let mut references = ReferencedVariables::new();
85588586
references.visit_typed_expr(expression);
85598587
references.variables
85608588
}
85618589

8590+
fn referenced_variables_for_statements(
8591+
statements: &[&TypedStatement],
8592+
) -> Vec<(EcoString, Arc<Type>)> {
8593+
let mut references = ReferencedVariables::new();
8594+
for statement in statements {
8595+
references.visit_typed_statement(*statement);
8596+
}
8597+
references.variables
8598+
}
8599+
85628600
struct ReferencedVariables {
85638601
variables: Vec<(EcoString, Arc<Type>)>,
85648602
defined_variables: HashSet<EcoString>,
85658603
}
85668604

85678605
impl ReferencedVariables {
8606+
fn new() -> Self {
8607+
Self {
8608+
variables: Vec::new(),
8609+
defined_variables: HashSet::new(),
8610+
}
8611+
}
8612+
85688613
fn register(&mut self, name: &EcoString, type_: &Arc<Type>) {
85698614
if self.defined_variables.contains(name) {
85708615
return;

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10248,3 +10248,19 @@ pub fn do_things(a, b) {
1024810248
.select_until(find_position_of("}\n").under_char('\n'))
1024910249
);
1025010250
}
10251+
10252+
#[test]
10253+
fn extract_function_from_statements() {
10254+
assert_code_action!(
10255+
EXTRACT_FUNCTION,
10256+
"
10257+
pub fn do_things(a, b) {
10258+
let a = 10 + a
10259+
let b = 10 + b
10260+
let result = a * b
10261+
result + 3
10262+
}
10263+
",
10264+
find_position_of("let").select_until(find_position_of("* b\n").under_char('\n'))
10265+
);
10266+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
source: compiler-core/src/language_server/tests/action.rs
3+
expression: "\npub fn do_things(a, b) {\n let a = 10 + a\n let b = 10 + b\n let result = a * b\n result + 3\n}\n"
4+
---
5+
----- BEFORE ACTION
6+
7+
pub fn do_things(a, b) {
8+
let a = 10 + a
9+
▔▔▔▔▔▔▔▔▔▔▔▔▔▔
10+
let b = 10 + b
11+
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
12+
let result = a * b
13+
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
14+
result + 3
15+
}
16+
17+
18+
----- AFTER ACTION
19+
20+
pub fn do_things(a, b) {
21+
function(a, b)
22+
result + 3
23+
}
24+
25+
fn function(a: Int, b: Int) -> Int {
26+
let a = 10 + a
27+
let b = 10 + b
28+
let result = a * b
29+
}

0 commit comments

Comments
 (0)