mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
fix(semantic): incorrect resolve references for ExportSpecifier (#4320)
```ts
type A = any;
const B = 0;
export { A, B }
^^^^^^^^ ExportSpecifiers
export { A }
^^^^^ type-only ExportSpecifiers
```
non-type-only `ExportSpecifier` can reference value and type symbols. but currently, `IdentifierReference` in ExportSpecifier only has a `ReferenceFlags::Read`
This commit is contained in:
parent
a88d588a07
commit
95e15b6dc5
6 changed files with 45 additions and 23 deletions
|
|
@ -399,9 +399,15 @@ impl<'a> SemanticBuilder<'a> {
|
|||
resolved_references.reserve(references.len());
|
||||
|
||||
references.retain(|(id, flag)| {
|
||||
if flag.is_type() && symbol_flag.is_type()
|
||||
if flag.is_type() && symbol_flag.is_can_be_referenced_by_type()
|
||||
|| flag.is_value() && symbol_flag.is_value()
|
||||
{
|
||||
// The non type-only ExportSpecifier can reference a type,
|
||||
// If the reference is not a type, remove the type flag from the reference
|
||||
if !symbol_flag.is_type() && !flag.is_type_only() {
|
||||
*self.symbols.references[*id].flag_mut() -= ReferenceFlag::Type;
|
||||
}
|
||||
|
||||
self.symbols.references[*id].set_symbol_id(symbol_id);
|
||||
resolved_references.push(*id);
|
||||
false
|
||||
|
|
@ -1619,11 +1625,12 @@ impl<'a> SemanticBuilder<'a> {
|
|||
self.current_reference_flag = ReferenceFlag::Type;
|
||||
}
|
||||
}
|
||||
AstKind::ExportAllDeclaration(s) if s.export_kind.is_type() => {
|
||||
self.current_reference_flag = ReferenceFlag::Type;
|
||||
}
|
||||
AstKind::ExportSpecifier(s) if s.export_kind.is_type() => {
|
||||
self.current_reference_flag = ReferenceFlag::Type;
|
||||
AstKind::ExportSpecifier(s) => {
|
||||
if self.current_reference_flag.is_type() || s.export_kind.is_type() {
|
||||
self.current_reference_flag = ReferenceFlag::Type;
|
||||
} else {
|
||||
self.current_reference_flag = ReferenceFlag::Read | ReferenceFlag::Type;
|
||||
}
|
||||
}
|
||||
AstKind::ImportSpecifier(specifier) => {
|
||||
specifier.bind(self);
|
||||
|
|
@ -1709,9 +1716,6 @@ impl<'a> SemanticBuilder<'a> {
|
|||
AstKind::TSTypeParameter(type_parameter) => {
|
||||
type_parameter.bind(self);
|
||||
}
|
||||
AstKind::ExportSpecifier(s) if s.export_kind.is_type() => {
|
||||
self.current_reference_flag = ReferenceFlag::Type;
|
||||
}
|
||||
AstKind::TSInterfaceHeritage(_) => {
|
||||
self.current_reference_flag = ReferenceFlag::Type;
|
||||
}
|
||||
|
|
@ -1798,17 +1802,11 @@ impl<'a> SemanticBuilder<'a> {
|
|||
AstKind::BindingIdentifier(_) => {
|
||||
self.current_symbol_flags -= SymbolFlags::Export;
|
||||
}
|
||||
AstKind::ExportNamedDeclaration(decl) => {
|
||||
if decl.export_kind.is_type() {
|
||||
self.current_reference_flag -= ReferenceFlag::Type;
|
||||
AstKind::ExportSpecifier(_) => {
|
||||
if !self.current_reference_flag.is_type_only() {
|
||||
self.current_reference_flag = ReferenceFlag::empty();
|
||||
}
|
||||
}
|
||||
AstKind::ExportAllDeclaration(s) if s.export_kind.is_type() => {
|
||||
self.current_reference_flag -= ReferenceFlag::Type;
|
||||
}
|
||||
AstKind::ExportSpecifier(s) if s.export_kind.is_type() => {
|
||||
self.current_reference_flag -= ReferenceFlag::Type;
|
||||
}
|
||||
AstKind::LabeledStatement(_) => self.label_builder.leave(),
|
||||
AstKind::StaticBlock(_) => {
|
||||
self.label_builder.leave_function_or_static_block();
|
||||
|
|
@ -1851,7 +1849,9 @@ impl<'a> SemanticBuilder<'a> {
|
|||
self.current_reference_flag -= ReferenceFlag::Read;
|
||||
}
|
||||
}
|
||||
AstKind::MemberExpression(_) | AstKind::TSTypeQuery(_) => {
|
||||
AstKind::MemberExpression(_)
|
||||
| AstKind::TSTypeQuery(_)
|
||||
| AstKind::ExportNamedDeclaration(_) => {
|
||||
self.current_reference_flag = ReferenceFlag::empty();
|
||||
}
|
||||
AstKind::AssignmentTarget(_) => self.current_reference_flag -= ReferenceFlag::Write,
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/export/named-du
|
|||
"node": "VariableDeclarator",
|
||||
"references": [
|
||||
{
|
||||
"flag": "ReferenceFlag(Read)",
|
||||
"flag": "ReferenceFlag(Read | Type)",
|
||||
"id": 0,
|
||||
"name": "T",
|
||||
"node_id": 12
|
||||
|
|
|
|||
|
|
@ -22,7 +22,14 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/export/named2-t
|
|||
"id": 0,
|
||||
"name": "A",
|
||||
"node": "TSTypeAliasDeclaration",
|
||||
"references": []
|
||||
"references": [
|
||||
{
|
||||
"flag": "ReferenceFlag(Read | Type)",
|
||||
"id": 0,
|
||||
"name": "A",
|
||||
"node_id": 8
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,14 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/export/named3-t
|
|||
"id": 0,
|
||||
"name": "V",
|
||||
"node": "TSTypeAliasDeclaration",
|
||||
"references": []
|
||||
"references": [
|
||||
{
|
||||
"flag": "ReferenceFlag(Read | Type)",
|
||||
"id": 0,
|
||||
"name": "V",
|
||||
"node_id": 8
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,6 +99,10 @@ impl ReferenceFlag {
|
|||
self.contains(Self::Type)
|
||||
}
|
||||
|
||||
pub const fn is_type_only(self) -> bool {
|
||||
matches!(self, Self::Type)
|
||||
}
|
||||
|
||||
pub const fn is_value(&self) -> bool {
|
||||
self.intersects(Self::Value)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,7 +95,11 @@ impl SymbolFlags {
|
|||
}
|
||||
|
||||
pub fn is_type(&self) -> bool {
|
||||
self.intersects(Self::Type | Self::TypeImport | Self::Import)
|
||||
self.intersects(Self::Type | Self::TypeImport)
|
||||
}
|
||||
|
||||
pub fn is_can_be_referenced_by_type(&self) -> bool {
|
||||
self.is_type() || self.contains(Self::Import)
|
||||
}
|
||||
|
||||
pub fn is_value(&self) -> bool {
|
||||
|
|
|
|||
Loading…
Reference in a new issue