perf: Remove cloning of parser
Remove full clones of the whole `parser` from the JS parser implementation.
MODIFY
crates/rslint_parser/src/parser.rs
crates/rslint_parser/src/parser.rs
@@ -115,7 +115,6 @@ impl ParserProgress {
///
/// assert_eq!(typed_expr.expression().unwrap().syntax().text(), "delete b");
/// ```
-#[derive(Clone)]
pub struct Parser<'t> {
pub file_id: usize,
tokens: TokenSource<'t>,

MODIFY
crates/rslint_parser/src/syntax/expr.rs
crates/rslint_parser/src/syntax/expr.rs
@@ -759,36 +759,7 @@ pub fn paren_or_arrow_expr(p: &mut Parser, can_be_arrow: bool) -> CompletedMarke
}
drop(temp);
- // if we are in a ternary expression, then we need to try and see if parsing as an arrow worked
- // if it did then we just return it, otherwise it should be interpreted as a grouping expr
- if p.state.in_cond_expr && p.at(T![:]) && params_marker.is_none() {
- let func = |p: &mut Parser| {
- let p = &mut *p.with_state(ParserState {
- no_recovery: true,
- ..p.state.clone()
- });
- p.rewind(checkpoint);
- parse_parameter_list(p).or_missing_with_error(p, js_parse_error::expected_parameters);
- if p.at(T![:]) {
- if let Some(mut ret) = ts_type_or_type_predicate_ann(p, T![:]) {
- ret.err_if_not_ts(
- p,
- "arrow functions can only have return types in TypeScript files",
- );
- }
- }
- p.expect_no_recover(T![=>])?;
- parse_arrow_body(p).or_missing_with_error(p, js_parse_error::expected_arrow_body)
- };
- // we can't just rewind the parser, since the function rewinds, and cloning and replacing the
- // events does not work apparently, therefore we need to clone the entire parser
- let cloned = p.clone();
- if func(p).is_some() {
- return m.complete(p, JS_ARROW_FUNCTION_EXPRESSION);
- } else {
- *p = cloned;
- }
- }
+
let has_ret_type = !p.state.in_cond_expr && p.at(T![:]) && !p.state.in_case_cond;
// This is an arrow expr, so we rewind the parser and reparse as parameters

MODIFY
crates/rslint_parser/src/syntax/typescript.rs
crates/rslint_parser/src/syntax/typescript.rs
@@ -685,16 +685,19 @@ pub fn try_parse_ts(
p: &mut Parser,
func: impl FnOnce(&mut Parser) -> Option<CompletedMarker>,
) -> Option<CompletedMarker> {
- // FIXME: simply rewinding doesnt work for `new A < T;` and it makes the parser enter unreachable
- // code, and i really cant be bothered to debug incorrect event code because i don't have enough sanity
- // left in me
- let old = p.to_owned();
- let res = func(&mut *p.with_state(ParserState {
+ let checkpoint = p.checkpoint();
+
+ let res = if p.state.no_recovery {
+ func(p)
+ } else {
+ func(&mut *p.with_state(ParserState {
no_recovery: true,
..p.state.clone()
- }));
+ }))
+ };
+
if res.is_none() {
- *p = old;
+ p.rewind(checkpoint);
}
res
}

MODIFY
crates/rslint_parser/src/token_source.rs
crates/rslint_parser/src/token_source.rs
@@ -3,7 +3,6 @@ use rslint_lexer::is_linebreak;
use std::collections::HashSet;
/// The source of tokens for the parser
-#[derive(Clone)]
pub struct TokenSource<'t> {
source: &'t str,
/// Hashset of offsets for tokens which occur after a linebreak.

perf: Remove cloning of parser (#1841)

Remove full clones of the whole `parser` from the JS parser implementation.