mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-14 06:15:27 +00:00
fix: Recover from missing argument in call expressions
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.
This commit is contained in:
parent
bcc8a09a0d
commit
e865d45904
4 changed files with 53 additions and 22 deletions
|
@ -631,20 +631,6 @@ fn foo () {a . b ; bar () ;}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn extraneous_comma() {
|
|
||||||
check(
|
|
||||||
r#"
|
|
||||||
fn foo() {
|
|
||||||
bar(,);
|
|
||||||
}
|
|
||||||
"#,
|
|
||||||
expect![[r#"
|
|
||||||
fn foo () {__ra_fixup ;}
|
|
||||||
"#]],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn fixup_if_1() {
|
fn fixup_if_1() {
|
||||||
check(
|
check(
|
||||||
|
|
|
@ -611,6 +611,7 @@ fn cast_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
|
||||||
// foo(bar::);
|
// foo(bar::);
|
||||||
// foo(bar:);
|
// foo(bar:);
|
||||||
// foo(bar+);
|
// foo(bar+);
|
||||||
|
// foo(a, , b);
|
||||||
// }
|
// }
|
||||||
fn arg_list(p: &mut Parser<'_>) {
|
fn arg_list(p: &mut Parser<'_>) {
|
||||||
assert!(p.at(T!['(']));
|
assert!(p.at(T!['(']));
|
||||||
|
@ -619,14 +620,30 @@ fn arg_list(p: &mut Parser<'_>) {
|
||||||
// fn main() {
|
// fn main() {
|
||||||
// foo(#[attr] 92)
|
// foo(#[attr] 92)
|
||||||
// }
|
// }
|
||||||
delimited(
|
p.bump(T!['(']);
|
||||||
p,
|
while !p.at(T![')']) && !p.at(EOF) {
|
||||||
T!['('],
|
if p.at(T![,]) {
|
||||||
T![')'],
|
// Recover if an argument is missing and only got a delimiter,
|
||||||
T![,],
|
// e.g. `(a, , b)`.
|
||||||
EXPR_FIRST.union(ATTRIBUTE_FIRST),
|
p.error("expected expression");
|
||||||
|p: &mut Parser<'_>| expr(p).is_some(),
|
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);
|
m.complete(p, ARG_LIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,32 @@ SOURCE_FILE
|
||||||
PLUS "+"
|
PLUS "+"
|
||||||
R_PAREN ")"
|
R_PAREN ")"
|
||||||
SEMICOLON ";"
|
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"
|
WHITESPACE "\n"
|
||||||
R_CURLY "}"
|
R_CURLY "}"
|
||||||
WHITESPACE "\n"
|
WHITESPACE "\n"
|
||||||
|
@ -75,3 +101,4 @@ error 25: expected identifier
|
||||||
error 39: expected COMMA
|
error 39: expected COMMA
|
||||||
error 39: expected expression
|
error 39: expected expression
|
||||||
error 55: expected expression
|
error 55: expected expression
|
||||||
|
error 68: expected expression
|
||||||
|
|
|
@ -2,4 +2,5 @@ fn main() {
|
||||||
foo(bar::);
|
foo(bar::);
|
||||||
foo(bar:);
|
foo(bar:);
|
||||||
foo(bar+);
|
foo(bar+);
|
||||||
|
foo(a, , b);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue