fix(parser): mixed side effects of different choices in parse_oneof (#14912)

# Description

This PR fixes #14784.

<img width="384" alt="image"
src="https://github.com/user-attachments/assets/aac063a0-645d-4adb-a399-525bdb004999"
/>

Also fixes the related behavior of lsp:

completion won't work in match/else blocks, because:

1. truncation in completion causes unmatched `{`, thus a parse error.
2. the parse error further leads to a state where the whole block
expression marked as garbage

<img width="453" alt="image"
src="https://github.com/user-attachments/assets/aaf86ccc-646e-4b91-bb27-4b1737100ff2"
/>

Related PR: #14856, @tmillr

I don't have any background knowledge of those `propagate_error`,
@sgvictorino you may want to review this.

# User-Facing Changes

# Tests + Formatting

# After Submitting
This commit is contained in:
zc he
2025-01-30 20:30:45 +08:00
committed by GitHub
parent 6be42d94d9
commit 3836da0cf1
2 changed files with 61 additions and 22 deletions

View File

@ -2426,7 +2426,7 @@ mod input_types {
add_declarations(&mut engine_state);
let mut working_set = StateWorkingSet::new(&engine_state);
parse(
let block = parse(
&mut working_set,
None,
b"if false { 'a' } else { $foo }",
@ -2437,6 +2437,30 @@ mod input_types {
working_set.parse_errors.first(),
Some(ParseError::VariableNotFound(_, _))
));
let element = &block
.pipelines
.first()
.unwrap()
.elements
.first()
.unwrap()
.expr;
let Expr::Call(call) = &element.expr else {
eprintln!("{:?}", element.expr);
panic!("Expected Expr::Call");
};
let Expr::Keyword(else_kwd) = &call
.arguments
.get(2)
.expect("This call of `if` should have 3 arguments")
.expr()
.unwrap()
.expr
else {
panic!("Expected Expr::Keyword");
};
assert!(!matches!(else_kwd.expr.expr, Expr::Garbage))
}
#[test]
@ -2597,7 +2621,7 @@ mod record {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let block = parse(&mut working_set, None, expr, false);
assert!(working_set.parse_errors.first().is_none());
assert!(working_set.parse_errors.is_empty());
let pipeline_el_expr = &block
.pipelines
.first()