Skip to content

Commit

Permalink
fix: Recover from missing argument in call expressions
Browse files Browse the repository at this point in the history
Previously, when parsing an argument list with a missing argument (e.g.,
`(a, , b)` in `foo(a, , b)`), the parser would stop upon an unexpected
token (at the second comma in the example), resulting in an incorrect
parse tree.

This commit improves error handling in such cases, ensuring a more
accurate parse tree is built.
  • Loading branch information
ohno418 committed Dec 14, 2023
1 parent 35e2f13 commit fcf2d9a
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 22 deletions.
14 changes: 0 additions & 14 deletions crates/hir-expand/src/fixup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -601,20 +601,6 @@ fn foo () {a . b ; bar () ;}
)
}

#[test]
fn extraneous_comma() {
check(
r#"
fn foo() {
bar(,);
}
"#,
expect![[r#"
fn foo () {__ra_fixup ;}
"#]],
)
}

#[test]
fn fixup_if_1() {
check(
Expand Down
33 changes: 25 additions & 8 deletions crates/parser/src/grammar/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,7 @@ fn cast_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
// foo(bar::);
// foo(bar:);
// foo(bar+);
// foo(a, , b);
// }
fn arg_list(p: &mut Parser<'_>) {
assert!(p.at(T!['(']));
Expand All @@ -602,14 +603,30 @@ fn arg_list(p: &mut Parser<'_>) {
// fn main() {
// foo(#[attr] 92)
// }
delimited(
p,
T!['('],
T![')'],
T![,],
EXPR_FIRST.union(ATTRIBUTE_FIRST),
|p: &mut Parser<'_>| expr(p).is_some(),
);
p.bump(T!['(']);
while !p.at(T![')']) && !p.at(EOF) {
if p.at(T![,]) {
// Recover if an argument is missing and only got a delimiter,
// e.g. `(a, , b)`.
p.error("expected expression");
p.bump(T![,]);
continue;
}

if expr(p).is_none() {
break;
}
if !p.at(T![,]) {
if p.at_ts(EXPR_FIRST.union(ATTRIBUTE_FIRST)) {
p.error(format!("expected {:?}", T![,]));
} else {
break;
}
} else {
p.bump(T![,]);
}
}
p.expect(T![')']);
m.complete(p, ARG_LIST);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,37 @@ SOURCE_FILE
PLUS "+"
R_PAREN ")"
SEMICOLON ";"
WHITESPACE "\n "
EXPR_STMT
CALL_EXPR
PATH_EXPR
PATH
PATH_SEGMENT
NAME_REF
IDENT "foo"
ARG_LIST
L_PAREN "("
PATH_EXPR
PATH
PATH_SEGMENT
NAME_REF
IDENT "a"
COMMA ","
WHITESPACE " "
COMMA ","
WHITESPACE " "
PATH_EXPR
PATH
PATH_SEGMENT
NAME_REF
IDENT "b"
R_PAREN ")"
SEMICOLON ";"
WHITESPACE "\n"
R_CURLY "}"
WHITESPACE "\n"
error 25: expected identifier
error 39: expected COMMA
error 39: expected expression
error 55: expected expression
error 68: expected expression
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ fn main() {
foo(bar::);
foo(bar:);
foo(bar+);
foo(a, , b);
}

0 comments on commit fcf2d9a

Please sign in to comment.