+11
-10
compiler-core/src/language_server/code_action.rs
+11
-10
compiler-core/src/language_server/code_action.rs
···
8505
8505
8506
8506
let location = SrcSpan::new(first.location().start, last.location().end);
8507
8507
8508
-
let referenced_variables = referenced_variables_for_statements(&statements);
8508
+
let referenced_variables = referenced_variables_for_statements(&statements, location);
8509
8509
8510
8510
let code = code_at(self.module, location);
8511
8511
···
8582
8582
}
8583
8583
8584
8584
fn referenced_variables(expression: &TypedExpr) -> Vec<(EcoString, Arc<Type>)> {
8585
-
let mut references = ReferencedVariables::new();
8585
+
let mut references = ReferencedVariables::new(expression.location());
8586
8586
references.visit_typed_expr(expression);
8587
8587
references.variables
8588
8588
}
8589
8589
8590
8590
fn referenced_variables_for_statements(
8591
8591
statements: &[&TypedStatement],
8592
+
location: SrcSpan,
8592
8593
) -> Vec<(EcoString, Arc<Type>)> {
8593
-
let mut references = ReferencedVariables::new();
8594
+
let mut references = ReferencedVariables::new(location);
8594
8595
for statement in statements {
8595
8596
references.visit_typed_statement(*statement);
8596
8597
}
···
8599
8600
8600
8601
struct ReferencedVariables {
8601
8602
variables: Vec<(EcoString, Arc<Type>)>,
8602
-
defined_variables: HashSet<EcoString>,
8603
+
location: SrcSpan,
8603
8604
}
8604
8605
8605
8606
impl ReferencedVariables {
8606
-
fn new() -> Self {
8607
+
fn new(location: SrcSpan) -> Self {
8607
8608
Self {
8608
8609
variables: Vec::new(),
8609
-
defined_variables: HashSet::new(),
8610
+
location,
8610
8611
}
8611
8612
}
8612
8613
8613
-
fn register(&mut self, name: &EcoString, type_: &Arc<Type>) {
8614
-
if self.defined_variables.contains(name) {
8614
+
fn register(&mut self, name: &EcoString, type_: &Arc<Type>, definition_location: SrcSpan) {
8615
+
if self.location.contains_span(definition_location) {
8615
8616
return;
8616
8617
}
8617
8618
···
8633
8634
name: &'ast EcoString,
8634
8635
) {
8635
8636
match &constructor.variant {
8636
-
type_::ValueConstructorVariant::LocalVariable { .. } => {
8637
-
self.register(name, &constructor.type_);
8637
+
type_::ValueConstructorVariant::LocalVariable { location, .. } => {
8638
+
self.register(name, &constructor.type_, *location);
8638
8639
}
8639
8640
type_::ValueConstructorVariant::ModuleConstant { .. }
8640
8641
| type_::ValueConstructorVariant::LocalConstant { .. }
+35
compiler-core/src/language_server/tests/action.rs
+35
compiler-core/src/language_server/tests/action.rs
···
10264
10264
find_position_of("let").select_until(find_position_of("* b\n").under_char('\n'))
10265
10265
);
10266
10266
}
10267
+
10268
+
#[test]
10269
+
fn extract_function_which_use_variables_defined_in_the_extracted_span() {
10270
+
assert_code_action!(
10271
+
EXTRACT_FUNCTION,
10272
+
"
10273
+
pub fn do_things(a, b) {
10274
+
let new_a = 10 + a
10275
+
let new_b = 10 + b
10276
+
let result = new_a * new_b
10277
+
result + 3
10278
+
}
10279
+
",
10280
+
find_position_of("let").select_until(find_position_of("* new_b\n").under_char('\n'))
10281
+
);
10282
+
}
10283
+
10284
+
#[test]
10285
+
fn extract_function_which_use_variables_shadowed_in_an_inner_scope() {
10286
+
assert_code_action!(
10287
+
EXTRACT_FUNCTION,
10288
+
"
10289
+
pub fn do_things(a, b) {
10290
+
let first_part = {
10291
+
let a = a + 10
10292
+
let b = b + 10
10293
+
a * b
10294
+
}
10295
+
let result = first_part + a * b
10296
+
result + 3
10297
+
}
10298
+
",
10299
+
find_position_of("let").select_until(find_position_of("+ a * b\n").under_char('\n'))
10300
+
);
10301
+
}
+29
compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__extract_function_which_use_variables_defined_in_the_extracted_span.snap
+29
compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__extract_function_which_use_variables_defined_in_the_extracted_span.snap
···
1
+
---
2
+
source: compiler-core/src/language_server/tests/action.rs
3
+
expression: "\npub fn do_things(a, b) {\n let new_a = 10 + a\n let new_b = 10 + b\n let result = new_a * new_b\n result + 3\n}\n"
4
+
---
5
+
----- BEFORE ACTION
6
+
7
+
pub fn do_things(a, b) {
8
+
let new_a = 10 + a
9
+
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
10
+
let new_b = 10 + b
11
+
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
12
+
let result = new_a * new_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 new_a = 10 + a
27
+
let new_b = 10 + b
28
+
let result = new_a * new_b
29
+
}
+38
compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__extract_function_which_use_variables_shadowed_in_an_inner_scope.snap
+38
compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__extract_function_which_use_variables_shadowed_in_an_inner_scope.snap
···
1
+
---
2
+
source: compiler-core/src/language_server/tests/action.rs
3
+
expression: "\npub fn do_things(a, b) {\n let first_part = {\n let a = a + 10\n let b = b + 10\n a * b\n }\n let result = first_part + a * b\n result + 3\n}\n"
4
+
---
5
+
----- BEFORE ACTION
6
+
7
+
pub fn do_things(a, b) {
8
+
let first_part = {
9
+
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
10
+
let a = a + 10
11
+
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
12
+
let b = b + 10
13
+
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
14
+
a * b
15
+
▔▔▔▔▔▔▔▔▔
16
+
}
17
+
▔▔▔
18
+
let result = first_part + a * b
19
+
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
20
+
result + 3
21
+
}
22
+
23
+
24
+
----- AFTER ACTION
25
+
26
+
pub fn do_things(a, b) {
27
+
function(a, b)
28
+
result + 3
29
+
}
30
+
31
+
fn function(a: Int, b: Int) -> Int {
32
+
let first_part = {
33
+
let a = a + 10
34
+
let b = b + 10
35
+
a * b
36
+
}
37
+
let result = first_part + a * b
38
+
}