diff --git a/crates/oxc_parser/src/js/arrow.rs b/crates/oxc_parser/src/js/arrow.rs index 632d5cc71f72d..4f536b8ab2cb5 100644 --- a/crates/oxc_parser/src/js/arrow.rs +++ b/crates/oxc_parser/src/js/arrow.rs @@ -79,7 +79,7 @@ impl<'a> ParserImpl<'a> { Kind::RParen => { let third = self.nth_kind(offset + 2); return match third { - Kind::Colon if self.ts_enabled() => Tristate::Maybe, + Kind::Colon if self.is_ts => Tristate::Maybe, Kind::Arrow | Kind::LCurly => Tristate::True, _ => Tristate::False, }; diff --git a/crates/oxc_parser/src/js/binding.rs b/crates/oxc_parser/src/js/binding.rs index af0b05cddf707..07df82ee1c984 100644 --- a/crates/oxc_parser/src/js/binding.rs +++ b/crates/oxc_parser/src/js/binding.rs @@ -19,8 +19,7 @@ impl<'a> ParserImpl<'a> { allow_question: bool, ) -> Result> { let mut kind = self.parse_binding_pattern_kind()?; - let optional = - if allow_question && self.ts_enabled() { self.eat(Kind::Question) } else { false }; + let optional = if allow_question && self.is_ts { self.eat(Kind::Question) } else { false }; let type_annotation = self.parse_ts_type_annotation()?; if let Some(type_annotation) = &type_annotation { Self::extend_binding_pattern_span_end(type_annotation.span, &mut kind); @@ -111,7 +110,7 @@ impl<'a> ParserImpl<'a> { let kind = self.parse_binding_pattern_kind()?; // Rest element does not allow `?`, checked in checker/typescript.rs - if self.at(Kind::Question) && self.ts_enabled() { + if self.at(Kind::Question) && self.is_ts { let span = self.cur_token().span(); self.bump_any(); self.error(diagnostics::a_rest_parameter_cannot_be_optional(span)); diff --git a/crates/oxc_parser/src/js/class.rs b/crates/oxc_parser/src/js/class.rs index d8ed536cf7bb4..089bd49e04b63 100644 --- a/crates/oxc_parser/src/js/class.rs +++ b/crates/oxc_parser/src/js/class.rs @@ -75,8 +75,7 @@ impl<'a> ParserImpl<'a> { None }; - let type_parameters = - if self.ts_enabled() { self.parse_ts_type_parameters()? } else { None }; + let type_parameters = if self.is_ts { self.parse_ts_type_parameters()? } else { None }; let (extends, implements) = self.parse_heritage_clause()?; let mut super_class = None; let mut super_type_parameters = None; @@ -283,7 +282,7 @@ impl<'a> ParserImpl<'a> { if let PropertyKey::PrivateIdentifier(private_ident) = &key { // `private #foo`, etc. is illegal - if self.ts_enabled() { + if self.is_ts { self.verify_modifiers( &modifiers, ModifierFlags::all() - ModifierFlags::ACCESSIBILITY, @@ -457,8 +456,7 @@ impl<'a> ParserImpl<'a> { optional: bool, definite: bool, ) -> Result> { - let type_annotation = - if self.ts_enabled() { self.parse_ts_type_annotation()? } else { None }; + let type_annotation = if self.is_ts { self.parse_ts_type_annotation()? } else { None }; let decorators = self.consume_decorators(); let value = if self.eat(Kind::Eq) { Some(self.parse_expr()?) } else { None }; self.asi()?; @@ -506,8 +504,7 @@ impl<'a> ParserImpl<'a> { definite: bool, accessibility: Option, ) -> Result> { - let type_annotation = - if self.ts_enabled() { self.parse_ts_type_annotation()? } else { None }; + let type_annotation = if self.is_ts { self.parse_ts_type_annotation()? } else { None }; let value = self.eat(Kind::Eq).then(|| self.parse_assignment_expression_or_higher()).transpose()?; let r#type = if r#abstract { diff --git a/crates/oxc_parser/src/js/declaration.rs b/crates/oxc_parser/src/js/declaration.rs index b7d4757b82ca6..ab8f87132e367 100644 --- a/crates/oxc_parser/src/js/declaration.rs +++ b/crates/oxc_parser/src/js/declaration.rs @@ -95,7 +95,7 @@ impl<'a> ParserImpl<'a> { let mut binding_kind = self.parse_binding_pattern_kind()?; - let (id, definite) = if self.ts_enabled() { + let (id, definite) = if self.is_ts { // const x!: number = 1 // ^ definite let mut definite = false; diff --git a/crates/oxc_parser/src/js/expression.rs b/crates/oxc_parser/src/js/expression.rs index f028f08172052..3edbf02f0230e 100644 --- a/crates/oxc_parser/src/js/expression.rs +++ b/crates/oxc_parser/src/js/expression.rs @@ -644,7 +644,7 @@ impl<'a> ParserImpl<'a> { _ => break, } } - Kind::Bang if !self.cur_token().is_on_new_line && self.ts_enabled() => { + Kind::Bang if !self.cur_token().is_on_new_line && self.is_ts => { self.bump_any(); self.ast.expression_ts_non_null(self.end_span(lhs_span), lhs) } @@ -905,7 +905,7 @@ impl<'a> ParserImpl<'a> { if self.source_type.is_jsx() { return self.parse_jsx_expression(); } - if self.ts_enabled() { + if self.is_ts { return self.parse_ts_type_assertion(); } Err(self.unexpected()) @@ -951,13 +951,12 @@ impl<'a> ParserImpl<'a> { // Pratt Parsing Algorithm // let mut lhs = lhs; - let is_ts = self.ts_enabled(); loop { // re-lex for `>=` `>>` `>>>` // This is need for jsx `
=
` case let kind = self.re_lex_right_angle(); - let Some(left_precedence) = kind_to_precedence(kind, is_ts) else { break }; + let Some(left_precedence) = kind_to_precedence(kind, self.is_ts) else { break }; let stop = if left_precedence.is_right_associative() { left_precedence < min_precedence @@ -976,7 +975,7 @@ impl<'a> ParserImpl<'a> { break; } - if self.ts_enabled() && matches!(kind, Kind::As | Kind::Satisfies) { + if self.is_ts && matches!(kind, Kind::As | Kind::Satisfies) { if self.cur_token().is_on_new_line { break; } diff --git a/crates/oxc_parser/src/js/function.rs b/crates/oxc_parser/src/js/function.rs index a5bb794897c43..e204053c46314 100644 --- a/crates/oxc_parser/src/js/function.rs +++ b/crates/oxc_parser/src/js/function.rs @@ -47,7 +47,7 @@ impl<'a> ParserImpl<'a> { ) -> Result<(Option>, Box<'a, FormalParameters<'a>>)> { let span = self.start_span(); self.expect(Kind::LParen)?; - let this_param = if self.ts_enabled() && self.at(Kind::This) { + let this_param = if self.is_ts && self.at(Kind::This) { let param = self.parse_ts_this_parameter()?; if !self.at(Kind::RParen) { self.expect(Kind::Comma)?; @@ -135,7 +135,7 @@ impl<'a> ParserImpl<'a> { self.ctx = self.ctx.and_in(ctx.has_in()).and_await(ctx.has_await()).and_yield(ctx.has_yield()); - if !self.ts_enabled() && body.is_none() { + if !self.is_ts && body.is_none() { return Err(self.unexpected()); } diff --git a/crates/oxc_parser/src/js/module.rs b/crates/oxc_parser/src/js/module.rs index 088b4a424a818..82ada7b37b441 100644 --- a/crates/oxc_parser/src/js/module.rs +++ b/crates/oxc_parser/src/js/module.rs @@ -34,7 +34,7 @@ impl<'a> ParserImpl<'a> { self.bump_any(); // advance `import` - if self.ts_enabled() + if self.is_ts && ((self.cur_kind().is_binding_identifier() && self.peek_at(Kind::Eq)) || (self.at(Kind::Type) && self.peek_kind().is_binding_identifier() @@ -208,10 +208,10 @@ impl<'a> ParserImpl<'a> { self.bump_any(); // advance `export` let decl = match self.cur_kind() { - Kind::Eq if self.ts_enabled() => self + Kind::Eq if self.is_ts => self .parse_ts_export_assignment_declaration(span) .map(ModuleDeclaration::TSExportAssignment), - Kind::As if self.peek_at(Kind::Namespace) && self.ts_enabled() => self + Kind::As if self.peek_at(Kind::Namespace) && self.is_ts => self .parse_ts_export_namespace() .map(ModuleDeclaration::TSNamespaceExportDeclaration), Kind::Default => self @@ -223,7 +223,7 @@ impl<'a> ParserImpl<'a> { Kind::LCurly => self .parse_export_named_specifiers(span) .map(ModuleDeclaration::ExportNamedDeclaration), - Kind::Type if self.peek_at(Kind::LCurly) && self.ts_enabled() => self + Kind::Type if self.peek_at(Kind::LCurly) && self.is_ts => self .parse_export_named_specifiers(span) .map(ModuleDeclaration::ExportNamedDeclaration), Kind::Type if self.peek_at(Kind::Star) => { @@ -328,11 +328,8 @@ impl<'a> ParserImpl<'a> { // For tc39/proposal-decorators // For more information, please refer to self.eat_decorators()?; - let modifiers = if self.ts_enabled() { - self.eat_modifiers_before_declaration()? - } else { - Modifiers::empty() - }; + let modifiers = + if self.is_ts { self.eat_modifiers_before_declaration()? } else { Modifiers::empty() }; let declaration = self.parse_declaration(decl_span, &modifiers)?; let span = self.end_span(span); @@ -362,16 +359,13 @@ impl<'a> ParserImpl<'a> { Kind::Class => self .parse_class_declaration(decl_span, /* modifiers */ &Modifiers::empty()) .map(ExportDefaultDeclarationKind::ClassDeclaration)?, - _ if self.at(Kind::Abstract) && self.peek_at(Kind::Class) && self.ts_enabled() => { + _ if self.at(Kind::Abstract) && self.peek_at(Kind::Class) && self.is_ts => { // eat the abstract modifier let modifiers = self.eat_modifiers_before_declaration()?; self.parse_class_declaration(decl_span, &modifiers) .map(ExportDefaultDeclarationKind::ClassDeclaration)? } - _ if self.at(Kind::Interface) - && !self.peek_token().is_on_new_line - && self.ts_enabled() => - { + _ if self.at(Kind::Interface) && !self.peek_token().is_on_new_line && self.is_ts => { self.parse_ts_interface_declaration(decl_span, &Modifiers::empty()).map(|decl| { match decl { Declaration::TSInterfaceDeclaration(decl) => { @@ -424,7 +418,7 @@ impl<'a> ParserImpl<'a> { let specifier_span = self.start_span(); let peek_kind = self.peek_kind(); let mut import_kind = ImportOrExportKind::Value; - if self.ts_enabled() && self.at(Kind::Type) { + if self.is_ts && self.at(Kind::Type) { if self.peek_at(Kind::As) { if self.nth_at(2, Kind::As) { if self.nth_kind(3).is_identifier_name() { @@ -477,7 +471,7 @@ impl<'a> ParserImpl<'a> { } fn parse_import_or_export_kind(&mut self) -> ImportOrExportKind { - if !self.ts_enabled() { + if !self.is_ts { return ImportOrExportKind::Value; } // OK @@ -521,7 +515,7 @@ impl<'a> ParserImpl<'a> { // export { type as as } // name: `type` type-export: `false` (aliased to `as`) // export { type as as as } // name: `as` type-export: `true`, aliased to `as` let mut export_kind = ImportOrExportKind::Value; - if self.ts_enabled() && self.at(Kind::Type) { + if self.is_ts && self.at(Kind::Type) { if self.peek_at(Kind::As) { if self.nth_at(2, Kind::As) { if self.nth_at(3, Kind::Str) || self.nth_kind(3).is_identifier_name() { diff --git a/crates/oxc_parser/src/js/object.rs b/crates/oxc_parser/src/js/object.rs index f6aaa6e608ac4..71976138f37e0 100644 --- a/crates/oxc_parser/src/js/object.rs +++ b/crates/oxc_parser/src/js/object.rs @@ -65,7 +65,7 @@ impl<'a> ParserImpl<'a> { // Report and handle illegal modifiers // e.g. const x = { public foo() {} } modifier_kind - if self.ts_enabled() + if self.is_ts && modifier_kind.is_modifier_kind() && peek_kind.is_identifier_or_keyword() => { diff --git a/crates/oxc_parser/src/js/statement.rs b/crates/oxc_parser/src/js/statement.rs index da4edcee57722..4c9ceafa8cbcf 100644 --- a/crates/oxc_parser/src/js/statement.rs +++ b/crates/oxc_parser/src/js/statement.rs @@ -105,7 +105,7 @@ impl<'a> ParserImpl<'a> { // [+Return] ReturnStatement[?Yield, ?Await] Kind::Return => self.parse_return_statement(), Kind::Var => self.parse_variable_statement(stmt_ctx), - Kind::Const if !(self.ts_enabled() && self.is_at_enum_declaration()) => { + Kind::Const if !(self.is_ts && self.is_at_enum_declaration()) => { self.parse_variable_statement(stmt_ctx) } Kind::Let if !self.cur_token().escaped() => self.parse_let(stmt_ctx), @@ -116,7 +116,7 @@ impl<'a> ParserImpl<'a> { } Kind::Using if self.peek_kind().is_binding_identifier() => self.parse_using(), _ if self.at_function_with_async() => self.parse_function_declaration(stmt_ctx), - _ if self.ts_enabled() && self.at_start_of_ts_declaration() => { + _ if self.is_ts && self.at_start_of_ts_declaration() => { self.parse_ts_declaration_statement(start_span) } _ => self.parse_expression_or_labeled_statement(), diff --git a/crates/oxc_parser/src/jsx/mod.rs b/crates/oxc_parser/src/jsx/mod.rs index 62cd1bccae1f5..6c06b45e88b91 100644 --- a/crates/oxc_parser/src/jsx/mod.rs +++ b/crates/oxc_parser/src/jsx/mod.rs @@ -95,8 +95,7 @@ impl<'a> ParserImpl<'a> { self.expect(Kind::LAngle)?; let name = self.parse_jsx_element_name()?; // for tsx - let type_parameters = - if self.ts_enabled() { self.try_parse_type_arguments()? } else { None }; + let type_parameters = if self.is_ts { self.try_parse_type_arguments()? } else { None }; let attributes = self.parse_jsx_attributes()?; let self_closing = self.eat(Kind::Slash); if !self_closing || in_jsx_child { diff --git a/crates/oxc_parser/src/lib.rs b/crates/oxc_parser/src/lib.rs index b7f0419dd3775..264771157cf76 100644 --- a/crates/oxc_parser/src/lib.rs +++ b/crates/oxc_parser/src/lib.rs @@ -356,8 +356,11 @@ struct ParserImpl<'a> { /// Parsing context ctx: Context, - /// Ast builder for creating AST spans + /// Ast builder for creating AST nodes ast: AstBuilder<'a>, + + /// Precomputed typescript detection + is_ts: bool, } impl<'a> ParserImpl<'a> { @@ -384,6 +387,7 @@ impl<'a> ParserImpl<'a> { state: ParserState::default(), ctx: Self::default_context(source_type, options), ast: AstBuilder::new(allocator), + is_ts: source_type.is_typescript(), } } @@ -508,10 +512,6 @@ impl<'a> ParserImpl<'a> { self.errors.len() + self.lexer.errors.len() } - fn ts_enabled(&self) -> bool { - self.source_type.is_typescript() - } - fn set_source_type_to_module_if_unambiguous(&mut self) { if self.source_type.is_unambiguous() { self.source_type = self.source_type.with_module(true); diff --git a/crates/oxc_parser/src/ts/statement.rs b/crates/oxc_parser/src/ts/statement.rs index ecf6a898ad4f5..6fb24353b15ba 100644 --- a/crates/oxc_parser/src/ts/statement.rs +++ b/crates/oxc_parser/src/ts/statement.rs @@ -116,7 +116,7 @@ impl<'a> ParserImpl<'a> { pub(crate) fn parse_ts_type_annotation( &mut self, ) -> Result>>> { - if !self.ts_enabled() { + if !self.is_ts { return Ok(None); } if !self.at(Kind::Colon) { @@ -398,7 +398,7 @@ impl<'a> ParserImpl<'a> { if declare { self.parse_ts_declare_function(start_span, modifiers) .map(Declaration::FunctionDeclaration) - } else if self.ts_enabled() { + } else if self.is_ts { self.parse_ts_function_impl(start_span, FunctionKind::Declaration, modifiers) .map(Declaration::FunctionDeclaration) } else { diff --git a/crates/oxc_parser/src/ts/types.rs b/crates/oxc_parser/src/ts/types.rs index aa631c26c6b7b..8f09720c159c6 100644 --- a/crates/oxc_parser/src/ts/types.rs +++ b/crates/oxc_parser/src/ts/types.rs @@ -138,7 +138,7 @@ impl<'a> ParserImpl<'a> { pub(crate) fn parse_ts_type_parameters( &mut self, ) -> Result>>> { - if !self.ts_enabled() { + if !self.is_ts { return Ok(None); } if !self.at(Kind::LAngle) { @@ -811,7 +811,7 @@ impl<'a> ParserImpl<'a> { pub(crate) fn parse_type_arguments_in_expression( &mut self, ) -> Result>>> { - if !self.ts_enabled() { + if !self.is_ts { return Ok(None); } let span = self.start_span(); @@ -1049,7 +1049,7 @@ impl<'a> ParserImpl<'a> { kind: Kind, is_type: bool, ) -> Result>>> { - if !self.ts_enabled() { + if !self.is_ts { return Ok(None); } if !self.at(Kind::Colon) { @@ -1315,7 +1315,7 @@ impl<'a> ParserImpl<'a> { &mut self, is_constructor_parameter: bool, ) -> Modifiers<'a> { - if !self.ts_enabled() { + if !self.is_ts { return Modifiers::empty(); }