diff --git a/crates/oxc_ast/src/ast/ts.rs b/crates/oxc_ast/src/ast/ts.rs index 53e1ec11dc14f..73fd1b610d043 100644 --- a/crates/oxc_ast/src/ast/ts.rs +++ b/crates/oxc_ast/src/ast/ts.rs @@ -20,7 +20,7 @@ use serde::Serialize; #[cfg(feature = "serialize")] use tsify::Tsify; -use super::{inherit_variants, js::*, jsx::*, literal::*, Modifiers}; +use super::{inherit_variants, js::*, jsx::*, literal::*}; #[cfg(feature = "serialize")] #[wasm_bindgen::prelude::wasm_bindgen(typescript_custom_section)] @@ -597,8 +597,7 @@ pub struct TSTypeAliasDeclaration<'a> { pub id: BindingIdentifier<'a>, pub type_annotation: TSType<'a>, pub type_parameters: Option>>, - /// Valid Modifiers: `declare`, `export` - pub modifiers: Modifiers<'a>, + pub declare: bool, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -635,8 +634,7 @@ pub struct TSInterfaceDeclaration<'a> { pub body: Box<'a, TSInterfaceBody<'a>>, pub type_parameters: Option>>, pub extends: Option>>, - /// Valid Modifiers: `export`, `default`, `declare` - pub modifiers: Modifiers<'a>, + pub declare: bool, } #[visited_node] @@ -803,8 +801,7 @@ pub struct TSModuleDeclaration<'a> { /// ^^^^^^ /// ``` pub kind: TSModuleDeclarationKind, - /// Valid Modifiers: `declare`, `export` - pub modifiers: Modifiers<'a>, + pub declare: bool, pub scope_id: Cell>, } diff --git a/crates/oxc_ast/src/ast_builder.rs b/crates/oxc_ast/src/ast_builder.rs index a3ef09dc50910..51c15a323bd95 100644 --- a/crates/oxc_ast/src/ast_builder.rs +++ b/crates/oxc_ast/src/ast_builder.rs @@ -1512,9 +1512,9 @@ impl<'a> AstBuilder<'a> { id: TSModuleDeclarationName<'a>, body: Option>, kind: TSModuleDeclarationKind, - modifiers: Modifiers<'a>, + declare: bool, ) -> Box<'a, TSModuleDeclaration<'a>> { - self.alloc(TSModuleDeclaration::new(span, id, body, kind, modifiers)) + self.alloc(TSModuleDeclaration::new(span, id, body, kind, declare)) } #[inline] @@ -1847,7 +1847,7 @@ impl<'a> AstBuilder<'a> { body: Box<'a, TSInterfaceBody<'a>>, type_parameters: Option>>, extends: Option>>, - modifiers: Modifiers<'a>, + declare: bool, ) -> Declaration<'a> { Declaration::TSInterfaceDeclaration(self.alloc(TSInterfaceDeclaration { span, @@ -1855,7 +1855,7 @@ impl<'a> AstBuilder<'a> { body, type_parameters, extends, - modifiers, + declare, })) } @@ -1866,14 +1866,14 @@ impl<'a> AstBuilder<'a> { id: BindingIdentifier<'a>, type_annotation: TSType<'a>, type_parameters: Option>>, - modifiers: Modifiers<'a>, + declare: bool, ) -> Declaration<'a> { Declaration::TSTypeAliasDeclaration(self.alloc(TSTypeAliasDeclaration { span, id, type_annotation, type_parameters, - modifiers, + declare, })) } diff --git a/crates/oxc_ast/src/ast_impl/js.rs b/crates/oxc_ast/src/ast_impl/js.rs index f9430026eceba..282d260cbe740 100644 --- a/crates/oxc_ast/src/ast_impl/js.rs +++ b/crates/oxc_ast/src/ast_impl/js.rs @@ -711,9 +711,9 @@ impl<'a> Declaration<'a> { Declaration::FunctionDeclaration(decl) => decl.declare, Declaration::ClassDeclaration(decl) => decl.declare, Declaration::TSEnumDeclaration(decl) => decl.declare, - Declaration::TSTypeAliasDeclaration(decl) => decl.modifiers.is_contains_declare(), - Declaration::TSModuleDeclaration(decl) => decl.modifiers.is_contains_declare(), - Declaration::TSInterfaceDeclaration(decl) => decl.modifiers.is_contains_declare(), + Declaration::TSTypeAliasDeclaration(decl) => decl.declare, + Declaration::TSModuleDeclaration(decl) => decl.declare, + Declaration::TSInterfaceDeclaration(decl) => decl.declare, _ => false, } } diff --git a/crates/oxc_ast/src/ast_impl/ts.rs b/crates/oxc_ast/src/ast_impl/ts.rs index 1e5af02caf98c..f28bf1750a7e6 100644 --- a/crates/oxc_ast/src/ast_impl/ts.rs +++ b/crates/oxc_ast/src/ast_impl/ts.rs @@ -11,7 +11,6 @@ use std::{cell::Cell, hash::Hash}; use oxc_allocator::Vec; use oxc_span::{Atom, GetSpan, Span}; -use crate::ast::Modifiers; use crate::ast::*; impl<'a> TSEnumDeclaration<'a> { @@ -150,9 +149,9 @@ impl<'a> TSModuleDeclaration<'a> { id: TSModuleDeclarationName<'a>, body: Option>, kind: TSModuleDeclarationKind, - modifiers: Modifiers<'a>, + declare: bool, ) -> Self { - Self { span, id, body, kind, modifiers, scope_id: Cell::default() } + Self { span, id, body, kind, declare, scope_id: Cell::default() } } } @@ -161,7 +160,7 @@ impl<'a> Hash for TSModuleDeclaration<'a> { self.id.hash(state); self.body.hash(state); self.kind.hash(state); - self.modifiers.hash(state); + self.declare.hash(state); } } diff --git a/crates/oxc_codegen/src/gen.rs b/crates/oxc_codegen/src/gen.rs index ed415e4bb4427..08536c05ea5b8 100644 --- a/crates/oxc_codegen/src/gen.rs +++ b/crates/oxc_codegen/src/gen.rs @@ -3245,10 +3245,7 @@ impl<'a, const MINIFY: bool> Gen for TSNamedTupleMember<'a> { impl<'a, const MINIFY: bool> Gen for TSModuleDeclaration<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { - if self.modifiers.contains(ModifierKind::Export) { - p.print_str(b"export "); - } - if self.modifiers.contains(ModifierKind::Declare) { + if self.declare { p.print_str(b"declare "); } p.print_str(b"module"); @@ -3300,10 +3297,7 @@ impl<'a, const MINIFY: bool> Gen for TSModuleBlock<'a> { impl<'a, const MINIFY: bool> Gen for TSTypeAliasDeclaration<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { - if self.modifiers.contains(ModifierKind::Export) { - p.print_str(b"export "); - } - if self.modifiers.contains(ModifierKind::Declare) { + if self.declare { p.print_str(b"declare "); } p.print_str(b"type"); diff --git a/crates/oxc_isolated_declarations/src/declaration.rs b/crates/oxc_isolated_declarations/src/declaration.rs index 2b233ba536253..507fd754001a7 100644 --- a/crates/oxc_isolated_declarations/src/declaration.rs +++ b/crates/oxc_isolated_declarations/src/declaration.rs @@ -145,7 +145,7 @@ impl<'a> IsolatedDeclarations<'a> { &mut self, decl: &Box<'a, TSModuleDeclaration<'a>>, ) -> Box<'a, TSModuleDeclaration<'a>> { - if decl.modifiers.is_contains_declare() { + if decl.declare { return self.ast.copy(decl); } @@ -156,23 +156,23 @@ impl<'a> IsolatedDeclarations<'a> { match body { TSModuleDeclarationBody::TSModuleDeclaration(decl) => { let inner = self.transform_ts_module_declaration(decl); - return self.ast.ts_module_declaration( + self.ast.ts_module_declaration( decl.span, self.ast.copy(&decl.id), Some(TSModuleDeclarationBody::TSModuleDeclaration(inner)), decl.kind, - self.modifiers_declare(), - ); + self.modifiers_declare().is_contains_declare(), + ) } TSModuleDeclarationBody::TSModuleBlock(block) => { let body = self.transform_ts_module_block(block); - return self.ast.ts_module_declaration( + self.ast.ts_module_declaration( decl.span, self.ast.copy(&decl.id), Some(TSModuleDeclarationBody::TSModuleBlock(body)), decl.kind, - self.modifiers_declare(), - ); + self.modifiers_declare().is_contains_declare(), + ) } } } diff --git a/crates/oxc_linter/src/rules/typescript/consistent_type_definitions.rs b/crates/oxc_linter/src/rules/typescript/consistent_type_definitions.rs index 128d6e6065cad..e4d27eae70280 100644 --- a/crates/oxc_linter/src/rules/typescript/consistent_type_definitions.rs +++ b/crates/oxc_linter/src/rules/typescript/consistent_type_definitions.rs @@ -72,11 +72,7 @@ impl Rule for ConsistentTypeDefinitions { TSType::TSTypeLiteral(_) if self.config == ConsistentTypeDefinitionsConfig::Interface => { - let start = if decl.modifiers.is_contains_declare() { - decl.span.start + 8 - } else { - decl.span.start - }; + let start = if decl.declare { decl.span.start + 8 } else { decl.span.start }; let name_span_start = &decl.id.span.start; let mut name_span_end = &decl.id.span.end; @@ -170,11 +166,7 @@ impl Rule for ConsistentTypeDefinitions { AstKind::TSInterfaceDeclaration(decl) if self.config == ConsistentTypeDefinitionsConfig::Type => { - let start = if decl.modifiers.is_contains_declare() { - decl.span.start + 8 - } else { - decl.span.start - }; + let start = if decl.declare { decl.span.start + 8 } else { decl.span.start }; let name_span_start = &decl.id.span.start; let mut name_span_end = &decl.id.span.end; diff --git a/crates/oxc_linter/src/rules/typescript/no_namespace.rs b/crates/oxc_linter/src/rules/typescript/no_namespace.rs index bbd807735b2e1..e6f0ee70aa083 100644 --- a/crates/oxc_linter/src/rules/typescript/no_namespace.rs +++ b/crates/oxc_linter/src/rules/typescript/no_namespace.rs @@ -1,5 +1,5 @@ use oxc_ast::{ - ast::{ModifierKind, TSModuleDeclarationKind, TSModuleDeclarationName}, + ast::{TSModuleDeclarationKind, TSModuleDeclarationName}, AstKind, }; use oxc_diagnostics::OxcDiagnostic; @@ -107,7 +107,7 @@ fn is_declaration(node: &AstNode, ctx: &LintContext) -> bool { let AstKind::TSModuleDeclaration(declaration) = node.kind() else { return false; }; - declaration.modifiers.contains(ModifierKind::Declare) + declaration.declare }) } diff --git a/crates/oxc_parser/src/js/module.rs b/crates/oxc_parser/src/js/module.rs index 879d0019d3e63..949e4d4ab3f51 100644 --- a/crates/oxc_parser/src/js/module.rs +++ b/crates/oxc_parser/src/js/module.rs @@ -292,7 +292,7 @@ impl<'a> ParserImpl<'a> { Modifiers::empty() }; - let declaration = self.parse_declaration(decl_span, modifiers)?; + let declaration = self.parse_declaration(decl_span, &modifiers)?; let span = self.end_span(span); Ok(self.ast.export_named_declaration( span, @@ -330,7 +330,7 @@ impl<'a> ParserImpl<'a> { && !self.peek_token().is_on_new_line && self.ts_enabled() => { - self.parse_ts_interface_declaration(decl_span, Modifiers::empty()).map(|decl| { + self.parse_ts_interface_declaration(decl_span, &Modifiers::empty()).map(|decl| { match decl { Declaration::TSInterfaceDeclaration(decl) => { ExportDefaultDeclarationKind::TSInterfaceDeclaration(decl) diff --git a/crates/oxc_parser/src/ts/statement.rs b/crates/oxc_parser/src/ts/statement.rs index b26fbe1952eb9..9f20939c225bd 100644 --- a/crates/oxc_parser/src/ts/statement.rs +++ b/crates/oxc_parser/src/ts/statement.rs @@ -106,7 +106,7 @@ impl<'a> ParserImpl<'a> { pub(crate) fn parse_ts_type_alias_declaration( &mut self, span: Span, - modifiers: Modifiers<'a>, + modifiers: &Modifiers<'a>, ) -> Result> { self.expect(Kind::Type)?; @@ -118,7 +118,23 @@ impl<'a> ParserImpl<'a> { self.asi()?; let span = self.end_span(span); - Ok(self.ast.ts_type_alias_declaration(span, id, annotation, params, modifiers)) + + for modifier in modifiers.iter() { + if modifier.kind != ModifierKind::Declare { + self.error(diagnostics::modifiers_cannot_appear( + modifier.span, + modifier.kind.as_str(), + )); + } + } + + Ok(self.ast.ts_type_alias_declaration( + span, + id, + annotation, + params, + modifiers.is_contains_declare(), + )) } /** --------------------- Interface ------------------------ */ @@ -126,7 +142,7 @@ impl<'a> ParserImpl<'a> { pub(crate) fn parse_ts_interface_declaration( &mut self, span: Span, - modifiers: Modifiers<'a>, + modifiers: &Modifiers<'a>, ) -> Result> { self.expect(Kind::Interface)?; // bump interface let id = self.parse_binding_identifier()?; @@ -134,13 +150,23 @@ impl<'a> ParserImpl<'a> { let (extends, _) = self.parse_heritage_clause()?; let body = self.parse_ts_interface_body()?; let extends = extends.map(|e| self.ast.ts_interface_heritages(e)); + + for modifier in modifiers.iter() { + if modifier.kind != ModifierKind::Declare { + self.error(diagnostics::modifiers_cannot_appear( + modifier.span, + modifier.kind.as_str(), + )); + } + } + Ok(self.ast.ts_interface_declaration( self.end_span(span), id, body, type_parameters, extends, - modifiers, + modifiers.is_contains_declare(), )) } @@ -245,7 +271,7 @@ impl<'a> ParserImpl<'a> { &mut self, span: Span, kind: TSModuleDeclarationKind, - modifiers: Modifiers<'a>, + modifiers: &Modifiers<'a>, ) -> Result>> { let id = match self.cur_kind() { Kind::Str => self.parse_literal_string().map(TSModuleDeclarationName::StringLiteral), @@ -254,8 +280,11 @@ impl<'a> ParserImpl<'a> { let body = if self.eat(Kind::Dot) { let span = self.start_span(); - let decl = - self.parse_ts_namespace_or_module_declaration_body(span, kind, Modifiers::empty())?; + let decl = self.parse_ts_namespace_or_module_declaration_body( + span, + kind, + &Modifiers::empty(), + )?; Some(TSModuleDeclarationBody::TSModuleDeclaration(decl)) } else if self.at(Kind::LCurly) { let block = self.parse_ts_module_block()?; @@ -264,7 +293,21 @@ impl<'a> ParserImpl<'a> { None }; - Ok(self.ast.ts_module_declaration(self.end_span(span), id, body, kind, modifiers)) + for modifier in modifiers.iter() { + if modifier.kind != ModifierKind::Declare { + self.error(diagnostics::modifiers_cannot_appear( + modifier.span, + modifier.kind.as_str(), + )); + } + } + Ok(self.ast.ts_module_declaration( + self.end_span(span), + id, + body, + kind, + modifiers.is_contains_declare(), + )) } /** ----------------------- declare --------------------- */ @@ -276,7 +319,7 @@ impl<'a> ParserImpl<'a> { let reserved_ctx = self.ctx; let (flags, modifiers) = self.eat_modifiers_before_declaration(); self.ctx = self.ctx.union_ambient_if(flags.declare()).and_await(flags.r#async()); - let result = self.parse_declaration(start_span, modifiers); + let result = self.parse_declaration(start_span, &modifiers); self.ctx = reserved_ctx; result.map(Statement::from) } @@ -284,7 +327,7 @@ impl<'a> ParserImpl<'a> { pub(crate) fn parse_declaration( &mut self, start_span: Span, - modifiers: Modifiers<'a>, + modifiers: &Modifiers<'a>, ) -> Result> { match self.cur_kind() { Kind::Namespace => { @@ -306,12 +349,12 @@ impl<'a> ParserImpl<'a> { .map(Declaration::TSModuleDeclaration) } Kind::Type => self.parse_ts_type_alias_declaration(start_span, modifiers), - Kind::Enum => self.parse_ts_enum_declaration(start_span, &modifiers), + Kind::Enum => self.parse_ts_enum_declaration(start_span, modifiers), Kind::Interface if self.is_at_interface_declaration() => { self.parse_ts_interface_declaration(start_span, modifiers) } Kind::Class => self - .parse_class_declaration(start_span, &modifiers) + .parse_class_declaration(start_span, modifiers) .map(Declaration::ClassDeclaration), Kind::Import => { self.bump_any(); @@ -321,16 +364,16 @@ impl<'a> ParserImpl<'a> { .parse_variable_declaration( start_span, VariableDeclarationContext::new(VariableDeclarationParent::Clause), - &modifiers, + modifiers, ) .map(Declaration::VariableDeclaration), _ if self.at_function_with_async() => { let declare = modifiers.contains(ModifierKind::Declare); if declare { - self.parse_ts_declare_function(start_span, &modifiers) + self.parse_ts_declare_function(start_span, modifiers) .map(Declaration::FunctionDeclaration) } else if self.ts_enabled() { - self.parse_ts_function_impl(start_span, FunctionKind::Declaration, &modifiers) + self.parse_ts_function_impl(start_span, FunctionKind::Declaration, modifiers) .map(Declaration::FunctionDeclaration) } else { self.parse_function_impl(FunctionKind::Declaration) diff --git a/crates/oxc_semantic/src/binder.rs b/crates/oxc_semantic/src/binder.rs index b06821c5f4c5b..e19ab2117655a 100644 --- a/crates/oxc_semantic/src/binder.rs +++ b/crates/oxc_semantic/src/binder.rs @@ -357,11 +357,7 @@ impl<'a> Binder for TSModuleDeclaration<'a> { fn bind(&self, builder: &mut SemanticBuilder) { // At declaration time a module has no value declaration it is only when a value declaration // is made inside a the scope of a module that the symbol is modified - let ambient = if self.modifiers.contains(ModifierKind::Declare) { - SymbolFlags::Ambient - } else { - SymbolFlags::None - }; + let ambient = if self.declare { SymbolFlags::Ambient } else { SymbolFlags::None }; builder.declare_symbol( self.span, self.id.name().as_str(), diff --git a/crates/oxc_semantic/src/checker/mod.rs b/crates/oxc_semantic/src/checker/mod.rs index 7d521891fcfc3..eb36d98ddcdb9 100644 --- a/crates/oxc_semantic/src/checker/mod.rs +++ b/crates/oxc_semantic/src/checker/mod.rs @@ -97,14 +97,8 @@ pub fn check<'a>(node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) { AstKind::TSTypeParameterDeclaration(declaration) => { ts::check_ts_type_parameter_declaration(declaration, ctx); } - AstKind::TSModuleDeclaration(decl) => ts::check_ts_module_declaration(decl, node, ctx), + AstKind::TSModuleDeclaration(decl) => ts::check_ts_module_declaration(decl, ctx), AstKind::TSEnumDeclaration(decl) => ts::check_ts_enum_declaration(decl, ctx), - AstKind::TSTypeAliasDeclaration(decl) => { - ts::check_ts_type_alias_declaration(decl, node, ctx); - } - AstKind::TSInterfaceDeclaration(decl) => { - ts::check_ts_interface_declaration(decl, node, ctx); - } _ => {} } } diff --git a/crates/oxc_semantic/src/checker/typescript.rs b/crates/oxc_semantic/src/checker/typescript.rs index f3e73cc825552..7979c9987aabe 100644 --- a/crates/oxc_semantic/src/checker/typescript.rs +++ b/crates/oxc_semantic/src/checker/typescript.rs @@ -3,10 +3,9 @@ use oxc_ast::syntax_directed_operations::BoundNames; use oxc_ast::{ast::*, AstKind}; use oxc_diagnostics::OxcDiagnostic; use oxc_span::{Atom, GetSpan, Span}; -use oxc_syntax::scope::ScopeFlags; use rustc_hash::FxHashMap; -use crate::{builder::SemanticBuilder, diagnostics::redeclaration, AstNode}; +use crate::{builder::SemanticBuilder, diagnostics::redeclaration}; fn empty_type_parameter_list(span0: Span) -> OxcDiagnostic { OxcDiagnostic::error("Type parameter list cannot be empty.").with_labels([span0.into()]) @@ -114,80 +113,6 @@ pub fn check_array_pattern<'a>(pattern: &ArrayPattern<'a>, ctx: &SemanticBuilder } } -/// ts(1184) -fn modifiers_cannot_be_used_here(span: Span) -> OxcDiagnostic { - OxcDiagnostic::error("Modifiers cannot be used here.").with_labels([span.into()]) -} - -/// ts(1024) -fn readonly_only_on_index_signature_or_property_decl(span: Span) -> OxcDiagnostic { - OxcDiagnostic::error( - "'readonly' modifier can only appear on a property declaration or index signature.", - ) - .with_labels([span.into()]) -} -/// ts(1042) -fn async_cannot_be_used_here(span: Span) -> OxcDiagnostic { - OxcDiagnostic::error("'async' modifier cannot be used here.").with_labels([span.into()]) -} - -/// Returns `true` if the scope described by `scope_flags` supports export -/// declarations or specifiers. -pub const fn scope_can_export(scope_flags: ScopeFlags) -> bool { - const CAN_EXPORT: ScopeFlags = ScopeFlags::Top.union(ScopeFlags::TsModuleBlock); - scope_flags.contains(CAN_EXPORT) -} - -fn check_declaration_modifiers<'a>( - modifiers: &Modifiers<'a>, - decl_node: &AstNode<'a>, - ctx: &SemanticBuilder<'a>, -) { - let scope_flags = ctx.scope.get_flags(decl_node.scope_id()); - let kind = decl_node.kind(); - let is_class = matches!(kind, AstKind::Class(_)); - let is_function = matches!(kind, AstKind::Function(_)); - for modifier in modifiers.iter() { - match modifier.kind { - ModifierKind::Public - | ModifierKind::Private - | ModifierKind::Protected - | ModifierKind::Static - | ModifierKind::Override => { - ctx.error(modifiers_cannot_be_used_here(modifier.span)); - } - ModifierKind::Abstract if !is_class => { - ctx.error(modifiers_cannot_be_used_here(modifier.span)); - } - ModifierKind::Async if !is_function => { - ctx.error(async_cannot_be_used_here(modifier.span)); - } - ModifierKind::Readonly => { - ctx.error(readonly_only_on_index_signature_or_property_decl(modifier.span)); - } - ModifierKind::Export if !scope_can_export(scope_flags) => { - ctx.error(modifiers_cannot_be_used_here(modifier.span)); - } - _ => {} - } - } -} - -pub fn check_ts_type_alias_declaration<'a>( - decl: &TSTypeAliasDeclaration<'a>, - node: &AstNode<'a>, - ctx: &SemanticBuilder<'a>, -) { - check_declaration_modifiers(&decl.modifiers, node, ctx); -} -pub fn check_ts_interface_declaration<'a>( - decl: &TSInterfaceDeclaration<'a>, - node: &AstNode<'a>, - ctx: &SemanticBuilder<'a>, -) { - check_declaration_modifiers(&decl.modifiers, node, ctx); -} - fn not_allowed_namespace_declaration(span0: Span) -> OxcDiagnostic { OxcDiagnostic::error( "A namespace declaration is only allowed at the top level of a namespace or module.", @@ -195,12 +120,7 @@ fn not_allowed_namespace_declaration(span0: Span) -> OxcDiagnostic { .with_labels([span0.into()]) } -pub fn check_ts_module_declaration<'a>( - decl: &TSModuleDeclaration<'a>, - node: &AstNode<'a>, - ctx: &SemanticBuilder<'a>, -) { - check_declaration_modifiers(&decl.modifiers, node, ctx); +pub fn check_ts_module_declaration<'a>(decl: &TSModuleDeclaration<'a>, ctx: &SemanticBuilder<'a>) { // skip current node for node in ctx.nodes.iter_parents(ctx.current_node_id).skip(1) { match node.kind() { diff --git a/crates/oxc_transformer/src/typescript/namespace.rs b/crates/oxc_transformer/src/typescript/namespace.rs index e2a26fbb1d4d6..592408299db88 100644 --- a/crates/oxc_transformer/src/typescript/namespace.rs +++ b/crates/oxc_transformer/src/typescript/namespace.rs @@ -40,7 +40,7 @@ impl<'a> TypeScript<'a> { for stmt in self.ctx.ast.move_statement_vec(&mut program.body) { match stmt { Statement::TSModuleDeclaration(decl) => { - if !decl.modifiers.is_contains_declare() { + if !decl.declare { if !self.options.allow_namespaces { self.ctx.error(namespace_not_supported(decl.span)); } @@ -63,7 +63,7 @@ impl<'a> TypeScript<'a> { Statement::ExportNamedDeclaration(ref export_decl) => { match &export_decl.declaration { Some(Declaration::TSModuleDeclaration(decl)) => { - if !decl.modifiers.is_contains_declare() { + if !decl.declare { if !self.options.allow_namespaces { self.ctx.error(namespace_not_supported(decl.span)); } diff --git a/crates/oxc_traverse/src/ancestor.rs b/crates/oxc_traverse/src/ancestor.rs index 7fece0005c756..7eebf90dabb60 100644 --- a/crates/oxc_traverse/src/ancestor.rs +++ b/crates/oxc_traverse/src/ancestor.rs @@ -9466,8 +9466,8 @@ pub(crate) const OFFSET_TS_TYPE_ALIAS_DECLARATION_TYPE_ANNOTATION: usize = offset_of!(TSTypeAliasDeclaration, type_annotation); pub(crate) const OFFSET_TS_TYPE_ALIAS_DECLARATION_TYPE_PARAMETERS: usize = offset_of!(TSTypeAliasDeclaration, type_parameters); -pub(crate) const OFFSET_TS_TYPE_ALIAS_DECLARATION_MODIFIERS: usize = - offset_of!(TSTypeAliasDeclaration, modifiers); +pub(crate) const OFFSET_TS_TYPE_ALIAS_DECLARATION_DECLARE: usize = + offset_of!(TSTypeAliasDeclaration, declare); #[repr(transparent)] #[derive(Debug)] @@ -9498,10 +9498,9 @@ impl<'a> TSTypeAliasDeclarationWithoutId<'a> { } #[inline] - pub fn modifiers(&self) -> &Modifiers<'a> { + pub fn declare(&self) -> &bool { unsafe { - &*((self.0 as *const u8).add(OFFSET_TS_TYPE_ALIAS_DECLARATION_MODIFIERS) - as *const Modifiers<'a>) + &*((self.0 as *const u8).add(OFFSET_TS_TYPE_ALIAS_DECLARATION_DECLARE) as *const bool) } } } @@ -9537,10 +9536,9 @@ impl<'a> TSTypeAliasDeclarationWithoutTypeAnnotation<'a> { } #[inline] - pub fn modifiers(&self) -> &Modifiers<'a> { + pub fn declare(&self) -> &bool { unsafe { - &*((self.0 as *const u8).add(OFFSET_TS_TYPE_ALIAS_DECLARATION_MODIFIERS) - as *const Modifiers<'a>) + &*((self.0 as *const u8).add(OFFSET_TS_TYPE_ALIAS_DECLARATION_DECLARE) as *const bool) } } } @@ -9576,10 +9574,9 @@ impl<'a> TSTypeAliasDeclarationWithoutTypeParameters<'a> { } #[inline] - pub fn modifiers(&self) -> &Modifiers<'a> { + pub fn declare(&self) -> &bool { unsafe { - &*((self.0 as *const u8).add(OFFSET_TS_TYPE_ALIAS_DECLARATION_MODIFIERS) - as *const Modifiers<'a>) + &*((self.0 as *const u8).add(OFFSET_TS_TYPE_ALIAS_DECLARATION_DECLARE) as *const bool) } } } @@ -9637,8 +9634,8 @@ pub(crate) const OFFSET_TS_INTERFACE_DECLARATION_TYPE_PARAMETERS: usize = offset_of!(TSInterfaceDeclaration, type_parameters); pub(crate) const OFFSET_TS_INTERFACE_DECLARATION_EXTENDS: usize = offset_of!(TSInterfaceDeclaration, extends); -pub(crate) const OFFSET_TS_INTERFACE_DECLARATION_MODIFIERS: usize = - offset_of!(TSInterfaceDeclaration, modifiers); +pub(crate) const OFFSET_TS_INTERFACE_DECLARATION_DECLARE: usize = + offset_of!(TSInterfaceDeclaration, declare); #[repr(transparent)] #[derive(Debug)] @@ -9677,10 +9674,9 @@ impl<'a> TSInterfaceDeclarationWithoutId<'a> { } #[inline] - pub fn modifiers(&self) -> &Modifiers<'a> { + pub fn declare(&self) -> &bool { unsafe { - &*((self.0 as *const u8).add(OFFSET_TS_INTERFACE_DECLARATION_MODIFIERS) - as *const Modifiers<'a>) + &*((self.0 as *const u8).add(OFFSET_TS_INTERFACE_DECLARATION_DECLARE) as *const bool) } } } @@ -9722,10 +9718,9 @@ impl<'a> TSInterfaceDeclarationWithoutBody<'a> { } #[inline] - pub fn modifiers(&self) -> &Modifiers<'a> { + pub fn declare(&self) -> &bool { unsafe { - &*((self.0 as *const u8).add(OFFSET_TS_INTERFACE_DECLARATION_MODIFIERS) - as *const Modifiers<'a>) + &*((self.0 as *const u8).add(OFFSET_TS_INTERFACE_DECLARATION_DECLARE) as *const bool) } } } @@ -9769,10 +9764,9 @@ impl<'a> TSInterfaceDeclarationWithoutTypeParameters<'a> { } #[inline] - pub fn modifiers(&self) -> &Modifiers<'a> { + pub fn declare(&self) -> &bool { unsafe { - &*((self.0 as *const u8).add(OFFSET_TS_INTERFACE_DECLARATION_MODIFIERS) - as *const Modifiers<'a>) + &*((self.0 as *const u8).add(OFFSET_TS_INTERFACE_DECLARATION_DECLARE) as *const bool) } } } @@ -9814,10 +9808,9 @@ impl<'a> TSInterfaceDeclarationWithoutExtends<'a> { } #[inline] - pub fn modifiers(&self) -> &Modifiers<'a> { + pub fn declare(&self) -> &bool { unsafe { - &*((self.0 as *const u8).add(OFFSET_TS_INTERFACE_DECLARATION_MODIFIERS) - as *const Modifiers<'a>) + &*((self.0 as *const u8).add(OFFSET_TS_INTERFACE_DECLARATION_DECLARE) as *const bool) } } } @@ -10700,8 +10693,8 @@ pub(crate) const OFFSET_TS_MODULE_DECLARATION_SPAN: usize = offset_of!(TSModuleD pub(crate) const OFFSET_TS_MODULE_DECLARATION_ID: usize = offset_of!(TSModuleDeclaration, id); pub(crate) const OFFSET_TS_MODULE_DECLARATION_BODY: usize = offset_of!(TSModuleDeclaration, body); pub(crate) const OFFSET_TS_MODULE_DECLARATION_KIND: usize = offset_of!(TSModuleDeclaration, kind); -pub(crate) const OFFSET_TS_MODULE_DECLARATION_MODIFIERS: usize = - offset_of!(TSModuleDeclaration, modifiers); +pub(crate) const OFFSET_TS_MODULE_DECLARATION_DECLARE: usize = + offset_of!(TSModuleDeclaration, declare); pub(crate) const OFFSET_TS_MODULE_DECLARATION_SCOPE_ID: usize = offset_of!(TSModuleDeclaration, scope_id); @@ -10732,10 +10725,9 @@ impl<'a> TSModuleDeclarationWithoutId<'a> { } #[inline] - pub fn modifiers(&self) -> &Modifiers<'a> { + pub fn declare(&self) -> &bool { unsafe { - &*((self.0 as *const u8).add(OFFSET_TS_MODULE_DECLARATION_MODIFIERS) - as *const Modifiers<'a>) + &*((self.0 as *const u8).add(OFFSET_TS_MODULE_DECLARATION_DECLARE) as *const bool) } } @@ -10775,10 +10767,9 @@ impl<'a> TSModuleDeclarationWithoutBody<'a> { } #[inline] - pub fn modifiers(&self) -> &Modifiers<'a> { + pub fn declare(&self) -> &bool { unsafe { - &*((self.0 as *const u8).add(OFFSET_TS_MODULE_DECLARATION_MODIFIERS) - as *const Modifiers<'a>) + &*((self.0 as *const u8).add(OFFSET_TS_MODULE_DECLARATION_DECLARE) as *const bool) } } diff --git a/tasks/coverage/parser_babel.snap b/tasks/coverage/parser_babel.snap index a7abecfc9a5ba..80430d782fca6 100644 --- a/tasks/coverage/parser_babel.snap +++ b/tasks/coverage/parser_babel.snap @@ -10137,7 +10137,7 @@ Expect to Parse: "typescript/types/const-type-parameters-babel-7/input.ts" · ── ╰──── - × Modifiers cannot be used here. + × TS1044: 'abstract' modifier cannot appear on a module or namespace element. ╭─[typescript/interface/abstract/input.ts:1:1] 1 │ abstract interface Foo { · ──────── @@ -10152,7 +10152,7 @@ Expect to Parse: "typescript/types/const-type-parameters-babel-7/input.ts" ╰──── help: Try insert a semicolon here - × Modifiers cannot be used here. + × TS1044: 'abstract' modifier cannot appear on a module or namespace element. ╭─[typescript/interface/export-abstract-interface/input.ts:1:8] 1 │ export abstract interface I { · ──────── diff --git a/tasks/coverage/parser_typescript.snap b/tasks/coverage/parser_typescript.snap index 306fdd28ed83e..6b3cf9013756f 100644 --- a/tasks/coverage/parser_typescript.snap +++ b/tasks/coverage/parser_typescript.snap @@ -6438,6 +6438,22 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" 7 │ export export interface I { } ╰──── + × TS1044: 'export' modifier cannot appear on a module or namespace element. + ╭─[compiler/exportAlreadySeen.ts:7:16] + 6 │ export export class C { } + 7 │ export export interface I { } + · ────── + 8 │ } + ╰──── + + × TS1044: 'export' modifier cannot appear on a module or namespace element. + ╭─[compiler/exportAlreadySeen.ts:5:12] + 4 │ + 5 │ export export module N { + · ────── + 6 │ export export class C { } + ╰──── + × TS1044: 'export' modifier cannot appear on a module or namespace element. ╭─[compiler/exportAlreadySeen.ts:12:12] 11 │ declare module A { @@ -6462,23 +6478,7 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" 17 │ export export interface I { } ╰──── - × Modifiers cannot be used here. - ╭─[compiler/exportAlreadySeen.ts:7:16] - 6 │ export export class C { } - 7 │ export export interface I { } - · ────── - 8 │ } - ╰──── - - × Modifiers cannot be used here. - ╭─[compiler/exportAlreadySeen.ts:5:12] - 4 │ - 5 │ export export module N { - · ────── - 6 │ export export class C { } - ╰──── - - × Modifiers cannot be used here. + × TS1044: 'export' modifier cannot appear on a module or namespace element. ╭─[compiler/exportAlreadySeen.ts:17:16] 16 │ export export class C { } 17 │ export export interface I { } @@ -6486,7 +6486,7 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" 18 │ } ╰──── - × Modifiers cannot be used here. + × TS1044: 'export' modifier cannot appear on a module or namespace element. ╭─[compiler/exportAlreadySeen.ts:15:12] 14 │ 15 │ export export module N { @@ -8697,7 +8697,7 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" 1 │ if (true) { ╰──── - × Modifiers cannot be used here. + × TS1044: 'export' modifier cannot appear on a module or namespace element. ╭─[compiler/privacyImportParseErrors.ts:326:9] 325 │ 326 │ declare export module "anotherParseError2" { @@ -10699,14 +10699,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" 3 │ } ╰──── - × 'async' modifier cannot be used here. + × TS1044: 'async' modifier cannot appear on a module or namespace element. ╭─[conformance/async/es5/asyncInterface_es5.ts:1:1] 1 │ async interface I { · ───── 2 │ } ╰──── - × 'async' modifier cannot be used here. + × TS1044: 'async' modifier cannot appear on a module or namespace element. ╭─[conformance/async/es5/asyncModule_es5.ts:1:1] 1 │ async module M { · ───── @@ -10834,14 +10834,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" 3 │ } ╰──── - × 'async' modifier cannot be used here. + × TS1044: 'async' modifier cannot appear on a module or namespace element. ╭─[conformance/async/es6/asyncInterface_es6.ts:1:1] 1 │ async interface I { · ───── 2 │ } ╰──── - × 'async' modifier cannot be used here. + × TS1044: 'async' modifier cannot appear on a module or namespace element. ╭─[conformance/async/es6/asyncModule_es6.ts:1:1] 1 │ async module M { · ───── @@ -11005,7 +11005,7 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" 17 │ } ╰──── - × Modifiers cannot be used here. + × TS1044: 'abstract' modifier cannot appear on a module or namespace element. ╭─[conformance/classes/classDeclarations/classAbstractKeyword/classAbstractWithInterface.ts:1:1] 1 │ abstract interface I {} · ──────── @@ -16229,6 +16229,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" 13 │ public interface I { id: number } ╰──── + × TS1044: 'public' modifier cannot appear on a module or namespace element. + ╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:13:5] + 12 │ public class AA { s: T } + 13 │ public interface I { id: number } + · ────── + 14 │ + ╰──── + × TS1044: 'public' modifier cannot appear on a module or namespace element. ╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:15:5] 14 │ @@ -16237,6 +16245,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" 16 │ } ╰──── + × TS1044: 'public' modifier cannot appear on a module or namespace element. + ╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:19:5] + 18 │ module Y3 { + 19 │ public module Module { + · ────── + 20 │ class A { s: string } + ╰──── + × TS1044: 'public' modifier cannot appear on a module or namespace element. ╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:25:5] 24 │ module Y4 { @@ -16269,6 +16285,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" 38 │ private interface I { id: number } ╰──── + × TS1044: 'private' modifier cannot appear on a module or namespace element. + ╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:38:5] + 37 │ private class AA { s: T } + 38 │ private interface I { id: number } + · ─────── + 39 │ + ╰──── + × TS1044: 'private' modifier cannot appear on a module or namespace element. ╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:40:5] 39 │ @@ -16277,6 +16301,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" 41 │ } ╰──── + × TS1044: 'private' modifier cannot appear on a module or namespace element. + ╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:44:5] + 43 │ module YY3 { + 44 │ private module Module { + · ─────── + 45 │ class A { s: string } + ╰──── + × TS1044: 'private' modifier cannot appear on a module or namespace element. ╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:50:5] 49 │ module YY4 { @@ -16309,6 +16341,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" 64 │ static interface I { id: number } ╰──── + × TS1044: 'static' modifier cannot appear on a module or namespace element. + ╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:64:5] + 63 │ static class AA { s: T } + 64 │ static interface I { id: number } + · ────── + 65 │ + ╰──── + × TS1044: 'static' modifier cannot appear on a module or namespace element. ╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:66:5] 65 │ @@ -16318,54 +16358,6 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" ╰──── × TS1044: 'static' modifier cannot appear on a module or namespace element. - ╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:76:5] - 75 │ module YYY4 { - 76 │ static enum Color { Blue, Red } - · ────── - 77 │ } - ╰──── - - × Modifiers cannot be used here. - ╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:13:5] - 12 │ public class AA { s: T } - 13 │ public interface I { id: number } - · ────── - 14 │ - ╰──── - - × Modifiers cannot be used here. - ╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:19:5] - 18 │ module Y3 { - 19 │ public module Module { - · ────── - 20 │ class A { s: string } - ╰──── - - × Modifiers cannot be used here. - ╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:38:5] - 37 │ private class AA { s: T } - 38 │ private interface I { id: number } - · ─────── - 39 │ - ╰──── - - × Modifiers cannot be used here. - ╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:44:5] - 43 │ module YY3 { - 44 │ private module Module { - · ─────── - 45 │ class A { s: string } - ╰──── - - × Modifiers cannot be used here. - ╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:64:5] - 63 │ static class AA { s: T } - 64 │ static interface I { id: number } - · ────── - 65 │ - ╰──── - - × Modifiers cannot be used here. ╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:70:5] 69 │ module YYY3 { 70 │ static module Module { @@ -16373,6 +16365,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" 71 │ class A { s: string } ╰──── + × TS1044: 'static' modifier cannot appear on a module or namespace element. + ╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:76:5] + 75 │ module YYY4 { + 76 │ static enum Color { Blue, Red } + · ────── + 77 │ } + ╰──── + × TS1044: 'public' modifier cannot appear on a module or namespace element. ╭─[conformance/internalModules/moduleBody/invalidModuleWithVarStatements.ts:4:5] 3 │ module Y { @@ -17508,21 +17508,21 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" 3 │ } ╰──── - × Modifiers cannot be used here. + × TS1044: 'public' modifier cannot appear on a module or namespace element. ╭─[conformance/parser/ecmascript5/InterfaceDeclarations/parserInterfaceDeclaration3.ts:1:1] 1 │ public interface I { · ────── 2 │ } ╰──── - × Modifiers cannot be used here. + × TS1044: 'static' modifier cannot appear on a module or namespace element. ╭─[conformance/parser/ecmascript5/InterfaceDeclarations/parserInterfaceDeclaration4.ts:1:1] 1 │ static interface I { · ────── 2 │ } ╰──── - × Modifiers cannot be used here. + × TS1044: 'export' modifier cannot appear on a module or namespace element. ╭─[conformance/parser/ecmascript5/InterfaceDeclarations/parserInterfaceDeclaration6.ts:1:8] 1 │ export export interface I { · ────── @@ -17758,7 +17758,7 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" 2 │ } ╰──── - × Modifiers cannot be used here. + × TS1044: 'protected' modifier cannot appear on a module or namespace element. ╭─[conformance/parser/ecmascript5/Protected/Protected2.ts:1:1] 1 │ protected module M { · ─────────