@@ -2449,13 +2449,13 @@ namespace ts {
24492449 if (!inTypeAlias && type.aliasSymbol &&
24502450 isSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === SymbolAccessibility.Accessible) {
24512451 const name = symbolToName(type.aliasSymbol, /*expectsIdentifier*/ false, SymbolFlags.Type, context);
2452- const typeArgumentNodes = type.aliasTypeArguments && mapToTypeNodeArray(type.aliasTypeArguments, /*addInElementTypeFlag*/ false);
2452+ const typeArgumentNodes = type.aliasTypeArguments && mapToTypeNodeArray(type.aliasTypeArguments, context, /*addInElementTypeFlag*/ false, /*addInFirstTypeArgumentFlag*/ true );
24532453 return createTypeReferenceNode(name, typeArgumentNodes);
24542454 }
24552455
24562456 if (type.flags & (TypeFlags.Union | TypeFlags.Intersection)) {
24572457 const types = type.flags & TypeFlags.Union ? formatUnionTypes((<UnionType>type).types) : (<IntersectionType>type).types;
2458- const typeNodes = types && mapToTypeNodeArray(types, /*addInElementTypeFlag*/ true);
2458+ const typeNodes = types && mapToTypeNodeArray(types, context, /*addInElementTypeFlag*/ true, /*addInFirstTypeArgumentFlag*/ false );
24592459 if (typeNodes && typeNodes.length > 0) {
24602460 const unionOrIntersectionTypeNode = createUnionOrIntersectionTypeNode(type.flags & TypeFlags.Union ? SyntaxKind.UnionType : SyntaxKind.IntersectionType, typeNodes);
24612461 return InElementType ? createParenthesizedTypeNode(unionOrIntersectionTypeNode) : unionOrIntersectionTypeNode;
@@ -2492,20 +2492,6 @@ namespace ts {
24922492
24932493 Debug.fail("Should be unreachable.");
24942494
2495- function mapToTypeNodeArray(types: Type[], addInElementTypeFlag: boolean): TypeNode[] {
2496- const result = [];
2497- Debug.assert(context.InElementType === false, "should be unset at the beginning of the helper");
2498- for (const type of types) {
2499- context.InElementType = addInElementTypeFlag;
2500- const typeNode = typeToTypeNodeHelper(type, context);
2501- if (typeNode) {
2502- result.push(typeNode);
2503- }
2504- }
2505- Debug.assert(context.InElementType === false, "should be unset at the beginning of the helper");
2506- return result;
2507- }
2508-
25092495 function createMappedTypeNodeFromType(type: MappedType) {
25102496 Debug.assert(!!(type.flags & TypeFlags.Object));
25112497 const typeParameter = getTypeParameterFromMappedType(type);
@@ -2642,7 +2628,7 @@ namespace ts {
26422628 }
26432629 else if (type.target.objectFlags & ObjectFlags.Tuple) {
26442630 if (typeArguments.length > 0) {
2645- const tupleConstituentNodes = mapToTypeNodeArray(typeArguments.slice(0, getTypeReferenceArity(type)), /*addInElementTypeFlag*/ false);
2631+ const tupleConstituentNodes = mapToTypeNodeArray(typeArguments.slice(0, getTypeReferenceArity(type)), context, /*addInElementTypeFlag*/ false, /*addInFirstTypeArgumentFlag */ false);
26462632 if (tupleConstituentNodes && tupleConstituentNodes.length > 0) {
26472633 return createTupleTypeNode(tupleConstituentNodes);
26482634 }
@@ -2669,8 +2655,11 @@ namespace ts {
26692655 // When type parameters are their own type arguments for the whole group (i.e. we have
26702656 // the default outer type arguments), we don't show the group.
26712657 if (!rangeEquals(outerTypeParameters, typeArguments, start, i)) {
2672- // inFirstTypeArgument???
2658+ const qualifiedNamePartTypeArguments = typeArguments.slice(start,i);
2659+ const qualifiedNamePartTypeArgumentNodes = qualifiedNamePartTypeArguments && createNodeArray(mapToTypeNodeArray(qualifiedNamePartTypeArguments, context, /*addInElementTypeFlag*/ false, /*addInFirstTypeArgumentFlag*/ true));
26732660 const qualifiedNamePart = symbolToName(parent, /*expectsIdentifier*/ true, SymbolFlags.Type, context);
2661+ qualifiedNamePart.typeArguments = qualifiedNamePartTypeArgumentNodes;
2662+
26742663 if (!qualifiedName) {
26752664 qualifiedName = createQualifiedName(qualifiedNamePart, /*right*/ undefined);
26762665 }
@@ -2699,7 +2688,7 @@ namespace ts {
26992688 if (some(typeArguments)) {
27002689 const slice = typeArguments.slice(i, typeParameterCount - i);
27012690 context.InFirstTypeArgument = true;
2702- typeArgumentNodes = mapToTypeNodeArray(slice, /*addInElementTypeFlag*/ false);
2691+ typeArgumentNodes = mapToTypeNodeArray(slice, context, /*addInElementTypeFlag*/ false, /*addInFirstTypeArgumentFlag*/ true );
27032692 }
27042693
27052694 return createTypeReferenceNode(entityName, typeArgumentNodes);
@@ -2761,6 +2750,24 @@ namespace ts {
27612750 }
27622751 }
27632752
2753+ function mapToTypeNodeArray(types: Type[], context: NodeBuilderContext, addInElementTypeFlag: boolean, addInFirstTypeArgumentFlag: boolean): TypeNode[] {
2754+ const result = [];
2755+ Debug.assert(context.InElementType === false, "should be unset at the beginning of the helper");
2756+ for (let i = 0; i < types.length; ++i) {
2757+ let type = types[i]
2758+ context.InElementType = addInElementTypeFlag;
2759+ if (i === 0) {
2760+ context.InFirstTypeArgument = addInFirstTypeArgumentFlag;
2761+ }
2762+ const typeNode = typeToTypeNodeHelper(type, context);
2763+ if (typeNode) {
2764+ result.push(typeNode);
2765+ }
2766+ }
2767+ Debug.assert(context.InElementType === false, "should be unset at the beginning of the helper");
2768+ return result;
2769+ }
2770+
27642771 function indexInfoToIndexSignatureDeclarationHelper(indexInfo: IndexInfo, kind: IndexKind, context: NodeBuilderContext): IndexSignatureDeclaration {
27652772 const indexerTypeNode = createKeywordTypeNode(kind === IndexKind.String ? SyntaxKind.StringKeyword : SyntaxKind.NumberKeyword);
27662773 const name = getNameFromIndexInfo(indexInfo) || "x";
@@ -2889,9 +2896,8 @@ namespace ts {
28892896 Debug.assert(chain && 0 <= index && index < chain.length);
28902897 // const parentIndex = index - 1;
28912898 const symbol = chain[index];
2892- let typeParameterString = "" ;
2899+ let typeParameterNodes: TypeNode[] | undefined ;
28932900 if (index > 0) {
2894-
28952901 const parentSymbol = chain[index - 1];
28962902 let typeParameters: TypeParameter[];
28972903 if (getCheckFlags(symbol) & CheckFlags.Instantiated) {
@@ -2907,17 +2913,12 @@ namespace ts {
29072913 if (!context.encounteredError && !(context.flags & NodeBuilderFlags.allowTypeParameterInQualifiedName)) {
29082914 context.encounteredError = true;
29092915 }
2910- const writer = getSingleLineStringWriter();
2911- const displayBuilder = getSymbolDisplayBuilder();
2912- displayBuilder.buildDisplayForTypeParametersAndDelimiters(typeParameters, writer, context.enclosingDeclaration, 0);
2913- typeParameterString = writer.string();
2914- releaseStringWriter(writer);
2915-
2916+ typeParameterNodes = typeParameters && mapToTypeNodeArray(typeParameters, context, /*addInElementTypeFlag*/ false, /*addInFirstTypeArgumentFlag*/ true);
29162917 }
29172918 }
2919+
29182920 const symbolName = getNameOfSymbol(symbol, context);
2919- const symbolNameWithTypeParameters = typeParameterString.length > 0 ? `${symbolName}<${typeParameterString}>` : symbolName;
2920- const identifier = createIdentifier(symbolNameWithTypeParameters);
2921+ const identifier = createIdentifier(symbolName, typeParameterNodes);
29212922
29222923 return index > 0 ? createQualifiedName(createEntityNameFromSymbolChain(chain, index - 1), identifier) : identifier;
29232924 }
0 commit comments