diff --git a/crates/oxc_semantic/src/builder.rs b/crates/oxc_semantic/src/builder.rs index 0e3965aaf..fb668d9d6 100644 --- a/crates/oxc_semantic/src/builder.rs +++ b/crates/oxc_semantic/src/builder.rs @@ -70,6 +70,8 @@ pub struct SemanticBuilder<'a> { // and when we reach a value declaration we set it // to value like pub namespace_stack: Vec, + /// If true, the current node is in the type definition + in_type_definition: bool, // builders pub nodes: AstNodes<'a>, @@ -107,6 +109,7 @@ impl<'a> SemanticBuilder<'a> { current_node_id: AstNodeId::new(0), current_node_flags: NodeFlags::empty(), current_symbol_flags: SymbolFlags::empty(), + in_type_definition: false, current_scope_id, function_stack: vec![], namespace_stack: vec![], @@ -459,17 +462,24 @@ impl<'a> SemanticBuilder<'a> { .get_bindings(self.current_scope_id) .get(module_declaration.id.name()); self.namespace_stack.push(*symbol_id.unwrap()); + self.in_type_definition = true; } AstKind::TSTypeAliasDeclaration(type_alias_declaration) => { type_alias_declaration.bind(self); + self.in_type_definition = true; } AstKind::TSInterfaceDeclaration(interface_declaration) => { interface_declaration.bind(self); + self.in_type_definition = true; } AstKind::TSEnumDeclaration(enum_declaration) => { enum_declaration.bind(self); // TODO: const enum? self.make_all_namespaces_valuelike(); + self.in_type_definition = true; + } + AstKind::TSTypeAnnotation(_) => { + self.in_type_definition = true; } AstKind::TSEnumMember(enum_member) => { enum_member.bind(self); @@ -539,6 +549,13 @@ impl<'a> SemanticBuilder<'a> { AstKind::TSModuleBlock(_) => { self.namespace_stack.pop(); } + AstKind::TSEnumDeclaration(_) + | AstKind::TSTypeAliasDeclaration(_) + | AstKind::TSInterfaceDeclaration(_) + | AstKind::TSModuleDeclaration(_) + | AstKind::TSTypeAnnotation(_) => { + self.in_type_definition = false; + } _ => {} } } @@ -566,6 +583,10 @@ impl<'a> SemanticBuilder<'a> { /// Resolve reference flags for the current ast node. fn resolve_reference_usages(&self) -> ReferenceFlag { + if self.in_type_definition { + return ReferenceFlag::Type; + } + let mut flags = ReferenceFlag::None; if self.nodes.parent_id(self.current_node_id).is_none() { diff --git a/crates/oxc_semantic/src/reference.rs b/crates/oxc_semantic/src/reference.rs index 38d385f5c..8c0d62877 100644 --- a/crates/oxc_semantic/src/reference.rs +++ b/crates/oxc_semantic/src/reference.rs @@ -55,4 +55,8 @@ impl Reference { pub fn is_write(&self) -> bool { self.flag.is_write() } + + pub fn is_type(&self) -> bool { + self.flag.is_type() + } } diff --git a/crates/oxc_syntax/src/reference.rs b/crates/oxc_syntax/src/reference.rs index ad16137b6..9dff72f59 100644 --- a/crates/oxc_syntax/src/reference.rs +++ b/crates/oxc_syntax/src/reference.rs @@ -14,6 +14,8 @@ bitflags! { const None = 0; const Read = 1 << 0; const Write = 1 << 1; + // Used in type definitions. + const Type = 1 << 2; const ReadWrite = Self::Read.bits() | Self::Write.bits(); } } @@ -55,4 +57,9 @@ impl ReferenceFlag { pub const fn is_read_write(&self) -> bool { self.contains(Self::ReadWrite) } + + /// The identifier is used in a type definition. + pub const fn is_type(&self) -> bool { + self.contains(Self::Type) + } } diff --git a/crates/oxc_transformer/src/typescript/mod.rs b/crates/oxc_transformer/src/typescript/mod.rs index f5826702b..bf23388a6 100644 --- a/crates/oxc_transformer/src/typescript/mod.rs +++ b/crates/oxc_transformer/src/typescript/mod.rs @@ -199,10 +199,7 @@ impl<'a> TypeScript<'a> { .scopes() .get_binding(root_scope_id, name) .map(|symbol_id| { - self.ctx - .symbols() - .get_resolved_references(symbol_id) - .any(|x| x.is_read() || x.is_write()) + self.ctx.symbols().get_resolved_references(symbol_id).any(|x| !x.is_type()) }) .unwrap_or_default() } diff --git a/tasks/transform_conformance/babel.snap.md b/tasks/transform_conformance/babel.snap.md index ac7289288..c7f281a97 100644 --- a/tasks/transform_conformance/babel.snap.md +++ b/tasks/transform_conformance/babel.snap.md @@ -1,4 +1,4 @@ -Passed: 298/1179 +Passed: 304/1179 # All Passed: * babel-plugin-transform-numeric-separator @@ -832,7 +832,7 @@ Passed: 298/1179 * general/function-duplicate-name/input.js * general/object/input.js -# babel-plugin-transform-typescript (67/158) +# babel-plugin-transform-typescript (73/158) * class/abstract-class-decorated/input.ts * class/abstract-class-decorated-method/input.ts * class/abstract-class-decorated-parameter/input.ts @@ -862,12 +862,7 @@ Passed: 298/1179 * function/overloads-exports/input.mjs * imports/elide-injected/input.ts * imports/elide-no-import-specifiers/input.ts -* imports/elide-preact/input.ts -* imports/elide-react/input.ts -* imports/elision/input.ts * imports/elision-locations/input.ts -* imports/elision-qualifiedname/input.ts -* imports/elision-rename/input.ts * imports/enum-id/input.ts * imports/enum-value/input.ts * imports/import-named-type/input.ts @@ -877,7 +872,6 @@ Passed: 298/1179 * imports/import=-module-to-cjs/input.ts * imports/only-remove-type-imports/input.ts * imports/parameter-decorators/input.ts -* imports/property-signature/input.ts * imports/type-only-export-specifier-1/input.ts * imports/type-only-export-specifier-2/input.ts * imports/type-only-import-specifier-3/input.ts