mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-13 05:38:46 +00:00
start item recovery
This commit is contained in:
parent
faebae74e4
commit
8fc7f438c4
7 changed files with 40 additions and 9 deletions
|
@ -24,6 +24,10 @@ pub(super) enum ItemFlavor {
|
||||||
Mod, Trait
|
Mod, Trait
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ITEM_RECOVERY_SET: TokenSet =
|
||||||
|
token_set![FN_KW, STRUCT_KW, ENUM_KW, IMPL_KW, TRAIT_KW, CONST_KW, STATIC_KW, LET_KW,
|
||||||
|
MOD_KW, PUB_KW, CRATE_KW];
|
||||||
|
|
||||||
pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) {
|
pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) {
|
||||||
let m = p.start();
|
let m = p.start();
|
||||||
match maybe_item(p, flavor) {
|
match maybe_item(p, flavor) {
|
||||||
|
@ -231,7 +235,7 @@ fn fn_def(p: &mut Parser, flavor: ItemFlavor) {
|
||||||
assert!(p.at(FN_KW));
|
assert!(p.at(FN_KW));
|
||||||
p.bump();
|
p.bump();
|
||||||
|
|
||||||
name(p);
|
name_r(p, ITEM_RECOVERY_SET);
|
||||||
// test function_type_params
|
// test function_type_params
|
||||||
// fn foo<T: Clone + Copy>(){}
|
// fn foo<T: Clone + Copy>(){}
|
||||||
type_params::opt_type_param_list(p);
|
type_params::opt_type_param_list(p);
|
||||||
|
|
|
@ -4,7 +4,7 @@ pub(super) fn struct_def(p: &mut Parser) {
|
||||||
assert!(p.at(STRUCT_KW));
|
assert!(p.at(STRUCT_KW));
|
||||||
p.bump();
|
p.bump();
|
||||||
|
|
||||||
name(p);
|
name_r(p, ITEM_RECOVERY_SET);
|
||||||
type_params::opt_type_param_list(p);
|
type_params::opt_type_param_list(p);
|
||||||
match p.current() {
|
match p.current() {
|
||||||
WHERE_KW => {
|
WHERE_KW => {
|
||||||
|
@ -41,7 +41,7 @@ pub(super) fn struct_def(p: &mut Parser) {
|
||||||
pub(super) fn enum_def(p: &mut Parser) {
|
pub(super) fn enum_def(p: &mut Parser) {
|
||||||
assert!(p.at(ENUM_KW));
|
assert!(p.at(ENUM_KW));
|
||||||
p.bump();
|
p.bump();
|
||||||
name(p);
|
name_r(p, ITEM_RECOVERY_SET);
|
||||||
type_params::opt_type_param_list(p);
|
type_params::opt_type_param_list(p);
|
||||||
type_params::opt_where_clause(p);
|
type_params::opt_where_clause(p);
|
||||||
if p.at(L_CURLY) {
|
if p.at(L_CURLY) {
|
||||||
|
|
|
@ -5,7 +5,7 @@ use super::*;
|
||||||
pub(super) fn trait_def(p: &mut Parser) {
|
pub(super) fn trait_def(p: &mut Parser) {
|
||||||
assert!(p.at(TRAIT_KW));
|
assert!(p.at(TRAIT_KW));
|
||||||
p.bump();
|
p.bump();
|
||||||
name(p);
|
name_r(p, ITEM_RECOVERY_SET);
|
||||||
type_params::opt_type_param_list(p);
|
type_params::opt_type_param_list(p);
|
||||||
if p.at(COLON) {
|
if p.at(COLON) {
|
||||||
type_params::bounds(p);
|
type_params::bounds(p);
|
||||||
|
|
|
@ -129,16 +129,20 @@ fn opt_fn_ret_type(p: &mut Parser) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn name(p: &mut Parser) {
|
fn name_r(p: &mut Parser, recovery: TokenSet) {
|
||||||
if p.at(IDENT) {
|
if p.at(IDENT) {
|
||||||
let m = p.start();
|
let m = p.start();
|
||||||
p.bump();
|
p.bump();
|
||||||
m.complete(p, NAME);
|
m.complete(p, NAME);
|
||||||
} else {
|
} else {
|
||||||
p.err_and_bump("expected a name");
|
p.err_recover("expected a name", recovery);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn name(p: &mut Parser) {
|
||||||
|
name_r(p, TokenSet::EMPTY)
|
||||||
|
}
|
||||||
|
|
||||||
fn name_ref(p: &mut Parser) {
|
fn name_ref(p: &mut Parser) {
|
||||||
if p.at(IDENT) {
|
if p.at(IDENT) {
|
||||||
let m = p.start();
|
let m = p.start();
|
||||||
|
|
|
@ -12,7 +12,7 @@ fn mask(kind: SyntaxKind) -> u128 {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TokenSet {
|
impl TokenSet {
|
||||||
const EMPTY: TokenSet = TokenSet(0);
|
pub const EMPTY: TokenSet = TokenSet(0);
|
||||||
|
|
||||||
pub fn contains(&self, kind: SyntaxKind) -> bool {
|
pub fn contains(&self, kind: SyntaxKind) -> bool {
|
||||||
self.0 & mask(kind) != 0
|
self.0 & mask(kind) != 0
|
||||||
|
@ -145,10 +145,10 @@ impl<'t> Parser<'t> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an error node and consume the next token.
|
/// Create an error node and consume the next token.
|
||||||
pub(crate) fn err_recover(&mut self, message: &str, recovery_set: TokenSet) {
|
pub(crate) fn err_recover(&mut self, message: &str, recovery: TokenSet) {
|
||||||
if self.at(SyntaxKind::L_CURLY)
|
if self.at(SyntaxKind::L_CURLY)
|
||||||
|| self.at(SyntaxKind::R_CURLY)
|
|| self.at(SyntaxKind::R_CURLY)
|
||||||
|| recovery_set.contains(self.current()) {
|
|| recovery.contains(self.current()) {
|
||||||
self.error(message);
|
self.error(message);
|
||||||
} else {
|
} else {
|
||||||
let m = self.start();
|
let m = self.start();
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
fn
|
||||||
|
|
||||||
|
fn foo() {}
|
20
crates/libsyntax2/tests/data/parser/err/0020_fn_recover.txt
Normal file
20
crates/libsyntax2/tests/data/parser/err/0020_fn_recover.txt
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
ROOT@[0; 16)
|
||||||
|
FN_DEF@[0; 2)
|
||||||
|
FN_KW@[0; 2)
|
||||||
|
err: `expected a name`
|
||||||
|
err: `expected function arguments`
|
||||||
|
err: `expected a block`
|
||||||
|
WHITESPACE@[2; 4)
|
||||||
|
FN_DEF@[4; 15)
|
||||||
|
FN_KW@[4; 6)
|
||||||
|
WHITESPACE@[6; 7)
|
||||||
|
NAME@[7; 10)
|
||||||
|
IDENT@[7; 10) "foo"
|
||||||
|
PARAM_LIST@[10; 12)
|
||||||
|
L_PAREN@[10; 11)
|
||||||
|
R_PAREN@[11; 12)
|
||||||
|
WHITESPACE@[12; 13)
|
||||||
|
BLOCK@[13; 15)
|
||||||
|
L_CURLY@[13; 14)
|
||||||
|
R_CURLY@[14; 15)
|
||||||
|
WHITESPACE@[15; 16)
|
Loading…
Reference in a new issue