···68686969 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
70707171+- The "remove unreachable patterns" code action can now be triggered on
7272+ unreachable alternative patterns of a case expression.
7373+ ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
7474+7175- The language server now permits renaming type variables in functions, types,
7276 and constants. For example:
7377···165169 use statement, only the selected statement(s) are extracted.
166170167171 For example,
172172+168173 ```gleam
169174 pub fn wibble() {
170175 use wobble <- result.map(todo)
···172177 echo wobble as "2"
173178 }
174179 ```
180180+175181 is turned into
182182+176183 ```gleam
177184 pub fn wibble() {
178185 use wobble <- result.map(todo)
···184191 Nil
185192 }
186193 ```
194194+187195 ([Gavin Morrow](https://github.com/gavinmorrow))
···1012710127 let pattern_range = self.edits.src_span_to_lsp_range(clause.pattern_location());
1012810128 within(self.params.range, pattern_range)
1012910129 });
1013010130- if is_hovering_clause {
1013110131- self.clauses_to_delete = clauses
1013210132- .iter()
1013310133- .filter(|clause| {
1013410134- self.unreachable_clauses
1013510135- .contains(&clause.pattern_location())
1013610136- })
1013710137- .map(|clause| clause.location())
1013810138- .collect_vec();
1013910139- return;
1014010140- }
10141101301014210131 // If we're not hovering any of the clauses then we want to
1014310132 // keep visiting the case expression as the unreachable branch might be
1014410133 // in one of the nested cases.
1014510145- ast::visit::visit_typed_expr_case(self, location, type_, subjects, clauses, compiled_case);
1013410134+ if !is_hovering_clause {
1013510135+ ast::visit::visit_typed_expr_case(
1013610136+ self,
1013710137+ location,
1013810138+ type_,
1013910139+ subjects,
1014010140+ clauses,
1014110141+ compiled_case,
1014210142+ );
1014310143+ return;
1014410144+ }
1014510145+1014610146+ for clause in clauses {
1014710147+ let mut all_alternatives_are_unreachable = true;
1014810148+ let mut unreachable_alternatives = vec![];
1014910149+ let mut previous_alternative_end = None;
1015010150+ let mut all_previous_alternatives_were_deleted = true;
1015110151+1015210152+ for alternative in clause.alternatives() {
1015310153+ let alternative_location = alternative_location(alternative);
1015410154+ if self.unreachable_clauses.contains(&alternative_location) {
1015510155+ // If an alternative is unreachable we want to delete
1015610156+ // everything from the end of the previous alternative to
1015710157+ // the start of this one.
1015810158+ //
1015910159+ // ```gleam
1016010160+ // Error(_) | Error(_) | Ok(_)
1016110161+ // // ^^^^^^^^^^^ We want to delete all of this
1016210162+ // ```
1016310163+ unreachable_alternatives.push(
1016410164+ previous_alternative_end.map_or(alternative_location, |previous_end| {
1016510165+ SrcSpan::new(previous_end, alternative_location.end)
1016610166+ }),
1016710167+ );
1016810168+ } else {
1016910169+ // If all the previous alternatives have been deleted and
1017010170+ // this one is reachable there's some final cleanup we need
1017110171+ // to take care of:
1017210172+ //
1017310173+ // ```gleam
1017410174+ // Ok(_) | Ok(_) | Error(_) -> todo
1017510175+ // //^^^^^^^^^^^ All of this has been deleted, but there's
1017610176+ // // that last vertical bar that needs to be
1017710177+ // // taken care of!
1017810178+ // ```
1017910179+ //
1018010180+1018110181+ if all_previous_alternatives_were_deleted
1018210182+ && let Some(end) = previous_alternative_end
1018310183+ {
1018410184+ self.clauses_to_delete
1018510185+ .push(SrcSpan::new(end, alternative_location.start));
1018610186+ }
1018710187+1018810188+ all_previous_alternatives_were_deleted = false;
1018910189+ all_alternatives_are_unreachable = false;
1019010190+ }
1019110191+1019210192+ previous_alternative_end = alternative.last().map(|pattern| pattern.location().end);
1019310193+ }
1019410194+1019510195+ if all_alternatives_are_unreachable {
1019610196+ // If all the patterns of the clause are unreachable then we
1019710197+ // want to delete the entire branch:
1019810198+ //
1019910199+ // ```gleam
1020010200+ // case a, b {
1020110201+ // _, _ -> todo
1020210202+ // Ok(_), Ok(_) | Error(_), Error(_) -> todo
1020310203+ // // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1020410204+ // // we want the entire branch to be deleted!
1020510205+ // }
1020610206+ // ```
1020710207+ self.clauses_to_delete.push(clause.location())
1020810208+ } else {
1020910209+ // If only some of the variants are unreachable but not all
1021010210+ // we want to delete just those.
1021110211+ // case a, b {
1021210212+ // 1, 2 | 1, 2 -> todo
1021310213+ // // ^^^^ just this one should be deleted
1021410214+ // }
1021510215+ self.clauses_to_delete.extend(&unreachable_alternatives);
1021610216+ }
1021710217+ }
1014610218 }
1021910219+}
1022010220+1022110221+fn alternative_location(alternative: &[Pattern<Arc<Type>>]) -> SrcSpan {
1022210222+ let start = alternative
1022310223+ .first()
1022410224+ .map(|pattern| pattern.location().start)
1022510225+ .unwrap_or_default();
1022610226+ let end = alternative
1022710227+ .last()
1022810228+ .map(|pattern| pattern.location().end)
1022910229+ .unwrap_or_default();
1023010230+1023110231+ SrcSpan::new(start, end)
1014710232}
10148102331014910234/// Code action to remove a record update when all of its fields have been
···11-# SPDX-License-Identifier: Apache-2.0
22-# SPDX-FileCopyrightText: 2026 The Gleam contributors
33-41# Do not manually edit this file, it is managed by Gleam.
52#
63# This file locks the dependency versions used, to make your build
···11-# SPDX-License-Identifier: Apache-2.0
22-# SPDX-FileCopyrightText: 2026 The Gleam contributors
33-41# Do not manually edit this file, it is managed by Gleam.
52#
63# This file locks the dependency versions used, to make your build
···11-# SPDX-License-Identifier: Apache-2.0
22-# SPDX-FileCopyrightText: 2026 The Gleam contributors
33-41# Do not manually edit this file, it is managed by Gleam.
52#
63# This file locks the dependency versions used, to make your build
···11-# SPDX-License-Identifier: Apache-2.0
22-# SPDX-FileCopyrightText: 2026 The Gleam contributors
33-41# Do not manually edit this file, it is managed by Gleam.
52#
63# This file locks the dependency versions used, to make your build