New switch errors.

This commit is contained in:
Stephen Chung 2021-04-16 13:28:36 +08:00
parent 1f987ec61a
commit 208e5fdbf4
4 changed files with 60 additions and 2 deletions

View File

@ -18,7 +18,7 @@ Breaking changes
---------------- ----------------
* Negative index to an array or string yields the appropriate element/character counting from the _end_. * Negative index to an array or string yields the appropriate element/character counting from the _end_.
* The default `_` case of a `switch` statement now must be the last case, together with a new error variant `EvalAltResult::WrongSwitchDefaultCase`. * The default `_` case of a `switch` statement now must be the last case, together with two new error variants: `EvalAltResult::WrongSwitchDefaultCase` and `EvalAltResult::WrongSwitchCaseCondition`.
* `ModuleResolver` trait methods take an additional parameter `source_path` that contains the path of the current environment. This is to facilitate loading other script files always from the current directory. * `ModuleResolver` trait methods take an additional parameter `source_path` that contains the path of the current environment. This is to facilitate loading other script files always from the current directory.
* `FileModuleResolver` now resolves relative paths under the source path if there is no base path set. * `FileModuleResolver` now resolves relative paths under the source path if there is no base path set.
* `FileModuleResolver::base_path` now returns `Option<&str>` which is `None` if there is no base path set. * `FileModuleResolver::base_path` now returns `Option<&str>` which is `None` if there is no base path set.

View File

@ -117,6 +117,8 @@ pub enum ParseErrorType {
DuplicatedSwitchCase, DuplicatedSwitchCase,
/// The default case of a `switch` statement is not the last. /// The default case of a `switch` statement is not the last.
WrongSwitchDefaultCase, WrongSwitchDefaultCase,
/// The case condition of a `switch` statement is not appropriate.
WrongSwitchCaseCondition,
/// Missing a property name for custom types and maps. /// Missing a property name for custom types and maps.
/// ///
/// Never appears under the `no_object` feature. /// Never appears under the `no_object` feature.
@ -198,6 +200,7 @@ impl ParseErrorType {
Self::DuplicatedProperty(_) => "Duplicated property in object map literal", Self::DuplicatedProperty(_) => "Duplicated property in object map literal",
Self::DuplicatedSwitchCase => "Duplicated switch case", Self::DuplicatedSwitchCase => "Duplicated switch case",
Self::WrongSwitchDefaultCase => "Default switch case is not the last", Self::WrongSwitchDefaultCase => "Default switch case is not the last",
Self::WrongSwitchCaseCondition => "Default switch case cannot have condition",
Self::PropertyExpected => "Expecting name of a property", Self::PropertyExpected => "Expecting name of a property",
Self::VariableExpected => "Expecting name of a variable", Self::VariableExpected => "Expecting name of a variable",
Self::Reserved(_) => "Invalid use of reserved keyword", Self::Reserved(_) => "Invalid use of reserved keyword",

View File

@ -829,6 +829,13 @@ fn parse_switch(
(Token::Underscore, pos) if def_stmt.is_none() => { (Token::Underscore, pos) if def_stmt.is_none() => {
def_pos = *pos; def_pos = *pos;
eat_token(input, Token::Underscore); eat_token(input, Token::Underscore);
let (if_clause, if_pos) = match_token(input, Token::If);
if if_clause {
return Err(PERR::WrongSwitchCaseCondition.into_err(if_pos));
}
(None, None) (None, None)
} }
(Token::Underscore, pos) => return Err(PERR::DuplicatedSwitchCase.into_err(*pos)), (Token::Underscore, pos) => return Err(PERR::DuplicatedSwitchCase.into_err(*pos)),

View File

@ -1,4 +1,4 @@
use rhai::{Engine, EvalAltResult, Scope, INT}; use rhai::{Engine, EvalAltResult, ParseErrorType, Scope, INT};
#[test] #[test]
fn test_switch() -> Result<(), Box<EvalAltResult>> { fn test_switch() -> Result<(), Box<EvalAltResult>> {
@ -67,6 +67,28 @@ fn test_switch() -> Result<(), Box<EvalAltResult>> {
Ok(()) Ok(())
} }
#[test]
fn test_switch_errors() -> Result<(), Box<EvalAltResult>> {
let engine = Engine::new();
assert!(matches!(
*engine
.compile("switch x { 1 => 123, 1 => 42 }")
.expect_err("should error")
.0,
ParseErrorType::DuplicatedSwitchCase
));
assert!(matches!(
*engine
.compile("switch x { _ => 123, 1 => 42 }")
.expect_err("should error")
.0,
ParseErrorType::WrongSwitchDefaultCase
));
Ok(())
}
#[test] #[test]
fn test_switch_condition() -> Result<(), Box<EvalAltResult>> { fn test_switch_condition() -> Result<(), Box<EvalAltResult>> {
let engine = Engine::new(); let engine = Engine::new();
@ -103,6 +125,32 @@ fn test_switch_condition() -> Result<(), Box<EvalAltResult>> {
9 9
); );
assert!(matches!(
*engine
.compile(
r"
switch x {
21 if x < 40 => 1,
21 if x == 10 => 10,
0 if x < 100 => 2,
1 => 3,
_ => 9
}
"
)
.expect_err("should error")
.0,
ParseErrorType::DuplicatedSwitchCase
));
assert!(matches!(
*engine
.compile("switch x { 1 => 123, _ if true => 42 }")
.expect_err("should error")
.0,
ParseErrorType::WrongSwitchCaseCondition
));
Ok(()) Ok(())
} }