Skip to content

Commit 834ee2a

Browse files
committed
fix(semantic): TSConditionalType scope enter/exit locations (#6351)
Fixes the same problem as #6270, but uses `#[scope(enter_before)]` and `#[scope(exit_after)]` to correct scope entry/exit locations.
1 parent d9718ad commit 834ee2a

File tree

7 files changed

+63
-40
lines changed

7 files changed

+63
-40
lines changed

crates/oxc_ast/src/ast/ts.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,10 +347,12 @@ pub struct TSConditionalType<'a> {
347347
/// The type before `extends` in the test expression.
348348
pub check_type: TSType<'a>,
349349
/// The type `check_type` is being tested against.
350+
#[scope(enter_before)]
350351
pub extends_type: TSType<'a>,
351352
/// The type evaluated to if the test is true.
352353
pub true_type: TSType<'a>,
353354
/// The type evaluated to if the test is false.
355+
#[scope(exit_before)]
354356
pub false_type: TSType<'a>,
355357
#[serde(skip)]
356358
#[clone_in(default)]

crates/oxc_ast/src/generated/visit.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1913,12 +1913,12 @@ pub mod walk {
19131913
pub fn walk_ts_conditional_type<'a, V: Visit<'a>>(visitor: &mut V, it: &TSConditionalType<'a>) {
19141914
let kind = AstKind::TSConditionalType(visitor.alloc(it));
19151915
visitor.enter_node(kind);
1916-
visitor.enter_scope(ScopeFlags::empty(), &it.scope_id);
19171916
visitor.visit_ts_type(&it.check_type);
1917+
visitor.enter_scope(ScopeFlags::empty(), &it.scope_id);
19181918
visitor.visit_ts_type(&it.extends_type);
19191919
visitor.visit_ts_type(&it.true_type);
1920-
visitor.visit_ts_type(&it.false_type);
19211920
visitor.leave_scope();
1921+
visitor.visit_ts_type(&it.false_type);
19221922
visitor.leave_node(kind);
19231923
}
19241924

crates/oxc_ast/src/generated/visit_mut.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1956,12 +1956,12 @@ pub mod walk_mut {
19561956
) {
19571957
let kind = AstType::TSConditionalType;
19581958
visitor.enter_node(kind);
1959-
visitor.enter_scope(ScopeFlags::empty(), &it.scope_id);
19601959
visitor.visit_ts_type(&mut it.check_type);
1960+
visitor.enter_scope(ScopeFlags::empty(), &it.scope_id);
19611961
visitor.visit_ts_type(&mut it.extends_type);
19621962
visitor.visit_ts_type(&mut it.true_type);
1963-
visitor.visit_ts_type(&mut it.false_type);
19641963
visitor.leave_scope();
1964+
visitor.visit_ts_type(&mut it.false_type);
19651965
visitor.leave_node(kind);
19661966
}
19671967

crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional-nested.snap

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,45 +12,44 @@ SCOPES
1212
{
1313
"children": [
1414
{
15-
"children": [
15+
"children": [],
16+
"flags": "ScopeFlags(StrictMode)",
17+
"id": 2,
18+
"node": "TSConditionalType",
19+
"symbols": [
1620
{
17-
"children": [],
18-
"flags": "ScopeFlags(StrictMode)",
19-
"id": 3,
20-
"node": "TSConditionalType",
21-
"symbols": [
21+
"flags": "SymbolFlags(TypeParameter)",
22+
"id": 2,
23+
"name": "U",
24+
"node": "TSTypeParameter(U)",
25+
"references": [
2226
{
23-
"flags": "SymbolFlags(TypeParameter)",
24-
"id": 3,
27+
"flags": "ReferenceFlags(Type)",
28+
"id": 2,
2529
"name": "U",
26-
"node": "TSTypeParameter(U)",
27-
"references": [
28-
{
29-
"flags": "ReferenceFlags(Type)",
30-
"id": 5,
31-
"name": "U",
32-
"node_id": 33
33-
}
34-
]
30+
"node_id": 19
3531
}
3632
]
3733
}
38-
],
34+
]
35+
},
36+
{
37+
"children": [],
3938
"flags": "ScopeFlags(StrictMode)",
40-
"id": 2,
39+
"id": 3,
4140
"node": "TSConditionalType",
4241
"symbols": [
4342
{
4443
"flags": "SymbolFlags(TypeParameter)",
45-
"id": 2,
44+
"id": 3,
4645
"name": "U",
4746
"node": "TSTypeParameter(U)",
4847
"references": [
4948
{
5049
"flags": "ReferenceFlags(Type)",
51-
"id": 2,
50+
"id": 5,
5251
"name": "U",
53-
"node_id": 19
52+
"node_id": 33
5453
}
5554
]
5655
}

crates/oxc_semantic/tests/integration/scopes.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,3 +239,25 @@ fn get_child_ids() {
239239
let child_scope_ids = scopes.get_child_ids(child_scope_ids[0]);
240240
assert!(child_scope_ids.is_empty());
241241
}
242+
243+
#[test]
244+
fn test_ts_conditional_types() {
245+
SemanticTester::ts("type A<T> = T extends string ? T : false;")
246+
.has_some_symbol("T")
247+
.has_number_of_references(2)
248+
.test();
249+
250+
// Conditional types create a new scope after check_type.
251+
SemanticTester::ts(
252+
"type S<A> = A extends (infer B extends number ? string : never) ? B : false;",
253+
)
254+
.has_some_symbol("B")
255+
.has_number_of_references(1)
256+
.test();
257+
258+
// Inferred type parameter is only available within true branch
259+
SemanticTester::ts("type S<A> = A extends infer R ? never : R")
260+
.has_some_symbol("R")
261+
.has_number_of_references(0)
262+
.test();
263+
}

crates/oxc_traverse/src/generated/walk.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3964,13 +3964,6 @@ pub(crate) unsafe fn walk_ts_conditional_type<'a, Tr: Traverse<'a>>(
39643964
ctx: &mut TraverseCtx<'a>,
39653965
) {
39663966
traverser.enter_ts_conditional_type(&mut *node, ctx);
3967-
let previous_scope_id = ctx.current_scope_id();
3968-
ctx.set_current_scope_id(
3969-
(*((node as *mut u8).add(ancestor::OFFSET_TS_CONDITIONAL_TYPE_SCOPE_ID)
3970-
as *mut Cell<Option<ScopeId>>))
3971-
.get()
3972-
.unwrap(),
3973-
);
39743967
let pop_token = ctx.push_stack(Ancestor::TSConditionalTypeCheckType(
39753968
ancestor::TSConditionalTypeWithoutCheckType(node, PhantomData),
39763969
));
@@ -3979,6 +3972,13 @@ pub(crate) unsafe fn walk_ts_conditional_type<'a, Tr: Traverse<'a>>(
39793972
(node as *mut u8).add(ancestor::OFFSET_TS_CONDITIONAL_TYPE_CHECK_TYPE) as *mut TSType,
39803973
ctx,
39813974
);
3975+
let previous_scope_id = ctx.current_scope_id();
3976+
ctx.set_current_scope_id(
3977+
(*((node as *mut u8).add(ancestor::OFFSET_TS_CONDITIONAL_TYPE_SCOPE_ID)
3978+
as *mut Cell<Option<ScopeId>>))
3979+
.get()
3980+
.unwrap(),
3981+
);
39823982
ctx.retag_stack(AncestorType::TSConditionalTypeExtendsType);
39833983
walk_ts_type(
39843984
traverser,
@@ -3991,14 +3991,14 @@ pub(crate) unsafe fn walk_ts_conditional_type<'a, Tr: Traverse<'a>>(
39913991
(node as *mut u8).add(ancestor::OFFSET_TS_CONDITIONAL_TYPE_TRUE_TYPE) as *mut TSType,
39923992
ctx,
39933993
);
3994+
ctx.set_current_scope_id(previous_scope_id);
39943995
ctx.retag_stack(AncestorType::TSConditionalTypeFalseType);
39953996
walk_ts_type(
39963997
traverser,
39973998
(node as *mut u8).add(ancestor::OFFSET_TS_CONDITIONAL_TYPE_FALSE_TYPE) as *mut TSType,
39983999
ctx,
39994000
);
40004001
ctx.pop_stack(pop_token);
4001-
ctx.set_current_scope_id(previous_scope_id);
40024002
traverser.exit_ts_conditional_type(&mut *node, ctx);
40034003
}
40044004

tasks/coverage/snapshots/semantic_typescript.snap

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3897,13 +3897,13 @@ Bindings mismatch:
38973897
after transform: ScopeId(2): ["P", "attrs"]
38983898
rebuilt : ScopeId(1): ["attrs"]
38993899
Scope children mismatch:
3900-
after transform: ScopeId(2): [ScopeId(3)]
3900+
after transform: ScopeId(2): [ScopeId(3), ScopeId(5)]
39013901
rebuilt : ScopeId(1): []
39023902
Bindings mismatch:
39033903
after transform: ScopeId(6): ["P", "attrs"]
39043904
rebuilt : ScopeId(2): ["attrs"]
39053905
Scope children mismatch:
3906-
after transform: ScopeId(6): [ScopeId(7)]
3906+
after transform: ScopeId(6): [ScopeId(7), ScopeId(8)]
39073907
rebuilt : ScopeId(2): []
39083908
Bindings mismatch:
39093909
after transform: ScopeId(9): ["P", "attrs"]
@@ -8852,7 +8852,7 @@ Bindings mismatch:
88528852
after transform: ScopeId(3): ["D", "clientDef"]
88538853
rebuilt : ScopeId(1): ["clientDef"]
88548854
Scope children mismatch:
8855-
after transform: ScopeId(3): [ScopeId(4)]
8855+
after transform: ScopeId(3): [ScopeId(4), ScopeId(5)]
88568856
rebuilt : ScopeId(1): []
88578857
Unresolved references mismatch:
88588858
after transform: ["Record"]
@@ -17164,7 +17164,7 @@ Scope children mismatch:
1716417164
after transform: ScopeId(8): [ScopeId(9), ScopeId(10)]
1716517165
rebuilt : ScopeId(2): []
1716617166
Symbol reference IDs mismatch for "state":
17167-
after transform: SymbolId(8): [ReferenceId(11), ReferenceId(12), ReferenceId(13), ReferenceId(15)]
17167+
after transform: SymbolId(9): [ReferenceId(11), ReferenceId(12), ReferenceId(13), ReferenceId(15)]
1716817168
rebuilt : SymbolId(1): [ReferenceId(0), ReferenceId(1), ReferenceId(2)]
1716917169
Unresolved references mismatch:
1717017170
after transform: ["State", "true"]
@@ -52205,10 +52205,10 @@ Scope children mismatch:
5220552205
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)]
5220652206
rebuilt : ScopeId(0): [ScopeId(1), ScopeId(2)]
5220752207
Reference symbol mismatch for "x1":
52208-
after transform: SymbolId(126) "x1"
52208+
after transform: SymbolId(127) "x1"
5220952209
rebuilt : <None>
5221052210
Reference symbol mismatch for "x2":
52211-
after transform: SymbolId(132) "x2"
52211+
after transform: SymbolId(133) "x2"
5221252212
rebuilt : <None>
5221352213
Unresolved references mismatch:
5221452214
after transform: ["Promise"]

0 commit comments

Comments
 (0)