diff --git a/crates/rslint_parser/src/parser.rs b/crates/rslint_parser/src/parser.rs index 202bb0fc005..aa5d64ef87a 100644 --- a/crates/rslint_parser/src/parser.rs +++ b/crates/rslint_parser/src/parser.rs @@ -191,11 +191,20 @@ impl<'t> Parser<'t> { } /// Recover from an error with a recovery set or by using a `{` or `}`. + /// + /// # Arguments + /// + /// * `error` - the [Diagnostic] to emit + /// * `recovery` - it recovers the parser position is inside a set [tokens](TokenSet) + /// * `include_braces` - it recovers the parser if the current token is a curly brace + /// * `unknown_node` - The kind of the unknown node the parser inserts if it isn't able to recover because + /// the current token is neither in the recovery set nor any of `{` or `}`. pub fn err_recover( &mut self, error: impl Into, recovery: TokenSet, include_braces: bool, + unknown_node: SyntaxKind, ) -> Option<()> { if self.state.no_recovery { return None; @@ -217,12 +226,24 @@ impl<'t> Parser<'t> { let m = self.start(); self.error(error); self.bump_any(); - m.complete(self, SyntaxKind::ERROR); + m.complete(self, unknown_node); Some(()) } /// Recover from an error but don't add an error to the events - pub fn err_recover_no_err(&mut self, recovery: TokenSet, include_braces: bool) { + /// + /// # Arguments + /// + /// * `recovery` - it recovers the parser position is inside a set [tokens](TokenSet) + /// * `include_braces` - it recovers the parser if the current token is a curly brace + /// * `unknown_node` - The kind of the unknown node the parser inserts if it isn't able to recover because + /// the current token is neither in the recovery set nor any of `{` or `}`. + pub fn err_recover_no_err( + &mut self, + recovery: TokenSet, + include_braces: bool, + unknown_node: SyntaxKind, + ) { match self.cur() { T!['{'] | T!['}'] if include_braces => { return; @@ -239,7 +260,7 @@ impl<'t> Parser<'t> { let m = self.start(); self.bump_any(); - m.complete(self, SyntaxKind::ERROR); + m.complete(self, unknown_node); } /// Starts a new node in the syntax tree. All nodes and tokens diff --git a/crates/rslint_parser/src/syntax/decl.rs b/crates/rslint_parser/src/syntax/decl.rs index 44e07d02b03..40ca469a14b 100644 --- a/crates/rslint_parser/src/syntax/decl.rs +++ b/crates/rslint_parser/src/syntax/decl.rs @@ -220,6 +220,7 @@ pub(super) fn parameters_list( T![')'], ], true, + ERROR, ); None } diff --git a/crates/rslint_parser/src/syntax/expr.rs b/crates/rslint_parser/src/syntax/expr.rs index cc94cb25bd9..4cca90f50c2 100644 --- a/crates/rslint_parser/src/syntax/expr.rs +++ b/crates/rslint_parser/src/syntax/expr.rs @@ -722,7 +722,7 @@ pub fn paren_or_arrow_expr(p: &mut Parser, can_be_arrow: bool) -> CompletedMarke let err = temp.err_builder(&format!("expect a closing parenthesis after a spread element, but instead found `{}`", temp.cur_src())) .primary(temp.cur_tok().range, ""); - temp.err_recover(err, EXPR_RECOVERY_SET, false); + temp.err_recover(err, EXPR_RECOVERY_SET, false, ERROR); } } break; @@ -1058,7 +1058,7 @@ pub fn primary_expr(p: &mut Parser) -> Option { let err = p .err_builder("Expected an expression, but found none") .primary(p.cur_tok().range, "Expected an expression here"); - p.err_recover(err, p.state.expr_recovery_set, true); + p.err_recover(err, p.state.expr_recovery_set, true, ERROR); return None; } }; @@ -1078,7 +1078,7 @@ pub fn identifier_reference(p: &mut Parser) -> Option { .err_builder("Expected an identifier, but found none") .primary(p.cur_tok().range, ""); - p.err_recover(err, p.state.expr_recovery_set, true); + p.err_recover(err, p.state.expr_recovery_set, true, ERROR); None } } diff --git a/crates/rslint_parser/src/syntax/object.rs b/crates/rslint_parser/src/syntax/object.rs index 58667b1fc7c..3e89b9899ac 100644 --- a/crates/rslint_parser/src/syntax/object.rs +++ b/crates/rslint_parser/src/syntax/object.rs @@ -139,7 +139,7 @@ fn object_member(p: &mut Parser) -> Option { // test_err object_expr_non_ident_literal_prop // let b = {5} - p.err_recover_no_err(token_set![T![:], T![,]], false); + p.err_recover_no_err(token_set![T![:], T![,]], false, ERROR); if p.eat(T![:]) { assign_expr(p); @@ -304,7 +304,7 @@ fn method_object_member_body(p: &mut Parser) -> Result<(), ()> { .err_builder("expected a method definition, but found none") .primary(p.cur_tok().range, ""); - p.err_recover(err, BASE_METHOD_RECOVERY_SET, false); + p.err_recover(err, BASE_METHOD_RECOVERY_SET, false, ERROR); Err(()) }; diff --git a/crates/rslint_parser/src/syntax/pat.rs b/crates/rslint_parser/src/syntax/pat.rs index 95d69c42169..617978f705f 100644 --- a/crates/rslint_parser/src/syntax/pat.rs +++ b/crates/rslint_parser/src/syntax/pat.rs @@ -77,7 +77,7 @@ pub fn pattern(p: &mut Parser, parameters: bool, assignment: bool) -> Option Option>) -> Option return None; } - p.err_recover(err, recovery_set.into().unwrap_or(STMT_RECOVERY_SET), false); + p.err_recover( + err, + recovery_set.into().unwrap_or(STMT_RECOVERY_SET), + false, + ERROR, + ); return None; } }; @@ -995,7 +1000,7 @@ fn switch_clause(p: &mut Parser) -> Option> { "Expected the start to a case or default clause here", ); - p.err_recover(err, STMT_RECOVERY_SET, true); + p.err_recover(err, STMT_RECOVERY_SET, true, ERROR); } } None diff --git a/crates/rslint_parser/src/syntax/typescript.rs b/crates/rslint_parser/src/syntax/typescript.rs index 380c9c7e2ce..5b9a2304e85 100644 --- a/crates/rslint_parser/src/syntax/typescript.rs +++ b/crates/rslint_parser/src/syntax/typescript.rs @@ -607,6 +607,7 @@ pub fn ts_enum(p: &mut Parser) -> CompletedMarker { err, token_set![T!['}'], T![ident], T![yield], T![await], T![=], T![,]], false, + ERROR, ); true } else { @@ -1052,6 +1053,7 @@ pub fn ts_non_array_type(p: &mut Parser) -> Option { T![|] ]), false, + ERROR, ); None } @@ -1164,6 +1166,7 @@ fn type_param(p: &mut Parser) -> Option { err, token_set![T![ident], T![yield], T![await], T![>], T![=]], false, + ERROR, ); None } @@ -1400,6 +1403,6 @@ pub fn ts_type_name( )) .primary(p.cur_tok().range, ""); - p.err_recover(err, set, false)?; + p.err_recover(err, set, false, ERROR)?; None }