mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 20:32:10 +00:00
feat(transformer/typescript): support transform namespace (#2075)
This commit is contained in:
parent
2e78b918d1
commit
56ca8b6dfe
5 changed files with 369 additions and 4 deletions
|
|
@ -891,6 +891,10 @@ impl<'a> Modifiers<'a> {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(false, |modifiers| modifiers.iter().any(|modifier| modifier.kind == target))
|
.map_or(false, |modifiers| modifiers.iter().any(|modifier| modifier.kind == target))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_contains_declare(&self) -> bool {
|
||||||
|
self.contains(ModifierKind::Declare)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Export Assignment in non-module files
|
/// Export Assignment in non-module files
|
||||||
|
|
|
||||||
|
|
@ -181,6 +181,8 @@ impl<'a> VisitMut<'a> for Transformer<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_statements(&mut self, stmts: &mut oxc_allocator::Vec<'a, Statement<'a>>) {
|
fn visit_statements(&mut self, stmts: &mut oxc_allocator::Vec<'a, Statement<'a>>) {
|
||||||
|
self.typescript.as_mut().map(|t| t.transform_statements(stmts));
|
||||||
|
|
||||||
for stmt in stmts.iter_mut() {
|
for stmt in stmts.iter_mut() {
|
||||||
self.visit_statement(stmt);
|
self.visit_statement(stmt);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,10 @@ impl<'a> TypeScript<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn transform_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>) {
|
||||||
|
self.insert_let_decl_for_ts_module_block(stmts);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn transform_statement(&mut self, stmt: &mut Statement<'a>) {
|
pub fn transform_statement(&mut self, stmt: &mut Statement<'a>) {
|
||||||
let new_stmt = match stmt {
|
let new_stmt = match stmt {
|
||||||
Statement::ModuleDeclaration(module_decl) => {
|
Statement::ModuleDeclaration(module_decl) => {
|
||||||
|
|
@ -58,6 +62,13 @@ impl<'a> TypeScript<'a> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Statement::Declaration(Declaration::TSModuleDeclaration(ts_module_decl)) => {
|
||||||
|
if ts_module_decl.modifiers.is_contains_declare() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(self.transform_ts_module_block(ts_module_decl))
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -562,4 +573,128 @@ impl<'a> TypeScript<'a> {
|
||||||
|
|
||||||
Some(Statement::Declaration(self.ast.move_declaration(declaration)))
|
Some(Statement::Declaration(self.ast.move_declaration(declaration)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Insert let declaration for ts module block
|
||||||
|
fn insert_let_decl_for_ts_module_block(&mut self, stmts: &mut Vec<'a, Statement<'a>>) {
|
||||||
|
let mut insert_var_decl = vec![];
|
||||||
|
|
||||||
|
for (index, stmt) in stmts.iter().enumerate() {
|
||||||
|
if let Statement::Declaration(Declaration::TSModuleDeclaration(decl)) = stmt {
|
||||||
|
if !decl.modifiers.is_contains_declare() {
|
||||||
|
insert_var_decl.push((index, decl.id.name().clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (index, name) in insert_var_decl.into_iter().rev() {
|
||||||
|
let kind = VariableDeclarationKind::Let;
|
||||||
|
let decls = {
|
||||||
|
let binding_identifier = BindingIdentifier::new(SPAN, name.clone());
|
||||||
|
let binding_pattern_kind = self.ast.binding_pattern_identifier(binding_identifier);
|
||||||
|
let binding = self.ast.binding_pattern(binding_pattern_kind, None, false);
|
||||||
|
let decl = self.ast.variable_declarator(SPAN, kind, binding, None, false);
|
||||||
|
self.ast.new_vec_single(decl)
|
||||||
|
};
|
||||||
|
let variable_declaration =
|
||||||
|
self.ast.variable_declaration(SPAN, kind, decls, Modifiers::empty());
|
||||||
|
|
||||||
|
let stmt =
|
||||||
|
Statement::Declaration(Declaration::VariableDeclaration(variable_declaration));
|
||||||
|
stmts.insert(index, stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ```TypeScript
|
||||||
|
/// // transform ts module block
|
||||||
|
/// namespace Foo {
|
||||||
|
/// }
|
||||||
|
/// // to
|
||||||
|
/// let Foo; // this line added in `insert_let_decl_for_ts_module_block`
|
||||||
|
/// (function (_Foo) {
|
||||||
|
/// })(Foo || (Foo = {}));
|
||||||
|
/// ```
|
||||||
|
fn transform_ts_module_block(
|
||||||
|
&mut self,
|
||||||
|
block: &mut Box<'a, TSModuleDeclaration<'a>>,
|
||||||
|
) -> Statement<'a> {
|
||||||
|
let body_statements = match &mut block.body {
|
||||||
|
TSModuleDeclarationBody::TSModuleDeclaration(decl) => {
|
||||||
|
let transformed_module_block = self.transform_ts_module_block(decl);
|
||||||
|
self.ast.new_vec_single(transformed_module_block)
|
||||||
|
}
|
||||||
|
TSModuleDeclarationBody::TSModuleBlock(ts_module_block) => {
|
||||||
|
self.ast.move_statement_vec(&mut ts_module_block.body)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let name = block.id.name();
|
||||||
|
|
||||||
|
let callee = {
|
||||||
|
let body = self.ast.function_body(SPAN, self.ast.new_vec(), body_statements);
|
||||||
|
let params = self.ast.formal_parameters(
|
||||||
|
SPAN,
|
||||||
|
FormalParameterKind::FormalParameter,
|
||||||
|
self.ast.new_vec_single(self.ast.formal_parameter(
|
||||||
|
SPAN,
|
||||||
|
self.ast.binding_pattern(
|
||||||
|
self.ast.binding_pattern_identifier(BindingIdentifier::new(
|
||||||
|
SPAN,
|
||||||
|
format!("_{}", name.clone()).into(),
|
||||||
|
)),
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
self.ast.new_vec(),
|
||||||
|
)),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
let function = self.ast.function(
|
||||||
|
FunctionType::FunctionExpression,
|
||||||
|
SPAN,
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
None,
|
||||||
|
params,
|
||||||
|
Some(body),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Modifiers::empty(),
|
||||||
|
);
|
||||||
|
let function_expr = self.ast.function_expression(function);
|
||||||
|
self.ast.parenthesized_expression(SPAN, function_expr)
|
||||||
|
};
|
||||||
|
|
||||||
|
let arguments = {
|
||||||
|
let right = {
|
||||||
|
let left = AssignmentTarget::SimpleAssignmentTarget(
|
||||||
|
self.ast.simple_assignment_target_identifier(IdentifierReference::new(
|
||||||
|
SPAN,
|
||||||
|
name.clone(),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
let right = self.ast.object_expression(SPAN, self.ast.new_vec(), None);
|
||||||
|
self.ast.parenthesized_expression(
|
||||||
|
SPAN,
|
||||||
|
self.ast.assignment_expression(SPAN, AssignmentOperator::Assign, left, right),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
self.ast.new_vec_single(Argument::Expression(
|
||||||
|
self.ast.logical_expression(
|
||||||
|
SPAN,
|
||||||
|
self.ast.identifier_reference_expression(IdentifierReference::new(
|
||||||
|
SPAN,
|
||||||
|
name.clone(),
|
||||||
|
)),
|
||||||
|
LogicalOperator::Or,
|
||||||
|
right,
|
||||||
|
),
|
||||||
|
))
|
||||||
|
};
|
||||||
|
let expr = self.ast.call_expression(SPAN, callee, arguments, false, None);
|
||||||
|
self.ast.expression_statement(SPAN, expr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
Passed: 314/1179
|
Passed: 316/1179
|
||||||
|
|
||||||
# All Passed:
|
# All Passed:
|
||||||
* babel-plugin-transform-numeric-separator
|
* babel-plugin-transform-numeric-separator
|
||||||
|
|
@ -832,7 +832,7 @@ Passed: 314/1179
|
||||||
* general/function-duplicate-name/input.js
|
* general/function-duplicate-name/input.js
|
||||||
* general/object/input.js
|
* general/object/input.js
|
||||||
|
|
||||||
# babel-plugin-transform-typescript (83/158)
|
# babel-plugin-transform-typescript (85/158)
|
||||||
* class/abstract-class-decorated/input.ts
|
* class/abstract-class-decorated/input.ts
|
||||||
* class/abstract-class-decorated-method/input.ts
|
* class/abstract-class-decorated-method/input.ts
|
||||||
* class/abstract-class-decorated-parameter/input.ts
|
* class/abstract-class-decorated-parameter/input.ts
|
||||||
|
|
@ -875,7 +875,6 @@ Passed: 314/1179
|
||||||
* namespace/clobber-import/input.ts
|
* namespace/clobber-import/input.ts
|
||||||
* namespace/contentious-names/input.ts
|
* namespace/contentious-names/input.ts
|
||||||
* namespace/declare/input.ts
|
* namespace/declare/input.ts
|
||||||
* namespace/declare-global-nested-namespace/input.ts
|
|
||||||
* namespace/empty-removed/input.ts
|
* namespace/empty-removed/input.ts
|
||||||
* namespace/export/input.ts
|
* namespace/export/input.ts
|
||||||
* namespace/export-type-only/input.ts
|
* namespace/export-type-only/input.ts
|
||||||
|
|
@ -891,7 +890,6 @@ Passed: 314/1179
|
||||||
* namespace/nested-shorthand/input.ts
|
* namespace/nested-shorthand/input.ts
|
||||||
* namespace/nested-shorthand-export/input.ts
|
* namespace/nested-shorthand-export/input.ts
|
||||||
* namespace/same-name/input.ts
|
* namespace/same-name/input.ts
|
||||||
* namespace/undeclared/input.ts
|
|
||||||
* optimize-const-enums/custom-values/input.ts
|
* optimize-const-enums/custom-values/input.ts
|
||||||
* optimize-const-enums/custom-values-exported/input.ts
|
* optimize-const-enums/custom-values-exported/input.ts
|
||||||
* optimize-const-enums/declare/input.ts
|
* optimize-const-enums/declare/input.ts
|
||||||
|
|
|
||||||
|
|
@ -511,11 +511,237 @@ var Animals = (Animals => {
|
||||||
|
|
||||||
# typescript/tests/cases/conformance/enums/enumMerging.ts
|
# typescript/tests/cases/conformance/enums/enumMerging.ts
|
||||||
```typescript
|
```typescript
|
||||||
|
let M1;
|
||||||
|
(function(_M1) {
|
||||||
|
var EImpl1 = (EImpl1 => {
|
||||||
|
const A = 0;
|
||||||
|
EImpl1[EImpl1['A'] = A] = 'A';
|
||||||
|
const B = 1 + A;
|
||||||
|
EImpl1[EImpl1['B'] = B] = 'B';
|
||||||
|
const C = 1 + B;
|
||||||
|
EImpl1[EImpl1['C'] = C] = 'C';
|
||||||
|
return EImpl1;
|
||||||
|
})(EImpl1 || {});
|
||||||
|
var EImpl1 = (EImpl1 => {
|
||||||
|
const D = 1;
|
||||||
|
EImpl1[EImpl1['D'] = D] = 'D';
|
||||||
|
const E = 1 + D;
|
||||||
|
EImpl1[EImpl1['E'] = E] = 'E';
|
||||||
|
const F = 1 + E;
|
||||||
|
EImpl1[EImpl1['F'] = F] = 'F';
|
||||||
|
return EImpl1;
|
||||||
|
})(EImpl1 || {});
|
||||||
|
export var EConst1 = (EConst1 => {
|
||||||
|
const A = 3;
|
||||||
|
EConst1[EConst1['A'] = A] = 'A';
|
||||||
|
const B = 2;
|
||||||
|
EConst1[EConst1['B'] = B] = 'B';
|
||||||
|
const C = 1;
|
||||||
|
EConst1[EConst1['C'] = C] = 'C';
|
||||||
|
return EConst1;
|
||||||
|
})(EConst1 || {});
|
||||||
|
var EConst1 = (EConst1 => {
|
||||||
|
const D = 7;
|
||||||
|
EConst1[EConst1['D'] = D] = 'D';
|
||||||
|
const E = 9;
|
||||||
|
EConst1[EConst1['E'] = E] = 'E';
|
||||||
|
const F = 8;
|
||||||
|
EConst1[EConst1['F'] = F] = 'F';
|
||||||
|
return EConst1;
|
||||||
|
})(EConst1 || {});
|
||||||
|
var x = [EConst1.A, EConst1.B, EConst1.C, EConst1.D, EConst1.E, EConst1.F];
|
||||||
|
})(M1 || (M1 = {}));
|
||||||
|
let M2;
|
||||||
|
(function(_M2) {
|
||||||
|
export var EComp2 = (EComp2 => {
|
||||||
|
const A = 'foo'.length;
|
||||||
|
EComp2[EComp2['A'] = A] = 'A';
|
||||||
|
const B = 'foo'.length;
|
||||||
|
EComp2[EComp2['B'] = B] = 'B';
|
||||||
|
const C = 'foo'.length;
|
||||||
|
EComp2[EComp2['C'] = C] = 'C';
|
||||||
|
return EComp2;
|
||||||
|
})(EComp2 || {});
|
||||||
|
var EComp2 = (EComp2 => {
|
||||||
|
const D = 'foo'.length;
|
||||||
|
EComp2[EComp2['D'] = D] = 'D';
|
||||||
|
const E = 'foo'.length;
|
||||||
|
EComp2[EComp2['E'] = E] = 'E';
|
||||||
|
const F = 'foo'.length;
|
||||||
|
EComp2[EComp2['F'] = F] = 'F';
|
||||||
|
return EComp2;
|
||||||
|
})(EComp2 || {});
|
||||||
|
var x = [EComp2.A, EComp2.B, EComp2.C, EComp2.D, EComp2.E, EComp2.F];
|
||||||
|
})(M2 || (M2 = {}));
|
||||||
|
let M3;
|
||||||
|
(function(_M3) {
|
||||||
|
var EInit = (EInit => {
|
||||||
|
const A = 0;
|
||||||
|
EInit[EInit['A'] = A] = 'A';
|
||||||
|
const B = 1 + A;
|
||||||
|
EInit[EInit['B'] = B] = 'B';
|
||||||
|
return EInit;
|
||||||
|
})(EInit || {});
|
||||||
|
var EInit = (EInit => {
|
||||||
|
const C = 1;
|
||||||
|
EInit[EInit['C'] = C] = 'C';
|
||||||
|
const D = 1 + C;
|
||||||
|
EInit[EInit['D'] = D] = 'D';
|
||||||
|
const E = 1 + D;
|
||||||
|
EInit[EInit['E'] = E] = 'E';
|
||||||
|
return EInit;
|
||||||
|
})(EInit || {});
|
||||||
|
})(M3 || (M3 = {}));
|
||||||
|
let M4;
|
||||||
|
(function(_M4) {
|
||||||
|
export var Color = (Color => {
|
||||||
|
const Red = 0;
|
||||||
|
Color[Color['Red'] = Red] = 'Red';
|
||||||
|
const Green = 1 + Red;
|
||||||
|
Color[Color['Green'] = Green] = 'Green';
|
||||||
|
const Blue = 1 + Green;
|
||||||
|
Color[Color['Blue'] = Blue] = 'Blue';
|
||||||
|
return Color;
|
||||||
|
})(Color || {});
|
||||||
|
})(M4 || (M4 = {}));
|
||||||
|
let M5;
|
||||||
|
(function(_M5) {
|
||||||
|
var Color = (Color => {
|
||||||
|
const Red = 0;
|
||||||
|
Color[Color['Red'] = Red] = 'Red';
|
||||||
|
const Green = 1 + Red;
|
||||||
|
Color[Color['Green'] = Green] = 'Green';
|
||||||
|
const Blue = 1 + Green;
|
||||||
|
Color[Color['Blue'] = Blue] = 'Blue';
|
||||||
|
return Color;
|
||||||
|
})(Color || {});
|
||||||
|
})(M5 || (M5 = {}));
|
||||||
|
let M6;
|
||||||
|
(function(_M6) {
|
||||||
|
(function(_A) {
|
||||||
|
var Color = (Color => {
|
||||||
|
const Red = 0;
|
||||||
|
Color[Color['Red'] = Red] = 'Red';
|
||||||
|
const Green = 1 + Red;
|
||||||
|
Color[Color['Green'] = Green] = 'Green';
|
||||||
|
const Blue = 1 + Green;
|
||||||
|
Color[Color['Blue'] = Blue] = 'Blue';
|
||||||
|
return Color;
|
||||||
|
})(Color || {});
|
||||||
|
})(A || (A = {}));
|
||||||
|
})(M6 || (M6 = {}));
|
||||||
|
let M6;
|
||||||
|
(function(_M6) {
|
||||||
|
var t = A.Color.Yellow;
|
||||||
|
t = A.Color.Red;
|
||||||
|
})(M6 || (M6 = {}));
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# typescript/tests/cases/conformance/enums/enumMergingErrors.ts
|
# typescript/tests/cases/conformance/enums/enumMergingErrors.ts
|
||||||
```typescript
|
```typescript
|
||||||
|
let M;
|
||||||
|
(function(_M) {
|
||||||
|
export var E1 = (E1 => {
|
||||||
|
const A = 0;
|
||||||
|
E1[E1['A'] = A] = 'A';
|
||||||
|
return E1;
|
||||||
|
})(E1 || {});
|
||||||
|
export var E2 = (E2 => {
|
||||||
|
const C = 0;
|
||||||
|
E2[E2['C'] = C] = 'C';
|
||||||
|
return E2;
|
||||||
|
})(E2 || {});
|
||||||
|
export var E3 = (E3 => {
|
||||||
|
const A = 0;
|
||||||
|
E3[E3['A'] = A] = 'A';
|
||||||
|
return E3;
|
||||||
|
})(E3 || {});
|
||||||
|
})(M || (M = {}));
|
||||||
|
let M;
|
||||||
|
(function(_M) {
|
||||||
|
var E1 = (E1 => {
|
||||||
|
const B = 'foo'.length;
|
||||||
|
E1[E1['B'] = B] = 'B';
|
||||||
|
return E1;
|
||||||
|
})(E1 || {});
|
||||||
|
var E2 = (E2 => {
|
||||||
|
const B = 'foo'.length;
|
||||||
|
E2[E2['B'] = B] = 'B';
|
||||||
|
return E2;
|
||||||
|
})(E2 || {});
|
||||||
|
var E3 = (E3 => {
|
||||||
|
const C = 0;
|
||||||
|
E3[E3['C'] = C] = 'C';
|
||||||
|
return E3;
|
||||||
|
})(E3 || {});
|
||||||
|
})(M || (M = {}));
|
||||||
|
let M;
|
||||||
|
(function(_M) {
|
||||||
|
var E1 = (E1 => {
|
||||||
|
const C = 0;
|
||||||
|
E1[E1['C'] = C] = 'C';
|
||||||
|
return E1;
|
||||||
|
})(E1 || {});
|
||||||
|
var E2 = (E2 => {
|
||||||
|
const A = 0;
|
||||||
|
E2[E2['A'] = A] = 'A';
|
||||||
|
return E2;
|
||||||
|
})(E2 || {});
|
||||||
|
var E3 = (E3 => {
|
||||||
|
const B = 'foo'.length;
|
||||||
|
E3[E3['B'] = B] = 'B';
|
||||||
|
return E3;
|
||||||
|
})(E3 || {});
|
||||||
|
})(M || (M = {}));
|
||||||
|
let M1;
|
||||||
|
(function(_M1) {
|
||||||
|
var E1 = (E1 => {
|
||||||
|
const A = 0;
|
||||||
|
E1[E1['A'] = A] = 'A';
|
||||||
|
return E1;
|
||||||
|
})(E1 || {});
|
||||||
|
})(M1 || (M1 = {}));
|
||||||
|
let M1;
|
||||||
|
(function(_M1) {
|
||||||
|
var E1 = (E1 => {
|
||||||
|
const B = 0;
|
||||||
|
E1[E1['B'] = B] = 'B';
|
||||||
|
return E1;
|
||||||
|
})(E1 || {});
|
||||||
|
})(M1 || (M1 = {}));
|
||||||
|
let M1;
|
||||||
|
(function(_M1) {
|
||||||
|
var E1 = (E1 => {
|
||||||
|
const C = 0;
|
||||||
|
E1[E1['C'] = C] = 'C';
|
||||||
|
return E1;
|
||||||
|
})(E1 || {});
|
||||||
|
})(M1 || (M1 = {}));
|
||||||
|
let M2;
|
||||||
|
(function(_M2) {
|
||||||
|
var E1 = (E1 => {
|
||||||
|
const A = 0;
|
||||||
|
E1[E1['A'] = A] = 'A';
|
||||||
|
return E1;
|
||||||
|
})(E1 || {});
|
||||||
|
})(M2 || (M2 = {}));
|
||||||
|
let M2;
|
||||||
|
(function(_M2) {
|
||||||
|
var E1 = (E1 => {
|
||||||
|
const B = 0;
|
||||||
|
E1[E1['B'] = B] = 'B';
|
||||||
|
return E1;
|
||||||
|
})(E1 || {});
|
||||||
|
})(M2 || (M2 = {}));
|
||||||
|
let M2;
|
||||||
|
(function(_M2) {
|
||||||
|
var E1 = (E1 => {
|
||||||
|
const C = 0;
|
||||||
|
E1[E1['C'] = C] = 'C';
|
||||||
|
return E1;
|
||||||
|
})(E1 || {});
|
||||||
|
})(M2 || (M2 = {}));
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue