Skip to content

Commit 3f99b74

Browse files
committed
Display nested generic types as f<A>.g<B>.C<X, Y>
1 parent 26b955a commit 3f99b74

File tree

2 files changed

+63
-6
lines changed

2 files changed

+63
-6
lines changed

src/compiler/checker.ts

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,17 +1530,60 @@ module ts {
15301530
}
15311531
}
15321532

1533+
function writeSymbolTypeReference(symbol: Symbol, typeArguments: Type[], pos: number, end: number) {
1534+
if (!isReservedMemberName(symbol.name)) {
1535+
buildSymbolDisplay(symbol, writer, enclosingDeclaration, SymbolFlags.Type);
1536+
}
1537+
if (pos < end) {
1538+
writePunctuation(writer, SyntaxKind.LessThanToken);
1539+
writeType(typeArguments[pos++], TypeFormatFlags.None);
1540+
while (pos < end) {
1541+
writePunctuation(writer, SyntaxKind.CommaToken);
1542+
writeSpace(writer);
1543+
writeType(typeArguments[pos++], TypeFormatFlags.None);
1544+
}
1545+
writePunctuation(writer, SyntaxKind.GreaterThanToken);
1546+
}
1547+
}
1548+
15331549
function writeTypeReference(type: TypeReference, flags: TypeFormatFlags) {
1550+
let typeArguments = type.typeArguments;
15341551
if (type.target === globalArrayType && !(flags & TypeFormatFlags.WriteArrayAsGenericType)) {
1535-
writeType(type.typeArguments[0], TypeFormatFlags.InElementType);
1552+
writeType(typeArguments[0], TypeFormatFlags.InElementType);
15361553
writePunctuation(writer, SyntaxKind.OpenBracketToken);
15371554
writePunctuation(writer, SyntaxKind.CloseBracketToken);
15381555
}
15391556
else {
1540-
buildSymbolDisplay(type.target.symbol, writer, enclosingDeclaration, SymbolFlags.Type);
1541-
writePunctuation(writer, SyntaxKind.LessThanToken);
1542-
writeTypeList(type.typeArguments, /*union*/ false);
1543-
writePunctuation(writer, SyntaxKind.GreaterThanToken);
1557+
// Write the type reference in the format f<A>.g<B>.C<X, Y> where A and B are type arguments
1558+
// for outer type parameters, and f and g are the respective declaring containers of those
1559+
// type parameters.
1560+
let outerTypeParameters = type.target.outerTypeParameters;
1561+
let i = 0;
1562+
if (outerTypeParameters) {
1563+
let length = outerTypeParameters.length;
1564+
let group = 0;
1565+
while (i < length) {
1566+
// Find group of type arguments for type parameters with the same declaring container.
1567+
let start = i;
1568+
let parent = getParentSymbolOfTypeParameter(outerTypeParameters[i]);
1569+
do {
1570+
i++;
1571+
} while (i < length && getParentSymbolOfTypeParameter(outerTypeParameters[i]) === parent);
1572+
// When type parameters are their own type arguments for the whole group (i.e. we have
1573+
// the default outer type arguments), we don't show the group.
1574+
if (!rangeEquals(outerTypeParameters, typeArguments, start, i)) {
1575+
if (group) {
1576+
writePunctuation(writer, SyntaxKind.DotToken);
1577+
}
1578+
writeSymbolTypeReference(parent, typeArguments, start, i);
1579+
group++;
1580+
}
1581+
}
1582+
if (group) {
1583+
writePunctuation(writer, SyntaxKind.DotToken);
1584+
}
1585+
}
1586+
writeSymbolTypeReference(type.symbol, typeArguments, i, typeArguments.length);
15441587
}
15451588
}
15461589

@@ -1736,7 +1779,7 @@ module ts {
17361779
function buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaraiton?: Node, flags?: TypeFormatFlags) {
17371780
let targetSymbol = getTargetSymbol(symbol);
17381781
if (targetSymbol.flags & SymbolFlags.Class || targetSymbol.flags & SymbolFlags.Interface) {
1739-
buildDisplayForTypeParametersAndDelimiters(getTypeParametersOfClassOrInterface(symbol), writer, enclosingDeclaraiton, flags);
1782+
buildDisplayForTypeParametersAndDelimiters(getLocalTypeParametersOfClassOrInterface(symbol), writer, enclosingDeclaraiton, flags);
17401783
}
17411784
}
17421785

@@ -3356,6 +3399,10 @@ module ts {
33563399
return type.constraint === noConstraintType ? undefined : type.constraint;
33573400
}
33583401

3402+
function getParentSymbolOfTypeParameter(typeParameter: TypeParameter): Symbol {
3403+
return getSymbolOfNode(getDeclarationOfKind(typeParameter.symbol, SyntaxKind.TypeParameter).parent);
3404+
}
3405+
33593406
function getTypeListId(types: Type[]) {
33603407
switch (types.length) {
33613408
case 1:

src/compiler/core.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,16 @@ module ts {
129129
}
130130
}
131131

132+
export function rangeEquals<T>(array1: T[], array2: T[], pos: number, end: number) {
133+
while (pos < end) {
134+
if (array1[pos] !== array2[pos]) {
135+
return false;
136+
}
137+
pos++;
138+
}
139+
return true;
140+
}
141+
132142
/**
133143
* Returns the last element of an array if non-empty, undefined otherwise.
134144
*/

0 commit comments

Comments
 (0)