mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-03-06 02:00:01 -06:00
Add factory functions for rest of NodeEdgeTraversal
This commit is contained in:
parent
7a539d0b85
commit
bd98bc97bd
@ -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[]) {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user