Skip to content

Commit 9815359

Browse files
author
Andy Hanson
committed
Ensure that emitter calls calbacks
1 parent d790f1d commit 9815359

File tree

12 files changed

+162
-75
lines changed

12 files changed

+162
-75
lines changed

src/compiler/emitter.ts

Lines changed: 64 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,10 +1035,8 @@ namespace ts {
10351035

10361036
function emitTypeLiteral(node: TypeLiteralNode) {
10371037
write("{");
1038-
// If the literal is empty, do not add spaces between braces.
1039-
if (node.members.length > 0) {
1040-
emitList(node, node.members, getEmitFlags(node) & EmitFlags.SingleLine ? ListFormat.SingleLineTypeLiteralMembers : ListFormat.MultiLineTypeLiteralMembers);
1041-
}
1038+
const flags = getEmitFlags(node) & EmitFlags.SingleLine ? ListFormat.SingleLineTypeLiteralMembers : ListFormat.MultiLineTypeLiteralMembers;
1039+
emitList(node, node.members, flags | ListFormat.NoSpaceIfEmpty);
10421040
write("}");
10431041
}
10441042

@@ -1095,11 +1093,14 @@ namespace ts {
10951093
increaseIndent();
10961094
}
10971095
writeIfPresent(node.readonlyToken, "readonly ");
1098-
write("[");
1099-
emit(node.typeParameter.name);
1100-
write(" in ");
1101-
emit(node.typeParameter.constraint);
1102-
write("]");
1096+
1097+
if (onEmitNode) {
1098+
onEmitNode(EmitHint.Unspecified, node.typeParameter, emitMappedTypeParameter);
1099+
}
1100+
else {
1101+
emitMappedTypeParameter(EmitHint.Unspecified, node.typeParameter);
1102+
}
1103+
11031104
writeIfPresent(node.questionToken, "?");
11041105
write(": ");
11051106
emit(node.type);
@@ -1114,6 +1115,14 @@ namespace ts {
11141115
write("}");
11151116
}
11161117

1118+
function emitMappedTypeParameter(_hint: EmitHint, node: TypeParameterDeclaration) {
1119+
write("[");
1120+
emit(node.name);
1121+
write(" in ");
1122+
emit(node.constraint);
1123+
write("]");
1124+
}
1125+
11171126
function emitLiteralType(node: LiteralTypeNode) {
11181127
emitExpression(node.literal);
11191128
}
@@ -1159,33 +1168,22 @@ namespace ts {
11591168

11601169
function emitArrayLiteralExpression(node: ArrayLiteralExpression) {
11611170
const elements = node.elements;
1162-
if (elements.length === 0) {
1163-
write("[]");
1164-
}
1165-
else {
1166-
const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None;
1167-
emitExpressionList(node, elements, ListFormat.ArrayLiteralExpressionElements | preferNewLine);
1168-
}
1171+
const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None;
1172+
emitExpressionList(node, elements, ListFormat.ArrayLiteralExpressionElements | preferNewLine);
11691173
}
11701174

11711175
function emitObjectLiteralExpression(node: ObjectLiteralExpression) {
1172-
const properties = node.properties;
1173-
if (properties.length === 0) {
1174-
write("{}");
1176+
const indentedFlag = getEmitFlags(node) & EmitFlags.Indented;
1177+
if (indentedFlag) {
1178+
increaseIndent();
11751179
}
1176-
else {
1177-
const indentedFlag = getEmitFlags(node) & EmitFlags.Indented;
1178-
if (indentedFlag) {
1179-
increaseIndent();
1180-
}
11811180

1182-
const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None;
1183-
const allowTrailingComma = currentSourceFile.languageVersion >= ScriptTarget.ES5 ? ListFormat.AllowTrailingComma : ListFormat.None;
1184-
emitList(node, properties, ListFormat.ObjectLiteralExpressionProperties | allowTrailingComma | preferNewLine);
1181+
const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None;
1182+
const allowTrailingComma = currentSourceFile.languageVersion >= ScriptTarget.ES5 ? ListFormat.AllowTrailingComma : ListFormat.None;
1183+
emitList(node, node.properties, ListFormat.ObjectLiteralExpressionProperties | allowTrailingComma | preferNewLine);
11851184

1186-
if (indentedFlag) {
1187-
decreaseIndent();
1188-
}
1185+
if (indentedFlag) {
1186+
decreaseIndent();
11891187
}
11901188
}
11911189

@@ -1286,7 +1284,8 @@ namespace ts {
12861284
emitTypeParameters(node, node.typeParameters);
12871285
emitParametersForArrow(node, node.parameters);
12881286
emitWithPrefix(": ", node.type);
1289-
write(" =>");
1287+
write(" ");
1288+
emit(node.equalsGreaterThanToken);
12901289
}
12911290

12921291
function emitDeleteExpression(node: DeleteExpression) {
@@ -1382,7 +1381,10 @@ namespace ts {
13821381
}
13831382

13841383
function emitYieldExpression(node: YieldExpression) {
1385-
write(node.asteriskToken ? "yield*" : "yield");
1384+
write("yield");
1385+
if (node.asteriskToken) {
1386+
emit(node.asteriskToken);
1387+
}
13861388
emitExpressionWithPrefix(" ", node.expression);
13871389
}
13881390

@@ -1662,7 +1664,11 @@ namespace ts {
16621664
function emitFunctionDeclarationOrExpression(node: FunctionDeclaration | FunctionExpression) {
16631665
emitDecorators(node, node.decorators);
16641666
emitModifiers(node, node.modifiers);
1665-
write(node.asteriskToken ? "function* " : "function ");
1667+
write("function");
1668+
if (node.asteriskToken) {
1669+
emit(node.asteriskToken);
1670+
}
1671+
write(" ");
16661672
emitIdentifierName(node.name);
16671673
emitSignatureAndBody(node, emitSignatureHead);
16681674
}
@@ -2068,9 +2074,7 @@ namespace ts {
20682074
function emitJsxExpression(node: JsxExpression) {
20692075
if (node.expression) {
20702076
write("{");
2071-
if (node.dotDotDotToken) {
2072-
write("...");
2073-
}
2077+
writeIfPresent(node.dotDotDotToken, "...");
20742078
emitExpression(node.expression);
20752079
write("}");
20762080
}
@@ -2130,7 +2134,7 @@ namespace ts {
21302134

21312135
if (emitAsSingleStatement) {
21322136
write(" ");
2133-
emit(statements[0]);
2137+
emitSingleElementList(statements);
21342138
}
21352139
else {
21362140
emitList(parentNode, statements, ListFormat.CaseOrDefaultClauseStatements);
@@ -2384,7 +2388,7 @@ namespace ts {
23842388

23852389
function emitParametersForArrow(parentNode: FunctionTypeNode | ArrowFunction, parameters: NodeArray<ParameterDeclaration>) {
23862390
if (canEmitSimpleArrowHead(parentNode, parameters)) {
2387-
emit(parameters[0]);
2391+
emitSingleElementList(parameters);
23882392
}
23892393
else {
23902394
emitParameters(parentNode, parameters);
@@ -2395,6 +2399,17 @@ namespace ts {
23952399
emitList(parentNode, parameters, ListFormat.IndexSignatureParameters);
23962400
}
23972401

2402+
function emitSingleElementList(list: NodeArray<Node>) {
2403+
Debug.assert(list.length === 1);
2404+
if (onBeforeEmitNodeArray) {
2405+
onBeforeEmitNodeArray(list);
2406+
}
2407+
emit(list[0]);
2408+
if (onAfterEmitNodeArray) {
2409+
onAfterEmitNodeArray(list);
2410+
}
2411+
}
2412+
23982413
function emitList(parentNode: Node, children: NodeArray<Node>, format: ListFormat, start?: number, count?: number) {
23992414
emitNodeList(emit, parentNode, children, format, start, count);
24002415
}
@@ -2427,7 +2442,7 @@ namespace ts {
24272442
if (format & ListFormat.MultiLine) {
24282443
writeLine();
24292444
}
2430-
else if (format & ListFormat.SpaceBetweenBraces) {
2445+
else if (format & ListFormat.SpaceBetweenBraces && !(format & ListFormat.NoSpaceIfEmpty)) {
24312446
write(" ");
24322447
}
24332448
}
@@ -2570,7 +2585,7 @@ namespace ts {
25702585

25712586
function writeIfPresent(node: Node, text: string) {
25722587
if (node) {
2573-
write(text);
2588+
writeTokenAndCallCallbacks(node, text);
25742589
}
25752590
}
25762591

@@ -2580,16 +2595,20 @@ namespace ts {
25802595
: writeTokenText(token, pos);
25812596
}
25822597

2583-
function writeTokenNode(node: Node) {
2598+
function writeTokenAndCallCallbacks(node: Node, text: string) {
25842599
if (onBeforeEmitToken) {
25852600
onBeforeEmitToken(node);
25862601
}
2587-
writeTokenText(node.kind);
2602+
write(text);
25882603
if (onAfterEmitToken) {
25892604
onAfterEmitToken(node);
25902605
}
25912606
}
25922607

2608+
function writeTokenNode(node: Node) {
2609+
writeTokenAndCallCallbacks(node, tokenToString(node.kind));
2610+
}
2611+
25932612
function writeTokenText(token: SyntaxKind, pos?: number) {
25942613
const tokenString = tokenToString(token);
25952614
write(tokenString);
@@ -3107,6 +3126,8 @@ namespace ts {
31073126
NoTrailingNewLine = 1 << 16, // Do not emit a trailing NewLine for a MultiLine list.
31083127
NoInterveningComments = 1 << 17, // Do not emit comments between each node
31093128

3129+
NoSpaceIfEmpty = 1 << 18, // If the literal is empty, do not add spaces between braces.
3130+
31103131
// Precomputed Formats
31113132
Modifiers = SingleLine | SpaceBetweenSiblings | NoInterveningComments,
31123133
HeritageClauses = SingleLine | SpaceBetweenSiblings,
@@ -3118,7 +3139,7 @@ namespace ts {
31183139
IntersectionTypeConstituents = AmpersandDelimited | SpaceBetweenSiblings | SingleLine,
31193140
ObjectBindingPatternElements = SingleLine | AllowTrailingComma | SpaceBetweenBraces | CommaDelimited | SpaceBetweenSiblings,
31203141
ArrayBindingPatternElements = SingleLine | AllowTrailingComma | CommaDelimited | SpaceBetweenSiblings,
3121-
ObjectLiteralExpressionProperties = PreserveLines | CommaDelimited | SpaceBetweenSiblings | SpaceBetweenBraces | Indented | Braces,
3142+
ObjectLiteralExpressionProperties = PreserveLines | CommaDelimited | SpaceBetweenSiblings | SpaceBetweenBraces | Indented | Braces | NoSpaceIfEmpty,
31223143
ArrayLiteralExpressionElements = PreserveLines | CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | Indented | SquareBrackets,
31233144
CommaListElements = CommaDelimited | SpaceBetweenSiblings | SingleLine,
31243145
CallExpressionArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis,

src/compiler/factory.ts

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ namespace ts {
281281
|| node.questionToken !== questionToken
282282
|| node.type !== type
283283
|| node.initializer !== initializer
284-
? updateNode(createParameter(decorators, modifiers, dotDotDotToken, name, node.questionToken, type, initializer), node)
284+
? updateNode(createParameter(decorators, modifiers, dotDotDotToken, name, questionToken, type, initializer), node)
285285
: node;
286286
}
287287

@@ -1016,19 +1016,48 @@ namespace ts {
10161016
return node;
10171017
}
10181018

1019+
/* @deprecated */ export function updateArrowFunction(
1020+
node: ArrowFunction,
1021+
modifiers: ReadonlyArray<Modifier> | undefined,
1022+
typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined,
1023+
parameters: ReadonlyArray<ParameterDeclaration>,
1024+
type: TypeNode | undefined,
1025+
body: ConciseBody): ArrowFunction;
10191026
export function updateArrowFunction(
10201027
node: ArrowFunction,
10211028
modifiers: ReadonlyArray<Modifier> | undefined,
10221029
typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined,
10231030
parameters: ReadonlyArray<ParameterDeclaration>,
10241031
type: TypeNode | undefined,
1025-
body: ConciseBody) {
1032+
equalsGreaterThanToken: Token<SyntaxKind.EqualsGreaterThanToken>,
1033+
body: ConciseBody): ArrowFunction;
1034+
export function updateArrowFunction(
1035+
node: ArrowFunction,
1036+
modifiers: ReadonlyArray<Modifier> | undefined,
1037+
typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined,
1038+
parameters: ReadonlyArray<ParameterDeclaration>,
1039+
type: TypeNode | undefined,
1040+
equalsGreaterThanTokenOrBody: Token<SyntaxKind.EqualsGreaterThanToken> | ConciseBody,
1041+
bodyOrUndefined?: ConciseBody): ArrowFunction {
1042+
let equalsGreaterThanToken: Token<SyntaxKind.EqualsGreaterThanToken>;
1043+
let body: ConciseBody;
1044+
if (bodyOrUndefined === undefined) {
1045+
equalsGreaterThanToken = node.equalsGreaterThanToken;
1046+
body = cast(equalsGreaterThanTokenOrBody, isConciseBody);
1047+
}
1048+
else {
1049+
equalsGreaterThanToken = cast(equalsGreaterThanTokenOrBody, (n): n is Token<SyntaxKind.EqualsGreaterThanToken> =>
1050+
n.kind === SyntaxKind.EqualsGreaterThanToken);
1051+
body = bodyOrUndefined;
1052+
}
1053+
10261054
return node.modifiers !== modifiers
10271055
|| node.typeParameters !== typeParameters
10281056
|| node.parameters !== parameters
10291057
|| node.type !== type
1058+
|| node.equalsGreaterThanToken !== equalsGreaterThanToken
10301059
|| node.body !== body
1031-
? updateNode(createArrowFunction(modifiers, typeParameters, parameters, type, node.equalsGreaterThanToken, body), node)
1060+
? updateNode(createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body), node)
10321061
: node;
10331062
}
10341063

src/compiler/transformers/es2017.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ namespace ts {
197197
/*typeParameters*/ undefined,
198198
visitParameterList(node.parameters, visitor, context),
199199
/*type*/ undefined,
200+
node.equalsGreaterThanToken,
200201
getFunctionFlags(node) & FunctionFlags.Async
201202
? transformAsyncFunctionBody(node)
202203
: visitFunctionBody(node.body, visitor, context)

src/compiler/transformers/esnext.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,7 @@ namespace ts {
595595
/*typeParameters*/ undefined,
596596
visitParameterList(node.parameters, visitor, context),
597597
/*type*/ undefined,
598+
node.equalsGreaterThanToken,
598599
transformFunctionBody(node)
599600
);
600601
enclosingFunctionFlags = savedEnclosingFunctionFlags;

src/compiler/transformers/ts.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2291,6 +2291,7 @@ namespace ts {
22912291
/*typeParameters*/ undefined,
22922292
visitParameterList(node.parameters, visitor, context),
22932293
/*type*/ undefined,
2294+
node.equalsGreaterThanToken,
22942295
visitFunctionBody(node.body, visitor, context)
22952296
);
22962297
return updated;

src/compiler/utilities.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4666,8 +4666,12 @@ namespace ts {
46664666

46674667
/* @internal */
46684668
export function isNodeArray<T extends Node>(array: ReadonlyArray<T>): array is NodeArray<T> {
4669-
return array.hasOwnProperty("pos")
4670-
&& array.hasOwnProperty("end");
4669+
const res = array.hasOwnProperty("pos") && array.hasOwnProperty("end");
4670+
if (res) {
4671+
const { pos, end } = array as NodeArray<T>;
4672+
Debug.assert(typeof pos === "number" && typeof end === "number");
4673+
}
4674+
return res;
46714675
}
46724676

46734677
// Literals

src/compiler/visitor.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,7 @@ namespace ts {
488488
nodesVisitor((<ArrowFunction>node).typeParameters, visitor, isTypeParameterDeclaration),
489489
visitParameterList((<ArrowFunction>node).parameters, visitor, context, nodesVisitor),
490490
visitNode((<ArrowFunction>node).type, visitor, isTypeNode),
491+
visitNode((<ArrowFunction>node).equalsGreaterThanToken, visitor, n => n.kind === SyntaxKind.EqualsGreaterThanToken),
491492
visitFunctionBody((<ArrowFunction>node).body, visitor, context));
492493

493494
case SyntaxKind.DeleteExpression:

src/services/formatting/formatting.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,7 @@ namespace ts.formatting {
728728
parent: Node,
729729
parentStartLine: number,
730730
parentDynamicIndentation: DynamicIndentation): void {
731+
Debug.assert(isNodeArray(nodes));
731732

732733
const listStartToken = getOpenTokenForList(parent, nodes);
733734
const listEndToken = getCloseTokenForOpenToken(listStartToken);

src/services/refactors/extractMethod.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -656,11 +656,13 @@ namespace ts.refactor.extractMethod {
656656
const typeParametersAndDeclarations = arrayFrom(typeParameterUsages.values()).map(type => ({ type, declaration: getFirstDeclaration(type) }));
657657
const sortedTypeParametersAndDeclarations = typeParametersAndDeclarations.sort(compareTypesByDeclarationOrder);
658658

659-
const typeParameters: ReadonlyArray<TypeParameterDeclaration> = sortedTypeParametersAndDeclarations.map(t => t.declaration as TypeParameterDeclaration);
659+
const typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined = sortedTypeParametersAndDeclarations.length === 0
660+
? undefined
661+
: sortedTypeParametersAndDeclarations.map(t => t.declaration as TypeParameterDeclaration);
660662

661663
// Strictly speaking, we should check whether each name actually binds to the appropriate type
662664
// parameter. In cases of shadowing, they may not.
663-
const callTypeArguments: ReadonlyArray<TypeNode> | undefined = typeParameters.length > 0
665+
const callTypeArguments: ReadonlyArray<TypeNode> | undefined = typeParameters !== undefined
664666
? typeParameters.map(decl => createTypeReferenceNode(decl.name, /*typeArguments*/ undefined))
665667
: undefined;
666668

0 commit comments

Comments
 (0)