diff --git a/crates/oxc_ast/src/ast_kind.rs b/crates/oxc_ast/src/ast_kind.rs index b20644459c8030..0c02e6c0d9c565 100644 --- a/crates/oxc_ast/src/ast_kind.rs +++ b/crates/oxc_ast/src/ast_kind.rs @@ -112,6 +112,7 @@ ast_kinds! { Class(&'a Class<'a>), ClassBody(&'a ClassBody<'a>), ClassHeritage(&'a Expression<'a>), + TSClassImplements(&'a TSClassImplements<'a>), StaticBlock(&'a StaticBlock<'a>), PropertyDefinition(&'a PropertyDefinition<'a>), MethodDefinition(&'a MethodDefinition<'a>), @@ -191,11 +192,13 @@ ast_kinds! { TSQualifiedName(&'a TSQualifiedName<'a>), TSInterfaceDeclaration(&'a TSInterfaceDeclaration<'a>), + TSInterfaceHeritage(&'a TSInterfaceHeritage<'a>), TSModuleDeclaration(&'a TSModuleDeclaration<'a>), TSTypeAliasDeclaration(&'a TSTypeAliasDeclaration<'a>), TSTypeAnnotation(&'a TSTypeAnnotation<'a>), TSTypeQuery(&'a TSTypeQuery<'a>), TSTypeAssertion(&'a TSTypeAssertion<'a>), + TSThisParameter(&'a TSThisParameter<'a>), TSTypeParameter(&'a TSTypeParameter<'a>), TSTypeParameterDeclaration(&'a TSTypeParameterDeclaration<'a>), TSTypeParameterInstantiation(&'a TSTypeParameterInstantiation<'a>), @@ -452,6 +455,7 @@ impl<'a> GetSpan for AstKind<'a> { Self::Class(x) => x.span, Self::ClassBody(x) => x.span, Self::ClassHeritage(x) => x.span(), + Self::TSClassImplements(x) => x.span, Self::StaticBlock(x) => x.span, Self::PropertyDefinition(x) => x.span, Self::MethodDefinition(x) => x.span, @@ -525,11 +529,13 @@ impl<'a> GetSpan for AstKind<'a> { Self::TSExternalModuleReference(x) => x.span, Self::TSQualifiedName(x) => x.span, Self::TSInterfaceDeclaration(x) => x.span, + Self::TSInterfaceHeritage(x) => x.span, Self::TSModuleDeclaration(x) => x.span, Self::TSTypeAliasDeclaration(x) => x.span, Self::TSTypeAnnotation(x) => x.span, Self::TSTypeQuery(x) => x.span, Self::TSTypeAssertion(x) => x.span, + Self::TSThisParameter(x) => x.span, Self::TSTypeParameter(x) => x.span, Self::TSTypeParameterDeclaration(x) => x.span, Self::TSTypeParameterInstantiation(x) => x.span, @@ -653,6 +659,7 @@ impl<'a> AstKind<'a> { c.id.as_ref().map_or_else(|| "", |id| id.name.as_str()) ) .into(), + Self::TSClassImplements(_) => "TSClassImplements".into(), Self::ClassBody(_) => "ClassBody".into(), Self::ClassHeritage(_) => "ClassHeritage".into(), Self::StaticBlock(_) => "StaticBlock".into(), @@ -728,11 +735,13 @@ impl<'a> AstKind<'a> { Self::TSExternalModuleReference(_) => "TSExternalModuleReference".into(), Self::TSQualifiedName(_) => "TSQualifiedName".into(), Self::TSInterfaceDeclaration(_) => "TSInterfaceDeclaration".into(), + Self::TSInterfaceHeritage(_) => "TSInterfaceHeritage".into(), Self::TSModuleDeclaration(_) => "TSModuleDeclaration".into(), Self::TSTypeAliasDeclaration(_) => "TSTypeAliasDeclaration".into(), Self::TSTypeAnnotation(_) => "TSTypeAnnotation".into(), Self::TSTypeQuery(_) => "TSTypeQuery".into(), Self::TSTypeAssertion(_) => "TSTypeAssertion".into(), + Self::TSThisParameter(_) => "TSThisParameter".into(), Self::TSTypeParameter(_) => "TSTypeParameter".into(), Self::TSTypeParameterDeclaration(_) => "TSTypeParameterDeclaration".into(), Self::TSTypeParameterInstantiation(_) => "TSTypeParameterInstantiation".into(), diff --git a/crates/oxc_ast/src/visit/visit.rs b/crates/oxc_ast/src/visit/visit.rs index 03fe92b6a60a58..aaf4cd713b03a2 100644 --- a/crates/oxc_ast/src/visit/visit.rs +++ b/crates/oxc_ast/src/visit/visit.rs @@ -187,6 +187,10 @@ pub trait Visit<'a>: Sized { walk_class_heritage(self, expr); } + fn visit_ts_class_implements(&mut self, expr: &TSClassImplements<'a>) { + walk_ts_class_implements(self, expr); + } + fn visit_class_body(&mut self, body: &ClassBody<'a>) { walk_class_body(self, body); } @@ -657,6 +661,10 @@ pub trait Visit<'a>: Sized { walk_ts_interface_declaration(self, decl); } + fn visit_ts_interface_heritage(&mut self, heritage: &TSInterfaceHeritage<'a>) { + walk_ts_interface_heritage(self, heritage); + } + fn visit_ts_as_expression(&mut self, expr: &TSAsExpression<'a>) { walk_ts_as_expression(self, expr); } @@ -689,6 +697,10 @@ pub trait Visit<'a>: Sized { walk_ts_tuple_element(self, ty); } + fn visit_ts_this_parameter(&mut self, param: &TSThisParameter<'a>) { + walk_ts_this_parameter(self, param); + } + fn visit_ts_type_parameter(&mut self, ty: &TSTypeParameter<'a>) { walk_ts_type_parameter(self, ty); } @@ -1253,6 +1265,9 @@ pub mod walk { if let Some(parameters) = &func.type_parameters { visitor.visit_ts_type_parameter_declaration(parameters); } + if let Some(this_param) = &func.this_param { + visitor.visit_ts_this_parameter(this_param); + } visitor.visit_formal_parameters(&func.params); if let Some(body) = &func.body { visitor.visit_function_body(body); @@ -1337,6 +1352,11 @@ pub mod walk { if let Some(super_class) = &class.super_class { visitor.visit_class_heritage(super_class); } + if let Some(implements) = &class.implements { + for implement in implements { + visitor.visit_ts_class_implements(implement); + } + } if let Some(super_parameters) = &class.super_type_parameters { visitor.visit_ts_type_parameter_instantiation(super_parameters); } @@ -1354,6 +1374,19 @@ pub mod walk { visitor.leave_node(kind); } + pub fn walk_ts_class_implements<'a, V: Visit<'a>>( + visitor: &mut V, + implements: &TSClassImplements<'a>, + ) { + let kind = AstKind::TSClassImplements(visitor.alloc(implements)); + visitor.enter_node(kind); + visitor.visit_ts_type_name(&implements.expression); + if let Some(type_parameters) = &implements.type_parameters { + visitor.visit_ts_type_parameter_instantiation(type_parameters); + } + visitor.leave_node(kind); + } + pub fn walk_class_body<'a, V: Visit<'a>>(visitor: &mut V, body: &ClassBody<'a>) { let kind = AstKind::ClassBody(visitor.alloc(body)); visitor.enter_node(kind); @@ -2624,6 +2657,11 @@ pub mod walk { let kind = AstKind::TSInterfaceDeclaration(visitor.alloc(decl)); visitor.enter_node(kind); visitor.visit_binding_identifier(&decl.id); + if let Some(extends) = &decl.extends { + for extend in extends { + visitor.visit_ts_interface_heritage(extend); + } + } if let Some(parameters) = &decl.type_parameters { visitor.visit_ts_type_parameter_declaration(parameters); } @@ -2633,6 +2671,19 @@ pub mod walk { visitor.leave_node(kind); } + pub fn walk_ts_interface_heritage<'a, V: Visit<'a>>( + visitor: &mut V, + heritage: &TSInterfaceHeritage<'a>, + ) { + let kind = AstKind::TSInterfaceHeritage(visitor.alloc(heritage)); + visitor.enter_node(kind); + visitor.visit_expression(&heritage.expression); + if let Some(type_parameters) = &heritage.type_parameters { + visitor.visit_ts_type_parameter_instantiation(type_parameters); + } + visitor.leave_node(kind); + } + pub fn walk_ts_as_expression<'a, V: Visit<'a>>(visitor: &mut V, expr: &TSAsExpression<'a>) { let kind = AstKind::TSAsExpression(visitor.alloc(expr)); visitor.enter_node(kind); @@ -2786,13 +2837,26 @@ pub mod walk { } pub fn walk_ts_function_type<'a, V: Visit<'a>>(visitor: &mut V, ty: &TSFunctionType<'a>) { - visitor.visit_formal_parameters(&ty.params); if let Some(parameters) = &ty.type_parameters { visitor.visit_ts_type_parameter_declaration(parameters); } + if let Some(this_param) = &ty.this_param { + visitor.visit_ts_this_parameter(this_param); + } + visitor.visit_formal_parameters(&ty.params); visitor.visit_ts_type_annotation(&ty.return_type); } + pub fn walk_ts_this_parameter<'a, V: Visit<'a>>(visitor: &mut V, ty: &TSThisParameter<'a>) { + let kind = AstKind::TSThisParameter(visitor.alloc(ty)); + visitor.enter_node(kind); + visitor.visit_identifier_name(&ty.this); + if let Some(type_annotation) = &ty.type_annotation { + visitor.visit_ts_type_annotation(type_annotation); + } + visitor.leave_node(kind); + } + pub fn walk_ts_type_parameter<'a, V: Visit<'a>>(visitor: &mut V, ty: &TSTypeParameter<'a>) { let kind = AstKind::TSTypeParameter(visitor.alloc(ty)); visitor.enter_scope(ScopeFlags::empty()); diff --git a/crates/oxc_isolated_declarations/tests/fixtures/eliminate-imports.ts b/crates/oxc_isolated_declarations/tests/fixtures/eliminate-imports.ts new file mode 100644 index 00000000000000..ef65926dc6b9ee --- /dev/null +++ b/crates/oxc_isolated_declarations/tests/fixtures/eliminate-imports.ts @@ -0,0 +1,7 @@ +import { AExtend, BExtend, Type, CImplements, CType, ThisType1, ThisType2, Unused } from 'mod'; + +export interface A extends AExtend {} +export class B extends BExtend {} +export class C implements CImplements {} +export function foo(this: ThisType1): void {} +export const bar: (this: ThisType2) => void = function() {} \ No newline at end of file diff --git a/crates/oxc_isolated_declarations/tests/snapshots/eliminate-imports.snap b/crates/oxc_isolated_declarations/tests/snapshots/eliminate-imports.snap new file mode 100644 index 00000000000000..beac1ada1b7d96 --- /dev/null +++ b/crates/oxc_isolated_declarations/tests/snapshots/eliminate-imports.snap @@ -0,0 +1,12 @@ +--- +source: crates/oxc_isolated_declarations/tests/mod.rs +input_file: crates/oxc_isolated_declarations/tests/fixtures/eliminate-imports.ts +--- +==================== .D.TS ==================== + +import { AExtend, BExtend, Type, CImplements, CType, ThisType1, ThisType2 } from 'mod'; +export interface A extends AExtend {} +export declare class B extends BExtend {} +export declare class C {} +export declare function foo(): void; +export declare const bar: (this:ThisType2 ) => void;