mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
feat(transformer-dts): report error for invalid signature property key (#3698)
This commit is contained in:
parent
d65c652700
commit
af5009a591
5 changed files with 78 additions and 35 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue