feat(transformer/typescript): if the binding exists, the identifier reference is not renamed (#3387)

Related:
https://github.com/oxc-project/oxc/discussions/3251#discussioncomment-9528247
This commit is contained in:
Dunqing 2024-05-27 09:00:04 +08:00 committed by GitHub
parent d4371e8f95
commit 241e8d1899
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 30 additions and 16 deletions

View file

@ -234,8 +234,8 @@ impl<'a> Traverse<'a> for Transformer<'a> {
self.x0_typescript.transform_identifier_reference(ident, ctx); self.x0_typescript.transform_identifier_reference(ident, ctx);
} }
fn enter_statement(&mut self, stmt: &mut Statement<'a>, _ctx: &mut TraverseCtx<'a>) { fn enter_statement(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_statement(stmt); self.x0_typescript.transform_statement(stmt, ctx);
} }
fn enter_declaration(&mut self, decl: &mut Declaration<'a>, _ctx: &mut TraverseCtx<'a>) { fn enter_declaration(&mut self, decl: &mut Declaration<'a>, _ctx: &mut TraverseCtx<'a>) {

View file

@ -7,6 +7,7 @@ use oxc_syntax::{
number::{NumberBase, ToJsInt32, ToJsString}, number::{NumberBase, ToJsInt32, ToJsString},
operator::{AssignmentOperator, BinaryOperator, LogicalOperator, UnaryOperator}, operator::{AssignmentOperator, BinaryOperator, LogicalOperator, UnaryOperator},
}; };
use oxc_traverse::TraverseCtx;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use crate::context::Ctx; use crate::context::Ctx;
@ -37,6 +38,7 @@ impl<'a> TypeScriptEnum<'a> {
&mut self, &mut self,
decl: &Box<'a, TSEnumDeclaration<'a>>, decl: &Box<'a, TSEnumDeclaration<'a>>,
is_export: bool, is_export: bool,
ctx: &TraverseCtx<'a>,
) -> Option<Statement<'a>> { ) -> Option<Statement<'a>> {
if decl.modifiers.contains(ModifierKind::Declare) { if decl.modifiers.contains(ModifierKind::Declare) {
return None; return None;
@ -61,7 +63,7 @@ impl<'a> TypeScriptEnum<'a> {
// Foo[Foo["X"] = 0] = "X"; // Foo[Foo["X"] = 0] = "X";
let enum_name = decl.id.name.clone(); let enum_name = decl.id.name.clone();
let is_already_declared = self.enums.contains_key(&enum_name); let is_already_declared = self.enums.contains_key(&enum_name);
let statements = self.transform_ts_enum_members(&decl.members, &enum_name); let statements = self.transform_ts_enum_members(&decl.members, &enum_name, ctx);
let body = self.ctx.ast.function_body(decl.span, self.ctx.ast.new_vec(), statements); let body = self.ctx.ast.function_body(decl.span, self.ctx.ast.new_vec(), statements);
let r#type = FunctionType::FunctionExpression; let r#type = FunctionType::FunctionExpression;
let callee = self.ctx.ast.plain_function(r#type, SPAN, None, params, Some(body)); let callee = self.ctx.ast.plain_function(r#type, SPAN, None, params, Some(body));
@ -128,6 +130,7 @@ impl<'a> TypeScriptEnum<'a> {
&mut self, &mut self,
members: &Vec<'a, TSEnumMember<'a>>, members: &Vec<'a, TSEnumMember<'a>>,
enum_name: &Atom<'a>, enum_name: &Atom<'a>,
ctx: &TraverseCtx<'a>,
) -> Vec<'a, Statement<'a>> { ) -> Vec<'a, Statement<'a>> {
let mut statements = self.ctx.ast.new_vec(); let mut statements = self.ctx.ast.new_vec();
let mut prev_constant_value = Some(ConstantValue::Number(-1.0)); let mut prev_constant_value = Some(ConstantValue::Number(-1.0));
@ -153,12 +156,24 @@ impl<'a> TypeScriptEnum<'a> {
None => { None => {
prev_constant_value = None; prev_constant_value = None;
let mut new_initializer = self.ctx.ast.copy(initializer); let mut new_initializer = self.ctx.ast.copy(initializer);
IdentifierReferenceRename::new(
enum_name.clone(), // If the initializer is a binding identifier,
previous_enum_members.clone(), // and it is not a binding in the current scope and parent scopes,
&self.ctx, // we need to rename it to the enum name. e.g. `d = c` to `d = A.c`
) // same behavior in https://github.com/babel/babel/blob/610897a9a96c5e344e77ca9665df7613d2f88358/packages/babel-plugin-transform-typescript/src/enum.ts#L145-L150
.visit_expression(&mut new_initializer); let has_binding = matches!(
&new_initializer,
Expression::Identifier(ident) if ctx.scopes().has_binding(ctx.current_scope_id(), &ident.name)
);
if !has_binding {
IdentifierReferenceRename::new(
enum_name.clone(),
previous_enum_members.clone(),
&self.ctx,
)
.visit_expression(&mut new_initializer);
}
new_initializer new_initializer
} }
Some(constant_value) => { Some(constant_value) => {

View file

@ -136,11 +136,11 @@ impl<'a> TypeScript<'a> {
self.annotations.transform_statements_on_exit(stmts); self.annotations.transform_statements_on_exit(stmts);
} }
pub fn transform_statement(&mut self, stmt: &mut Statement<'a>) { pub fn transform_statement(&mut self, stmt: &mut Statement<'a>, ctx: &TraverseCtx<'a>) {
let new_stmt = match stmt { let new_stmt = match stmt {
match_declaration!(Statement) => { match_declaration!(Statement) => {
if let Declaration::TSEnumDeclaration(ts_enum_decl) = &stmt.to_declaration() { if let Declaration::TSEnumDeclaration(ts_enum_decl) = &stmt.to_declaration() {
self.r#enum.transform_ts_enum(ts_enum_decl, false) self.r#enum.transform_ts_enum(ts_enum_decl, false, ctx)
} else { } else {
None None
} }
@ -150,7 +150,7 @@ impl<'a> TypeScript<'a> {
stmt.to_module_declaration_mut() stmt.to_module_declaration_mut()
{ {
if let Some(Declaration::TSEnumDeclaration(ts_enum_decl)) = &decl.declaration { if let Some(Declaration::TSEnumDeclaration(ts_enum_decl)) = &decl.declaration {
self.r#enum.transform_ts_enum(ts_enum_decl, true) self.r#enum.transform_ts_enum(ts_enum_decl, true, ctx)
} else { } else {
None None
} }
@ -180,7 +180,7 @@ impl<'a> TypeScript<'a> {
pub fn transform_identifier_reference( pub fn transform_identifier_reference(
&mut self, &mut self,
ident: &mut IdentifierReference<'a>, ident: &mut IdentifierReference<'a>,
ctx: &TraverseCtx, ctx: &TraverseCtx<'a>,
) { ) {
if !ctx.parent().is_ts_interface_heritage() && !ctx.parent().is_ts_type_reference() { if !ctx.parent().is_ts_interface_heritage() && !ctx.parent().is_ts_type_reference() {
self.reference_collector.visit_identifier_reference(ident); self.reference_collector.visit_identifier_reference(ident);

View file

@ -1,6 +1,6 @@
commit: 4bd1b2c2 commit: 4bd1b2c2
Passed: 313/351 Passed: 314/351
# All Passed: # All Passed:
* babel-preset-react * babel-preset-react
@ -21,12 +21,11 @@ Passed: 313/351
* opts/optimizeConstEnums/input.ts * opts/optimizeConstEnums/input.ts
* opts/rewriteImportExtensions/input.ts * opts/rewriteImportExtensions/input.ts
# babel-plugin-transform-typescript (127/154) # babel-plugin-transform-typescript (128/154)
* enum/mix-references/input.ts * enum/mix-references/input.ts
* enum/scoped/input.ts * enum/scoped/input.ts
* enum/ts5.0-const-foldable/input.ts * enum/ts5.0-const-foldable/input.ts
* exports/declared-types/input.ts * exports/declared-types/input.ts
* imports/enum-value/input.ts
* imports/type-only-export-specifier-2/input.ts * imports/type-only-export-specifier-2/input.ts
* namespace/empty-removed/input.ts * namespace/empty-removed/input.ts
* namespace/mutable-fail/input.ts * namespace/mutable-fail/input.ts