From e5c22122250c31dc062993d49c34b375e653bc3a Mon Sep 17 00:00:00 2001 From: Giacomo Cavalieri Date: Thu, 5 Sep 2024 14:02:16 +0200 Subject: [PATCH] add helpful error message --- CHANGELOG.md | 32 +++++++++++++++++++ compiler-core/src/parse.rs | 6 ++++ compiler-core/src/parse/error.rs | 14 ++++++++ ...ore__parse__tests__if_like_expression.snap | 18 +++++++++++ compiler-core/src/parse/tests.rs | 13 ++++++++ 5 files changed, 83 insertions(+) create mode 100644 compiler-core/src/parse/snapshots/gleam_core__parse__tests__if_like_expression.snap diff --git a/CHANGELOG.md b/CHANGELOG.md index 478818289fa..46a3e872864 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -239,6 +239,38 @@ - Improved error title when using an unknown module value. ([Giacomo Cavalieri](https://github.com/giacomocavalieri)) +- The compiler now shows an helpful error message if you try writing an `if` + expression instead of a case. For example, this code: + + ```gleam + pub fn main() { + let a = if wibble { + 1 + } + } + ``` + + Results in the following error: + + ```txt + error: Syntax error + ┌─ /src/parse/error.gleam:3:11 + │ + 3 │ let a = if wibble { + │ ^^ Gleam doesn't have if expressions + + If you want to write a conditional expression you can use a `case`: + + case condition { + True -> todo + False -> todo + } + + See: https://tour.gleam.run/flow-control/case-expressions/ + ``` + + ([Giacomo Cavalieri](https://github.com/giacomocavalieri)) + ### Formatter - The formatter now adds a `todo` after a `use` expression if it is the last diff --git a/compiler-core/src/parse.rs b/compiler-core/src/parse.rs index b4fa2ef58b9..776acf13044 100644 --- a/compiler-core/src/parse.rs +++ b/compiler-core/src/parse.rs @@ -715,6 +715,12 @@ where } } + // Helpful error if trying to write an if expression instead of a + // case. + Some((start, Token::If, end)) => { + return parse_error(ParseErrorType::IfExpression, SrcSpan { start, end }); + } + // helpful error on possibly trying to group with "" Some((start, Token::LeftParen, _)) => { return parse_error(ParseErrorType::ExprLparStart, SrcSpan { start, end: start }); diff --git a/compiler-core/src/parse/error.rs b/compiler-core/src/parse/error.rs index f8cb1e0f4ad..b5720d32218 100644 --- a/compiler-core/src/parse/error.rs +++ b/compiler-core/src/parse/error.rs @@ -295,6 +295,19 @@ utf16_codepoint, utf32_codepoint, signed, unsigned, big, little, native, size, u "Unsupported expression", vec!["Functions cannot be called in clause guards.".into()], ), + ParseErrorType::IfExpression => ( + "Gleam doesn't have if expressions", + vec![ + "If you want to write a conditional expression you can use a `case`:".into(), + "".into(), + " case condition {".into(), + " True -> todo".into(), + " False -> todo".into(), + " }".into(), + "".into(), + "See: https://tour.gleam.run/flow-control/case-expressions/".into(), + ], + ), } } } @@ -361,6 +374,7 @@ pub enum ParseErrorType { field_type: Option, }, CallInClauseGuard, // case x { _ if f() -> 1 } + IfExpression, } impl LexicalError { diff --git a/compiler-core/src/parse/snapshots/gleam_core__parse__tests__if_like_expression.snap b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__if_like_expression.snap new file mode 100644 index 00000000000..f422ea67320 --- /dev/null +++ b/compiler-core/src/parse/snapshots/gleam_core__parse__tests__if_like_expression.snap @@ -0,0 +1,18 @@ +--- +source: compiler-core/src/parse/tests.rs +expression: "\npub fn main() {\n let a = if wibble {\n wobble\n }\n}\n" +--- +error: Syntax error + ┌─ /src/parse/error.gleam:3:11 + │ +3 │ let a = if wibble { + │ ^^ Gleam doesn't have if expressions + +If you want to write a conditional expression you can use a `case`: + + case condition { + True -> todo + False -> todo + } + +See: https://tour.gleam.run/flow-control/case-expressions/ diff --git a/compiler-core/src/parse/tests.rs b/compiler-core/src/parse/tests.rs index 8e049abed5c..d90e78b9e3e 100644 --- a/compiler-core/src/parse/tests.rs +++ b/compiler-core/src/parse/tests.rs @@ -1493,3 +1493,16 @@ type Wibble { "# ); } + +#[test] +fn if_like_expression() { + assert_module_error!( + r#" +pub fn main() { + let a = if wibble { + wobble + } +} +"# + ); +}