mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-28 10:39:45 +00:00
fix: Improve parser recovery a bit
This commit is contained in:
parent
62e7e2b489
commit
e0dca847ad
15 changed files with 86 additions and 20 deletions
|
|
@ -285,8 +285,6 @@ fn main() {
|
||||||
/* parse error: expected expression */
|
/* parse error: expected expression */
|
||||||
builtin #format_args (x = );
|
builtin #format_args (x = );
|
||||||
/* parse error: expected expression */
|
/* parse error: expected expression */
|
||||||
/* parse error: expected R_PAREN */
|
|
||||||
/* parse error: expected expression, item or let statement */
|
|
||||||
builtin #format_args (x = , x = 2);
|
builtin #format_args (x = , x = 2);
|
||||||
/* parse error: expected expression */
|
/* parse error: expected expression */
|
||||||
builtin #format_args ("{}", x = );
|
builtin #format_args ("{}", x = );
|
||||||
|
|
|
||||||
|
|
@ -661,9 +661,8 @@ fn expected_type_and_name(
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
cov_mark::hit!(expected_type_struct_field_without_leading_char);
|
cov_mark::hit!(expected_type_struct_field_without_leading_char);
|
||||||
let expr_field = token.prev_sibling_or_token()?
|
cov_mark::hit!(expected_type_struct_field_followed_by_comma);
|
||||||
.into_node()
|
let expr_field = previous_non_trivia_token(token.clone())?.parent().and_then(ast::RecordExprField::cast)?;
|
||||||
.and_then(ast::RecordExprField::cast)?;
|
|
||||||
let (_, _, ty) = sema.resolve_record_field(&expr_field)?;
|
let (_, _, ty) = sema.resolve_record_field(&expr_field)?;
|
||||||
Some((
|
Some((
|
||||||
Some(ty),
|
Some(ty),
|
||||||
|
|
@ -681,7 +680,6 @@ fn expected_type_and_name(
|
||||||
.or_else(|| sema.type_of_expr(&expr).map(TypeInfo::original));
|
.or_else(|| sema.type_of_expr(&expr).map(TypeInfo::original));
|
||||||
(ty, field_name)
|
(ty, field_name)
|
||||||
} else {
|
} else {
|
||||||
cov_mark::hit!(expected_type_struct_field_followed_by_comma);
|
|
||||||
(field_ty, field_name)
|
(field_ty, field_name)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use crate::grammar::attributes::ATTRIBUTE_FIRST;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub(super) use atom::{LITERAL_FIRST, literal};
|
pub(super) use atom::{EXPR_RECOVERY_SET, LITERAL_FIRST, literal};
|
||||||
pub(crate) use atom::{block_expr, match_arm_list};
|
pub(crate) use atom::{block_expr, match_arm_list};
|
||||||
|
|
||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq)]
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,6 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet =
|
||||||
T!['['],
|
T!['['],
|
||||||
T![|],
|
T![|],
|
||||||
T![async],
|
T![async],
|
||||||
T![box],
|
|
||||||
T![break],
|
T![break],
|
||||||
T![const],
|
T![const],
|
||||||
T![continue],
|
T![continue],
|
||||||
|
|
@ -68,7 +67,8 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet =
|
||||||
LIFETIME_IDENT,
|
LIFETIME_IDENT,
|
||||||
]));
|
]));
|
||||||
|
|
||||||
pub(super) const EXPR_RECOVERY_SET: TokenSet = TokenSet::new(&[T![')'], T![']']]);
|
pub(in crate::grammar) const EXPR_RECOVERY_SET: TokenSet =
|
||||||
|
TokenSet::new(&[T!['}'], T![')'], T![']'], T![,]]);
|
||||||
|
|
||||||
pub(super) fn atom_expr(
|
pub(super) fn atom_expr(
|
||||||
p: &mut Parser<'_>,
|
p: &mut Parser<'_>,
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,9 @@ pub(super) const ITEM_RECOVERY_SET: TokenSet = TokenSet::new(&[
|
||||||
T![impl],
|
T![impl],
|
||||||
T![trait],
|
T![trait],
|
||||||
T![const],
|
T![const],
|
||||||
|
T![async],
|
||||||
|
T![unsafe],
|
||||||
|
T![extern],
|
||||||
T![static],
|
T![static],
|
||||||
T![let],
|
T![let],
|
||||||
T![mod],
|
T![mod],
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ fn path_for_qualifier(
|
||||||
}
|
}
|
||||||
|
|
||||||
const EXPR_PATH_SEGMENT_RECOVERY_SET: TokenSet =
|
const EXPR_PATH_SEGMENT_RECOVERY_SET: TokenSet =
|
||||||
items::ITEM_RECOVERY_SET.union(TokenSet::new(&[T![')'], T![,], T![let]]));
|
expressions::EXPR_RECOVERY_SET.union(items::ITEM_RECOVERY_SET);
|
||||||
const TYPE_PATH_SEGMENT_RECOVERY_SET: TokenSet = types::TYPE_RECOVERY_SET;
|
const TYPE_PATH_SEGMENT_RECOVERY_SET: TokenSet = types::TYPE_RECOVERY_SET;
|
||||||
|
|
||||||
fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) -> Option<CompletedMarker> {
|
fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) -> Option<CompletedMarker> {
|
||||||
|
|
|
||||||
|
|
@ -199,8 +199,19 @@ fn pattern_single_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const PAT_RECOVERY_SET: TokenSet =
|
const PAT_RECOVERY_SET: TokenSet = TokenSet::new(&[
|
||||||
TokenSet::new(&[T![let], T![if], T![while], T![loop], T![match], T![')'], T![,], T![=]]);
|
T![let],
|
||||||
|
T![if],
|
||||||
|
T![while],
|
||||||
|
T![loop],
|
||||||
|
T![match],
|
||||||
|
T![')'],
|
||||||
|
T![']'],
|
||||||
|
T!['}'],
|
||||||
|
T![,],
|
||||||
|
T![=],
|
||||||
|
T![&],
|
||||||
|
]);
|
||||||
|
|
||||||
fn atom_pat(p: &mut Parser<'_>, recovery_set: TokenSet) -> Option<CompletedMarker> {
|
fn atom_pat(p: &mut Parser<'_>, recovery_set: TokenSet) -> Option<CompletedMarker> {
|
||||||
let m = match p.current() {
|
let m = match p.current() {
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,15 @@ pub(super) const TYPE_FIRST: TokenSet = paths::PATH_FIRST.union(TokenSet::new(&[
|
||||||
|
|
||||||
pub(super) const TYPE_RECOVERY_SET: TokenSet = TokenSet::new(&[
|
pub(super) const TYPE_RECOVERY_SET: TokenSet = TokenSet::new(&[
|
||||||
T![')'],
|
T![')'],
|
||||||
|
// test_err type_in_array_recover
|
||||||
|
// const _: [&];
|
||||||
|
T![']'],
|
||||||
|
T!['}'],
|
||||||
T![>],
|
T![>],
|
||||||
T![,],
|
T![,],
|
||||||
// test_err struct_field_recover
|
// test_err struct_field_recover
|
||||||
// struct S { f pub g: () }
|
// struct S { f pub g: () }
|
||||||
|
// struct S { f: pub g: () }
|
||||||
T![pub],
|
T![pub],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -870,6 +870,10 @@ mod err {
|
||||||
run_and_expect_errors("test_data/parser/inline/err/tuple_pat_leading_comma.rs");
|
run_and_expect_errors("test_data/parser/inline/err/tuple_pat_leading_comma.rs");
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
|
fn type_in_array_recover() {
|
||||||
|
run_and_expect_errors("test_data/parser/inline/err/type_in_array_recover.rs");
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
fn unsafe_block_in_mod() {
|
fn unsafe_block_in_mod() {
|
||||||
run_and_expect_errors("test_data/parser/inline/err/unsafe_block_in_mod.rs");
|
run_and_expect_errors("test_data/parser/inline/err/unsafe_block_in_mod.rs");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -149,7 +149,8 @@ error 17: expected expression, item or let statement
|
||||||
error 25: expected a name
|
error 25: expected a name
|
||||||
error 26: expected `;`, `{`, or `(`
|
error 26: expected `;`, `{`, or `(`
|
||||||
error 30: expected pattern
|
error 30: expected pattern
|
||||||
error 31: expected SEMICOLON
|
error 30: expected SEMICOLON
|
||||||
|
error 30: expected expression, item or let statement
|
||||||
error 53: expected expression
|
error 53: expected expression
|
||||||
error 54: expected R_PAREN
|
error 54: expected R_PAREN
|
||||||
error 54: expected SEMICOLON
|
error 54: expected SEMICOLON
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ SOURCE_FILE
|
||||||
L_CURLY "{"
|
L_CURLY "{"
|
||||||
WHITESPACE " "
|
WHITESPACE " "
|
||||||
DOT2 ".."
|
DOT2 ".."
|
||||||
ERROR
|
|
||||||
COMMA ","
|
COMMA ","
|
||||||
WHITESPACE " "
|
WHITESPACE " "
|
||||||
R_CURLY "}"
|
R_CURLY "}"
|
||||||
|
|
@ -39,7 +38,6 @@ SOURCE_FILE
|
||||||
L_CURLY "{"
|
L_CURLY "{"
|
||||||
WHITESPACE " "
|
WHITESPACE " "
|
||||||
DOT2 ".."
|
DOT2 ".."
|
||||||
ERROR
|
|
||||||
COMMA ","
|
COMMA ","
|
||||||
WHITESPACE " "
|
WHITESPACE " "
|
||||||
RECORD_EXPR_FIELD
|
RECORD_EXPR_FIELD
|
||||||
|
|
@ -55,5 +53,6 @@ SOURCE_FILE
|
||||||
R_CURLY "}"
|
R_CURLY "}"
|
||||||
WHITESPACE "\n"
|
WHITESPACE "\n"
|
||||||
error 21: expected expression
|
error 21: expected expression
|
||||||
|
error 21: cannot use a comma after the base struct
|
||||||
error 36: expected expression
|
error 36: expected expression
|
||||||
error 37: expected COMMA
|
error 36: cannot use a comma after the base struct
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,36 @@ SOURCE_FILE
|
||||||
WHITESPACE " "
|
WHITESPACE " "
|
||||||
R_CURLY "}"
|
R_CURLY "}"
|
||||||
WHITESPACE "\n"
|
WHITESPACE "\n"
|
||||||
|
STRUCT
|
||||||
|
STRUCT_KW "struct"
|
||||||
|
WHITESPACE " "
|
||||||
|
NAME
|
||||||
|
IDENT "S"
|
||||||
|
WHITESPACE " "
|
||||||
|
RECORD_FIELD_LIST
|
||||||
|
L_CURLY "{"
|
||||||
|
WHITESPACE " "
|
||||||
|
RECORD_FIELD
|
||||||
|
NAME
|
||||||
|
IDENT "f"
|
||||||
|
COLON ":"
|
||||||
|
WHITESPACE " "
|
||||||
|
RECORD_FIELD
|
||||||
|
VISIBILITY
|
||||||
|
PUB_KW "pub"
|
||||||
|
WHITESPACE " "
|
||||||
|
NAME
|
||||||
|
IDENT "g"
|
||||||
|
COLON ":"
|
||||||
|
WHITESPACE " "
|
||||||
|
TUPLE_TYPE
|
||||||
|
L_PAREN "("
|
||||||
|
R_PAREN ")"
|
||||||
|
WHITESPACE " "
|
||||||
|
R_CURLY "}"
|
||||||
|
WHITESPACE "\n"
|
||||||
error 12: expected COLON
|
error 12: expected COLON
|
||||||
error 12: expected type
|
error 12: expected type
|
||||||
error 12: expected COMMA
|
error 12: expected COMMA
|
||||||
|
error 38: expected type
|
||||||
|
error 38: expected COMMA
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
struct S { f pub g: () }
|
struct S { f pub g: () }
|
||||||
|
struct S { f: pub g: () }
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
SOURCE_FILE
|
||||||
|
CONST
|
||||||
|
CONST_KW "const"
|
||||||
|
WHITESPACE " "
|
||||||
|
UNDERSCORE "_"
|
||||||
|
COLON ":"
|
||||||
|
WHITESPACE " "
|
||||||
|
SLICE_TYPE
|
||||||
|
L_BRACK "["
|
||||||
|
REF_TYPE
|
||||||
|
AMP "&"
|
||||||
|
R_BRACK "]"
|
||||||
|
SEMICOLON ";"
|
||||||
|
WHITESPACE "\n"
|
||||||
|
error 11: expected type
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
const _: [&];
|
||||||
Loading…
Add table
Add a link
Reference in a new issue