Skip to content

Commit 41452a5

Browse files
author
Arthur Ozga
committed
add typeArguments to identifier
1 parent ad58572 commit 41452a5

File tree

6 files changed

+44
-30
lines changed

6 files changed

+44
-30
lines changed

src/compiler/checker.ts

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

src/compiler/emitter.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,7 @@ namespace ts {
780780

781781
function emitIdentifier(node: Identifier) {
782782
write(getTextOfNode(node, /*includeTrivia*/ false));
783+
emitTypeArguments(node, node.typeArguments);
783784
}
784785

785786
//

src/compiler/factory.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,15 +136,22 @@ namespace ts {
136136

137137
// Identifiers
138138

139-
export function createIdentifier(text: string): Identifier {
139+
export function createIdentifier(text: string, typeArguments?: TypeNode[]): Identifier {
140140
const node = <Identifier>createSynthesizedNode(SyntaxKind.Identifier);
141141
node.text = escapeIdentifier(text);
142142
node.originalKeywordKind = text ? stringToToken(text) : SyntaxKind.Unknown;
143143
node.autoGenerateKind = GeneratedIdentifierKind.None;
144144
node.autoGenerateId = 0;
145+
node.typeArguments = asNodeArray(typeArguments);
145146
return node;
146147
}
147148

149+
export function updateIdentifier(node: Identifier, typeArguments: NodeArray<TypeNode> | undefined): Identifier {
150+
return node.typeArguments !== typeArguments
151+
? updateNode(createIdentifier(node.text, typeArguments), node)
152+
: node;
153+
}
154+
148155
let nextAutoGenerateId = 0;
149156

150157
/** Create a unique temporary variable. */

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,7 @@ namespace ts {
575575
/*@internal*/ autoGenerateKind?: GeneratedIdentifierKind; // Specifies whether to auto-generate the text for an identifier.
576576
/*@internal*/ autoGenerateId?: number; // Ensures unique generated identifiers get unique names, but clones get the same name.
577577
isInJSDocNamespace?: boolean; // if the node is a member in a JSDoc namespace
578+
/*@internal*/ typeArguments: NodeArray<TypeNode>; // Only defined on synthesized nodes.Though not syntactically valid, used in emitting diagnostics.
578579
}
579580

580581
// Transient identifier node (marked by id === -1)

src/compiler/visitor.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,9 @@ namespace ts {
219219
}
220220

221221
switch (node.kind) {
222+
case SyntaxKind.Identifier:
223+
return updateIdentifier(<Identifier>node, nodesVisitor((<Identifier>node).typeArguments, visitor, isTypeNode));
224+
222225
case SyntaxKind.SemicolonClassElement:
223226
case SyntaxKind.EmptyStatement:
224227
case SyntaxKind.OmittedExpression:

src/services/services.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ namespace ts {
357357
_incrementExpressionBrand: any;
358358
_unaryExpressionBrand: any;
359359
_expressionBrand: any;
360+
typeArguments: any;
360361
constructor(_kind: SyntaxKind.Identifier, pos: number, end: number) {
361362
super(pos, end);
362363
}

0 commit comments

Comments
 (0)