TypeScript/src/compiler/visitorPublic.ts
Wenlu Wang 906cbd2715
Proposal class static block support (#43370)
* Class static block (#9)

* Add types factory and parser

* Add some case

* Make class static block as a container

* Update cases

* Add visitor

* Add emitter and more compile target

* Check boundary of break and continue

* Add basic transformer

* Fix emit behavior

* Add more tests

* Add friend tests

* Update baseline

* Fix cr issues

* Accept baseline

* Add decorator and modifier check

* Add functional boundary check

* Fix conflict

* Fix computed prop name within context

* Add more tests

* Update baseline

* Avoid invalid test baseline

* Support use before initialize check

* wip

* Fix class static block context

* Fix checks

* Fix missing case

* Improve assert message

* Accept baseline

* Avoid new context

* Update diagnostic message

* Fix name collision

* Fix targets

* Avoid unnecessary files

* Add more case

* Add more test cases

* Fix strict mode function declaration

* Avoid private fields initializer if no private identifier references

* Avoid private fields and add more test case

* Add more case

* Add tests and support for related services functionality

* Fix this reference in static block

* Split parser diagnostic and binder diagnostic

Co-authored-by: Ron Buckton <ron.buckton@microsoft.com>
2021-06-25 09:24:05 -07:00

1279 lines
67 KiB
TypeScript

namespace ts {
/**
* 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<T extends Node>(node: T, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: readonly Node[]) => 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<T extends Node>(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: readonly Node[]) => T): T | undefined;
export function visitNode<T extends Node>(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: readonly Node[]) => T): T | undefined {
if (node === undefined || visitor === undefined) {
return 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);
return visitedNode as T;
}
/**
* 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<T extends Node>(nodes: NodeArray<T>, visitor: Visitor | undefined, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray<T>;
/**
* 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<T extends Node>(nodes: NodeArray<T> | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray<T> | 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<T extends Node>(nodes: NodeArray<T> | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray<T> | undefined {
if (nodes === undefined || visitor === undefined) {
return nodes;
}
let updated: T[] | 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;
}
let hasTrailingComma: boolean | undefined;
let pos = -1;
let end = -1;
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 = [];
hasTrailingComma = nodes.hasTrailingComma && start + count === length;
}
// Visit each original node.
for (let i = 0; i < count; i++) {
const node: T = nodes[i + start];
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 = nodes.slice(0, i);
hasTrailingComma = nodes.hasTrailingComma;
pos = nodes.pos;
end = nodes.end;
}
if (visited) {
if (isArray(visited)) {
for (const visitedNode of visited) {
void Debug.assertNode(visitedNode, test);
updated.push(visitedNode as T);
}
}
else {
void Debug.assertNode(visited, test);
updated.push(visited as T);
}
}
}
}
if (updated) {
// TODO(rbuckton): Remove dependency on `ts.factory` in favor of a provided factory.
const updatedArray = factory.createNodeArray(updated, hasTrailingComma);
setTextRangePosEnd(updatedArray, pos, end);
return updatedArray;
}
return 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<Statement>, visitor: Visitor, context: TransformationContext, start?: number, ensureUseStrict?: boolean, nodesVisitor: NodesVisitor = visitNodes) {
context.startLexicalEnvironment();
statements = nodesVisitor(statements, visitor, isStatement, start);
if (ensureUseStrict) statements = context.factory.ensureUseStrict(statements);
return factory.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<ParameterDeclaration>, visitor: Visitor, context: TransformationContext, nodesVisitor?: NodesVisitor): NodeArray<ParameterDeclaration>;
export function visitParameterList(nodes: NodeArray<ParameterDeclaration> | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: NodesVisitor): NodeArray<ParameterDeclaration> | undefined;
export function visitParameterList(nodes: NodeArray<ParameterDeclaration> | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes) {
let updated: NodeArray<ParameterDeclaration> | undefined;
context.startLexicalEnvironment();
if (nodes) {
context.setLexicalEnvironmentFlags(LexicalEnvironmentFlags.InParameters, true);
updated = nodesVisitor(nodes, visitor, isParameterDeclaration);
// As of ES2015, any runtime execution of that occurs in for a parameter (such as evaluating an
// initializer or a binding pattern), occurs in its own lexical scope. As a result, any expression
// that we might transform that introduces a temporary variable would fail as the temporary variable
// exists in a different lexical scope. To address this, we move any binding patterns and initializers
// in a parameter list to the body if we detect a variable being hoisted while visiting a parameter list
// when the emit target is greater than ES2015.
if (context.getLexicalEnvironmentFlags() & LexicalEnvironmentFlags.VariablesHoistedInParameters &&
getEmitScriptTarget(context.getCompilerOptions()) >= ScriptTarget.ES2015) {
updated = addDefaultValueAssignmentsIfNeeded(updated, context);
}
context.setLexicalEnvironmentFlags(LexicalEnvironmentFlags.InParameters, false);
}
context.suspendLexicalEnvironment();
return updated;
}
function addDefaultValueAssignmentsIfNeeded(parameters: NodeArray<ParameterDeclaration>, context: TransformationContext) {
let result: ParameterDeclaration[] | undefined;
for (let i = 0; i < parameters.length; i++) {
const parameter = parameters[i];
const updated = addDefaultValueAssignmentIfNeeded(parameter, context);
if (result || updated !== parameter) {
if (!result) result = parameters.slice(0, i);
result[i] = updated;
}
}
if (result) {
return setTextRange(context.factory.createNodeArray(result, parameters.hasTrailingComma), parameters);
}
return parameters;
}
function addDefaultValueAssignmentIfNeeded(parameter: ParameterDeclaration, context: TransformationContext) {
// A rest parameter cannot have a binding pattern or an initializer,
// so let's just ignore it.
return parameter.dotDotDotToken ? parameter :
isBindingPattern(parameter.name) ? addDefaultValueAssignmentForBindingPattern(parameter, context) :
parameter.initializer ? addDefaultValueAssignmentForInitializer(parameter, parameter.name, parameter.initializer, context) :
parameter;
}
function addDefaultValueAssignmentForBindingPattern(parameter: ParameterDeclaration, context: TransformationContext) {
const { factory } = context;
context.addInitializationStatement(
factory.createVariableStatement(
/*modifiers*/ undefined,
factory.createVariableDeclarationList([
factory.createVariableDeclaration(
parameter.name,
/*exclamationToken*/ undefined,
parameter.type,
parameter.initializer ?
factory.createConditionalExpression(
factory.createStrictEquality(
factory.getGeneratedNameForNode(parameter),
factory.createVoidZero()
),
/*questionToken*/ undefined,
parameter.initializer,
/*colonToken*/ undefined,
factory.getGeneratedNameForNode(parameter)
) :
factory.getGeneratedNameForNode(parameter)
),
])
)
);
return factory.updateParameterDeclaration(parameter,
parameter.decorators,
parameter.modifiers,
parameter.dotDotDotToken,
factory.getGeneratedNameForNode(parameter),
parameter.questionToken,
parameter.type,
/*initializer*/ undefined);
}
function addDefaultValueAssignmentForInitializer(parameter: ParameterDeclaration, name: Identifier, initializer: Expression, context: TransformationContext) {
const factory = context.factory;
context.addInitializationStatement(
factory.createIfStatement(
factory.createTypeCheck(factory.cloneNode(name), "undefined"),
setEmitFlags(
setTextRange(
factory.createBlock([
factory.createExpressionStatement(
setEmitFlags(
setTextRange(
factory.createAssignment(
setEmitFlags(factory.cloneNode(name), EmitFlags.NoSourceMap),
setEmitFlags(initializer, EmitFlags.NoSourceMap | getEmitFlags(initializer) | EmitFlags.NoComments)
),
parameter
),
EmitFlags.NoComments
)
)
]),
parameter
),
EmitFlags.SingleLine | EmitFlags.NoTrailingSourceMap | EmitFlags.NoTokenSourceMaps | EmitFlags.NoComments
)
)
);
return factory.updateParameterDeclaration(parameter,
parameter.decorators,
parameter.modifiers,
parameter.dotDotDotToken,
parameter.name,
parameter.questionToken,
parameter.type,
/*initializer*/ undefined);
}
/**
* 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;
/* @internal*/ export function visitFunctionBody(node: FunctionBody, visitor: Visitor, context: TransformationContext, nodeVisitor?: NodeVisitor): FunctionBody; // eslint-disable-line @typescript-eslint/unified-signatures
/* @internal*/ export function visitFunctionBody(node: FunctionBody | undefined, visitor: Visitor, context: TransformationContext, nodeVisitor?: NodeVisitor): FunctionBody | undefined; // eslint-disable-line @typescript-eslint/unified-signatures
/* @internal*/ export function visitFunctionBody(node: ConciseBody, visitor: Visitor, context: TransformationContext, nodeVisitor?: NodeVisitor): ConciseBody; // eslint-disable-line @typescript-eslint/unified-signatures
export function visitFunctionBody(node: ConciseBody | undefined, visitor: Visitor, context: TransformationContext, nodeVisitor: NodeVisitor = visitNode): ConciseBody | undefined {
context.resumeLexicalEnvironment();
const updated = nodeVisitor(node, visitor, isConciseBody);
const declarations = context.endLexicalEnvironment();
if (some(declarations)) {
if (!updated) {
return context.factory.createBlock(declarations);
}
const block = context.factory.converters.convertToFunctionBlock(updated);
const statements = factory.mergeLexicalEnvironment(block.statements, declarations);
return context.factory.updateBlock(block, statements);
}
return updated;
}
/**
* Visits an iteration body, adding any block-scoped variables required by the transformation.
*/
export function visitIterationBody(body: Statement, visitor: Visitor, context: TransformationContext): Statement {
context.startBlockScope();
const updated = visitNode(body, visitor, isStatement, context.factory.liftToBlock);
const declarations = context.endBlockScope();
if (some(declarations)) {
if (isBlock(updated)) {
declarations.push(...updated.statements);
return context.factory.updateBlock(updated, declarations);
}
declarations.push(updated);
return context.factory.createBlock(declarations);
}
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<T extends Node>(node: T, visitor: Visitor, context: TransformationContext): T;
/* @internal */
export function visitEachChild<T extends Node>(node: T, visitor: Visitor, context: TransformationContext, nodesVisitor?: NodesVisitor, tokenVisitor?: Visitor, nodeVisitor?: NodeVisitor): T; // eslint-disable-line @typescript-eslint/unified-signatures
/**
* 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<T extends Node>(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes, tokenVisitor?: Visitor): T | undefined;
/* @internal */
export function visitEachChild<T extends Node>(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: NodesVisitor, tokenVisitor?: Visitor, nodeVisitor?: NodeVisitor): T | undefined; // eslint-disable-line @typescript-eslint/unified-signatures
export function visitEachChild(node: Node | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes, tokenVisitor?: Visitor, nodeVisitor: NodeVisitor = visitNode): 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;
}
const factory = context.factory;
switch (kind) {
// Names
case SyntaxKind.Identifier:
Debug.type<Identifier>(node);
return factory.updateIdentifier(node,
nodesVisitor(node.typeArguments, visitor, isTypeNodeOrTypeParameterDeclaration));
case SyntaxKind.QualifiedName:
Debug.type<QualifiedName>(node);
return factory.updateQualifiedName(node,
nodeVisitor(node.left, visitor, isEntityName),
nodeVisitor(node.right, visitor, isIdentifier));
case SyntaxKind.ComputedPropertyName:
Debug.type<ComputedPropertyName>(node);
return factory.updateComputedPropertyName(node,
nodeVisitor(node.expression, visitor, isExpression));
// Signature elements
case SyntaxKind.TypeParameter:
Debug.type<TypeParameterDeclaration>(node);
return factory.updateTypeParameterDeclaration(node,
nodeVisitor(node.name, visitor, isIdentifier),
nodeVisitor(node.constraint, visitor, isTypeNode),
nodeVisitor(node.default, visitor, isTypeNode));
case SyntaxKind.Parameter:
Debug.type<ParameterDeclaration>(node);
return factory.updateParameterDeclaration(node,
nodesVisitor(node.decorators, visitor, isDecorator),
nodesVisitor(node.modifiers, visitor, isModifier),
nodeVisitor(node.dotDotDotToken, tokenVisitor, isDotDotDotToken),
nodeVisitor(node.name, visitor, isBindingName),
nodeVisitor(node.questionToken, tokenVisitor, isQuestionToken),
nodeVisitor(node.type, visitor, isTypeNode),
nodeVisitor(node.initializer, visitor, isExpression));
case SyntaxKind.Decorator:
Debug.type<Decorator>(node);
return factory.updateDecorator(node,
nodeVisitor(node.expression, visitor, isExpression));
// Type elements
case SyntaxKind.PropertySignature:
Debug.type<PropertySignature>(node);
return factory.updatePropertySignature(node,
nodesVisitor(node.modifiers, visitor, isModifier),
nodeVisitor(node.name, visitor, isPropertyName),
nodeVisitor(node.questionToken, tokenVisitor, isToken),
nodeVisitor(node.type, visitor, isTypeNode));
case SyntaxKind.PropertyDeclaration:
Debug.type<PropertyDeclaration>(node);
return factory.updatePropertyDeclaration(node,
nodesVisitor(node.decorators, visitor, isDecorator),
nodesVisitor(node.modifiers, visitor, isModifier),
nodeVisitor(node.name, visitor, isPropertyName),
// QuestionToken and ExclamationToken is uniqued in Property Declaration and the signature of 'updateProperty' is that too
nodeVisitor(node.questionToken || node.exclamationToken, tokenVisitor, isQuestionOrExclamationToken),
nodeVisitor(node.type, visitor, isTypeNode),
nodeVisitor(node.initializer, visitor, isExpression));
case SyntaxKind.MethodSignature:
Debug.type<MethodSignature>(node);
return factory.updateMethodSignature(node,
nodesVisitor(node.modifiers, visitor, isModifier),
nodeVisitor(node.name, visitor, isPropertyName),
nodeVisitor(node.questionToken, tokenVisitor, isQuestionToken),
nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration),
nodesVisitor(node.parameters, visitor, isParameterDeclaration),
nodeVisitor(node.type, visitor, isTypeNode));
case SyntaxKind.MethodDeclaration:
Debug.type<MethodDeclaration>(node);
return factory.updateMethodDeclaration(node,
nodesVisitor(node.decorators, visitor, isDecorator),
nodesVisitor(node.modifiers, visitor, isModifier),
nodeVisitor(node.asteriskToken, tokenVisitor, isAsteriskToken),
nodeVisitor(node.name, visitor, isPropertyName),
nodeVisitor(node.questionToken, tokenVisitor, isQuestionToken),
nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration),
visitParameterList(node.parameters, visitor, context, nodesVisitor),
nodeVisitor(node.type, visitor, isTypeNode),
visitFunctionBody(node.body!, visitor, context, nodeVisitor));
case SyntaxKind.Constructor:
Debug.type<ConstructorDeclaration>(node);
return factory.updateConstructorDeclaration(node,
nodesVisitor(node.decorators, visitor, isDecorator),
nodesVisitor(node.modifiers, visitor, isModifier),
visitParameterList(node.parameters, visitor, context, nodesVisitor),
visitFunctionBody(node.body!, visitor, context, nodeVisitor));
case SyntaxKind.GetAccessor:
Debug.type<GetAccessorDeclaration>(node);
return factory.updateGetAccessorDeclaration(node,
nodesVisitor(node.decorators, visitor, isDecorator),
nodesVisitor(node.modifiers, visitor, isModifier),
nodeVisitor(node.name, visitor, isPropertyName),
visitParameterList(node.parameters, visitor, context, nodesVisitor),
nodeVisitor(node.type, visitor, isTypeNode),
visitFunctionBody(node.body!, visitor, context, nodeVisitor));
case SyntaxKind.SetAccessor:
Debug.type<SetAccessorDeclaration>(node);
return factory.updateSetAccessorDeclaration(node,
nodesVisitor(node.decorators, visitor, isDecorator),
nodesVisitor(node.modifiers, visitor, isModifier),
nodeVisitor(node.name, visitor, isPropertyName),
visitParameterList(node.parameters, visitor, context, nodesVisitor),
visitFunctionBody(node.body!, visitor, context, nodeVisitor));
case SyntaxKind.ClassStaticBlockDeclaration:
Debug.type<ClassStaticBlockDeclaration>(node);
context.startLexicalEnvironment();
context.suspendLexicalEnvironment();
return factory.updateClassStaticBlockDeclaration(node,
nodesVisitor(node.decorators, visitor, isDecorator),
nodesVisitor(node.modifiers, visitor, isModifier),
visitFunctionBody(node.body, visitor, context, nodeVisitor));
case SyntaxKind.CallSignature:
Debug.type<CallSignatureDeclaration>(node);
return factory.updateCallSignature(node,
nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration),
nodesVisitor(node.parameters, visitor, isParameterDeclaration),
nodeVisitor(node.type, visitor, isTypeNode));
case SyntaxKind.ConstructSignature:
Debug.type<ConstructSignatureDeclaration>(node);
return factory.updateConstructSignature(node,
nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration),
nodesVisitor(node.parameters, visitor, isParameterDeclaration),
nodeVisitor(node.type, visitor, isTypeNode));
case SyntaxKind.IndexSignature:
Debug.type<IndexSignatureDeclaration>(node);
return factory.updateIndexSignature(node,
nodesVisitor(node.decorators, visitor, isDecorator),
nodesVisitor(node.modifiers, visitor, isModifier),
nodesVisitor(node.parameters, visitor, isParameterDeclaration),
nodeVisitor(node.type, visitor, isTypeNode));
// Types
case SyntaxKind.TypePredicate:
Debug.type<TypePredicateNode>(node);
return factory.updateTypePredicateNode(node,
nodeVisitor(node.assertsModifier, visitor, isAssertsKeyword),
nodeVisitor(node.parameterName, visitor, isIdentifierOrThisTypeNode),
nodeVisitor(node.type, visitor, isTypeNode));
case SyntaxKind.TypeReference:
Debug.type<TypeReferenceNode>(node);
return factory.updateTypeReferenceNode(node,
nodeVisitor(node.typeName, visitor, isEntityName),
nodesVisitor(node.typeArguments, visitor, isTypeNode));
case SyntaxKind.FunctionType:
Debug.type<FunctionTypeNode>(node);
return factory.updateFunctionTypeNode(node,
nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration),
nodesVisitor(node.parameters, visitor, isParameterDeclaration),
nodeVisitor(node.type, visitor, isTypeNode));
case SyntaxKind.ConstructorType:
Debug.type<ConstructorTypeNode>(node);
return factory.updateConstructorTypeNode(node,
nodesVisitor(node.modifiers, visitor, isModifier),
nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration),
nodesVisitor(node.parameters, visitor, isParameterDeclaration),
nodeVisitor(node.type, visitor, isTypeNode));
case SyntaxKind.TypeQuery:
Debug.type<TypeQueryNode>(node);
return factory.updateTypeQueryNode(node,
nodeVisitor(node.exprName, visitor, isEntityName));
case SyntaxKind.TypeLiteral:
Debug.type<TypeLiteralNode>(node);
return factory.updateTypeLiteralNode(node,
nodesVisitor(node.members, visitor, isTypeElement));
case SyntaxKind.ArrayType:
Debug.type<ArrayTypeNode>(node);
return factory.updateArrayTypeNode(node,
nodeVisitor(node.elementType, visitor, isTypeNode));
case SyntaxKind.TupleType:
Debug.type<TupleTypeNode>(node);
return factory.updateTupleTypeNode(node,
nodesVisitor(node.elements, visitor, isTypeNode));
case SyntaxKind.OptionalType:
Debug.type<OptionalTypeNode>(node);
return factory.updateOptionalTypeNode(node,
nodeVisitor(node.type, visitor, isTypeNode));
case SyntaxKind.RestType:
Debug.type<RestTypeNode>(node);
return factory.updateRestTypeNode(node,
nodeVisitor(node.type, visitor, isTypeNode));
case SyntaxKind.UnionType:
Debug.type<UnionTypeNode>(node);
return factory.updateUnionTypeNode(node,
nodesVisitor(node.types, visitor, isTypeNode));
case SyntaxKind.IntersectionType:
Debug.type<IntersectionTypeNode>(node);
return factory.updateIntersectionTypeNode(node,
nodesVisitor(node.types, visitor, isTypeNode));
case SyntaxKind.ConditionalType:
Debug.type<ConditionalTypeNode>(node);
return factory.updateConditionalTypeNode(node,
nodeVisitor(node.checkType, visitor, isTypeNode),
nodeVisitor(node.extendsType, visitor, isTypeNode),
nodeVisitor(node.trueType, visitor, isTypeNode),
nodeVisitor(node.falseType, visitor, isTypeNode));
case SyntaxKind.InferType:
Debug.type<InferTypeNode>(node);
return factory.updateInferTypeNode(node,
nodeVisitor(node.typeParameter, visitor, isTypeParameterDeclaration));
case SyntaxKind.ImportType:
Debug.type<ImportTypeNode>(node);
return factory.updateImportTypeNode(node,
nodeVisitor(node.argument, visitor, isTypeNode),
nodeVisitor(node.qualifier, visitor, isEntityName),
visitNodes(node.typeArguments, visitor, isTypeNode),
node.isTypeOf
);
case SyntaxKind.NamedTupleMember:
Debug.type<NamedTupleMember>(node);
return factory.updateNamedTupleMember(node,
visitNode(node.dotDotDotToken, visitor, isDotDotDotToken),
visitNode(node.name, visitor, isIdentifier),
visitNode(node.questionToken, visitor, isQuestionToken),
visitNode(node.type, visitor, isTypeNode),
);
case SyntaxKind.ParenthesizedType:
Debug.type<ParenthesizedTypeNode>(node);
return factory.updateParenthesizedType(node,
nodeVisitor(node.type, visitor, isTypeNode));
case SyntaxKind.TypeOperator:
Debug.type<TypeOperatorNode>(node);
return factory.updateTypeOperatorNode(node,
nodeVisitor(node.type, visitor, isTypeNode));
case SyntaxKind.IndexedAccessType:
Debug.type<IndexedAccessTypeNode>(node);
return factory.updateIndexedAccessTypeNode(node,
nodeVisitor(node.objectType, visitor, isTypeNode),
nodeVisitor(node.indexType, visitor, isTypeNode));
case SyntaxKind.MappedType:
Debug.type<MappedTypeNode>(node);
return factory.updateMappedTypeNode(node,
nodeVisitor(node.readonlyToken, tokenVisitor, isReadonlyKeywordOrPlusOrMinusToken),
nodeVisitor(node.typeParameter, visitor, isTypeParameterDeclaration),
nodeVisitor(node.nameType, visitor, isTypeNode),
nodeVisitor(node.questionToken, tokenVisitor, isQuestionOrPlusOrMinusToken),
nodeVisitor(node.type, visitor, isTypeNode));
case SyntaxKind.LiteralType:
Debug.type<LiteralTypeNode>(node);
return factory.updateLiteralTypeNode(node,
nodeVisitor(node.literal, visitor, isExpression));
case SyntaxKind.TemplateLiteralType:
Debug.type<TemplateLiteralTypeNode>(node);
return factory.updateTemplateLiteralType(node,
nodeVisitor(node.head, visitor, isTemplateHead),
nodesVisitor(node.templateSpans, visitor, isTemplateLiteralTypeSpan));
case SyntaxKind.TemplateLiteralTypeSpan:
Debug.type<TemplateLiteralTypeSpan>(node);
return factory.updateTemplateLiteralTypeSpan(node,
nodeVisitor(node.type, visitor, isTypeNode),
nodeVisitor(node.literal, visitor, isTemplateMiddleOrTemplateTail));
// Binding patterns
case SyntaxKind.ObjectBindingPattern:
Debug.type<ObjectBindingPattern>(node);
return factory.updateObjectBindingPattern(node,
nodesVisitor(node.elements, visitor, isBindingElement));
case SyntaxKind.ArrayBindingPattern:
Debug.type<ArrayBindingPattern>(node);
return factory.updateArrayBindingPattern(node,
nodesVisitor(node.elements, visitor, isArrayBindingElement));
case SyntaxKind.BindingElement:
Debug.type<BindingElement>(node);
return factory.updateBindingElement(node,
nodeVisitor(node.dotDotDotToken, tokenVisitor, isDotDotDotToken),
nodeVisitor(node.propertyName, visitor, isPropertyName),
nodeVisitor(node.name, visitor, isBindingName),
nodeVisitor(node.initializer, visitor, isExpression));
// Expression
case SyntaxKind.ArrayLiteralExpression:
Debug.type<ArrayLiteralExpression>(node);
return factory.updateArrayLiteralExpression(node,
nodesVisitor(node.elements, visitor, isExpression));
case SyntaxKind.ObjectLiteralExpression:
Debug.type<ObjectLiteralExpression>(node);
return factory.updateObjectLiteralExpression(node,
nodesVisitor(node.properties, visitor, isObjectLiteralElementLike));
case SyntaxKind.PropertyAccessExpression:
if (node.flags & NodeFlags.OptionalChain) {
Debug.type<PropertyAccessChain>(node);
return factory.updatePropertyAccessChain(node,
nodeVisitor(node.expression, visitor, isExpression),
nodeVisitor(node.questionDotToken, tokenVisitor, isQuestionDotToken),
nodeVisitor(node.name, visitor, isMemberName));
}
Debug.type<PropertyAccessExpression>(node);
return factory.updatePropertyAccessExpression(node,
nodeVisitor(node.expression, visitor, isExpression),
nodeVisitor(node.name, visitor, isMemberName));
case SyntaxKind.ElementAccessExpression:
if (node.flags & NodeFlags.OptionalChain) {
Debug.type<ElementAccessChain>(node);
return factory.updateElementAccessChain(node,
nodeVisitor(node.expression, visitor, isExpression),
nodeVisitor(node.questionDotToken, tokenVisitor, isQuestionDotToken),
nodeVisitor(node.argumentExpression, visitor, isExpression));
}
Debug.type<ElementAccessExpression>(node);
return factory.updateElementAccessExpression(node,
nodeVisitor(node.expression, visitor, isExpression),
nodeVisitor(node.argumentExpression, visitor, isExpression));
case SyntaxKind.CallExpression:
if (node.flags & NodeFlags.OptionalChain) {
Debug.type<CallChain>(node);
return factory.updateCallChain(node,
nodeVisitor(node.expression, visitor, isExpression),
nodeVisitor(node.questionDotToken, tokenVisitor, isQuestionDotToken),
nodesVisitor(node.typeArguments, visitor, isTypeNode),
nodesVisitor(node.arguments, visitor, isExpression));
}
Debug.type<CallExpression>(node);
return factory.updateCallExpression(node,
nodeVisitor(node.expression, visitor, isExpression),
nodesVisitor(node.typeArguments, visitor, isTypeNode),
nodesVisitor(node.arguments, visitor, isExpression));
case SyntaxKind.NewExpression:
Debug.type<NewExpression>(node);
return factory.updateNewExpression(node,
nodeVisitor(node.expression, visitor, isExpression),
nodesVisitor(node.typeArguments, visitor, isTypeNode),
nodesVisitor(node.arguments, visitor, isExpression));
case SyntaxKind.TaggedTemplateExpression:
Debug.type<TaggedTemplateExpression>(node);
return factory.updateTaggedTemplateExpression(node,
nodeVisitor(node.tag, visitor, isExpression),
visitNodes(node.typeArguments, visitor, isTypeNode),
nodeVisitor(node.template, visitor, isTemplateLiteral));
case SyntaxKind.TypeAssertionExpression:
Debug.type<TypeAssertion>(node);
return factory.updateTypeAssertion(node,
nodeVisitor(node.type, visitor, isTypeNode),
nodeVisitor(node.expression, visitor, isExpression));
case SyntaxKind.ParenthesizedExpression:
Debug.type<ParenthesizedExpression>(node);
return factory.updateParenthesizedExpression(node,
nodeVisitor(node.expression, visitor, isExpression));
case SyntaxKind.FunctionExpression:
Debug.type<FunctionExpression>(node);
return factory.updateFunctionExpression(node,
nodesVisitor(node.modifiers, visitor, isModifier),
nodeVisitor(node.asteriskToken, tokenVisitor, isAsteriskToken),
nodeVisitor(node.name, visitor, isIdentifier),
nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration),
visitParameterList(node.parameters, visitor, context, nodesVisitor),
nodeVisitor(node.type, visitor, isTypeNode),
visitFunctionBody(node.body, visitor, context, nodeVisitor));
case SyntaxKind.ArrowFunction:
Debug.type<ArrowFunction>(node);
return factory.updateArrowFunction(node,
nodesVisitor(node.modifiers, visitor, isModifier),
nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration),
visitParameterList(node.parameters, visitor, context, nodesVisitor),
nodeVisitor(node.type, visitor, isTypeNode),
nodeVisitor(node.equalsGreaterThanToken, tokenVisitor, isEqualsGreaterThanToken),
visitFunctionBody(node.body, visitor, context, nodeVisitor));
case SyntaxKind.DeleteExpression:
Debug.type<DeleteExpression>(node);
return factory.updateDeleteExpression(node,
nodeVisitor(node.expression, visitor, isExpression));
case SyntaxKind.TypeOfExpression:
Debug.type<TypeOfExpression>(node);
return factory.updateTypeOfExpression(node,
nodeVisitor(node.expression, visitor, isExpression));
case SyntaxKind.VoidExpression:
Debug.type<VoidExpression>(node);
return factory.updateVoidExpression(node,
nodeVisitor(node.expression, visitor, isExpression));
case SyntaxKind.AwaitExpression:
Debug.type<AwaitExpression>(node);
return factory.updateAwaitExpression(node,
nodeVisitor(node.expression, visitor, isExpression));
case SyntaxKind.PrefixUnaryExpression:
Debug.type<PrefixUnaryExpression>(node);
return factory.updatePrefixUnaryExpression(node,
nodeVisitor(node.operand, visitor, isExpression));
case SyntaxKind.PostfixUnaryExpression:
Debug.type<PostfixUnaryExpression>(node);
return factory.updatePostfixUnaryExpression(node,
nodeVisitor(node.operand, visitor, isExpression));
case SyntaxKind.BinaryExpression:
Debug.type<BinaryExpression>(node);
return factory.updateBinaryExpression(node,
nodeVisitor(node.left, visitor, isExpression),
nodeVisitor(node.operatorToken, tokenVisitor, isBinaryOperatorToken),
nodeVisitor(node.right, visitor, isExpression));
case SyntaxKind.ConditionalExpression:
Debug.type<ConditionalExpression>(node);
return factory.updateConditionalExpression(node,
nodeVisitor(node.condition, visitor, isExpression),
nodeVisitor(node.questionToken, tokenVisitor, isQuestionToken),
nodeVisitor(node.whenTrue, visitor, isExpression),
nodeVisitor(node.colonToken, tokenVisitor, isColonToken),
nodeVisitor(node.whenFalse, visitor, isExpression));
case SyntaxKind.TemplateExpression:
Debug.type<TemplateExpression>(node);
return factory.updateTemplateExpression(node,
nodeVisitor(node.head, visitor, isTemplateHead),
nodesVisitor(node.templateSpans, visitor, isTemplateSpan));
case SyntaxKind.YieldExpression:
Debug.type<YieldExpression>(node);
return factory.updateYieldExpression(node,
nodeVisitor(node.asteriskToken, tokenVisitor, isAsteriskToken),
nodeVisitor(node.expression, visitor, isExpression));
case SyntaxKind.SpreadElement:
Debug.type<SpreadElement>(node);
return factory.updateSpreadElement(node,
nodeVisitor(node.expression, visitor, isExpression));
case SyntaxKind.ClassExpression:
Debug.type<ClassExpression>(node);
return factory.updateClassExpression(node,
nodesVisitor(node.decorators, visitor, isDecorator),
nodesVisitor(node.modifiers, visitor, isModifier),
nodeVisitor(node.name, visitor, isIdentifier),
nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration),
nodesVisitor(node.heritageClauses, visitor, isHeritageClause),
nodesVisitor(node.members, visitor, isClassElement));
case SyntaxKind.ExpressionWithTypeArguments:
Debug.type<ExpressionWithTypeArguments>(node);
return factory.updateExpressionWithTypeArguments(node,
nodeVisitor(node.expression, visitor, isExpression),
nodesVisitor(node.typeArguments, visitor, isTypeNode));
case SyntaxKind.AsExpression:
Debug.type<AsExpression>(node);
return factory.updateAsExpression(node,
nodeVisitor(node.expression, visitor, isExpression),
nodeVisitor(node.type, visitor, isTypeNode));
case SyntaxKind.NonNullExpression:
if (node.flags & NodeFlags.OptionalChain) {
Debug.type<NonNullChain>(node);
return factory.updateNonNullChain(node,
nodeVisitor(node.expression, visitor, isExpression));
}
Debug.type<NonNullExpression>(node);
return factory.updateNonNullExpression(node,
nodeVisitor(node.expression, visitor, isExpression));
case SyntaxKind.MetaProperty:
Debug.type<MetaProperty>(node);
return factory.updateMetaProperty(node,
nodeVisitor(node.name, visitor, isIdentifier));
// Misc
case SyntaxKind.TemplateSpan:
Debug.type<TemplateSpan>(node);
return factory.updateTemplateSpan(node,
nodeVisitor(node.expression, visitor, isExpression),
nodeVisitor(node.literal, visitor, isTemplateMiddleOrTemplateTail));
// Element
case SyntaxKind.Block:
Debug.type<Block>(node);
return factory.updateBlock(node,
nodesVisitor(node.statements, visitor, isStatement));
case SyntaxKind.VariableStatement:
Debug.type<VariableStatement>(node);
return factory.updateVariableStatement(node,
nodesVisitor(node.modifiers, visitor, isModifier),
nodeVisitor(node.declarationList, visitor, isVariableDeclarationList));
case SyntaxKind.ExpressionStatement:
Debug.type<ExpressionStatement>(node);
return factory.updateExpressionStatement(node,
nodeVisitor(node.expression, visitor, isExpression));
case SyntaxKind.IfStatement:
Debug.type<IfStatement>(node);
return factory.updateIfStatement(node,
nodeVisitor(node.expression, visitor, isExpression),
nodeVisitor(node.thenStatement, visitor, isStatement, factory.liftToBlock),
nodeVisitor(node.elseStatement, visitor, isStatement, factory.liftToBlock));
case SyntaxKind.DoStatement:
Debug.type<DoStatement>(node);
return factory.updateDoStatement(node,
visitIterationBody(node.statement, visitor, context),
nodeVisitor(node.expression, visitor, isExpression));
case SyntaxKind.WhileStatement:
Debug.type<WhileStatement>(node);
return factory.updateWhileStatement(node,
nodeVisitor(node.expression, visitor, isExpression),
visitIterationBody(node.statement, visitor, context));
case SyntaxKind.ForStatement:
Debug.type<ForStatement>(node);
return factory.updateForStatement(node,
nodeVisitor(node.initializer, visitor, isForInitializer),
nodeVisitor(node.condition, visitor, isExpression),
nodeVisitor(node.incrementor, visitor, isExpression),
visitIterationBody(node.statement, visitor, context));
case SyntaxKind.ForInStatement:
Debug.type<ForInStatement>(node);
return factory.updateForInStatement(node,
nodeVisitor(node.initializer, visitor, isForInitializer),
nodeVisitor(node.expression, visitor, isExpression),
visitIterationBody(node.statement, visitor, context));
case SyntaxKind.ForOfStatement:
Debug.type<ForOfStatement>(node);
return factory.updateForOfStatement(node,
nodeVisitor(node.awaitModifier, tokenVisitor, isAwaitKeyword),
nodeVisitor(node.initializer, visitor, isForInitializer),
nodeVisitor(node.expression, visitor, isExpression),
visitIterationBody(node.statement, visitor, context));
case SyntaxKind.ContinueStatement:
Debug.type<ContinueStatement>(node);
return factory.updateContinueStatement(node,
nodeVisitor(node.label, visitor, isIdentifier));
case SyntaxKind.BreakStatement:
Debug.type<BreakStatement>(node);
return factory.updateBreakStatement(node,
nodeVisitor(node.label, visitor, isIdentifier));
case SyntaxKind.ReturnStatement:
Debug.type<ReturnStatement>(node);
return factory.updateReturnStatement(node,
nodeVisitor(node.expression, visitor, isExpression));
case SyntaxKind.WithStatement:
Debug.type<WithStatement>(node);
return factory.updateWithStatement(node,
nodeVisitor(node.expression, visitor, isExpression),
nodeVisitor(node.statement, visitor, isStatement, factory.liftToBlock));
case SyntaxKind.SwitchStatement:
Debug.type<SwitchStatement>(node);
return factory.updateSwitchStatement(node,
nodeVisitor(node.expression, visitor, isExpression),
nodeVisitor(node.caseBlock, visitor, isCaseBlock));
case SyntaxKind.LabeledStatement:
Debug.type<LabeledStatement>(node);
return factory.updateLabeledStatement(node,
nodeVisitor(node.label, visitor, isIdentifier),
nodeVisitor(node.statement, visitor, isStatement, factory.liftToBlock));
case SyntaxKind.ThrowStatement:
Debug.type<ThrowStatement>(node);
return factory.updateThrowStatement(node,
nodeVisitor(node.expression, visitor, isExpression));
case SyntaxKind.TryStatement:
Debug.type<TryStatement>(node);
return factory.updateTryStatement(node,
nodeVisitor(node.tryBlock, visitor, isBlock),
nodeVisitor(node.catchClause, visitor, isCatchClause),
nodeVisitor(node.finallyBlock, visitor, isBlock));
case SyntaxKind.VariableDeclaration:
Debug.type<VariableDeclaration>(node);
return factory.updateVariableDeclaration(node,
nodeVisitor(node.name, visitor, isBindingName),
nodeVisitor(node.exclamationToken, tokenVisitor, isExclamationToken),
nodeVisitor(node.type, visitor, isTypeNode),
nodeVisitor(node.initializer, visitor, isExpression));
case SyntaxKind.VariableDeclarationList:
Debug.type<VariableDeclarationList>(node);
return factory.updateVariableDeclarationList(node,
nodesVisitor(node.declarations, visitor, isVariableDeclaration));
case SyntaxKind.FunctionDeclaration:
Debug.type<FunctionDeclaration>(node);
return factory.updateFunctionDeclaration(node,
nodesVisitor(node.decorators, visitor, isDecorator),
nodesVisitor(node.modifiers, visitor, isModifier),
nodeVisitor(node.asteriskToken, tokenVisitor, isAsteriskToken),
nodeVisitor(node.name, visitor, isIdentifier),
nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration),
visitParameterList(node.parameters, visitor, context, nodesVisitor),
nodeVisitor(node.type, visitor, isTypeNode),
visitFunctionBody(node.body, visitor, context, nodeVisitor));
case SyntaxKind.ClassDeclaration:
Debug.type<ClassDeclaration>(node);
return factory.updateClassDeclaration(node,
nodesVisitor(node.decorators, visitor, isDecorator),
nodesVisitor(node.modifiers, visitor, isModifier),
nodeVisitor(node.name, visitor, isIdentifier),
nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration),
nodesVisitor(node.heritageClauses, visitor, isHeritageClause),
nodesVisitor(node.members, visitor, isClassElement));
case SyntaxKind.InterfaceDeclaration:
Debug.type<InterfaceDeclaration>(node);
return factory.updateInterfaceDeclaration(node,
nodesVisitor(node.decorators, visitor, isDecorator),
nodesVisitor(node.modifiers, visitor, isModifier),
nodeVisitor(node.name, visitor, isIdentifier),
nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration),
nodesVisitor(node.heritageClauses, visitor, isHeritageClause),
nodesVisitor(node.members, visitor, isTypeElement));
case SyntaxKind.TypeAliasDeclaration:
Debug.type<TypeAliasDeclaration>(node);
return factory.updateTypeAliasDeclaration(node,
nodesVisitor(node.decorators, visitor, isDecorator),
nodesVisitor(node.modifiers, visitor, isModifier),
nodeVisitor(node.name, visitor, isIdentifier),
nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration),
nodeVisitor(node.type, visitor, isTypeNode));
case SyntaxKind.EnumDeclaration:
Debug.type<EnumDeclaration>(node);
return factory.updateEnumDeclaration(node,
nodesVisitor(node.decorators, visitor, isDecorator),
nodesVisitor(node.modifiers, visitor, isModifier),
nodeVisitor(node.name, visitor, isIdentifier),
nodesVisitor(node.members, visitor, isEnumMember));
case SyntaxKind.ModuleDeclaration:
Debug.type<ModuleDeclaration>(node);
return factory.updateModuleDeclaration(node,
nodesVisitor(node.decorators, visitor, isDecorator),
nodesVisitor(node.modifiers, visitor, isModifier),
nodeVisitor(node.name, visitor, isModuleName),
nodeVisitor(node.body, visitor, isModuleBody));
case SyntaxKind.ModuleBlock:
Debug.type<ModuleBlock>(node);
return factory.updateModuleBlock(node,
nodesVisitor(node.statements, visitor, isStatement));
case SyntaxKind.CaseBlock:
Debug.type<CaseBlock>(node);
return factory.updateCaseBlock(node,
nodesVisitor(node.clauses, visitor, isCaseOrDefaultClause));
case SyntaxKind.NamespaceExportDeclaration:
Debug.type<NamespaceExportDeclaration>(node);
return factory.updateNamespaceExportDeclaration(node,
nodeVisitor(node.name, visitor, isIdentifier));
case SyntaxKind.ImportEqualsDeclaration:
Debug.type<ImportEqualsDeclaration>(node);
return factory.updateImportEqualsDeclaration(node,
nodesVisitor(node.decorators, visitor, isDecorator),
nodesVisitor(node.modifiers, visitor, isModifier),
node.isTypeOnly,
nodeVisitor(node.name, visitor, isIdentifier),
nodeVisitor(node.moduleReference, visitor, isModuleReference));
case SyntaxKind.ImportDeclaration:
Debug.type<ImportDeclaration>(node);
return factory.updateImportDeclaration(node,
nodesVisitor(node.decorators, visitor, isDecorator),
nodesVisitor(node.modifiers, visitor, isModifier),
nodeVisitor(node.importClause, visitor, isImportClause),
nodeVisitor(node.moduleSpecifier, visitor, isExpression));
case SyntaxKind.ImportClause:
Debug.type<ImportClause>(node);
return factory.updateImportClause(node,
node.isTypeOnly,
nodeVisitor(node.name, visitor, isIdentifier),
nodeVisitor(node.namedBindings, visitor, isNamedImportBindings));
case SyntaxKind.NamespaceImport:
Debug.type<NamespaceImport>(node);
return factory.updateNamespaceImport(node,
nodeVisitor(node.name, visitor, isIdentifier));
case SyntaxKind.NamespaceExport:
Debug.type<NamespaceExport>(node);
return factory.updateNamespaceExport(node,
nodeVisitor(node.name, visitor, isIdentifier));
case SyntaxKind.NamedImports:
Debug.type<NamedImports>(node);
return factory.updateNamedImports(node,
nodesVisitor(node.elements, visitor, isImportSpecifier));
case SyntaxKind.ImportSpecifier:
Debug.type<ImportSpecifier>(node);
return factory.updateImportSpecifier(node,
nodeVisitor(node.propertyName, visitor, isIdentifier),
nodeVisitor(node.name, visitor, isIdentifier));
case SyntaxKind.ExportAssignment:
Debug.type<ExportAssignment>(node);
return factory.updateExportAssignment(node,
nodesVisitor(node.decorators, visitor, isDecorator),
nodesVisitor(node.modifiers, visitor, isModifier),
nodeVisitor(node.expression, visitor, isExpression));
case SyntaxKind.ExportDeclaration:
Debug.type<ExportDeclaration>(node);
return factory.updateExportDeclaration(node,
nodesVisitor(node.decorators, visitor, isDecorator),
nodesVisitor(node.modifiers, visitor, isModifier),
node.isTypeOnly,
nodeVisitor(node.exportClause, visitor, isNamedExportBindings),
nodeVisitor(node.moduleSpecifier, visitor, isExpression));
case SyntaxKind.NamedExports:
Debug.type<NamedExports>(node);
return factory.updateNamedExports(node,
nodesVisitor(node.elements, visitor, isExportSpecifier));
case SyntaxKind.ExportSpecifier:
Debug.type<ExportSpecifier>(node);
return factory.updateExportSpecifier(node,
nodeVisitor(node.propertyName, visitor, isIdentifier),
nodeVisitor(node.name, visitor, isIdentifier));
// Module references
case SyntaxKind.ExternalModuleReference:
Debug.type<ExternalModuleReference>(node);
return factory.updateExternalModuleReference(node,
nodeVisitor(node.expression, visitor, isExpression));
// JSX
case SyntaxKind.JsxElement:
Debug.type<JsxElement>(node);
return factory.updateJsxElement(node,
nodeVisitor(node.openingElement, visitor, isJsxOpeningElement),
nodesVisitor(node.children, visitor, isJsxChild),
nodeVisitor(node.closingElement, visitor, isJsxClosingElement));
case SyntaxKind.JsxSelfClosingElement:
Debug.type<JsxSelfClosingElement>(node);
return factory.updateJsxSelfClosingElement(node,
nodeVisitor(node.tagName, visitor, isJsxTagNameExpression),
nodesVisitor(node.typeArguments, visitor, isTypeNode),
nodeVisitor(node.attributes, visitor, isJsxAttributes));
case SyntaxKind.JsxOpeningElement:
Debug.type<JsxOpeningElement>(node);
return factory.updateJsxOpeningElement(node,
nodeVisitor(node.tagName, visitor, isJsxTagNameExpression),
nodesVisitor(node.typeArguments, visitor, isTypeNode),
nodeVisitor(node.attributes, visitor, isJsxAttributes));
case SyntaxKind.JsxClosingElement:
Debug.type<JsxClosingElement>(node);
return factory.updateJsxClosingElement(node,
nodeVisitor(node.tagName, visitor, isJsxTagNameExpression));
case SyntaxKind.JsxFragment:
Debug.type<JsxFragment>(node);
return factory.updateJsxFragment(node,
nodeVisitor(node.openingFragment, visitor, isJsxOpeningFragment),
nodesVisitor(node.children, visitor, isJsxChild),
nodeVisitor(node.closingFragment, visitor, isJsxClosingFragment));
case SyntaxKind.JsxAttribute:
Debug.type<JsxAttribute>(node);
return factory.updateJsxAttribute(node,
nodeVisitor(node.name, visitor, isIdentifier),
nodeVisitor(node.initializer, visitor, isStringLiteralOrJsxExpression));
case SyntaxKind.JsxAttributes:
Debug.type<JsxAttributes>(node);
return factory.updateJsxAttributes(node,
nodesVisitor(node.properties, visitor, isJsxAttributeLike));
case SyntaxKind.JsxSpreadAttribute:
Debug.type<JsxSpreadAttribute>(node);
return factory.updateJsxSpreadAttribute(node,
nodeVisitor(node.expression, visitor, isExpression));
case SyntaxKind.JsxExpression:
Debug.type<JsxExpression>(node);
return factory.updateJsxExpression(node,
nodeVisitor(node.expression, visitor, isExpression));
// Clauses
case SyntaxKind.CaseClause:
Debug.type<CaseClause>(node);
return factory.updateCaseClause(node,
nodeVisitor(node.expression, visitor, isExpression),
nodesVisitor(node.statements, visitor, isStatement));
case SyntaxKind.DefaultClause:
Debug.type<DefaultClause>(node);
return factory.updateDefaultClause(node,
nodesVisitor(node.statements, visitor, isStatement));
case SyntaxKind.HeritageClause:
Debug.type<HeritageClause>(node);
return factory.updateHeritageClause(node,
nodesVisitor(node.types, visitor, isExpressionWithTypeArguments));
case SyntaxKind.CatchClause:
Debug.type<CatchClause>(node);
return factory.updateCatchClause(node,
nodeVisitor(node.variableDeclaration, visitor, isVariableDeclaration),
nodeVisitor(node.block, visitor, isBlock));
// Property assignments
case SyntaxKind.PropertyAssignment:
Debug.type<PropertyAssignment>(node);
return factory.updatePropertyAssignment(node,
nodeVisitor(node.name, visitor, isPropertyName),
nodeVisitor(node.initializer, visitor, isExpression));
case SyntaxKind.ShorthandPropertyAssignment:
Debug.type<ShorthandPropertyAssignment>(node);
return factory.updateShorthandPropertyAssignment(node,
nodeVisitor(node.name, visitor, isIdentifier),
nodeVisitor(node.objectAssignmentInitializer, visitor, isExpression));
case SyntaxKind.SpreadAssignment:
Debug.type<SpreadAssignment>(node);
return factory.updateSpreadAssignment(node,
nodeVisitor(node.expression, visitor, isExpression));
// Enum
case SyntaxKind.EnumMember:
Debug.type<EnumMember>(node);
return factory.updateEnumMember(node,
nodeVisitor(node.name, visitor, isPropertyName),
nodeVisitor(node.initializer, visitor, isExpression));
// Top-level nodes
case SyntaxKind.SourceFile:
Debug.type<SourceFile>(node);
return factory.updateSourceFile(node,
visitLexicalEnvironment(node.statements, visitor, context));
// Transformation nodes
case SyntaxKind.PartiallyEmittedExpression:
Debug.type<PartiallyEmittedExpression>(node);
return factory.updatePartiallyEmittedExpression(node,
nodeVisitor(node.expression, visitor, isExpression));
case SyntaxKind.CommaListExpression:
Debug.type<CommaListExpression>(node);
return factory.updateCommaListExpression(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);
}
}