Clean up pushTypeResolution
This commit is contained in:
parent
c0b3835b19
commit
3b78377cf0
2 changed files with 53 additions and 38 deletions
|
@ -159,9 +159,9 @@ namespace ts {
|
|||
let emitAwaiter = false;
|
||||
let emitGenerator = false;
|
||||
|
||||
let resolutionTargets: Object[] = [];
|
||||
let resolutionTargets: TypeSystemEntity[] = [];
|
||||
let resolutionResults: boolean[] = [];
|
||||
let resolutionKinds: TypeSystemObjectKind[] = [];
|
||||
let resolutionPropertyNames: TypeSystemPropertyName[] = [];
|
||||
|
||||
let mergedSymbols: Symbol[] = [];
|
||||
let symbolLinks: SymbolLinks[] = [];
|
||||
|
@ -202,11 +202,11 @@ namespace ts {
|
|||
let assignableRelation: Map<RelationComparisonResult> = {};
|
||||
let identityRelation: Map<RelationComparisonResult> = {};
|
||||
|
||||
enum TypeSystemObjectKind {
|
||||
Symbol,
|
||||
enum TypeSystemPropertyName {
|
||||
Type,
|
||||
SymbolLinks,
|
||||
Signature
|
||||
ResolvedBaseConstructorType,
|
||||
DeclaredType,
|
||||
ResolvedReturnType
|
||||
}
|
||||
|
||||
initializeTypeChecker();
|
||||
|
@ -2185,45 +2185,58 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
// Push an entry on the type resolution stack. If an entry with the given target is not already on the stack,
|
||||
// a new entry with that target and an associated result value of true is pushed on the stack, and the value
|
||||
// true is returned. Otherwise, a circularity has occurred and the result values of the existing entry and
|
||||
// all entries pushed after it are changed to false, and the value false is returned. The target object provides
|
||||
// a unique identity for a particular type resolution result: Symbol instances are used to track resolution of
|
||||
// SymbolLinks.type, SymbolLinks instances are used to track resolution of SymbolLinks.declaredType, and
|
||||
// Signature instances are used to track resolution of Signature.resolvedReturnType.
|
||||
function pushTypeResolution(target: Object, flags: TypeSystemObjectKind): boolean {
|
||||
let count = resolutionTargets.length;
|
||||
let i = count - 1;
|
||||
let foundGoodType = false;
|
||||
while (i >= 0 && !(foundGoodType = !!hasType(resolutionTargets[i], resolutionKinds[i])) && resolutionTargets[i] !== target) {
|
||||
i--;
|
||||
}
|
||||
if (i >= 0 && !foundGoodType) {
|
||||
do {
|
||||
resolutionResults[i++] = false;
|
||||
/**
|
||||
* Push an entry on the type resolution stack. If an entry with the given target and the given property name
|
||||
* is already on the stack, and no entries in between already have a type, then a circularity has occurred.
|
||||
* In this case, the result values of the existing entry and all entries pushed after it are changed to false,
|
||||
* and the value false is returned. Otherwise, the new entry is just pushed onto the stack, and true is returned.
|
||||
* In order to see if the same query has already been done before, the target object and the propertyName both
|
||||
* must match the one passed in.
|
||||
*
|
||||
* @param target The symbol, type, or signature whose type is being queried
|
||||
* @param propertyName The property name that should be used to query the target for its type
|
||||
*/
|
||||
function pushTypeResolution(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): boolean {
|
||||
let resolutionCycleStartIndex = findResolutionCycleStartIndex(target, propertyName);
|
||||
if (resolutionCycleStartIndex >= 0) {
|
||||
// A cycle was found
|
||||
let { length } = resolutionTargets;
|
||||
for (let i = resolutionCycleStartIndex; i < length; i++) {
|
||||
resolutionResults[i] = false;
|
||||
}
|
||||
while (i < count);
|
||||
return false;
|
||||
}
|
||||
resolutionTargets.push(target);
|
||||
resolutionResults.push(true);
|
||||
resolutionKinds.push(flags);
|
||||
resolutionPropertyNames.push(propertyName);
|
||||
return true;
|
||||
}
|
||||
|
||||
function hasType(target: Object, flags: TypeSystemObjectKind): Type {
|
||||
if (flags === TypeSystemObjectKind.Symbol) {
|
||||
function findResolutionCycleStartIndex(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): number {
|
||||
for (let i = resolutionTargets.length - 1; i >= 0; i--) {
|
||||
if (hasType(resolutionTargets[i], resolutionPropertyNames[i])) {
|
||||
return -1;
|
||||
}
|
||||
if (resolutionTargets[i] === target && resolutionPropertyNames[i] === propertyName) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
function hasType(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): Type {
|
||||
if (propertyName === TypeSystemPropertyName.Type) {
|
||||
return getSymbolLinks(<Symbol>target).type;
|
||||
}
|
||||
else if (flags === TypeSystemObjectKind.Type) {
|
||||
else if (propertyName === TypeSystemPropertyName.DeclaredType) {
|
||||
return getSymbolLinks(<Symbol>target).declaredType;
|
||||
}
|
||||
else if (propertyName === TypeSystemPropertyName.ResolvedBaseConstructorType) {
|
||||
Debug.assert(!!((<Type>target).flags & TypeFlags.Class));
|
||||
return (<InterfaceType>target).resolvedBaseConstructorType;
|
||||
}
|
||||
else if (flags === TypeSystemObjectKind.SymbolLinks) {
|
||||
return (<SymbolLinks>target).declaredType;
|
||||
}
|
||||
else if (flags === TypeSystemObjectKind.Signature) {
|
||||
else if (propertyName === TypeSystemPropertyName.ResolvedReturnType) {
|
||||
return (<Signature>target).resolvedReturnType;
|
||||
}
|
||||
|
||||
|
@ -2234,7 +2247,7 @@ namespace ts {
|
|||
// be true if no circularities were detected, or false if a circularity was found.
|
||||
function popTypeResolution(): boolean {
|
||||
resolutionTargets.pop();
|
||||
resolutionKinds.pop();
|
||||
resolutionPropertyNames.pop();
|
||||
return resolutionResults.pop();
|
||||
}
|
||||
|
||||
|
@ -2497,7 +2510,7 @@ namespace ts {
|
|||
return links.type = checkExpression((<ExportAssignment>declaration).expression);
|
||||
}
|
||||
// Handle variable, parameter or property
|
||||
if (!pushTypeResolution(symbol, TypeSystemObjectKind.Symbol)) {
|
||||
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
|
||||
return unknownType;
|
||||
}
|
||||
let type = getWidenedTypeForVariableLikeDeclaration(<VariableLikeDeclaration>declaration, /*reportErrors*/ true);
|
||||
|
@ -2538,7 +2551,7 @@ namespace ts {
|
|||
function getTypeOfAccessors(symbol: Symbol): Type {
|
||||
let links = getSymbolLinks(symbol);
|
||||
if (!links.type) {
|
||||
if (!pushTypeResolution(symbol, TypeSystemObjectKind.Symbol)) {
|
||||
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
|
||||
return unknownType;
|
||||
}
|
||||
let getter = <AccessorDeclaration>getDeclarationOfKind(symbol, SyntaxKind.GetAccessor);
|
||||
|
@ -2754,7 +2767,7 @@ namespace ts {
|
|||
if (!baseTypeNode) {
|
||||
return type.resolvedBaseConstructorType = undefinedType;
|
||||
}
|
||||
if (!pushTypeResolution(type, TypeSystemObjectKind.Type)) {
|
||||
if (!pushTypeResolution(type, TypeSystemPropertyName.ResolvedBaseConstructorType)) {
|
||||
return unknownType;
|
||||
}
|
||||
let baseConstructorType = checkExpression(baseTypeNode.expression);
|
||||
|
@ -2881,7 +2894,7 @@ namespace ts {
|
|||
if (!links.declaredType) {
|
||||
// Note that we use the links object as the target here because the symbol object is used as the unique
|
||||
// identity for resolution of the 'type' property in SymbolLinks.
|
||||
if (!pushTypeResolution(links, TypeSystemObjectKind.SymbolLinks)) {
|
||||
if (!pushTypeResolution(symbol, TypeSystemPropertyName.DeclaredType)) {
|
||||
return unknownType;
|
||||
}
|
||||
let declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration);
|
||||
|
@ -3568,7 +3581,7 @@ namespace ts {
|
|||
|
||||
function getReturnTypeOfSignature(signature: Signature): Type {
|
||||
if (!signature.resolvedReturnType) {
|
||||
if (!pushTypeResolution(signature, TypeSystemObjectKind.Signature)) {
|
||||
if (!pushTypeResolution(signature, TypeSystemPropertyName.ResolvedReturnType)) {
|
||||
return unknownType;
|
||||
}
|
||||
let type: Type;
|
||||
|
|
|
@ -1904,6 +1904,8 @@ namespace ts {
|
|||
isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison
|
||||
}
|
||||
|
||||
export type TypeSystemEntity = Symbol | Type | Signature;
|
||||
|
||||
export const enum IndexKind {
|
||||
String,
|
||||
Number,
|
||||
|
|
Loading…
Reference in a new issue