mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Improved handing of evolving types in iteration statements
This commit is contained in:
+37
-21
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user