mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-10 01:43:59 -05:00
Moved constant value emit to ts transform.
This commit is contained in:
@@ -1143,10 +1143,6 @@ const _super = (function (geti, seti) {
|
||||
}
|
||||
|
||||
function emitPropertyAccessExpression(node: PropertyAccessExpression) {
|
||||
if (tryEmitConstantValue(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let indentBeforeDot = false;
|
||||
let indentAfterDot = false;
|
||||
if (!(getEmitFlags(node) & EmitFlags.NoIndentation)) {
|
||||
@@ -1156,11 +1152,13 @@ const _super = (function (geti, seti) {
|
||||
indentBeforeDot = needsIndentation(node, node.expression, dotToken);
|
||||
indentAfterDot = needsIndentation(node, dotToken, node.name);
|
||||
}
|
||||
const shouldEmitDotDot = !indentBeforeDot && needsDotDotForPropertyAccess(node.expression);
|
||||
|
||||
emitExpression(node.expression);
|
||||
increaseIndentIf(indentBeforeDot);
|
||||
|
||||
const shouldEmitDotDot = !indentBeforeDot && needsDotDotForPropertyAccess(node.expression);
|
||||
write(shouldEmitDotDot ? ".." : ".");
|
||||
|
||||
increaseIndentIf(indentAfterDot);
|
||||
emit(node.name);
|
||||
decreaseIndentIf(indentBeforeDot, indentAfterDot);
|
||||
@@ -1176,17 +1174,15 @@ const _super = (function (geti, seti) {
|
||||
}
|
||||
else {
|
||||
// check if constant enum value is integer
|
||||
const constantValue = tryGetConstEnumValue(expression);
|
||||
const constantValue = getConstantValue(expression);
|
||||
// isFinite handles cases when constantValue is undefined
|
||||
return isFinite(constantValue) && Math.floor(constantValue) === constantValue;
|
||||
return isFinite(constantValue)
|
||||
&& Math.floor(constantValue) === constantValue
|
||||
&& compilerOptions.removeComments;
|
||||
}
|
||||
}
|
||||
|
||||
function emitElementAccessExpression(node: ElementAccessExpression) {
|
||||
if (tryEmitConstantValue(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
emitExpression(node.expression);
|
||||
write("[");
|
||||
emitExpression(node.argumentExpression);
|
||||
@@ -2260,24 +2256,6 @@ const _super = (function (geti, seti) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(rbuckton): Move this into a transformer
|
||||
function tryEmitConstantValue(node: PropertyAccessExpression | ElementAccessExpression): boolean {
|
||||
const constantValue = tryGetConstEnumValue(node);
|
||||
if (constantValue !== undefined) {
|
||||
write(String(constantValue));
|
||||
if (!compilerOptions.removeComments) {
|
||||
const propertyName = isPropertyAccessExpression(node)
|
||||
? declarationNameToString(node.name)
|
||||
: getTextOfNode(node.argumentExpression);
|
||||
write(` /* ${propertyName} */`);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function emitEmbeddedStatement(node: Statement) {
|
||||
if (isBlock(node)) {
|
||||
write(" ");
|
||||
@@ -2628,16 +2606,6 @@ const _super = (function (geti, seti) {
|
||||
return getLiteralText(node, currentSourceFile, languageVersion);
|
||||
}
|
||||
|
||||
function tryGetConstEnumValue(node: Node): number {
|
||||
if (compilerOptions.isolatedModules) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return isPropertyAccessExpression(node) || isElementAccessExpression(node)
|
||||
? resolver.getConstantValue(<PropertyAccessExpression | ElementAccessExpression>node)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function isSingleLineEmptyBlock(block: Block) {
|
||||
return !block.multiLine
|
||||
&& block.statements.length === 0
|
||||
|
||||
@@ -2798,6 +2798,20 @@ namespace ts {
|
||||
return tokenSourceMapRanges && tokenSourceMapRanges[token];
|
||||
}
|
||||
|
||||
export function getConstantValue(node: Node) {
|
||||
const emitNode = node.emitNode;
|
||||
if (emitNode && emitNode.flags & EmitFlags.ConstantValue) {
|
||||
return emitNode.constantValue;
|
||||
}
|
||||
}
|
||||
|
||||
export function setConstantValue(node: Node, value: number) {
|
||||
const emitNode = getOrCreateEmitNode(node);
|
||||
emitNode.constantValue = value;
|
||||
emitNode.flags |= EmitFlags.ConstantValue;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function setTextRange<T extends TextRange>(node: T, location: TextRange): T {
|
||||
if (location) {
|
||||
node.pos = location.pos;
|
||||
|
||||
@@ -42,6 +42,10 @@ namespace ts {
|
||||
context.onEmitNode = onEmitNode;
|
||||
context.onSubstituteNode = onSubstituteNode;
|
||||
|
||||
// Enable substitution for property/element access to emit const enum values.
|
||||
context.enableSubstitution(SyntaxKind.PropertyAccessExpression);
|
||||
context.enableSubstitution(SyntaxKind.ElementAccessExpression);
|
||||
|
||||
// These variables contain state that changes as we descend into the tree.
|
||||
let currentSourceFile: SourceFile;
|
||||
let currentNamespace: ModuleDeclaration;
|
||||
@@ -3294,17 +3298,15 @@ namespace ts {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
return substituteExpressionIdentifier(<Identifier>node);
|
||||
}
|
||||
|
||||
if (enabledSubstitutions & TypeScriptSubstitutionFlags.AsyncMethodsWithSuper) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.CallExpression:
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
return substitutePropertyAccessExpression(<PropertyAccessExpression>node);
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
return substituteElementAccessExpression(<ElementAccessExpression>node);
|
||||
case SyntaxKind.CallExpression:
|
||||
if (enabledSubstitutions & TypeScriptSubstitutionFlags.AsyncMethodsWithSuper) {
|
||||
return substituteCallExpression(<CallExpression>node);
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
return substitutePropertyAccessExpression(<PropertyAccessExpression>node);
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
return substituteElementAccessExpression(<ElementAccessExpression>node);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return node;
|
||||
@@ -3381,7 +3383,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function substitutePropertyAccessExpression(node: PropertyAccessExpression) {
|
||||
if (node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
if (enabledSubstitutions & TypeScriptSubstitutionFlags.AsyncMethodsWithSuper && node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
const flags = getSuperContainerAsyncMethodFlags();
|
||||
if (flags) {
|
||||
return createSuperAccessInAsyncMethod(
|
||||
@@ -3392,11 +3394,11 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
return substituteConstantValue(node);
|
||||
}
|
||||
|
||||
function substituteElementAccessExpression(node: ElementAccessExpression) {
|
||||
if (node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
if (enabledSubstitutions & TypeScriptSubstitutionFlags.AsyncMethodsWithSuper && node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
const flags = getSuperContainerAsyncMethodFlags();
|
||||
if (flags) {
|
||||
return createSuperAccessInAsyncMethod(
|
||||
@@ -3407,9 +3409,39 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
return substituteConstantValue(node);
|
||||
}
|
||||
|
||||
function substituteConstantValue(node: PropertyAccessExpression | ElementAccessExpression): LeftHandSideExpression {
|
||||
const constantValue = tryGetConstEnumValue(node);
|
||||
if (constantValue !== undefined) {
|
||||
const substitute = createLiteral(constantValue);
|
||||
setSourceMapRange(substitute, node);
|
||||
setCommentRange(substitute, node);
|
||||
if (!compilerOptions.removeComments) {
|
||||
const propertyName = isPropertyAccessExpression(node)
|
||||
? declarationNameToString(node.name)
|
||||
: getTextOfNode(node.argumentExpression);
|
||||
substitute.trailingComment = ` ${propertyName} `;
|
||||
}
|
||||
|
||||
setConstantValue(node, constantValue);
|
||||
return substitute;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
function tryGetConstEnumValue(node: Node): number {
|
||||
if (compilerOptions.isolatedModules) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return isPropertyAccessExpression(node) || isElementAccessExpression(node)
|
||||
? resolver.getConstantValue(<PropertyAccessExpression | ElementAccessExpression>node)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function createSuperAccessInAsyncMethod(argumentExpression: Expression, flags: NodeCheckFlags, location: TextRange): LeftHandSideExpression {
|
||||
if (flags & NodeCheckFlags.AsyncMethodWithSuperBinding) {
|
||||
return createPropertyAccess(
|
||||
|
||||
@@ -3156,6 +3156,7 @@ namespace ts {
|
||||
sourceMapRange?: TextRange;
|
||||
tokenSourceMapRanges?: Map<TextRange>;
|
||||
annotatedNodes?: Node[]; // Tracks Parse-tree nodes with EmitNodes for eventual cleanup.
|
||||
constantValue?: number;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -3187,6 +3188,7 @@ namespace ts {
|
||||
AsyncFunctionBody = 1 << 21,
|
||||
ReuseTempVariableScope = 1 << 22, // Reuse the existing temp variable scope during emit.
|
||||
CustomPrologue = 1 << 23, // Treat the statement as if it were a prologue directive (NOTE: Prologue directives are *not* transformed).
|
||||
ConstantValue = 1 << 24, // The node was replaced with a constant value during substitution.
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
||||
@@ -23,15 +23,15 @@ let c1 = Foo["C"].toString();
|
||||
|
||||
|
||||
//// [constEnumToStringWithComments.js]
|
||||
var x0 = 100 /* X */..toString();
|
||||
var x1 = 100 /* "X" */..toString();
|
||||
var x0 = 100 /* X */.toString();
|
||||
var x1 = 100 /* "X" */.toString();
|
||||
var y0 = 0.5 /* Y */.toString();
|
||||
var y1 = 0.5 /* "Y" */.toString();
|
||||
var z0 = 2 /* Z */..toString();
|
||||
var z1 = 2 /* "Z" */..toString();
|
||||
var a0 = -1 /* A */..toString();
|
||||
var a1 = -1 /* "A" */..toString();
|
||||
var z0 = 2 /* Z */.toString();
|
||||
var z1 = 2 /* "Z" */.toString();
|
||||
var a0 = -1 /* A */.toString();
|
||||
var a1 = -1 /* "A" */.toString();
|
||||
var b0 = -1.5 /* B */.toString();
|
||||
var b1 = -1.5 /* "B" */.toString();
|
||||
var c0 = -1 /* C */..toString();
|
||||
var c1 = -1 /* "C" */..toString();
|
||||
var c0 = -1 /* C */.toString();
|
||||
var c1 = -1 /* "C" */.toString();
|
||||
|
||||
Reference in New Issue
Block a user