// noinspection JSUnusedGlobalSymbols /* * Copyright 2025 the original author or authors. *

* Licensed under the Moderne Source Available License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *

* https://docs.moderne.io/licensing/moderne-source-available-license *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {mapAsync, updateIfChanged} from "../util"; import {SourceFile} from "../tree"; import {ValidRecipeReturnType} from "../visitor"; import {Expression, J, JavaVisitor, NameTree, Statement, Type, TypedTree} from "../java"; import {create, Draft} from "mutative"; import {isJavaScript, JS, JSX} from "./tree"; export class JavaScriptVisitor

extends JavaVisitor

{ override async isAcceptable(sourceFile: SourceFile): Promise { return isJavaScript(sourceFile); } // noinspection JSUnusedGlobalSymbols,JSUnusedLocalSymbols protected override async visitExpression(expression: Expression, p: P): Promise { return expression; } // noinspection JSUnusedGlobalSymbols,JSUnusedLocalSymbols protected override async visitStatement(statement: Statement, p: P): Promise { return statement; } // noinspection JSUnusedLocalSymbols override async visitSpace(space: J.Space, p: P): Promise { return space; } // noinspection JSUnusedLocalSymbols protected override async visitType(javaType: Type | undefined, p: P): Promise { return javaType; } // noinspection JSUnusedLocalSymbols protected override async visitTypeName(nameTree: N, p: P): Promise { return nameTree; } protected async produceJavaScript( before: J2, p: P, recipe?: (draft: Draft) => ValidRecipeReturnType> | PromiseLike>> ): Promise { const [draft, finishDraft] = create(before!); (draft as Draft).prefix = await this.visitSpace(before!.prefix, p); (draft as Draft).markers = await this.visitMarkers(before!.markers, p); if (recipe) { await recipe(draft); } return finishDraft() as J2; } protected async visitAlias(alias: JS.Alias, p: P): Promise { const expression = await this.visitExpression(alias, p); if (!expression?.kind || expression.kind !== JS.Kind.Alias) { return expression; } alias = expression as JS.Alias; const updates: any = { prefix: await this.visitSpace(alias.prefix, p), markers: await this.visitMarkers(alias.markers, p), propertyName: await this.visitRightPadded(alias.propertyName, p), alias: await this.visitDefined(alias.alias, p) }; return updateIfChanged(alias, updates); } protected async visitArrowFunction(arrowFunction: JS.ArrowFunction, p: P): Promise { const expression = await this.visitExpression(arrowFunction, p); if (!expression?.kind || expression.kind !== JS.Kind.ArrowFunction) { return expression; } arrowFunction = expression as JS.ArrowFunction; const statement = await this.visitStatement(arrowFunction, p); if (!statement?.kind || statement.kind !== JS.Kind.ArrowFunction) { return statement; } arrowFunction = statement as JS.ArrowFunction; const updates: any = { prefix: await this.visitSpace(arrowFunction.prefix, p), markers: await this.visitMarkers(arrowFunction.markers, p), leadingAnnotations: await mapAsync(arrowFunction.leadingAnnotations, item => this.visitDefined(item, p)), modifiers: await mapAsync(arrowFunction.modifiers, item => this.visitDefined(item, p)), typeParameters: arrowFunction.typeParameters && await this.visitDefined(arrowFunction.typeParameters, p), lambda: await this.visitDefined(arrowFunction.lambda, p), returnTypeExpression: arrowFunction.returnTypeExpression && await this.visitDefined(arrowFunction.returnTypeExpression, p) }; return updateIfChanged(arrowFunction, updates); } protected async visitAs(as_: JS.As, p: P): Promise { const updates: any = { prefix: await this.visitSpace(as_.prefix, p), markers: await this.visitMarkers(as_.markers, p), left: await this.visitRightPadded(as_.left, p), right: await this.visitDefined(as_.right, p), type: as_.type && await this.visitType(as_.type, p) }; return updateIfChanged(as_, updates); } protected async visitAwait(await_: JS.Await, p: P): Promise { const expression = await this.visitExpression(await_, p); if (!expression?.kind || expression.kind !== JS.Kind.Await) { return expression; } await_ = expression as JS.Await; const updates: any = { prefix: await this.visitSpace(await_.prefix, p), markers: await this.visitMarkers(await_.markers, p), expression: await this.visitDefined(await_.expression, p), type: await_.type && await this.visitType(await_.type, p) }; return updateIfChanged(await_, updates); } protected async visitJsxTag(element: JSX.Tag, p: P): Promise { const updates: any = { prefix: await this.visitSpace(element.prefix, p), markers: await this.visitMarkers(element.markers, p), openName: await this.visitLeftPadded(element.openName, p), typeArguments: element.typeArguments && await this.visitContainer(element.typeArguments, p), afterName: await this.visitSpace(element.afterName, p), attributes: await mapAsync(element.attributes, attr => this.visitRightPadded(attr, p)), selfClosing: element.selfClosing && await this.visitSpace(element.selfClosing, p), children: element.children && await mapAsync(element.children, child => this.visit(child, p)), closingName: element.closingName && await this.visitLeftPadded(element.closingName, p), afterClosingName: element.afterClosingName && await this.visitSpace(element.afterClosingName, p) }; return updateIfChanged(element, updates); } protected async visitJsxAttribute(attribute: JSX.Attribute, p: P): Promise { const updates: any = { prefix: await this.visitSpace(attribute.prefix, p), markers: await this.visitMarkers(attribute.markers, p), key: await this.visitDefined(attribute.key, p), value: attribute.value && await this.visitLeftPadded(attribute.value, p) }; return updateIfChanged(attribute, updates); } protected async visitJsxSpreadAttribute(spread: JSX.SpreadAttribute, p: P): Promise { const updates: any = { prefix: await this.visitSpace(spread.prefix, p), markers: await this.visitMarkers(spread.markers, p), dots: await this.visitSpace(spread.dots, p), expression: await this.visitRightPadded(spread.expression, p) }; return updateIfChanged(spread, updates); } protected async visitJsxEmbeddedExpression(expr: JSX.EmbeddedExpression, p: P): Promise { const updates: any = { prefix: await this.visitSpace(expr.prefix, p), markers: await this.visitMarkers(expr.markers, p), expression: await this.visitRightPadded(expr.expression, p) }; return updateIfChanged(expr, updates); } protected async visitJsxNamespacedName(ns: JSX.NamespacedName, p: P): Promise { const updates: any = { prefix: await this.visitSpace(ns.prefix, p), markers: await this.visitMarkers(ns.markers, p), namespace: await this.visitDefined(ns.namespace, p), name: await this.visitLeftPadded(ns.name, p) }; return updateIfChanged(ns, updates); } protected async visitJsCompilationUnit(compilationUnit: JS.CompilationUnit, p: P): Promise { const updates: any = { prefix: await this.visitSpace(compilationUnit.prefix, p), markers: await this.visitMarkers(compilationUnit.markers, p), statements: await mapAsync(compilationUnit.statements, stmt => this.visitRightPadded(stmt, p)), eof: await this.visitSpace(compilationUnit.eof, p) }; return updateIfChanged(compilationUnit, updates); } protected async visitConditionalType(conditionalType: JS.ConditionalType, p: P): Promise { const expression = await this.visitExpression(conditionalType, p); if (!expression?.kind || expression.kind !== JS.Kind.ConditionalType) { return expression; } conditionalType = expression as JS.ConditionalType; const updates: any = { prefix: await this.visitSpace(conditionalType.prefix, p), markers: await this.visitMarkers(conditionalType.markers, p), checkType: await this.visitDefined(conditionalType.checkType, p), condition: await this.visitLeftPadded(conditionalType.condition, p), type: conditionalType.type && await this.visitType(conditionalType.type, p) }; return updateIfChanged(conditionalType, updates); } protected async visitDelete(delete_: JS.Delete, p: P): Promise { const expression = await this.visitExpression(delete_, p); if (!expression?.kind || expression.kind !== JS.Kind.Delete) { return expression; } delete_ = expression as JS.Delete; const statement = await this.visitStatement(delete_, p); if (!statement?.kind || statement.kind !== JS.Kind.Delete) { return statement; } delete_ = statement as JS.Delete; const updates: any = { prefix: await this.visitSpace(delete_.prefix, p), markers: await this.visitMarkers(delete_.markers, p), expression: await this.visitDefined(delete_.expression, p) }; return updateIfChanged(delete_, updates); } protected async visitExpressionStatement(expressionStatement: JS.ExpressionStatement, p: P): Promise { const expression = await this.visitExpression(expressionStatement, p); if (!expression?.kind || expression.kind !== JS.Kind.ExpressionStatement) { return expression; } expressionStatement = expression as JS.ExpressionStatement; const statement = await this.visitStatement(expressionStatement, p); if (!statement?.kind || statement.kind !== JS.Kind.ExpressionStatement) { return statement; } expressionStatement = statement as JS.ExpressionStatement; const updates: any = { prefix: await this.visitSpace(expressionStatement.prefix, p), markers: await this.visitMarkers(expressionStatement.markers, p), expression: await this.visitDefined(expressionStatement.expression, p) }; return updateIfChanged(expressionStatement, updates); } protected async visitExpressionWithTypeArguments(expressionWithTypeArguments: JS.ExpressionWithTypeArguments, p: P): Promise { const expression = await this.visitExpression(expressionWithTypeArguments, p); if (!expression?.kind || expression.kind !== JS.Kind.ExpressionWithTypeArguments) { return expression; } expressionWithTypeArguments = expression as JS.ExpressionWithTypeArguments; const updates: any = { prefix: await this.visitSpace(expressionWithTypeArguments.prefix, p), markers: await this.visitMarkers(expressionWithTypeArguments.markers, p), clazz: await this.visitDefined(expressionWithTypeArguments.clazz, p), typeArguments: expressionWithTypeArguments.typeArguments && await this.visitContainer(expressionWithTypeArguments.typeArguments, p), type: expressionWithTypeArguments.type && await this.visitType(expressionWithTypeArguments.type, p) }; return updateIfChanged(expressionWithTypeArguments, updates); } protected async visitFunctionCall(functionCall: JS.FunctionCall, p: P): Promise { const expression = await this.visitExpression(functionCall, p); if (!expression?.kind || expression.kind !== JS.Kind.FunctionCall) { return expression; } functionCall = expression as JS.FunctionCall; const statement = await this.visitStatement(functionCall, p); if (!statement?.kind || statement.kind !== JS.Kind.FunctionCall) { return statement; } functionCall = statement as JS.FunctionCall; const updates: any = { prefix: await this.visitSpace(functionCall.prefix, p), markers: await this.visitMarkers(functionCall.markers, p), function: await this.visitOptionalRightPadded(functionCall.function, p), typeParameters: await this.visitOptionalContainer(functionCall.typeParameters, p), arguments: await this.visitContainer(functionCall.arguments, p), methodType: await this.visitType(functionCall.methodType, p) as Type.Method | undefined }; return updateIfChanged(functionCall, updates); } protected async visitFunctionType(functionType: JS.FunctionType, p: P): Promise { const expression = await this.visitExpression(functionType, p); if (!expression?.kind || expression.kind !== JS.Kind.FunctionType) { return expression; } functionType = expression as JS.FunctionType; const updates: any = { prefix: await this.visitSpace(functionType.prefix, p), markers: await this.visitMarkers(functionType.markers, p), constructorType: await this.visitLeftPadded(functionType.constructorType, p), typeParameters: functionType.typeParameters && await this.visitDefined(functionType.typeParameters, p), parameters: await this.visitContainer(functionType.parameters, p), returnType: await this.visitLeftPadded(functionType.returnType, p) }; return updateIfChanged(functionType, updates); } protected async visitInferType(inferType: JS.InferType, p: P): Promise { const expression = await this.visitExpression(inferType, p); if (!expression?.kind || expression.kind !== JS.Kind.InferType) { return expression; } inferType = expression as JS.InferType; const updates: any = { prefix: await this.visitSpace(inferType.prefix, p), markers: await this.visitMarkers(inferType.markers, p), typeParameter: await this.visitLeftPadded(inferType.typeParameter, p), type: inferType.type && await this.visitType(inferType.type, p) }; return updateIfChanged(inferType, updates); } protected async visitImportType(importType: JS.ImportType, p: P): Promise { const expression = await this.visitExpression(importType, p); if (!expression?.kind || expression.kind !== JS.Kind.ImportType) { return expression; } importType = expression as JS.ImportType; const updates: any = { prefix: await this.visitSpace(importType.prefix, p), markers: await this.visitMarkers(importType.markers, p), hasTypeof: await this.visitRightPadded(importType.hasTypeof, p), argumentAndAttributes: await this.visitContainer(importType.argumentAndAttributes, p), qualifier: importType.qualifier && await this.visitLeftPadded(importType.qualifier, p), typeArguments: importType.typeArguments && await this.visitContainer(importType.typeArguments, p), type: importType.type && await this.visitType(importType.type, p) }; return updateIfChanged(importType, updates); } protected async visitImportDeclaration(jsImport: JS.Import, p: P): Promise { const statement = await this.visitStatement(jsImport, p); if (!statement?.kind || statement.kind !== JS.Kind.Import) { return statement; } jsImport = statement as JS.Import; const updates: any = { prefix: await this.visitSpace(jsImport.prefix, p), markers: await this.visitMarkers(jsImport.markers, p), modifiers: await mapAsync(jsImport.modifiers, item => this.visitDefined(item, p)), importClause: jsImport.importClause && await this.visitDefined(jsImport.importClause, p), moduleSpecifier: jsImport.moduleSpecifier && await this.visitLeftPadded(jsImport.moduleSpecifier, p), attributes: jsImport.attributes && await this.visitDefined(jsImport.attributes, p), initializer: jsImport.initializer && await this.visitLeftPadded(jsImport.initializer, p) }; return updateIfChanged(jsImport, updates); } protected async visitImportClause(importClause: JS.ImportClause, p: P): Promise { const updates: any = { prefix: await this.visitSpace(importClause.prefix, p), markers: await this.visitMarkers(importClause.markers, p), name: importClause.name && await this.visitRightPadded(importClause.name, p), namedBindings: importClause.namedBindings && await this.visitDefined(importClause.namedBindings, p) }; return updateIfChanged(importClause, updates); } protected async visitNamedImports(namedImports: JS.NamedImports, p: P): Promise { const expression = await this.visitExpression(namedImports, p); if (!expression?.kind || expression.kind !== JS.Kind.NamedImports) { return expression; } namedImports = expression as JS.NamedImports; const updates: any = { prefix: await this.visitSpace(namedImports.prefix, p), markers: await this.visitMarkers(namedImports.markers, p), elements: await this.visitContainer(namedImports.elements, p), type: namedImports.type && await this.visitType(namedImports.type, p) }; return updateIfChanged(namedImports, updates); } protected async visitImportSpecifier(importSpecifier: JS.ImportSpecifier, p: P): Promise { const expression = await this.visitExpression(importSpecifier, p); if (!expression?.kind || expression.kind !== JS.Kind.ImportSpecifier) { return expression; } importSpecifier = expression as JS.ImportSpecifier; const updates: any = { prefix: await this.visitSpace(importSpecifier.prefix, p), markers: await this.visitMarkers(importSpecifier.markers, p), importType: await this.visitLeftPadded(importSpecifier.importType, p), specifier: await this.visitDefined(importSpecifier.specifier, p), type: importSpecifier.type && await this.visitType(importSpecifier.type, p) }; return updateIfChanged(importSpecifier, updates); } protected async visitImportAttributes(importAttributes: JS.ImportAttributes, p: P): Promise { const updates: any = { prefix: await this.visitSpace(importAttributes.prefix, p), markers: await this.visitMarkers(importAttributes.markers, p), elements: await this.visitContainer(importAttributes.elements, p) }; return updateIfChanged(importAttributes, updates); } protected async visitImportTypeAttributes(importTypeAttributes: JS.ImportTypeAttributes, p: P): Promise { const updates: any = { prefix: await this.visitSpace(importTypeAttributes.prefix, p), markers: await this.visitMarkers(importTypeAttributes.markers, p), token: await this.visitRightPadded(importTypeAttributes.token, p), elements: await this.visitContainer(importTypeAttributes.elements, p), end: await this.visitSpace(importTypeAttributes.end, p) }; return updateIfChanged(importTypeAttributes, updates); } protected async visitImportAttribute(importAttribute: JS.ImportAttribute, p: P): Promise { const statement = await this.visitStatement(importAttribute, p); if (!statement?.kind || statement.kind !== JS.Kind.ImportAttribute) { return statement; } importAttribute = statement as JS.ImportAttribute; const updates: any = { prefix: await this.visitSpace(importAttribute.prefix, p), markers: await this.visitMarkers(importAttribute.markers, p), name: await this.visitDefined(importAttribute.name, p), value: await this.visitLeftPadded(importAttribute.value, p) }; return updateIfChanged(importAttribute, updates); } protected async visitBinaryExtensions(jsBinary: JS.Binary, p: P): Promise { const updates: any = { prefix: await this.visitSpace(jsBinary.prefix, p), markers: await this.visitMarkers(jsBinary.markers, p), left: await this.visitDefined(jsBinary.left, p), operator: await this.visitLeftPadded(jsBinary.operator, p), right: await this.visitDefined(jsBinary.right, p), type: jsBinary.type && await this.visitType(jsBinary.type, p) }; return updateIfChanged(jsBinary, updates); } protected async visitLiteralType(literalType: JS.LiteralType, p: P): Promise { const expression = await this.visitExpression(literalType, p); if (!expression?.kind || expression.kind !== JS.Kind.LiteralType) { return expression; } literalType = expression as JS.LiteralType; const updates: any = { prefix: await this.visitSpace(literalType.prefix, p), markers: await this.visitMarkers(literalType.markers, p), literal: await this.visitDefined(literalType.literal, p), type: (await this.visitType(literalType.type, p))! }; return updateIfChanged(literalType, updates); } protected async visitMappedType(mappedType: JS.MappedType, p: P): Promise { const expression = await this.visitExpression(mappedType, p); if (!expression?.kind || expression.kind !== JS.Kind.MappedType) { return expression; } mappedType = expression as JS.MappedType; const updates: any = { prefix: await this.visitSpace(mappedType.prefix, p), markers: await this.visitMarkers(mappedType.markers, p), prefixToken: mappedType.prefixToken && await this.visitLeftPadded(mappedType.prefixToken, p), hasReadonly: await this.visitLeftPadded(mappedType.hasReadonly, p), keysRemapping: await this.visitDefined(mappedType.keysRemapping, p), suffixToken: mappedType.suffixToken && await this.visitLeftPadded(mappedType.suffixToken, p), hasQuestionToken: await this.visitLeftPadded(mappedType.hasQuestionToken, p), valueType: await this.visitContainer(mappedType.valueType, p), type: mappedType.type && await this.visitType(mappedType.type, p) }; return updateIfChanged(mappedType, updates); } protected async visitMappedTypeKeysRemapping(keysRemapping: JS.MappedType.KeysRemapping, p: P): Promise { const updates: any = { prefix: await this.visitSpace(keysRemapping.prefix, p), markers: await this.visitMarkers(keysRemapping.markers, p), typeParameter: await this.visitRightPadded(keysRemapping.typeParameter, p), nameType: keysRemapping.nameType && await this.visitRightPadded(keysRemapping.nameType, p) }; return updateIfChanged(keysRemapping, updates); } protected async visitMappedTypeParameter(mappedTypeParameter: JS.MappedType.Parameter, p: P): Promise { const updates: any = { prefix: await this.visitSpace(mappedTypeParameter.prefix, p), markers: await this.visitMarkers(mappedTypeParameter.markers, p), name: await this.visitDefined(mappedTypeParameter.name, p), iterateType: await this.visitLeftPadded(mappedTypeParameter.iterateType, p) }; return updateIfChanged(mappedTypeParameter, updates); } protected async visitObjectBindingPattern(objectBindingPattern: JS.ObjectBindingPattern, p: P): Promise { const expression = await this.visitExpression(objectBindingPattern, p); if (!expression?.kind || expression.kind !== JS.Kind.ObjectBindingPattern) { return expression; } objectBindingPattern = expression as JS.ObjectBindingPattern; const updates: any = { prefix: await this.visitSpace(objectBindingPattern.prefix, p), markers: await this.visitMarkers(objectBindingPattern.markers, p), leadingAnnotations: await mapAsync(objectBindingPattern.leadingAnnotations, item => this.visitDefined(item, p)), modifiers: await mapAsync(objectBindingPattern.modifiers, item => this.visitDefined(item, p)), typeExpression: objectBindingPattern.typeExpression && await this.visitDefined(objectBindingPattern.typeExpression, p), bindings: await this.visitContainer(objectBindingPattern.bindings, p), initializer: objectBindingPattern.initializer && await this.visitLeftPadded(objectBindingPattern.initializer, p) }; return updateIfChanged(objectBindingPattern, updates); } protected async visitPropertyAssignment(propertyAssignment: JS.PropertyAssignment, p: P): Promise { const statement = await this.visitStatement(propertyAssignment, p); if (!statement?.kind || statement.kind !== JS.Kind.PropertyAssignment) { return statement; } propertyAssignment = statement as JS.PropertyAssignment; const updates: any = { prefix: await this.visitSpace(propertyAssignment.prefix, p), markers: await this.visitMarkers(propertyAssignment.markers, p), name: await this.visitRightPadded(propertyAssignment.name, p), initializer: propertyAssignment.initializer && await this.visitDefined(propertyAssignment.initializer, p) }; return updateIfChanged(propertyAssignment, updates); } protected async visitSatisfiesExpression(satisfiesExpression: JS.SatisfiesExpression, p: P): Promise { const expression = await this.visitExpression(satisfiesExpression, p); if (!expression?.kind || expression.kind !== JS.Kind.SatisfiesExpression) { return expression; } satisfiesExpression = expression as JS.SatisfiesExpression; const updates: any = { prefix: await this.visitSpace(satisfiesExpression.prefix, p), markers: await this.visitMarkers(satisfiesExpression.markers, p), expression: await this.visitDefined(satisfiesExpression.expression, p), satisfiesType: await this.visitLeftPadded(satisfiesExpression.satisfiesType, p), type: satisfiesExpression.type && await this.visitType(satisfiesExpression.type, p) }; return updateIfChanged(satisfiesExpression, updates); } protected async visitScopedVariableDeclarations(scopedVariableDeclarations: JS.ScopedVariableDeclarations, p: P): Promise { const statement = await this.visitStatement(scopedVariableDeclarations, p); if (!statement?.kind || statement.kind !== JS.Kind.ScopedVariableDeclarations) { return statement; } scopedVariableDeclarations = statement as JS.ScopedVariableDeclarations; const updates: any = { prefix: await this.visitSpace(scopedVariableDeclarations.prefix, p), markers: await this.visitMarkers(scopedVariableDeclarations.markers, p), modifiers: await mapAsync(scopedVariableDeclarations.modifiers, item => this.visitDefined(item, p)), variables: await mapAsync(scopedVariableDeclarations.variables, item => this.visitRightPadded(item, p)) }; return updateIfChanged(scopedVariableDeclarations, updates); } protected async visitShebang(shebang: JS.Shebang, p: P): Promise { const updates: any = { prefix: await this.visitSpace(shebang.prefix, p), markers: await this.visitMarkers(shebang.markers, p) }; return updateIfChanged(shebang, updates); } protected async visitSpread(spread: JS.Spread, p: P): Promise { const expression = await this.visitExpression(spread, p); if (!expression?.kind || expression.kind !== JS.Kind.Spread) { return expression; } spread = expression as JS.Spread; const statement = await this.visitStatement(spread, p); if (!statement?.kind || statement.kind !== JS.Kind.Spread) { return statement; } spread = statement as JS.Spread; const updates: any = { prefix: await this.visitSpace(spread.prefix, p), markers: await this.visitMarkers(spread.markers, p), expression: await this.visitDefined(spread.expression, p), type: await this.visitType(spread.type, p) }; return updateIfChanged(spread, updates); } protected async visitStatementExpression(statementExpression: JS.StatementExpression, p: P): Promise { const expression = await this.visitExpression(statementExpression, p); if (!expression?.kind || expression.kind !== JS.Kind.StatementExpression) { return expression; } statementExpression = expression as JS.StatementExpression; const statement = await this.visitStatement(statementExpression, p); if (!statement?.kind || statement.kind !== JS.Kind.StatementExpression) { return statement; } statementExpression = statement as JS.StatementExpression; const updates: any = { prefix: await this.visitSpace(statementExpression.prefix, p), markers: await this.visitMarkers(statementExpression.markers, p), statement: await this.visitDefined(statementExpression.statement, p) }; return updateIfChanged(statementExpression, updates); } protected async visitTaggedTemplateExpression(taggedTemplateExpression: JS.TaggedTemplateExpression, p: P): Promise { const expression = await this.visitExpression(taggedTemplateExpression, p); if (!expression?.kind || expression.kind !== JS.Kind.TaggedTemplateExpression) { return expression; } taggedTemplateExpression = expression as JS.TaggedTemplateExpression; const statement = await this.visitStatement(taggedTemplateExpression, p); if (!statement?.kind || statement.kind !== JS.Kind.TaggedTemplateExpression) { return statement; } taggedTemplateExpression = statement as JS.TaggedTemplateExpression; const updates: any = { prefix: await this.visitSpace(taggedTemplateExpression.prefix, p), markers: await this.visitMarkers(taggedTemplateExpression.markers, p), tag: taggedTemplateExpression.tag && await this.visitRightPadded(taggedTemplateExpression.tag, p), typeArguments: taggedTemplateExpression.typeArguments && await this.visitContainer(taggedTemplateExpression.typeArguments, p), templateExpression: await this.visitDefined(taggedTemplateExpression.templateExpression, p), type: taggedTemplateExpression.type && await this.visitType(taggedTemplateExpression.type, p) }; return updateIfChanged(taggedTemplateExpression, updates); } protected async visitTemplateExpression(templateExpression: JS.TemplateExpression, p: P): Promise { const expression = await this.visitExpression(templateExpression, p); if (!expression?.kind || expression.kind !== JS.Kind.TemplateExpression) { return expression; } templateExpression = expression as JS.TemplateExpression; const statement = await this.visitStatement(templateExpression, p); if (!statement?.kind || statement.kind !== JS.Kind.TemplateExpression) { return statement; } templateExpression = statement as JS.TemplateExpression; const updates: any = { prefix: await this.visitSpace(templateExpression.prefix, p), markers: await this.visitMarkers(templateExpression.markers, p), head: await this.visitDefined(templateExpression.head, p), spans: await mapAsync(templateExpression.spans, item => this.visitRightPadded(item, p)), type: templateExpression.type && await this.visitType(templateExpression.type, p) }; return updateIfChanged(templateExpression, updates); } protected async visitTemplateExpressionSpan(span: JS.TemplateExpression.Span, p: P): Promise { const updates: any = { prefix: await this.visitSpace(span.prefix, p), markers: await this.visitMarkers(span.markers, p), expression: await this.visitDefined(span.expression, p), tail: await this.visitDefined(span.tail, p) }; return updateIfChanged(span, updates); } protected async visitTuple(tuple: JS.Tuple, p: P): Promise { const expression = await this.visitExpression(tuple, p); if (!expression?.kind || expression.kind !== JS.Kind.Tuple) { return expression; } tuple = expression as JS.Tuple; const updates: any = { prefix: await this.visitSpace(tuple.prefix, p), markers: await this.visitMarkers(tuple.markers, p), elements: await this.visitContainer(tuple.elements, p), type: tuple.type && await this.visitType(tuple.type, p) }; return updateIfChanged(tuple, updates); } protected async visitTypeDeclaration(typeDeclaration: JS.TypeDeclaration, p: P): Promise { const statement = await this.visitStatement(typeDeclaration, p); if (!statement?.kind || statement.kind !== JS.Kind.TypeDeclaration) { return statement; } typeDeclaration = statement as JS.TypeDeclaration; const updates: any = { prefix: await this.visitSpace(typeDeclaration.prefix, p), markers: await this.visitMarkers(typeDeclaration.markers, p), modifiers: await mapAsync(typeDeclaration.modifiers, item => this.visitDefined(item, p)), name: await this.visitLeftPadded(typeDeclaration.name, p), typeParameters: typeDeclaration.typeParameters && await this.visitDefined(typeDeclaration.typeParameters, p), initializer: await this.visitLeftPadded(typeDeclaration.initializer, p), type: typeDeclaration.type && await this.visitType(typeDeclaration.type, p) }; return updateIfChanged(typeDeclaration, updates); } protected async visitTypeOf(typeOf: JS.TypeOf, p: P): Promise { const expression = await this.visitExpression(typeOf, p); if (!expression?.kind || expression.kind !== JS.Kind.TypeOf) { return expression; } typeOf = expression as JS.TypeOf; const updates: any = { prefix: await this.visitSpace(typeOf.prefix, p), markers: await this.visitMarkers(typeOf.markers, p), expression: await this.visitDefined(typeOf.expression, p), type: typeOf.type && await this.visitType(typeOf.type, p) }; return updateIfChanged(typeOf, updates); } protected async visitTypeTreeExpression(typeTreeExpression: JS.TypeTreeExpression, p: P): Promise { const expression = await this.visitExpression(typeTreeExpression, p); if (!expression?.kind || expression.kind !== JS.Kind.TypeTreeExpression) { return expression; } typeTreeExpression = expression as JS.TypeTreeExpression; const updates: any = { prefix: await this.visitSpace(typeTreeExpression.prefix, p), markers: await this.visitMarkers(typeTreeExpression.markers, p), expression: await this.visitDefined(typeTreeExpression.expression, p) }; return updateIfChanged(typeTreeExpression, updates); } protected async visitAssignmentOperationExtensions(assignmentOperation: JS.AssignmentOperation, p: P): Promise { const updates: any = { prefix: await this.visitSpace(assignmentOperation.prefix, p), markers: await this.visitMarkers(assignmentOperation.markers, p), variable: await this.visitDefined(assignmentOperation.variable, p), operator: await this.visitLeftPadded(assignmentOperation.operator, p), assignment: await this.visitDefined(assignmentOperation.assignment, p), type: assignmentOperation.type && await this.visitType(assignmentOperation.type, p) }; return updateIfChanged(assignmentOperation, updates); } protected async visitIndexedAccessType(indexedAccessType: JS.IndexedAccessType, p: P): Promise { const expression = await this.visitExpression(indexedAccessType, p); if (!expression?.kind || expression.kind !== JS.Kind.IndexedAccessType) { return expression; } indexedAccessType = expression as JS.IndexedAccessType; const updates: any = { prefix: await this.visitSpace(indexedAccessType.prefix, p), markers: await this.visitMarkers(indexedAccessType.markers, p), objectType: await this.visitDefined(indexedAccessType.objectType, p), indexType: await this.visitDefined(indexedAccessType.indexType, p), type: indexedAccessType.type && await this.visitType(indexedAccessType.type, p) }; return updateIfChanged(indexedAccessType, updates); } protected async visitIndexedAccessTypeIndexType(indexType: JS.IndexedAccessType.IndexType, p: P): Promise { const updates: any = { prefix: await this.visitSpace(indexType.prefix, p), markers: await this.visitMarkers(indexType.markers, p), element: await this.visitRightPadded(indexType.element, p), type: indexType.type && await this.visitType(indexType.type, p) }; return updateIfChanged(indexType, updates); } protected async visitTypeQuery(typeQuery: JS.TypeQuery, p: P): Promise { const expression = await this.visitExpression(typeQuery, p); if (!expression?.kind || expression.kind !== JS.Kind.TypeQuery) { return expression; } typeQuery = expression as JS.TypeQuery; const updates: any = { prefix: await this.visitSpace(typeQuery.prefix, p), markers: await this.visitMarkers(typeQuery.markers, p), typeExpression: await this.visitDefined(typeQuery.typeExpression, p), typeArguments: typeQuery.typeArguments && await this.visitContainer(typeQuery.typeArguments, p), type: typeQuery.type && await this.visitType(typeQuery.type, p) }; return updateIfChanged(typeQuery, updates); } protected async visitTypeInfo(typeInfo: JS.TypeInfo, p: P): Promise { const expression = await this.visitExpression(typeInfo, p); if (!expression?.kind || expression.kind !== JS.Kind.TypeInfo) { return expression; } typeInfo = expression as JS.TypeInfo; const updates: any = { prefix: await this.visitSpace(typeInfo.prefix, p), markers: await this.visitMarkers(typeInfo.markers, p), typeIdentifier: await this.visitDefined(typeInfo.typeIdentifier, p) }; return updateIfChanged(typeInfo, updates); } protected async visitComputedPropertyName(computedPropertyName: JS.ComputedPropertyName, p: P): Promise { const expression = await this.visitExpression(computedPropertyName, p); if (!expression?.kind || expression.kind !== JS.Kind.ComputedPropertyName) { return expression; } computedPropertyName = expression as JS.ComputedPropertyName; const updates: any = { prefix: await this.visitSpace(computedPropertyName.prefix, p), markers: await this.visitMarkers(computedPropertyName.markers, p), expression: await this.visitRightPadded(computedPropertyName.expression, p) }; return updateIfChanged(computedPropertyName, updates); } protected async visitTypeOperator(typeOperator: JS.TypeOperator, p: P): Promise { const expression = await this.visitExpression(typeOperator, p); if (!expression?.kind || expression.kind !== JS.Kind.TypeOperator) { return expression; } typeOperator = expression as JS.TypeOperator; const updates: any = { prefix: await this.visitSpace(typeOperator.prefix, p), markers: await this.visitMarkers(typeOperator.markers, p), expression: await this.visitLeftPadded(typeOperator.expression, p) }; return updateIfChanged(typeOperator, updates); } protected async visitTypePredicate(typePredicate: JS.TypePredicate, p: P): Promise { const expression = await this.visitExpression(typePredicate, p); if (!expression?.kind || expression.kind !== JS.Kind.TypePredicate) { return expression; } typePredicate = expression as JS.TypePredicate; const updates: any = { prefix: await this.visitSpace(typePredicate.prefix, p), markers: await this.visitMarkers(typePredicate.markers, p), asserts: await this.visitLeftPadded(typePredicate.asserts, p), parameterName: await this.visitDefined(typePredicate.parameterName, p), expression: typePredicate.expression && await this.visitLeftPadded(typePredicate.expression, p), type: typePredicate.type && await this.visitType(typePredicate.type, p) }; return updateIfChanged(typePredicate, updates); } protected async visitUnion(union: JS.Union, p: P): Promise { const expression = await this.visitExpression(union, p); if (!expression?.kind || expression.kind !== JS.Kind.Union) { return expression; } union = expression as JS.Union; const updates: any = { prefix: await this.visitSpace(union.prefix, p), markers: await this.visitMarkers(union.markers, p), types: await mapAsync(union.types, item => this.visitRightPadded(item, p)), type: union.type && await this.visitType(union.type, p) }; return updateIfChanged(union, updates); } protected async visitIntersection(intersection: JS.Intersection, p: P): Promise { const expression = await this.visitExpression(intersection, p); if (!expression?.kind || expression.kind !== JS.Kind.Intersection) { return expression; } intersection = expression as JS.Intersection; const updates: any = { prefix: await this.visitSpace(intersection.prefix, p), markers: await this.visitMarkers(intersection.markers, p), types: await mapAsync(intersection.types, item => this.visitRightPadded(item, p)), type: intersection.type && await this.visitType(intersection.type, p) }; return updateIfChanged(intersection, updates); } protected async visitVoid(void_: JS.Void, p: P): Promise { const expression = await this.visitExpression(void_, p); if (!expression?.kind || expression.kind !== JS.Kind.Void) { return expression; } void_ = expression as JS.Void; const updates: any = { prefix: await this.visitSpace(void_.prefix, p), markers: await this.visitMarkers(void_.markers, p), expression: await this.visitDefined(void_.expression, p) }; return updateIfChanged(void_, updates); } protected async visitWithStatement(withStatement: JS.WithStatement, p: P): Promise { const statement = await this.visitStatement(withStatement, p); if (!statement?.kind || statement.kind !== JS.Kind.WithStatement) { return statement; } withStatement = statement as JS.WithStatement; const updates: any = { prefix: await this.visitSpace(withStatement.prefix, p), markers: await this.visitMarkers(withStatement.markers, p), expression: await this.visitDefined>(withStatement.expression, p), body: await this.visitRightPadded(withStatement.body, p) }; return updateIfChanged(withStatement, updates); } protected async visitIndexSignatureDeclaration(indexSignatureDeclaration: JS.IndexSignatureDeclaration, p: P): Promise { const statement = await this.visitStatement(indexSignatureDeclaration, p); if (!statement?.kind || statement.kind !== JS.Kind.IndexSignatureDeclaration) { return statement; } indexSignatureDeclaration = statement as JS.IndexSignatureDeclaration; const updates: any = { prefix: await this.visitSpace(indexSignatureDeclaration.prefix, p), markers: await this.visitMarkers(indexSignatureDeclaration.markers, p), modifiers: await mapAsync(indexSignatureDeclaration.modifiers, item => this.visitDefined(item, p)), parameters: await this.visitContainer(indexSignatureDeclaration.parameters, p), typeExpression: await this.visitLeftPadded(indexSignatureDeclaration.typeExpression, p), type: indexSignatureDeclaration.type && await this.visitType(indexSignatureDeclaration.type, p) }; return updateIfChanged(indexSignatureDeclaration, updates); } protected async visitComputedPropertyMethodDeclaration(computedPropMethod: JS.ComputedPropertyMethodDeclaration, p: P): Promise { const statement = await this.visitStatement(computedPropMethod, p); if (!statement?.kind || statement.kind !== JS.Kind.ComputedPropertyMethodDeclaration) { return statement; } computedPropMethod = statement as JS.ComputedPropertyMethodDeclaration; const updates: any = { prefix: await this.visitSpace(computedPropMethod.prefix, p), markers: await this.visitMarkers(computedPropMethod.markers, p), leadingAnnotations: await mapAsync(computedPropMethod.leadingAnnotations, item => this.visitDefined(item, p)), modifiers: await mapAsync(computedPropMethod.modifiers, item => this.visitDefined(item, p)), typeParameters: computedPropMethod.typeParameters && await this.visitDefined(computedPropMethod.typeParameters, p), returnTypeExpression: computedPropMethod.returnTypeExpression && await this.visitDefined(computedPropMethod.returnTypeExpression, p), name: await this.visitDefined(computedPropMethod.name, p), parameters: await this.visitContainer(computedPropMethod.parameters, p), body: computedPropMethod.body && await this.visitDefined(computedPropMethod.body, p), methodType: computedPropMethod.methodType && (await this.visitType(computedPropMethod.methodType, p) as Type.Method) }; return updateIfChanged(computedPropMethod, updates); } protected async visitForOfLoop(forOfLoop: JS.ForOfLoop, p: P): Promise { const updates: any = { prefix: await this.visitSpace(forOfLoop.prefix, p), markers: await this.visitMarkers(forOfLoop.markers, p), loop: await this.visitDefined(forOfLoop.loop, p) }; return updateIfChanged(forOfLoop, updates); } protected async visitForInLoop(forInLoop: JS.ForInLoop, p: P): Promise { const updates: any = { prefix: await this.visitSpace(forInLoop.prefix, p), markers: await this.visitMarkers(forInLoop.markers, p), control: await this.visitDefined(forInLoop.control, p), body: await this.visitRightPadded(forInLoop.body, p) }; return updateIfChanged(forInLoop, updates); } protected async visitNamespaceDeclaration(namespaceDeclaration: JS.NamespaceDeclaration, p: P): Promise { const statement = await this.visitStatement(namespaceDeclaration, p); if (!statement?.kind || statement.kind !== JS.Kind.NamespaceDeclaration) { return statement; } namespaceDeclaration = statement as JS.NamespaceDeclaration; const updates: any = { prefix: await this.visitSpace(namespaceDeclaration.prefix, p), markers: await this.visitMarkers(namespaceDeclaration.markers, p), modifiers: await mapAsync(namespaceDeclaration.modifiers, item => this.visitDefined(item, p)), keywordType: await this.visitLeftPadded(namespaceDeclaration.keywordType, p), name: await this.visitRightPadded(namespaceDeclaration.name, p), body: namespaceDeclaration.body && await this.visitDefined(namespaceDeclaration.body, p) }; return updateIfChanged(namespaceDeclaration, updates); } protected async visitTypeLiteral(typeLiteral: JS.TypeLiteral, p: P): Promise { const updates: any = { prefix: await this.visitSpace(typeLiteral.prefix, p), markers: await this.visitMarkers(typeLiteral.markers, p), members: await this.visitDefined(typeLiteral.members, p), type: typeLiteral.type && await this.visitType(typeLiteral.type, p) }; return updateIfChanged(typeLiteral, updates); } protected async visitArrayBindingPattern(arrayBindingPattern: JS.ArrayBindingPattern, p: P): Promise { const updates: any = { prefix: await this.visitSpace(arrayBindingPattern.prefix, p), markers: await this.visitMarkers(arrayBindingPattern.markers, p), elements: await this.visitContainer(arrayBindingPattern.elements, p), type: arrayBindingPattern.type && await this.visitType(arrayBindingPattern.type, p) }; return updateIfChanged(arrayBindingPattern, updates); } protected async visitBindingElement(bindingElement: JS.BindingElement, p: P): Promise { const statement = await this.visitStatement(bindingElement, p); if (!statement?.kind || statement.kind !== JS.Kind.BindingElement) { return statement; } bindingElement = statement as JS.BindingElement; const updates: any = { prefix: await this.visitSpace(bindingElement.prefix, p), markers: await this.visitMarkers(bindingElement.markers, p), propertyName: bindingElement.propertyName && await this.visitRightPadded(bindingElement.propertyName, p), name: await this.visitDefined(bindingElement.name, p), initializer: bindingElement.initializer && await this.visitLeftPadded(bindingElement.initializer, p), variableType: bindingElement.variableType && (await this.visitType(bindingElement.variableType, p) as Type.Variable) }; return updateIfChanged(bindingElement, updates); } protected async visitExportDeclaration(exportDeclaration: JS.ExportDeclaration, p: P): Promise { const statement = await this.visitStatement(exportDeclaration, p); if (!statement?.kind || statement.kind !== JS.Kind.ExportDeclaration) { return statement; } exportDeclaration = statement as JS.ExportDeclaration; const updates: any = { prefix: await this.visitSpace(exportDeclaration.prefix, p), markers: await this.visitMarkers(exportDeclaration.markers, p), modifiers: await mapAsync(exportDeclaration.modifiers, item => this.visitDefined(item, p)), typeOnly: await this.visitLeftPadded(exportDeclaration.typeOnly, p), exportClause: exportDeclaration.exportClause && await this.visitDefined(exportDeclaration.exportClause, p), moduleSpecifier: exportDeclaration.moduleSpecifier && await this.visitLeftPadded(exportDeclaration.moduleSpecifier, p), attributes: exportDeclaration.attributes && await this.visitDefined(exportDeclaration.attributes, p) }; return updateIfChanged(exportDeclaration, updates); } protected async visitExportAssignment(exportAssignment: JS.ExportAssignment, p: P): Promise { const statement = await this.visitStatement(exportAssignment, p); if (!statement?.kind || statement.kind !== JS.Kind.ExportAssignment) { return statement; } exportAssignment = statement as JS.ExportAssignment; const updates: any = { prefix: await this.visitSpace(exportAssignment.prefix, p), markers: await this.visitMarkers(exportAssignment.markers, p), expression: await this.visitLeftPadded(exportAssignment.expression, p) }; return updateIfChanged(exportAssignment, updates); } protected async visitNamedExports(namedExports: JS.NamedExports, p: P): Promise { const updates: any = { prefix: await this.visitSpace(namedExports.prefix, p), markers: await this.visitMarkers(namedExports.markers, p), elements: await this.visitContainer(namedExports.elements, p), type: namedExports.type && await this.visitType(namedExports.type, p) }; return updateIfChanged(namedExports, updates); } protected async visitExportSpecifier(exportSpecifier: JS.ExportSpecifier, p: P): Promise { const updates: any = { prefix: await this.visitSpace(exportSpecifier.prefix, p), markers: await this.visitMarkers(exportSpecifier.markers, p), typeOnly: await this.visitLeftPadded(exportSpecifier.typeOnly, p), specifier: await this.visitDefined(exportSpecifier.specifier, p), type: exportSpecifier.type && await this.visitType(exportSpecifier.type, p) }; return updateIfChanged(exportSpecifier, updates); } override async accept(j: J2, p: P2): Promise { if (isJavaScript(j)) { const tree = j as JS; switch (tree.kind) { case JS.Kind.Alias: return this.visitAlias(tree as unknown as JS.Alias, p); case JS.Kind.ArrowFunction: return this.visitArrowFunction(tree as unknown as JS.ArrowFunction, p); case JS.Kind.As: return this.visitAs(tree as unknown as JS.As, p); case JS.Kind.Await: return this.visitAwait(tree as unknown as JS.Await, p); case JS.Kind.CompilationUnit: return this.visitJsCompilationUnit(tree as unknown as JS.CompilationUnit, p); case JS.Kind.ComputedPropertyName: return this.visitComputedPropertyName(tree as unknown as JS.ComputedPropertyName, p); case JS.Kind.ConditionalType: return this.visitConditionalType(tree as unknown as JS.ConditionalType, p); case JS.Kind.Delete: return this.visitDelete(tree as unknown as JS.Delete, p); case JS.Kind.ExpressionStatement: return this.visitExpressionStatement(tree as unknown as JS.ExpressionStatement, p); case JS.Kind.ExpressionWithTypeArguments: return this.visitExpressionWithTypeArguments(tree as unknown as JS.ExpressionWithTypeArguments, p); case JS.Kind.FunctionCall: return this.visitFunctionCall(tree as unknown as JS.FunctionCall, p); case JS.Kind.FunctionType: return this.visitFunctionType(tree as unknown as JS.FunctionType, p); case JS.Kind.InferType: return this.visitInferType(tree as unknown as JS.InferType, p); case JS.Kind.ImportType: return this.visitImportType(tree as unknown as JS.ImportType, p); case JS.Kind.Import: return this.visitImportDeclaration(tree as unknown as JS.Import, p); case JS.Kind.ImportClause: return this.visitImportClause(tree as unknown as JS.ImportClause, p); case JS.Kind.NamedImports: return this.visitNamedImports(tree as unknown as JS.NamedImports, p); case JS.Kind.ImportSpecifier: return this.visitImportSpecifier(tree as unknown as JS.ImportSpecifier, p); case JS.Kind.ImportAttributes: return this.visitImportAttributes(tree as unknown as JS.ImportAttributes, p); case JS.Kind.ImportTypeAttributes: return this.visitImportTypeAttributes(tree as unknown as JS.ImportTypeAttributes, p); case JS.Kind.ImportAttribute: return this.visitImportAttribute(tree as unknown as JS.ImportAttribute, p); case JS.Kind.JsxAttribute: return this.visitJsxAttribute(tree as unknown as JSX.Attribute, p); case JS.Kind.JsxSpreadAttribute: return this.visitJsxSpreadAttribute(tree as unknown as JSX.SpreadAttribute, p); case JS.Kind.JsxEmbeddedExpression: return this.visitJsxEmbeddedExpression(tree as unknown as JSX.EmbeddedExpression, p); case JS.Kind.JsxNamespacedName: return this.visitJsxNamespacedName(tree as unknown as JSX.NamespacedName, p); case JS.Kind.JsxTag: return this.visitJsxTag(tree as unknown as JSX.Tag, p); case JS.Kind.Binary: return this.visitBinaryExtensions(tree as unknown as JS.Binary, p); case JS.Kind.LiteralType: return this.visitLiteralType(tree as unknown as JS.LiteralType, p); case JS.Kind.MappedType: return this.visitMappedType(tree as unknown as JS.MappedType, p); case JS.Kind.MappedTypeKeysRemapping: return this.visitMappedTypeKeysRemapping(tree as unknown as JS.MappedType.KeysRemapping, p); case JS.Kind.MappedTypeParameter: return this.visitMappedTypeParameter(tree as unknown as JS.MappedType.Parameter, p); case JS.Kind.ObjectBindingPattern: return this.visitObjectBindingPattern(tree as unknown as JS.ObjectBindingPattern, p); case JS.Kind.PropertyAssignment: return this.visitPropertyAssignment(tree as unknown as JS.PropertyAssignment, p); case JS.Kind.SatisfiesExpression: return this.visitSatisfiesExpression(tree as unknown as JS.SatisfiesExpression, p); case JS.Kind.ScopedVariableDeclarations: return this.visitScopedVariableDeclarations(tree as unknown as JS.ScopedVariableDeclarations, p); case JS.Kind.Shebang: return this.visitShebang(tree as unknown as JS.Shebang, p); case JS.Kind.Spread: return this.visitSpread(tree as unknown as JS.Spread, p); case JS.Kind.StatementExpression: return this.visitStatementExpression(tree as unknown as JS.StatementExpression, p); case JS.Kind.TaggedTemplateExpression: return this.visitTaggedTemplateExpression(tree as unknown as JS.TaggedTemplateExpression, p); case JS.Kind.TemplateExpression: return this.visitTemplateExpression(tree as unknown as JS.TemplateExpression, p); case JS.Kind.TemplateExpressionSpan: return this.visitTemplateExpressionSpan(tree as unknown as JS.TemplateExpression.Span, p); case JS.Kind.Tuple: return this.visitTuple(tree as unknown as JS.Tuple, p); case JS.Kind.TypeDeclaration: return this.visitTypeDeclaration(tree as unknown as JS.TypeDeclaration, p); case JS.Kind.TypeOf: return this.visitTypeOf(tree as unknown as JS.TypeOf, p); case JS.Kind.TypeTreeExpression: return this.visitTypeTreeExpression(tree as unknown as JS.TypeTreeExpression, p); case JS.Kind.AssignmentOperation: return this.visitAssignmentOperationExtensions(tree as unknown as JS.AssignmentOperation, p); case JS.Kind.IndexedAccessType: return this.visitIndexedAccessType(tree as unknown as JS.IndexedAccessType, p); case JS.Kind.IndexType: return this.visitIndexedAccessTypeIndexType(tree as unknown as JS.IndexedAccessType.IndexType, p); case JS.Kind.TypeQuery: return this.visitTypeQuery(tree as unknown as JS.TypeQuery, p); case JS.Kind.TypeInfo: return this.visitTypeInfo(tree as unknown as JS.TypeInfo, p); case JS.Kind.TypeOperator: return this.visitTypeOperator(tree as unknown as JS.TypeOperator, p); case JS.Kind.TypePredicate: return this.visitTypePredicate(tree as unknown as JS.TypePredicate, p); case JS.Kind.Union: return this.visitUnion(tree as unknown as JS.Union, p); case JS.Kind.Intersection: return this.visitIntersection(tree as unknown as JS.Intersection, p); case JS.Kind.Void: return this.visitVoid(tree as unknown as JS.Void, p); case JS.Kind.WithStatement: return this.visitWithStatement(tree as unknown as JS.WithStatement, p); case JS.Kind.IndexSignatureDeclaration: return this.visitIndexSignatureDeclaration(tree as unknown as JS.IndexSignatureDeclaration, p); case JS.Kind.ComputedPropertyMethodDeclaration: return this.visitComputedPropertyMethodDeclaration(tree as unknown as JS.ComputedPropertyMethodDeclaration, p); case JS.Kind.ForOfLoop: return this.visitForOfLoop(tree as unknown as JS.ForOfLoop, p); case JS.Kind.ForInLoop: return this.visitForInLoop(tree as unknown as JS.ForInLoop, p); case JS.Kind.NamespaceDeclaration: return this.visitNamespaceDeclaration(tree as unknown as JS.NamespaceDeclaration, p); case JS.Kind.TypeLiteral: return this.visitTypeLiteral(tree as unknown as JS.TypeLiteral, p); case JS.Kind.ArrayBindingPattern: return this.visitArrayBindingPattern(tree as unknown as JS.ArrayBindingPattern, p); case JS.Kind.BindingElement: return this.visitBindingElement(tree as unknown as JS.BindingElement, p); case JS.Kind.ExportDeclaration: return this.visitExportDeclaration(tree as unknown as JS.ExportDeclaration, p); case JS.Kind.ExportAssignment: return this.visitExportAssignment(tree as unknown as JS.ExportAssignment, p); case JS.Kind.NamedExports: return this.visitNamedExports(tree as unknown as JS.NamedExports, p); case JS.Kind.ExportSpecifier: return this.visitExportSpecifier(tree as unknown as JS.ExportSpecifier, p); } } return super.accept(j, p); } }