Moved constant value emit to ts transform.

This commit is contained in:
Ron Buckton
2016-09-26 17:53:46 -07:00
parent bfb8933a93
commit 21c10af13c
5 changed files with 76 additions and 60 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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(

View File

@@ -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 */

View File

@@ -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();