Improved handing of evolving types in iteration statements

This commit is contained in:
Anders Hejlsberg
2016-04-16 15:11:34 -07:00
parent 1ed987152f
commit 921efec6b8
+37 -21
View File
@@ -180,6 +180,7 @@ namespace ts {
let jsxElementClassType: Type;
let deferredNodes: Node[];
let inFlowCheck = false;
const tupleTypes: Map<TupleType> = {};
const unionTypes: Map<UnionType> = {};
@@ -7528,7 +7529,11 @@ namespace ts {
function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType: Type) {
let key: string;
return reference.flowNode ? getTypeAtFlowNode(reference.flowNode) : declaredType;
const saveInFlowCheck = inFlowCheck;
inFlowCheck = true;
const result = reference.flowNode ? getTypeAtFlowNode(reference.flowNode) : declaredType;
inFlowCheck = saveInFlowCheck;
return result;
function getTypeAtFlowNode(flow: FlowNode): Type {
while (true) {
@@ -8537,7 +8542,7 @@ namespace ts {
const args = getEffectiveCallArguments(callTarget);
const argIndex = indexOf(args, arg);
if (argIndex >= 0) {
const signature = getResolvedSignature(callTarget);
const signature = getResolvedOrAnySignature(callTarget);
return getTypeAtPosition(signature, argIndex);
}
return undefined;
@@ -11071,6 +11076,20 @@ namespace ts {
return resolveCall(node, callSignatures, candidatesOutArray, headMessage);
}
function resolveSignature(node: CallLikeExpression, candidatesOutArray?: Signature[]): Signature {
switch (node.kind) {
case SyntaxKind.CallExpression:
return resolveCallExpression(<CallExpression>node, candidatesOutArray);
case SyntaxKind.NewExpression:
return resolveNewExpression(<NewExpression>node, candidatesOutArray);
case SyntaxKind.TaggedTemplateExpression:
return resolveTaggedTemplateExpression(<TaggedTemplateExpression>node, candidatesOutArray);
case SyntaxKind.Decorator:
return resolveDecorator(<Decorator>node, candidatesOutArray);
}
Debug.fail("Branch in 'resolveSignature' should be unreachable.");
}
// candidatesOutArray is passed by signature help in the language service, and collectCandidates
// must fill it up with the appropriate candidate signatures
function getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[]): Signature {
@@ -11079,26 +11098,23 @@ namespace ts {
// However, it is possible that either candidatesOutArray was not passed in the first time,
// or that a different candidatesOutArray was passed in. Therefore, we need to redo the work
// to correctly fill the candidatesOutArray.
if (!links.resolvedSignature || candidatesOutArray) {
links.resolvedSignature = anySignature;
if (node.kind === SyntaxKind.CallExpression) {
links.resolvedSignature = resolveCallExpression(<CallExpression>node, candidatesOutArray);
}
else if (node.kind === SyntaxKind.NewExpression) {
links.resolvedSignature = resolveNewExpression(<NewExpression>node, candidatesOutArray);
}
else if (node.kind === SyntaxKind.TaggedTemplateExpression) {
links.resolvedSignature = resolveTaggedTemplateExpression(<TaggedTemplateExpression>node, candidatesOutArray);
}
else if (node.kind === SyntaxKind.Decorator) {
links.resolvedSignature = resolveDecorator(<Decorator>node, candidatesOutArray);
}
else {
Debug.fail("Branch in 'getResolvedSignature' should be unreachable.");
}
const cached = links.resolvedSignature;
if (cached && cached !== anySignature && !candidatesOutArray) {
return cached;
}
return links.resolvedSignature;
links.resolvedSignature = anySignature;
const result = resolveSignature(node, candidatesOutArray);
// If signature resolution originated in control flow type analysis (for example to compute the
// assigned type in a flow assignment) we don't cache the result as it may be based on temporary
// types from the control flow analysis.
links.resolvedSignature = inFlowCheck ? cached : result;
return result;
}
function getResolvedOrAnySignature(node: CallLikeExpression) {
// If we're already in the process of resolving the given signature, don't resolve again as
// that could cause infinite recursion. Instead, return anySignature.
return getNodeLinks(node).resolvedSignature === anySignature ? anySignature : getResolvedSignature(node);
}
function getInferredClassType(symbol: Symbol) {