Merge pull request #41543 from a-tarasyuk/fix/41534

fix(41534): Maximum call stack error while computing document symbol file
This commit is contained in:
Armando Aguirre 2020-12-01 18:03:11 -08:00 committed by GitHub
commit fd50f1e3c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 238 additions and 6 deletions

View File

@ -490,7 +490,6 @@ namespace ts.NavigationBar {
[AssignmentDeclarationKind.ThisProperty]: false,
};
function tryMergeEs5Class(a: NavigationBarNode, b: NavigationBarNode, bIndex: number, parent: NavigationBarNode): boolean | undefined {
function isPossibleConstructor(node: Node) {
return isFunctionExpression(node) || isFunctionDeclaration(node) || isVariableDeclaration(node);
}
@ -506,10 +505,10 @@ namespace ts.NavigationBar {
if ((isEs5ClassMember[bAssignmentDeclarationKind] && isEs5ClassMember[aAssignmentDeclarationKind]) // merge two class elements
|| (isPossibleConstructor(a.node) && isEs5ClassMember[bAssignmentDeclarationKind]) // ctor function & member
|| (isPossibleConstructor(b.node) && isEs5ClassMember[aAssignmentDeclarationKind]) // member & ctor function
|| (isClassDeclaration(a.node) && isEs5ClassMember[bAssignmentDeclarationKind]) // class (generated) & member
|| (isClassDeclaration(a.node) && isSynthesized(a.node) && isEs5ClassMember[bAssignmentDeclarationKind]) // class (generated) & member
|| (isClassDeclaration(b.node) && isEs5ClassMember[aAssignmentDeclarationKind]) // member & class (generated)
|| (isClassDeclaration(a.node) && isPossibleConstructor(b.node)) // class (generated) & ctor
|| (isClassDeclaration(b.node) && isPossibleConstructor(a.node)) // ctor & class (generated)
|| (isClassDeclaration(a.node) && isSynthesized(a.node) && isPossibleConstructor(b.node)) // class (generated) & ctor
|| (isClassDeclaration(b.node) && isPossibleConstructor(a.node) && isSynthesized(a.node)) // ctor & class (generated)
) {
let lastANode = a.additionalNodes && lastOrUndefined(a.additionalNodes) || a.node;
@ -528,11 +527,11 @@ namespace ts.NavigationBar {
const ctor = emptyNavigationBarNode(ctorNode);
ctor.indent = a.indent + 1;
ctor.children = a.node === ctorFunction ? a.children : b.children;
a.children = a.node === ctorFunction ? concatenate([ctor], b.children || [b]) : concatenate(a.children || [a], [ctor]);
a.children = a.node === ctorFunction ? concatenate([ctor], b.children || [b]) : concatenate(a.children || [{ ...a }], [ctor]);
}
else {
if (a.children || b.children) {
a.children = concatenate(a.children || [a], b.children || [b]);
a.children = concatenate(a.children || [{ ...a }], b.children || [b]);
if (a.children) {
mergeChildren(a.children, a);
sortChildren(a.children);
@ -612,6 +611,10 @@ namespace ts.NavigationBar {
}
}
function isSynthesized(node: Node) {
return !!(node.flags & NodeFlags.Synthesized);
}
// We want to merge own children like `I` in in `module A { interface I {} } module A { interface I {} }`
// We don't want to merge unrelated children like `m` in `const o = { a: { m() {} }, b: { m() {} } };`
function isOwnChild(n: Node, parent: NavigationBarNode): boolean {

View File

@ -0,0 +1,46 @@
/// <reference path="fourslash.ts" />
////function Foo() {}
////class Foo {}
verify.navigationTree({
text: "<global>",
kind: "script",
childItems: [
{
text: "Foo",
kind: "function"
},
{
text: "Foo",
kind: "class"
}
]
});
verify.navigationBar([
{
text: "<global>",
kind: "script",
childItems: [
{
text: "Foo",
kind: "function"
},
{
text: "Foo",
kind: "class"
}
]
},
{
text: "Foo",
kind: "function",
indent: 1
},
{
text: "Foo",
kind: "class",
indent: 1
}
]);

View File

@ -0,0 +1,46 @@
/// <reference path="fourslash.ts" />
////class Foo {}
////function Foo() {}
verify.navigationTree({
text: "<global>",
kind: "script",
childItems: [
{
text: "Foo",
kind: "function"
},
{
text: "Foo",
kind: "class"
}
]
});
verify.navigationBar([
{
text: "<global>",
kind: "script",
childItems: [
{
text: "Foo",
kind: "function"
},
{
text: "Foo",
kind: "class"
}
]
},
{
text: "Foo",
kind: "function",
indent: 1
},
{
text: "Foo",
kind: "class",
indent: 1
}
]);

View File

@ -0,0 +1,48 @@
/// <reference path="fourslash.ts" />
// @allowJs: true
// @filename: /foo.js
////function Foo() {}
////class Foo {}
verify.navigationTree({
text: "<global>",
kind: "script",
childItems: [
{
text: "Foo",
kind: "function"
},
{
text: "Foo",
kind: "class"
}
]
});
verify.navigationBar([
{
text: "<global>",
kind: "script",
childItems: [
{
text: "Foo",
kind: "function"
},
{
text: "Foo",
kind: "class"
}
]
},
{
text: "Foo",
kind: "function",
indent: 1
},
{
text: "Foo",
kind: "class",
indent: 1
}
]);

View File

@ -0,0 +1,48 @@
/// <reference path="fourslash.ts" />
// @allowJs: true
// @filename: /foo.js
////class Foo {}
////function Foo() {}
verify.navigationTree({
text: "<global>",
kind: "script",
childItems: [
{
text: "Foo",
kind: "function"
},
{
text: "Foo",
kind: "class"
}
]
});
verify.navigationBar([
{
text: "<global>",
kind: "script",
childItems: [
{
text: "Foo",
kind: "function"
},
{
text: "Foo",
kind: "class"
}
]
},
{
text: "Foo",
kind: "function",
indent: 1
},
{
text: "Foo",
kind: "class",
indent: 1
}
]);

View File

@ -0,0 +1,41 @@
/// <reference path="fourslash.ts" />
////class Foo {}
////let Foo = 1;
verify.navigationTree({
text: "<global>",
kind: "script",
childItems: [
{
text: "Foo",
kind: "let"
},
{
text: "Foo",
kind: "class"
}
]
});
verify.navigationBar([
{
text: "<global>",
kind: "script",
childItems: [
{
text: "Foo",
kind: "let"
},
{
text: "Foo",
kind: "class"
}
]
},
{
text: "Foo",
kind: "class",
indent: 1
}
])