Skip to content

Commit ed4e2e6

Browse files
author
Andy
authored
Ensure that emitter calls callbacks (microsoft#18284)
* Ensure that emitter calls calbacks * Move new parameter to end of parameters * Fix for ConditionalExpression * Make suggested changes to emitter * Fix parameter ordering * Respond to minor comments * Remove potentially expensive assertion * More emitter cleanup
1 parent 8c64937 commit ed4e2e6

20 files changed

+325
-197
lines changed

src/compiler/emitter.ts

Lines changed: 63 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,14 @@ namespace ts {
406406
setWriter(/*output*/ undefined);
407407
}
408408

409+
// TODO: Should this just be `emit`?
410+
// See https://github.com/Microsoft/TypeScript/pull/18284#discussion_r137611034
411+
function emitIfPresent(node: Node | undefined) {
412+
if (node) {
413+
emit(node);
414+
}
415+
}
416+
409417
function emit(node: Node) {
410418
pipelineEmitWithNotification(EmitHint.Unspecified, node);
411419
}
@@ -451,6 +459,7 @@ namespace ts {
451459
case EmitHint.SourceFile: return pipelineEmitSourceFile(node);
452460
case EmitHint.IdentifierName: return pipelineEmitIdentifierName(node);
453461
case EmitHint.Expression: return pipelineEmitExpression(node);
462+
case EmitHint.MappedTypeParameter: return emitMappedTypeParameter(cast(node, isTypeParameterDeclaration));
454463
case EmitHint.Unspecified: return pipelineEmitUnspecified(node);
455464
}
456465
}
@@ -465,6 +474,12 @@ namespace ts {
465474
emitIdentifier(<Identifier>node);
466475
}
467476

477+
function emitMappedTypeParameter(node: TypeParameterDeclaration): void {
478+
emit(node.name);
479+
write(" in ");
480+
emit(node.constraint);
481+
}
482+
468483
function pipelineEmitUnspecified(node: Node): void {
469484
const kind = node.kind;
470485

@@ -898,9 +913,9 @@ namespace ts {
898913
function emitParameter(node: ParameterDeclaration) {
899914
emitDecorators(node, node.decorators);
900915
emitModifiers(node, node.modifiers);
901-
writeIfPresent(node.dotDotDotToken, "...");
916+
emitIfPresent(node.dotDotDotToken);
902917
emit(node.name);
903-
writeIfPresent(node.questionToken, "?");
918+
emitIfPresent(node.questionToken);
904919
emitWithPrefix(": ", node.type);
905920
emitExpressionWithPrefix(" = ", node.initializer);
906921
}
@@ -918,7 +933,7 @@ namespace ts {
918933
emitDecorators(node, node.decorators);
919934
emitModifiers(node, node.modifiers);
920935
emit(node.name);
921-
writeIfPresent(node.questionToken, "?");
936+
emitIfPresent(node.questionToken);
922937
emitWithPrefix(": ", node.type);
923938
write(";");
924939
}
@@ -927,7 +942,7 @@ namespace ts {
927942
emitDecorators(node, node.decorators);
928943
emitModifiers(node, node.modifiers);
929944
emit(node.name);
930-
writeIfPresent(node.questionToken, "?");
945+
emitIfPresent(node.questionToken);
931946
emitWithPrefix(": ", node.type);
932947
emitExpressionWithPrefix(" = ", node.initializer);
933948
write(";");
@@ -937,7 +952,7 @@ namespace ts {
937952
emitDecorators(node, node.decorators);
938953
emitModifiers(node, node.modifiers);
939954
emit(node.name);
940-
writeIfPresent(node.questionToken, "?");
955+
emitIfPresent(node.questionToken);
941956
emitTypeParameters(node, node.typeParameters);
942957
emitParameters(node, node.parameters);
943958
emitWithPrefix(": ", node.type);
@@ -947,9 +962,9 @@ namespace ts {
947962
function emitMethodDeclaration(node: MethodDeclaration) {
948963
emitDecorators(node, node.decorators);
949964
emitModifiers(node, node.modifiers);
950-
writeIfPresent(node.asteriskToken, "*");
965+
emitIfPresent(node.asteriskToken);
951966
emit(node.name);
952-
writeIfPresent(node.questionToken, "?");
967+
emitIfPresent(node.questionToken);
953968
emitSignatureAndBody(node, emitSignatureHead);
954969
}
955970

@@ -1035,10 +1050,8 @@ namespace ts {
10351050

10361051
function emitTypeLiteral(node: TypeLiteralNode) {
10371052
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-
}
1053+
const flags = getEmitFlags(node) & EmitFlags.SingleLine ? ListFormat.SingleLineTypeLiteralMembers : ListFormat.MultiLineTypeLiteralMembers;
1054+
emitList(node, node.members, flags | ListFormat.NoSpaceIfEmpty);
10421055
write("}");
10431056
}
10441057

@@ -1094,13 +1107,16 @@ namespace ts {
10941107
writeLine();
10951108
increaseIndent();
10961109
}
1097-
writeIfPresent(node.readonlyToken, "readonly ");
1110+
if (node.readonlyToken) {
1111+
emit(node.readonlyToken);
1112+
write(" ");
1113+
}
1114+
10981115
write("[");
1099-
emit(node.typeParameter.name);
1100-
write(" in ");
1101-
emit(node.typeParameter.constraint);
1116+
pipelineEmitWithNotification(EmitHint.MappedTypeParameter, node.typeParameter);
11021117
write("]");
1103-
writeIfPresent(node.questionToken, "?");
1118+
1119+
emitIfPresent(node.questionToken);
11041120
write(": ");
11051121
emit(node.type);
11061122
write(";");
@@ -1148,7 +1164,7 @@ namespace ts {
11481164

11491165
function emitBindingElement(node: BindingElement) {
11501166
emitWithSuffix(node.propertyName, ": ");
1151-
writeIfPresent(node.dotDotDotToken, "...");
1167+
emitIfPresent(node.dotDotDotToken);
11521168
emit(node.name);
11531169
emitExpressionWithPrefix(" = ", node.initializer);
11541170
}
@@ -1159,33 +1175,22 @@ namespace ts {
11591175

11601176
function emitArrayLiteralExpression(node: ArrayLiteralExpression) {
11611177
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-
}
1178+
const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None;
1179+
emitExpressionList(node, elements, ListFormat.ArrayLiteralExpressionElements | preferNewLine);
11691180
}
11701181

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

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);
1188+
const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None;
1189+
const allowTrailingComma = currentSourceFile.languageVersion >= ScriptTarget.ES5 ? ListFormat.AllowTrailingComma : ListFormat.None;
1190+
emitList(node, node.properties, ListFormat.ObjectLiteralExpressionProperties | allowTrailingComma | preferNewLine);
11851191

1186-
if (indentedFlag) {
1187-
decreaseIndent();
1188-
}
1192+
if (indentedFlag) {
1193+
decreaseIndent();
11891194
}
11901195
}
11911196

@@ -1286,7 +1291,8 @@ namespace ts {
12861291
emitTypeParameters(node, node.typeParameters);
12871292
emitParametersForArrow(node, node.parameters);
12881293
emitWithPrefix(": ", node.type);
1289-
write(" =>");
1294+
write(" ");
1295+
emit(node.equalsGreaterThanToken);
12901296
}
12911297

12921298
function emitDeleteExpression(node: DeleteExpression) {
@@ -1364,13 +1370,13 @@ namespace ts {
13641370

13651371
emitExpression(node.condition);
13661372
increaseIndentIf(indentBeforeQuestion, " ");
1367-
write("?");
1373+
emit(node.questionToken);
13681374
increaseIndentIf(indentAfterQuestion, " ");
13691375
emitExpression(node.whenTrue);
13701376
decreaseIndentIf(indentBeforeQuestion, indentAfterQuestion);
13711377

13721378
increaseIndentIf(indentBeforeColon, " ");
1373-
write(":");
1379+
emit(node.colonToken);
13741380
increaseIndentIf(indentAfterColon, " ");
13751381
emitExpression(node.whenFalse);
13761382
decreaseIndentIf(indentBeforeColon, indentAfterColon);
@@ -1382,7 +1388,8 @@ namespace ts {
13821388
}
13831389

13841390
function emitYieldExpression(node: YieldExpression) {
1385-
write(node.asteriskToken ? "yield*" : "yield");
1391+
write("yield");
1392+
emit(node.asteriskToken);
13861393
emitExpressionWithPrefix(" ", node.expression);
13871394
}
13881395

@@ -1662,7 +1669,9 @@ namespace ts {
16621669
function emitFunctionDeclarationOrExpression(node: FunctionDeclaration | FunctionExpression) {
16631670
emitDecorators(node, node.decorators);
16641671
emitModifiers(node, node.modifiers);
1665-
write(node.asteriskToken ? "function* " : "function ");
1672+
write("function");
1673+
emitIfPresent(node.asteriskToken);
1674+
write(" ");
16661675
emitIdentifierName(node.name);
16671676
emitSignatureAndBody(node, emitSignatureHead);
16681677
}
@@ -2068,9 +2077,7 @@ namespace ts {
20682077
function emitJsxExpression(node: JsxExpression) {
20692078
if (node.expression) {
20702079
write("{");
2071-
if (node.dotDotDotToken) {
2072-
write("...");
2073-
}
2080+
emitIfPresent(node.dotDotDotToken);
20742081
emitExpression(node.expression);
20752082
write("}");
20762083
}
@@ -2128,13 +2135,12 @@ namespace ts {
21282135
emitTrailingCommentsOfPosition(statements.pos);
21292136
}
21302137

2138+
let format = ListFormat.CaseOrDefaultClauseStatements;
21312139
if (emitAsSingleStatement) {
21322140
write(" ");
2133-
emit(statements[0]);
2134-
}
2135-
else {
2136-
emitList(parentNode, statements, ListFormat.CaseOrDefaultClauseStatements);
2141+
format &= ~(ListFormat.MultiLine | ListFormat.Indented);
21372142
}
2143+
emitList(parentNode, statements, format);
21382144
}
21392145

21402146
function emitHeritageClause(node: HeritageClause) {
@@ -2384,7 +2390,7 @@ namespace ts {
23842390

23852391
function emitParametersForArrow(parentNode: FunctionTypeNode | ArrowFunction, parameters: NodeArray<ParameterDeclaration>) {
23862392
if (canEmitSimpleArrowHead(parentNode, parameters)) {
2387-
emit(parameters[0]);
2393+
emitList(parentNode, parameters, ListFormat.Parameters & ~ListFormat.Parenthesis);
23882394
}
23892395
else {
23902396
emitParameters(parentNode, parameters);
@@ -2427,7 +2433,7 @@ namespace ts {
24272433
if (format & ListFormat.MultiLine) {
24282434
writeLine();
24292435
}
2430-
else if (format & ListFormat.SpaceBetweenBraces) {
2436+
else if (format & ListFormat.SpaceBetweenBraces && !(format & ListFormat.NoSpaceIfEmpty)) {
24312437
write(" ");
24322438
}
24332439
}
@@ -2568,12 +2574,6 @@ namespace ts {
25682574
}
25692575
}
25702576

2571-
function writeIfPresent(node: Node, text: string) {
2572-
if (node) {
2573-
write(text);
2574-
}
2575-
}
2576-
25772577
function writeToken(token: SyntaxKind, pos: number, contextNode?: Node) {
25782578
return onEmitSourceMapOfToken
25792579
? onEmitSourceMapOfToken(contextNode, token, pos, writeTokenText)
@@ -2584,7 +2584,7 @@ namespace ts {
25842584
if (onBeforeEmitToken) {
25852585
onBeforeEmitToken(node);
25862586
}
2587-
writeTokenText(node.kind);
2587+
write(tokenToString(node.kind));
25882588
if (onAfterEmitToken) {
25892589
onAfterEmitToken(node);
25902590
}
@@ -3107,6 +3107,9 @@ namespace ts {
31073107
NoTrailingNewLine = 1 << 16, // Do not emit a trailing NewLine for a MultiLine list.
31083108
NoInterveningComments = 1 << 17, // Do not emit comments between each node
31093109

3110+
NoSpaceIfEmpty = 1 << 18, // If the literal is empty, do not add spaces between braces.
3111+
SingleElement = 1 << 19,
3112+
31103113
// Precomputed Formats
31113114
Modifiers = SingleLine | SpaceBetweenSiblings | NoInterveningComments,
31123115
HeritageClauses = SingleLine | SpaceBetweenSiblings,
@@ -3118,7 +3121,7 @@ namespace ts {
31183121
IntersectionTypeConstituents = AmpersandDelimited | SpaceBetweenSiblings | SingleLine,
31193122
ObjectBindingPatternElements = SingleLine | AllowTrailingComma | SpaceBetweenBraces | CommaDelimited | SpaceBetweenSiblings,
31203123
ArrayBindingPatternElements = SingleLine | AllowTrailingComma | CommaDelimited | SpaceBetweenSiblings,
3121-
ObjectLiteralExpressionProperties = PreserveLines | CommaDelimited | SpaceBetweenSiblings | SpaceBetweenBraces | Indented | Braces,
3124+
ObjectLiteralExpressionProperties = PreserveLines | CommaDelimited | SpaceBetweenSiblings | SpaceBetweenBraces | Indented | Braces | NoSpaceIfEmpty,
31223125
ArrayLiteralExpressionElements = PreserveLines | CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | Indented | SquareBrackets,
31233126
CommaListElements = CommaDelimited | SpaceBetweenSiblings | SingleLine,
31243127
CallExpressionArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis,

0 commit comments

Comments
 (0)