@@ -2993,9 +2993,6 @@ namespace ts {
29932993 }
29942994
29952995 function typeToString(type: Type, enclosingDeclaration?: Node, flags: TypeFormatFlags = TypeFormatFlags.AllowUniqueESSymbolType | TypeFormatFlags.UseAliasDefinedOutsideCurrentScope, writer: EmitTextWriter = createTextWriter("")): string {
2996- if (writer.maximumApproximateLength === undefined) {
2997- writer.maximumApproximateLength = defaultMaximumTruncationLength;
2998- }
29992996 const noTruncation = compilerOptions.noErrorTruncation || flags & TypeFormatFlags.NoTruncation;
30002997 const typeNode = nodeBuilder.typeToTypeNode(type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | (noTruncation ? NodeBuilderFlags.NoTruncation : 0), writer);
30012998 if (typeNode === undefined) return Debug.fail("should always get typenode");
@@ -3005,7 +3002,7 @@ namespace ts {
30053002 printer.writeNode(EmitHint.Unspecified, typeNode, /*sourceFile*/ sourceFile, writer);
30063003 const result = writer.getText();
30073004
3008- const maxLength = noTruncation ? undefined : writer.maximumApproximateLength ;
3005+ const maxLength = noTruncation ? undefined : defaultMaximumTruncationLength * 2 ;
30093006 if (maxLength && result && result.length >= maxLength) {
30103007 return result.substr(0, maxLength - "...".length) + "...";
30113008 }
@@ -3051,6 +3048,11 @@ namespace ts {
30513048 return context.encounteredError ? undefined : resultingNode;
30523049 }
30533050
3051+ function checkTruncationLength(context: NodeBuilderContext): boolean {
3052+ if (context.truncating) return context.truncating;
3053+ return context.truncating = !(context.flags & NodeBuilderFlags.NoTruncation) && context.approximateLength > defaultMaximumTruncationLength;
3054+ }
3055+
30543056 function typeToTypeNodeHelper(type: Type, context: NodeBuilderContext): TypeNode {
30553057 if (cancellationToken && cancellationToken.throwIfCancellationRequested) {
30563058 cancellationToken.throwIfCancellationRequested();
@@ -3063,7 +3065,7 @@ namespace ts {
30633065 return undefined!; // TODO: GH#18217
30643066 }
30653067
3066- if (type.flags & TypeFlags.Any || (!(context.flags & NodeBuilderFlags.NoTruncation) && context.approximateLength > (context.tracker.maximumApproximateLength || 2000)) ) {
3068+ if (type.flags & TypeFlags.Any) {
30673069 context.approximateLength += 3;
30683070 return createKeywordTypeNode(SyntaxKind.AnyKeyword);
30693071 }
@@ -3189,10 +3191,9 @@ namespace ts {
31893191 }
31903192 if (type.flags & (TypeFlags.Union | TypeFlags.Intersection)) {
31913193 const types = type.flags & TypeFlags.Union ? formatUnionTypes((<UnionType>type).types) : (<IntersectionType>type).types;
3192- const typeNodes = mapToTypeNodes(types, context);
3194+ const typeNodes = mapToTypeNodes(types, context, /*isBareList*/ true );
31933195 if (typeNodes && typeNodes.length > 0) {
31943196 const unionOrIntersectionTypeNode = createUnionOrIntersectionTypeNode(type.flags & TypeFlags.Union ? SyntaxKind.UnionType : SyntaxKind.IntersectionType, typeNodes);
3195- context.approximateLength += (3 * (types.length - 1));
31963197 return unionOrIntersectionTypeNode;
31973198 }
31983199 else {
@@ -3471,6 +3472,9 @@ namespace ts {
34713472 }
34723473
34733474 function createTypeNodesFromResolvedType(resolvedType: ResolvedType): TypeElement[] | undefined {
3475+ if (checkTruncationLength(context)) {
3476+ return [createPropertySignature(/*modifiers*/ undefined, "...", /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined)];
3477+ }
34743478 const typeElements: TypeElement[] = [];
34753479 for (const signature of resolvedType.callSignatures) {
34763480 typeElements.push(<CallSignatureDeclaration>signatureToSignatureDeclarationHelper(signature, SyntaxKind.CallSignature, context));
@@ -3493,7 +3497,9 @@ namespace ts {
34933497 return typeElements;
34943498 }
34953499
3500+ let i = 0;
34963501 for (const propertySymbol of properties) {
3502+ i++;
34973503 if (context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral) {
34983504 if (propertySymbol.flags & SymbolFlags.Prototype) {
34993505 continue;
@@ -3502,69 +3508,102 @@ namespace ts {
35023508 context.tracker.reportPrivateInBaseOfClassExpression(unescapeLeadingUnderscores(propertySymbol.escapedName));
35033509 }
35043510 }
3505- const propertyType = getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped && context.flags & NodeBuilderFlags.InReverseMappedType ?
3506- anyType : getTypeOfSymbol(propertySymbol);
3507- const saveEnclosingDeclaration = context.enclosingDeclaration;
3508- context.enclosingDeclaration = undefined;
3509- if (getCheckFlags(propertySymbol) & CheckFlags.Late) {
3510- const decl = first(propertySymbol.declarations);
3511- if (context.tracker.trackSymbol && hasLateBindableName(decl)) {
3512- // get symbol of the first identifier of the entityName
3513- const firstIdentifier = getFirstIdentifier(decl.name.expression);
3514- const name = resolveName(firstIdentifier, firstIdentifier.escapedText, SymbolFlags.Value | SymbolFlags.ExportValue, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true);
3515- if (name) {
3516- context.tracker.trackSymbol(name, saveEnclosingDeclaration, SymbolFlags.Value);
3517- }
3518- }
3511+ if (checkTruncationLength(context) && (i + 2 < properties.length - 1)) {
3512+ typeElements.push(createPropertySignature(/*modifiers*/ undefined, `... ${properties.length - i} more ...`, /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined));
3513+ addPropertyToElementList(properties[properties.length - 1], context, typeElements);
3514+ break;
35193515 }
3520- const propertyName = symbolToName(propertySymbol, context, SymbolFlags.Value, /*expectsIdentifier*/ true);
3521- context.approximateLength += (symbolName(propertySymbol).length + 1);
3522- context.enclosingDeclaration = saveEnclosingDeclaration;
3523- const optionalToken = propertySymbol.flags & SymbolFlags.Optional ? createToken(SyntaxKind.QuestionToken) : undefined;
3524- if (propertySymbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && !getPropertiesOfObjectType(propertyType).length) {
3525- const signatures = getSignaturesOfType(propertyType, SignatureKind.Call);
3526- for (const signature of signatures) {
3527- const methodDeclaration = <MethodSignature>signatureToSignatureDeclarationHelper(signature, SyntaxKind.MethodSignature, context);
3528- methodDeclaration.name = propertyName;
3529- methodDeclaration.questionToken = optionalToken;
3530- if (propertySymbol.valueDeclaration) {
3531- // Copy comments to node for declaration emit
3532- setCommentRange(methodDeclaration, propertySymbol.valueDeclaration);
3533- }
3534- typeElements.push(methodDeclaration);
3535- }
3516+ addPropertyToElementList(propertySymbol, context, typeElements);
3517+
3518+ }
3519+ return typeElements.length ? typeElements : undefined;
3520+ }
3521+ }
3522+
3523+ function addPropertyToElementList(propertySymbol: Symbol, context: NodeBuilderContext, typeElements: TypeElement[]) {
3524+ const propertyType = getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped && context.flags & NodeBuilderFlags.InReverseMappedType ?
3525+ anyType : getTypeOfSymbol(propertySymbol);
3526+ const saveEnclosingDeclaration = context.enclosingDeclaration;
3527+ context.enclosingDeclaration = undefined;
3528+ if (getCheckFlags(propertySymbol) & CheckFlags.Late) {
3529+ const decl = first(propertySymbol.declarations);
3530+ if (context.tracker.trackSymbol && hasLateBindableName(decl)) {
3531+ // get symbol of the first identifier of the entityName
3532+ const firstIdentifier = getFirstIdentifier(decl.name.expression);
3533+ const name = resolveName(firstIdentifier, firstIdentifier.escapedText, SymbolFlags.Value | SymbolFlags.ExportValue, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true);
3534+ if (name) {
3535+ context.tracker.trackSymbol(name, saveEnclosingDeclaration, SymbolFlags.Value);
35363536 }
3537- else {
3538- const savedFlags = context.flags;
3539- context.flags |= !!(getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped) ? NodeBuilderFlags.InReverseMappedType : 0;
3540- const propertyTypeNode = propertyType ? typeToTypeNodeHelper(propertyType, context) : createKeywordTypeNode(SyntaxKind.AnyKeyword);
3541- context.flags = savedFlags;
3542-
3543- const modifiers = isReadonlySymbol(propertySymbol) ? [createToken(SyntaxKind.ReadonlyKeyword)] : undefined;
3544- if (modifiers) {
3545- context.approximateLength += 9;
3546- }
3547- const propertySignature = createPropertySignature(
3548- modifiers,
3549- propertyName,
3550- optionalToken,
3551- propertyTypeNode,
3552- /*initializer*/ undefined);
3553- if (propertySymbol.valueDeclaration) {
3554- // Copy comments to node for declaration emit
3555- setCommentRange(propertySignature, propertySymbol.valueDeclaration);
3556- }
3557- typeElements.push(propertySignature);
3537+ }
3538+ }
3539+ const propertyName = symbolToName(propertySymbol, context, SymbolFlags.Value, /*expectsIdentifier*/ true);
3540+ context.approximateLength += (symbolName(propertySymbol).length + 1);
3541+ context.enclosingDeclaration = saveEnclosingDeclaration;
3542+ const optionalToken = propertySymbol.flags & SymbolFlags.Optional ? createToken(SyntaxKind.QuestionToken) : undefined;
3543+ if (propertySymbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && !getPropertiesOfObjectType(propertyType).length) {
3544+ const signatures = getSignaturesOfType(propertyType, SignatureKind.Call);
3545+ for (const signature of signatures) {
3546+ const methodDeclaration = <MethodSignature>signatureToSignatureDeclarationHelper(signature, SyntaxKind.MethodSignature, context);
3547+ methodDeclaration.name = propertyName;
3548+ methodDeclaration.questionToken = optionalToken;
3549+ if (propertySymbol.valueDeclaration) {
3550+ // Copy comments to node for declaration emit
3551+ setCommentRange(methodDeclaration, propertySymbol.valueDeclaration);
35583552 }
3553+ typeElements.push(methodDeclaration);
35593554 }
3560- return typeElements.length ? typeElements : undefined;
3555+ }
3556+ else {
3557+ const savedFlags = context.flags;
3558+ context.flags |= !!(getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped) ? NodeBuilderFlags.InReverseMappedType : 0;
3559+ const propertyTypeNode = propertyType ? typeToTypeNodeHelper(propertyType, context) : createKeywordTypeNode(SyntaxKind.AnyKeyword);
3560+ context.flags = savedFlags;
3561+
3562+ const modifiers = isReadonlySymbol(propertySymbol) ? [createToken(SyntaxKind.ReadonlyKeyword)] : undefined;
3563+ if (modifiers) {
3564+ context.approximateLength += 9;
3565+ }
3566+ const propertySignature = createPropertySignature(
3567+ modifiers,
3568+ propertyName,
3569+ optionalToken,
3570+ propertyTypeNode,
3571+ /*initializer*/ undefined);
3572+ if (propertySymbol.valueDeclaration) {
3573+ // Copy comments to node for declaration emit
3574+ setCommentRange(propertySignature, propertySymbol.valueDeclaration);
3575+ }
3576+ typeElements.push(propertySignature);
35613577 }
35623578 }
35633579
3564- function mapToTypeNodes(types: ReadonlyArray<Type> | undefined, context: NodeBuilderContext): TypeNode[] | undefined {
3580+ function mapToTypeNodes(types: ReadonlyArray<Type> | undefined, context: NodeBuilderContext, isBareList?: boolean ): TypeNode[] | undefined {
35653581 if (some(types)) {
3582+ if (checkTruncationLength(context)) {
3583+ if (!isBareList) {
3584+ return [createTypeReferenceNode("...", /*typeArguments*/ undefined)];
3585+ }
3586+ else if (types.length > 2) {
3587+ return [
3588+ typeToTypeNodeHelper(types[0], context),
3589+ createTypeReferenceNode(`... ${types.length - 2} more ...`, /*typeArguments*/ undefined),
3590+ typeToTypeNodeHelper(types[types.length - 1], context)
3591+ ];
3592+ }
3593+ }
35663594 const result = [];
3595+ let i = 0;
35673596 for (const type of types) {
3597+ i++;
3598+ if (checkTruncationLength(context) && (i + 2 < types.length - 1)) {
3599+ result.push(createTypeReferenceNode(`... ${types.length - i} more ...`, /*typeArguments*/ undefined));
3600+ const typeNode = typeToTypeNodeHelper(types[types.length - 1], context);
3601+ if (typeNode) {
3602+ result.push(typeNode);
3603+ }
3604+ break;
3605+ }
3606+ context.approximateLength += 2; // Account for whitespace + separator
35683607 const typeNode = typeToTypeNodeHelper(type, context);
35693608 if (typeNode) {
35703609 result.push(typeNode);
@@ -4078,6 +4117,7 @@ namespace ts {
40784117 visitedSymbols: Map<true> | undefined;
40794118 inferTypeParameters: TypeParameter[] | undefined;
40804119 approximateLength: number;
4120+ truncating?: boolean;
40814121 }
40824122
40834123 function isDefaultBindingContext(location: Node) {
0 commit comments