General fixes and cleanup

This commit is contained in:
Ron Buckton
2016-03-07 16:48:40 -08:00
parent 1cf183b09a
commit d89e21aecd
10 changed files with 60 additions and 68 deletions
+21 -39
View File
@@ -110,21 +110,15 @@ namespace ts {
}
/**
* Creates a shallow, memberwise clone of a node. The "kind", "pos", "end", "flags", and "parent"
* properties are excluded by default, and can be provided via the "location", "flags", and
* "parent" parameters.
*
* @param node The node to clone.
* @param location An optional TextRange to use to supply the new position.
* @param flags The NodeFlags to use for the cloned node.
* @param parent The parent for the new node.
* @param original An optional pointer to the original source tree node.
* Creates a shallow, memberwise clone of a node with no source map location.
*/
export function cloneNode<T extends Node>(node: T, location?: TextRange, flags?: NodeFlags, parent?: Node, original?: Node): T {
export function getSynthesizedClone<T extends Node>(node: T): T {
// We don't use "clone" from core.ts here, as we need to preserve the prototype chain of
// the original node. We also need to exclude specific properties and only include own-
// properties (to skip members already defined on the shared prototype).
const clone = <T>createNode(node.kind, location);
const clone = <T>createSynthesizedNode(node.kind);
clone.flags = node.flags;
clone.original = node;
for (const key in node) {
if (clone.hasOwnProperty(key) || !node.hasOwnProperty(key)) {
@@ -134,18 +128,6 @@ namespace ts {
(<any>clone)[key] = (<any>node)[key];
}
if (flags !== undefined) {
clone.flags = flags;
}
if (parent !== undefined) {
clone.parent = parent;
}
if (original !== undefined) {
clone.original = original;
}
return clone;
}
@@ -153,21 +135,21 @@ namespace ts {
* Creates a shallow, memberwise clone of a node for mutation.
*/
export function getMutableClone<T extends Node>(node: T): T {
return cloneNode(node, /*location*/ node, node.flags, /*parent*/ undefined, /*original*/ node);
}
/**
* Creates a shallow, memberwise clone of a node with no source map location.
*/
export function getSynthesizedClone<T extends Node>(node: T): T {
return nodeIsSynthesized(node) ? node : cloneNode(node, /*location*/ undefined, node.flags, /*parent*/ undefined, /*original*/ node);
const clone = getSynthesizedClone(node);
clone.pos = node.pos;
clone.end = node.end;
clone.parent = node.parent;
return clone;
}
/**
* Creates a shallow, memberwise clone of a node at the specified source map location.
*/
export function getRelocatedClone<T extends Node>(node: T, location: TextRange): T {
return cloneNode(node, location, node.flags, /*parent*/ undefined, /*original*/ node);
const clone = getSynthesizedClone(node);
clone.pos = location.pos;
clone.end = location.end;
return clone;
}
export function createNodeArrayNode<T extends Node>(elements: T[]): NodeArrayNode<T> {
@@ -718,8 +700,8 @@ namespace ts {
export function createMemberAccessForPropertyName(target: Expression, memberName: PropertyName, location?: TextRange): MemberExpression {
return isIdentifier(memberName)
? createPropertyAccess(target, cloneNode(memberName), location)
: createElementAccess(target, cloneNode(isComputedPropertyName(memberName) ? memberName.expression : memberName), location);
? createPropertyAccess(target, getSynthesizedClone(memberName), location)
: createElementAccess(target, getSynthesizedClone(isComputedPropertyName(memberName) ? memberName.expression : memberName), location);
}
export function createRestParameter(name: string | Identifier) {
@@ -1154,15 +1136,15 @@ namespace ts {
return isQualifiedName(node)
? createPropertyAccess(
createExpressionFromEntityName(node.left),
cloneNode(node.right)
getSynthesizedClone(node.right)
)
: cloneNode(node);
: getSynthesizedClone(node);
}
export function createExpressionForPropertyName(memberName: PropertyName, location?: TextRange): Expression {
return isIdentifier(memberName) ? createLiteral(memberName.text, location)
: isComputedPropertyName(memberName) ? cloneNode(memberName.expression, location)
: cloneNode(memberName, location);
: isComputedPropertyName(memberName) ? getRelocatedClone(memberName.expression, location)
: getRelocatedClone(memberName, location);
}
// Utilities
@@ -1370,7 +1352,7 @@ namespace ts {
const callee = expression.expression;
if (callee.kind === SyntaxKind.FunctionExpression
|| callee.kind === SyntaxKind.ArrowFunction) {
const clone = cloneNode(expression, expression, expression.flags, expression.parent, expression);
const clone = getMutableClone(expression);
clone.expression = createParen(callee, /*location*/ callee);
return clone;
}
+5 -1
View File
@@ -675,7 +675,7 @@ const _super = (function (geti, seti) {
//
function emitIdentifier(node: Identifier) {
if (getNodeEmitFlags(node) && NodeEmitFlags.UMDDefine) {
if (getNodeEmitFlags(node) & NodeEmitFlags.UMDDefine) {
writeLines(umdHelper);
}
else {
@@ -1411,6 +1411,10 @@ const _super = (function (geti, seti) {
}
function shouldEmitBlockFunctionBodyOnSingleLine(parentNode: Node, body: Block) {
if (body.multiLine) {
return false;
}
const originalNode = getOriginalNode(parentNode);
if (isFunctionLike(originalNode) && !nodeIsSynthesized(originalNode)) {
const body = originalNode.body;
+3 -3
View File
@@ -236,7 +236,7 @@ namespace ts {
emitArrayLiteralAssignment(<ArrayLiteralExpression>target, value, location);
}
else {
const name = cloneNode(<Identifier>target, /*location*/ target, /*flags*/ undefined, /*parent*/ undefined, /*original*/ target);
const name = getRelocatedClone(<Identifier>target, /*location*/ target);
emitAssignment(name, value, location, /*original*/ undefined);
}
}
@@ -326,7 +326,7 @@ namespace ts {
}
}
else {
const clonedName = cloneNode(name, /*location*/ undefined, /*flags*/ undefined, /*parent*/ undefined, /*original*/ name);
const clonedName = getSynthesizedClone(name);
emitAssignment(clonedName, value, target, target);
}
}
@@ -365,7 +365,7 @@ namespace ts {
// otherwise occur when the identifier is emitted.
return createElementAccess(
expression,
cloneNode(propertyName)
getSynthesizedClone(propertyName)
);
}
}
+9 -5
View File
@@ -16,6 +16,7 @@ namespace ts {
startLexicalEnvironment,
endLexicalEnvironment,
hoistVariableDeclaration,
getNodeEmitFlags,
setNodeEmitFlags,
} = context;
@@ -50,6 +51,7 @@ namespace ts {
function transformSourceFile(node: SourceFile) {
currentSourceFile = node;
enclosingBlockScopeContainer = node;
return visitEachChild(node, visitor, context);
}
@@ -772,7 +774,9 @@ namespace ts {
enableSubstitutionsForCapturedThis();
}
return transformFunctionLikeToExpression(node, /*location*/ node, /*name*/ undefined);
const func = transformFunctionLikeToExpression(node, /*location*/ node, /*name*/ undefined);
setNodeEmitFlags(func, NodeEmitFlags.CapturesThis);
return func;
}
/**
@@ -1514,7 +1518,7 @@ namespace ts {
* @param node A template literal.
*/
function visitTemplateLiteral(node: LiteralExpression): LeftHandSideExpression {
return createLiteral(node.text);
return createLiteral(node.text, /*location*/ node);
}
/**
@@ -1579,7 +1583,7 @@ namespace ts {
// <CR><LF> and <CR> LineTerminatorSequences are normalized to <LF> for both TV and TRV.
text = text.replace(/\r\n?/g, "\n");
text = escapeString(text);
return createLiteral(text);
return createLiteral(text, /*location*/ node);
}
/**
@@ -1689,7 +1693,7 @@ namespace ts {
addCaptureThisForNodeIfNeeded(statements, node);
addRange(statements, visitNodes(createNodeArray(remaining), visitor, isStatement));
addRange(statements, endLexicalEnvironment());
const clone = cloneNode(node, node, node.flags, /*parent*/ undefined, node);
const clone = getMutableClone(node);
clone.statements = createNodeArray(statements, /*location*/ node.statements);
return clone;
}
@@ -1705,7 +1709,7 @@ namespace ts {
if (enabledSubstitutions & ES6SubstitutionFlags.CapturedThis && isFunctionLike(node)) {
// If we are tracking a captured `this`, push a bit that indicates whether the
// containing function is an arrow function.
useCapturedThis = node.kind === SyntaxKind.ArrowFunction;
useCapturedThis = (getNodeEmitFlags(node) & NodeEmitFlags.CapturesThis) !== 0;
}
previousOnEmitNode(node, emit);
+1 -1
View File
@@ -750,7 +750,7 @@ namespace ts {
}
function updateSourceFile(node: SourceFile, statements: Statement[]) {
const updated = cloneNode(node, node, node.flags, /*parent*/ undefined, node);
const updated = getMutableClone(node);
updated.statements = createNodeArray(statements, node.statements);
return updated;
}
+1 -1
View File
@@ -1271,7 +1271,7 @@ namespace ts {
}
function updateSourceFile(node: SourceFile, statements: Statement[]) {
const updated = cloneNode(node, node, node.flags, /*parent*/ undefined, node);
const updated = getMutableClone(node);
updated.statements = createNodeArray(statements, node.statements);
return updated;
}
+9 -9
View File
@@ -198,8 +198,11 @@ namespace ts {
// Fallback to the default visit behavior.
return visitorWorker(node);
case SyntaxKind.SemicolonClassElement:
return node;
default:
Debug.fail("Unexpected node.");
Debug.fail(`Unexpected node kind: ${formatSyntaxKind(node.kind)}.`);
break;
}
}
@@ -867,7 +870,7 @@ namespace ts {
function transformParameterWithPropertyAssignment(node: ParameterDeclaration) {
Debug.assert(isIdentifier(node.name));
const name = cloneNode(<Identifier>node.name);
const name = getSynthesizedClone(<Identifier>node.name);
return startOnNewLine(
createStatement(
createAssignment(
@@ -1730,10 +1733,7 @@ namespace ts {
);
}
else {
return setOriginalNode(
cloneNode(name),
name
);
return getSynthesizedClone(name);
}
}
@@ -2347,7 +2347,7 @@ namespace ts {
function trackChildOfNotEmittedNode<T extends Node>(parent: Node, child: T, original: T) {
if (!child.parent && !child.original) {
child = cloneNode(child, child, child.flags, child.parent, original);
child = getMutableClone(child);
}
setNodeEmitFlags(parent, NodeEmitFlags.IsNotEmittedNode);
@@ -2403,7 +2403,7 @@ namespace ts {
);
if (isNamespaceExport(node)) {
moduleParam = createAssignment(cloneNode(node.name), moduleParam);
moduleParam = createAssignment(getSynthesizedClone(node.name), moduleParam);
}
currentNamespaceLocalName = getGeneratedNameForNode(node);
@@ -2710,7 +2710,7 @@ namespace ts {
if (declaration) {
const classAlias = currentDecoratedClassAliases[getNodeId(declaration)];
if (classAlias) {
return cloneNode(classAlias);
return getRelocatedClone(classAlias, /*location*/ node);
}
}
}
+1
View File
@@ -2810,6 +2810,7 @@ namespace ts {
IsNotEmittedNode = 1 << 8, // Is a node that is not emitted but whose comments should be preserved if possible.
EmitCommentsOfNotEmittedParent = 1 << 9, // Emits comments of missing parent nodes.
NoSubstitution = 1 << 10, // Disables further substitution of an expression.
CapturesThis = 1 << 11, // The function captures a lexical `this`
}
/** Additional context provided to `visitEachChild` */
+4 -3
View File
@@ -1666,11 +1666,11 @@ namespace ts {
* @param parent The parent for the cloned node.
*/
export function cloneEntityName(node: EntityName, parent?: Node): EntityName {
const clone = cloneNode(node, node, node.flags, parent);
const clone = getMutableClone(node);
if (isQualifiedName(clone)) {
const { left, right } = clone;
clone.left = cloneEntityName(left, clone);
clone.right = cloneNode(right, right, right.flags, parent);
clone.right = getMutableClone(right);
}
return clone;
@@ -3066,7 +3066,8 @@ namespace ts {
|| kind === SyntaxKind.MethodDeclaration
|| kind === SyntaxKind.GetAccessor
|| kind === SyntaxKind.SetAccessor
|| kind === SyntaxKind.IndexSignature;
|| kind === SyntaxKind.IndexSignature
|| kind === SyntaxKind.SemicolonClassElement;
}
export function isObjectLiteralElement(node: Node): node is ObjectLiteralElement {
+6 -6
View File
@@ -516,7 +516,7 @@ namespace ts {
return undefined;
}
Debug.assert(test === undefined || test(visited), "Wrong node type after visit.");
Debug.assert(test === undefined || test(visited), "Wrong node type after visit.", () => `Node ${formatSyntaxKind(visited.kind)} did not pass test ${(<any>test).name}.`);
aggregateTransformFlags(visited);
return visited;
}
@@ -717,7 +717,7 @@ namespace ts {
from = parenthesize(from, parentNode);
}
Debug.assert(test === undefined || test(from), "Wrong node type after visit.");
Debug.assert(test === undefined || test(from), "Wrong node type after visit.", () => `Node ${formatSyntaxKind(from.kind)} did not pass test ${(<any>test).name}.`);
if (startOnNewLine) {
from.startsOnNewLine = true;
@@ -774,7 +774,7 @@ namespace ts {
*/
export function mergeSourceFileLexicalEnvironment(node: SourceFile, declarations: Statement[]) {
if (declarations !== undefined && declarations.length) {
const mutableNode = cloneNode(node, /*location*/ node, node.flags, /*parent*/ undefined, /*original*/ node);
const mutableNode = getMutableClone(node);
mutableNode.statements = mergeStatements(mutableNode.statements, declarations);
return mutableNode;
}
@@ -791,7 +791,7 @@ namespace ts {
export function mergeModuleDeclarationLexicalEnvironment(node: ModuleDeclaration, declarations: Statement[]) {
Debug.assert(node.body.kind === SyntaxKind.ModuleBlock);
if (declarations !== undefined && declarations.length) {
const mutableNode = cloneNode(node, /*location*/ node, node.flags, /*parent*/ undefined, /*original*/ node);
const mutableNode = getMutableClone(node);
mutableNode.body = mergeBlockLexicalEnvironment(<ModuleBlock>node.body, declarations);
return mutableNode;
}
@@ -808,7 +808,7 @@ namespace ts {
function mergeFunctionLikeLexicalEnvironment(node: FunctionLikeDeclaration, declarations: Statement[]) {
Debug.assert(node.body !== undefined);
if (declarations !== undefined && declarations.length) {
const mutableNode = cloneNode(node, /*location*/ node, node.flags, /*parent*/ undefined, /*original*/ node);
const mutableNode = getMutableClone(node);
mutableNode.body = mergeConciseBodyLexicalEnvironment(mutableNode.body, declarations);
return mutableNode;
}
@@ -859,7 +859,7 @@ namespace ts {
* @param declarations The lexical declarations to merge.
*/
function mergeBlockLexicalEnvironment<T extends Block>(node: T, declarations: Statement[]) {
const mutableNode = cloneNode(node, /*location*/ node, node.flags, /*parent*/ undefined, /*original*/ node);
const mutableNode = getMutableClone(node);
mutableNode.statements = mergeStatements(node.statements, declarations);
return mutableNode;
}