mirror of
https://github.com/danbulant/oxc
synced 2026-05-25 04:42:10 +00:00
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:
parent
d4371e8f95
commit
241e8d1899
4 changed files with 30 additions and 16 deletions
|
|
@ -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>) {
|
||||||
|
|
|
||||||
|
|
@ -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) => {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue