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

Configure Feed

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

fix wrong binops in clause guards as well

author
Giacomo Cavalieri
committer
Louis Pilfold
date (May 21, 2026, 12:52 PM +0100) commit 6e8376ad parent f420722a change-id skovzxlx
+332 -14
+64 -14
language-server/src/code_action.rs
··· 8688 8688 .push_to(&mut action); 8689 8689 action 8690 8690 } 8691 + 8692 + fn try_fix( 8693 + &mut self, 8694 + left: Arc<Type>, 8695 + right: Arc<Type>, 8696 + operator: ast::BinOp, 8697 + operator_location: SrcSpan, 8698 + ) { 8699 + if operator.is_int_operator() && left.is_float() && right.is_float() { 8700 + self.fix = operator 8701 + .float_equivalent() 8702 + .map(|fix| (operator_location, fix)); 8703 + } else if operator.is_float_operator() && left.is_int() && right.is_int() { 8704 + self.fix = operator 8705 + .int_equivalent() 8706 + .map(|fix| (operator_location, fix)) 8707 + } else if operator == ast::BinOp::AddInt && left.is_string() && right.is_string() { 8708 + self.fix = Some((operator_location, ast::BinOp::Concatenate)) 8709 + } 8710 + } 8691 8711 } 8692 8712 8693 8713 impl<'ast> ast::visit::Visit<'ast> for FixBinaryOperation<'ast> { 8714 + fn visit_typed_expr_case( 8715 + &mut self, 8716 + location: &'ast SrcSpan, 8717 + type_: &'ast Arc<Type>, 8718 + subjects: &'ast [TypedExpr], 8719 + clauses: &'ast [ast::TypedClause], 8720 + compiled_case: &'ast CompiledCase, 8721 + ) { 8722 + ast::visit::visit_typed_expr_case(self, location, type_, subjects, clauses, compiled_case); 8723 + } 8724 + fn visit_typed_clause_guard(&mut self, guard: &'ast TypedClauseGuard) { 8725 + ast::visit::visit_typed_clause_guard(self, guard); 8726 + } 8727 + 8728 + fn visit_typed_clause_guard_bin_op( 8729 + &mut self, 8730 + left: &'ast TypedClauseGuard, 8731 + right: &'ast TypedClauseGuard, 8732 + operator: &'ast ast::BinOp, 8733 + operator_location: &'ast SrcSpan, 8734 + location: &'ast SrcSpan, 8735 + ) { 8736 + let binop_range = self.edits.src_span_to_lsp_range(*location); 8737 + if !within(self.params.range, binop_range) { 8738 + return; 8739 + } 8740 + 8741 + self.try_fix(left.type_(), right.type_(), *operator, *operator_location); 8742 + 8743 + ast::visit::visit_typed_clause_guard_bin_op( 8744 + self, 8745 + left, 8746 + right, 8747 + operator, 8748 + operator_location, 8749 + location, 8750 + ); 8751 + } 8752 + 8694 8753 fn visit_typed_expr_bin_op( 8695 8754 &mut self, 8696 8755 location: &'ast SrcSpan, 8697 8756 type_: &'ast Arc<Type>, 8698 - name: &'ast ast::BinOp, 8699 - name_location: &'ast SrcSpan, 8757 + operator: &'ast ast::BinOp, 8758 + operator_location: &'ast SrcSpan, 8700 8759 left: &'ast TypedExpr, 8701 8760 right: &'ast TypedExpr, 8702 8761 ) { ··· 8705 8764 return; 8706 8765 } 8707 8766 8708 - if name.is_int_operator() && left.type_().is_float() && right.type_().is_float() { 8709 - self.fix = name.float_equivalent().map(|fix| (*name_location, fix)); 8710 - } else if name.is_float_operator() && left.type_().is_int() && right.type_().is_int() { 8711 - self.fix = name.int_equivalent().map(|fix| (*name_location, fix)) 8712 - } else if *name == ast::BinOp::AddInt 8713 - && left.type_().is_string() 8714 - && right.type_().is_string() 8715 - { 8716 - self.fix = Some((*name_location, ast::BinOp::Concatenate)) 8717 - } 8767 + self.try_fix(left.type_(), right.type_(), *operator, *operator_location); 8718 8768 8719 8769 ast::visit::visit_typed_expr_bin_op( 8720 8770 self, 8721 8771 location, 8722 8772 type_, 8723 - name, 8724 - name_location, 8773 + operator, 8774 + operator_location, 8725 8775 left, 8726 8776 right, 8727 8777 );
+115
language-server/src/tests/action.rs
··· 10048 10048 ); 10049 10049 } 10050 10050 10051 + #[test] 10052 + fn fix_float_operator_on_ints_in_guards() { 10053 + let name = "Use `>=`"; 10054 + assert_code_action!( 10055 + name, 10056 + r#" 10057 + pub fn main() { 10058 + case todo { 10059 + _ if 1 >=. 2 -> todo 10060 + } 10061 + } 10062 + "#, 10063 + find_position_of("1").to_selection() 10064 + ); 10065 + } 10066 + 10067 + #[test] 10068 + fn fix_float_operator_on_ints_in_guards_2() { 10069 + let name = "Use `-`"; 10070 + assert_code_action!( 10071 + name, 10072 + r#" 10073 + pub fn main() { 10074 + case todo { 10075 + _ if 1 -. 2 -> todo 10076 + } 10077 + } 10078 + "#, 10079 + find_position_of("1").select_until(find_position_of("2")) 10080 + ); 10081 + } 10082 + 10083 + #[test] 10084 + fn fix_float_operator_on_ints_in_guards_3() { 10085 + let name = "Use `*`"; 10086 + assert_code_action!( 10087 + name, 10088 + r#" 10089 + pub fn main() { 10090 + let wobble = 3 10091 + case todo { 10092 + _ if 1 *. wobble -> todo 10093 + } 10094 + } 10095 + "#, 10096 + find_position_of("*.").to_selection() 10097 + ); 10098 + } 10099 + 10100 + #[test] 10101 + fn fix_int_operator_on_floats_in_guards() { 10102 + let name = "Use `>=.`"; 10103 + assert_code_action!( 10104 + name, 10105 + r#" 10106 + pub fn main() { 10107 + case todo { 10108 + _ if 1.0 >= 2.3 -> todo 10109 + } 10110 + } 10111 + "#, 10112 + find_position_of("1").to_selection() 10113 + ); 10114 + } 10115 + 10116 + #[test] 10117 + fn fix_int_operator_on_floats_in_guards_2() { 10118 + let name = "Use `-.`"; 10119 + assert_code_action!( 10120 + name, 10121 + r#" 10122 + pub fn main() { 10123 + case todo { 10124 + _ if 1.12 - 2.0 -> todo 10125 + } 10126 + } 10127 + "#, 10128 + find_position_of("1").select_until(find_position_of("2.0")) 10129 + ); 10130 + } 10131 + 10132 + #[test] 10133 + fn fix_int_operator_on_floats_in_guards_3() { 10134 + let name = "Use `*.`"; 10135 + assert_code_action!( 10136 + name, 10137 + r#" 10138 + pub fn main() { 10139 + let wobble = 3.2 10140 + case todo { 10141 + _ if 1.3 * wobble -> todo 10142 + } 10143 + } 10144 + "#, 10145 + find_position_of("*").to_selection() 10146 + ); 10147 + } 10148 + 10149 + #[test] 10150 + fn fix_plus_operator_on_strings_in_guards() { 10151 + let name = "Use `<>`"; 10152 + assert_code_action!( 10153 + name, 10154 + r#" 10155 + pub fn main() { 10156 + let name = "jak" 10157 + case todo { 10158 + _ if "hello, " + name -> todo 10159 + } 10160 + } 10161 + "#, 10162 + find_position_of("hello").select_until(find_position_of("name ->")) 10163 + ); 10164 + } 10165 + 10051 10166 // https://github.com/gleam-lang/gleam/issues/4454 10052 10167 #[test] 10053 10168 fn unqualify_already_imported_type() {
+21
language-server/src/tests/snapshots/gleam_language_server__tests__action__fix_float_operator_on_ints_in_guards.snap
··· 1 + --- 2 + source: language-server/src/tests/action.rs 3 + expression: "\npub fn main() {\n case todo {\n _ if 1 >=. 2 -> todo\n }\n}\n" 4 + --- 5 + ----- BEFORE ACTION 6 + 7 + pub fn main() { 8 + case todo { 9 + _ if 1 >=. 2 -> todo 10 + 11 + } 12 + } 13 + 14 + 15 + ----- AFTER ACTION 16 + 17 + pub fn main() { 18 + case todo { 19 + _ if 1 >= 2 -> todo 20 + } 21 + }
+21
language-server/src/tests/snapshots/gleam_language_server__tests__action__fix_float_operator_on_ints_in_guards_2.snap
··· 1 + --- 2 + source: language-server/src/tests/action.rs 3 + expression: "\npub fn main() {\n case todo {\n _ if 1 -. 2 -> todo\n }\n}\n" 4 + --- 5 + ----- BEFORE ACTION 6 + 7 + pub fn main() { 8 + case todo { 9 + _ if 1 -. 2 -> todo 10 + ▔▔▔▔▔↑ 11 + } 12 + } 13 + 14 + 15 + ----- AFTER ACTION 16 + 17 + pub fn main() { 18 + case todo { 19 + _ if 1 - 2 -> todo 20 + } 21 + }
+23
language-server/src/tests/snapshots/gleam_language_server__tests__action__fix_float_operator_on_ints_in_guards_3.snap
··· 1 + --- 2 + source: language-server/src/tests/action.rs 3 + expression: "\npub fn main() {\n let wobble = 3\n case todo {\n _ if 1 *. wobble -> todo\n }\n}\n" 4 + --- 5 + ----- BEFORE ACTION 6 + 7 + pub fn main() { 8 + let wobble = 3 9 + case todo { 10 + _ if 1 *. wobble -> todo 11 + 12 + } 13 + } 14 + 15 + 16 + ----- AFTER ACTION 17 + 18 + pub fn main() { 19 + let wobble = 3 20 + case todo { 21 + _ if 1 * wobble -> todo 22 + } 23 + }
+21
language-server/src/tests/snapshots/gleam_language_server__tests__action__fix_int_operator_on_floats_in_guards.snap
··· 1 + --- 2 + source: language-server/src/tests/action.rs 3 + expression: "\npub fn main() {\n case todo {\n _ if 1.0 >= 2.3 -> todo\n }\n}\n" 4 + --- 5 + ----- BEFORE ACTION 6 + 7 + pub fn main() { 8 + case todo { 9 + _ if 1.0 >= 2.3 -> todo 10 + 11 + } 12 + } 13 + 14 + 15 + ----- AFTER ACTION 16 + 17 + pub fn main() { 18 + case todo { 19 + _ if 1.0 >=. 2.3 -> todo 20 + } 21 + }
+21
language-server/src/tests/snapshots/gleam_language_server__tests__action__fix_int_operator_on_floats_in_guards_2.snap
··· 1 + --- 2 + source: language-server/src/tests/action.rs 3 + expression: "\npub fn main() {\n case todo {\n _ if 1.12 - 2.0 -> todo\n }\n}\n" 4 + --- 5 + ----- BEFORE ACTION 6 + 7 + pub fn main() { 8 + case todo { 9 + _ if 1.12 - 2.0 -> todo 10 + ▔▔▔▔▔▔▔↑ 11 + } 12 + } 13 + 14 + 15 + ----- AFTER ACTION 16 + 17 + pub fn main() { 18 + case todo { 19 + _ if 1.12 -. 2.0 -> todo 20 + } 21 + }
+23
language-server/src/tests/snapshots/gleam_language_server__tests__action__fix_int_operator_on_floats_in_guards_3.snap
··· 1 + --- 2 + source: language-server/src/tests/action.rs 3 + expression: "\npub fn main() {\n let wobble = 3.2\n case todo {\n _ if 1.3 * wobble -> todo\n }\n}\n" 4 + --- 5 + ----- BEFORE ACTION 6 + 7 + pub fn main() { 8 + let wobble = 3.2 9 + case todo { 10 + _ if 1.3 * wobble -> todo 11 + 12 + } 13 + } 14 + 15 + 16 + ----- AFTER ACTION 17 + 18 + pub fn main() { 19 + let wobble = 3.2 20 + case todo { 21 + _ if 1.3 *. wobble -> todo 22 + } 23 + }
+23
language-server/src/tests/snapshots/gleam_language_server__tests__action__fix_plus_operator_on_strings_in_guards.snap
··· 1 + --- 2 + source: language-server/src/tests/action.rs 3 + expression: "\npub fn main() {\n let name = \"jak\"\n case todo {\n _ if \"hello, \" + name -> todo\n }\n}\n" 4 + --- 5 + ----- BEFORE ACTION 6 + 7 + pub fn main() { 8 + let name = "jak" 9 + case todo { 10 + _ if "hello, " + name -> todo 11 + ▔▔▔▔▔▔▔▔▔▔▔↑ 12 + } 13 + } 14 + 15 + 16 + ----- AFTER ACTION 17 + 18 + pub fn main() { 19 + let name = "jak" 20 + case todo { 21 + _ if "hello, " <> name -> todo 22 + } 23 + }