Skip to content

Commit

Permalink
fix(semantic): TSConditionalType scope enter/exit locations
Browse files Browse the repository at this point in the history
  • Loading branch information
DonIsaac committed Oct 8, 2024
1 parent 54a28b8 commit df22a40
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 39 deletions.
2 changes: 2 additions & 0 deletions crates/oxc_ast/src/ast/ts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,8 +347,10 @@ pub struct TSConditionalType<'a> {
/// The type before `extends` in the test expression.
pub check_type: TSType<'a>,
/// The type `check_type` is being tested against.
#[scope(enter_before)]
pub extends_type: TSType<'a>,
/// The type evaluated to if the test is true.
#[scope(exit_after)]
pub true_type: TSType<'a>,
/// The type evaluated to if the test is false.
pub false_type: TSType<'a>,
Expand Down
4 changes: 2 additions & 2 deletions crates/oxc_ast/src/generated/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1913,12 +1913,12 @@ pub mod walk {
pub fn walk_ts_conditional_type<'a, V: Visit<'a>>(visitor: &mut V, it: &TSConditionalType<'a>) {
let kind = AstKind::TSConditionalType(visitor.alloc(it));
visitor.enter_node(kind);
visitor.enter_scope(ScopeFlags::empty(), &it.scope_id);
visitor.visit_ts_type(&it.check_type);
visitor.enter_scope(ScopeFlags::empty(), &it.scope_id);
visitor.visit_ts_type(&it.extends_type);
visitor.visit_ts_type(&it.true_type);
visitor.visit_ts_type(&it.false_type);
visitor.leave_scope();
visitor.visit_ts_type(&it.false_type);
visitor.leave_node(kind);
}

Expand Down
4 changes: 2 additions & 2 deletions crates/oxc_ast/src/generated/visit_mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1956,12 +1956,12 @@ pub mod walk_mut {
) {
let kind = AstType::TSConditionalType;
visitor.enter_node(kind);
visitor.enter_scope(ScopeFlags::empty(), &it.scope_id);
visitor.visit_ts_type(&mut it.check_type);
visitor.enter_scope(ScopeFlags::empty(), &it.scope_id);
visitor.visit_ts_type(&mut it.extends_type);
visitor.visit_ts_type(&mut it.true_type);
visitor.visit_ts_type(&mut it.false_type);
visitor.leave_scope();
visitor.visit_ts_type(&mut it.false_type);
visitor.leave_node(kind);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,45 +12,44 @@ SCOPES
{
"children": [
{
"children": [
"children": [],
"flags": "ScopeFlags(StrictMode)",
"id": 2,
"node": "TSConditionalType",
"symbols": [
{
"children": [],
"flags": "ScopeFlags(StrictMode)",
"id": 3,
"node": "TSConditionalType",
"symbols": [
"flags": "SymbolFlags(TypeParameter)",
"id": 2,
"name": "U",
"node": "TSTypeParameter(U)",
"references": [
{
"flags": "SymbolFlags(TypeParameter)",
"id": 3,
"flags": "ReferenceFlags(Type)",
"id": 2,
"name": "U",
"node": "TSTypeParameter(U)",
"references": [
{
"flags": "ReferenceFlags(Type)",
"id": 5,
"name": "U",
"node_id": 33
}
]
"node_id": 19
}
]
}
],
]
},
{
"children": [],
"flags": "ScopeFlags(StrictMode)",
"id": 2,
"id": 3,
"node": "TSConditionalType",
"symbols": [
{
"flags": "SymbolFlags(TypeParameter)",
"id": 2,
"id": 3,
"name": "U",
"node": "TSTypeParameter(U)",
"references": [
{
"flags": "ReferenceFlags(Type)",
"id": 2,
"id": 5,
"name": "U",
"node_id": 19
"node_id": 33
}
]
}
Expand Down
22 changes: 22 additions & 0 deletions crates/oxc_semantic/tests/integration/scopes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,25 @@ fn get_child_ids() {
let child_scope_ids = scopes.get_child_ids(child_scope_ids[0]);
assert!(child_scope_ids.is_empty());
}

#[test]
fn test_ts_conditional_types() {
SemanticTester::ts("type A<T> = T extends string ? T : false;")
.has_some_symbol("T")
.has_number_of_references(2)
.test();

// Conditional types create a new scope after check_type.
SemanticTester::ts(
"type S<A> = A extends (infer B extends number ? string : never) ? B : false;",
)
.has_some_symbol("B")
.has_number_of_references(1)
.test();

// Inferred type parameter is only available within true branch
SemanticTester::ts("type S<A> = A extends infer R ? never : R")
.has_some_symbol("R")
.has_number_of_references(0)
.test();
}
14 changes: 7 additions & 7 deletions crates/oxc_traverse/src/generated/walk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3964,13 +3964,6 @@ pub(crate) unsafe fn walk_ts_conditional_type<'a, Tr: Traverse<'a>>(
ctx: &mut TraverseCtx<'a>,
) {
traverser.enter_ts_conditional_type(&mut *node, ctx);
let previous_scope_id = ctx.current_scope_id();
ctx.set_current_scope_id(
(*((node as *mut u8).add(ancestor::OFFSET_TS_CONDITIONAL_TYPE_SCOPE_ID)
as *mut Cell<Option<ScopeId>>))
.get()
.unwrap(),
);
let pop_token = ctx.push_stack(Ancestor::TSConditionalTypeCheckType(
ancestor::TSConditionalTypeWithoutCheckType(node, PhantomData),
));
Expand All @@ -3979,6 +3972,13 @@ pub(crate) unsafe fn walk_ts_conditional_type<'a, Tr: Traverse<'a>>(
(node as *mut u8).add(ancestor::OFFSET_TS_CONDITIONAL_TYPE_CHECK_TYPE) as *mut TSType,
ctx,
);
let previous_scope_id = ctx.current_scope_id();
ctx.set_current_scope_id(
(*((node as *mut u8).add(ancestor::OFFSET_TS_CONDITIONAL_TYPE_SCOPE_ID)
as *mut Cell<Option<ScopeId>>))
.get()
.unwrap(),
);
ctx.retag_stack(AncestorType::TSConditionalTypeExtendsType);
walk_ts_type(
traverser,
Expand Down
12 changes: 6 additions & 6 deletions tasks/coverage/snapshots/semantic_typescript.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3897,13 +3897,13 @@ Bindings mismatch:
after transform: ScopeId(2): ["P", "attrs"]
rebuilt : ScopeId(1): ["attrs"]
Scope children mismatch:
after transform: ScopeId(2): [ScopeId(3)]
after transform: ScopeId(2): [ScopeId(3), ScopeId(5)]
rebuilt : ScopeId(1): []
Bindings mismatch:
after transform: ScopeId(6): ["P", "attrs"]
rebuilt : ScopeId(2): ["attrs"]
Scope children mismatch:
after transform: ScopeId(6): [ScopeId(7)]
after transform: ScopeId(6): [ScopeId(7), ScopeId(8)]
rebuilt : ScopeId(2): []
Bindings mismatch:
after transform: ScopeId(9): ["P", "attrs"]
Expand Down Expand Up @@ -8852,7 +8852,7 @@ Bindings mismatch:
after transform: ScopeId(3): ["D", "clientDef"]
rebuilt : ScopeId(1): ["clientDef"]
Scope children mismatch:
after transform: ScopeId(3): [ScopeId(4)]
after transform: ScopeId(3): [ScopeId(4), ScopeId(5)]
rebuilt : ScopeId(1): []
Unresolved references mismatch:
after transform: ["Record"]
Expand Down Expand Up @@ -17164,7 +17164,7 @@ Scope children mismatch:
after transform: ScopeId(8): [ScopeId(9), ScopeId(10)]
rebuilt : ScopeId(2): []
Symbol reference IDs mismatch for "state":
after transform: SymbolId(8): [ReferenceId(11), ReferenceId(12), ReferenceId(13), ReferenceId(15)]
after transform: SymbolId(9): [ReferenceId(11), ReferenceId(12), ReferenceId(13), ReferenceId(15)]
rebuilt : SymbolId(1): [ReferenceId(0), ReferenceId(1), ReferenceId(2)]
Unresolved references mismatch:
after transform: ["State", "true"]
Expand Down Expand Up @@ -52205,10 +52205,10 @@ Scope children mismatch:
after transform: ScopeId(0): [ScopeId(1), ScopeId(4), ScopeId(5), ScopeId(6), ScopeId(7), ScopeId(10), ScopeId(11), ScopeId(12), ScopeId(13), ScopeId(16), ScopeId(17), ScopeId(18), ScopeId(19), ScopeId(22), ScopeId(23), ScopeId(24), ScopeId(25), ScopeId(28), ScopeId(29), ScopeId(30), ScopeId(31), ScopeId(34), ScopeId(35), ScopeId(36), ScopeId(37), ScopeId(40), ScopeId(41), ScopeId(42), ScopeId(43), ScopeId(44), ScopeId(47), ScopeId(48), ScopeId(49), ScopeId(50), ScopeId(51), ScopeId(54), ScopeId(55), ScopeId(56), ScopeId(57), ScopeId(58), ScopeId(61), ScopeId(63), ScopeId(64), ScopeId(67), ScopeId(69), ScopeId(71), ScopeId(73), ScopeId(77), ScopeId(80), ScopeId(84), ScopeId(87), ScopeId(89), ScopeId(90), ScopeId(91), ScopeId(92), ScopeId(95), ScopeId(96), ScopeId(98), ScopeId(99), ScopeId(100), ScopeId(101), ScopeId(102), ScopeId(103), ScopeId(107), ScopeId(108), ScopeId(109), ScopeId(110), ScopeId(111)]
rebuilt : ScopeId(0): [ScopeId(1), ScopeId(2)]
Reference symbol mismatch for "x1":
after transform: SymbolId(126) "x1"
after transform: SymbolId(127) "x1"
rebuilt : <None>
Reference symbol mismatch for "x2":
after transform: SymbolId(132) "x2"
after transform: SymbolId(133) "x2"
rebuilt : <None>
Unresolved references mismatch:
after transform: ["Promise"]
Expand Down

0 comments on commit df22a40

Please sign in to comment.