Skip to content

Commit 7919c9a

Browse files
Add CFA regression test for while loop with continue statements (#1325)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com> Co-authored-by: Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com>
1 parent 2fe47a5 commit 7919c9a

File tree

3 files changed

+260
-0
lines changed

3 files changed

+260
-0
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
//// [tests/cases/compiler/circularControlFlowNarrowingWithCurrentElement01.ts] ////
2+
3+
=== circularControlFlowNarrowingWithCurrentElement01.ts ===
4+
class A {
5+
>A : Symbol(A, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 0, 0))
6+
7+
next: A | null = null;
8+
>next : Symbol(next, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 0, 9))
9+
>A : Symbol(A, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 0, 0))
10+
11+
constructor(readonly children: (A | null)[]) {}
12+
>children : Symbol(children, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 3, 14))
13+
>A : Symbol(A, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 0, 0))
14+
}
15+
16+
function getNodes(): A[] {
17+
>getNodes : Symbol(getNodes, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 4, 1))
18+
>A : Symbol(A, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 0, 0))
19+
20+
const out: A[] = [];
21+
>out : Symbol(out, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 7, 7))
22+
>A : Symbol(A, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 0, 0))
23+
24+
let current: A | null = new A([]);
25+
>current : Symbol(current, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 9, 5))
26+
>A : Symbol(A, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 0, 0))
27+
>A : Symbol(A, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 0, 0))
28+
29+
while (current !== null) {
30+
>current : Symbol(current, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 9, 5))
31+
32+
let firstChild = null;
33+
>firstChild : Symbol(firstChild, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 12, 7))
34+
35+
if (out.length) {
36+
>out.length : Symbol(length, Decl(lib.es5.d.ts, --, --))
37+
>out : Symbol(out, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 7, 7))
38+
>length : Symbol(length, Decl(lib.es5.d.ts, --, --))
39+
40+
current = current.next;
41+
>current : Symbol(current, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 9, 5))
42+
>current.next : Symbol(next, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 0, 9))
43+
>current : Symbol(current, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 9, 5))
44+
>next : Symbol(next, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 0, 9))
45+
46+
continue;
47+
}
48+
49+
for (let i = 0; i < current.children.length; i++) {
50+
>i : Symbol(i, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 19, 12))
51+
>i : Symbol(i, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 19, 12))
52+
>current.children.length : Symbol(length, Decl(lib.es5.d.ts, --, --))
53+
>current.children : Symbol(children, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 3, 14))
54+
>current : Symbol(current, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 9, 5))
55+
>children : Symbol(children, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 3, 14))
56+
>length : Symbol(length, Decl(lib.es5.d.ts, --, --))
57+
>i : Symbol(i, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 19, 12))
58+
59+
const child = current.children[i];
60+
>child : Symbol(child, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 20, 11))
61+
>current.children : Symbol(children, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 3, 14))
62+
>current : Symbol(current, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 9, 5))
63+
>children : Symbol(children, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 3, 14))
64+
>i : Symbol(i, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 19, 12))
65+
66+
if (child) {
67+
>child : Symbol(child, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 20, 11))
68+
69+
if (!firstChild) {
70+
>firstChild : Symbol(firstChild, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 12, 7))
71+
72+
firstChild = child;
73+
>firstChild : Symbol(firstChild, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 12, 7))
74+
>child : Symbol(child, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 20, 11))
75+
76+
firstChild.next = current.next;
77+
>firstChild.next : Symbol(next, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 0, 9))
78+
>firstChild : Symbol(firstChild, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 12, 7))
79+
>next : Symbol(next, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 0, 9))
80+
>current.next : Symbol(next, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 0, 9))
81+
>current : Symbol(current, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 9, 5))
82+
>next : Symbol(next, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 0, 9))
83+
}
84+
85+
child.next = current.next;
86+
>child.next : Symbol(next, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 0, 9))
87+
>child : Symbol(child, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 20, 11))
88+
>next : Symbol(next, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 0, 9))
89+
>current.next : Symbol(next, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 0, 9))
90+
>current : Symbol(current, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 9, 5))
91+
>next : Symbol(next, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 0, 9))
92+
}
93+
}
94+
95+
current = firstChild || current.next;
96+
>current : Symbol(current, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 9, 5))
97+
>firstChild : Symbol(firstChild, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 12, 7))
98+
>current.next : Symbol(next, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 0, 9))
99+
>current : Symbol(current, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 9, 5))
100+
>next : Symbol(next, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 0, 9))
101+
}
102+
103+
return out;
104+
>out : Symbol(out, Decl(circularControlFlowNarrowingWithCurrentElement01.ts, 7, 7))
105+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
//// [tests/cases/compiler/circularControlFlowNarrowingWithCurrentElement01.ts] ////
2+
3+
=== circularControlFlowNarrowingWithCurrentElement01.ts ===
4+
class A {
5+
>A : A
6+
7+
next: A | null = null;
8+
>next : A | null
9+
10+
constructor(readonly children: (A | null)[]) {}
11+
>children : (A | null)[]
12+
}
13+
14+
function getNodes(): A[] {
15+
>getNodes : () => A[]
16+
17+
const out: A[] = [];
18+
>out : A[]
19+
>[] : never[]
20+
21+
let current: A | null = new A([]);
22+
>current : A | null
23+
>new A([]) : A
24+
>A : typeof A
25+
>[] : never[]
26+
27+
while (current !== null) {
28+
>current !== null : boolean
29+
>current : A | null
30+
31+
let firstChild = null;
32+
>firstChild : any
33+
34+
if (out.length) {
35+
>out.length : number
36+
>out : A[]
37+
>length : number
38+
39+
current = current.next;
40+
>current = current.next : A | null
41+
>current : A | null
42+
>current.next : A | null
43+
>current : A
44+
>next : A | null
45+
46+
continue;
47+
}
48+
49+
for (let i = 0; i < current.children.length; i++) {
50+
>i : number
51+
>0 : 0
52+
>i < current.children.length : boolean
53+
>i : number
54+
>current.children.length : number
55+
>current.children : (A | null)[]
56+
>current : A
57+
>children : (A | null)[]
58+
>length : number
59+
>i++ : number
60+
>i : number
61+
62+
const child = current.children[i];
63+
>child : A | null
64+
>current.children[i] : A | null
65+
>current.children : (A | null)[]
66+
>current : A
67+
>children : (A | null)[]
68+
>i : number
69+
70+
if (child) {
71+
>child : A | null
72+
73+
if (!firstChild) {
74+
>!firstChild : boolean
75+
>firstChild : A | null
76+
77+
firstChild = child;
78+
>firstChild = child : A
79+
>firstChild : any
80+
>child : A
81+
82+
firstChild.next = current.next;
83+
>firstChild.next = current.next : A | null
84+
>firstChild.next : A | null
85+
>firstChild : A
86+
>next : A | null
87+
>current.next : A | null
88+
>current : A
89+
>next : A | null
90+
}
91+
92+
child.next = current.next;
93+
>child.next = current.next : A | null
94+
>child.next : A | null
95+
>child : A
96+
>next : A | null
97+
>current.next : A | null
98+
>current : A
99+
>next : A | null
100+
}
101+
}
102+
103+
current = firstChild || current.next;
104+
>current = firstChild || current.next : A | null
105+
>current : A | null
106+
>firstChild || current.next : A | null
107+
>firstChild : A | null
108+
>current.next : A | null
109+
>current : A
110+
>next : A | null
111+
}
112+
113+
return out;
114+
>out : A[]
115+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// @strict: true
2+
// @noEmit: true
3+
4+
class A {
5+
next: A | null = null;
6+
7+
constructor(readonly children: (A | null)[]) {}
8+
}
9+
10+
function getNodes(): A[] {
11+
const out: A[] = [];
12+
13+
let current: A | null = new A([]);
14+
15+
while (current !== null) {
16+
let firstChild = null;
17+
18+
if (out.length) {
19+
current = current.next;
20+
continue;
21+
}
22+
23+
for (let i = 0; i < current.children.length; i++) {
24+
const child = current.children[i];
25+
26+
if (child) {
27+
if (!firstChild) {
28+
firstChild = child;
29+
firstChild.next = current.next;
30+
}
31+
32+
child.next = current.next;
33+
}
34+
}
35+
36+
current = firstChild || current.next;
37+
}
38+
39+
return out;
40+
}

0 commit comments

Comments
 (0)