Report error on first token of excessively large function or module body

This commit is contained in:
Anders Hejlsberg 2017-09-08 06:35:14 -07:00
parent 4f43ae207a
commit 9eecf8ca56
3 changed files with 19 additions and 9 deletions

View file

@ -11486,6 +11486,13 @@ namespace ts {
return false;
}
function reportFlowControlError(node: Node) {
const block = <Block | ModuleBlock | SourceFile>findAncestor(node, isFunctionOrModuleBlock);
const sourceFile = getSourceFileOfNode(node);
const span = getSpanOfTokenAtPosition(sourceFile, block.statements.pos);
diagnostics.add(createFileDiagnostic(sourceFile, span.start, span.length, Diagnostics.The_containing_function_or_module_body_is_too_large_for_control_flow_analysis));
}
function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType = declaredType, flowContainer?: Node, couldBeUninitialized?: boolean) {
let key: string;
let flowLength = 0;
@ -11509,15 +11516,15 @@ namespace ts {
return resultType;
function getTypeAtFlowNode(flow: FlowNode): FlowType {
const saveFlowLength = flowLength;
flowLength++;
while (true) {
flowLength++;
if (flowLength === 5000) {
// The length of this particular control flow path is 5000 nodes or more. Rather than spending an
// excessive amount of time and possibly overflowing the call stack, we report an error and disable
// further control flow analysis in the containing function or module body.
if (flowLength >= 5000) {
// We have visited as many as 5000 nodes through as many as 2500 recursive invocations. Rather than
// spending an excessive amount of time and possibly overflowing the call stack, we report an error
// and disable further control flow analysis in the containing function or module body.
flowAnalysisDisabled = true;
error(reference, Diagnostics.The_body_of_the_containing_function_or_module_is_too_large_for_control_flow_analysis);
reportFlowControlError(reference);
return unknownType;
}
const flags = flow.flags;
@ -11527,7 +11534,6 @@ namespace ts {
// antecedent of more than one node.
for (let i = visitedFlowStart; i < visitedFlowCount; i++) {
if (visitedFlowNodes[i] === flow) {
flowLength = saveFlowLength;
return visitedFlowTypes[i];
}
}
@ -11595,7 +11601,6 @@ namespace ts {
visitedFlowTypes[visitedFlowCount] = type;
visitedFlowCount++;
}
flowLength = saveFlowLength;
return type;
}
}

View file

@ -1920,7 +1920,7 @@
"category": "Error",
"code": 2562
},
"The body of the containing function or module is too large for control flow analysis.": {
"The containing function or module body is too large for control flow analysis.": {
"category": "Error",
"code": 2563
},

View file

@ -4790,6 +4790,11 @@ namespace ts {
return false;
}
/* @internal */
export function isFunctionOrModuleBlock(node: Node): boolean {
return isSourceFile(node) || isModuleBlock(node) || isBlock(node) && isFunctionLike(node.parent);
}
// Classes
export function isClassElement(node: Node): node is ClassElement {
const kind = node.kind;