@@ -3540,7 +3540,6 @@ namespace ts {
3540
3540
}
3541
3541
3542
3542
function createNodeBuilder() {
3543
- let depth = 0;
3544
3543
return {
3545
3544
typeToTypeNode: (type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) =>
3546
3545
withContext(enclosingDeclaration, flags, tracker, context => typeToTypeNodeHelper(type, context)),
@@ -3712,7 +3711,7 @@ namespace ts {
3712
3711
3713
3712
if (objectFlags & ObjectFlags.Reference) {
3714
3713
Debug.assert(!!(type.flags & TypeFlags.Object));
3715
- return typeReferenceToTypeNode(<TypeReference>type);
3714
+ return (<TypeReference>type).node ? visitAndTransformType(type, typeReferenceToTypeNode) : typeReferenceToTypeNode(<TypeReference>type);
3716
3715
}
3717
3716
if (type.flags & TypeFlags.TypeParameter || objectFlags & ObjectFlags.ClassOrInterface) {
3718
3717
if (type.flags & TypeFlags.TypeParameter && contains(context.inferTypeParameters, type)) {
@@ -3804,10 +3803,7 @@ namespace ts {
3804
3803
function createAnonymousTypeNode(type: ObjectType): TypeNode {
3805
3804
const typeId = "" + type.id;
3806
3805
const symbol = type.symbol;
3807
- let id: string;
3808
3806
if (symbol) {
3809
- const isConstructorObject = getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & SymbolFlags.Class;
3810
- id = (isConstructorObject ? "+" : "") + getSymbolId(symbol);
3811
3807
if (isJSConstructor(symbol.valueDeclaration)) {
3812
3808
// Instance and static types share the same symbol; only add 'typeof' for the static side.
3813
3809
const isInstanceType = type === getInferredClassType(symbol) ? SymbolFlags.Type : SymbolFlags.Value;
@@ -3831,25 +3827,7 @@ namespace ts {
3831
3827
}
3832
3828
}
3833
3829
else {
3834
- // Since instantiations of the same anonymous type have the same symbol, tracking symbols instead
3835
- // of types allows us to catch circular references to instantiations of the same anonymous type
3836
- if (!context.visitedTypes) {
3837
- context.visitedTypes = createMap<true>();
3838
- }
3839
- if (!context.symbolDepth) {
3840
- context.symbolDepth = createMap<number>();
3841
- }
3842
-
3843
- const depth = context.symbolDepth.get(id) || 0;
3844
- if (depth > 10) {
3845
- return createElidedInformationPlaceholder(context);
3846
- }
3847
- context.symbolDepth.set(id, depth + 1);
3848
- context.visitedTypes.set(typeId, true);
3849
- const result = createTypeNodeFromObjectType(type);
3850
- context.visitedTypes.delete(typeId);
3851
- context.symbolDepth.set(id, depth);
3852
- return result;
3830
+ return visitAndTransformType(type, createTypeNodeFromObjectType);
3853
3831
}
3854
3832
}
3855
3833
else {
@@ -3871,6 +3849,37 @@ namespace ts {
3871
3849
}
3872
3850
}
3873
3851
3852
+ function visitAndTransformType<T>(type: Type, transform: (type: Type) => T) {
3853
+ const typeId = "" + type.id;
3854
+ const isConstructorObject = getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & SymbolFlags.Class;
3855
+ const id = getObjectFlags(type) & ObjectFlags.Reference ? "N" + getNodeId((<DeferredTypeReference>type).node) :
3856
+ (isConstructorObject ? "+" : "") + getSymbolId(type.symbol);
3857
+ // Since instantiations of the same anonymous type have the same symbol, tracking symbols instead
3858
+ // of types allows us to catch circular references to instantiations of the same anonymous type
3859
+ if (!context.visitedTypes) {
3860
+ context.visitedTypes = createMap<true>();
3861
+ }
3862
+ if (id && !context.symbolDepth) {
3863
+ context.symbolDepth = createMap<number>();
3864
+ }
3865
+
3866
+ let depth: number | undefined;
3867
+ if (id) {
3868
+ depth = context.symbolDepth!.get(id) || 0;
3869
+ if (depth > 10) {
3870
+ return createElidedInformationPlaceholder(context);
3871
+ }
3872
+ context.symbolDepth!.set(id, depth + 1);
3873
+ }
3874
+ context.visitedTypes.set(typeId, true);
3875
+ const result = transform(type);
3876
+ context.visitedTypes.delete(typeId);
3877
+ if (id) {
3878
+ context.symbolDepth!.set(id, depth!);
3879
+ }
3880
+ return result;
3881
+ }
3882
+
3874
3883
function createTypeNodeFromObjectType(type: ObjectType): TypeNode {
3875
3884
if (isGenericMappedType(type)) {
3876
3885
return createMappedTypeNodeFromType(type);
@@ -3910,15 +3919,10 @@ namespace ts {
3910
3919
const typeArguments: ReadonlyArray<Type> = getTypeArguments(type);
3911
3920
if (type.target === globalArrayType || type.target === globalReadonlyArrayType) {
3912
3921
if (context.flags & NodeBuilderFlags.WriteArrayAsGenericType) {
3913
- depth++;
3914
- const typeArgumentNode = typeToTypeNodeHelper(depth >= 5 ? anyType : typeArguments[0], context);
3915
- depth--;
3916
- createTypeReferenceNode(type.target === globalArrayType ? "Array" : "ReadonlyArray", [typeArgumentNode]);
3922
+ const typeArgumentNode = typeToTypeNodeHelper(typeArguments[0], context);
3923
+ return createTypeReferenceNode(type.target === globalArrayType ? "Array" : "ReadonlyArray", [typeArgumentNode]);
3917
3924
}
3918
-
3919
- depth++;
3920
- const elementType = typeToTypeNodeHelper(depth >= 5 ? anyType : typeArguments[0], context);
3921
- depth--;
3925
+ const elementType = typeToTypeNodeHelper(typeArguments[0], context);
3922
3926
const arrayType = createArrayTypeNode(elementType);
3923
3927
return type.target === globalArrayType ? arrayType : createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, arrayType);
3924
3928
}
0 commit comments