Skip to content

Commit d3b8d5e

Browse files
committed
Refactor emit substitution into transform
1 parent 60a6240 commit d3b8d5e

27 files changed

+5569
-4052
lines changed

src/compiler/debug.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,14 @@ namespace ts {
275275
}
276276
}
277277

278+
/**
279+
* Asserts a value has the specified type in typespace only (does not perform a runtime assertion).
280+
* This is useful in cases where we switch on `node.kind` and can be reasonably sure the type is accurate, and
281+
* as a result can reduce the number of unnecessary casts.
282+
*/
283+
export function type<T>(value: unknown): asserts value is T;
284+
export function type(_value: unknown) { }
285+
278286
export function getFunctionName(func: AnyFunction) {
279287
if (typeof func !== "function") {
280288
return "";

src/compiler/emitter.ts

Lines changed: 4590 additions & 3454 deletions
Large diffs are not rendered by default.

src/compiler/factory/nodeTests.ts

Lines changed: 83 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,51 +39,114 @@ namespace ts {
3939
return node.kind === SyntaxKind.TemplateTail;
4040
}
4141

42+
// Punctuation
43+
44+
export function isDotDotDotToken(node: Node): node is DotDotDotToken {
45+
return node.kind === SyntaxKind.DotDotDotToken;
46+
}
47+
48+
/*@internal*/
49+
export function isCommaToken(node: Node): node is Token<SyntaxKind.CommaToken> {
50+
return node.kind === SyntaxKind.CommaToken;
51+
}
52+
53+
export function isPlusToken(node: Node): node is PlusToken {
54+
return node.kind === SyntaxKind.PlusToken;
55+
}
56+
57+
export function isMinusToken(node: Node): node is MinusToken {
58+
return node.kind === SyntaxKind.MinusToken;
59+
}
60+
61+
export function isAsteriskToken(node: Node): node is AsteriskToken {
62+
return node.kind === SyntaxKind.AsteriskToken;
63+
}
64+
65+
/*@internal*/
66+
export function isExclamationToken(node: Node): node is ExclamationToken {
67+
return node.kind === SyntaxKind.ExclamationToken;
68+
}
69+
70+
/*@internal*/
71+
export function isQuestionToken(node: Node): node is QuestionToken {
72+
return node.kind === SyntaxKind.QuestionToken;
73+
}
74+
75+
/*@internal*/
76+
export function isColonToken(node: Node): node is ColonToken {
77+
return node.kind === SyntaxKind.ColonToken;
78+
}
79+
80+
/*@internal*/
81+
export function isQuestionDotToken(node: Node): node is QuestionDotToken {
82+
return node.kind === SyntaxKind.QuestionDotToken;
83+
}
84+
85+
/*@internal*/
86+
export function isEqualsGreaterThanToken(node: Node): node is EqualsGreaterThanToken {
87+
return node.kind === SyntaxKind.EqualsGreaterThanToken;
88+
}
89+
4290
// Identifiers
4391

4492
export function isIdentifier(node: Node): node is Identifier {
4593
return node.kind === SyntaxKind.Identifier;
4694
}
4795

48-
// Names
96+
export function isPrivateIdentifier(node: Node): node is PrivateIdentifier {
97+
return node.kind === SyntaxKind.PrivateIdentifier;
98+
}
4999

50-
export function isQualifiedName(node: Node): node is QualifiedName {
51-
return node.kind === SyntaxKind.QualifiedName;
100+
// Reserved Words
101+
102+
/* @internal */
103+
export function isExportModifier(node: Node): node is ExportKeyword {
104+
return node.kind === SyntaxKind.ExportKeyword;
52105
}
53106

54-
export function isComputedPropertyName(node: Node): node is ComputedPropertyName {
55-
return node.kind === SyntaxKind.ComputedPropertyName;
107+
/* @internal */
108+
export function isAsyncModifier(node: Node): node is AsyncKeyword {
109+
return node.kind === SyntaxKind.AsyncKeyword;
56110
}
57111

58-
export function isPrivateIdentifier(node: Node): node is PrivateIdentifier {
59-
return node.kind === SyntaxKind.PrivateIdentifier;
112+
/* @internal */
113+
export function isAssertsKeyword(node: Node): node is AssertsKeyword {
114+
return node.kind === SyntaxKind.AssertsKeyword;
115+
}
116+
117+
/* @internal */
118+
export function isAwaitKeyword(node: Node): node is AwaitKeyword {
119+
return node.kind === SyntaxKind.AwaitKeyword;
60120
}
61121

62-
// Tokens
122+
/* @internal */
123+
export function isReadonlyKeyword(node: Node): node is ReadonlyKeyword {
124+
return node.kind === SyntaxKind.ReadonlyKeyword;
125+
}
126+
127+
/* @internal */
128+
export function isStaticModifier(node: Node): node is StaticKeyword {
129+
return node.kind === SyntaxKind.StaticKeyword;
130+
}
63131

64132
/*@internal*/
65-
export function isSuperKeyword(node: Node): node is Token<SyntaxKind.SuperKeyword> {
133+
export function isSuperKeyword(node: Node): node is SuperExpression {
66134
return node.kind === SyntaxKind.SuperKeyword;
67135
}
68136

69137
/*@internal*/
70-
export function isImportKeyword(node: Node): node is Token<SyntaxKind.ImportKeyword> {
138+
export function isImportKeyword(node: Node): node is ImportExpression {
71139
return node.kind === SyntaxKind.ImportKeyword;
72140
}
73141

74-
/*@internal*/
75-
export function isCommaToken(node: Node): node is Token<SyntaxKind.CommaToken> {
76-
return node.kind === SyntaxKind.CommaToken;
77-
}
142+
// Names
78143

79-
/*@internal*/
80-
export function isQuestionToken(node: Node): node is Token<SyntaxKind.QuestionToken> {
81-
return node.kind === SyntaxKind.QuestionToken;
144+
export function isQualifiedName(node: Node): node is QualifiedName {
145+
return node.kind === SyntaxKind.QualifiedName;
82146
}
83147

84-
/*@internal*/
85-
export function isExclamationToken(node: Node): node is Token<SyntaxKind.ExclamationToken> {
86-
return node.kind === SyntaxKind.ExclamationToken;
148+
export function isComputedPropertyName(node: Node): node is ComputedPropertyName {
149+
return node.kind === SyntaxKind.ComputedPropertyName;
87150
}
88151

89152
// Signature elements

src/compiler/factory/utilities.ts

Lines changed: 111 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace ts {
1313
}
1414
else {
1515
const expression = setTextRange(
16-
isIdentifierOrPrivateIdentifier(memberName)
16+
isMemberName(memberName)
1717
? factory.createPropertyAccessExpression(target, memberName)
1818
: factory.createElementAccessExpression(target, memberName),
1919
memberName
@@ -412,7 +412,7 @@ namespace ts {
412412
const helperNames: string[] = [];
413413
for (const helper of helpers) {
414414
if (!helper.scoped) {
415-
const importName = (helper as UnscopedEmitHelper).importName;
415+
const importName = helper.importName;
416416
if (importName) {
417417
pushIfUnique(helperNames, importName);
418418
}
@@ -815,18 +815,118 @@ namespace ts {
815815
|| kind === SyntaxKind.ExportDeclaration;
816816
}
817817

818-
/* @internal */
819-
export function isExportModifier(node: Modifier): node is ExportKeyword {
820-
return node.kind === SyntaxKind.ExportKeyword;
818+
export const isTypeNodeOrTypeParameterDeclaration = or(isTypeNode, isTypeParameterDeclaration) as (node: Node) => node is TypeNode | TypeParameterDeclaration;
819+
export const isQuestionOrExclamationToken = or(isQuestionToken, isExclamationToken) as (node: Node) => node is QuestionToken | ExclamationToken;
820+
export const isIdentifierOrThisTypeNode = or(isIdentifier, isThisTypeNode) as (node: Node) => node is Identifier | ThisTypeNode;
821+
export const isReadonlyKeywordOrPlusOrMinusToken = or(isReadonlyKeyword, isPlusToken, isMinusToken) as (node: Node) => node is ReadonlyKeyword | PlusToken | MinusToken;
822+
export const isQuestionOrPlusOrMinusToken = or(isQuestionToken, isPlusToken, isMinusToken) as (node: Node) => node is QuestionToken | PlusToken | MinusToken;
823+
export const isModuleName = or(isIdentifier, isStringLiteral) as (node: Node) => node is ModuleName;
824+
825+
export function isLiteralTypeLikeExpression(node: Node): node is NullLiteral | BooleanLiteral | LiteralExpression | PrefixUnaryExpression {
826+
const kind = node.kind;
827+
return kind === SyntaxKind.NullKeyword
828+
|| kind === SyntaxKind.TrueKeyword
829+
|| kind === SyntaxKind.FalseKeyword
830+
|| isLiteralExpression(node)
831+
|| isPrefixUnaryExpression(node);
821832
}
822833

823-
/* @internal */
824-
export function isAsyncModifier(node: Modifier): node is AsyncKeyword {
825-
return node.kind === SyntaxKind.AsyncKeyword;
834+
function isExponentiationOperator(kind: SyntaxKind): kind is ExponentiationOperator {
835+
return kind === SyntaxKind.AsteriskAsteriskToken;
826836
}
827837

828-
/* @internal */
829-
export function isStaticModifier(node: Modifier): node is StaticKeyword {
830-
return node.kind === SyntaxKind.StaticKeyword;
838+
function isMultiplicativeOperator(kind: SyntaxKind): kind is MultiplicativeOperator {
839+
return kind === SyntaxKind.AsteriskToken
840+
|| kind === SyntaxKind.SlashToken
841+
|| kind === SyntaxKind.PercentToken;
842+
}
843+
844+
function isMultiplicativeOperatorOrHigher(kind: SyntaxKind): kind is MultiplicativeOperatorOrHigher {
845+
return isExponentiationOperator(kind)
846+
|| isMultiplicativeOperator(kind);
847+
}
848+
849+
function isAdditiveOperator(kind: SyntaxKind): kind is AdditiveOperator {
850+
return kind === SyntaxKind.PlusToken
851+
|| kind === SyntaxKind.MinusToken;
852+
}
853+
854+
function isAdditiveOperatorOrHigher(kind: SyntaxKind): kind is AdditiveOperatorOrHigher {
855+
return isAdditiveOperator(kind)
856+
|| isMultiplicativeOperatorOrHigher(kind);
857+
}
858+
859+
function isShiftOperator(kind: SyntaxKind): kind is ShiftOperator {
860+
return kind === SyntaxKind.LessThanLessThanToken
861+
|| kind === SyntaxKind.GreaterThanGreaterThanToken
862+
|| kind === SyntaxKind.GreaterThanGreaterThanGreaterThanToken;
863+
}
864+
865+
function isShiftOperatorOrHigher(kind: SyntaxKind): kind is ShiftOperatorOrHigher {
866+
return isShiftOperator(kind)
867+
|| isAdditiveOperatorOrHigher(kind);
868+
}
869+
870+
function isRelationalOperator(kind: SyntaxKind): kind is RelationalOperator {
871+
return kind === SyntaxKind.LessThanToken
872+
|| kind === SyntaxKind.LessThanEqualsToken
873+
|| kind === SyntaxKind.GreaterThanToken
874+
|| kind === SyntaxKind.GreaterThanEqualsToken
875+
|| kind === SyntaxKind.InstanceOfKeyword
876+
|| kind === SyntaxKind.InKeyword;
877+
}
878+
879+
function isRelationalOperatorOrHigher(kind: SyntaxKind): kind is RelationalOperatorOrHigher {
880+
return isRelationalOperator(kind)
881+
|| isShiftOperatorOrHigher(kind);
882+
}
883+
884+
function isEqualityOperator(kind: SyntaxKind): kind is EqualityOperator {
885+
return kind === SyntaxKind.EqualsEqualsToken
886+
|| kind === SyntaxKind.EqualsEqualsEqualsToken
887+
|| kind === SyntaxKind.ExclamationEqualsToken
888+
|| kind === SyntaxKind.ExclamationEqualsEqualsToken;
889+
}
890+
891+
function isEqualityOperatorOrHigher(kind: SyntaxKind): kind is EqualityOperatorOrHigher {
892+
return isEqualityOperator(kind)
893+
|| isRelationalOperatorOrHigher(kind);
894+
}
895+
896+
function isBitwiseOperator(kind: SyntaxKind): kind is BitwiseOperator {
897+
return kind === SyntaxKind.AmpersandToken
898+
|| kind === SyntaxKind.BarToken
899+
|| kind === SyntaxKind.CaretToken;
900+
}
901+
902+
function isBitwiseOperatorOrHigher(kind: SyntaxKind): kind is BitwiseOperatorOrHigher {
903+
return isBitwiseOperator(kind)
904+
|| isEqualityOperatorOrHigher(kind);
905+
}
906+
907+
// NOTE: The version in utilities includes ExclamationToken, which is not a binary operator.
908+
function isLogicalOperator(kind: SyntaxKind): kind is LogicalOperator {
909+
return kind === SyntaxKind.AmpersandAmpersandToken
910+
|| kind === SyntaxKind.BarBarToken;
911+
}
912+
913+
function isLogicalOperatorOrHigher(kind: SyntaxKind): kind is LogicalOperatorOrHigher {
914+
return isLogicalOperator(kind)
915+
|| isBitwiseOperatorOrHigher(kind);
916+
}
917+
918+
function isAssignmentOperatorOrHigher(kind: SyntaxKind): kind is AssignmentOperatorOrHigher {
919+
return kind === SyntaxKind.QuestionQuestionToken
920+
|| isLogicalOperatorOrHigher(kind)
921+
|| isAssignmentOperator(kind);
922+
}
923+
924+
function isBinaryOperator(kind: SyntaxKind): kind is BinaryOperator {
925+
return isAssignmentOperatorOrHigher(kind)
926+
|| kind === SyntaxKind.CommaToken;
927+
}
928+
929+
export function isBinaryOperatorToken(node: Node): node is BinaryOperatorToken {
930+
return isBinaryOperator(node.kind);
831931
}
832932
}

src/compiler/transformers/module/module.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1864,17 +1864,22 @@ namespace ts {
18641864
if (exportedNames) {
18651865
let expression: Expression = node.kind === SyntaxKind.PostfixUnaryExpression
18661866
? setTextRange(
1867-
factory.createBinaryExpression(
1868-
node.operand,
1869-
factory.createToken(node.operator === SyntaxKind.PlusPlusToken ? SyntaxKind.PlusEqualsToken : SyntaxKind.MinusEqualsToken),
1870-
factory.createNumericLiteral(1)
1867+
factory.createPrefixUnaryExpression(
1868+
node.operator,
1869+
node.operand
18711870
),
18721871
/*location*/ node)
18731872
: node;
18741873
for (const exportName of exportedNames) {
18751874
// Mark the node to prevent triggering this rule again.
18761875
noSubstitution[getNodeId(expression)] = true;
1877-
expression = factory.createParenthesizedExpression(createExportExpression(exportName, expression));
1876+
expression = createExportExpression(exportName, expression);
1877+
}
1878+
if (node.kind === SyntaxKind.PostfixUnaryExpression) {
1879+
noSubstitution[getNodeId(expression)] = true;
1880+
expression = node.operator === SyntaxKind.PlusPlusToken
1881+
? factory.createSubtract(expression, factory.createNumericLiteral(1))
1882+
: factory.createAdd(expression, factory.createNumericLiteral(1));
18781883
}
18791884
return expression;
18801885
}

0 commit comments

Comments
 (0)