mirror of
https://github.com/nushell/nushell.git
synced 2025-06-08 19:17:16 +02:00
Hello! This is my 1st contribution and an attempt at fixing #15417. # Description When parsing a brace expression, check if the shape is a block or match block before attempting to parse it as a closure. Results: - `if true {|| print hi}` now produces a `nu::parser` error instead of executing and outputting `hi`. The `nu::parser` error is the same one produced by running `|| print hi` (`nu::parser::shell_oror`) - `match true {|| print hi}` now fails with a `nu::parser` error instead of passing parsing and failing with `nu::compile::invalid_keyword_call` My understanding reading the code/docs is that the shape is a contextual constraint that needs to be satisfied for parsing to succeed, in this case the `if` placing a `Block` shape constraint on next tokens. So it would need to be checked in priority (if not `Any`) to understand how the next tokens should be parsed. Is that correct? Or is there a reason I'm not aware of to ignore the shape and attempt to parse as closure like it's currently the case when the parser sees `|` or `||` as next tokens? # User-Facing Changes No change in behaviour, but this PR fixes parsing to fail on some incorrect syntax which could be considered a breaking change. # Tests + Formatting - Added corresponding tests - `toolkit check pr` passed
This commit is contained in:
parent
2f74574e35
commit
803c24f9ce
@ -2057,6 +2057,10 @@ pub fn parse_brace_expr(
|
|||||||
} else if matches!(second_token_contents, Some(TokenContents::Pipe))
|
} else if matches!(second_token_contents, Some(TokenContents::Pipe))
|
||||||
|| matches!(second_token_contents, Some(TokenContents::PipePipe))
|
|| matches!(second_token_contents, Some(TokenContents::PipePipe))
|
||||||
{
|
{
|
||||||
|
if matches!(shape, SyntaxShape::Block) {
|
||||||
|
working_set.error(ParseError::Mismatch("block".into(), "closure".into(), span));
|
||||||
|
return Expression::garbage(working_set, span);
|
||||||
|
}
|
||||||
parse_closure_expression(working_set, shape, span)
|
parse_closure_expression(working_set, shape, span)
|
||||||
} else if matches!(third_token, Some(b":")) {
|
} else if matches!(third_token, Some(b":")) {
|
||||||
parse_full_cell_path(working_set, None, span)
|
parse_full_cell_path(working_set, None, span)
|
||||||
|
@ -2796,6 +2796,26 @@ mod input_types {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn closure_in_block_position_errors_correctly() {
|
||||||
|
let mut engine_state = EngineState::new();
|
||||||
|
add_declarations(&mut engine_state);
|
||||||
|
|
||||||
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
let inputs = [r#"if true { || print hi }"#, r#"if true { |x| $x }"#];
|
||||||
|
|
||||||
|
for input in inputs {
|
||||||
|
parse(&mut working_set, None, input.as_bytes(), true);
|
||||||
|
assert!(
|
||||||
|
matches!(
|
||||||
|
working_set.parse_errors.first(),
|
||||||
|
Some(ParseError::Mismatch(_, _, _))
|
||||||
|
),
|
||||||
|
"testing: {input}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn else_errors_correctly() {
|
fn else_errors_correctly() {
|
||||||
let mut engine_state = EngineState::new();
|
let mut engine_state = EngineState::new();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user