From fd1e5ab6ed75e793bd1d0e42f4d3bafbedfb7e8a Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 22 Jun 2017 08:55:18 -1000 Subject: [PATCH] Simplify forEachChild --- src/compiler/parser.ts | 166 +++++++++++++++++++---------------------- 1 file changed, 78 insertions(+), 88 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index a8234b850e2..47e8157b8a7 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -22,20 +22,15 @@ namespace ts { } } - function visitNode(cbNode: (node: Node) => T, node?: Node): T | undefined { - if (node) { - return cbNode(node); - } + function visitNode(cbNode: (node: Node) => T, node: Node): T | undefined { + return node && cbNode(node); } - function visitNodeArray(cbNodes: (nodes: Node[]) => T, nodes?: Node[]): T | undefined { - if (nodes) { - return cbNodes(nodes); - } - } - - function visitEachNode(cbNode: (node: Node) => T, nodes?: Node[]): T | undefined { + function visitNodes(cbNode: (node: Node) => T, cbNodes: (node: NodeArray) => T | undefined, nodes: NodeArray): T | undefined { if (nodes) { + if (cbNodes) { + return cbNodes(nodes); + } for (const node of nodes) { const result = cbNode(node); if (result) { @@ -53,17 +48,12 @@ namespace ts { * * @param node a given node to visit its children * @param cbNode a callback to be invoked for all child nodes - * @param cbNodeArray a callback to be invoked for embedded array + * @param cbNodes a callback to be invoked for embedded array */ - export function forEachChild(node: Node, cbNode: (node: Node) => T | undefined, cbNodeArray?: (nodes: NodeArray) => T | undefined): T | undefined { + export function forEachChild(node: Node, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { if (!node) { return; } - // The visitXXX functions could be written as local functions that close over the cbNode and cbNodeArray - // callback parameters, but that causes a closure allocation for each invocation with noticeable effects - // on performance. - const visitNodes: (cb: ((node?: Node) => T | undefined) | ((node?: Node[]) => T | undefined), nodes?: Node[]) => T | undefined = cbNodeArray ? visitNodeArray : visitEachNode; - const cbNodes = cbNodeArray || cbNode; switch (node.kind) { case SyntaxKind.QualifiedName: return visitNode(cbNode, (node).left) || @@ -74,8 +64,8 @@ namespace ts { visitNode(cbNode, (node).default) || visitNode(cbNode, (node).expression); case SyntaxKind.ShorthandPropertyAssignment: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || + return visitNodes(cbNode, cbNodes, node.decorators) || + visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, (node).name) || visitNode(cbNode, (node).questionToken) || visitNode(cbNode, (node).equalsToken) || @@ -88,8 +78,8 @@ namespace ts { case SyntaxKind.PropertyAssignment: case SyntaxKind.VariableDeclaration: case SyntaxKind.BindingElement: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || + return visitNodes(cbNode, cbNodes, node.decorators) || + visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, (node).propertyName) || visitNode(cbNode, (node).dotDotDotToken) || visitNode(cbNode, (node).name) || @@ -101,10 +91,10 @@ namespace ts { case SyntaxKind.CallSignature: case SyntaxKind.ConstructSignature: case SyntaxKind.IndexSignature: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNodes(cbNodes, (node).typeParameters) || - visitNodes(cbNodes, (node).parameters) || + return visitNodes(cbNode, cbNodes, node.decorators) || + visitNodes(cbNode, cbNodes, node.modifiers) || + visitNodes(cbNode, cbNodes, (node).typeParameters) || + visitNodes(cbNode, cbNodes, (node).parameters) || visitNode(cbNode, (node).type); case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: @@ -114,33 +104,33 @@ namespace ts { case SyntaxKind.FunctionExpression: case SyntaxKind.FunctionDeclaration: case SyntaxKind.ArrowFunction: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || + return visitNodes(cbNode, cbNodes, node.decorators) || + visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, (node).asteriskToken) || visitNode(cbNode, (node).name) || visitNode(cbNode, (node).questionToken) || - visitNodes(cbNodes, (node).typeParameters) || - visitNodes(cbNodes, (node).parameters) || + visitNodes(cbNode, cbNodes, (node).typeParameters) || + visitNodes(cbNode, cbNodes, (node).parameters) || visitNode(cbNode, (node).type) || visitNode(cbNode, (node).equalsGreaterThanToken) || visitNode(cbNode, (node).body); case SyntaxKind.TypeReference: return visitNode(cbNode, (node).typeName) || - visitNodes(cbNodes, (node).typeArguments); + visitNodes(cbNode, cbNodes, (node).typeArguments); case SyntaxKind.TypePredicate: return visitNode(cbNode, (node).parameterName) || visitNode(cbNode, (node).type); case SyntaxKind.TypeQuery: return visitNode(cbNode, (node).exprName); case SyntaxKind.TypeLiteral: - return visitNodes(cbNodes, (node).members); + return visitNodes(cbNode, cbNodes, (node).members); case SyntaxKind.ArrayType: return visitNode(cbNode, (node).elementType); case SyntaxKind.TupleType: - return visitNodes(cbNodes, (node).elementTypes); + return visitNodes(cbNode, cbNodes, (node).elementTypes); case SyntaxKind.UnionType: case SyntaxKind.IntersectionType: - return visitNodes(cbNodes, (node).types); + return visitNodes(cbNode, cbNodes, (node).types); case SyntaxKind.ParenthesizedType: case SyntaxKind.TypeOperator: return visitNode(cbNode, (node).type); @@ -156,11 +146,11 @@ namespace ts { return visitNode(cbNode, (node).literal); case SyntaxKind.ObjectBindingPattern: case SyntaxKind.ArrayBindingPattern: - return visitNodes(cbNodes, (node).elements); + return visitNodes(cbNode, cbNodes, (node).elements); case SyntaxKind.ArrayLiteralExpression: - return visitNodes(cbNodes, (node).elements); + return visitNodes(cbNode, cbNodes, (node).elements); case SyntaxKind.ObjectLiteralExpression: - return visitNodes(cbNodes, (node).properties); + return visitNodes(cbNode, cbNodes, (node).properties); case SyntaxKind.PropertyAccessExpression: return visitNode(cbNode, (node).expression) || visitNode(cbNode, (node).name); @@ -170,8 +160,8 @@ namespace ts { case SyntaxKind.CallExpression: case SyntaxKind.NewExpression: return visitNode(cbNode, (node).expression) || - visitNodes(cbNodes, (node).typeArguments) || - visitNodes(cbNodes, (node).arguments); + visitNodes(cbNode, cbNodes, (node).typeArguments) || + visitNodes(cbNode, cbNodes, (node).arguments); case SyntaxKind.TaggedTemplateExpression: return visitNode(cbNode, (node).tag) || visitNode(cbNode, (node).template); @@ -216,16 +206,16 @@ namespace ts { return visitNode(cbNode, (node).expression); case SyntaxKind.Block: case SyntaxKind.ModuleBlock: - return visitNodes(cbNodes, (node).statements); + return visitNodes(cbNode, cbNodes, (node).statements); case SyntaxKind.SourceFile: - return visitNodes(cbNodes, (node).statements) || + return visitNodes(cbNode, cbNodes, (node).statements) || visitNode(cbNode, (node).endOfFileToken); case SyntaxKind.VariableStatement: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || + return visitNodes(cbNode, cbNodes, node.decorators) || + visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, (node).declarationList); case SyntaxKind.VariableDeclarationList: - return visitNodes(cbNodes, (node).declarations); + return visitNodes(cbNode, cbNodes, (node).declarations); case SyntaxKind.ExpressionStatement: return visitNode(cbNode, (node).expression); case SyntaxKind.IfStatement: @@ -264,12 +254,12 @@ namespace ts { return visitNode(cbNode, (node).expression) || visitNode(cbNode, (node).caseBlock); case SyntaxKind.CaseBlock: - return visitNodes(cbNodes, (node).clauses); + return visitNodes(cbNode, cbNodes, (node).clauses); case SyntaxKind.CaseClause: return visitNode(cbNode, (node).expression) || - visitNodes(cbNodes, (node).statements); + visitNodes(cbNode, cbNodes, (node).statements); case SyntaxKind.DefaultClause: - return visitNodes(cbNodes, (node).statements); + return visitNodes(cbNode, cbNodes, (node).statements); case SyntaxKind.LabeledStatement: return visitNode(cbNode, (node).label) || visitNode(cbNode, (node).statement); @@ -286,46 +276,46 @@ namespace ts { return visitNode(cbNode, (node).expression); case SyntaxKind.ClassDeclaration: case SyntaxKind.ClassExpression: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || + return visitNodes(cbNode, cbNodes, node.decorators) || + visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, (node).name) || - visitNodes(cbNodes, (node).typeParameters) || - visitNodes(cbNodes, (node).heritageClauses) || - visitNodes(cbNodes, (node).members); + visitNodes(cbNode, cbNodes, (node).typeParameters) || + visitNodes(cbNode, cbNodes, (node).heritageClauses) || + visitNodes(cbNode, cbNodes, (node).members); case SyntaxKind.InterfaceDeclaration: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || + return visitNodes(cbNode, cbNodes, node.decorators) || + visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, (node).name) || - visitNodes(cbNodes, (node).typeParameters) || - visitNodes(cbNodes, (node).heritageClauses) || - visitNodes(cbNodes, (node).members); + visitNodes(cbNode, cbNodes, (node).typeParameters) || + visitNodes(cbNode, cbNodes, (node).heritageClauses) || + visitNodes(cbNode, cbNodes, (node).members); case SyntaxKind.TypeAliasDeclaration: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || + return visitNodes(cbNode, cbNodes, node.decorators) || + visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, (node).name) || - visitNodes(cbNodes, (node).typeParameters) || + visitNodes(cbNode, cbNodes, (node).typeParameters) || visitNode(cbNode, (node).type); case SyntaxKind.EnumDeclaration: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || + return visitNodes(cbNode, cbNodes, node.decorators) || + visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, (node).name) || - visitNodes(cbNodes, (node).members); + visitNodes(cbNode, cbNodes, (node).members); case SyntaxKind.EnumMember: return visitNode(cbNode, (node).name) || visitNode(cbNode, (node).initializer); case SyntaxKind.ModuleDeclaration: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || + return visitNodes(cbNode, cbNodes, node.decorators) || + visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, (node).name) || visitNode(cbNode, (node).body); case SyntaxKind.ImportEqualsDeclaration: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || + return visitNodes(cbNode, cbNodes, node.decorators) || + visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, (node).name) || visitNode(cbNode, (node).moduleReference); case SyntaxKind.ImportDeclaration: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || + return visitNodes(cbNode, cbNodes, node.decorators) || + visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, (node).importClause) || visitNode(cbNode, (node).moduleSpecifier); case SyntaxKind.ImportClause: @@ -338,10 +328,10 @@ namespace ts { return visitNode(cbNode, (node).name); case SyntaxKind.NamedImports: case SyntaxKind.NamedExports: - return visitNodes(cbNodes, (node).elements); + return visitNodes(cbNode, cbNodes, (node).elements); case SyntaxKind.ExportDeclaration: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || + return visitNodes(cbNode, cbNodes, node.decorators) || + visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, (node).exportClause) || visitNode(cbNode, (node).moduleSpecifier); case SyntaxKind.ImportSpecifier: @@ -349,37 +339,37 @@ namespace ts { return visitNode(cbNode, (node).propertyName) || visitNode(cbNode, (node).name); case SyntaxKind.ExportAssignment: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || + return visitNodes(cbNode, cbNodes, node.decorators) || + visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, (node).expression); case SyntaxKind.TemplateExpression: - return visitNode(cbNode, (node).head) || visitNodes(cbNodes, (node).templateSpans); + return visitNode(cbNode, (node).head) || visitNodes(cbNode, cbNodes, (node).templateSpans); case SyntaxKind.TemplateSpan: return visitNode(cbNode, (node).expression) || visitNode(cbNode, (node).literal); case SyntaxKind.ComputedPropertyName: return visitNode(cbNode, (node).expression); case SyntaxKind.HeritageClause: - return visitNodes(cbNodes, (node).types); + return visitNodes(cbNode, cbNodes, (node).types); case SyntaxKind.ExpressionWithTypeArguments: return visitNode(cbNode, (node).expression) || - visitNodes(cbNodes, (node).typeArguments); + visitNodes(cbNode, cbNodes, (node).typeArguments); case SyntaxKind.ExternalModuleReference: return visitNode(cbNode, (node).expression); case SyntaxKind.MissingDeclaration: - return visitNodes(cbNodes, node.decorators); + return visitNodes(cbNode, cbNodes, node.decorators); case SyntaxKind.CommaListExpression: - return visitNodes(cbNodes, (node).elements); + return visitNodes(cbNode, cbNodes, (node).elements); case SyntaxKind.JsxElement: return visitNode(cbNode, (node).openingElement) || - visitNodes(cbNodes, (node).children) || + visitNodes(cbNode, cbNodes, (node).children) || visitNode(cbNode, (node).closingElement); case SyntaxKind.JsxSelfClosingElement: case SyntaxKind.JsxOpeningElement: return visitNode(cbNode, (node).tagName) || visitNode(cbNode, (node).attributes); case SyntaxKind.JsxAttributes: - return visitNodes(cbNodes, (node).properties); + return visitNodes(cbNode, cbNodes, (node).properties); case SyntaxKind.JsxAttribute: return visitNode(cbNode, (node).name) || visitNode(cbNode, (node).initializer); @@ -394,9 +384,9 @@ namespace ts { case SyntaxKind.JSDocTypeExpression: return visitNode(cbNode, (node).type); case SyntaxKind.JSDocUnionType: - return visitNodes(cbNodes, (node).types); + return visitNodes(cbNode, cbNodes, (node).types); case SyntaxKind.JSDocTupleType: - return visitNodes(cbNodes, (node).types); + return visitNodes(cbNode, cbNodes, (node).types); case SyntaxKind.JSDocArrayType: return visitNode(cbNode, (node).elementType); case SyntaxKind.JSDocNonNullableType: @@ -407,11 +397,11 @@ namespace ts { return visitNode(cbNode, (node).literal); case SyntaxKind.JSDocTypeReference: return visitNode(cbNode, (node).name) || - visitNodes(cbNodes, (node).typeArguments); + visitNodes(cbNode, cbNodes, (node).typeArguments); case SyntaxKind.JSDocOptionalType: return visitNode(cbNode, (node).type); case SyntaxKind.JSDocFunctionType: - return visitNodes(cbNodes, (node).parameters) || + return visitNodes(cbNode, cbNodes, (node).parameters) || visitNode(cbNode, (node).type); case SyntaxKind.JSDocVariadicType: return visitNode(cbNode, (node).type); @@ -423,7 +413,7 @@ namespace ts { return visitNode(cbNode, (node).name) || visitNode(cbNode, (node).type); case SyntaxKind.JSDocComment: - return visitNodes(cbNodes, (node).tags); + return visitNodes(cbNode, cbNodes, (node).tags); case SyntaxKind.JSDocParameterTag: return visitNode(cbNode, (node).preParameterName) || visitNode(cbNode, (node).typeExpression) || @@ -435,14 +425,14 @@ namespace ts { case SyntaxKind.JSDocAugmentsTag: return visitNode(cbNode, (node).typeExpression); case SyntaxKind.JSDocTemplateTag: - return visitNodes(cbNodes, (node).typeParameters); + return visitNodes(cbNode, cbNodes, (node).typeParameters); case SyntaxKind.JSDocTypedefTag: return visitNode(cbNode, (node).typeExpression) || visitNode(cbNode, (node).fullName) || visitNode(cbNode, (node).name) || visitNode(cbNode, (node).jsDocTypeLiteral); case SyntaxKind.JSDocTypeLiteral: - return visitNodes(cbNodes, (node).jsDocPropertyTags); + return visitNodes(cbNode, cbNodes, (node).jsDocPropertyTags); case SyntaxKind.JSDocPropertyTag: return visitNode(cbNode, (node).typeExpression) || visitNode(cbNode, (node).name);