Skip to content

Commit

Permalink
Record flow analysis errors in NodeLinks
Browse files Browse the repository at this point in the history
  • Loading branch information
ahejlsberg committed Apr 15, 2019
1 parent 93b1c53 commit c01064e
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 12 deletions.
24 changes: 12 additions & 12 deletions src/compiler/checker.ts
Expand Up @@ -541,7 +541,7 @@ namespace ts {
let flowLoopCount = 0;
let sharedFlowCount = 0;
let flowNodeCount = -1;
let flowAnalysisDisabled = false;
let flowAnalysisErrors = false;

const emptyStringType = getLiteralType("");
const zeroType = getLiteralType(0);
Expand Down Expand Up @@ -15950,17 +15950,14 @@ 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_complex_for_control_flow_analysis));
function getContainingBlock(node: Node) {
return <Block | ModuleBlock | SourceFile>findAncestor(node, isFunctionOrModuleBlock);
}

function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType = declaredType, flowContainer?: Node, couldBeUninitialized?: boolean) {
let key: string | undefined;
let flowDepth = 0;
if (flowAnalysisDisabled) {
if (flowAnalysisErrors && getNodeLinks(getContainingBlock(reference)).flags & NodeCheckFlags.FlowAnalysisError) {
return errorType;
}
if (!reference.flowNode || !couldBeUninitialized && !(declaredType.flags & TypeFlags.Narrowable)) {
Expand All @@ -15984,9 +15981,14 @@ namespace ts {
// We have made 2000 recursive invocations or visited 500000 control flow nodes while analyzing
// the containing function or module body, the limit at which we consider the function or module
// body is too complex and disable further control flow analysis.
if (!flowAnalysisDisabled) {
flowAnalysisDisabled = true;
reportFlowControlError(reference);
const block = getContainingBlock(reference);
const nodeLinks = getNodeLinks(block);
if (!(nodeLinks.flags & NodeCheckFlags.FlowAnalysisError)) {
nodeLinks.flags |= NodeCheckFlags.FlowAnalysisError;
const sourceFile = getSourceFileOfNode(block);
const span = getSpanOfTokenAtPosition(sourceFile, block.statements.pos);
diagnostics.add(createFileDiagnostic(sourceFile, span.start, span.length, Diagnostics.The_containing_function_or_module_body_is_too_complex_for_control_flow_analysis));
flowAnalysisErrors = true;
}
return errorType;
}
Expand Down Expand Up @@ -26032,11 +26034,9 @@ namespace ts {
}
if (isFunctionOrModuleBlock(node)) {
const saveFlowNodeCount = flowNodeCount;
const saveFlowAnalysisDisabled = flowAnalysisDisabled;
flowNodeCount = 0;
forEach(node.statements, checkSourceElement);
flowNodeCount = saveFlowNodeCount;
flowAnalysisDisabled = saveFlowAnalysisDisabled;
}
else {
forEach(node.statements, checkSourceElement);
Expand Down
1 change: 1 addition & 0 deletions src/compiler/types.ts
Expand Up @@ -3855,6 +3855,7 @@ namespace ts {
AssignmentsMarked = 0x00800000, // Parameter assignments have been marked
ClassWithConstructorReference = 0x01000000, // Class that contains a binding to its constructor inside of the class body.
ConstructorReferenceInClass = 0x02000000, // Binding to a class constructor inside of the class's body.
FlowAnalysisError = 0x04000000, // Control flow analysis error in this block
}

/* @internal */
Expand Down

0 comments on commit c01064e

Please sign in to comment.