Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #19723 from Veykril/push-skswknpxtzlz
fix: Improve parser recovery a bit
Lukas Wirth 12 months ago
parent 1ad31ef · parent e0dca84 · commit 5d66d45
-rw-r--r--crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs2
-rw-r--r--crates/ide-completion/src/context/analysis.rs6
-rw-r--r--crates/parser/src/grammar/expressions.rs2
-rw-r--r--crates/parser/src/grammar/expressions/atom.rs4
-rw-r--r--crates/parser/src/grammar/items.rs3
-rw-r--r--crates/parser/src/grammar/paths.rs2
-rw-r--r--crates/parser/src/grammar/patterns.rs15
-rw-r--r--crates/parser/src/grammar/types.rs5
-rw-r--r--crates/parser/test_data/generated/runner.rs4
-rw-r--r--crates/parser/test_data/parser/err/0022_bad_exprs.rast7
-rw-r--r--crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rast9
-rw-r--r--crates/parser/test_data/parser/inline/err/struct_field_recover.rast30
-rw-r--r--crates/parser/test_data/parser/inline/err/struct_field_recover.rs1
-rw-r--r--crates/parser/test_data/parser/inline/err/type_in_array_recover.rast15
-rw-r--r--crates/parser/test_data/parser/inline/err/type_in_array_recover.rs1
15 files changed, 86 insertions, 20 deletions
diff --git a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
index a3b48831a0..e21d1415aa 100644
--- a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
+++ b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
@@ -285,8 +285,6 @@ fn main() {
/* parse error: expected expression */
builtin #format_args (x = );
/* parse error: expected expression */
-/* parse error: expected R_PAREN */
-/* parse error: expected expression, item or let statement */
builtin #format_args (x = , x = 2);
/* parse error: expected expression */
builtin #format_args ("{}", x = );
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index 5959973589..822dae2578 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -661,9 +661,8 @@ fn expected_type_and_name(
))
} else {
cov_mark::hit!(expected_type_struct_field_without_leading_char);
- let expr_field = token.prev_sibling_or_token()?
- .into_node()
- .and_then(ast::RecordExprField::cast)?;
+ cov_mark::hit!(expected_type_struct_field_followed_by_comma);
+ let expr_field = previous_non_trivia_token(token.clone())?.parent().and_then(ast::RecordExprField::cast)?;
let (_, _, ty) = sema.resolve_record_field(&expr_field)?;
Some((
Some(ty),
@@ -681,7 +680,6 @@ fn expected_type_and_name(
.or_else(|| sema.type_of_expr(&expr).map(TypeInfo::original));
(ty, field_name)
} else {
- cov_mark::hit!(expected_type_struct_field_followed_by_comma);
(field_ty, field_name)
}
},
diff --git a/crates/parser/src/grammar/expressions.rs b/crates/parser/src/grammar/expressions.rs
index 34dcf2a182..0ac25da329 100644
--- a/crates/parser/src/grammar/expressions.rs
+++ b/crates/parser/src/grammar/expressions.rs
@@ -4,7 +4,7 @@ use crate::grammar::attributes::ATTRIBUTE_FIRST;
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};
#[derive(PartialEq, Eq)]
diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs
index c66afed91c..5faf6fc275 100644
--- a/crates/parser/src/grammar/expressions/atom.rs
+++ b/crates/parser/src/grammar/expressions/atom.rs
@@ -46,7 +46,6 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet =
T!['['],
T![|],
T![async],
- T![box],
T![break],
T![const],
T![continue],
@@ -68,7 +67,8 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet =
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(
p: &mut Parser<'_>,
diff --git a/crates/parser/src/grammar/items.rs b/crates/parser/src/grammar/items.rs
index f5f003be48..b9f4866574 100644
--- a/crates/parser/src/grammar/items.rs
+++ b/crates/parser/src/grammar/items.rs
@@ -32,6 +32,9 @@ pub(super) const ITEM_RECOVERY_SET: TokenSet = TokenSet::new(&[
T![impl],
T![trait],
T![const],
+ T![async],
+ T![unsafe],
+ T![extern],
T![static],
T![let],
T![mod],
diff --git a/crates/parser/src/grammar/paths.rs b/crates/parser/src/grammar/paths.rs
index 3410505cd4..770827c6b0 100644
--- a/crates/parser/src/grammar/paths.rs
+++ b/crates/parser/src/grammar/paths.rs
@@ -81,7 +81,7 @@ fn path_for_qualifier(
}
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;
fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) -> Option<CompletedMarker> {
diff --git a/crates/parser/src/grammar/patterns.rs b/crates/parser/src/grammar/patterns.rs
index 460051a0f4..4dd44c030f 100644
--- a/crates/parser/src/grammar/patterns.rs
+++ b/crates/parser/src/grammar/patterns.rs
@@ -199,8 +199,19 @@ fn pattern_single_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
}
}
-const PAT_RECOVERY_SET: TokenSet =
- TokenSet::new(&[T![let], T![if], T![while], T![loop], T![match], T![')'], T![,], T![=]]);
+const PAT_RECOVERY_SET: TokenSet = TokenSet::new(&[
+ 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> {
let m = match p.current() {
diff --git a/crates/parser/src/grammar/types.rs b/crates/parser/src/grammar/types.rs
index 0133b7d5d8..9d31e435cf 100644
--- a/crates/parser/src/grammar/types.rs
+++ b/crates/parser/src/grammar/types.rs
@@ -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(&[
T![')'],
+ // test_err type_in_array_recover
+ // const _: [&];
+ T![']'],
+ T!['}'],
T![>],
T![,],
// test_err struct_field_recover
// struct S { f pub g: () }
+ // struct S { f: pub g: () }
T![pub],
]);
diff --git a/crates/parser/test_data/generated/runner.rs b/crates/parser/test_data/generated/runner.rs
index 6c9d02aaa8..24db9478ee 100644
--- a/crates/parser/test_data/generated/runner.rs
+++ b/crates/parser/test_data/generated/runner.rs
@@ -870,6 +870,10 @@ mod err {
run_and_expect_errors("test_data/parser/inline/err/tuple_pat_leading_comma.rs");
}
#[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() {
run_and_expect_errors("test_data/parser/inline/err/unsafe_block_in_mod.rs");
}
diff --git a/crates/parser/test_data/parser/err/0022_bad_exprs.rast b/crates/parser/test_data/parser/err/0022_bad_exprs.rast
index d97fc6c720..1a8e881dd9 100644
--- a/crates/parser/test_data/parser/err/0022_bad_exprs.rast
+++ b/crates/parser/test_data/parser/err/0022_bad_exprs.rast
@@ -35,8 +35,8 @@ SOURCE_FILE
WHITESPACE " "
LET_STMT
LET_KW "let"
- ERROR
- R_BRACK "]"
+ ERROR
+ R_BRACK "]"
WHITESPACE " "
R_CURLY "}"
WHITESPACE "\n"
@@ -149,7 +149,8 @@ error 17: expected expression, item or let statement
error 25: expected a name
error 26: expected `;`, `{`, or `(`
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 54: expected R_PAREN
error 54: expected SEMICOLON
diff --git a/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rast b/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rast
index feb617e1aa..b57066f2fb 100644
--- a/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rast
+++ b/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rast
@@ -23,8 +23,7 @@ SOURCE_FILE
L_CURLY "{"
WHITESPACE " "
DOT2 ".."
- ERROR
- COMMA ","
+ COMMA ","
WHITESPACE " "
R_CURLY "}"
SEMICOLON ";"
@@ -39,8 +38,7 @@ SOURCE_FILE
L_CURLY "{"
WHITESPACE " "
DOT2 ".."
- ERROR
- COMMA ","
+ COMMA ","
WHITESPACE " "
RECORD_EXPR_FIELD
NAME_REF
@@ -55,5 +53,6 @@ SOURCE_FILE
R_CURLY "}"
WHITESPACE "\n"
error 21: expected expression
+error 21: cannot use a comma after the base struct
error 36: expected expression
-error 37: expected COMMA
+error 36: cannot use a comma after the base struct
diff --git a/crates/parser/test_data/parser/inline/err/struct_field_recover.rast b/crates/parser/test_data/parser/inline/err/struct_field_recover.rast
index 458d7f4e2f..5a12c21b64 100644
--- a/crates/parser/test_data/parser/inline/err/struct_field_recover.rast
+++ b/crates/parser/test_data/parser/inline/err/struct_field_recover.rast
@@ -26,6 +26,36 @@ SOURCE_FILE
WHITESPACE " "
R_CURLY "}"
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 type
error 12: expected COMMA
+error 38: expected type
+error 38: expected COMMA
diff --git a/crates/parser/test_data/parser/inline/err/struct_field_recover.rs b/crates/parser/test_data/parser/inline/err/struct_field_recover.rs
index da32227adc..5b1e5a5b8a 100644
--- a/crates/parser/test_data/parser/inline/err/struct_field_recover.rs
+++ b/crates/parser/test_data/parser/inline/err/struct_field_recover.rs
@@ -1 +1,2 @@
struct S { f pub g: () }
+struct S { f: pub g: () }
diff --git a/crates/parser/test_data/parser/inline/err/type_in_array_recover.rast b/crates/parser/test_data/parser/inline/err/type_in_array_recover.rast
new file mode 100644
index 0000000000..db76e8d7c8
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/err/type_in_array_recover.rast
@@ -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
diff --git a/crates/parser/test_data/parser/inline/err/type_in_array_recover.rs b/crates/parser/test_data/parser/inline/err/type_in_array_recover.rs
new file mode 100644
index 0000000000..039bf82997
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/err/type_in_array_recover.rs
@@ -0,0 +1 @@
+const _: [&];