diff --git a/crates/oxc_transformer_dts/src/class.rs b/crates/oxc_transformer_dts/src/class.rs index 45b13550a..5edd58f26 100644 --- a/crates/oxc_transformer_dts/src/class.rs +++ b/crates/oxc_transformer_dts/src/class.rs @@ -2,25 +2,31 @@ use oxc_ast::ast::*; use oxc_allocator::Box; -use oxc_diagnostics::OxcDiagnostic; use oxc_span::{GetSpan, SPAN}; -use crate::TransformerDts; +use crate::{diagnostics::computed_property_name, TransformerDts}; impl<'a> TransformerDts<'a> { + pub fn is_literal_key(&self, key: &PropertyKey<'a>) -> bool { + match key { + PropertyKey::StringLiteral(_) + | PropertyKey::NumericLiteral(_) + | PropertyKey::BigintLiteral(_) => true, + PropertyKey::TemplateLiteral(l) => l.expressions.is_empty(), + PropertyKey::UnaryExpression(expr) => { + expr.operator.is_arithmetic() + && matches!( + expr.argument, + Expression::NumericLiteral(_) | Expression::BigintLiteral(_) + ) + } + _ => false, + } + } + pub fn report_property_key(&self, key: &PropertyKey<'a>, computed: bool) -> bool { - if computed - && !matches!( - key, - PropertyKey::StringLiteral(_) - | PropertyKey::NumericLiteral(_) - | PropertyKey::BigintLiteral(_) - ) - { - self.ctx.error( - OxcDiagnostic::error("Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.") - .with_label(key.span()) - ); + if computed && self.is_literal_key(key) { + computed_property_name(key.span()); true } else { false diff --git a/crates/oxc_transformer_dts/src/declaration.rs b/crates/oxc_transformer_dts/src/declaration.rs index 354212995..253399a6c 100644 --- a/crates/oxc_transformer_dts/src/declaration.rs +++ b/crates/oxc_transformer_dts/src/declaration.rs @@ -7,7 +7,7 @@ use oxc_diagnostics::OxcDiagnostic; use oxc_span::{GetSpan, SPAN}; use oxc_syntax::scope::ScopeFlags; -use crate::TransformerDts; +use crate::{diagnostics::signature_computed_property_name, TransformerDts}; impl<'a> TransformerDts<'a> { pub fn transform_variable_declaration( @@ -195,23 +195,25 @@ impl<'a> TransformerDts<'a> { None } } - Declaration::TSTypeAliasDeclaration(decl) => { - if !check_binding || self.scope.has_reference(&decl.id.name) { - Some(Declaration::TSTypeAliasDeclaration(self.ctx.ast.copy(decl))) + Declaration::TSTypeAliasDeclaration(alias_decl) => { + self.visit_ts_type_alias_declaration(alias_decl); + if !check_binding || self.scope.has_reference(&alias_decl.id.name) { + Some(self.ctx.ast.copy(decl)) } else { None } } - Declaration::TSInterfaceDeclaration(decl) => { - if !check_binding || self.scope.has_reference(&decl.id.name) { - Some(Declaration::TSInterfaceDeclaration(self.ctx.ast.copy(decl))) + Declaration::TSInterfaceDeclaration(interface_decl) => { + self.visit_ts_interface_declaration(interface_decl); + if !check_binding || self.scope.has_reference(&interface_decl.id.name) { + Some(self.ctx.ast.copy(decl)) } else { None } } - Declaration::TSEnumDeclaration(decl) => { - if !check_binding || self.scope.has_reference(&decl.id.name) { - Some(Declaration::TSEnumDeclaration(self.ctx.ast.copy(decl))) + Declaration::TSEnumDeclaration(enum_decl) => { + if !check_binding || self.scope.has_reference(&enum_decl.id.name) { + Some(self.ctx.ast.copy(decl)) } else { None } @@ -240,4 +242,35 @@ impl<'a> TransformerDts<'a> { } } } + + fn report_signature_property_key(&self, key: &PropertyKey<'a>, computed: bool) { + if !computed { + return; + } + + let is_not_allowed = match key { + PropertyKey::StaticIdentifier(_) | PropertyKey::Identifier(_) => false, + PropertyKey::StaticMemberExpression(expr) => { + let mut object = &expr.object; + while let Expression::StaticMemberExpression(expr) = &object { + object = &expr.object; + } + !object.is_identifier_reference() + } + key => !self.is_literal_key(key), + }; + + if is_not_allowed { + self.ctx.error(signature_computed_property_name(key.span())); + } + } +} + +impl<'a> Visit<'a> for TransformerDts<'a> { + fn visit_ts_method_signature(&mut self, signature: &TSMethodSignature<'a>) { + self.report_signature_property_key(&signature.key, signature.computed); + } + fn visit_ts_property_signature(&mut self, signature: &TSPropertySignature<'a>) { + self.report_signature_property_key(&signature.key, signature.computed); + } } diff --git a/crates/oxc_transformer_dts/src/diagnostics.rs b/crates/oxc_transformer_dts/src/diagnostics.rs index 3d586e592..b2b66d3c4 100644 --- a/crates/oxc_transformer_dts/src/diagnostics.rs +++ b/crates/oxc_transformer_dts/src/diagnostics.rs @@ -21,3 +21,13 @@ pub fn type_containing_private_name(name: &Atom<'_>, span: Span) -> OxcDiagnosti )) .with_label(span) } + +pub fn computed_property_name(span: Span) -> OxcDiagnostic { + OxcDiagnostic::error("Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.") + .with_label(span) +} + +pub fn signature_computed_property_name(span: Span) -> OxcDiagnostic { + OxcDiagnostic::error("Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations.") + .with_label(span) +} diff --git a/crates/oxc_transformer_dts/src/module.rs b/crates/oxc_transformer_dts/src/module.rs index bc390a66d..9689ef8ae 100644 --- a/crates/oxc_transformer_dts/src/module.rs +++ b/crates/oxc_transformer_dts/src/module.rs @@ -2,6 +2,7 @@ use oxc_ast::ast::*; use oxc_allocator::Box; +use oxc_ast::Visit; use oxc_span::{GetSpan, SPAN}; use crate::TransformerDts; @@ -34,12 +35,9 @@ impl<'a> TransformerDts<'a> { ExportDefaultDeclarationKind::ClassDeclaration(decl) => self .transform_class(decl) .map(|d| (None, ExportDefaultDeclarationKind::ClassDeclaration(d))), - ExportDefaultDeclarationKind::TSInterfaceDeclaration(decl) => { - // TODO: need to transform TSInterfaceDeclaration - Some(( - None, - ExportDefaultDeclarationKind::TSInterfaceDeclaration(self.ctx.ast.copy(decl)), - )) + ExportDefaultDeclarationKind::TSInterfaceDeclaration(interface_decl) => { + self.visit_ts_interface_declaration(interface_decl); + Some((None, self.ctx.ast.copy(&decl.declaration))) } expr @ match_expression!(ExportDefaultDeclarationKind) => { let expr = expr.to_expression(); diff --git a/crates/oxc_transformer_dts/src/types.rs b/crates/oxc_transformer_dts/src/types.rs index 7e45c91bf..9e7314c21 100644 --- a/crates/oxc_transformer_dts/src/types.rs +++ b/crates/oxc_transformer_dts/src/types.rs @@ -62,11 +62,7 @@ impl<'a> TransformerDts<'a> { let members = self.ctx.ast.new_vec_from_iter(expr.properties.iter().filter_map(|property| match property { ObjectPropertyKind::ObjectProperty(object) => { - if object.computed { - self.ctx.error( - OxcDiagnostic::error("Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.") - .with_label(object.span) - ); + if self.report_property_key(&object.key, object.computed) { return None; }