/*
* 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 {Cursor, isTree, SourceFile} from "../tree";
import {mapAsync, updateIfChanged} from "../util";
import {TreeVisitor, ValidRecipeReturnType} from "../visitor";
import {Expression, isSpace, J, NameTree, Statement, TypedTree, TypeTree} from "./tree";
import {create, Draft, rawReturn} from "mutative";
import {Type} from "./type";
const javaKindValues = new Set(Object.values(J.Kind));
const extendedJavaKinds = new Map(visitor: JavaVisitor) => JavaVisitor
>();
/**
* Register additional kind values for interfaces that extend J.
* This allows isJava to recognize implementations of those interfaces.
* @param kinds - Array of kind values to register
* @param adapter - Adapter function to transform a JavaVisitor to, for example, a JavaScriptVisitor
*/
export function registerJavaExtensionKinds(
kinds: readonly string[],
adapter:
(visitor: JavaVisitor
) => JavaVisitor
): void {
for (const kind of kinds) {
extendedJavaKinds.set(kind, adapter);
}
}
export function isJava(tree: any): tree is J {
return javaKindValues.has(tree["kind"]) || extendedJavaKinds.has(tree["kind"]);
}
export class JavaVisitor
extends TreeVisitor {
// protected javadocVisitor: any | null = null;
async isAcceptable(sourceFile: SourceFile): Promise {
return isJava(sourceFile);
}
// noinspection JSUnusedGlobalSymbols,JSUnusedLocalSymbols
protected async visitExpression(expression: Expression, p: P): Promise {
return expression;
}
// noinspection JSUnusedGlobalSymbols,JSUnusedLocalSymbols
protected async visitStatement(statement: Statement, p: P): Promise {
return statement;
}
// noinspection JSUnusedLocalSymbols
public async visitSpace(space: J.Space, p: P): Promise {
return space;
}
// noinspection JSUnusedLocalSymbols
protected async visitType(javaType: Type | undefined, p: P): Promise {
return javaType;
}
// noinspection JSUnusedLocalSymbols
protected async visitTypeName(nameTree: N, p: P): Promise {
return nameTree;
}
protected async visitAnnotatedType(annotatedType: J.AnnotatedType, p: P): Promise {
const expression = await this.visitExpression(annotatedType, p);
if (!expression?.kind || expression.kind !== J.Kind.AnnotatedType) {
return expression;
}
annotatedType = expression as J.AnnotatedType;
const updates = {
prefix: await this.visitSpace(annotatedType.prefix, p),
markers: await this.visitMarkers(annotatedType.markers, p),
annotations: await mapAsync(annotatedType.annotations, a => this.visitDefined(a, p)),
typeExpression: await this.visitDefined(annotatedType.typeExpression, p) as TypedTree
};
return updateIfChanged(annotatedType, updates);
}
protected async visitAnnotation(annotation: J.Annotation, p: P): Promise {
const expression = await this.visitExpression(annotation, p);
if (!expression?.kind || expression.kind !== J.Kind.Annotation) {
return expression;
}
annotation = expression as J.Annotation;
const updates = {
prefix: await this.visitSpace(annotation.prefix, p),
markers: await this.visitMarkers(annotation.markers, p),
annotationType: await this.visitTypeName(annotation.annotationType, p),
arguments: await this.visitOptionalContainer(annotation.arguments, p)
};
return updateIfChanged(annotation, updates);
}
protected async visitArrayAccess(arrayAccess: J.ArrayAccess, p: P): Promise {
const expression = await this.visitExpression(arrayAccess, p);
if (!expression?.kind || expression.kind !== J.Kind.ArrayAccess) {
return expression;
}
arrayAccess = expression as J.ArrayAccess;
const updates = {
prefix: await this.visitSpace(arrayAccess.prefix, p),
markers: await this.visitMarkers(arrayAccess.markers, p),
indexed: await this.visitDefined(arrayAccess.indexed, p) as Expression,
dimension: await this.visitDefined(arrayAccess.dimension, p) as J.ArrayDimension
};
return updateIfChanged(arrayAccess, updates);
}
protected async visitArrayDimension(arrayDimension: J.ArrayDimension, p: P): Promise {
const updates = {
prefix: await this.visitSpace(arrayDimension.prefix, p),
markers: await this.visitMarkers(arrayDimension.markers, p),
index: await this.visitRightPadded(arrayDimension.index, p)
};
return updateIfChanged(arrayDimension, updates);
}
protected async visitArrayType(arrayType: J.ArrayType, p: P): Promise {
const expression = await this.visitExpression(arrayType, p);
if (!expression?.kind || expression.kind !== J.Kind.ArrayType) {
return expression;
}
arrayType = expression as J.ArrayType;
const updates: any = {
prefix: await this.visitSpace(arrayType.prefix, p),
markers: await this.visitMarkers(arrayType.markers, p),
elementType: await this.visitDefined(arrayType.elementType, p) as TypedTree,
dimension: await this.visitLeftPadded(arrayType.dimension, p),
type: await this.visitType(arrayType.type, p)
};
if (arrayType.annotations) {
updates.annotations = await mapAsync(arrayType.annotations, a => this.visitDefined(a, p));
}
return updateIfChanged(arrayType, updates);
}
protected async visitAssert(anAssert: J.Assert, p: P): Promise {
const statement = await this.visitStatement(anAssert, p);
if (!statement?.kind || statement.kind !== J.Kind.Assert) {
return statement;
}
anAssert = statement as J.Assert;
const updates = {
prefix: await this.visitSpace(anAssert.prefix, p),
markers: await this.visitMarkers(anAssert.markers, p),
condition: await this.visitDefined(anAssert.condition, p) as Expression,
detail: await this.visitOptionalLeftPadded(anAssert.detail, p)
};
return updateIfChanged(anAssert, updates);
}
protected async visitAssignment(assignment: J.Assignment, p: P): Promise {
const expression = await this.visitExpression(assignment, p);
if (!expression?.kind || expression.kind !== J.Kind.Assignment) {
return expression;
}
assignment = expression as J.Assignment;
const statement = await this.visitStatement(assignment, p);
if (!statement?.kind || statement.kind !== J.Kind.Assignment) {
return statement;
}
assignment = statement as J.Assignment;
const updates = {
prefix: await this.visitSpace(assignment.prefix, p),
markers: await this.visitMarkers(assignment.markers, p),
variable: await this.visitDefined(assignment.variable, p) as Expression,
assignment: await this.visitLeftPadded(assignment.assignment, p),
type: await this.visitType(assignment.type, p)
};
return updateIfChanged(assignment, updates);
}
protected async visitAssignmentOperation(assignOp: J.AssignmentOperation, p: P): Promise {
const expression = await this.visitExpression(assignOp, p);
if (!expression?.kind || expression.kind !== J.Kind.AssignmentOperation) {
return expression;
}
assignOp = expression as J.AssignmentOperation;
const updates = {
prefix: await this.visitSpace(assignOp.prefix, p),
markers: await this.visitMarkers(assignOp.markers, p),
variable: await this.visitDefined(assignOp.variable, p) as Expression,
operator: await this.visitLeftPadded(assignOp.operator, p),
assignment: await this.visitDefined(assignOp.assignment, p) as Expression,
type: await this.visitType(assignOp.type, p)
};
return updateIfChanged(assignOp, updates);
}
protected async visitBinary(binary: J.Binary, p: P): Promise {
const expression = await this.visitExpression(binary, p);
if (!expression?.kind || expression.kind !== J.Kind.Binary) {
return expression;
}
binary = expression as J.Binary;
const updates = {
prefix: await this.visitSpace(binary.prefix, p),
markers: await this.visitMarkers(binary.markers, p),
left: await this.visitDefined(binary.left, p) as Expression,
operator: await this.visitLeftPadded(binary.operator, p),
right: await this.visitDefined(binary.right, p) as Expression,
type: await this.visitType(binary.type, p)
};
return updateIfChanged(binary, updates);
}
protected async visitBlock(block: J.Block, p: P): Promise {
const updates = {
prefix: await this.visitSpace(block.prefix, p),
markers: await this.visitMarkers(block.markers, p),
static: await this.visitRightPadded(block.static, p),
statements: await mapAsync(block.statements, stmt => this.visitRightPadded(stmt, p)),
end: await this.visitSpace(block.end, p)
};
return updateIfChanged(block, updates);
}
protected async visitBreak(breakStatement: J.Break, p: P): Promise {
const statement = await this.visitStatement(breakStatement, p);
if (!statement?.kind || statement.kind !== J.Kind.Break) {
return statement;
}
breakStatement = statement as J.Break;
const updates: any = {
prefix: await this.visitSpace(breakStatement.prefix, p),
markers: await this.visitMarkers(breakStatement.markers, p)
};
if (breakStatement.label) {
updates.label = await this.visitDefined(breakStatement.label, p) as J.Identifier;
}
return updateIfChanged(breakStatement, updates);
}
protected async visitCase(aCase: J.Case, p: P): Promise {
const statement = await this.visitStatement(aCase, p);
if (!statement?.kind || statement.kind !== J.Kind.Case) {
return statement;
}
aCase = statement as J.Case;
const updates: any = {
prefix: await this.visitSpace(aCase.prefix, p),
markers: await this.visitMarkers(aCase.markers, p),
caseLabels: await this.visitContainer(aCase.caseLabels, p),
statements: await this.visitContainer(aCase.statements, p),
body: await this.visitOptionalRightPadded(aCase.body, p)
};
if (aCase.guard) {
updates.guard = await this.visitDefined(aCase.guard, p) as Expression;
}
return updateIfChanged(aCase, updates);
}
protected async visitClassDeclaration(classDecl: J.ClassDeclaration, p: P): Promise {
const statement = await this.visitStatement(classDecl, p);
if (!statement?.kind || statement.kind !== J.Kind.ClassDeclaration) {
return statement;
}
classDecl = statement as J.ClassDeclaration;
const updates: any = {
prefix: await this.visitSpace(classDecl.prefix, p),
markers: await this.visitMarkers(classDecl.markers, p),
leadingAnnotations: await mapAsync(classDecl.leadingAnnotations, a => this.visitDefined(a, p)),
modifiers: await mapAsync(classDecl.modifiers, m => this.visitDefined(m, p)),
classKind: await this.visitDefined(classDecl.classKind, p) as J.ClassDeclaration.Kind,
name: await this.visitDefined(classDecl.name, p) as J.Identifier,
typeParameters: await this.visitOptionalContainer(classDecl.typeParameters, p),
primaryConstructor: await this.visitOptionalContainer(classDecl.primaryConstructor, p),
extends: await this.visitOptionalLeftPadded(classDecl.extends, p),
implements: await this.visitOptionalContainer(classDecl.implements, p),
permitting: await this.visitOptionalContainer(classDecl.permitting, p),
body: await this.visitDefined(classDecl.body, p) as J.Block,
type: await this.visitType(classDecl.type, p) as Type.Class | undefined
};
return updateIfChanged(classDecl, updates);
}
protected async visitClassDeclarationKind(kind: J.ClassDeclaration.Kind, p: P): Promise {
const updates: any = {
prefix: await this.visitSpace(kind.prefix, p),
markers: await this.visitMarkers(kind.markers, p),
annotations: await mapAsync(kind.annotations, a => this.visitDefined(a, p))
};
return updateIfChanged(kind, updates);
}
protected async visitCompilationUnit(cu: J.CompilationUnit, p: P): Promise {
const updates: any = {
prefix: await this.visitSpace(cu.prefix, p),
markers: await this.visitMarkers(cu.markers, p),
packageDeclaration: await this.visitRightPadded(cu.packageDeclaration, p) as J.RightPadded,
imports: await mapAsync(cu.imports, imp => this.visitRightPadded(imp, p)),
classes: await mapAsync(cu.classes, cls => this.visitDefined(cls, p) as Promise),
eof: await this.visitSpace(cu.eof, p)
};
return updateIfChanged(cu, updates);
}
protected async visitContinue(continueStatement: J.Continue, p: P): Promise {
const statement = await this.visitStatement(continueStatement, p);
if (!statement?.kind || statement.kind !== J.Kind.Continue) {
return statement;
}
continueStatement = statement as J.Continue;
const updates: any = {
prefix: await this.visitSpace(continueStatement.prefix, p),
markers: await this.visitMarkers(continueStatement.markers, p)
};
if (continueStatement.label) {
updates.label = await this.visitDefined(continueStatement.label, p) as J.Identifier;
}
return updateIfChanged(continueStatement, updates);
}
protected async visitControlParentheses(controlParens: J.ControlParentheses, p: P): Promise {
const updates: any = {
prefix: await this.visitSpace(controlParens.prefix, p),
markers: await this.visitMarkers(controlParens.markers, p),
tree: await this.visitRightPadded(controlParens.tree, p)
};
return updateIfChanged(controlParens, updates);
}
protected async visitDeconstructionPattern(pattern: J.DeconstructionPattern, p: P): Promise {
const updates: any = {
prefix: await this.visitSpace(pattern.prefix, p),
markers: await this.visitMarkers(pattern.markers, p),
deconstructor: await this.visitDefined(pattern.deconstructor, p) as Expression,
nested: await this.visitContainer(pattern.nested, p),
type: await this.visitType(pattern.type, p)
};
return updateIfChanged(pattern, updates);
}
protected async visitDoWhileLoop(doWhileLoop: J.DoWhileLoop, p: P): Promise {
const statement = await this.visitStatement(doWhileLoop, p);
if (!statement?.kind || statement.kind !== J.Kind.DoWhileLoop) {
return statement;
}
doWhileLoop = statement as J.DoWhileLoop;
const updates: any = {
prefix: await this.visitSpace(doWhileLoop.prefix, p),
markers: await this.visitMarkers(doWhileLoop.markers, p),
body: await this.visitRightPadded(doWhileLoop.body, p),
whileCondition: await this.visitLeftPadded(doWhileLoop.whileCondition, p)
};
return updateIfChanged(doWhileLoop, updates);
}
protected async visitEmpty(empty: J.Empty, p: P): Promise {
const expression = await this.visitExpression(empty, p);
if (!expression?.kind || expression.kind !== J.Kind.Empty) {
return expression;
}
empty = expression as J.Empty;
const statement = await this.visitStatement(empty, p);
if (!statement?.kind || statement.kind !== J.Kind.Empty) {
return statement;
}
empty = statement as J.Empty;
const updates: any = {
prefix: await this.visitSpace(empty.prefix, p),
markers: await this.visitMarkers(empty.markers, p)
};
return updateIfChanged(empty, updates);
}
protected async visitEnumValue(enumValue: J.EnumValue, p: P): Promise {
const updates: any = {
prefix: await this.visitSpace(enumValue.prefix, p),
markers: await this.visitMarkers(enumValue.markers, p),
annotations: await mapAsync(enumValue.annotations, a => this.visitDefined(a, p)),
name: await this.visitDefined(enumValue.name, p) as J.Identifier
};
if (enumValue.initializer) {
updates.initializer = await this.visitDefined(enumValue.initializer, p) as J.NewClass;
}
return updateIfChanged(enumValue, updates);
}
protected async visitEnumValueSet(enumValueSet: J.EnumValueSet, p: P): Promise {
const statement = await this.visitStatement(enumValueSet, p);
if (!statement?.kind || statement.kind !== J.Kind.EnumValueSet) {
return statement;
}
enumValueSet = statement as J.EnumValueSet;
const updates: any = {
prefix: await this.visitSpace(enumValueSet.prefix, p),
markers: await this.visitMarkers(enumValueSet.markers, p),
enums: await mapAsync(enumValueSet.enums, e => this.visitRightPadded(e, p))
};
return updateIfChanged(enumValueSet, updates);
}
protected async visitErroneous(erroneous: J.Erroneous, p: P): Promise {
const expression = await this.visitExpression(erroneous, p);
if (!expression?.kind || expression.kind !== J.Kind.Erroneous) {
return expression;
}
erroneous = expression as J.Erroneous;
const statement = await this.visitStatement(erroneous, p);
if (!statement?.kind || statement.kind !== J.Kind.Erroneous) {
return statement;
}
erroneous = statement as J.Erroneous;
const updates: any = {
prefix: await this.visitSpace(erroneous.prefix, p),
markers: await this.visitMarkers(erroneous.markers, p)
};
return updateIfChanged(erroneous, updates);
}
protected async visitFieldAccess(fieldAccess: J.FieldAccess, p: P): Promise {
const expression = await this.visitExpression(fieldAccess, p);
if (!expression?.kind || expression.kind !== J.Kind.FieldAccess) {
return expression;
}
fieldAccess = expression as J.FieldAccess;
const statement = await this.visitStatement(fieldAccess, p);
if (!statement?.kind || statement.kind !== J.Kind.FieldAccess) {
return statement;
}
fieldAccess = statement as J.FieldAccess;
const updates: any = {
prefix: await this.visitSpace(fieldAccess.prefix, p),
markers: await this.visitMarkers(fieldAccess.markers, p),
target: await this.visitDefined(fieldAccess.target, p) as Expression,
name: await this.visitLeftPadded(fieldAccess.name, p),
type: await this.visitType(fieldAccess.type, p)
};
return updateIfChanged(fieldAccess, updates);
}
protected async visitForEachLoop(forLoop: J.ForEachLoop, p: P): Promise {
const statement = await this.visitStatement(forLoop, p);
if (!statement?.kind || statement.kind !== J.Kind.ForEachLoop) {
return statement;
}
forLoop = statement as J.ForEachLoop;
const updates: any = {
prefix: await this.visitSpace(forLoop.prefix, p),
markers: await this.visitMarkers(forLoop.markers, p),
control: await this.visitDefined(forLoop.control, p) as J.ForEachLoop.Control,
body: await this.visitRightPadded(forLoop.body, p)
};
return updateIfChanged(forLoop, updates);
}
protected async visitForEachLoopControl(control: J.ForEachLoop.Control, p: P): Promise {
const updates: any = {
prefix: await this.visitSpace(control.prefix, p),
markers: await this.visitMarkers(control.markers, p),
variable: await this.visitRightPadded(control.variable, p),
iterable: await this.visitRightPadded(control.iterable, p)
};
return updateIfChanged(control, updates);
}
protected async visitForLoop(forLoop: J.ForLoop, p: P): Promise {
const statement = await this.visitStatement(forLoop, p);
if (!statement?.kind || statement.kind !== J.Kind.ForLoop) {
return statement;
}
forLoop = statement as J.ForLoop;
const updates: any = {
prefix: await this.visitSpace(forLoop.prefix, p),
markers: await this.visitMarkers(forLoop.markers, p),
control: await this.visitDefined(forLoop.control, p) as J.ForLoop.Control,
body: await this.visitRightPadded(forLoop.body, p)
};
return updateIfChanged(forLoop, updates);
}
protected async visitForLoopControl(control: J.ForLoop.Control, p: P): Promise {
const updates: any = {
prefix: await this.visitSpace(control.prefix, p),
markers: await this.visitMarkers(control.markers, p),
init: await mapAsync(control.init, i => this.visitRightPadded(i, p)),
condition: await this.visitOptionalRightPadded(control.condition, p),
update: await mapAsync(control.update, u => this.visitRightPadded(u, p))
};
return updateIfChanged(control, updates);
}
protected async visitIdentifier(ident: J.Identifier, p: P): Promise {
const expression = await this.visitExpression(ident, p);
if (!expression?.kind || expression.kind !== J.Kind.Identifier) {
return expression;
}
ident = expression as J.Identifier;
const updates: any = {
prefix: await this.visitSpace(ident.prefix, p),
markers: await this.visitMarkers(ident.markers, p),
annotations: await mapAsync(ident.annotations, a => this.visitDefined(a, p)),
type: await this.visitType(ident.type, p),
fieldType: await this.visitType(ident.fieldType, p) as Type.Variable | undefined
};
return updateIfChanged(ident, updates);
}
protected async visitIf(iff: J.If, p: P): Promise {
const statement = await this.visitStatement(iff, p);
if (!statement?.kind || statement.kind !== J.Kind.If) {
return statement;
}
iff = statement as J.If;
const updates: any = {
prefix: await this.visitSpace(iff.prefix, p),
markers: await this.visitMarkers(iff.markers, p),
ifCondition: await this.visitDefined(iff.ifCondition, p) as J.ControlParentheses,
thenPart: await this.visitRightPadded(iff.thenPart, p)
};
if (iff.elsePart) {
updates.elsePart = await this.visitDefined(iff.elsePart, p) as J.If.Else;
}
return updateIfChanged(iff, updates);
}
protected async visitElse(anElse: J.If.Else, p: P): Promise {
const updates: any = {
prefix: await this.visitSpace(anElse.prefix, p),
markers: await this.visitMarkers(anElse.markers, p),
body: await this.visitRightPadded(anElse.body, p)
};
return updateIfChanged(anElse, updates);
}
protected async visitImport(anImport: J.Import, p: P): Promise {
const updates: any = {
prefix: await this.visitSpace(anImport.prefix, p),
markers: await this.visitMarkers(anImport.markers, p),
static: await this.visitLeftPadded(anImport.static, p),
qualid: await this.visitDefined(anImport.qualid, p) as J.FieldAccess,
alias: await this.visitOptionalLeftPadded(anImport.alias, p)
};
return updateIfChanged(anImport, updates);
}
protected async visitInstanceOf(instanceOf: J.InstanceOf, p: P): Promise {
const expression = await this.visitExpression(instanceOf, p);
if (!expression?.kind || expression.kind !== J.Kind.InstanceOf) {
return expression;
}
instanceOf = expression as J.InstanceOf;
const updates: any = {
prefix: await this.visitSpace(instanceOf.prefix, p),
markers: await this.visitMarkers(instanceOf.markers, p),
expression: await this.visitRightPadded(instanceOf.expression, p),
class: await this.visitDefined(instanceOf.class, p) as J,
type: await this.visitType(instanceOf.type, p)
};
if (instanceOf.pattern) {
updates.pattern = await this.visitDefined(instanceOf.pattern, p) as J;
}
if (instanceOf.modifier) {
updates.modifier = await this.visitDefined(instanceOf.modifier, p) as J.Modifier;
}
return updateIfChanged(instanceOf, updates);
}
protected async visitIntersectionType(intersectionType: J.IntersectionType, p: P): Promise {
const expression = await this.visitExpression(intersectionType, p);
if (!expression?.kind || expression.kind !== J.Kind.IntersectionType) {
return expression;
}
intersectionType = expression as J.IntersectionType;
const updates: any = {
prefix: await this.visitSpace(intersectionType.prefix, p),
markers: await this.visitMarkers(intersectionType.markers, p),
bounds: await this.visitContainer(intersectionType.bounds, p)
};
return updateIfChanged(intersectionType, updates);
}
protected async visitLabel(label: J.Label, p: P): Promise {
const statement = await this.visitStatement(label, p);
if (!statement?.kind || statement.kind !== J.Kind.Label) {
return statement;
}
label = statement as J.Label;
const updates: any = {
prefix: await this.visitSpace(label.prefix, p),
markers: await this.visitMarkers(label.markers, p),
label: await this.visitRightPadded(label.label, p),
statement: await this.visitDefined(label.statement, p) as Statement
};
return updateIfChanged(label, updates);
}
protected async visitLambda(lambda: J.Lambda, p: P): Promise {
const expression = await this.visitExpression(lambda, p);
if (!expression?.kind || expression.kind !== J.Kind.Lambda) {
return expression;
}
lambda = expression as J.Lambda;
const statement = await this.visitStatement(lambda, p);
if (!statement?.kind || statement.kind !== J.Kind.Lambda) {
return statement;
}
lambda = statement as J.Lambda;
const updates: any = {
prefix: await this.visitSpace(lambda.prefix, p),
markers: await this.visitMarkers(lambda.markers, p),
parameters: await this.visitDefined(lambda.parameters, p) as J.Lambda.Parameters,
arrow: await this.visitSpace(lambda.arrow, p),
body: await this.visitDefined(lambda.body, p) as Statement | Expression,
type: await this.visitType(lambda.type, p)
};
return updateIfChanged(lambda, updates);
}
protected async visitLambdaParameters(params: J.Lambda.Parameters, p: P): Promise {
const updates: any = {
prefix: await this.visitSpace(params.prefix, p),
markers: await this.visitMarkers(params.markers, p),
parameters: await mapAsync(params.parameters, param => this.visitRightPadded(param, p))
};
return updateIfChanged(params, updates);
}
protected async visitLiteral(literal: J.Literal, p: P): Promise {
const expression = await this.visitExpression(literal, p);
if (!expression?.kind || expression.kind !== J.Kind.Literal) {
return expression;
}
literal = expression as J.Literal;
const updates: any = {
prefix: await this.visitSpace(literal.prefix, p),
markers: await this.visitMarkers(literal.markers, p),
type: await this.visitType(literal.type, p) as Type.Primitive | undefined
};
return updateIfChanged(literal, updates);
}
protected async visitMemberReference(memberRef: J.MemberReference, p: P): Promise {
const expression = await this.visitExpression(memberRef, p);
if (!expression?.kind || expression.kind !== J.Kind.MemberReference) {
return expression;
}
memberRef = expression as J.MemberReference;
const updates: any = {
prefix: await this.visitSpace(memberRef.prefix, p),
markers: await this.visitMarkers(memberRef.markers, p),
containing: await this.visitRightPadded(memberRef.containing, p),
typeParameters: await this.visitOptionalContainer(memberRef.typeParameters, p),
reference: await this.visitLeftPadded(memberRef.reference, p),
type: await this.visitType(memberRef.type, p),
methodType: await this.visitType(memberRef.methodType, p) as Type.Method | undefined,
variableType: await this.visitType(memberRef.variableType, p) as Type.Variable | undefined
};
return updateIfChanged(memberRef, updates);
}
protected async visitMethodDeclaration(method: J.MethodDeclaration, p: P): Promise {
const statement = await this.visitStatement(method, p);
if (!statement?.kind || statement.kind !== J.Kind.MethodDeclaration) {
return statement;
}
method = statement as J.MethodDeclaration;
const updates: any = {
prefix: await this.visitSpace(method.prefix, p),
markers: await this.visitMarkers(method.markers, p),
leadingAnnotations: await mapAsync(method.leadingAnnotations, a => this.visitDefined(a, p)),
modifiers: await mapAsync(method.modifiers, m => this.visitDefined(m, p)),
nameAnnotations: await mapAsync(method.nameAnnotations, a => this.visitDefined(a, p)),
name: await this.visitDefined(method.name, p),
parameters: await this.visitContainer(method.parameters, p),
dimensionsAfterName: await mapAsync(method.dimensionsAfterName ?? [], dim => this.visitLeftPadded(dim, p)),
throws: method.throws && await this.visitContainer(method.throws, p),
body: method.body && await this.visitDefined(method.body, p) as J.Block,
defaultValue: await this.visitOptionalLeftPadded(method.defaultValue, p),
methodType: await this.visitType(method.methodType, p) as Type.Method | undefined
};
if (method.typeParameters) {
updates.typeParameters = await this.visitDefined(method.typeParameters, p) as J.TypeParameters;
}
if (method.returnTypeExpression) {
updates.returnTypeExpression = await this.visitDefined(method.returnTypeExpression, p) as TypedTree;
}
return updateIfChanged(method, updates);
}
protected async visitMethodInvocation(method: J.MethodInvocation, p: P): Promise {
const expression = await this.visitExpression(method, p);
if (!expression?.kind || expression.kind !== J.Kind.MethodInvocation) {
return expression;
}
method = expression as J.MethodInvocation;
const statement = await this.visitStatement(method, p);
if (!statement?.kind || statement.kind !== J.Kind.MethodInvocation) {
return statement;
}
method = statement as J.MethodInvocation;
const updates: any = {
prefix: await this.visitSpace(method.prefix, p),
markers: await this.visitMarkers(method.markers, p),
select: await this.visitOptionalRightPadded(method.select, p),
typeParameters: await this.visitOptionalContainer(method.typeParameters, p),
name: await this.visitDefined(method.name, p) as J.Identifier,
arguments: await this.visitContainer(method.arguments, p),
methodType: await this.visitType(method.methodType, p) as Type.Method | undefined
};
return updateIfChanged(method, updates);
}
protected async visitModifier(modifier: J.Modifier, p: P): Promise {
const updates: any = {
prefix: await this.visitSpace(modifier.prefix, p),
markers: await this.visitMarkers(modifier.markers, p),
annotations: await mapAsync(modifier.annotations, a => this.visitDefined(a, p))
};
return updateIfChanged(modifier, updates);
}
protected async visitMultiCatch(multiCatch: J.MultiCatch, p: P): Promise {
const updates: any = {
prefix: await this.visitSpace(multiCatch.prefix, p),
markers: await this.visitMarkers(multiCatch.markers, p),
alternatives: await mapAsync(multiCatch.alternatives, alt => this.visitRightPadded(alt, p))
};
return updateIfChanged(multiCatch, updates);
}
protected async visitNewArray(newArray: J.NewArray, p: P): Promise {
const expression = await this.visitExpression(newArray, p);
if (!expression?.kind || expression.kind !== J.Kind.NewArray) {
return expression;
}
newArray = expression as J.NewArray;
const updates: any = {
prefix: await this.visitSpace(newArray.prefix, p),
markers: await this.visitMarkers(newArray.markers, p),
dimensions: await mapAsync(newArray.dimensions, dim => this.visitDefined(dim, p)),
initializer: await this.visitOptionalContainer(newArray.initializer, p),
type: await this.visitType(newArray.type, p)
};
if (newArray.typeExpression) {
updates.typeExpression = await this.visitDefined(newArray.typeExpression, p) as TypedTree;
}
return updateIfChanged(newArray, updates);
}
protected async visitNewClass(newClass: J.NewClass, p: P): Promise {
const expression = await this.visitExpression(newClass, p);
if (!expression?.kind || expression.kind !== J.Kind.NewClass) {
return expression;
}
newClass = expression as J.NewClass;
const updates: any = {
prefix: await this.visitSpace(newClass.prefix, p),
markers: await this.visitMarkers(newClass.markers, p),
new: await this.visitSpace(newClass.new, p),
arguments: await this.visitContainer(newClass.arguments, p),
constructorType: await this.visitType(newClass.constructorType, p) as Type.Method | undefined
};
if (newClass.enclosing) {
updates.enclosing = await this.visitRightPadded(newClass.enclosing, p);
}
if (newClass.class) {
updates.class = await this.visitDefined(newClass.class, p) as TypedTree;
}
if (newClass.body) {
updates.body = await this.visitDefined(newClass.body, p) as J.Block;
}
return updateIfChanged(newClass, updates);
}
protected async visitNullableType(nullableType: J.NullableType, p: P): Promise {
const expression = await this.visitExpression(nullableType, p);
if (!expression?.kind || expression.kind !== J.Kind.NullableType) {
return expression;
}
nullableType = expression as J.NullableType;
const updates: any = {
prefix: await this.visitSpace(nullableType.prefix, p),
markers: await this.visitMarkers(nullableType.markers, p),
annotations: await mapAsync(nullableType.annotations, a => this.visitDefined(a, p)),
typeTree: await this.visitRightPadded(nullableType.typeTree, p)
};
return updateIfChanged(nullableType, updates);
}
protected async visitPackage(aPackage: J.Package, p: P): Promise {
const updates: any = {
prefix: await this.visitSpace(aPackage.prefix, p),
markers: await this.visitMarkers(aPackage.markers, p),
expression: await this.visitDefined(aPackage.expression, p) as Expression
};
if (aPackage.annotations) {
updates.annotations = await mapAsync(aPackage.annotations, a => this.visitDefined(a, p));
}
return updateIfChanged(aPackage, updates);
}
protected async visitParameterizedType(parameterizedType: J.ParameterizedType, p: P): Promise {
const updates: any = {
prefix: await this.visitSpace(parameterizedType.prefix, p),
markers: await this.visitMarkers(parameterizedType.markers, p),
class: await this.visitTypeName(parameterizedType.class, p),
typeParameters: await this.visitOptionalContainer(parameterizedType.typeParameters, p),
type: await this.visitType(parameterizedType.type, p)
};
return updateIfChanged(parameterizedType, updates);
}
protected async visitParentheses(parentheses: J.Parentheses, p: P): Promise {
const updates: any = {
prefix: await this.visitSpace(parentheses.prefix, p),
markers: await this.visitMarkers(parentheses.markers, p),
tree: await this.visitRightPadded(parentheses.tree, p)
};
return updateIfChanged(parentheses, updates);
}
protected async visitParenthesizedTypeTree(parTypeTree: J.ParenthesizedTypeTree, p: P): Promise {
const expression = await this.visitExpression(parTypeTree, p);
if (!expression?.kind || expression.kind !== J.Kind.ParenthesizedTypeTree) {
return expression;
}
parTypeTree = expression as J.ParenthesizedTypeTree;
const updates: any = {
prefix: await this.visitSpace(parTypeTree.prefix, p),
markers: await this.visitMarkers(parTypeTree.markers, p),
annotations: await mapAsync(parTypeTree.annotations, a => this.visitDefined(a, p)),
parenthesizedType: await this.visitDefined(parTypeTree.parenthesizedType, p) as J.Parentheses
};
return updateIfChanged(parTypeTree, updates);
}
protected async visitPrimitive(primitive: J.Primitive, p: P): Promise {
const expression = await this.visitExpression(primitive, p);
if (!expression?.kind || expression.kind !== J.Kind.Primitive) {
return expression;
}
primitive = expression as J.Primitive;
const updates: any = {
prefix: await this.visitSpace(primitive.prefix, p),
markers: await this.visitMarkers(primitive.markers, p),
type: await this.visitType(primitive.type, p) as Type.Primitive
};
return updateIfChanged(primitive, updates);
}
protected async visitReturn(ret: J.Return, p: P): Promise {
const statement = await this.visitStatement(ret, p);
if (!statement?.kind || statement.kind !== J.Kind.Return) {
return statement;
}
ret = statement as J.Return;
const updates: any = {
prefix: await this.visitSpace(ret.prefix, p),
markers: await this.visitMarkers(ret.markers, p)
};
if (ret.expression) {
updates.expression = await this.visitDefined(ret.expression, p) as Expression;
}
return updateIfChanged(ret, updates);
}
protected async visitSwitch(aSwitch: J.Switch, p: P): Promise {
const statement = await this.visitStatement(aSwitch, p);
if (!statement?.kind || statement.kind !== J.Kind.Switch) {
return statement;
}
aSwitch = statement as J.Switch;
const updates: any = {
prefix: await this.visitSpace(aSwitch.prefix, p),
markers: await this.visitMarkers(aSwitch.markers, p),
selector: await this.visitDefined(aSwitch.selector, p) as J.ControlParentheses,
cases: await this.visitDefined(aSwitch.cases, p) as J.Block
};
return updateIfChanged(aSwitch, updates);
}
protected async visitSwitchExpression(switchExpr: J.SwitchExpression, p: P): Promise {
const expression = await this.visitExpression(switchExpr, p);
if (!expression?.kind || expression.kind !== J.Kind.SwitchExpression) {
return expression;
}
switchExpr = expression as J.SwitchExpression;
const updates: any = {
prefix: await this.visitSpace(switchExpr.prefix, p),
markers: await this.visitMarkers(switchExpr.markers, p),
selector: await this.visitDefined(switchExpr.selector, p) as J.ControlParentheses,
cases: await this.visitDefined(switchExpr.cases, p) as J.Block,
type: await this.visitType(switchExpr.type, p)
};
return updateIfChanged(switchExpr, updates);
}
protected async visitSynchronized(sync: J.Synchronized, p: P): Promise {
const statement = await this.visitStatement(sync, p);
if (!statement?.kind || statement.kind !== J.Kind.Synchronized) {
return statement;
}
sync = statement as J.Synchronized;
const updates: any = {
prefix: await this.visitSpace(sync.prefix, p),
markers: await this.visitMarkers(sync.markers, p),
lock: await this.visitDefined(sync.lock, p) as J.ControlParentheses,
body: await this.visitDefined(sync.body, p) as J.Block
};
return updateIfChanged(sync, updates);
}
protected async visitTernary(ternary: J.Ternary, p: P): Promise {
const expression = await this.visitExpression(ternary, p);
if (!expression?.kind || expression.kind !== J.Kind.Ternary) {
return expression;
}
ternary = expression as J.Ternary;
const statement = await this.visitStatement(ternary, p);
if (!statement?.kind || statement.kind !== J.Kind.Ternary) {
return statement;
}
ternary = statement as J.Ternary;
const updates: any = {
prefix: await this.visitSpace(ternary.prefix, p),
markers: await this.visitMarkers(ternary.markers, p),
condition: await this.visitDefined(ternary.condition, p) as Expression,
truePart: await this.visitLeftPadded(ternary.truePart, p),
falsePart: await this.visitLeftPadded(ternary.falsePart, p),
type: await this.visitType(ternary.type, p)
};
return updateIfChanged(ternary, updates);
}
protected async visitThrow(thrown: J.Throw, p: P): Promise {
const statement = await this.visitStatement(thrown, p);
if (!statement?.kind || statement.kind !== J.Kind.Throw) {
return statement;
}
thrown = statement as J.Throw;
const updates: any = {
prefix: await this.visitSpace(thrown.prefix, p),
markers: await this.visitMarkers(thrown.markers, p),
exception: await this.visitDefined(thrown.exception, p) as Expression
};
return updateIfChanged(thrown, updates);
}
protected async visitTry(tryable: J.Try, p: P): Promise {
const statement = await this.visitStatement(tryable, p);
if (!statement?.kind || statement.kind !== J.Kind.Try) {
return statement;
}
tryable = statement as J.Try;
const updates: any = {
prefix: await this.visitSpace(tryable.prefix, p),
markers: await this.visitMarkers(tryable.markers, p),
resources: await this.visitOptionalContainer(tryable.resources, p),
body: await this.visitDefined(tryable.body, p) as J.Block,
catches: await mapAsync(tryable.catches, c => this.visitDefined(c, p)),
finally: await this.visitOptionalLeftPadded(tryable.finally, p)
};
return updateIfChanged(tryable, updates);
}
protected async visitTryResource(resource: J.Try.Resource, p: P): Promise {
const updates: any = {
prefix: await this.visitSpace(resource.prefix, p),
markers: await this.visitMarkers(resource.markers, p),
variableDeclarations: await this.visitDefined(resource.variableDeclarations, p) as TypedTree
};
return updateIfChanged(resource, updates);
}
protected async visitTryCatch(tryCatch: J.Try.Catch, p: P): Promise {
const updates: any = {
prefix: await this.visitSpace(tryCatch.prefix, p),
markers: await this.visitMarkers(tryCatch.markers, p),
parameter: await this.visitDefined(tryCatch.parameter, p) as J.ControlParentheses,
body: await this.visitDefined(tryCatch.body, p) as J.Block
};
return updateIfChanged(tryCatch, updates);
}
protected async visitTypeCast(typeCast: J.TypeCast, p: P): Promise {
const expression = await this.visitExpression(typeCast, p);
if (!expression?.kind || expression.kind !== J.Kind.TypeCast) {
return expression;
}
typeCast = expression as J.TypeCast;
const updates: any = {
prefix: await this.visitSpace(typeCast.prefix, p),
markers: await this.visitMarkers(typeCast.markers, p),
class: await this.visitDefined(typeCast.class, p) as J.ControlParentheses,
expression: await this.visitDefined(typeCast.expression, p) as Expression
};
return updateIfChanged(typeCast, updates);
}
protected async visitTypeParameter(typeParam: J.TypeParameter, p: P): Promise {
const updates: any = {
prefix: await this.visitSpace(typeParam.prefix, p),
markers: await this.visitMarkers(typeParam.markers, p),
annotations: await mapAsync(typeParam.annotations, a => this.visitDefined(a, p)),
modifiers: await mapAsync(typeParam.modifiers, m => this.visitDefined(m, p)),
name: await this.visitDefined(typeParam.name, p) as J.Identifier,
bounds: await this.visitOptionalContainer(typeParam.bounds, p)
};
return updateIfChanged(typeParam, updates);
}
protected async visitTypeParameters(typeParams: J.TypeParameters, p: P): Promise {
const updates: any = {
prefix: await this.visitSpace(typeParams.prefix, p),
markers: await this.visitMarkers(typeParams.markers, p),
annotations: await mapAsync(typeParams.annotations, a => this.visitDefined(a, p)),
typeParameters: await mapAsync(typeParams.typeParameters, tp => this.visitRightPadded(tp, p))
};
return updateIfChanged(typeParams, updates);
}
protected async visitUnary(unary: J.Unary, p: P): Promise {
const expression = await this.visitExpression(unary, p);
if (!expression?.kind || expression.kind !== J.Kind.Unary) {
return expression;
}
unary = expression as J.Unary;
const statement = await this.visitStatement(unary, p);
if (!statement?.kind || statement.kind !== J.Kind.Unary) {
return statement;
}
unary = statement as J.Unary;
const updates: any = {
prefix: await this.visitSpace(unary.prefix, p),
markers: await this.visitMarkers(unary.markers, p),
operator: await this.visitLeftPadded(unary.operator, p),
expression: await this.visitDefined(unary.expression, p) as Expression,
type: await this.visitType(unary.type, p)
};
return updateIfChanged(unary, updates);
}
protected async visitUnknown(unknown: J.Unknown, p: P): Promise {
const expression = await this.visitExpression(unknown, p);
if (!expression?.kind || expression.kind !== J.Kind.Unknown) {
return expression;
}
unknown = expression as J.Unknown;
const statement = await this.visitStatement(unknown, p);
if (!statement?.kind || statement.kind !== J.Kind.Unknown) {
return statement;
}
unknown = statement as J.Unknown;
const updates: any = {
prefix: await this.visitSpace(unknown.prefix, p),
markers: await this.visitMarkers(unknown.markers, p),
source: await this.visitDefined(unknown.source, p) as J.UnknownSource
};
return updateIfChanged(unknown, updates);
}
protected async visitUnknownSource(source: J.UnknownSource, p: P): Promise {
const updates: any = {
prefix: await this.visitSpace(source.prefix, p),
markers: await this.visitMarkers(source.markers, p)
};
return updateIfChanged(source, updates);
}
protected async visitVariableDeclarations(varDecls: J.VariableDeclarations, p: P): Promise {
const statement = await this.visitStatement(varDecls, p);
if (!statement?.kind || statement.kind !== J.Kind.VariableDeclarations) {
return statement;
}
varDecls = statement as J.VariableDeclarations;
const updates: any = {
prefix: await this.visitSpace(varDecls.prefix, p),
markers: await this.visitMarkers(varDecls.markers, p),
leadingAnnotations: await mapAsync(varDecls.leadingAnnotations, a => this.visitDefined(a, p)),
modifiers: await mapAsync(varDecls.modifiers, m => this.visitDefined(m, p)),
variables: await mapAsync(varDecls.variables, v => this.visitRightPadded(v, p))
};
if (varDecls.typeExpression) {
updates.typeExpression = await this.visitDefined(varDecls.typeExpression, p) as TypedTree;
}
if (varDecls.varargs) {
updates.varargs = await this.visitSpace(varDecls.varargs, p);
}
return updateIfChanged(varDecls, updates);
}
protected async visitVariable(variable: J.VariableDeclarations.NamedVariable, p: P): Promise {
const updates: any = {
prefix: await this.visitSpace(variable.prefix, p),
markers: await this.visitMarkers(variable.markers, p),
name: await this.visitDefined(variable.name, p) as J.Identifier,
dimensionsAfterName: await mapAsync(variable.dimensionsAfterName, dim => this.visitLeftPadded(dim, p)),
initializer: await this.visitOptionalLeftPadded(variable.initializer, p),
variableType: await this.visitType(variable.variableType, p) as Type.Variable | undefined
};
return updateIfChanged(variable, updates);
}
protected async visitWhileLoop(whileLoop: J.WhileLoop, p: P): Promise {
const statement = await this.visitStatement(whileLoop, p);
if (!statement?.kind || statement.kind !== J.Kind.WhileLoop) {
return statement;
}
whileLoop = statement as J.WhileLoop;
const updates: any = {
prefix: await this.visitSpace(whileLoop.prefix, p),
markers: await this.visitMarkers(whileLoop.markers, p),
condition: await this.visitDefined(whileLoop.condition, p) as J.ControlParentheses,
body: await this.visitRightPadded(whileLoop.body, p)
};
return updateIfChanged(whileLoop, updates);
}
protected async visitWildcard(wildcard: J.Wildcard, p: P): Promise {
const expression = await this.visitExpression(wildcard, p);
if (!expression?.kind || expression.kind !== J.Kind.Wildcard) {
return expression;
}
wildcard = expression as J.Wildcard;
const updates: any = {
prefix: await this.visitSpace(wildcard.prefix, p),
markers: await this.visitMarkers(wildcard.markers, p),
bound: await this.visitOptionalLeftPadded(wildcard.bound, p)
};
if (wildcard.boundedType) {
updates.boundedType = await this.visitTypeName(wildcard.boundedType, p);
}
return updateIfChanged(wildcard, updates);
}
protected async visitYield(aYield: J.Yield, p: P): Promise {
const statement = await this.visitStatement(aYield, p);
if (!statement?.kind || statement.kind !== J.Kind.Yield) {
return statement;
}
aYield = statement as J.Yield;
const updates: any = {
prefix: await this.visitSpace(aYield.prefix, p),
markers: await this.visitMarkers(aYield.markers, p),
value: await this.visitDefined(aYield.value, p) as Expression
};
return updateIfChanged(aYield, updates);
}
protected async visitOptionalRightPadded(right: J.RightPadded | undefined, p: P): Promise | undefined> {
return right ? this.visitRightPadded(right, p) : undefined;
}
public async visitRightPadded(right: J.RightPadded, p: P): Promise | undefined> {
this.cursor = new Cursor(right, this.cursor);
const element = isTree(right.element) ? await this.visitDefined(right.element, p) as T : right.element;
const after = await this.visitSpace(right.after, p);
const markers = await this.visitMarkers(right.markers, p);
this.cursor = this.cursor.parent!;
if (element === undefined) {
return undefined;
}
return updateIfChanged(right, {element, after, markers});
}
protected async visitOptionalLeftPadded(left: J.LeftPadded | undefined, p: P): Promise | undefined> {
return left ? this.visitLeftPadded(left, p) : undefined;
}
public async visitLeftPadded(left: J.LeftPadded, p: P): Promise | undefined> {
this.cursor = new Cursor(left, this.cursor);
const before = await this.visitSpace(left.before, p);
let element: T | undefined = left.element;
if (isTree(left.element)) {
element = await this.visitDefined(left.element, p) as T | undefined;
} else if (isSpace(left.element)) {
element = await this.visitSpace(left.element, p) as T;
}
const markers = await this.visitMarkers(left.markers, p);
this.cursor = this.cursor.parent!;
if (element === undefined) {
return undefined;
}
return updateIfChanged(left, {before, element, markers});
}
protected async visitOptionalContainer(container: J.Container | undefined, p: P): Promise | undefined> {
return container ? this.visitContainer(container, p) : undefined;
}
public async visitContainer(container: J.Container, p: P): Promise> {
this.cursor = new Cursor(container, this.cursor);
const before = await this.visitSpace(container.before, p);
const elements = await mapAsync(container.elements, e => this.visitRightPadded(e, p));
const markers = await this.visitMarkers(container.markers, p);
this.cursor = this.cursor.parent!;
return updateIfChanged(container, {before, elements, markers});
}
protected async produceJava(
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 accept(t: J, p: P): Promise {
switch (t.kind) {
case J.Kind.AnnotatedType:
return this.visitAnnotatedType(t as J.AnnotatedType, p);
case J.Kind.Annotation:
return this.visitAnnotation(t as J.Annotation, p);
case J.Kind.ArrayAccess:
return this.visitArrayAccess(t as J.ArrayAccess, p);
case J.Kind.ArrayDimension:
return this.visitArrayDimension(t as J.ArrayDimension, p);
case J.Kind.ArrayType:
return this.visitArrayType(t as J.ArrayType, p);
case J.Kind.Assert:
return this.visitAssert(t as J.Assert, p);
case J.Kind.Assignment:
return this.visitAssignment(t as J.Assignment, p);
case J.Kind.AssignmentOperation:
return this.visitAssignmentOperation(t as J.AssignmentOperation, p);
case J.Kind.Binary:
return this.visitBinary(t as J.Binary, p);
case J.Kind.Block:
return this.visitBlock(t as J.Block, p);
case J.Kind.Break:
return this.visitBreak(t as J.Break, p);
case J.Kind.Case:
return this.visitCase(t as J.Case, p);
case J.Kind.ClassDeclaration:
return this.visitClassDeclaration(t as J.ClassDeclaration, p);
case J.Kind.ClassDeclarationKind:
return this.visitClassDeclarationKind(t as J.ClassDeclaration.Kind, p);
case J.Kind.CompilationUnit:
return this.visitCompilationUnit(t as J.CompilationUnit, p);
case J.Kind.Continue:
return this.visitContinue(t as J.Continue, p);
case J.Kind.ControlParentheses:
return this.visitControlParentheses(t as J.ControlParentheses, p);
case J.Kind.DeconstructionPattern:
return this.visitDeconstructionPattern(t as J.DeconstructionPattern, p);
case J.Kind.DoWhileLoop:
return this.visitDoWhileLoop(t as J.DoWhileLoop, p);
case J.Kind.Empty:
return this.visitEmpty(t as J.Empty, p);
case J.Kind.EnumValue:
return this.visitEnumValue(t as J.EnumValue, p);
case J.Kind.EnumValueSet:
return this.visitEnumValueSet(t as J.EnumValueSet, p);
case J.Kind.Erroneous:
return this.visitErroneous(t as J.Erroneous, p);
case J.Kind.FieldAccess:
return this.visitFieldAccess(t as J.FieldAccess, p);
case J.Kind.ForEachLoop:
return this.visitForEachLoop(t as J.ForEachLoop, p);
case J.Kind.ForEachLoopControl:
return this.visitForEachLoopControl(t as J.ForEachLoop.Control, p);
case J.Kind.ForLoop:
return this.visitForLoop(t as J.ForLoop, p);
case J.Kind.ForLoopControl:
return this.visitForLoopControl(t as J.ForLoop.Control, p);
case J.Kind.Identifier:
return this.visitIdentifier(t as J.Identifier, p);
case J.Kind.If:
return this.visitIf(t as J.If, p);
case J.Kind.IfElse:
return this.visitElse(t as J.If.Else, p);
case J.Kind.Import:
return this.visitImport(t as J.Import, p);
case J.Kind.InstanceOf:
return this.visitInstanceOf(t as J.InstanceOf, p);
case J.Kind.IntersectionType:
return this.visitIntersectionType(t as J.IntersectionType, p);
case J.Kind.Label:
return this.visitLabel(t as J.Label, p);
case J.Kind.Lambda:
return this.visitLambda(t as J.Lambda, p);
case J.Kind.LambdaParameters:
return this.visitLambdaParameters(t as J.Lambda.Parameters, p);
case J.Kind.Literal:
return this.visitLiteral(t as J.Literal, p);
case J.Kind.MemberReference:
return this.visitMemberReference(t as J.MemberReference, p);
case J.Kind.MethodDeclaration:
return this.visitMethodDeclaration(t as J.MethodDeclaration, p);
case J.Kind.MethodInvocation:
return this.visitMethodInvocation(t as J.MethodInvocation, p);
case J.Kind.Modifier:
return this.visitModifier(t as J.Modifier, p);
case J.Kind.MultiCatch:
return this.visitMultiCatch(t as J.MultiCatch, p);
case J.Kind.NewArray:
return this.visitNewArray(t as J.NewArray, p);
case J.Kind.NewClass:
return this.visitNewClass(t as J.NewClass, p);
case J.Kind.NullableType:
return this.visitNullableType(t as J.NullableType, p);
case J.Kind.Package:
return this.visitPackage(t as J.Package, p);
case J.Kind.ParameterizedType:
return this.visitParameterizedType(t as J.ParameterizedType, p);
case J.Kind.Parentheses:
return this.visitParentheses(t as J.Parentheses, p);
case J.Kind.ParenthesizedTypeTree:
return this.visitParenthesizedTypeTree(t as J.ParenthesizedTypeTree, p);
case J.Kind.Primitive:
return this.visitPrimitive(t as J.Primitive, p);
case J.Kind.Return:
return this.visitReturn(t as J.Return, p);
case J.Kind.Switch:
return this.visitSwitch(t as J.Switch, p);
case J.Kind.SwitchExpression:
return this.visitSwitchExpression(t as J.SwitchExpression, p);
case J.Kind.Synchronized:
return this.visitSynchronized(t as J.Synchronized, p);
case J.Kind.Ternary:
return this.visitTernary(t as J.Ternary, p);
case J.Kind.Throw:
return this.visitThrow(t as J.Throw, p);
case J.Kind.Try:
return this.visitTry(t as J.Try, p);
case J.Kind.TryResource:
return this.visitTryResource(t as J.Try.Resource, p);
case J.Kind.TryCatch:
return this.visitTryCatch(t as J.Try.Catch, p);
case J.Kind.TypeCast:
return this.visitTypeCast(t as J.TypeCast, p);
case J.Kind.TypeParameter:
return this.visitTypeParameter(t as J.TypeParameter, p);
case J.Kind.TypeParameters:
return this.visitTypeParameters(t as J.TypeParameters, p);
case J.Kind.Unary:
return this.visitUnary(t as J.Unary, p);
case J.Kind.Unknown:
return this.visitUnknown(t as J.Unknown, p);
case J.Kind.UnknownSource:
return this.visitUnknownSource(t as J.UnknownSource, p);
case J.Kind.VariableDeclarations:
return this.visitVariableDeclarations(t as J.VariableDeclarations, p);
case J.Kind.NamedVariable:
return this.visitVariable(t as J.VariableDeclarations.NamedVariable, p);
case J.Kind.WhileLoop:
return this.visitWhileLoop(t as J.WhileLoop, p);
case J.Kind.Wildcard:
return this.visitWildcard(t as J.Wildcard, p);
case J.Kind.Yield:
return this.visitYield(t as J.Yield, p);
default:
const adapter = extendedJavaKinds.get(t.kind)
if (adapter) {
return adapter(this).visit(t, p);
}
return Promise.resolve(t);
}
}
}