Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 20a4e32

Browse filesBrowse files
author
Arthur Ozga
committed
parenthesization in factory
1 parent 6fd86b4 commit 20a4e32
Copy full SHA for 20a4e32

4 files changed

+52-68Lines changed: 52 additions & 68 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/compiler/checker.ts‎

Copy file name to clipboardExpand all lines: src/compiler/checker.ts
+18-54Lines changed: 18 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2279,7 +2279,7 @@ namespace ts {
22792279
}
22802280

22812281
function typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string {
2282-
const typeNode = nodeBuilder.typeToTypeNode(type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.ignoreErrors);
2282+
const typeNode = nodeBuilder.typeToTypeNode(type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.ignoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName);
22832283
Debug.assert(typeNode !== undefined, "should always get typenode?");
22842284
const options = { removeComments: true };
22852285
const writer = createTextWriter("");
@@ -2360,10 +2360,8 @@ namespace ts {
23602360
}
23612361

23622362
function typeToTypeNodeHelper(type: Type, context: NodeBuilderContext): TypeNode {
2363-
const inElementType = context.flags & NodeBuilderFlags.InElementType;
2364-
const inFirstTypeArgument = context.flags & NodeBuilderFlags.InFirstTypeArgument;
23652363
const inTypeAlias = context.flags & NodeBuilderFlags.InTypeAlias;
2366-
context.flags &= ~(NodeBuilderFlags.StateClearingFlags);
2364+
context.flags &= ~(NodeBuilderFlags.InTypeAlias);
23672365

23682366
if (!type) {
23692367
context.encounteredError = true;
@@ -2443,15 +2441,15 @@ namespace ts {
24432441
if (!inTypeAlias && type.aliasSymbol &&
24442442
isSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === SymbolAccessibility.Accessible) {
24452443
const name = symbolToTypeReferenceName(type.aliasSymbol);
2446-
const typeArgumentNodes = toTypeArgumentNodes(type.aliasTypeArguments, context);
2444+
const typeArgumentNodes = type.aliasTypeArguments && mapToTypeNodeArray(type.aliasTypeArguments, context);
24472445
return createTypeReferenceNode(name, typeArgumentNodes);
24482446
}
24492447
if (type.flags & (TypeFlags.Union | TypeFlags.Intersection)) {
24502448
const types = type.flags & TypeFlags.Union ? formatUnionTypes((<UnionType>type).types) : (<IntersectionType>type).types;
2451-
const typeNodes = types && mapToTypeNodeArray(types, context, /*addInElementTypeFlag*/ true, /*addInFirstTypeArgumentFlag*/ false);
2449+
const typeNodes = types && mapToTypeNodeArray(types, context);
24522450
if (typeNodes && typeNodes.length > 0) {
24532451
const unionOrIntersectionTypeNode = createUnionOrIntersectionTypeNode(type.flags & TypeFlags.Union ? SyntaxKind.UnionType : SyntaxKind.IntersectionType, typeNodes);
2454-
return inElementType ? createParenthesizedType(unionOrIntersectionTypeNode) : unionOrIntersectionTypeNode;
2452+
return unionOrIntersectionTypeNode;
24552453
}
24562454
else {
24572455
if (!context.encounteredError && !(context.flags & NodeBuilderFlags.AllowEmptyUnionOrIntersection)) {
@@ -2467,15 +2465,11 @@ namespace ts {
24672465
}
24682466
if (type.flags & TypeFlags.Index) {
24692467
const indexedType = (<IndexType>type).type;
2470-
context.flags |= NodeBuilderFlags.InElementType;
24712468
const indexTypeNode = typeToTypeNodeHelper(indexedType, context);
2472-
Debug.assert(!(context.flags & NodeBuilderFlags.InElementType));
24732469
return createTypeOperatorNode(indexTypeNode);
24742470
}
24752471
if (type.flags & TypeFlags.IndexedAccess) {
2476-
context.flags |= NodeBuilderFlags.InElementType;
24772472
const objectTypeNode = typeToTypeNodeHelper((<IndexedAccessType>type).objectType, context);
2478-
Debug.assert(!(context.flags & NodeBuilderFlags.InElementType));
24792473
const indexTypeNode = typeToTypeNodeHelper((<IndexedAccessType>type).indexType, context);
24802474
return createIndexedAccessTypeNode(objectTypeNode, indexTypeNode);
24812475
}
@@ -2561,17 +2555,14 @@ namespace ts {
25612555
if (resolved.callSignatures.length === 1 && !resolved.constructSignatures.length) {
25622556
const signature = resolved.callSignatures[0];
25632557
const signatureNode = <FunctionTypeNode>signatureToSignatureDeclarationHelper(signature, SyntaxKind.FunctionType, context);
2564-
return shouldAddParenthesisAroundFunctionType(signature, context) ?
2565-
createParenthesizedType(signatureNode) :
2566-
signatureNode;
2558+
return signatureNode;
25672559

25682560
}
2561+
25692562
if (resolved.constructSignatures.length === 1 && !resolved.callSignatures.length) {
25702563
const signature = resolved.constructSignatures[0];
25712564
const signatureNode = <ConstructorTypeNode>signatureToSignatureDeclarationHelper(signature, SyntaxKind.ConstructorType, context);
2572-
return shouldAddParenthesisAroundFunctionType(signature, context) ?
2573-
createParenthesizedType(signatureNode) :
2574-
signatureNode;
2565+
return signatureNode;
25752566
}
25762567
}
25772568

@@ -2583,19 +2574,6 @@ namespace ts {
25832574
return setEmitFlags(typeLiteralNode, EmitFlags.SingleLine);
25842575
}
25852576

2586-
function shouldAddParenthesisAroundFunctionType(callSignature: Signature, context: NodeBuilderContext) {
2587-
if (inElementType) {
2588-
return true;
2589-
}
2590-
else if (inFirstTypeArgument) {
2591-
// Add parenthesis around function type for the first type argument to avoid ambiguity
2592-
const typeParameters = callSignature.target && (context.flags & NodeBuilderFlags.WriteTypeArgumentsOfSignature) ?
2593-
callSignature.target.typeParameters : callSignature.typeParameters;
2594-
return typeParameters && typeParameters.length !== 0;
2595-
}
2596-
return false;
2597-
}
2598-
25992577
function createTypeQueryNodeFromSymbol(symbol: Symbol, symbolFlags: SymbolFlags) {
26002578
const entityName = symbolToName(symbol, context, symbolFlags, /*expectsIdentifier*/ false);
26012579
return createTypeQueryNode(entityName);
@@ -2615,15 +2593,13 @@ namespace ts {
26152593
return createTypeReferenceNode("Array", [typeArgumentNode]);
26162594
}
26172595

2618-
context.flags |= NodeBuilderFlags.InElementType;
26192596
const elementType = typeToTypeNodeHelper(typeArguments[0], context);
2620-
Debug.assert(!(context.flags & NodeBuilderFlags.InElementType));
2621-
26222597
return createArrayTypeNode(elementType);
26232598
}
26242599
else if (type.target.objectFlags & ObjectFlags.Tuple) {
26252600
if (typeArguments.length > 0) {
2626-
const tupleConstituentNodes = mapToTypeNodeArray(typeArguments.slice(0, getTypeReferenceArity(type)), context, /*addInElementTypeFlag*/ false, /*addInFirstTypeArgumentFlag*/ false);
2601+
const slice = typeArguments.slice(0, getTypeReferenceArity(type));
2602+
const tupleConstituentNodes = slice && mapToTypeNodeArray(slice, context);
26272603
if (tupleConstituentNodes && tupleConstituentNodes.length > 0) {
26282604
return createTupleTypeNode(tupleConstituentNodes);
26292605
}
@@ -2649,7 +2625,8 @@ namespace ts {
26492625
// When type parameters are their own type arguments for the whole group (i.e. we have
26502626
// the default outer type arguments), we don't show the group.
26512627
if (!rangeEquals(outerTypeParameters, typeArguments, start, i)) {
2652-
const typeArgumentNodes = createNodeArray(toTypeArgumentNodes(typeArguments.slice(start, i), context));
2628+
const slice = typeArguments.slice(start, i);
2629+
const typeArgumentNodes = slice && createNodeArray(mapToTypeNodeArray(slice, context));
26532630
const namePart = symbolToTypeReferenceName(parent);
26542631
(namePart.kind === SyntaxKind.Identifier ? <Identifier>namePart : namePart.right).typeArguments = typeArgumentNodes;
26552632

@@ -2680,7 +2657,7 @@ namespace ts {
26802657
if (some(typeArguments)) {
26812658
const typeParameterCount = (type.target.typeParameters || emptyArray).length;
26822659
const slice = typeArguments && typeArguments.slice(i, typeParameterCount);
2683-
typeArgumentNodes = toTypeArgumentNodes(slice, context);
2660+
typeArgumentNodes = slice && mapToTypeNodeArray(slice, context);
26842661
}
26852662

26862663
if (typeArgumentNodes) {
@@ -2763,28 +2740,17 @@ namespace ts {
27632740
}
27642741
}
27652742

2766-
function mapToTypeNodeArray(types: Type[], context: NodeBuilderContext, addInElementTypeFlag: boolean, addInFirstTypeArgumentFlag: boolean): TypeNode[] {
2743+
function mapToTypeNodeArray(types: Type[], context: NodeBuilderContext): TypeNode[] {
27672744
const result = [];
2768-
Debug.assert(!(context.flags & NodeBuilderFlags.InElementType), "should be unset at the beginning of the helper");
27692745
for (let i = 0; i < types.length; ++i) {
27702746
const type = types[i];
2771-
if (addInElementTypeFlag) {
2772-
context.flags |= NodeBuilderFlags.InElementType;
2773-
}
2774-
if (i === 0 && addInFirstTypeArgumentFlag) {
2775-
context.flags |= NodeBuilderFlags.InFirstTypeArgument;
2776-
}
27772747
const typeNode = typeToTypeNodeHelper(type, context);
27782748
if (typeNode) {
27792749
result.push(typeNode);
27802750
}
27812751
}
2782-
Debug.assert(!(context.flags & NodeBuilderFlags.InElementType), "should be unset at the end of the helper");
2783-
return result;
2784-
}
27852752

2786-
function toTypeArgumentNodes(typeArguments: Type[], context: NodeBuilderContext) {
2787-
return typeArguments && mapToTypeNodeArray(typeArguments, context, /*addInElementTypeFlag*/ false, /*addInFirstTypeArgumentFlag*/ true);
2753+
return result;
27882754
}
27892755

27902756
function indexInfoToIndexSignatureDeclarationHelper(indexInfo: IndexInfo, kind: IndexKind, context: NodeBuilderContext): IndexSignatureDeclaration {
@@ -2909,7 +2875,7 @@ namespace ts {
29092875
Debug.assert(chain && 0 <= index && index < chain.length);
29102876
const symbol = chain[index];
29112877
let typeParameterNodes: TypeNode[] | undefined;
2912-
if (index > 0) {
2878+
if (context.flags & NodeBuilderFlags.WriteTypeParametersInQualifiedName && index > 0) {
29132879
const parentSymbol = chain[index - 1];
29142880
let typeParameters: TypeParameter[];
29152881
if (getCheckFlags(symbol) & CheckFlags.Instantiated) {
@@ -2921,11 +2887,9 @@ namespace ts {
29212887
typeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol);
29222888
}
29232889
}
2890+
29242891
if (typeParameters && typeParameters.length > 0) {
2925-
if (!context.encounteredError && !(context.flags & NodeBuilderFlags.AllowTypeParameterInQualifiedName)) {
2926-
context.encounteredError = true;
2927-
}
2928-
typeParameterNodes = toTypeArgumentNodes(typeParameters, context);
2892+
typeParameterNodes = mapToTypeNodeArray(typeParameters, context);
29292893
}
29302894
}
29312895

Collapse file

‎src/compiler/factory.ts‎

Copy file name to clipboardExpand all lines: src/compiler/factory.ts
+22-7Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ namespace ts {
506506
export function createTypeReferenceNode(typeName: string | EntityName, typeArguments: TypeNode[] | undefined) {
507507
const node = createSynthesizedNode(SyntaxKind.TypeReference) as TypeReferenceNode;
508508
node.typeName = asName(typeName);
509-
node.typeArguments = asNodeArray(typeArguments);
509+
node.typeArguments = typeArguments && parenthesizeTypeParameters(typeArguments);
510510
return node;
511511
}
512512

@@ -559,7 +559,7 @@ namespace ts {
559559

560560
export function createArrayTypeNode(elementType: TypeNode) {
561561
const node = createSynthesizedNode(SyntaxKind.ArrayType) as ArrayTypeNode;
562-
node.elementType = elementType;
562+
node.elementType = parenthesizeElementTypeMember(elementType);
563563
return node;
564564
}
565565

@@ -599,7 +599,7 @@ namespace ts {
599599

600600
export function createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, types: TypeNode[]) {
601601
const node = createSynthesizedNode(kind) as UnionTypeNode | IntersectionTypeNode;
602-
node.types = createNodeArray(types);
602+
node.types = parenthesizeElementTypeMembers(types);
603603
return node;
604604
}
605605

@@ -628,7 +628,7 @@ namespace ts {
628628
export function createTypeOperatorNode(type: TypeNode) {
629629
const node = createSynthesizedNode(SyntaxKind.TypeOperator) as TypeOperatorNode;
630630
node.operator = SyntaxKind.KeyOfKeyword;
631-
node.type = type;
631+
node.type = parenthesizeElementTypeMember(type);
632632
return node;
633633
}
634634

@@ -638,7 +638,7 @@ namespace ts {
638638

639639
export function createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode) {
640640
const node = createSynthesizedNode(SyntaxKind.IndexedAccessType) as IndexedAccessTypeNode;
641-
node.objectType = objectType;
641+
node.objectType = parenthesizeElementTypeMember(objectType);
642642
node.indexType = indexType;
643643
return node;
644644
}
@@ -3595,19 +3595,34 @@ namespace ts {
35953595
return expression;
35963596
}
35973597

3598-
function parenthesizeElementTypeMember(member: TypeNode) {
3598+
export function parenthesizeElementTypeMember(member: TypeNode) {
35993599
switch (member.kind) {
36003600
case SyntaxKind.UnionType:
36013601
case SyntaxKind.IntersectionType:
36023602
case SyntaxKind.FunctionType:
36033603
case SyntaxKind.ConstructorType:
36043604
return createParenthesizedType(member);
36053605
}
3606+
return member;
36063607
}
3607-
function parenthesizeElementTypeMembers(members: NodeArray<TypeNode>) {
3608+
3609+
export function parenthesizeElementTypeMembers(members: TypeNode[]) {
3610+
// TODO: does this lose `originalNode` ptr?
36083611
return createNodeArray(members.map(parenthesizeElementTypeMember));
36093612
}
36103613

3614+
export function parenthesizeTypeParameters(typeParameters: TypeNode[]) {
3615+
if (typeParameters && typeParameters.length > 0) {
3616+
const nodeArray = createNodeArray(typeParameters);
3617+
const firstEntry = nodeArray[0];
3618+
if (isFunctionOrConstructor(firstEntry) && firstEntry.typeParameters) {
3619+
nodeArray[0] = createParenthesizedType(firstEntry);
3620+
}
3621+
3622+
return nodeArray;
3623+
}
3624+
}
3625+
36113626
/**
36123627
* Clones a series of not-emitted expressions with a new inner expression.
36133628
*
Collapse file

‎src/compiler/types.ts‎

Copy file name to clipboardExpand all lines: src/compiler/types.ts
+2-7Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2590,25 +2590,20 @@ namespace ts {
25902590
WriteTypeArgumentsOfSignature = 1 << 5, // Write the type arguments instead of type parameters of the signature
25912591
UseFullyQualifiedType = 1 << 6, // Write out the fully qualified type name (eg. Module.Type, instead of Type)
25922592
SuppressAnyReturnType = 1 << 8, // If the return type is any-like, don't offer a return type.
2593+
WriteTypeParametersInQualifiedName = 1 << 9,
25932594

25942595
// Error handling
25952596
AllowThisInObjectLiteral = 1 << 10,
25962597
AllowQualifedNameInPlaceOfIdentifier = 1 << 11,
2597-
AllowTypeParameterInQualifiedName = 1 << 12,
25982598
AllowAnonymousIdentifier = 1 << 13,
25992599
AllowEmptyUnionOrIntersection = 1 << 14,
26002600
AllowEmptyTuple = 1 << 15,
26012601

2602-
ignoreErrors = AllowThisInObjectLiteral | AllowQualifedNameInPlaceOfIdentifier | AllowTypeParameterInQualifiedName | AllowAnonymousIdentifier | AllowEmptyUnionOrIntersection | AllowEmptyTuple,
2602+
ignoreErrors = AllowThisInObjectLiteral | AllowQualifedNameInPlaceOfIdentifier | AllowAnonymousIdentifier | AllowEmptyUnionOrIntersection | AllowEmptyTuple,
26032603

26042604
// State
26052605
inObjectTypeLiteral = 1 << 20,
2606-
InElementType = 1 << 21, // Writing an array or union element type
2607-
InFirstTypeArgument = 1 << 22, // Writing first type argument of the instantiated type
26082606
InTypeAlias = 1 << 23, // Writing type in type alias declaration
2609-
2610-
/** Flags that should not be passed on to sub-nodes of the current node being built. */
2611-
StateClearingFlags = InElementType | InFirstTypeArgument | InTypeAlias
26122607
}
26132608

26142609
export interface SymbolDisplayBuilder {
Collapse file

‎src/compiler/utilities.ts‎

Copy file name to clipboardExpand all lines: src/compiler/utilities.ts
+10Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,16 @@ namespace ts {
881881
return false;
882882
}
883883

884+
export function isFunctionOrConstructor(node: Node): node is FunctionTypeNode | ConstructorTypeNode {
885+
switch (node.kind) {
886+
case SyntaxKind.FunctionType:
887+
case SyntaxKind.ConstructorType:
888+
return true;
889+
}
890+
891+
return false;
892+
}
893+
884894
export function introducesArgumentsExoticObject(node: Node) {
885895
switch (node.kind) {
886896
case SyntaxKind.MethodDeclaration:

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.