Skip to content

Commit 9bcbca4

Browse files
committed
fix(41534): fix children circular references
1 parent 566faa7 commit 9bcbca4

6 files changed

Lines changed: 238 additions & 6 deletions

File tree

src/services/navigationBar.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,6 @@ namespace ts.NavigationBar {
490490
[AssignmentDeclarationKind.ThisProperty]: false,
491491
};
492492
function tryMergeEs5Class(a: NavigationBarNode, b: NavigationBarNode, bIndex: number, parent: NavigationBarNode): boolean | undefined {
493-
494493
function isPossibleConstructor(node: Node) {
495494
return isFunctionExpression(node) || isFunctionDeclaration(node) || isVariableDeclaration(node);
496495
}
@@ -506,10 +505,10 @@ namespace ts.NavigationBar {
506505
if ((isEs5ClassMember[bAssignmentDeclarationKind] && isEs5ClassMember[aAssignmentDeclarationKind]) // merge two class elements
507506
|| (isPossibleConstructor(a.node) && isEs5ClassMember[bAssignmentDeclarationKind]) // ctor function & member
508507
|| (isPossibleConstructor(b.node) && isEs5ClassMember[aAssignmentDeclarationKind]) // member & ctor function
509-
|| (isClassDeclaration(a.node) && isEs5ClassMember[bAssignmentDeclarationKind]) // class (generated) & member
508+
|| (isClassDeclaration(a.node) && isSynthesized(a.node) && isEs5ClassMember[bAssignmentDeclarationKind]) // class (generated) & member
510509
|| (isClassDeclaration(b.node) && isEs5ClassMember[aAssignmentDeclarationKind]) // member & class (generated)
511-
|| (isClassDeclaration(a.node) && isPossibleConstructor(b.node)) // class (generated) & ctor
512-
|| (isClassDeclaration(b.node) && isPossibleConstructor(a.node)) // ctor & class (generated)
510+
|| (isClassDeclaration(a.node) && isSynthesized(a.node) && isPossibleConstructor(b.node)) // class (generated) & ctor
511+
|| (isClassDeclaration(b.node) && isPossibleConstructor(a.node) && isSynthesized(a.node)) // ctor & class (generated)
513512
) {
514513

515514
let lastANode = a.additionalNodes && lastOrUndefined(a.additionalNodes) || a.node;
@@ -528,11 +527,11 @@ namespace ts.NavigationBar {
528527
const ctor = emptyNavigationBarNode(ctorNode);
529528
ctor.indent = a.indent + 1;
530529
ctor.children = a.node === ctorFunction ? a.children : b.children;
531-
a.children = a.node === ctorFunction ? concatenate([ctor], b.children || [b]) : concatenate(a.children || [a], [ctor]);
530+
a.children = a.node === ctorFunction ? concatenate([ctor], b.children || [b]) : concatenate(a.children || [{ ...a }], [ctor]);
532531
}
533532
else {
534533
if (a.children || b.children) {
535-
a.children = concatenate(a.children || [a], b.children || [b]);
534+
a.children = concatenate(a.children || [{ ...a }], b.children || [b]);
536535
if (a.children) {
537536
mergeChildren(a.children, a);
538537
sortChildren(a.children);
@@ -612,6 +611,10 @@ namespace ts.NavigationBar {
612611
}
613612
}
614613

614+
function isSynthesized(node: Node) {
615+
return !!(node.flags & NodeFlags.Synthesized);
616+
}
617+
615618
// We want to merge own children like `I` in in `module A { interface I {} } module A { interface I {} }`
616619
// We don't want to merge unrelated children like `m` in `const o = { a: { m() {} }, b: { m() {} } };`
617620
function isOwnChild(n: Node, parent: NavigationBarNode): boolean {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
////function Foo() {}
4+
////class Foo {}
5+
6+
verify.navigationTree({
7+
text: "<global>",
8+
kind: "script",
9+
childItems: [
10+
{
11+
text: "Foo",
12+
kind: "function"
13+
},
14+
{
15+
text: "Foo",
16+
kind: "class"
17+
}
18+
]
19+
});
20+
21+
verify.navigationBar([
22+
{
23+
text: "<global>",
24+
kind: "script",
25+
childItems: [
26+
{
27+
text: "Foo",
28+
kind: "function"
29+
},
30+
{
31+
text: "Foo",
32+
kind: "class"
33+
}
34+
]
35+
},
36+
{
37+
text: "Foo",
38+
kind: "function",
39+
indent: 1
40+
},
41+
{
42+
text: "Foo",
43+
kind: "class",
44+
indent: 1
45+
}
46+
]);
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
////class Foo {}
4+
////function Foo() {}
5+
6+
verify.navigationTree({
7+
text: "<global>",
8+
kind: "script",
9+
childItems: [
10+
{
11+
text: "Foo",
12+
kind: "function"
13+
},
14+
{
15+
text: "Foo",
16+
kind: "class"
17+
}
18+
]
19+
});
20+
21+
verify.navigationBar([
22+
{
23+
text: "<global>",
24+
kind: "script",
25+
childItems: [
26+
{
27+
text: "Foo",
28+
kind: "function"
29+
},
30+
{
31+
text: "Foo",
32+
kind: "class"
33+
}
34+
]
35+
},
36+
{
37+
text: "Foo",
38+
kind: "function",
39+
indent: 1
40+
},
41+
{
42+
text: "Foo",
43+
kind: "class",
44+
indent: 1
45+
}
46+
]);
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @allowJs: true
4+
// @filename: /foo.js
5+
////function Foo() {}
6+
////class Foo {}
7+
8+
verify.navigationTree({
9+
text: "<global>",
10+
kind: "script",
11+
childItems: [
12+
{
13+
text: "Foo",
14+
kind: "function"
15+
},
16+
{
17+
text: "Foo",
18+
kind: "class"
19+
}
20+
]
21+
});
22+
23+
verify.navigationBar([
24+
{
25+
text: "<global>",
26+
kind: "script",
27+
childItems: [
28+
{
29+
text: "Foo",
30+
kind: "function"
31+
},
32+
{
33+
text: "Foo",
34+
kind: "class"
35+
}
36+
]
37+
},
38+
{
39+
text: "Foo",
40+
kind: "function",
41+
indent: 1
42+
},
43+
{
44+
text: "Foo",
45+
kind: "class",
46+
indent: 1
47+
}
48+
]);
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @allowJs: true
4+
// @filename: /foo.js
5+
////class Foo {}
6+
////function Foo() {}
7+
8+
verify.navigationTree({
9+
text: "<global>",
10+
kind: "script",
11+
childItems: [
12+
{
13+
text: "Foo",
14+
kind: "function"
15+
},
16+
{
17+
text: "Foo",
18+
kind: "class"
19+
}
20+
]
21+
});
22+
23+
verify.navigationBar([
24+
{
25+
text: "<global>",
26+
kind: "script",
27+
childItems: [
28+
{
29+
text: "Foo",
30+
kind: "function"
31+
},
32+
{
33+
text: "Foo",
34+
kind: "class"
35+
}
36+
]
37+
},
38+
{
39+
text: "Foo",
40+
kind: "function",
41+
indent: 1
42+
},
43+
{
44+
text: "Foo",
45+
kind: "class",
46+
indent: 1
47+
}
48+
]);
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
////class Foo {}
4+
////let Foo = 1;
5+
6+
verify.navigationTree({
7+
text: "<global>",
8+
kind: "script",
9+
childItems: [
10+
{
11+
text: "Foo",
12+
kind: "let"
13+
},
14+
{
15+
text: "Foo",
16+
kind: "class"
17+
}
18+
]
19+
});
20+
21+
verify.navigationBar([
22+
{
23+
text: "<global>",
24+
kind: "script",
25+
childItems: [
26+
{
27+
text: "Foo",
28+
kind: "let"
29+
},
30+
{
31+
text: "Foo",
32+
kind: "class"
33+
}
34+
]
35+
},
36+
{
37+
text: "Foo",
38+
kind: "class",
39+
indent: 1
40+
}
41+
])

0 commit comments

Comments
 (0)