namespace ts { const isTypeNodeOrTypeParameterDeclaration = or(isTypeNode, isTypeParameterDeclaration); /** * Visits a Node using the supplied visitor, possibly returning a new Node in its place. * * @param node The Node to visit. * @param visitor The callback used to visit the Node. * @param test A callback to execute to verify the Node is valid. * @param lift An optional callback to execute to lift a NodeArray into a valid Node. */ export function visitNode(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray) => T): T; /** * Visits a Node using the supplied visitor, possibly returning a new Node in its place. * * @param node The Node to visit. * @param visitor The callback used to visit the Node. * @param test A callback to execute to verify the Node is valid. * @param lift An optional callback to execute to lift a NodeArray into a valid Node. */ export function visitNode(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray) => T): T | undefined; export function visitNode(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray) => T): T | undefined { if (node === undefined || visitor === undefined) { return node; } aggregateTransformFlags(node); const visited = visitor(node); if (visited === node) { return node; } let visitedNode: Node | undefined; if (visited === undefined) { return undefined; } else if (isArray(visited)) { visitedNode = (lift || extractSingleNode)(visited); } else { visitedNode = visited; } Debug.assertNode(visitedNode, test); aggregateTransformFlags(visitedNode!); return visitedNode; } /** * Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place. * * @param nodes The NodeArray to visit. * @param visitor The callback used to visit a Node. * @param test A node test to execute for each node. * @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 | undefined, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray; /** * Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place. * * @param nodes The NodeArray to visit. * @param visitor The callback used to visit a Node. * @param test A node test to execute for each node. * @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 | undefined, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray | undefined; /** * Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place. * * @param nodes The NodeArray to visit. * @param visitor The callback used to visit a Node. * @param test A node test to execute for each node. * @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 | undefined, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray | undefined { if (nodes === undefined || visitor === undefined) { return nodes; } let updated: MutableNodeArray | undefined; // Ensure start and count have valid values const length = nodes.length; if (start === undefined || start < 0) { start = 0; } if (count === undefined || count > length - start) { count = length - start; } if (start > 0 || count < length) { // 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([], /*hasTrailingComma*/ nodes.hasTrailingComma && start + count === length); } // Visit each original node. for (let i = 0; i < count; i++) { const node: T = nodes[i + start]; aggregateTransformFlags(node); const visited = node !== undefined ? visitor(node) : undefined; if (updated !== undefined || visited === undefined || visited !== node) { if (updated === undefined) { // Ensure we have a copy of `nodes`, up to the current index. updated = createNodeArray(nodes.slice(0, i), nodes.hasTrailingComma); setTextRange(updated, nodes); } if (visited) { if (isArray(visited)) { for (const visitedNode of visited) { Debug.assertNode(visitedNode, test); aggregateTransformFlags(visitedNode); updated.push(visitedNode); } } else { Debug.assertNode(visited, test); aggregateTransformFlags(visited); updated.push(visited); } } } } return updated || nodes; } /** * 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: Visitor, context: TransformationContext, start?: number, ensureUseStrict?: boolean) { context.startLexicalEnvironment(); statements = visitNodes(statements, visitor, isStatement, start); if (ensureUseStrict) statements = ts.ensureUseStrict(statements); // eslint-disable-line @typescript-eslint/no-unnecessary-qualifier return mergeLexicalEnvironment(statements, context.endLexicalEnvironment()); } /** * Starts a new lexical environment and visits a parameter list, suspending the lexical * environment upon completion. */ export function visitParameterList(nodes: NodeArray | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes) { context.startLexicalEnvironment(); const updated = nodesVisitor(nodes, visitor, isParameterDeclaration); context.suspendLexicalEnvironment(); return updated; } /** * 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: Visitor, context: TransformationContext): FunctionBody; /** * 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 | undefined, visitor: Visitor, context: TransformationContext): FunctionBody | undefined; /** * 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: Visitor, context: TransformationContext): ConciseBody; export function visitFunctionBody(node: ConciseBody | undefined, visitor: Visitor, context: TransformationContext): ConciseBody | undefined { context.resumeLexicalEnvironment(); const updated = visitNode(node, visitor, isConciseBody); const declarations = context.endLexicalEnvironment(); if (some(declarations)) { const block = convertToFunctionBody(updated); const statements = mergeLexicalEnvironment(block.statements, declarations); return updateBlock(block, statements); } return updated; } /** * Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place. * * @param node The Node whose children will be visited. * @param visitor The callback used to visit each child. * @param context A lexical environment context for the visitor. */ export function visitEachChild(node: T, visitor: Visitor, context: TransformationContext): T; /** * Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place. * * @param node The Node whose children will be visited. * @param visitor The callback used to visit each child. * @param context A lexical environment context for the visitor. */ export function visitEachChild(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes, tokenVisitor?: Visitor): T | undefined; export function visitEachChild(node: Node | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes, tokenVisitor?: Visitor): Node | undefined { if (node === undefined) { return undefined; } const kind = node.kind; // No need to visit nodes with no children. if ((kind > SyntaxKind.FirstToken && kind <= SyntaxKind.LastToken) || kind === SyntaxKind.ThisType) { return node; } switch (kind) { // Names case SyntaxKind.Identifier: return updateIdentifier(node, nodesVisitor((node).typeArguments, visitor, isTypeNodeOrTypeParameterDeclaration)); case SyntaxKind.QualifiedName: return updateQualifiedName(node, visitNode((node).left, visitor, isEntityName), visitNode((node).right, visitor, isIdentifier)); case SyntaxKind.ComputedPropertyName: return updateComputedPropertyName(node, visitNode((node).expression, visitor, isExpression)); // Signature elements case SyntaxKind.TypeParameter: return updateTypeParameterDeclaration(node, visitNode((node).name, visitor, isIdentifier), visitNode((node).constraint, visitor, isTypeNode), visitNode((node).default, visitor, isTypeNode)); case SyntaxKind.Parameter: return updateParameter(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).dotDotDotToken, tokenVisitor, isToken), visitNode((node).name, visitor, isBindingName), visitNode((node).questionToken, tokenVisitor, isToken), visitNode((node).type, visitor, isTypeNode), visitNode((node).initializer, visitor, isExpression)); case SyntaxKind.Decorator: return updateDecorator(node, visitNode((node).expression, visitor, isExpression)); // Type elements case SyntaxKind.PropertySignature: return updatePropertySignature((node), nodesVisitor((node).modifiers, visitor, isToken), visitNode((node).name, visitor, isPropertyName), visitNode((node).questionToken, tokenVisitor, isToken), visitNode((node).type, visitor, isTypeNode), visitNode((node).initializer, visitor, isExpression)); case SyntaxKind.PropertyDeclaration: return updateProperty(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isPropertyName), // QuestionToken and ExclamationToken is uniqued in Property Declaration and the signature of 'updateProperty' is that too visitNode((node).questionToken || (node).exclamationToken, tokenVisitor, isToken), visitNode((node).type, visitor, isTypeNode), visitNode((node).initializer, visitor, isExpression)); case SyntaxKind.MethodSignature: return updateMethodSignature(node, nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor((node).parameters, visitor, isParameterDeclaration), visitNode((node).type, visitor, isTypeNode), visitNode((node).name, visitor, isPropertyName), visitNode((node).questionToken, tokenVisitor, isToken)); case SyntaxKind.MethodDeclaration: return updateMethod(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).asteriskToken, tokenVisitor, isToken), visitNode((node).name, visitor, isPropertyName), visitNode((node).questionToken, tokenVisitor, isToken), nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), visitParameterList((node).parameters, visitor, context, nodesVisitor), visitNode((node).type, visitor, isTypeNode), visitFunctionBody((node).body!, visitor, context)); case SyntaxKind.Constructor: return updateConstructor(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitParameterList((node).parameters, visitor, context, nodesVisitor), visitFunctionBody((node).body!, visitor, context)); case SyntaxKind.GetAccessor: return updateGetAccessor(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isPropertyName), visitParameterList((node).parameters, visitor, context, nodesVisitor), visitNode((node).type, visitor, isTypeNode), visitFunctionBody((node).body!, visitor, context)); case SyntaxKind.SetAccessor: return updateSetAccessor(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isPropertyName), visitParameterList((node).parameters, visitor, context, nodesVisitor), visitFunctionBody((node).body!, visitor, context)); case SyntaxKind.CallSignature: return updateCallSignature(node, nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor((node).parameters, visitor, isParameterDeclaration), visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.ConstructSignature: return updateConstructSignature(node, nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor((node).parameters, visitor, isParameterDeclaration), visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.IndexSignature: return updateIndexSignature(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), nodesVisitor((node).parameters, visitor, isParameterDeclaration), visitNode((node).type, visitor, isTypeNode)); // Types case SyntaxKind.TypePredicate: return updateTypePredicateNodeWithModifier(node, visitNode((node).assertsModifier, visitor), visitNode((node).parameterName, visitor), visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.TypeReference: return updateTypeReferenceNode(node, visitNode((node).typeName, visitor, isEntityName), nodesVisitor((node).typeArguments, visitor, isTypeNode)); case SyntaxKind.FunctionType: return updateFunctionTypeNode(node, nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor((node).parameters, visitor, isParameterDeclaration), visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.ConstructorType: return updateConstructorTypeNode(node, nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor((node).parameters, visitor, isParameterDeclaration), visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.TypeQuery: return updateTypeQueryNode((node), visitNode((node).exprName, visitor, isEntityName)); case SyntaxKind.TypeLiteral: return updateTypeLiteralNode((node), nodesVisitor((node).members, visitor, isTypeElement)); case SyntaxKind.ArrayType: return updateArrayTypeNode(node, visitNode((node).elementType, visitor, isTypeNode)); case SyntaxKind.TupleType: return updateTupleTypeNode((node), nodesVisitor((node).elementTypes, visitor, isTypeNode)); case SyntaxKind.OptionalType: return updateOptionalTypeNode((node), visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.RestType: return updateRestTypeNode((node), visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.UnionType: return updateUnionTypeNode(node, nodesVisitor((node).types, visitor, isTypeNode)); case SyntaxKind.IntersectionType: return updateIntersectionTypeNode(node, nodesVisitor((node).types, visitor, isTypeNode)); case SyntaxKind.ConditionalType: return updateConditionalTypeNode(node, visitNode((node).checkType, visitor, isTypeNode), visitNode((node).extendsType, visitor, isTypeNode), visitNode((node).trueType, visitor, isTypeNode), visitNode((node).falseType, visitor, isTypeNode)); case SyntaxKind.InferType: return updateInferTypeNode(node, visitNode((node).typeParameter, visitor, isTypeParameterDeclaration)); case SyntaxKind.ImportType: return updateImportTypeNode(node, visitNode((node).argument, visitor, isTypeNode), visitNode((node).qualifier, visitor, isEntityName), visitNodes((node).typeArguments, visitor, isTypeNode), (node).isTypeOf ); case SyntaxKind.ParenthesizedType: return updateParenthesizedType(node, visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.TypeOperator: return updateTypeOperatorNode(node, visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.IndexedAccessType: return updateIndexedAccessTypeNode((node), visitNode((node).objectType, visitor, isTypeNode), visitNode((node).indexType, visitor, isTypeNode)); case SyntaxKind.MappedType: return updateMappedTypeNode((node), visitNode((node).readonlyToken, tokenVisitor, isToken), visitNode((node).typeParameter, visitor, isTypeParameterDeclaration), visitNode((node).questionToken, tokenVisitor, isToken), visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.LiteralType: return updateLiteralTypeNode(node, visitNode((node).literal, visitor, isExpression)); // Binding patterns case SyntaxKind.ObjectBindingPattern: return updateObjectBindingPattern(node, nodesVisitor((node).elements, visitor, isBindingElement)); case SyntaxKind.ArrayBindingPattern: return updateArrayBindingPattern(node, nodesVisitor((node).elements, visitor, isArrayBindingElement)); case SyntaxKind.BindingElement: return updateBindingElement(node, visitNode((node).dotDotDotToken, tokenVisitor, isToken), visitNode((node).propertyName, visitor, isPropertyName), visitNode((node).name, visitor, isBindingName), visitNode((node).initializer, visitor, isExpression)); // Expression case SyntaxKind.ArrayLiteralExpression: return updateArrayLiteral(node, nodesVisitor((node).elements, visitor, isExpression)); case SyntaxKind.ObjectLiteralExpression: return updateObjectLiteral(node, nodesVisitor((node).properties, visitor, isObjectLiteralElementLike)); case SyntaxKind.PropertyAccessExpression: if (node.flags & NodeFlags.OptionalChain) { return updatePropertyAccessChain(node, visitNode((node).expression, visitor, isExpression), visitNode((node).questionDotToken, tokenVisitor, isToken), visitNode((node).name, visitor, isIdentifier)); } return updatePropertyAccess(node, visitNode((node).expression, visitor, isExpression), visitNode((node).name, visitor, isIdentifierOrPrivateIdentifier)); case SyntaxKind.ElementAccessExpression: if (node.flags & NodeFlags.OptionalChain) { return updateElementAccessChain(node, visitNode((node).expression, visitor, isExpression), visitNode((node).questionDotToken, tokenVisitor, isToken), visitNode((node).argumentExpression, visitor, isExpression)); } return updateElementAccess(node, visitNode((node).expression, visitor, isExpression), visitNode((node).argumentExpression, visitor, isExpression)); case SyntaxKind.CallExpression: if (node.flags & NodeFlags.OptionalChain) { return updateCallChain(node, visitNode((node).expression, visitor, isExpression), visitNode((node).questionDotToken, tokenVisitor, isToken), nodesVisitor((node).typeArguments, visitor, isTypeNode), nodesVisitor((node).arguments, visitor, isExpression)); } return updateCall(node, visitNode((node).expression, visitor, isExpression), nodesVisitor((node).typeArguments, visitor, isTypeNode), nodesVisitor((node).arguments, visitor, isExpression)); case SyntaxKind.NewExpression: return updateNew(node, visitNode((node).expression, visitor, isExpression), nodesVisitor((node).typeArguments, visitor, isTypeNode), nodesVisitor((node).arguments, visitor, isExpression)); case SyntaxKind.TaggedTemplateExpression: return updateTaggedTemplate(node, visitNode((node).tag, visitor, isExpression), visitNodes((node).typeArguments, visitor, isExpression), visitNode((node).template, visitor, isTemplateLiteral)); case SyntaxKind.TypeAssertionExpression: return updateTypeAssertion(node, visitNode((node).type, visitor, isTypeNode), visitNode((node).expression, visitor, isExpression)); case SyntaxKind.ParenthesizedExpression: return updateParen(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.FunctionExpression: return updateFunctionExpression(node, nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).asteriskToken, tokenVisitor, isToken), visitNode((node).name, visitor, isIdentifier), nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), visitParameterList((node).parameters, visitor, context, nodesVisitor), visitNode((node).type, visitor, isTypeNode), visitFunctionBody((node).body, visitor, context)); case SyntaxKind.ArrowFunction: return updateArrowFunction(node, nodesVisitor((node).modifiers, visitor, isModifier), nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), visitParameterList((node).parameters, visitor, context, nodesVisitor), visitNode((node).type, visitor, isTypeNode), visitNode((node).equalsGreaterThanToken, tokenVisitor, isToken), visitFunctionBody((node).body, visitor, context)); case SyntaxKind.DeleteExpression: return updateDelete(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.TypeOfExpression: return updateTypeOf(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.VoidExpression: return updateVoid(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.AwaitExpression: return updateAwait(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.PrefixUnaryExpression: return updatePrefix(node, visitNode((node).operand, visitor, isExpression)); case SyntaxKind.PostfixUnaryExpression: return updatePostfix(node, visitNode((node).operand, visitor, isExpression)); case SyntaxKind.BinaryExpression: return updateBinary(node, visitNode((node).left, visitor, isExpression), visitNode((node).right, visitor, isExpression), visitNode((node).operatorToken, tokenVisitor, isToken)); case SyntaxKind.ConditionalExpression: return updateConditional(node, visitNode((node).condition, visitor, isExpression), visitNode((node).questionToken, tokenVisitor, isToken), visitNode((node).whenTrue, visitor, isExpression), visitNode((node).colonToken, tokenVisitor, isToken), visitNode((node).whenFalse, visitor, isExpression)); case SyntaxKind.TemplateExpression: return updateTemplateExpression(node, visitNode((node).head, visitor, isTemplateHead), nodesVisitor((node).templateSpans, visitor, isTemplateSpan)); case SyntaxKind.YieldExpression: return updateYield(node, visitNode((node).asteriskToken, tokenVisitor, isToken), visitNode((node).expression, visitor, isExpression)); case SyntaxKind.SpreadElement: return updateSpread(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.ClassExpression: return updateClassExpression(node, nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isIdentifier), nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor((node).heritageClauses, visitor, isHeritageClause), nodesVisitor((node).members, visitor, isClassElement)); case SyntaxKind.ExpressionWithTypeArguments: return updateExpressionWithTypeArguments(node, nodesVisitor((node).typeArguments, visitor, isTypeNode), visitNode((node).expression, visitor, isExpression)); case SyntaxKind.AsExpression: return updateAsExpression(node, visitNode((node).expression, visitor, isExpression), visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.NonNullExpression: return updateNonNullExpression(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.MetaProperty: return updateMetaProperty(node, visitNode((node).name, visitor, isIdentifier)); // Misc case SyntaxKind.TemplateSpan: return updateTemplateSpan(node, visitNode((node).expression, visitor, isExpression), visitNode((node).literal, visitor, isTemplateMiddleOrTemplateTail)); // Element case SyntaxKind.Block: return updateBlock(node, nodesVisitor((node).statements, visitor, isStatement)); case SyntaxKind.VariableStatement: return updateVariableStatement(node, nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).declarationList, visitor, isVariableDeclarationList)); case SyntaxKind.ExpressionStatement: return updateExpressionStatement(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.IfStatement: return updateIf(node, visitNode((node).expression, visitor, isExpression), visitNode((node).thenStatement, visitor, isStatement, liftToBlock), visitNode((node).elseStatement, visitor, isStatement, liftToBlock)); case SyntaxKind.DoStatement: return updateDo(node, visitNode((node).statement, visitor, isStatement, liftToBlock), visitNode((node).expression, visitor, isExpression)); case SyntaxKind.WhileStatement: return updateWhile(node, visitNode((node).expression, visitor, isExpression), visitNode((node).statement, visitor, isStatement, liftToBlock)); case SyntaxKind.ForStatement: return updateFor(node, visitNode((node).initializer, visitor, isForInitializer), visitNode((node).condition, visitor, isExpression), visitNode((node).incrementor, visitor, isExpression), visitNode((node).statement, visitor, isStatement, liftToBlock)); case SyntaxKind.ForInStatement: return updateForIn(node, visitNode((node).initializer, visitor, isForInitializer), visitNode((node).expression, visitor, isExpression), visitNode((node).statement, visitor, isStatement, liftToBlock)); case SyntaxKind.ForOfStatement: return updateForOf(node, visitNode((node).awaitModifier, tokenVisitor, isToken), visitNode((node).initializer, visitor, isForInitializer), visitNode((node).expression, visitor, isExpression), visitNode((node).statement, visitor, isStatement, liftToBlock)); case SyntaxKind.ContinueStatement: return updateContinue(node, visitNode((node).label, visitor, isIdentifier)); case SyntaxKind.BreakStatement: return updateBreak(node, visitNode((node).label, visitor, isIdentifier)); case SyntaxKind.ReturnStatement: return updateReturn(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.WithStatement: return updateWith(node, visitNode((node).expression, visitor, isExpression), visitNode((node).statement, visitor, isStatement, liftToBlock)); case SyntaxKind.SwitchStatement: return updateSwitch(node, visitNode((node).expression, visitor, isExpression), visitNode((node).caseBlock, visitor, isCaseBlock)); case SyntaxKind.LabeledStatement: return updateLabel(node, visitNode((node).label, visitor, isIdentifier), visitNode((node).statement, visitor, isStatement, liftToBlock)); case SyntaxKind.ThrowStatement: return updateThrow(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.TryStatement: return updateTry(node, visitNode((node).tryBlock, visitor, isBlock), visitNode((node).catchClause, visitor, isCatchClause), visitNode((node).finallyBlock, visitor, isBlock)); case SyntaxKind.VariableDeclaration: return updateTypeScriptVariableDeclaration(node, visitNode((node).name, visitor, isBindingName), visitNode((node).exclamationToken, tokenVisitor, isToken), visitNode((node).type, visitor, isTypeNode), visitNode((node).initializer, visitor, isExpression)); case SyntaxKind.VariableDeclarationList: return updateVariableDeclarationList(node, nodesVisitor((node).declarations, visitor, isVariableDeclaration)); case SyntaxKind.FunctionDeclaration: return updateFunctionDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).asteriskToken, tokenVisitor, isToken), visitNode((node).name, visitor, isIdentifier), nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), visitParameterList((node).parameters, visitor, context, nodesVisitor), visitNode((node).type, visitor, isTypeNode), visitFunctionBody((node).body, visitor, context)); case SyntaxKind.ClassDeclaration: return updateClassDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isIdentifier), nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor((node).heritageClauses, visitor, isHeritageClause), nodesVisitor((node).members, visitor, isClassElement)); case SyntaxKind.InterfaceDeclaration: return updateInterfaceDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isIdentifier), nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor((node).heritageClauses, visitor, isHeritageClause), nodesVisitor((node).members, visitor, isTypeElement)); case SyntaxKind.TypeAliasDeclaration: return updateTypeAliasDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isIdentifier), nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.EnumDeclaration: return updateEnumDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isIdentifier), nodesVisitor((node).members, visitor, isEnumMember)); case SyntaxKind.ModuleDeclaration: return updateModuleDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isIdentifier), visitNode((node).body, visitor, isModuleBody)); case SyntaxKind.ModuleBlock: return updateModuleBlock(node, nodesVisitor((node).statements, visitor, isStatement)); case SyntaxKind.CaseBlock: return updateCaseBlock(node, nodesVisitor((node).clauses, visitor, isCaseOrDefaultClause)); case SyntaxKind.NamespaceExportDeclaration: return updateNamespaceExportDeclaration(node, visitNode((node).name, visitor, isIdentifier)); case SyntaxKind.ImportEqualsDeclaration: return updateImportEqualsDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isIdentifier), visitNode((node).moduleReference, visitor, isModuleReference)); case SyntaxKind.ImportDeclaration: return updateImportDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).importClause, visitor, isImportClause), visitNode((node).moduleSpecifier, visitor, isExpression)); case SyntaxKind.ImportClause: return updateImportClause(node, visitNode((node).name, visitor, isIdentifier), visitNode((node).namedBindings, visitor, isNamedImportBindings), (node as ImportClause).isTypeOnly); case SyntaxKind.NamespaceImport: return updateNamespaceImport(node, visitNode((node).name, visitor, isIdentifier)); case SyntaxKind.NamespaceExport: return updateNamespaceExport(node, visitNode((node).name, visitor, isIdentifier)); case SyntaxKind.NamedImports: return updateNamedImports(node, nodesVisitor((node).elements, visitor, isImportSpecifier)); case SyntaxKind.ImportSpecifier: return updateImportSpecifier(node, visitNode((node).propertyName, visitor, isIdentifier), visitNode((node).name, visitor, isIdentifier)); case SyntaxKind.ExportAssignment: return updateExportAssignment(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).expression, visitor, isExpression)); case SyntaxKind.ExportDeclaration: return updateExportDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).exportClause, visitor, isNamedExportBindings), visitNode((node).moduleSpecifier, visitor, isExpression), (node as ExportDeclaration).isTypeOnly); case SyntaxKind.NamedExports: return updateNamedExports(node, nodesVisitor((node).elements, visitor, isExportSpecifier)); case SyntaxKind.ExportSpecifier: return updateExportSpecifier(node, visitNode((node).propertyName, visitor, isIdentifier), visitNode((node).name, visitor, isIdentifier)); // Module references case SyntaxKind.ExternalModuleReference: return updateExternalModuleReference(node, visitNode((node).expression, visitor, isExpression)); // JSX case SyntaxKind.JsxElement: return updateJsxElement(node, visitNode((node).openingElement, visitor, isJsxOpeningElement), nodesVisitor((node).children, visitor, isJsxChild), visitNode((node).closingElement, visitor, isJsxClosingElement)); case SyntaxKind.JsxSelfClosingElement: return updateJsxSelfClosingElement(node, visitNode((node).tagName, visitor, isJsxTagNameExpression), nodesVisitor((node).typeArguments, visitor, isTypeNode), visitNode((node).attributes, visitor, isJsxAttributes)); case SyntaxKind.JsxOpeningElement: return updateJsxOpeningElement(node, visitNode((node).tagName, visitor, isJsxTagNameExpression), nodesVisitor((node).typeArguments, visitor, isTypeNode), visitNode((node).attributes, visitor, isJsxAttributes)); case SyntaxKind.JsxClosingElement: return updateJsxClosingElement(node, visitNode((node).tagName, visitor, isJsxTagNameExpression)); case SyntaxKind.JsxFragment: return updateJsxFragment(node, visitNode((node).openingFragment, visitor, isJsxOpeningFragment), nodesVisitor((node).children, visitor, isJsxChild), visitNode((node).closingFragment, visitor, isJsxClosingFragment)); case SyntaxKind.JsxAttribute: return updateJsxAttribute(node, visitNode((node).name, visitor, isIdentifier), visitNode((node).initializer, visitor, isStringLiteralOrJsxExpression)); case SyntaxKind.JsxAttributes: return updateJsxAttributes(node, nodesVisitor((node).properties, visitor, isJsxAttributeLike)); case SyntaxKind.JsxSpreadAttribute: return updateJsxSpreadAttribute(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.JsxExpression: return updateJsxExpression(node, visitNode((node).expression, visitor, isExpression)); // Clauses case SyntaxKind.CaseClause: return updateCaseClause(node, visitNode((node).expression, visitor, isExpression), nodesVisitor((node).statements, visitor, isStatement)); case SyntaxKind.DefaultClause: return updateDefaultClause(node, nodesVisitor((node).statements, visitor, isStatement)); case SyntaxKind.HeritageClause: return updateHeritageClause(node, nodesVisitor((node).types, visitor, isExpressionWithTypeArguments)); case SyntaxKind.CatchClause: return updateCatchClause(node, visitNode((node).variableDeclaration, visitor, isVariableDeclaration), visitNode((node).block, visitor, isBlock)); // Property assignments case SyntaxKind.PropertyAssignment: return updatePropertyAssignment(node, visitNode((node).name, visitor, isPropertyName), visitNode((node).initializer, visitor, isExpression)); case SyntaxKind.ShorthandPropertyAssignment: return updateShorthandPropertyAssignment(node, visitNode((node).name, visitor, isIdentifier), visitNode((node).objectAssignmentInitializer, visitor, isExpression)); case SyntaxKind.SpreadAssignment: return updateSpreadAssignment(node, visitNode((node).expression, visitor, isExpression)); // Enum case SyntaxKind.EnumMember: return updateEnumMember(node, visitNode((node).name, visitor, isPropertyName), visitNode((node).initializer, visitor, isExpression)); // Top-level nodes case SyntaxKind.SourceFile: return updateSourceFileNode(node, visitLexicalEnvironment((node).statements, visitor, context)); // Transformation nodes case SyntaxKind.PartiallyEmittedExpression: return updatePartiallyEmittedExpression(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.CommaListExpression: return updateCommaList(node, nodesVisitor((node).elements, visitor, isExpression)); default: // No need to visit nodes with no children. return node; } } /** * Extracts the single node from a NodeArray. * * @param nodes The NodeArray. */ function extractSingleNode(nodes: readonly Node[]): Node | undefined { Debug.assert(nodes.length <= 1, "Too many nodes written to output."); return singleOrUndefined(nodes); } }