diff --git a/CHANGELOG.md b/CHANGELOG.md index f441ed5d1de..fae258009d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -120,6 +120,10 @@ keyword of a variable to inline. ([Giacomo Cavalieri](https://github.com/giacomocavalieri)) +- The "add omitted labels" code action can now be used in function calls where + some of the labels have been provided already. + ([Giacomo Cavalieri](https://github.com/giacomocavalieri)) + - The "pattern match on variable" code action can now pick better names when used on tuples. ([Giacomo Cavalieri](https://github.com/giacomocavalieri)) diff --git a/compiler-core/src/language_server/code_action.rs b/compiler-core/src/language_server/code_action.rs index 5ece4902e2d..5de973f16bf 100644 --- a/compiler-core/src/language_server/code_action.rs +++ b/compiler-core/src/language_server/code_action.rs @@ -8562,10 +8562,18 @@ impl<'ast> ast::visit::Visit<'ast> for AddOmittedLabels<'ast> { let mut omitted_labels = Vec::with_capacity(arguments.len()); for (index, argument) in arguments.iter().enumerate() { - // We can't apply this code action to calls where any of the - // arguments have a label explicitly provided. - if argument.label.is_some() { - return; + // If the argument already has a label we don't want to add a label + // for it, so we skip it. + if let Some(label) = &argument.label { + // Though, before skipping, we want to make sure that the label + // is actually right for the function call. If it's not then we + // give up on adding labels because there wouldn't be no way of + // knowing which label to add. + if !field_map.fields.contains_key(label) { + return; + } else { + continue; + } } let label = argument_index_to_label diff --git a/compiler-core/src/language_server/tests/action.rs b/compiler-core/src/language_server/tests/action.rs index 6d62ced9b42..4e788cdab84 100644 --- a/compiler-core/src/language_server/tests/action.rs +++ b/compiler-core/src/language_server/tests/action.rs @@ -10321,8 +10321,23 @@ pub type Labelled { } #[test] -fn add_omitted_labels_does_not_pop_up_if_function_already_has_labels() { - assert_no_code_actions!( +fn add_omitted_labels_works_with_constructors_calls_with_some_labels_1() { + assert_code_action!( + ADD_OMITTED_LABELS, + " +pub fn main() { + labelled(3, 1, b: 2) +} + +pub fn labelled(a a, b b, c c) { todo } + ", + find_position_of("labelled").to_selection(), + ); +} + +#[test] +fn add_omitted_labels_works_with_constructors_calls_with_some_labels() { + assert_code_action!( ADD_OMITTED_LABELS, " pub fn main() { @@ -10336,6 +10351,36 @@ pub fn labelled(a a, b b) { todo } ); } +#[test] +fn add_omitted_labels_works_on_call_with_wrongly_placed_labels() { + assert_code_action!( + ADD_OMITTED_LABELS, + " +pub fn main() { + labelled(3, b: 2, 1) +} + +pub fn labelled(a a, b b, c c) { todo } + ", + find_position_of("labelled").to_selection(), + ); +} + +#[test] +fn add_omitted_labels_does_not_work_on_call_with_wrong_labels_2() { + assert_no_code_actions!( + ADD_OMITTED_LABELS, + " +pub fn main() { + labelled(3, 1, d: 2) +} + +pub fn labelled(a a, b b, c c) { todo } + ", + find_position_of("labelled").to_selection(), + ); +} + #[test] fn add_omitted_labels_does_not_pop_up_if_called_function_has_no_labels() { assert_no_code_actions!( diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__add_omitted_labels_works_on_call_with_wrongly_placed_labels.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__add_omitted_labels_works_on_call_with_wrongly_placed_labels.snap new file mode 100644 index 00000000000..3a026e4d7f1 --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__add_omitted_labels_works_on_call_with_wrongly_placed_labels.snap @@ -0,0 +1,22 @@ +--- +source: compiler-core/src/language_server/tests/action.rs +expression: "\npub fn main() {\n labelled(3, b: 2, 1)\n}\n\npub fn labelled(a a, b b, c c) { todo }\n " +--- +----- BEFORE ACTION + +pub fn main() { + labelled(3, b: 2, 1) + ↑ +} + +pub fn labelled(a a, b b, c c) { todo } + + + +----- AFTER ACTION + +pub fn main() { + labelled(a: 3, b: 2, c: 1) +} + +pub fn labelled(a a, b b, c c) { todo } diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__add_omitted_labels_works_with_constructors_calls_with_some_labels.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__add_omitted_labels_works_with_constructors_calls_with_some_labels.snap new file mode 100644 index 00000000000..08cebb089e2 --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__add_omitted_labels_works_with_constructors_calls_with_some_labels.snap @@ -0,0 +1,24 @@ +--- +source: compiler-core/src/language_server/tests/action.rs +expression: "\npub fn main() {\n let a = 1\n labelled(a, b: 2)\n}\n\npub fn labelled(a a, b b) { todo }\n " +--- +----- BEFORE ACTION + +pub fn main() { + let a = 1 + labelled(a, b: 2) + ↑ +} + +pub fn labelled(a a, b b) { todo } + + + +----- AFTER ACTION + +pub fn main() { + let a = 1 + labelled(a:, b: 2) +} + +pub fn labelled(a a, b b) { todo } diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__add_omitted_labels_works_with_constructors_calls_with_some_labels_1.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__add_omitted_labels_works_with_constructors_calls_with_some_labels_1.snap new file mode 100644 index 00000000000..f15e9d6feb3 --- /dev/null +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__add_omitted_labels_works_with_constructors_calls_with_some_labels_1.snap @@ -0,0 +1,22 @@ +--- +source: compiler-core/src/language_server/tests/action.rs +expression: "\npub fn main() {\n labelled(3, 1, b: 2)\n}\n\npub fn labelled(a a, b b, c c) { todo }\n " +--- +----- BEFORE ACTION + +pub fn main() { + labelled(3, 1, b: 2) + ↑ +} + +pub fn labelled(a a, b b, c c) { todo } + + + +----- AFTER ACTION + +pub fn main() { + labelled(a: 3, c: 1, b: 2) +} + +pub fn labelled(a a, b b, c c) { todo } diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__allow_further_pattern_matching_on_assert.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__allow_further_pattern_matching_on_assert.snap deleted file mode 100644 index e9061d5357c..00000000000 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__allow_further_pattern_matching_on_assert.snap +++ /dev/null @@ -1,19 +0,0 @@ ---- -source: compiler-core/src/language_server/tests/action.rs -expression: "pub fn main(x) {\n let assert Ok(one) = Ok(Error(Nil))\n}\n" ---- ------ BEFORE ACTION -pub fn main(x) { - let assert Ok(one) = Ok(Error(Nil)) - ↑ -} - - ------ AFTER ACTION -pub fn main(x) { - let assert Ok(one) = Ok(Error(Nil)) - case one { - Ok(value) -> todo - Error(value) -> todo - } -} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__extract_block_tail_position_3.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__extract_block_tail_position_3.snap index c97315dbafe..b0e403c3631 100644 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__extract_block_tail_position_3.snap +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__extract_block_tail_position_3.snap @@ -1,8 +1,6 @@ --- source: compiler-core/src/language_server/tests/action.rs -assertion_line: 10596 expression: "\npub fn main() {\n case 1 {\n _ -> {\n use <- wibble\n 123\n }\n _ -> todo\n }\n}\n\nfn wibble(f: fn() -> Float) -> Float { f() }\n" -snapshot_kind: text --- ----- BEFORE ACTION diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__extract_block_tail_position_4.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__extract_block_tail_position_4.snap index 14d6b93d519..c2935470379 100644 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__extract_block_tail_position_4.snap +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__extract_block_tail_position_4.snap @@ -1,8 +1,6 @@ --- source: compiler-core/src/language_server/tests/action.rs -assertion_line: 10619 expression: "\npub fn main() {\n case 1 {\n _ -> {\n use <- wibble\n use <- wibble\n 123\n }\n _ -> todo\n }\n}\n\nfn wibble(f: fn() -> Float) -> Float { f() }\n" -snapshot_kind: text --- ----- BEFORE ACTION diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__fill_in_labelled_args_works_with_pattern_and_parentheses_with_spaces.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__fill_in_labelled_args_works_with_pattern_and_parentheses_with_spaces.snap index 0251ecc0fc3..8d795628776 100644 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__fill_in_labelled_args_works_with_pattern_and_parentheses_with_spaces.snap +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__fill_in_labelled_args_works_with_pattern_and_parentheses_with_spaces.snap @@ -1,8 +1,6 @@ --- source: compiler-core/src/language_server/tests/action.rs -assertion_line: 2004 expression: "\npub fn main() {\n let assert Ok(Wibble ()) = Wibble(1, \"2\")\n}\n\npub type Wibble { Wibble(arg1: Int, arg2: String) }\n " -snapshot_kind: text --- ----- BEFORE ACTION diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__generate_variant.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__generate_variant.snap deleted file mode 100644 index cd76b75ea43..00000000000 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__generate_variant.snap +++ /dev/null @@ -1,26 +0,0 @@ ---- -source: compiler-core/src/language_server/tests/action.rs -expression: "\npub type Wibble {\n Wibble\n}\n\npub fn main() -> Wibble {\n Wobble(1)\n}" ---- ------ BEFORE ACTION - -pub type Wibble { - Wibble -} - -pub fn main() -> Wibble { - Wobble(1) - ↑ -} - - ------ AFTER ACTION - -pub type Wibble { - Wibble - Wobble(Int) -} - -pub fn main() -> Wibble { - Wobble(1) -} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__remove_unreachable_branches.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__remove_unreachable_branches.snap deleted file mode 100644 index b6f510dab70..00000000000 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__remove_unreachable_branches.snap +++ /dev/null @@ -1,25 +0,0 @@ ---- -source: compiler-core/src/language_server/tests/action.rs -expression: "pub fn main(x) {\n case x {\n Ok(n) -> 1\n Ok(_) -> 2\n Error(_) -> todo\n Ok(1) -> 3\n }\n}\n" ---- ------ BEFORE ACTION -pub fn main(x) { - case x { - Ok(n) -> 1 - Ok(_) -> 2 - Error(_) -> todo - Ok(1) -> 3 - ↑ - } -} - - ------ AFTER ACTION -pub fn main(x) { - case x { - Ok(n) -> 1 - - Error(_) -> todo - - } -} diff --git a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__remove_unreachable_clauses.snap b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__remove_unreachable_clauses.snap index 0ca095fb8e1..b6f510dab70 100644 --- a/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__remove_unreachable_clauses.snap +++ b/compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__remove_unreachable_clauses.snap @@ -1,8 +1,6 @@ --- source: compiler-core/src/language_server/tests/action.rs -assertion_line: 10007 expression: "pub fn main(x) {\n case x {\n Ok(n) -> 1\n Ok(_) -> 2\n Error(_) -> todo\n Ok(1) -> 3\n }\n}\n" -snapshot_kind: text --- ----- BEFORE ACTION pub fn main(x) {