Add factory functions for rest of NodeEdgeTraversal

This commit is contained in:
Ron Buckton 2017-02-03 14:12:50 -08:00
parent 7a539d0b85
commit bd98bc97bd
4 changed files with 315 additions and 172 deletions

View File

@ -187,6 +187,20 @@ namespace ts {
// Names
export function createQualifiedName(left: EntityName, right: string | Identifier) {
const node = <QualifiedName>createSynthesizedNode(SyntaxKind.QualifiedName);
node.left = left;
node.right = asName(right);
return node;
}
export function updateQualifiedName(node: QualifiedName, left: EntityName, right: Identifier) {
return node.left !== left
|| node.right !== right
? updateNode(createQualifiedName(left, right), node)
: node;
}
export function createComputedPropertyName(expression: Expression) {
const node = <ComputedPropertyName>createSynthesizedNode(SyntaxKind.ComputedPropertyName);
node.expression = expression;
@ -502,6 +516,20 @@ namespace ts {
: node;
}
export function createTypeAssertion(type: TypeNode, expression: Expression) {
const node = <TypeAssertion>createSynthesizedNode(SyntaxKind.TypeAssertionExpression);
node.type = type;
node.expression = parenthesizePrefixOperand(expression);
return node;
}
export function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression) {
return node.type !== type
|| node.expression !== expression
? updateNode(createTypeAssertion(type, expression), node)
: node;
}
export function createParen(expression: Expression) {
const node = <ParenthesizedExpression>createSynthesizedNode(SyntaxKind.ParenthesizedExpression);
node.expression = expression;
@ -749,6 +777,32 @@ namespace ts {
: node;
}
export function createAsExpression(expression: Expression, type: TypeNode) {
const node = <AsExpression>createSynthesizedNode(SyntaxKind.AsExpression);
node.expression = expression;
node.type = type;
return node;
}
export function updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode) {
return node.expression !== expression
|| node.type !== type
? updateNode(createAsExpression(expression, type), node)
: node;
}
export function createNonNullExpression(expression: Expression) {
const node = <NonNullExpression>createSynthesizedNode(SyntaxKind.NonNullExpression);
node.expression = parenthesizeForAccess(expression);
return node;
}
export function updateNonNullExpression(node: NonNullExpression, expression: Expression) {
return node.expression !== expression
? updateNode(createNonNullExpression(expression), node)
: node;
}
// Misc
export function createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail) {
@ -1040,18 +1094,6 @@ namespace ts {
: node;
}
export function createCaseBlock(clauses: CaseOrDefaultClause[]): CaseBlock {
const node = <CaseBlock>createSynthesizedNode(SyntaxKind.CaseBlock);
node.clauses = createNodeArray(clauses);
return node;
}
export function updateCaseBlock(node: CaseBlock, clauses: CaseOrDefaultClause[]) {
return node.clauses !== clauses
? updateNode(createCaseBlock(clauses), node)
: node;
}
export function createFunctionDeclaration(decorators: Decorator[], modifiers: Modifier[], asteriskToken: AsteriskToken, name: string | Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block) {
const node = <FunctionDeclaration>createSynthesizedNode(SyntaxKind.FunctionDeclaration);
node.decorators = asNodeArray(decorators);
@ -1099,6 +1141,85 @@ namespace ts {
: node;
}
export function createEnumDeclaration(decorators: Decorator[], modifiers: Modifier[], name: string | Identifier, members: EnumMember[]) {
const node = <EnumDeclaration>createSynthesizedNode(SyntaxKind.EnumDeclaration);
node.decorators = asNodeArray(decorators);
node.modifiers = asNodeArray(modifiers);
node.name = asName(name);
node.members = createNodeArray(members);
return node;
}
export function updateEnumDeclaration(node: EnumDeclaration, decorators: Decorator[], modifiers: Modifier[], name: Identifier, members: EnumMember[]) {
return node.decorators !== decorators
|| node.modifiers !== modifiers
|| node.name !== name
|| node.members !== members
? updateNode(createEnumDeclaration(decorators, modifiers, name, members), node)
: node;
}
export function createModuleDeclaration(decorators: Decorator[], modifiers: Modifier[], name: ModuleName, body: ModuleBody, flags?: NodeFlags) {
const node = <ModuleDeclaration>createSynthesizedNode(SyntaxKind.ModuleDeclaration);
node.flags |= flags;
node.decorators = asNodeArray(decorators);
node.modifiers = asNodeArray(modifiers);
node.name = name;
node.body = body;
return node;
}
export function updateModuleDeclaration(node: ModuleDeclaration, decorators: Decorator[], modifiers: Modifier[], name: ModuleName, body: ModuleBody) {
return node.decorators !== decorators
|| node.modifiers !== modifiers
|| node.name !== name
|| node.body !== body
? updateNode(createModuleDeclaration(decorators, modifiers, name, body, node.flags), node)
: node;
}
export function createModuleBlock(statements: Statement[]) {
const node = <ModuleBlock>createSynthesizedNode(SyntaxKind.CaseBlock);
node.statements = createNodeArray(statements);
return node;
}
export function updateModuleBlock(node: ModuleBlock, statements: Statement[]) {
return node.statements !== statements
? updateNode(createModuleBlock(statements), node)
: node;
}
export function createCaseBlock(clauses: CaseOrDefaultClause[]): CaseBlock {
const node = <CaseBlock>createSynthesizedNode(SyntaxKind.CaseBlock);
node.clauses = createNodeArray(clauses);
return node;
}
export function updateCaseBlock(node: CaseBlock, clauses: CaseOrDefaultClause[]) {
return node.clauses !== clauses
? updateNode(createCaseBlock(clauses), node)
: node;
}
export function createImportEqualsDeclaration(decorators: Decorator[], modifiers: Modifier[], name: string | Identifier, moduleReference: ModuleReference) {
const node = <ImportEqualsDeclaration>createSynthesizedNode(SyntaxKind.ImportEqualsDeclaration);
node.decorators = asNodeArray(decorators);
node.modifiers = asNodeArray(modifiers);
node.name = asName(name);
node.moduleReference = moduleReference;
return node;
}
export function updateImportEqualsDeclaration(node: ImportEqualsDeclaration, decorators: Decorator[], modifiers: Modifier[], name: Identifier, moduleReference: ModuleReference) {
return node.decorators !== decorators
|| node.modifiers !== modifiers
|| node.name !== name
|| node.moduleReference !== moduleReference
? updateNode(createImportEqualsDeclaration(decorators, modifiers, name, moduleReference), node)
: node;
}
export function createImportDeclaration(decorators: Decorator[], modifiers: Modifier[], importClause: ImportClause, moduleSpecifier?: Expression): ImportDeclaration {
const node = <ImportDeclaration>createSynthesizedNode(SyntaxKind.ImportDeclaration);
node.decorators = asNodeArray(decorators);
@ -1228,6 +1349,20 @@ namespace ts {
: node;
}
// Module references
export function createExternalModuleReference(expression: Expression) {
const node = <ExternalModuleReference>createSynthesizedNode(SyntaxKind.ExternalModuleReference);
node.expression = expression;
return node;
}
export function updateExternalModuleReference(node: ExternalModuleReference, expression: Expression) {
return node.expression !== expression
? updateNode(createExternalModuleReference(expression), node)
: node;
}
// JSX
export function createJsxElement(openingElement: JsxOpeningElement, children: JsxChild[], closingElement: JsxClosingElement) {
@ -1426,6 +1561,22 @@ namespace ts {
return node;
}
// Enum
export function createEnumMember(name: string | PropertyName, initializer?: Expression) {
const node = <EnumMember>createSynthesizedNode(SyntaxKind.EnumMember);
node.name = asName(name);
node.initializer = initializer && parenthesizeExpressionForList(initializer);
return node;
}
export function updateEnumMember(node: EnumMember, name: PropertyName, initializer: Expression | undefined) {
return node.name !== name
|| node.initializer !== initializer
? updateNode(createEnumMember(name, initializer), node)
: node;
}
// Top-level nodes
export function updateSourceFileNode(node: SourceFile, statements: Statement[]) {

View File

@ -1771,24 +1771,28 @@
members: NodeArray<EnumMember>;
}
export type ModuleBody = ModuleBlock | ModuleDeclaration;
export type ModuleName = Identifier | StringLiteral;
export type ModuleBody = NamespaceBody | JSDocNamespaceBody;
export interface ModuleDeclaration extends DeclarationStatement {
kind: SyntaxKind.ModuleDeclaration;
name: Identifier | StringLiteral;
body?: ModuleBlock | NamespaceDeclaration | JSDocNamespaceDeclaration | Identifier;
body?: ModuleBody | JSDocNamespaceDeclaration | Identifier;
}
export type NamespaceBody = ModuleBlock | NamespaceDeclaration;
export interface NamespaceDeclaration extends ModuleDeclaration {
name: Identifier;
body: ModuleBlock | NamespaceDeclaration;
body: NamespaceBody;
}
export type JSDocNamespaceBody = Identifier | JSDocNamespaceDeclaration;
export interface JSDocNamespaceDeclaration extends ModuleDeclaration {
name: Identifier;
body: JSDocNamespaceDeclaration | Identifier;
body: JSDocNamespaceBody;
}
export interface ModuleBlock extends Node, Statement {

View File

@ -3887,6 +3887,19 @@ namespace ts {
export function isModuleBody(node: Node): node is ModuleBody {
const kind = node.kind;
return kind === SyntaxKind.ModuleBlock
|| kind === SyntaxKind.ModuleDeclaration
|| kind === SyntaxKind.Identifier;
}
export function isNamespaceBody(node: Node): node is NamespaceBody {
const kind = node.kind;
return kind === SyntaxKind.ModuleBlock
|| kind === SyntaxKind.ModuleDeclaration;
}
export function isJSDocNamespaceBody(node: Node): node is JSDocNamespaceBody {
const kind = node.kind;
return kind === SyntaxKind.Identifier
|| kind === SyntaxKind.ModuleDeclaration;
}

View File

@ -6,97 +6,6 @@
namespace ts {
export type VisitResult<T extends Node> = T | T[];
/**
* Describes an edge of a Node, used when traversing a syntax tree.
*/
interface NodeEdge {
/** The property name for the edge. */
name: string;
/** Indicates that the result is optional. */
optional?: boolean;
/** A callback used to test whether a node is valid. */
test?: (node: Node) => node is Node;
/** A callback used to lift a NodeArrayNode into a valid node. */
lift?: (nodes: NodeArray<Node>) => Node;
/** A callback used to parenthesize a node to preserve the intended order of operations. */
parenthesize?: (value: Node, parentNode: Node) => Node;
};
/**
* Describes the shape of a Node.
*/
type NodeTraversalPath = NodeEdge[];
/**
* This map contains information about the shape of each Node in "types.ts" pertaining to how
* each node should be traversed during a transformation.
*
* Each edge corresponds to a property in a Node subtype that should be traversed when visiting
* each child. The properties are assigned in the order in which traversal should occur.
*
* We only add entries for nodes that do not have a create/update pair defined in factory.ts
*
* NOTE: This needs to be kept up to date with changes to nodes in "types.ts". Currently, this
* map is not comprehensive. Only node edges relevant to tree transformation are
* currently defined. We may extend this to be more comprehensive, and eventually
* supplant the existing `forEachChild` implementation if performance is not
* significantly impacted.
*/
function getNodeEdgeTraversal(kind: SyntaxKind): NodeTraversalPath {
switch (kind) {
case SyntaxKind.QualifiedName: return [
{ name: "left", test: isEntityName },
{ name: "right", test: isIdentifier }
];
case SyntaxKind.Decorator: return [
{ name: "expression", test: isLeftHandSideExpression }
];
case SyntaxKind.TypeAssertionExpression: return [
{ name: "type", test: isTypeNode },
{ name: "expression", test: isUnaryExpression }
];
case SyntaxKind.AsExpression: return [
{ name: "expression", test: isExpression },
{ name: "type", test: isTypeNode }
];
case SyntaxKind.NonNullExpression: return [
{ name: "expression", test: isLeftHandSideExpression }
];
case SyntaxKind.EnumDeclaration: return [
{ name: "decorators", test: isDecorator },
{ name: "modifiers", test: isModifier },
{ name: "name", test: isIdentifier },
{ name: "members", test: isEnumMember }
];
case SyntaxKind.ModuleDeclaration: return [
{ name: "decorators", test: isDecorator },
{ name: "modifiers", test: isModifier },
{ name: "name", test: isModuleName },
{ name: "body", test: isModuleBody }
];
case SyntaxKind.ModuleBlock: return [
{ name: "statements", test: isStatement }
];
case SyntaxKind.ImportEqualsDeclaration: return [
{ name: "decorators", test: isDecorator },
{ name: "modifiers", test: isModifier },
{ name: "name", test: isIdentifier },
{ name: "moduleReference", test: isModuleReference }
];
case SyntaxKind.ExternalModuleReference: return [
{ name: "expression", test: isExpression, optional: true }
];
case SyntaxKind.EnumMember: return [
{ name: "name", test: isPropertyName },
{ name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList }
];
}
}
function reduceNode<T>(node: Node, f: (memo: T, node: Node) => T, initial: T) {
return node ? f(initial, node) : initial;
}
@ -107,8 +16,7 @@ namespace ts {
/**
* Similar to `reduceLeft`, performs a reduction against each child of a node.
* NOTE: Unlike `forEachChild`, this does *not* visit every node. Only nodes added to the
* `nodeEdgeTraversalMap` above will be visited.
* NOTE: Unlike `forEachChild`, this does *not* visit every node.
*
* @param node The node containing the children to reduce.
* @param initial The initial value to supply to the reduction.
@ -145,6 +53,11 @@ namespace ts {
break;
// Names
case SyntaxKind.QualifiedName:
result = reduceNode((<QualifiedName>node).left, cbNode, result);
result = reduceNode((<QualifiedName>node).right, cbNode, result);
break;
case SyntaxKind.ComputedPropertyName:
result = reduceNode((<ComputedPropertyName>node).expression, cbNode, result);
break;
@ -252,6 +165,11 @@ namespace ts {
result = reduceNode((<TaggedTemplateExpression>node).template, cbNode, result);
break;
case SyntaxKind.TypeAssertionExpression:
result = reduceNode((<TypeAssertion>node).type, cbNode, result);
result = reduceNode((<TypeAssertion>node).expression, cbNode, result);
break;
case SyntaxKind.FunctionExpression:
result = reduceNodes((<FunctionExpression>node).modifiers, cbNodes, result);
result = reduceNode((<FunctionExpression>node).name, cbNode, result);
@ -314,6 +232,15 @@ namespace ts {
result = reduceNodes((<ExpressionWithTypeArguments>node).typeArguments, cbNodes, result);
break;
case SyntaxKind.AsExpression:
result = reduceNode((<AsExpression>node).expression, cbNode, result);
result = reduceNode((<AsExpression>node).type, cbNode, result);
break;
case SyntaxKind.NonNullExpression:
result = reduceNode((<NonNullExpression>node).expression, cbNode, result);
break;
// Misc
case SyntaxKind.TemplateSpan:
result = reduceNode((<TemplateSpan>node).expression, cbNode, result);
@ -415,10 +342,35 @@ namespace ts {
result = reduceNodes((<ClassDeclaration>node).members, cbNodes, result);
break;
case SyntaxKind.EnumDeclaration:
result = reduceNodes((<EnumDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<EnumDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<EnumDeclaration>node).name, cbNode, result);
result = reduceNodes((<EnumDeclaration>node).members, cbNodes, result);
break;
case SyntaxKind.ModuleDeclaration:
result = reduceNodes((<ModuleDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<ModuleDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<ModuleDeclaration>node).name, cbNode, result);
result = reduceNode((<ModuleDeclaration>node).body, cbNode, result);
break;
case SyntaxKind.ModuleBlock:
result = reduceNodes((<ModuleBlock>node).statements, cbNodes, result);
break;
case SyntaxKind.CaseBlock:
result = reduceNodes((<CaseBlock>node).clauses, cbNodes, result);
break;
case SyntaxKind.ImportEqualsDeclaration:
result = reduceNodes((<ImportEqualsDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<ImportEqualsDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<ImportEqualsDeclaration>node).name, cbNode, result);
result = reduceNode((<ImportEqualsDeclaration>node).moduleReference, cbNode, result);
break;
case SyntaxKind.ImportDeclaration:
result = reduceNodes((<ImportDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<ImportDeclaration>node).modifiers, cbNodes, result);
@ -459,6 +411,11 @@ namespace ts {
result = reduceNode((<ExportDeclaration>node).moduleSpecifier, cbNode, result);
break;
// Module references
case SyntaxKind.ExternalModuleReference:
result = reduceNode((<ExternalModuleReference>node).expression, cbNode, result);
break;
// JSX
case SyntaxKind.JsxElement:
result = reduceNode((<JsxElement>node).openingElement, cbNode, result);
@ -519,30 +476,25 @@ namespace ts {
break;
case SyntaxKind.SpreadAssignment:
result = reduceNode((node as SpreadAssignment).expression, cbNode, result);
result = reduceNode((<SpreadAssignment>node).expression, cbNode, result);
break;
// Enum
case SyntaxKind.EnumMember:
result = reduceNode((<EnumMember>node).name, cbNode, result);
result = reduceNode((<EnumMember>node).initializer, cbNode, result);
// Top-level nodes
case SyntaxKind.SourceFile:
result = reduceNodes((<SourceFile>node).statements, cbNodes, result);
break;
// Transformation nodes
case SyntaxKind.PartiallyEmittedExpression:
result = reduceNode((<PartiallyEmittedExpression>node).expression, cbNode, result);
break;
default:
const edgeTraversalPath = getNodeEdgeTraversal(kind);
if (edgeTraversalPath) {
for (const edge of edgeTraversalPath) {
const value = (<MapLike<any>>node)[edge.name];
if (value !== undefined) {
result = isArray(value)
? reduceNodes(<NodeArray<Node>>value, cbNodes, result)
: cbNode(result, <Node>value);
}
}
}
break;
}
@ -556,11 +508,9 @@ namespace ts {
* @param visitor The callback used to visit the Node.
* @param test A callback to execute to verify the Node is valid.
* @param optional An optional value indicating whether the Node is itself optional.
* @param lift An optional callback to execute to lift a NodeArrayNode into a valid Node.
* @param lift An optional callback to execute to lift a NodeArray into a valid Node.
*/
export function visitNode<T extends Node>(node: T, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, optional?: boolean, lift?: (node: NodeArray<Node>) => T): T;
export function visitNode<T extends Node>(node: T, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, optional: boolean, lift: (node: NodeArray<Node>) => T, parenthesize: (node: Node, parentNode: Node) => Node, parentNode: Node): T;
export function visitNode(node: Node, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, optional?: boolean, lift?: (node: Node[]) => Node, parenthesize?: (node: Node, parentNode: Node) => Node, parentNode?: Node): Node {
export function visitNode<T extends Node>(node: T, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, optional?: boolean, lift?: (node: NodeArray<Node>) => T): T {
if (node === undefined || visitor === undefined) {
return node;
}
@ -586,13 +536,9 @@ namespace ts {
visitedNode = visited;
}
if (parenthesize !== undefined) {
visitedNode = parenthesize(visitedNode, parentNode);
}
Debug.assertNode(visitedNode, test);
aggregateTransformFlags(visitedNode);
return visitedNode;
return <T>visitedNode;
}
/**
@ -604,14 +550,12 @@ namespace ts {
* @param start An optional value indicating the starting offset at which to start visiting.
* @param count An optional value indicating the maximum number of nodes to visit.
*/
export function visitNodes<T extends Node>(nodes: NodeArray<T>, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, start?: number, count?: number): NodeArray<T>;
export function visitNodes<T extends Node>(nodes: NodeArray<T>, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, start: number, count: number, parenthesize: (node: Node, parentNode: Node) => Node, parentNode: Node): NodeArray<T>;
export function visitNodes(nodes: NodeArray<Node>, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, start?: number, count?: number, parenthesize?: (node: Node, parentNode: Node) => Node, parentNode?: Node): NodeArray<Node> {
export function visitNodes<T extends Node>(nodes: NodeArray<T>, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, start?: number, count?: number): NodeArray<T> {
if (nodes === undefined) {
return undefined;
}
let updated: NodeArray<Node>;
let updated: NodeArray<T>;
// Ensure start and count have valid values
const length = nodes.length;
@ -627,7 +571,7 @@ namespace ts {
// If we are not visiting all of the original nodes, we must always create a new array.
// Since this is a fragment of a node array, we do not copy over the previous location
// and will only copy over `hasTrailingComma` if we are including the last element.
updated = createNodeArray<Node>([], /*hasTrailingComma*/ nodes.hasTrailingComma && start + count === length);
updated = createNodeArray<T>([], /*hasTrailingComma*/ nodes.hasTrailingComma && start + count === length);
}
// Visit each original node.
@ -644,21 +588,15 @@ namespace ts {
if (visited) {
if (isArray(visited)) {
for (let visitedNode of visited) {
visitedNode = parenthesize
? parenthesize(visitedNode, parentNode)
: visitedNode;
Debug.assertNode(visitedNode, test);
aggregateTransformFlags(visitedNode);
updated.push(visitedNode);
updated.push(<T>visitedNode);
}
}
else {
const visitedNode = parenthesize
? parenthesize(visited, parentNode)
: visited;
Debug.assertNode(visitedNode, test);
aggregateTransformFlags(visitedNode);
updated.push(visitedNode);
Debug.assertNode(visited, test);
aggregateTransformFlags(visited);
updated.push(<T>visited);
}
}
}
@ -747,6 +685,11 @@ namespace ts {
return node;
// Names
case SyntaxKind.QualifiedName:
return updateQualifiedName(<QualifiedName>node,
visitNode((<QualifiedName>node).left, visitor, isEntityName),
visitNode((<QualifiedName>node).right, visitor, isIdentifier));
case SyntaxKind.ComputedPropertyName:
return updateComputedPropertyName(<ComputedPropertyName>node,
visitNode((<ComputedPropertyName>node).expression, visitor, isExpression));
@ -761,6 +704,10 @@ namespace ts {
visitNode((<ParameterDeclaration>node).type, visitor, isTypeNode, /*optional*/ true),
visitNode((<ParameterDeclaration>node).initializer, visitor, isExpression, /*optional*/ true));
case SyntaxKind.Decorator:
return updateDecorator(<Decorator>node,
visitNode((<Decorator>node).expression, visitor, isExpression));
// Type member
case SyntaxKind.PropertyDeclaration:
return updateProperty(<PropertyDeclaration>node,
@ -856,6 +803,11 @@ namespace ts {
visitNode((<TaggedTemplateExpression>node).tag, visitor, isExpression),
visitNode((<TaggedTemplateExpression>node).template, visitor, isTemplateLiteral));
case SyntaxKind.TypeAssertionExpression:
return updateTypeAssertion(<TypeAssertion>node,
visitNode((<TypeAssertion>node).type, visitor, isTypeNode),
visitNode((<TypeAssertion>node).expression, visitor, isExpression));
case SyntaxKind.ParenthesizedExpression:
return updateParen(<ParenthesizedExpression>node,
visitNode((<ParenthesizedExpression>node).expression, visitor, isExpression));
@ -938,6 +890,15 @@ namespace ts {
visitNodes((<ExpressionWithTypeArguments>node).typeArguments, visitor, isTypeNode),
visitNode((<ExpressionWithTypeArguments>node).expression, visitor, isExpression));
case SyntaxKind.AsExpression:
return updateAsExpression(<AsExpression>node,
visitNode((<AsExpression>node).expression, visitor, isExpression),
visitNode((<AsExpression>node).type, visitor, isTypeNode));
case SyntaxKind.NonNullExpression:
return updateNonNullExpression(<NonNullExpression>node,
visitNode((<NonNullExpression>node).expression, visitor, isExpression));
// Misc
case SyntaxKind.TemplateSpan:
return updateTemplateSpan(<TemplateSpan>node,
@ -1059,10 +1020,35 @@ namespace ts {
visitNodes((<ClassDeclaration>node).heritageClauses, visitor, isHeritageClause),
visitNodes((<ClassDeclaration>node).members, visitor, isClassElement));
case SyntaxKind.EnumDeclaration:
return updateEnumDeclaration(<EnumDeclaration>node,
visitNodes((<EnumDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<EnumDeclaration>node).modifiers, visitor, isModifier),
visitNode((<EnumDeclaration>node).name, visitor, isIdentifier),
visitNodes((<EnumDeclaration>node).members, visitor, isEnumMember));
case SyntaxKind.ModuleDeclaration:
return updateModuleDeclaration(<ModuleDeclaration>node,
visitNodes((<ModuleDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<ModuleDeclaration>node).modifiers, visitor, isModifier),
visitNode((<ModuleDeclaration>node).name, visitor, isIdentifier),
visitNode((<ModuleDeclaration>node).body, visitor, isModuleBody));
case SyntaxKind.ModuleBlock:
return updateModuleBlock(<ModuleBlock>node,
visitNodes((<ModuleBlock>node).statements, visitor, isStatement));
case SyntaxKind.CaseBlock:
return updateCaseBlock(<CaseBlock>node,
visitNodes((<CaseBlock>node).clauses, visitor, isCaseOrDefaultClause));
case SyntaxKind.ImportEqualsDeclaration:
return updateImportEqualsDeclaration(<ImportEqualsDeclaration>node,
visitNodes((<ImportEqualsDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<ImportEqualsDeclaration>node).modifiers, visitor, isModifier),
visitNode((<ImportEqualsDeclaration>node).name, visitor, isIdentifier),
visitNode((<ImportEqualsDeclaration>node).moduleReference, visitor, isModuleReference));
case SyntaxKind.ImportDeclaration:
return updateImportDeclaration(<ImportDeclaration>node,
visitNodes((<ImportDeclaration>node).decorators, visitor, isDecorator),
@ -1110,6 +1096,11 @@ namespace ts {
visitNode((<ExportSpecifier>node).propertyName, visitor, isIdentifier, /*optional*/ true),
visitNode((<ExportSpecifier>node).name, visitor, isIdentifier));
// Module references
case SyntaxKind.ExternalModuleReference:
return updateExternalModuleReference(<ExternalModuleReference>node,
visitNode((<ExternalModuleReference>node).expression, visitor, isExpression));
// JSX
case SyntaxKind.JsxElement:
return updateJsxElement(<JsxElement>node,
@ -1175,10 +1166,16 @@ namespace ts {
visitNode((<ShorthandPropertyAssignment>node).objectAssignmentInitializer, visitor, isExpression));
case SyntaxKind.SpreadAssignment:
return updateSpreadAssignment(node as SpreadAssignment,
visitNode((node as SpreadAssignment).expression, visitor, isExpression));
return updateSpreadAssignment(<SpreadAssignment>node,
visitNode((<SpreadAssignment>node).expression, visitor, isExpression));
// Top-level nodes
// Enum
case SyntaxKind.EnumMember:
return updateEnumMember(<EnumMember>node,
visitNode((<EnumMember>node).name, visitor, isPropertyName),
visitNode((<EnumMember>node).initializer, visitor, isExpression, /*optional*/ true));
// Top-level nodes
case SyntaxKind.SourceFile:
return updateSourceFileNode(<SourceFile>node,
visitLexicalEnvironment((<SourceFile>node).statements, visitor, context));
@ -1189,30 +1186,8 @@ namespace ts {
visitNode((<PartiallyEmittedExpression>node).expression, visitor, isExpression));
default:
let updated: Node & MapLike<any>;
const edgeTraversalPath = getNodeEdgeTraversal(kind);
if (edgeTraversalPath) {
for (const edge of edgeTraversalPath) {
const value = <Node | NodeArray<Node>>(<Node & MapLike<any>>node)[edge.name];
if (value !== undefined) {
const visited = isArray(value)
? visitNodes(value, visitor, edge.test, 0, value.length, edge.parenthesize, node)
: visitNode(value, visitor, edge.test, edge.optional, edge.lift, edge.parenthesize, node);
if (updated !== undefined || visited !== value) {
if (updated === undefined) {
updated = getMutableClone(node);
}
if (visited !== value) {
updated[edge.name] = visited;
}
}
}
}
}
return updated ? updateNode(updated, node) : node;
return node;
}
// return node;
}
/**