Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

do not use nested patterns when pattern matching on case variable

author
Giacomo Cavalieri
committer
Louis Pilfold
date (Sep 7, 2025, 4:04 PM +0100) commit 5c2bff1e parent 4b5a41de change-id xzwzyypp
+93 -45
+2 -5
CHANGELOG.md
··· 227 227 ```gleam 228 228 pub fn main() { 229 229 case find_user() { 230 - Ok(user) -> 231 - case user { 232 - Admin -> todo 233 - Member -> todo 234 - } 230 + Ok(Admin) -> todo 231 + Ok(Member) -> todo 235 232 Error(_) -> todo 236 233 } 237 234 }
+24 -30
compiler-core/src/language_server/code_action.rs
··· 4321 4321 module: &'a Module, 4322 4322 params: &'a CodeActionParams, 4323 4323 compiler: &'a LspProjectCompiler<A>, 4324 - pattern_variable_under_cursor: Option<(&'a EcoString, Arc<Type>)>, 4324 + pattern_variable_under_cursor: Option<(&'a EcoString, SrcSpan, Arc<Type>)>, 4325 4325 selected_value: Option<PatternMatchedValue<'a>>, 4326 4326 edits: TextEdits<'a>, 4327 4327 } ··· 4362 4362 /// ``` 4363 4363 /// 4364 4364 ClausePatternVariable { 4365 - variable_name: &'a EcoString, 4366 4365 variable_type: Arc<Type>, 4367 - clause_body_location: SrcSpan, 4366 + variable_location: SrcSpan, 4368 4367 clause_location: SrcSpan, 4369 4368 }, 4370 4369 UseVariable { ··· 4426 4425 } 4427 4426 4428 4427 Some(PatternMatchedValue::ClausePatternVariable { 4429 - variable_name, 4430 4428 variable_type, 4431 - clause_body_location, 4429 + variable_location, 4432 4430 clause_location, 4433 4431 }) => { 4434 - self.match_on_clause_variable( 4435 - variable_name, 4436 - variable_type, 4437 - clause_body_location, 4438 - clause_location, 4439 - ); 4432 + self.match_on_clause_variable(variable_type, variable_location, clause_location); 4440 4433 "Pattern match on variable" 4441 4434 } 4442 4435 ··· 4554 4547 4555 4548 fn match_on_clause_variable( 4556 4549 &mut self, 4557 - variable_name: &EcoString, 4558 4550 variable_type: Arc<Type>, 4559 - clause_body_location: SrcSpan, 4551 + variable_location: SrcSpan, 4560 4552 clause_location: SrcSpan, 4561 4553 ) { 4562 4554 let Some(patterns) = self.type_to_destructure_patterns(variable_type.as_ref()) else { 4563 4555 return; 4564 4556 }; 4565 4557 4566 - let body_code = code_at(self.module, clause_body_location); 4567 - 4568 4558 let clause_range = self.edits.src_span_to_lsp_range(clause_location); 4569 - let nesting = " ".repeat(2 + clause_range.start.character as usize); 4559 + let nesting = " ".repeat(clause_range.start.character as usize); 4570 4560 4561 + let variable_start = (variable_location.start - clause_location.start) as usize; 4562 + let variable_end = 4563 + variable_start + (variable_location.end - variable_location.start) as usize; 4564 + 4565 + let clause_code = code_at(self.module, clause_location); 4571 4566 let patterns = patterns 4572 4567 .iter() 4573 - .map(|p| format!(" {nesting}{p} -> {body_code}")) 4574 - .join("\n"); 4575 - let pattern_matching = format!("case {variable_name} {{\n{patterns}\n{nesting}}}"); 4568 + .map(|pattern| { 4569 + let mut clause_code = clause_code.to_string(); 4570 + clause_code.replace_range(variable_start..variable_end, pattern); 4571 + clause_code 4572 + }) 4573 + .join(&format!("\n{nesting}")); 4576 4574 4577 - self.edits.replace( 4578 - clause_body_location, 4579 - format!("\n{nesting}{pattern_matching}"), 4580 - ); 4575 + self.edits.replace(clause_location, patterns); 4581 4576 } 4582 4577 4583 4578 /// Will produce a pattern that can be used on the left hand side of a let ··· 4809 4804 4810 4805 fn visit_typed_assignment(&mut self, assignment: &'ast TypedAssignment) { 4811 4806 ast::visit::visit_typed_assignment(self, assignment); 4812 - if let Some((name, ref type_)) = self.pattern_variable_under_cursor { 4807 + if let Some((name, _, ref type_)) = self.pattern_variable_under_cursor { 4813 4808 self.selected_value = Some(PatternMatchedValue::LetVariable { 4814 4809 variable_name: name, 4815 4810 variable_type: type_.clone(), ··· 4828 4823 } 4829 4824 } 4830 4825 4831 - if let Some((name, type_)) = self.pattern_variable_under_cursor.take() { 4826 + if let Some((_, variable_location, type_)) = self.pattern_variable_under_cursor.take() { 4832 4827 self.selected_value = Some(PatternMatchedValue::ClausePatternVariable { 4833 - variable_name: name, 4834 4828 variable_type: type_, 4835 - clause_body_location: clause.then.location(), 4829 + variable_location, 4836 4830 clause_location: clause.location(), 4837 4831 }); 4838 4832 } else { ··· 4888 4882 self.params.range, 4889 4883 self.edits.src_span_to_lsp_range(*location), 4890 4884 ) { 4891 - self.pattern_variable_under_cursor = Some((name, type_.clone())); 4885 + self.pattern_variable_under_cursor = Some((name, *location, type_.clone())); 4892 4886 } 4893 4887 } 4894 4888 ··· 4907 4901 self.edits.src_span_to_lsp_range(*location), 4908 4902 ) 4909 4903 { 4910 - self.pattern_variable_under_cursor = Some((name, type_::string())); 4904 + self.pattern_variable_under_cursor = Some((name, *location, type_::string())); 4911 4905 } else if let AssignName::Variable(name) = right_side_assignment 4912 4906 && within( 4913 4907 self.params.range, 4914 4908 self.edits.src_span_to_lsp_range(*right_location), 4915 4909 ) 4916 4910 { 4917 - self.pattern_variable_under_cursor = Some((name, type_::string())); 4911 + self.pattern_variable_under_cursor = Some((name, *right_location, type_::string())); 4918 4912 } 4919 4913 } 4920 4914 }
+24
compiler-core/src/language_server/tests/action.rs
··· 6992 6992 } 6993 6993 6994 6994 #[test] 6995 + fn pattern_match_on_clause_variable_nested_pattern() { 6996 + assert_code_action!( 6997 + PATTERN_MATCH_ON_VARIABLE, 6998 + " 6999 + pub fn main() { 7000 + case maybe_wibble() { 7001 + Ok(Wobble(something)) -> 1 7002 + Error(_) -> 2 7003 + } 7004 + } 7005 + 7006 + type Wibble { 7007 + Wobble(Wibble) 7008 + Woo 7009 + } 7010 + 7011 + fn maybe_wibble() { Ok(Woo) } 7012 + 7013 + ", 7014 + find_position_of("something").to_selection() 7015 + ); 7016 + } 7017 + 7018 + #[test] 6995 7019 fn pattern_match_on_clause_variable_with_block_body() { 6996 7020 assert_code_action!( 6997 7021 PATTERN_MATCH_ON_VARIABLE,
+2 -5
compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__pattern_match_on_clause_variable.snap
··· 25 25 26 26 pub fn main() { 27 27 case maybe_wibble() { 28 - Ok(something) -> 29 - case something { 30 - Wobble -> 1 31 - Woo -> 1 32 - } 28 + Ok(Wobble) -> 1 29 + Ok(Woo) -> 1 33 30 Error(_) -> 2 34 31 } 35 32 }
+39
compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__pattern_match_on_clause_variable_nested_pattern.snap
··· 1 + --- 2 + source: compiler-core/src/language_server/tests/action.rs 3 + expression: "\npub fn main() {\n case maybe_wibble() {\n Ok(Wobble(something)) -> 1\n Error(_) -> 2\n }\n}\n\ntype Wibble {\n Wobble(Wibble)\n Woo\n}\n\nfn maybe_wibble() { Ok(Woo) }\n\n" 4 + --- 5 + ----- BEFORE ACTION 6 + 7 + pub fn main() { 8 + case maybe_wibble() { 9 + Ok(Wobble(something)) -> 1 10 + 11 + Error(_) -> 2 12 + } 13 + } 14 + 15 + type Wibble { 16 + Wobble(Wibble) 17 + Woo 18 + } 19 + 20 + fn maybe_wibble() { Ok(Woo) } 21 + 22 + 23 + 24 + ----- AFTER ACTION 25 + 26 + pub fn main() { 27 + case maybe_wibble() { 28 + Ok(Wobble(Wobble(wibble))) -> 1 29 + Ok(Wobble(Woo)) -> 1 30 + Error(_) -> 2 31 + } 32 + } 33 + 34 + type Wibble { 35 + Wobble(Wibble) 36 + Woo 37 + } 38 + 39 + fn maybe_wibble() { Ok(Woo) }
+2 -5
compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__pattern_match_on_clause_variable_with_block_body.snap
··· 28 28 29 29 pub fn main() { 30 30 case maybe_wibble() { 31 - Ok(something) -> 32 - case something { 33 - Wobble -> { 31 + Ok(Wobble) -> { 34 32 1 35 33 2 36 34 } 37 - Woo -> { 35 + Ok(Woo) -> { 38 36 1 39 37 2 40 38 } 41 - } 42 39 Error(_) -> 2 43 40 } 44 41 }