Use isReachableFlowNode to check for implicit return

This commit is contained in:
Anders Hejlsberg
2019-09-13 14:38:12 -07:00
parent 3749de6019
commit 3a89c8cc5c
3 changed files with 6 additions and 13 deletions

View File

@@ -569,7 +569,7 @@ namespace ts {
}
// We create a return control flow graph for IIFEs and constructors. For constructors
// we use the return control flow graph in strict property initialization checks.
currentReturnTarget = isIIFE || node.kind === SyntaxKind.Constructor ? createBranchLabel() : undefined;
currentReturnTarget = containerFlags & ContainerFlags.IsFunctionLike && nodeIsPresent((<FunctionLikeDeclaration>node).body) ? createBranchLabel() : undefined;
currentBreakTarget = undefined;
currentContinueTarget = undefined;
activeLabels = undefined;
@@ -589,9 +589,7 @@ namespace ts {
if (currentReturnTarget) {
addAntecedent(currentReturnTarget, currentFlow);
currentFlow = finishFlowLabel(currentReturnTarget);
if (node.kind === SyntaxKind.Constructor) {
(<ConstructorDeclaration>node).returnFlowNode = currentFlow;
}
(<FunctionLikeDeclaration>node).returnFlowNode = currentFlow;
}
if (!isIIFE) {
currentFlow = saveCurrentFlow;

View File

@@ -23803,15 +23803,10 @@ namespace ts {
return eachTypeContainedIn(mapType(type, getRegularTypeOfLiteralType), switchTypes);
}
function isNeverFunctionCall(expr: Expression) {
const signature = expr.kind === SyntaxKind.CallExpression && getEffectsSignature(<CallExpression>expr);
return !!(signature && getReturnTypeOfSignature(signature).flags & TypeFlags.Never);
}
function functionHasImplicitReturn(func: FunctionLikeDeclaration) {
return !!(func.flags & NodeFlags.HasImplicitReturn) && !some((<Block>func.body).statements, statement =>
statement.kind === SyntaxKind.SwitchStatement && isExhaustiveSwitchStatement(<SwitchStatement>statement) ||
statement.kind === SyntaxKind.ExpressionStatement && isNeverFunctionCall((<ExpressionStatement>statement).expression));
return !!(func.flags & NodeFlags.HasImplicitReturn &&
!some((<Block>func.body).statements, s => s.kind === SyntaxKind.SwitchStatement && isExhaustiveSwitchStatement(<SwitchStatement>s)) &&
!(func.returnFlowNode && !isReachableFlowNode(func.returnFlowNode)));
}
/** NOTE: Return value of `[]` means a different thing than `undefined`. `[]` means func returns `void`, `undefined` means it returns `never`. */

View File

@@ -1040,6 +1040,7 @@ namespace ts {
questionToken?: QuestionToken;
exclamationToken?: ExclamationToken;
body?: Block | Expression;
/* @internal */ returnFlowNode?: FlowNode;
}
export type FunctionLikeDeclaration =
@@ -1085,7 +1086,6 @@ namespace ts {
kind: SyntaxKind.Constructor;
parent: ClassLikeDeclaration;
body?: FunctionBody;
/* @internal */ returnFlowNode?: FlowNode;
}
/** For when we encounter a semicolon in a class declaration. ES6 allows these as class elements. */