Skip to content

Commit

Permalink
fix(semantic): reset references flags when resolved (#7923)
Browse files Browse the repository at this point in the history
For this case, we set `current_reference_flags` to `ReferenceFlags::Type` for `TSInterfaceHeritage`, but never unset it, which causes resolving `fowardRef` identifier reuse `current_reference_flags` of `TSInterfaceHeritage`.

```ts
import { forwardRef } from "react";
export interface MenuTriggerProps extends Object {}
export const MenuTrigger = forwardRef();
```

In this PR, reset the `current_reference_flags` when resolved, so that we don't need to reset it in individual visit functions. This is a reasonable change because the `current_reference_flags` only applies to the next encountered identifier.
  • Loading branch information
Dunqing committed Dec 16, 2024
1 parent 523d48c commit 596aead
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 20 deletions.
21 changes: 7 additions & 14 deletions crates/oxc_semantic/src/builder.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
//! Semantic Builder
use std::cell::{Cell, RefCell};
use std::{
cell::{Cell, RefCell},
mem,
};

use rustc_hash::FxHashMap;

Expand Down Expand Up @@ -1789,7 +1792,6 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
fn visit_simple_assignment_target(&mut self, it: &SimpleAssignmentTarget<'a>) {
let kind = AstKind::SimpleAssignmentTarget(self.alloc(it));
self.enter_node(kind);
let prev_reference_flags = self.current_reference_flags;
// Except that the read-write flags has been set in visit_assignment_expression
// and visit_update_expression, this is always a write-only reference here.
if !self.current_reference_flags.is_write() {
Expand Down Expand Up @@ -1819,7 +1821,6 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
self.visit_member_expression(it.to_member_expression());
}
}
self.current_reference_flags = prev_reference_flags;
self.leave_node(kind);
}

Expand All @@ -1828,10 +1829,8 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
it: &AssignmentTargetPropertyIdentifier<'a>,
) {
// NOTE: AstKind doesn't exists!
let prev_reference_flags = self.current_reference_flags;
self.current_reference_flags = ReferenceFlags::Write;
self.visit_identifier_reference(&it.binding);
self.current_reference_flags = prev_reference_flags;
if let Some(init) = &it.init {
self.visit_expression(init);
}
Expand All @@ -1850,10 +1849,8 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
ExportDefaultDeclarationKind::Identifier(it) => {
// `export default ident`
// ^^^^^ -> can reference both type/value symbols
let prev_reference_flags = self.current_reference_flags;
self.current_reference_flags = ReferenceFlags::Read | ReferenceFlags::Type;
self.visit_identifier_reference(it);
self.current_reference_flags = prev_reference_flags;
}
match_expression!(ExportDefaultDeclarationKind) => {
self.visit_expression(it.to_expression());
Expand All @@ -1868,13 +1865,10 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
if let Some(declaration) = &it.declaration {
self.visit_declaration(declaration);
}
// let prev_reference_flags = self.current_reference_flags;
if it.export_kind.is_type() {
self.current_reference_flags = ReferenceFlags::Type;
}
self.visit_export_specifiers(&it.specifiers);
// self.current_reference_flags = prev_reference_flags;

if let Some(source) = &it.source {
self.visit_string_literal(source);
}
Expand Down Expand Up @@ -1914,14 +1908,12 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
let kind = AstKind::TSExportAssignment(self.alloc(it));
self.enter_node(kind);
self.visit_span(&it.span);
let prev_reference_flags = self.current_reference_flags;
// export = a;
// ^ can reference type/value symbols
if it.expression.is_identifier_reference() {
self.current_reference_flags = ReferenceFlags::Read | ReferenceFlags::Type;
}
self.visit_expression(&it.expression);
self.current_reference_flags = prev_reference_flags;
self.leave_node(kind);
}
}
Expand Down Expand Up @@ -2140,11 +2132,12 @@ impl<'a> SemanticBuilder<'a> {

/// Resolve reference flags for the current ast node.
#[inline]
fn resolve_reference_usages(&self) -> ReferenceFlags {
fn resolve_reference_usages(&mut self) -> ReferenceFlags {
if self.current_reference_flags.is_empty() {
ReferenceFlags::Read
} else {
self.current_reference_flags
// Take the current reference flags so that we can reset it to empty
mem::take(&mut self.current_reference_flags)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
source: crates/oxc_semantic/tests/main.rs
input_file: crates/oxc_semantic/tests/fixtures/oxc/ts/exports/named/interface-heritage.ts
---
[
{
"children": [
{
"children": [],
"flags": "ScopeFlags(StrictMode)",
"id": 1,
"node": "TSInterfaceDeclaration",
"symbols": []
}
],
"flags": "ScopeFlags(StrictMode | Top)",
"id": 0,
"node": "Program",
"symbols": [
{
"flags": "SymbolFlags(Import)",
"id": 0,
"name": "forwardRef",
"node": "ImportSpecifier(forwardRef)",
"references": [
{
"flags": "ReferenceFlags(Read)",
"id": 1,
"name": "forwardRef",
"node_id": 19
}
]
},
{
"flags": "SymbolFlags(Interface)",
"id": 1,
"name": "MenuTriggerProps",
"node": "TSInterfaceDeclaration",
"references": []
},
{
"flags": "SymbolFlags(BlockScopedVariable | ConstVariable)",
"id": 2,
"name": "MenuTrigger",
"node": "VariableDeclarator(MenuTrigger)",
"references": []
}
]
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { forwardRef } from "react";
export interface MenuTriggerProps extends Object {}
export const MenuTrigger = forwardRef();
6 changes: 0 additions & 6 deletions tasks/coverage/snapshots/semantic_typescript.snap
Original file line number Diff line number Diff line change
Expand Up @@ -36818,9 +36818,6 @@ rebuilt : ScopeId(19): ["key", "obj"]
Bindings mismatch:
after transform: ScopeId(26): ["T", "a"]
rebuilt : ScopeId(21): ["a"]
Reference flags mismatch for "Monkey":
after transform: ReferenceId(7): ReferenceFlags(Type)
rebuilt : ReferenceId(2): ReferenceFlags(Read)
Unresolved references mismatch:
after transform: ["Partial", "Readonly"]
rebuilt : []
Expand Down Expand Up @@ -40376,9 +40373,6 @@ rebuilt : SymbolId(0): Span { start: 62, end: 63 }
Symbol redeclarations mismatch for "B":
after transform: SymbolId(1): [Span { start: 62, end: 63 }]
rebuilt : SymbolId(0): []
Reference flags mismatch for "B":
after transform: ReferenceId(1): ReferenceFlags(Type)
rebuilt : ReferenceId(0): ReferenceFlags(Read)

tasks/coverage/typescript/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty8.ts
semantic error: Bindings mismatch:
Expand Down

0 comments on commit 596aead

Please sign in to comment.