From fc2cf2f78f71d4a38f39c721b6dc992f4636b163 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 7 Feb 2017 17:21:29 -0800 Subject: [PATCH] Make visitor functions public --- src/compiler/types.ts | 7 + src/compiler/visitor.ts | 1038 +++++++++++++++++++-------------------- 2 files changed, 526 insertions(+), 519 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3c859694b44..c2bf7be4d15 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3935,6 +3935,13 @@ */ export type FileTransformer = (node: SourceFile) => SourceFile; + export type VisitResult = T | T[]; + + /** + * A function that accepts and possible transforms a node. + */ + export type Visitor = (node: Node) => VisitResult; + export interface Printer { /** * Print a node and its subtree as-is, without any emit transformations. diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index fd2b0314dda..bc6afacff66 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -2,505 +2,7 @@ /// /// -/* @internal */ namespace ts { - export type VisitResult = T | T[]; - - function reduceNode(node: Node, f: (memo: T, node: Node) => T, initial: T) { - return node ? f(initial, node) : initial; - } - - function reduceNodeArray(nodes: Node[], f: (memo: T, nodes: Node[]) => T, initial: T) { - return nodes ? f(initial, nodes) : initial; - } - - /** - * Similar to `reduceLeft`, performs a reduction against each child of a node. - * 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. - * @param f The callback function - */ - export function reduceEachChild(node: Node, initial: T, cbNode: (memo: T, node: Node) => T, cbNodeArray?: (memo: T, nodes: Node[]) => T): T { - if (node === undefined) { - return initial; - } - - const reduceNodes: (nodes: Node[], f: (memo: T, node: Node | Node[]) => T, initial: T) => T = cbNodeArray ? reduceNodeArray : reduceLeft; - const cbNodes = cbNodeArray || cbNode; - const kind = node.kind; - - // No need to visit nodes with no children. - if ((kind > SyntaxKind.FirstToken && kind <= SyntaxKind.LastToken)) { - return initial; - } - - // We do not yet support types. - if ((kind >= SyntaxKind.TypePredicate && kind <= SyntaxKind.LiteralType)) { - return initial; - } - - let result = initial; - switch (node.kind) { - // Leaf nodes - case SyntaxKind.SemicolonClassElement: - case SyntaxKind.EmptyStatement: - case SyntaxKind.OmittedExpression: - case SyntaxKind.DebuggerStatement: - case SyntaxKind.NotEmittedStatement: - // No need to visit nodes with no children. - break; - - // Names - case SyntaxKind.QualifiedName: - result = reduceNode((node).left, cbNode, result); - result = reduceNode((node).right, cbNode, result); - break; - - case SyntaxKind.ComputedPropertyName: - result = reduceNode((node).expression, cbNode, result); - break; - - // Signature elements - case SyntaxKind.Parameter: - result = reduceNodes((node).decorators, cbNodes, result); - result = reduceNodes((node).modifiers, cbNodes, result); - result = reduceNode((node).name, cbNode, result); - result = reduceNode((node).type, cbNode, result); - result = reduceNode((node).initializer, cbNode, result); - break; - - case SyntaxKind.Decorator: - result = reduceNode((node).expression, cbNode, result); - break; - - // Type member - case SyntaxKind.PropertyDeclaration: - result = reduceNodes((node).decorators, cbNodes, result); - result = reduceNodes((node).modifiers, cbNodes, result); - result = reduceNode((node).name, cbNode, result); - result = reduceNode((node).type, cbNode, result); - result = reduceNode((node).initializer, cbNode, result); - break; - - case SyntaxKind.MethodDeclaration: - result = reduceNodes((node).decorators, cbNodes, result); - result = reduceNodes((node).modifiers, cbNodes, result); - result = reduceNode((node).name, cbNode, result); - result = reduceNodes((node).typeParameters, cbNodes, result); - result = reduceNodes((node).parameters, cbNodes, result); - result = reduceNode((node).type, cbNode, result); - result = reduceNode((node).body, cbNode, result); - break; - - case SyntaxKind.Constructor: - result = reduceNodes((node).modifiers, cbNodes, result); - result = reduceNodes((node).parameters, cbNodes, result); - result = reduceNode((node).body, cbNode, result); - break; - - case SyntaxKind.GetAccessor: - result = reduceNodes((node).decorators, cbNodes, result); - result = reduceNodes((node).modifiers, cbNodes, result); - result = reduceNode((node).name, cbNode, result); - result = reduceNodes((node).parameters, cbNodes, result); - result = reduceNode((node).type, cbNode, result); - result = reduceNode((node).body, cbNode, result); - break; - - case SyntaxKind.SetAccessor: - result = reduceNodes((node).decorators, cbNodes, result); - result = reduceNodes((node).modifiers, cbNodes, result); - result = reduceNode((node).name, cbNode, result); - result = reduceNodes((node).parameters, cbNodes, result); - result = reduceNode((node).body, cbNode, result); - break; - - // Binding patterns - case SyntaxKind.ObjectBindingPattern: - case SyntaxKind.ArrayBindingPattern: - result = reduceNodes((node).elements, cbNodes, result); - break; - - case SyntaxKind.BindingElement: - result = reduceNode((node).propertyName, cbNode, result); - result = reduceNode((node).name, cbNode, result); - result = reduceNode((node).initializer, cbNode, result); - break; - - // Expression - case SyntaxKind.ArrayLiteralExpression: - result = reduceNodes((node).elements, cbNodes, result); - break; - - case SyntaxKind.ObjectLiteralExpression: - result = reduceNodes((node).properties, cbNodes, result); - break; - - case SyntaxKind.PropertyAccessExpression: - result = reduceNode((node).expression, cbNode, result); - result = reduceNode((node).name, cbNode, result); - break; - - case SyntaxKind.ElementAccessExpression: - result = reduceNode((node).expression, cbNode, result); - result = reduceNode((node).argumentExpression, cbNode, result); - break; - - case SyntaxKind.CallExpression: - result = reduceNode((node).expression, cbNode, result); - result = reduceNodes((node).typeArguments, cbNodes, result); - result = reduceNodes((node).arguments, cbNodes, result); - break; - - case SyntaxKind.NewExpression: - result = reduceNode((node).expression, cbNode, result); - result = reduceNodes((node).typeArguments, cbNodes, result); - result = reduceNodes((node).arguments, cbNodes, result); - break; - - case SyntaxKind.TaggedTemplateExpression: - result = reduceNode((node).tag, cbNode, result); - result = reduceNode((node).template, cbNode, result); - break; - - case SyntaxKind.TypeAssertionExpression: - result = reduceNode((node).type, cbNode, result); - result = reduceNode((node).expression, cbNode, result); - break; - - case SyntaxKind.FunctionExpression: - result = reduceNodes((node).modifiers, cbNodes, result); - result = reduceNode((node).name, cbNode, result); - result = reduceNodes((node).typeParameters, cbNodes, result); - result = reduceNodes((node).parameters, cbNodes, result); - result = reduceNode((node).type, cbNode, result); - result = reduceNode((node).body, cbNode, result); - break; - - case SyntaxKind.ArrowFunction: - result = reduceNodes((node).modifiers, cbNodes, result); - result = reduceNodes((node).typeParameters, cbNodes, result); - result = reduceNodes((node).parameters, cbNodes, result); - result = reduceNode((node).type, cbNode, result); - result = reduceNode((node).body, cbNode, result); - break; - - case SyntaxKind.ParenthesizedExpression: - case SyntaxKind.DeleteExpression: - case SyntaxKind.TypeOfExpression: - case SyntaxKind.VoidExpression: - case SyntaxKind.AwaitExpression: - case SyntaxKind.YieldExpression: - case SyntaxKind.SpreadElement: - case SyntaxKind.NonNullExpression: - result = reduceNode((node).expression, cbNode, result); - break; - - case SyntaxKind.PrefixUnaryExpression: - case SyntaxKind.PostfixUnaryExpression: - result = reduceNode((node).operand, cbNode, result); - break; - - case SyntaxKind.BinaryExpression: - result = reduceNode((node).left, cbNode, result); - result = reduceNode((node).right, cbNode, result); - break; - - case SyntaxKind.ConditionalExpression: - result = reduceNode((node).condition, cbNode, result); - result = reduceNode((node).whenTrue, cbNode, result); - result = reduceNode((node).whenFalse, cbNode, result); - break; - - case SyntaxKind.TemplateExpression: - result = reduceNode((node).head, cbNode, result); - result = reduceNodes((node).templateSpans, cbNodes, result); - break; - - case SyntaxKind.ClassExpression: - result = reduceNodes((node).modifiers, cbNodes, result); - result = reduceNode((node).name, cbNode, result); - result = reduceNodes((node).typeParameters, cbNodes, result); - result = reduceNodes((node).heritageClauses, cbNodes, result); - result = reduceNodes((node).members, cbNodes, result); - break; - - case SyntaxKind.ExpressionWithTypeArguments: - result = reduceNode((node).expression, cbNode, result); - result = reduceNodes((node).typeArguments, cbNodes, result); - break; - - case SyntaxKind.AsExpression: - result = reduceNode((node).expression, cbNode, result); - result = reduceNode((node).type, cbNode, result); - break; - - case SyntaxKind.NonNullExpression: - result = reduceNode((node).expression, cbNode, result); - break; - - // Misc - case SyntaxKind.TemplateSpan: - result = reduceNode((node).expression, cbNode, result); - result = reduceNode((node).literal, cbNode, result); - break; - - // Element - case SyntaxKind.Block: - result = reduceNodes((node).statements, cbNodes, result); - break; - - case SyntaxKind.VariableStatement: - result = reduceNodes((node).modifiers, cbNodes, result); - result = reduceNode((node).declarationList, cbNode, result); - break; - - case SyntaxKind.ExpressionStatement: - result = reduceNode((node).expression, cbNode, result); - break; - - case SyntaxKind.IfStatement: - result = reduceNode((node).expression, cbNode, result); - result = reduceNode((node).thenStatement, cbNode, result); - result = reduceNode((node).elseStatement, cbNode, result); - break; - - case SyntaxKind.DoStatement: - result = reduceNode((node).statement, cbNode, result); - result = reduceNode((node).expression, cbNode, result); - break; - - case SyntaxKind.WhileStatement: - case SyntaxKind.WithStatement: - result = reduceNode((node).expression, cbNode, result); - result = reduceNode((node).statement, cbNode, result); - break; - - case SyntaxKind.ForStatement: - result = reduceNode((node).initializer, cbNode, result); - result = reduceNode((node).condition, cbNode, result); - result = reduceNode((node).incrementor, cbNode, result); - result = reduceNode((node).statement, cbNode, result); - break; - - case SyntaxKind.ForInStatement: - case SyntaxKind.ForOfStatement: - result = reduceNode((node).initializer, cbNode, result); - result = reduceNode((node).expression, cbNode, result); - result = reduceNode((node).statement, cbNode, result); - break; - - case SyntaxKind.ReturnStatement: - case SyntaxKind.ThrowStatement: - result = reduceNode((node).expression, cbNode, result); - break; - - case SyntaxKind.SwitchStatement: - result = reduceNode((node).expression, cbNode, result); - result = reduceNode((node).caseBlock, cbNode, result); - break; - - case SyntaxKind.LabeledStatement: - result = reduceNode((node).label, cbNode, result); - result = reduceNode((node).statement, cbNode, result); - break; - - case SyntaxKind.TryStatement: - result = reduceNode((node).tryBlock, cbNode, result); - result = reduceNode((node).catchClause, cbNode, result); - result = reduceNode((node).finallyBlock, cbNode, result); - break; - - case SyntaxKind.VariableDeclaration: - result = reduceNode((node).name, cbNode, result); - result = reduceNode((node).type, cbNode, result); - result = reduceNode((node).initializer, cbNode, result); - break; - - case SyntaxKind.VariableDeclarationList: - result = reduceNodes((node).declarations, cbNodes, result); - break; - - case SyntaxKind.FunctionDeclaration: - result = reduceNodes((node).decorators, cbNodes, result); - result = reduceNodes((node).modifiers, cbNodes, result); - result = reduceNode((node).name, cbNode, result); - result = reduceNodes((node).typeParameters, cbNodes, result); - result = reduceNodes((node).parameters, cbNodes, result); - result = reduceNode((node).type, cbNode, result); - result = reduceNode((node).body, cbNode, result); - break; - - case SyntaxKind.ClassDeclaration: - result = reduceNodes((node).decorators, cbNodes, result); - result = reduceNodes((node).modifiers, cbNodes, result); - result = reduceNode((node).name, cbNode, result); - result = reduceNodes((node).typeParameters, cbNodes, result); - result = reduceNodes((node).heritageClauses, cbNodes, result); - result = reduceNodes((node).members, cbNodes, result); - break; - - case SyntaxKind.EnumDeclaration: - result = reduceNodes((node).decorators, cbNodes, result); - result = reduceNodes((node).modifiers, cbNodes, result); - result = reduceNode((node).name, cbNode, result); - result = reduceNodes((node).members, cbNodes, result); - break; - - case SyntaxKind.ModuleDeclaration: - result = reduceNodes((node).decorators, cbNodes, result); - result = reduceNodes((node).modifiers, cbNodes, result); - result = reduceNode((node).name, cbNode, result); - result = reduceNode((node).body, cbNode, result); - break; - - case SyntaxKind.ModuleBlock: - result = reduceNodes((node).statements, cbNodes, result); - break; - - case SyntaxKind.CaseBlock: - result = reduceNodes((node).clauses, cbNodes, result); - break; - - case SyntaxKind.ImportEqualsDeclaration: - result = reduceNodes((node).decorators, cbNodes, result); - result = reduceNodes((node).modifiers, cbNodes, result); - result = reduceNode((node).name, cbNode, result); - result = reduceNode((node).moduleReference, cbNode, result); - break; - - case SyntaxKind.ImportDeclaration: - result = reduceNodes((node).decorators, cbNodes, result); - result = reduceNodes((node).modifiers, cbNodes, result); - result = reduceNode((node).importClause, cbNode, result); - result = reduceNode((node).moduleSpecifier, cbNode, result); - break; - - case SyntaxKind.ImportClause: - result = reduceNode((node).name, cbNode, result); - result = reduceNode((node).namedBindings, cbNode, result); - break; - - case SyntaxKind.NamespaceImport: - result = reduceNode((node).name, cbNode, result); - break; - - case SyntaxKind.NamedImports: - case SyntaxKind.NamedExports: - result = reduceNodes((node).elements, cbNodes, result); - break; - - case SyntaxKind.ImportSpecifier: - case SyntaxKind.ExportSpecifier: - result = reduceNode((node).propertyName, cbNode, result); - result = reduceNode((node).name, cbNode, result); - break; - - case SyntaxKind.ExportAssignment: - result = reduceLeft((node).decorators, cbNode, result); - result = reduceLeft((node).modifiers, cbNode, result); - result = reduceNode((node).expression, cbNode, result); - break; - - case SyntaxKind.ExportDeclaration: - result = reduceLeft((node).decorators, cbNode, result); - result = reduceLeft((node).modifiers, cbNode, result); - result = reduceNode((node).exportClause, cbNode, result); - result = reduceNode((node).moduleSpecifier, cbNode, result); - break; - - // Module references - case SyntaxKind.ExternalModuleReference: - result = reduceNode((node).expression, cbNode, result); - break; - - // JSX - case SyntaxKind.JsxElement: - result = reduceNode((node).openingElement, cbNode, result); - result = reduceLeft((node).children, cbNode, result); - result = reduceNode((node).closingElement, cbNode, result); - break; - - case SyntaxKind.JsxSelfClosingElement: - case SyntaxKind.JsxOpeningElement: - result = reduceNode((node).tagName, cbNode, result); - result = reduceNodes((node).attributes, cbNodes, result); - break; - - case SyntaxKind.JsxClosingElement: - result = reduceNode((node).tagName, cbNode, result); - break; - - case SyntaxKind.JsxAttribute: - result = reduceNode((node).name, cbNode, result); - result = reduceNode((node).initializer, cbNode, result); - break; - - case SyntaxKind.JsxSpreadAttribute: - result = reduceNode((node).expression, cbNode, result); - break; - - case SyntaxKind.JsxExpression: - result = reduceNode((node).expression, cbNode, result); - break; - - // Clauses - case SyntaxKind.CaseClause: - result = reduceNode((node).expression, cbNode, result); - // fall-through - - case SyntaxKind.DefaultClause: - result = reduceNodes((node).statements, cbNodes, result); - break; - - case SyntaxKind.HeritageClause: - result = reduceNodes((node).types, cbNodes, result); - break; - - case SyntaxKind.CatchClause: - result = reduceNode((node).variableDeclaration, cbNode, result); - result = reduceNode((node).block, cbNode, result); - break; - - // Property assignments - case SyntaxKind.PropertyAssignment: - result = reduceNode((node).name, cbNode, result); - result = reduceNode((node).initializer, cbNode, result); - break; - - case SyntaxKind.ShorthandPropertyAssignment: - result = reduceNode((node).name, cbNode, result); - result = reduceNode((node).objectAssignmentInitializer, cbNode, result); - break; - - case SyntaxKind.SpreadAssignment: - result = reduceNode((node).expression, cbNode, result); - break; - - // Enum - case SyntaxKind.EnumMember: - result = reduceNode((node).name, cbNode, result); - result = reduceNode((node).initializer, cbNode, result); - - // Top-level nodes - case SyntaxKind.SourceFile: - result = reduceNodes((node).statements, cbNodes, result); - break; - - // Transformation nodes - case SyntaxKind.PartiallyEmittedExpression: - result = reduceNode((node).expression, cbNode, result); - break; - - default: - break; - } - - return result; - } - /** * Visits a Node using the supplied visitor, possibly returning a new Node in its place. * @@ -510,7 +12,7 @@ namespace ts { * @param optional An optional value indicating whether the Node is itself optional. * @param lift An optional callback to execute to lift a NodeArray into a valid Node. */ - export function visitNode(node: T, visitor: (node: Node) => VisitResult, test: (node: Node) => boolean, optional?: boolean, lift?: (node: NodeArray) => T): T { + export function visitNode(node: T, visitor: Visitor, test: (node: Node) => boolean, optional?: boolean, lift?: (node: NodeArray) => T): T { if (node === undefined || visitor === undefined) { return node; } @@ -550,9 +52,9 @@ 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(nodes: NodeArray, visitor: (node: Node) => VisitResult, test: (node: Node) => boolean, start?: number, count?: number): NodeArray { - if (nodes === undefined) { - return undefined; + export function visitNodes(nodes: NodeArray, visitor: Visitor, test: (node: Node) => boolean, start?: number, count?: number): NodeArray { + if (nodes === undefined || visitor === undefined) { + return nodes; } let updated: NodeArray; @@ -609,7 +111,7 @@ namespace ts { * Starts a new lexical environment and visits a statement list, ending the lexical environment * and merging hoisted declarations upon completion. */ - export function visitLexicalEnvironment(statements: NodeArray, visitor: (node: Node) => VisitResult, context: TransformationContext, start?: number, ensureUseStrict?: boolean) { + export function visitLexicalEnvironment(statements: NodeArray, visitor: Visitor, context: TransformationContext, start?: number, ensureUseStrict?: boolean) { context.startLexicalEnvironment(); statements = visitNodes(statements, visitor, isStatement, start); if (ensureUseStrict && !startsWithUseStrict(statements)) { @@ -623,7 +125,7 @@ namespace ts { * Starts a new lexical environment and visits a parameter list, suspending the lexical * environment upon completion. */ - export function visitParameterList(nodes: NodeArray, visitor: (node: Node) => VisitResult, context: TransformationContext) { + export function visitParameterList(nodes: NodeArray, visitor: Visitor, context: TransformationContext) { context.startLexicalEnvironment(); const updated = visitNodes(nodes, visitor, isParameterDeclaration); context.suspendLexicalEnvironment(); @@ -634,13 +136,13 @@ namespace ts { * Resumes a suspended lexical environment and visits a function body, ending the lexical * environment and merging hoisted declarations upon completion. */ - export function visitFunctionBody(node: FunctionBody, visitor: (node: Node) => VisitResult, context: TransformationContext): FunctionBody; + export function visitFunctionBody(node: FunctionBody, visitor: Visitor, context: TransformationContext): FunctionBody; /** * Resumes a suspended lexical environment and visits a concise body, ending the lexical * environment and merging hoisted declarations upon completion. */ - export function visitFunctionBody(node: ConciseBody, visitor: (node: Node) => VisitResult, context: TransformationContext): ConciseBody; - export function visitFunctionBody(node: ConciseBody, visitor: (node: Node) => VisitResult, context: TransformationContext): ConciseBody { + export function visitFunctionBody(node: ConciseBody, visitor: Visitor, context: TransformationContext): ConciseBody; + export function visitFunctionBody(node: ConciseBody, visitor: Visitor, context: TransformationContext): ConciseBody { context.resumeLexicalEnvironment(); const updated = visitNode(node, visitor, isConciseBody); const declarations = context.endLexicalEnvironment(); @@ -659,8 +161,8 @@ namespace ts { * @param visitor The callback used to visit each child. * @param context A lexical environment context for the visitor. */ - export function visitEachChild(node: T, visitor: (node: Node) => VisitResult, context: TransformationContext): T; - export function visitEachChild(node: Node, visitor: (node: Node) => VisitResult, context: TransformationContext): Node { + export function visitEachChild(node: T, visitor: Visitor, context: TransformationContext): T; + export function visitEachChild(node: Node, visitor: Visitor, context: TransformationContext): Node { if (node === undefined) { return undefined; } @@ -1190,6 +692,514 @@ namespace ts { } } + /** + * Extracts the single node from a NodeArray. + * + * @param nodes The NodeArray. + */ + function extractSingleNode(nodes: Node[]): Node { + Debug.assert(nodes.length <= 1, "Too many nodes written to output."); + return singleOrUndefined(nodes); + } +} + +/* @internal */ +namespace ts { + function reduceNode(node: Node, f: (memo: T, node: Node) => T, initial: T) { + return node ? f(initial, node) : initial; + } + + function reduceNodeArray(nodes: Node[], f: (memo: T, nodes: Node[]) => T, initial: T) { + return nodes ? f(initial, nodes) : initial; + } + + /** + * Similar to `reduceLeft`, performs a reduction against each child of a node. + * 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. + * @param f The callback function + */ + export function reduceEachChild(node: Node, initial: T, cbNode: (memo: T, node: Node) => T, cbNodeArray?: (memo: T, nodes: Node[]) => T): T { + if (node === undefined) { + return initial; + } + + const reduceNodes: (nodes: Node[], f: (memo: T, node: Node | Node[]) => T, initial: T) => T = cbNodeArray ? reduceNodeArray : reduceLeft; + const cbNodes = cbNodeArray || cbNode; + const kind = node.kind; + + // No need to visit nodes with no children. + if ((kind > SyntaxKind.FirstToken && kind <= SyntaxKind.LastToken)) { + return initial; + } + + // We do not yet support types. + if ((kind >= SyntaxKind.TypePredicate && kind <= SyntaxKind.LiteralType)) { + return initial; + } + + let result = initial; + switch (node.kind) { + // Leaf nodes + case SyntaxKind.SemicolonClassElement: + case SyntaxKind.EmptyStatement: + case SyntaxKind.OmittedExpression: + case SyntaxKind.DebuggerStatement: + case SyntaxKind.NotEmittedStatement: + // No need to visit nodes with no children. + break; + + // Names + case SyntaxKind.QualifiedName: + result = reduceNode((node).left, cbNode, result); + result = reduceNode((node).right, cbNode, result); + break; + + case SyntaxKind.ComputedPropertyName: + result = reduceNode((node).expression, cbNode, result); + break; + + // Signature elements + case SyntaxKind.Parameter: + result = reduceNodes((node).decorators, cbNodes, result); + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNode((node).name, cbNode, result); + result = reduceNode((node).type, cbNode, result); + result = reduceNode((node).initializer, cbNode, result); + break; + + case SyntaxKind.Decorator: + result = reduceNode((node).expression, cbNode, result); + break; + + // Type member + case SyntaxKind.PropertyDeclaration: + result = reduceNodes((node).decorators, cbNodes, result); + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNode((node).name, cbNode, result); + result = reduceNode((node).type, cbNode, result); + result = reduceNode((node).initializer, cbNode, result); + break; + + case SyntaxKind.MethodDeclaration: + result = reduceNodes((node).decorators, cbNodes, result); + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNode((node).name, cbNode, result); + result = reduceNodes((node).typeParameters, cbNodes, result); + result = reduceNodes((node).parameters, cbNodes, result); + result = reduceNode((node).type, cbNode, result); + result = reduceNode((node).body, cbNode, result); + break; + + case SyntaxKind.Constructor: + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNodes((node).parameters, cbNodes, result); + result = reduceNode((node).body, cbNode, result); + break; + + case SyntaxKind.GetAccessor: + result = reduceNodes((node).decorators, cbNodes, result); + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNode((node).name, cbNode, result); + result = reduceNodes((node).parameters, cbNodes, result); + result = reduceNode((node).type, cbNode, result); + result = reduceNode((node).body, cbNode, result); + break; + + case SyntaxKind.SetAccessor: + result = reduceNodes((node).decorators, cbNodes, result); + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNode((node).name, cbNode, result); + result = reduceNodes((node).parameters, cbNodes, result); + result = reduceNode((node).body, cbNode, result); + break; + + // Binding patterns + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ArrayBindingPattern: + result = reduceNodes((node).elements, cbNodes, result); + break; + + case SyntaxKind.BindingElement: + result = reduceNode((node).propertyName, cbNode, result); + result = reduceNode((node).name, cbNode, result); + result = reduceNode((node).initializer, cbNode, result); + break; + + // Expression + case SyntaxKind.ArrayLiteralExpression: + result = reduceNodes((node).elements, cbNodes, result); + break; + + case SyntaxKind.ObjectLiteralExpression: + result = reduceNodes((node).properties, cbNodes, result); + break; + + case SyntaxKind.PropertyAccessExpression: + result = reduceNode((node).expression, cbNode, result); + result = reduceNode((node).name, cbNode, result); + break; + + case SyntaxKind.ElementAccessExpression: + result = reduceNode((node).expression, cbNode, result); + result = reduceNode((node).argumentExpression, cbNode, result); + break; + + case SyntaxKind.CallExpression: + result = reduceNode((node).expression, cbNode, result); + result = reduceNodes((node).typeArguments, cbNodes, result); + result = reduceNodes((node).arguments, cbNodes, result); + break; + + case SyntaxKind.NewExpression: + result = reduceNode((node).expression, cbNode, result); + result = reduceNodes((node).typeArguments, cbNodes, result); + result = reduceNodes((node).arguments, cbNodes, result); + break; + + case SyntaxKind.TaggedTemplateExpression: + result = reduceNode((node).tag, cbNode, result); + result = reduceNode((node).template, cbNode, result); + break; + + case SyntaxKind.TypeAssertionExpression: + result = reduceNode((node).type, cbNode, result); + result = reduceNode((node).expression, cbNode, result); + break; + + case SyntaxKind.FunctionExpression: + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNode((node).name, cbNode, result); + result = reduceNodes((node).typeParameters, cbNodes, result); + result = reduceNodes((node).parameters, cbNodes, result); + result = reduceNode((node).type, cbNode, result); + result = reduceNode((node).body, cbNode, result); + break; + + case SyntaxKind.ArrowFunction: + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNodes((node).typeParameters, cbNodes, result); + result = reduceNodes((node).parameters, cbNodes, result); + result = reduceNode((node).type, cbNode, result); + result = reduceNode((node).body, cbNode, result); + break; + + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.DeleteExpression: + case SyntaxKind.TypeOfExpression: + case SyntaxKind.VoidExpression: + case SyntaxKind.AwaitExpression: + case SyntaxKind.YieldExpression: + case SyntaxKind.SpreadElement: + case SyntaxKind.NonNullExpression: + result = reduceNode((node).expression, cbNode, result); + break; + + case SyntaxKind.PrefixUnaryExpression: + case SyntaxKind.PostfixUnaryExpression: + result = reduceNode((node).operand, cbNode, result); + break; + + case SyntaxKind.BinaryExpression: + result = reduceNode((node).left, cbNode, result); + result = reduceNode((node).right, cbNode, result); + break; + + case SyntaxKind.ConditionalExpression: + result = reduceNode((node).condition, cbNode, result); + result = reduceNode((node).whenTrue, cbNode, result); + result = reduceNode((node).whenFalse, cbNode, result); + break; + + case SyntaxKind.TemplateExpression: + result = reduceNode((node).head, cbNode, result); + result = reduceNodes((node).templateSpans, cbNodes, result); + break; + + case SyntaxKind.ClassExpression: + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNode((node).name, cbNode, result); + result = reduceNodes((node).typeParameters, cbNodes, result); + result = reduceNodes((node).heritageClauses, cbNodes, result); + result = reduceNodes((node).members, cbNodes, result); + break; + + case SyntaxKind.ExpressionWithTypeArguments: + result = reduceNode((node).expression, cbNode, result); + result = reduceNodes((node).typeArguments, cbNodes, result); + break; + + case SyntaxKind.AsExpression: + result = reduceNode((node).expression, cbNode, result); + result = reduceNode((node).type, cbNode, result); + break; + + case SyntaxKind.NonNullExpression: + result = reduceNode((node).expression, cbNode, result); + break; + + // Misc + case SyntaxKind.TemplateSpan: + result = reduceNode((node).expression, cbNode, result); + result = reduceNode((node).literal, cbNode, result); + break; + + // Element + case SyntaxKind.Block: + result = reduceNodes((node).statements, cbNodes, result); + break; + + case SyntaxKind.VariableStatement: + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNode((node).declarationList, cbNode, result); + break; + + case SyntaxKind.ExpressionStatement: + result = reduceNode((node).expression, cbNode, result); + break; + + case SyntaxKind.IfStatement: + result = reduceNode((node).expression, cbNode, result); + result = reduceNode((node).thenStatement, cbNode, result); + result = reduceNode((node).elseStatement, cbNode, result); + break; + + case SyntaxKind.DoStatement: + result = reduceNode((node).statement, cbNode, result); + result = reduceNode((node).expression, cbNode, result); + break; + + case SyntaxKind.WhileStatement: + case SyntaxKind.WithStatement: + result = reduceNode((node).expression, cbNode, result); + result = reduceNode((node).statement, cbNode, result); + break; + + case SyntaxKind.ForStatement: + result = reduceNode((node).initializer, cbNode, result); + result = reduceNode((node).condition, cbNode, result); + result = reduceNode((node).incrementor, cbNode, result); + result = reduceNode((node).statement, cbNode, result); + break; + + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + result = reduceNode((node).initializer, cbNode, result); + result = reduceNode((node).expression, cbNode, result); + result = reduceNode((node).statement, cbNode, result); + break; + + case SyntaxKind.ReturnStatement: + case SyntaxKind.ThrowStatement: + result = reduceNode((node).expression, cbNode, result); + break; + + case SyntaxKind.SwitchStatement: + result = reduceNode((node).expression, cbNode, result); + result = reduceNode((node).caseBlock, cbNode, result); + break; + + case SyntaxKind.LabeledStatement: + result = reduceNode((node).label, cbNode, result); + result = reduceNode((node).statement, cbNode, result); + break; + + case SyntaxKind.TryStatement: + result = reduceNode((node).tryBlock, cbNode, result); + result = reduceNode((node).catchClause, cbNode, result); + result = reduceNode((node).finallyBlock, cbNode, result); + break; + + case SyntaxKind.VariableDeclaration: + result = reduceNode((node).name, cbNode, result); + result = reduceNode((node).type, cbNode, result); + result = reduceNode((node).initializer, cbNode, result); + break; + + case SyntaxKind.VariableDeclarationList: + result = reduceNodes((node).declarations, cbNodes, result); + break; + + case SyntaxKind.FunctionDeclaration: + result = reduceNodes((node).decorators, cbNodes, result); + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNode((node).name, cbNode, result); + result = reduceNodes((node).typeParameters, cbNodes, result); + result = reduceNodes((node).parameters, cbNodes, result); + result = reduceNode((node).type, cbNode, result); + result = reduceNode((node).body, cbNode, result); + break; + + case SyntaxKind.ClassDeclaration: + result = reduceNodes((node).decorators, cbNodes, result); + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNode((node).name, cbNode, result); + result = reduceNodes((node).typeParameters, cbNodes, result); + result = reduceNodes((node).heritageClauses, cbNodes, result); + result = reduceNodes((node).members, cbNodes, result); + break; + + case SyntaxKind.EnumDeclaration: + result = reduceNodes((node).decorators, cbNodes, result); + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNode((node).name, cbNode, result); + result = reduceNodes((node).members, cbNodes, result); + break; + + case SyntaxKind.ModuleDeclaration: + result = reduceNodes((node).decorators, cbNodes, result); + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNode((node).name, cbNode, result); + result = reduceNode((node).body, cbNode, result); + break; + + case SyntaxKind.ModuleBlock: + result = reduceNodes((node).statements, cbNodes, result); + break; + + case SyntaxKind.CaseBlock: + result = reduceNodes((node).clauses, cbNodes, result); + break; + + case SyntaxKind.ImportEqualsDeclaration: + result = reduceNodes((node).decorators, cbNodes, result); + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNode((node).name, cbNode, result); + result = reduceNode((node).moduleReference, cbNode, result); + break; + + case SyntaxKind.ImportDeclaration: + result = reduceNodes((node).decorators, cbNodes, result); + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNode((node).importClause, cbNode, result); + result = reduceNode((node).moduleSpecifier, cbNode, result); + break; + + case SyntaxKind.ImportClause: + result = reduceNode((node).name, cbNode, result); + result = reduceNode((node).namedBindings, cbNode, result); + break; + + case SyntaxKind.NamespaceImport: + result = reduceNode((node).name, cbNode, result); + break; + + case SyntaxKind.NamedImports: + case SyntaxKind.NamedExports: + result = reduceNodes((node).elements, cbNodes, result); + break; + + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ExportSpecifier: + result = reduceNode((node).propertyName, cbNode, result); + result = reduceNode((node).name, cbNode, result); + break; + + case SyntaxKind.ExportAssignment: + result = reduceLeft((node).decorators, cbNode, result); + result = reduceLeft((node).modifiers, cbNode, result); + result = reduceNode((node).expression, cbNode, result); + break; + + case SyntaxKind.ExportDeclaration: + result = reduceLeft((node).decorators, cbNode, result); + result = reduceLeft((node).modifiers, cbNode, result); + result = reduceNode((node).exportClause, cbNode, result); + result = reduceNode((node).moduleSpecifier, cbNode, result); + break; + + // Module references + case SyntaxKind.ExternalModuleReference: + result = reduceNode((node).expression, cbNode, result); + break; + + // JSX + case SyntaxKind.JsxElement: + result = reduceNode((node).openingElement, cbNode, result); + result = reduceLeft((node).children, cbNode, result); + result = reduceNode((node).closingElement, cbNode, result); + break; + + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxOpeningElement: + result = reduceNode((node).tagName, cbNode, result); + result = reduceNodes((node).attributes, cbNodes, result); + break; + + case SyntaxKind.JsxClosingElement: + result = reduceNode((node).tagName, cbNode, result); + break; + + case SyntaxKind.JsxAttribute: + result = reduceNode((node).name, cbNode, result); + result = reduceNode((node).initializer, cbNode, result); + break; + + case SyntaxKind.JsxSpreadAttribute: + result = reduceNode((node).expression, cbNode, result); + break; + + case SyntaxKind.JsxExpression: + result = reduceNode((node).expression, cbNode, result); + break; + + // Clauses + case SyntaxKind.CaseClause: + result = reduceNode((node).expression, cbNode, result); + // fall-through + + case SyntaxKind.DefaultClause: + result = reduceNodes((node).statements, cbNodes, result); + break; + + case SyntaxKind.HeritageClause: + result = reduceNodes((node).types, cbNodes, result); + break; + + case SyntaxKind.CatchClause: + result = reduceNode((node).variableDeclaration, cbNode, result); + result = reduceNode((node).block, cbNode, result); + break; + + // Property assignments + case SyntaxKind.PropertyAssignment: + result = reduceNode((node).name, cbNode, result); + result = reduceNode((node).initializer, cbNode, result); + break; + + case SyntaxKind.ShorthandPropertyAssignment: + result = reduceNode((node).name, cbNode, result); + result = reduceNode((node).objectAssignmentInitializer, cbNode, result); + break; + + case SyntaxKind.SpreadAssignment: + result = reduceNode((node).expression, cbNode, result); + break; + + // Enum + case SyntaxKind.EnumMember: + result = reduceNode((node).name, cbNode, result); + result = reduceNode((node).initializer, cbNode, result); + + // Top-level nodes + case SyntaxKind.SourceFile: + result = reduceNodes((node).statements, cbNodes, result); + break; + + // Transformation nodes + case SyntaxKind.PartiallyEmittedExpression: + result = reduceNode((node).expression, cbNode, result); + break; + + default: + break; + } + + return result; + } + /** * Merges generated lexical declarations into a new statement list. */ @@ -1255,16 +1265,6 @@ namespace ts { return singleOrUndefined(nodes) || createBlock(>nodes); } - /** - * Extracts the single node from a NodeArray. - * - * @param nodes The NodeArray. - */ - function extractSingleNode(nodes: Node[]): Node { - Debug.assert(nodes.length <= 1, "Too many nodes written to output."); - return singleOrUndefined(nodes); - } - /** * Aggregates the TransformFlags for a Node and its subtree. */