feat(transformer/typescript): support transform constructor method (#2551)

This commit is contained in:
Dunqing 2024-03-01 21:12:30 +08:00 committed by GitHub
parent 37de80d9c9
commit 6d43e851e8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 81 additions and 4 deletions

View file

@ -313,4 +313,25 @@ impl<'a> VisitMut<'a> for Transformer<'a> {
.as_mut()
.map(|t: &mut JsonStrings| t.transform_string_literal(lit));
}
fn visit_method_definition(&mut self, def: &mut MethodDefinition<'a>) {
let kind = AstKind::MethodDefinition(self.alloc(def));
self.enter_node(kind);
self.typescript.as_mut().map(|t| t.transform_method_definition(def));
for decorator in def.decorators.iter_mut() {
self.visit_decorator(decorator);
}
let flags = match def.kind {
MethodDefinitionKind::Get => ScopeFlags::GetAccessor,
MethodDefinitionKind::Set => ScopeFlags::SetAccessor,
MethodDefinitionKind::Constructor => ScopeFlags::Constructor,
MethodDefinitionKind::Method => ScopeFlags::empty(),
};
self.visit_property_key(&mut def.key);
self.visit_function(&mut def.value, Some(flags));
self.leave_node(kind);
}
}

View file

@ -728,4 +728,62 @@ impl<'a> TypeScript<'a> {
let expr = self.ast.call_expression(SPAN, callee, arguments, false, None);
self.ast.expression_statement(SPAN, expr)
}
/// Transform constructor method
/// ```typescript
///
/// constructor(public x) {
/// super();
/// }
/// // to
/// constructor(x) {
/// super();
/// this.x = x;
/// }
/// ```
pub fn transform_method_definition(&mut self, def: &mut MethodDefinition<'a>) {
if !def.kind.is_constructor() {
return;
}
let mut params_name = vec![];
def.value.params.items.iter().for_each(|param| {
if !param.accessibility.is_some_and(|a| matches!(a, TSAccessibility::Public)) {
return;
}
match &param.pattern.kind {
BindingPatternKind::BindingIdentifier(ident) => {
params_name.push(ident.name.clone());
}
BindingPatternKind::AssignmentPattern(pattern) => {
if let BindingPatternKind::BindingIdentifier(ident) = &pattern.left.kind {
params_name.push(ident.name.clone());
}
}
_ => {}
}
});
let Some(body) = &mut def.value.body else {
return;
};
for name in params_name {
// TODO: We should push it before the super call
body.statements.push(self.ast.expression_statement(
SPAN,
self.ast.assignment_expression(
SPAN,
AssignmentOperator::Assign,
self.ast.simple_assignment_target_member_expression(self.ast.static_member(
SPAN,
self.ast.this_expression(SPAN),
IdentifierName::new(SPAN, name.clone()),
false,
)),
self.ast.identifier_reference_expression(IdentifierReference::new(SPAN, name)),
),
));
}
}
}

View file

@ -1,4 +1,4 @@
Passed: 349/1369
Passed: 351/1369
# All Passed:
* babel-plugin-transform-numeric-separator
@ -832,19 +832,17 @@ Passed: 349/1369
* general/function-duplicate-name/input.js
* general/object/input.js
# babel-plugin-transform-typescript (95/158)
# babel-plugin-transform-typescript (97/158)
* class/abstract-class-decorated-method/input.ts
* class/abstract-class-decorated-parameter/input.ts
* class/accessor-allowDeclareFields-false/input.ts
* class/accessor-allowDeclareFields-true/input.ts
* class/declare/input.ts
* class/decorated-declare-properties/input.ts
* class/parameter-properties/input.ts
* class/parameter-properties-late-super/input.ts
* class/parameter-properties-with-class/input.ts
* class/parameter-properties-with-class-and-super/input.ts
* class/parameter-properties-with-parameters/input.ts
* class/parameter-properties-with-super/input.ts
* class/private-method-override-transform-private/input.ts
* class/transform-properties-declare-wrong-order/input.ts
* exports/declared-types/input.ts