/*
* 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 {JavaVisitor} from "./visitor";
import {asRef, RpcCodecs, RpcReceiveQueue, RpcSendQueue} from "../rpc";
import {Expression, isSpace, J, TextComment} from "./tree";
import {isTree} from "../tree";
import {Type} from "./type";
import {TypeVisitor} from "./type-visitor";
import {updateIfChanged} from "../util";
import Space = J.Space;
class TypeSender extends TypeVisitor {
protected async visitPrimitive(primitive: Type.Primitive, q: RpcSendQueue): Promise {
await q.getAndSend(primitive, p => p.keyword);
return primitive;
}
protected async visitClass(cls: Type.Class, q: RpcSendQueue): Promise {
await q.getAndSend(cls, c => c.flags);
await q.getAndSend(cls, c => c.classKind);
await q.getAndSend(cls, c => c.fullyQualifiedName);
await q.getAndSendList(cls, c => (c.typeParameters || []).map(t => asRef(t)), t => Type.signature(t), t => this.visit(t, q));
await q.getAndSend(cls, c => asRef(c.supertype), st => this.visit(st, q));
await q.getAndSend(cls, c => asRef(c.owningClass), oc => this.visit(oc, q));
await q.getAndSendList(cls, c => (c.annotations || []).map(a => asRef(a)), t => Type.signature(t), a => this.visit(a, q));
await q.getAndSendList(cls, c => (c.interfaces || []).map(i => asRef(i)), t => Type.signature(t), i => this.visit(i, q));
await q.getAndSendList(cls, c => (c.members || []).map(m => asRef(m)), t => Type.signature(t), m => this.visit(m, q));
await q.getAndSendList(cls, c => (c.methods || []).map(m => asRef(m)), t => Type.signature(t), m => this.visit(m, q));
return cls;
}
protected async visitVariable(variable: Type.Variable, q: RpcSendQueue): Promise {
await q.getAndSend(variable, v => v.name);
await q.getAndSend(variable, v => v.owner ? asRef(v.owner) : undefined, owner => this.visit(owner, q));
await q.getAndSend(variable, v => asRef(v.type), t => this.visit(t, q));
await q.getAndSendList(variable, v => (v.annotations || []).map(v2 => asRef(v2)), t => Type.signature(t), a => this.visit(a, q));
return variable;
}
protected async visitAnnotation(annotation: Type.Annotation, q: RpcSendQueue): Promise {
await q.getAndSend(annotation, a => asRef(a.type), t => this.visit(t, q));
await q.getAndSendList(
annotation,
a => (a.values || []).map(v => asRef(v)),
v => Type.signature(v.element),
async v => {
await q.getAndSend(v, e => asRef(e.element), elem => this.visit(elem, q));
if (v.kind === Type.Kind.ArrayElementValue) {
const array = v as Type.Annotation.ArrayElementValue;
// constantValues are sent as raw JSON-native values; numeric subtypes
// (int/long/float/double) and char/string distinctions are not preserved.
await q.getAndSendList(
array,
a => a.constantValues,
v => v == null ? "null" : v.toString(),
);
await q.getAndSendList(
array,
a => (a.referenceValues || []).map(r => asRef(r)),
t => Type.signature(t),
t => this.visit(t, q),
);
} else {
const single = v as Type.Annotation.SingleElementValue;
await q.getAndSend(single, s => s.constantValue);
await q.getAndSend(single, s => asRef(s.referenceValue), ref => this.visit(ref, q));
}
},
);
return annotation;
}
protected async visitMethod(method: Type.Method, q: RpcSendQueue): Promise {
await q.getAndSend(method, m => asRef(m.declaringType), dt => this.visit(dt, q));
await q.getAndSend(method, m => m.name);
await q.getAndSend(method, m => m.flags);
await q.getAndSend(method, m => asRef(m.returnType), rt => this.visit(rt, q));
await q.getAndSendList(method, m => m.parameterNames || [], v => v);
await q.getAndSendList(method, m => (m.parameterTypes || []).map(t => asRef(t)), t => Type.signature(t), pt => this.visit(pt, q));
await q.getAndSendList(method, m => (m.thrownExceptions || []).map(t => asRef(t)), t => Type.signature(t), et => this.visit(et, q));
await q.getAndSendList(method, m => (m.annotations || []).map(a => asRef(a)), t => Type.signature(t), a => this.visit(a, q));
await q.getAndSendList(method, m => m.defaultValue || undefined, v => v);
await q.getAndSendList(method, m => m.declaredFormalTypeNames || [], v => v);
return method;
}
protected async visitArray(array: Type.Array, q: RpcSendQueue): Promise {
await q.getAndSend(array, a => asRef(a.elemType), et => this.visit(et, q));
await q.getAndSendList(array, a => (a.annotations || []).map(ann => asRef(ann)), t => Type.signature(t), ann => this.visit(ann, q));
return array;
}
protected async visitParameterized(parameterized: Type.Parameterized, q: RpcSendQueue): Promise {
await q.getAndSend(parameterized, p => asRef(p.type), t => this.visit(t, q));
await q.getAndSendList(parameterized, p => (p.typeParameters || []).map(tp => asRef(tp)), t => Type.signature(t), tp => this.visit(tp, q));
return parameterized;
}
protected async visitGenericTypeVariable(generic: Type.GenericTypeVariable, q: RpcSendQueue): Promise {
await q.getAndSend(generic, g => g.name);
// Convert TypeScript enum to Java enum string
await q.getAndSend(generic, g => {
switch (g.variance) {
case Type.GenericTypeVariable.Variance.Covariant:
return 'COVARIANT';
case Type.GenericTypeVariable.Variance.Contravariant:
return 'CONTRAVARIANT';
case Type.GenericTypeVariable.Variance.Invariant:
default:
return 'INVARIANT';
}
});
await q.getAndSendList(generic, g => (g.bounds || []).map(b => asRef(b)), t => Type.signature(t), b => this.visit(b, q));
return generic;
}
protected async visitUnion(union: Type.Union, q: RpcSendQueue): Promise {
await q.getAndSendList(union, u => (u.bounds || []).map(b => asRef(b)), t => Type.signature(t), b => this.visit(b, q));
return union;
}
protected async visitIntersection(intersection: Type.Intersection, q: RpcSendQueue): Promise {
await q.getAndSendList(intersection, i => (i.bounds || []).map(b => asRef(b)), t => Type.signature(t), b => this.visit(b, q));
return intersection;
}
}
class TypeReceiver extends TypeVisitor {
async preVisit(_type: Type, _q: RpcReceiveQueue): Promise {
// Don't call default preVisit to avoid circular references
return _type;
}
async postVisit(_type: Type, _q: RpcReceiveQueue): Promise {
// Don't call default postVisit to avoid circular references
return _type;
}
protected async visitPrimitive(primitive: Type.Primitive, q: RpcReceiveQueue): Promise {
const keyword: string = await q.receive(primitive.keyword);
return Type.Primitive.fromKeyword(keyword)!;
}
protected async visitClass(cls: Type.Class, q: RpcReceiveQueue): Promise {
cls.flags = await q.receive(cls.flags);
cls.classKind = await q.receive(cls.classKind);
cls.fullyQualifiedName = await q.receive(cls.fullyQualifiedName);
cls.typeParameters = await q.receiveList(cls.typeParameters, tp => this.visit(tp, q)) || [];
cls.supertype = await q.receive(cls.supertype, st => this.visit(st, q));
cls.owningClass = await q.receive(cls.owningClass, oc => this.visit(oc, q));
cls.annotations = await q.receiveList(cls.annotations, a => this.visit(a, q)) || [];
cls.interfaces = await q.receiveList(cls.interfaces, i => this.visit(i, q)) || [];
cls.members = await q.receiveList(cls.members, m => this.visit(m, q)) || [];
cls.methods = await q.receiveList(cls.methods, m => this.visit(m, q)) || [];
return cls;
}
protected async visitVariable(variable: Type.Variable, q: RpcReceiveQueue): Promise {
variable.name = await q.receive(variable.name);
variable.owner = await q.receive(variable.owner, owner => this.visit(owner, q));
variable.type = await q.receive(variable.type, t => this.visit(t, q));
variable.annotations = await q.receiveList(variable.annotations, a => this.visit(a, q)) || [];
return variable;
}
protected async visitAnnotation(annotation: Type.Annotation, q: RpcReceiveQueue): Promise {
annotation.type = await q.receive(annotation.type, t => this.visit(t, q));
annotation.values = (await q.receiveList(annotation.values, async v => {
const element = await q.receive((v as Type.Annotation.ElementValue).element, elem => this.visit(elem, q));
if (v.kind === Type.Kind.ArrayElementValue) {
const array = v as Type.Annotation.ArrayElementValue;
const constantValues = await q.receiveList(array.constantValues);
const referenceValues = await q.receiveList(array.referenceValues, r => this.visit(r, q));
return {
kind: Type.Kind.ArrayElementValue,
element,
constantValues,
referenceValues,
} as Type.Annotation.ArrayElementValue;
}
const single = v as Type.Annotation.SingleElementValue;
const constantValue = await q.receive(single.constantValue);
const referenceValue = await q.receive(single.referenceValue, ref => this.visit(ref, q));
return {
kind: Type.Kind.SingleElementValue,
element,
constantValue,
referenceValue,
} as Type.Annotation.SingleElementValue;
})) || [];
return annotation;
}
protected async visitMethod(method: Type.Method, q: RpcReceiveQueue): Promise {
method.declaringType = await q.receive(method.declaringType, dt => this.visit(dt, q));
method.name = await q.receive(method.name);
method.flags = await q.receive(method.flags);
method.returnType = await q.receive(method.returnType, rt => this.visit(rt, q));
method.parameterNames = await q.receiveList(method.parameterNames) || [];
method.parameterTypes = await q.receiveList(method.parameterTypes, pt => this.visit(pt, q)) || [];
method.thrownExceptions = await q.receiveList(method.thrownExceptions, et => this.visit(et, q)) || [];
method.annotations = await q.receiveList(method.annotations, a => this.visit(a, q)) || [];
method.defaultValue = await q.receiveList(method.defaultValue);
method.declaredFormalTypeNames = await q.receiveList(method.declaredFormalTypeNames) || [];
return method;
}
protected async visitArray(array: Type.Array, q: RpcReceiveQueue): Promise {
array.elemType = await q.receive(array.elemType, et => this.visit(et, q));
array.annotations = await q.receiveList(array.annotations, ann => this.visit(ann, q)) || [];
return array;
}
protected async visitParameterized(parameterized: Type.Parameterized, q: RpcReceiveQueue): Promise {
parameterized.type = await q.receive(parameterized.type, t => this.visit(t, q));
parameterized.typeParameters = await q.receiveList(parameterized.typeParameters, tp => this.visit(tp, q)) || [];
return parameterized;
}
protected async visitGenericTypeVariable(generic: Type.GenericTypeVariable, q: RpcReceiveQueue): Promise {
generic.name = await q.receive(generic.name);
const varianceStr = await q.receive(generic.variance) as any as string;
// Convert Java enum string to TypeScript enum
switch (varianceStr) {
case 'COVARIANT':
generic.variance = Type.GenericTypeVariable.Variance.Covariant;
break;
case 'CONTRAVARIANT':
generic.variance = Type.GenericTypeVariable.Variance.Contravariant;
break;
case 'INVARIANT':
default:
generic.variance = Type.GenericTypeVariable.Variance.Invariant;
break;
}
generic.bounds = await q.receiveList(generic.bounds, b => this.visit(b, q)) || [];
return generic;
}
protected async visitUnion(union: Type.Union, q: RpcReceiveQueue): Promise {
union.bounds = await q.receiveList(union.bounds, b => this.visit(b, q)) || [];
return union;
}
protected async visitIntersection(intersection: Type.Intersection, q: RpcReceiveQueue): Promise {
intersection.bounds = await q.receiveList(intersection.bounds, b => this.visit(b, q)) || [];
return intersection;
}
}
export class JavaSender extends JavaVisitor {
protected async preVisit(j: J, q: RpcSendQueue): Promise {
await q.getAndSend(j, j2 => j2.id);
await q.getAndSend(j, j2 => j2.prefix, space => this.visitSpace(space, q));
await q.getAndSend(j, j2 => j2.markers);
return j;
}
protected async visitAnnotatedType(annotatedType: J.AnnotatedType, q: RpcSendQueue): Promise {
await q.getAndSendList(annotatedType, a => a.annotations, annot => annot.id, annot => this.visit(annot, q));
await q.getAndSend(annotatedType, a => a.typeExpression, type => this.visit(type, q));
return annotatedType;
}
protected async visitAnnotation(annotation: J.Annotation, q: RpcSendQueue): Promise {
await q.getAndSend(annotation, a => a.annotationType, type => this.visit(type, q));
await q.getAndSend(annotation, a => a.arguments, args => this.visitContainer(args, q));
return annotation;
}
protected async visitArrayAccess(arrayAccess: J.ArrayAccess, q: RpcSendQueue): Promise {
await q.getAndSend(arrayAccess, a => a.indexed, indexed => this.visit(indexed, q));
await q.getAndSend(arrayAccess, a => a.dimension, dim => this.visit(dim, q));
return arrayAccess;
}
protected async visitArrayDimension(dimension: J.ArrayDimension, q: RpcSendQueue): Promise {
await q.getAndSend(dimension, d => d.index, idx => this.visitRightPadded(idx, q));
return dimension;
}
protected async visitArrayType(arrayType: J.ArrayType, q: RpcSendQueue): Promise {
await q.getAndSend(arrayType, a => a.elementType, type => this.visit(type, q));
await q.getAndSendList(arrayType, a => a.annotations || [], annot => annot.id, annot => this.visit(annot, q));
await q.getAndSend(arrayType, a => a.dimension, d => this.visitLeftPadded(d, q));
await q.getAndSend(arrayType, a => asRef(a.type), type => this.visitType(type, q));
return arrayType;
}
protected async visitAssert(assert: J.Assert, q: RpcSendQueue): Promise {
await q.getAndSend(assert, a => a.condition, cond => this.visit(cond, q));
await q.getAndSend(assert, a => a.detail, detail => this.visitLeftPadded(detail, q));
return assert;
}
protected async visitAssignment(assignment: J.Assignment, q: RpcSendQueue): Promise {
await q.getAndSend(assignment, a => a.variable, variable => this.visit(variable, q));
await q.getAndSend(assignment, a => a.assignment, assign => this.visitLeftPadded(assign, q));
await q.getAndSend(assignment, a => asRef(a.type), type => this.visitType(type, q));
return assignment;
}
protected async visitAssignmentOperation(assignOp: J.AssignmentOperation, q: RpcSendQueue): Promise {
await q.getAndSend(assignOp, a => a.variable, variable => this.visit(variable, q));
await q.getAndSend(assignOp, a => a.operator, op => this.visitLeftPadded(op, q));
await q.getAndSend(assignOp, a => a.assignment, assign => this.visit(assign, q));
await q.getAndSend(assignOp, a => asRef(a.type), type => this.visitType(type, q));
return assignOp;
}
protected async visitBinary(binary: J.Binary, q: RpcSendQueue): Promise {
await q.getAndSend(binary, b => b.left, left => this.visit(left, q));
await q.getAndSend(binary, b => b.operator, op => this.visitLeftPadded(op, q));
await q.getAndSend(binary, b => b.right, right => this.visit(right, q));
await q.getAndSend(binary, a => asRef(a.type), type => this.visitType(type, q));
return binary;
}
protected async visitBreak(breakStmt: J.Break, q: RpcSendQueue): Promise {
await q.getAndSend(breakStmt, b => b.label, label => this.visit(label, q));
return breakStmt;
}
protected async visitCase(caseStmt: J.Case, q: RpcSendQueue): Promise {
await q.getAndSend(caseStmt, c => c.type);
await q.getAndSend(caseStmt, c => c.caseLabels, labels => this.visitContainer(labels, q));
await q.getAndSend(caseStmt, c => c.statements, stmts => this.visitContainer(stmts, q));
await q.getAndSend(caseStmt, c => c.body, body => this.visitRightPadded(body, q));
await q.getAndSend(caseStmt, c => c.guard, guard => this.visit(guard, q));
return caseStmt;
}
protected async visitContinue(continueStmt: J.Continue, q: RpcSendQueue): Promise {
await q.getAndSend(continueStmt, c => c.label, label => this.visit(label, q));
return continueStmt;
}
protected async visitControlParentheses(controlParens: J.ControlParentheses, q: RpcSendQueue): Promise {
await q.getAndSend(controlParens, c => c.tree, tree => this.visitRightPadded(tree, q));
return controlParens;
}
protected async visitDeconstructionPattern(pattern: J.DeconstructionPattern, q: RpcSendQueue): Promise {
await q.getAndSend(pattern, p => p.deconstructor, deconstructor => this.visit(deconstructor, q));
await q.getAndSend(pattern, p => p.nested, nested => this.visitContainer(nested, q));
await q.getAndSend(pattern, p => asRef(p.type), type => this.visitType(type, q));
return pattern;
}
protected async visitDoWhileLoop(doWhile: J.DoWhileLoop, q: RpcSendQueue): Promise {
await q.getAndSend(doWhile, d => d.body, body => this.visitRightPadded(body, q));
await q.getAndSend(doWhile, d => d.whileCondition, cond => this.visitLeftPadded(cond, q));
return doWhile;
}
protected async visitEmpty(empty: J.Empty, _q: RpcSendQueue): Promise {
// No additional properties to send
return empty;
}
protected async visitEnumValueSet(enumValueSet: J.EnumValueSet, q: RpcSendQueue): Promise {
await q.getAndSendList(enumValueSet, e => e.enums, enumValue => enumValue.element.id, enumValue => this.visitRightPadded(enumValue, q));
await q.getAndSend(enumValueSet, e => e.terminatedWithSemicolon);
return enumValueSet;
}
protected async visitEnumValue(enumValue: J.EnumValue, q: RpcSendQueue): Promise {
await q.getAndSendList(enumValue, e => e.annotations, annot => annot.id, annot => this.visit(annot, q));
await q.getAndSend(enumValue, e => e.name, name => this.visit(name, q));
await q.getAndSend(enumValue, e => e.initializer, init => this.visit(init, q));
return enumValue;
}
protected async visitErroneous(erroneous: J.Erroneous, q: RpcSendQueue): Promise {
await q.getAndSend(erroneous, e => e.text);
return erroneous;
}
protected async visitFieldAccess(fieldAccess: J.FieldAccess, q: RpcSendQueue): Promise {
await q.getAndSend(fieldAccess, f => f.target, target => this.visit(target, q));
await q.getAndSend(fieldAccess, f => f.name, name => this.visitLeftPadded(name, q));
await q.getAndSend(fieldAccess, a => asRef(a.type), type => this.visitType(type, q));
return fieldAccess;
}
protected async visitForEachLoop(forEach: J.ForEachLoop, q: RpcSendQueue): Promise {
await q.getAndSend(forEach, f => f.control, control => this.visit(control, q));
await q.getAndSend(forEach, f => f.body, body => this.visitRightPadded(body, q));
return forEach;
}
protected async visitForEachLoopControl(control: J.ForEachLoop.Control, q: RpcSendQueue): Promise {
await q.getAndSend(control, c => c.variable, variable => this.visitRightPadded(variable, q));
await q.getAndSend(control, c => c.iterable, iterable => this.visitRightPadded(iterable, q));
return control;
}
protected async visitForLoop(forLoop: J.ForLoop, q: RpcSendQueue): Promise {
await q.getAndSend(forLoop, f => f.control, control => this.visit(control, q));
await q.getAndSend(forLoop, f => f.body, body => this.visitRightPadded(body, q));
return forLoop;
}
protected async visitForLoopControl(control: J.ForLoop.Control, q: RpcSendQueue): Promise {
await q.getAndSendList(control, c => c.init, i => i.element.id, i => this.visitRightPadded(i, q));
await q.getAndSend(control, c => c.condition, c => this.visitRightPadded(c, q));
await q.getAndSendList(control, c => c.update, u => u.element.id, u => this.visitRightPadded(u, q));
return control;
}
protected async visitIf(ifStmt: J.If, q: RpcSendQueue): Promise {
await q.getAndSend(ifStmt, i => i.ifCondition, cond => this.visit(cond, q));
await q.getAndSend(ifStmt, i => i.thenPart, then => this.visitRightPadded(then, q));
await q.getAndSend(ifStmt, i => i.elsePart, elsePart => this.visit(elsePart, q));
return ifStmt;
}
protected async visitElse(ifElse: J.If.Else, q: RpcSendQueue): Promise {
await q.getAndSend(ifElse, e => e.body, body => this.visitRightPadded(body, q));
return ifElse;
}
protected async visitImport(importStmt: J.Import, q: RpcSendQueue): Promise {
await q.getAndSend(importStmt, i => i.static, static_ => this.visitLeftPadded(static_, q));
await q.getAndSend(importStmt, i => i.qualid, qualid => this.visit(qualid, q));
await q.getAndSend(importStmt, i => i.alias, alias => this.visitLeftPadded(alias, q));
return importStmt;
}
protected async visitInstanceOf(instanceOf: J.InstanceOf, q: RpcSendQueue): Promise {
await q.getAndSend(instanceOf, i => i.expression, expr => this.visitRightPadded(expr, q));
await q.getAndSend(instanceOf, i => i.class, clazz => this.visit(clazz, q));
await q.getAndSend(instanceOf, i => i.pattern, pattern => this.visit(pattern, q));
await q.getAndSend(instanceOf, i => asRef(i.type), type => this.visitType(type, q));
await q.getAndSend(instanceOf, i => i.modifier, modifier => this.visit(modifier, q));
return instanceOf;
}
protected async visitIntersectionType(intersectionType: J.IntersectionType, q: RpcSendQueue): Promise {
await q.getAndSend(intersectionType, i => i.bounds, bounds => this.visitContainer(bounds, q));
return intersectionType;
}
protected async visitLabel(label: J.Label, q: RpcSendQueue): Promise {
await q.getAndSend(label, l => l.label, id => this.visitRightPadded(id, q));
await q.getAndSend(label, l => l.statement, stmt => this.visit(stmt, q));
return label;
}
protected async visitLambda(lambda: J.Lambda, q: RpcSendQueue): Promise {
await q.getAndSend(lambda, l => l.parameters, params => this.visit(params, q));
await q.getAndSend(lambda, l => l.arrow, arrow => this.visitSpace(arrow, q));
await q.getAndSend(lambda, l => l.body, body => this.visit(body, q));
await q.getAndSend(lambda, l => asRef(l.type), type => this.visitType(type, q));
return lambda;
}
protected async visitLambdaParameters(params: J.Lambda.Parameters, q: RpcSendQueue): Promise {
await q.getAndSend(params, p => p.parenthesized);
await q.getAndSendList(params, p => p.parameters, param => param.element.id, param => this.visitRightPadded(param, q));
return params;
}
protected async visitLiteral(literal: J.Literal, q: RpcSendQueue): Promise {
await q.getAndSend(literal, l => l.value);
await q.getAndSend(literal, l => l.valueSource);
await q.getAndSendList(literal, l => l.unicodeEscapes, e => e.valueSourceIndex + e.codePoint, async (e) => {
await q.getAndSend(e, u => u.valueSourceIndex);
await q.getAndSend(e, u => u.codePoint);
});
await q.getAndSend(literal, l => asRef(l.type), type => this.visitType(type, q));
return literal;
}
protected async visitMemberReference(memberRef: J.MemberReference, q: RpcSendQueue): Promise {
await q.getAndSend(memberRef, m => m.containing, cont => this.visitRightPadded(cont, q));
await q.getAndSend(memberRef, m => m.typeParameters, params => this.visitContainer(params, q));
await q.getAndSend(memberRef, m => m.reference, ref => this.visitLeftPadded(ref, q));
await q.getAndSend(memberRef, m => asRef(m.type), type => this.visitType(type, q));
await q.getAndSend(memberRef, m => asRef(m.methodType), type => this.visitType(type, q));
await q.getAndSend(memberRef, m => asRef(m.variableType), type => this.visitType(type, q));
return memberRef;
}
protected async visitMethodInvocation(invocation: J.MethodInvocation, q: RpcSendQueue): Promise {
await q.getAndSend(invocation, m => m.select, select => this.visitRightPadded(select, q));
await q.getAndSend(invocation, m => m.typeParameters, params => this.visitContainer(params, q));
await q.getAndSend(invocation, m => m.name, name => this.visit(name, q));
await q.getAndSend(invocation, m => m.arguments, args => this.visitContainer(args, q));
await q.getAndSend(invocation, m => asRef(m.methodType), type => this.visitType(type, q));
return invocation;
}
protected async visitModifier(modifier: J.Modifier, q: RpcSendQueue): Promise {
await q.getAndSend(modifier, m => m.keyword);
await q.getAndSend(modifier, m => m.type);
await q.getAndSendList(modifier, m => m.annotations, annot => annot.id, annot => this.visit(annot, q));
return modifier;
}
protected async visitMultiCatch(multiCatch: J.MultiCatch, q: RpcSendQueue): Promise {
await q.getAndSendList(multiCatch, m => m.alternatives, alt => alt.element.id, alt => this.visitRightPadded(alt, q));
return multiCatch;
}
protected async visitNewArray(newArray: J.NewArray, q: RpcSendQueue): Promise {
await q.getAndSend(newArray, n => n.typeExpression, type => this.visit(type, q));
await q.getAndSendList(newArray, n => n.dimensions, dim => dim.id, dim => this.visit(dim, q));
await q.getAndSend(newArray, n => n.initializer, init => this.visitContainer(init, q));
await q.getAndSend(newArray, n => asRef(n.type), type => this.visitType(type, q));
return newArray;
}
protected async visitNewClass(newClass: J.NewClass, q: RpcSendQueue): Promise {
await q.getAndSend(newClass, n => n.enclosing, encl => this.visitRightPadded(encl, q));
await q.getAndSend(newClass, n => n.new, n => this.visitSpace(n, q));
await q.getAndSend(newClass, n => n.class, clazz => this.visit(clazz, q));
await q.getAndSend(newClass, n => n.arguments, args => this.visitContainer(args, q));
await q.getAndSend(newClass, n => n.body, body => this.visit(body, q));
await q.getAndSend(newClass, n => asRef(n.constructorType), type => this.visitType(type, q));
return newClass;
}
protected async visitNullableType(nullableType: J.NullableType, q: RpcSendQueue): Promise {
await q.getAndSendList(nullableType, a => a.annotations, annot => annot.id, annot => this.visit(annot, q));
await q.getAndSend(nullableType, n => n.typeTree, type => this.visitRightPadded(type, q));
return nullableType;
}
protected async visitParameterizedType(paramType: J.ParameterizedType, q: RpcSendQueue): Promise {
await q.getAndSend(paramType, p => p.class, clazz => this.visit(clazz, q));
await q.getAndSend(paramType, p => p.typeParameters, params => this.visitContainer(params, q));
await q.getAndSend(paramType, p => asRef(p.type), type => this.visitType(type, q));
return paramType;
}
protected async visitParentheses(parentheses: J.Parentheses, q: RpcSendQueue): Promise {
await q.getAndSend(parentheses, p => p.tree, tree => this.visitRightPadded(tree, q));
return parentheses;
}
protected async visitParenthesizedTypeTree(parenthesizedType: J.ParenthesizedTypeTree, q: RpcSendQueue): Promise {
await q.getAndSendList(parenthesizedType, a => a.annotations, annot => annot.id, annot => this.visit(annot, q));
await q.getAndSend(parenthesizedType, p => p.parenthesizedType, tree => this.visit(tree, q));
return parenthesizedType;
}
protected async visitPrimitive(primitive: J.Primitive, q: RpcSendQueue): Promise {
await q.getAndSend(primitive, p => asRef(p.type), type => this.visitType(type, q));
return primitive;
}
protected async visitReturn(returnStmt: J.Return, q: RpcSendQueue): Promise {
await q.getAndSend(returnStmt, r => r.expression, expr => this.visit(expr, q));
return returnStmt;
}
protected async visitSwitch(aSwitch: J.Switch, q: RpcSendQueue): Promise {
await q.getAndSend(aSwitch, s => s.selector, sel => this.visit(sel, q));
await q.getAndSend(aSwitch, s => s.cases, block => this.visit(block, q));
return aSwitch;
}
protected async visitSwitchExpression(switchExpr: J.SwitchExpression, q: RpcSendQueue): Promise {
await q.getAndSend(switchExpr, s => s.selector, sel => this.visit(sel, q));
await q.getAndSend(switchExpr, s => s.cases, block => this.visit(block, q));
await q.getAndSend(switchExpr, s => asRef(s.type), type => this.visitType(type, q));
return switchExpr;
}
protected async visitSynchronized(syncStmt: J.Synchronized, q: RpcSendQueue): Promise {
await q.getAndSend(syncStmt, s => s.lock, lock => this.visit(lock, q));
await q.getAndSend(syncStmt, s => s.body, body => this.visit(body, q));
return syncStmt;
}
protected async visitTernary(ternary: J.Ternary, q: RpcSendQueue): Promise {
await q.getAndSend(ternary, t => t.condition, cond => this.visit(cond, q));
await q.getAndSend(ternary, t => t.truePart, truePart => this.visitLeftPadded(truePart, q));
await q.getAndSend(ternary, t => t.falsePart, falsePart => this.visitLeftPadded(falsePart, q));
await q.getAndSend(ternary, t => asRef(t.type), type => this.visitType(type, q));
return ternary;
}
protected async visitThrow(throwStmt: J.Throw, q: RpcSendQueue): Promise {
await q.getAndSend(throwStmt, t => t.exception, exc => this.visit(exc, q));
return throwStmt;
}
protected async visitTry(tryStmt: J.Try, q: RpcSendQueue): Promise {
await q.getAndSend(tryStmt, t => t.resources, res => this.visitContainer(res, q));
await q.getAndSend(tryStmt, t => t.body, body => this.visit(body, q));
await q.getAndSendList(tryStmt, t => t.catches, catch_ => catch_.id, catch_ => this.visit(catch_, q));
await q.getAndSend(tryStmt, t => t.finally, fin => this.visitLeftPadded(fin, q));
return tryStmt;
}
protected async visitTryResource(resource: J.Try.Resource, q: RpcSendQueue): Promise {
await q.getAndSend(resource, r => r.variableDeclarations, variable => this.visit(variable, q));
await q.getAndSend(resource, r => r.terminatedWithSemicolon);
return resource;
}
protected async visitTryCatch(aCatch: J.Try.Catch, q: RpcSendQueue): Promise {
await q.getAndSend(aCatch, c => c.parameter, param => this.visit(param, q));
await q.getAndSend(aCatch, c => c.body, body => this.visit(body, q));
return aCatch;
}
protected async visitTypeCast(typeCast: J.TypeCast, q: RpcSendQueue): Promise {
await q.getAndSend(typeCast, t => t.class, clazz => this.visit(clazz, q));
await q.getAndSend(typeCast, t => t.expression, expr => this.visit(expr, q));
return typeCast;
}
protected async visitTypeParameter(typeParam: J.TypeParameter, q: RpcSendQueue): Promise {
await q.getAndSendList(typeParam, t => t.annotations, annot => annot.id, annot => this.visit(annot, q));
await q.getAndSendList(typeParam, t => t.modifiers, mod => mod.id, mod => this.visit(mod, q));
await q.getAndSend(typeParam, t => t.name, name => this.visit(name, q));
await q.getAndSend(typeParam, t => t.bounds, bounds => this.visitContainer(bounds, q));
return typeParam;
}
protected async visitTypeParameters(typeParams: J.TypeParameters, q: RpcSendQueue): Promise {
await q.getAndSendList(typeParams, a => a.annotations, annot => annot.id, annot => this.visit(annot, q));
await q.getAndSendList(typeParams, t => t.typeParameters, p => p.element.id, params => this.visitRightPadded(params, q));
return typeParams;
}
protected async visitUnary(unary: J.Unary, q: RpcSendQueue): Promise {
await q.getAndSend(unary, u => u.operator, op => this.visitLeftPadded(op, q));
await q.getAndSend(unary, u => u.expression, expr => this.visit(expr, q));
await q.getAndSend(unary, u => asRef(u.type), type => this.visitType(type, q));
return unary;
}
protected async visitVariable(variable: J.VariableDeclarations.NamedVariable, q: RpcSendQueue): Promise {
await q.getAndSend(variable, v => v.name, name => this.visit(name, q));
await q.getAndSendList(variable, v => v.dimensionsAfterName, d => JSON.stringify(d.element), dims => this.visitLeftPadded(dims, q));
await q.getAndSend(variable, v => v.initializer, init => this.visitLeftPadded(init, q));
await q.getAndSend(variable, v => asRef(v.variableType), type => this.visitType(type, q));
return variable;
}
protected async visitWhileLoop(whileLoop: J.WhileLoop, q: RpcSendQueue): Promise {
await q.getAndSend(whileLoop, w => w.condition, cond => this.visit(cond, q));
await q.getAndSend(whileLoop, w => w.body, body => this.visitRightPadded(body, q));
return whileLoop;
}
protected async visitWildcard(wildcard: J.Wildcard, q: RpcSendQueue): Promise {
await q.getAndSend(wildcard, w => w.bound, b => this.visitLeftPadded(b, q));
await q.getAndSend(wildcard, w => w.boundedType, type => this.visit(type, q));
return wildcard;
}
protected async visitYield(yieldExpr: J.Yield, q: RpcSendQueue): Promise {
await q.getAndSend(yieldExpr, y => y.implicit);
await q.getAndSend(yieldExpr, y => y.value, value => this.visit(value, q));
return yieldExpr;
}
protected async visitUnknown(unknown: J.Unknown, q: RpcSendQueue): Promise {
await q.getAndSend(unknown, u => u.source, source => this.visit(source, q));
return unknown;
}
protected async visitUnknownSource(source: J.UnknownSource, q: RpcSendQueue): Promise {
await q.getAndSend(source, s => s.text);
return source;
}
protected async visitCompilationUnit(cu: J.CompilationUnit, q: RpcSendQueue): Promise {
await q.getAndSend(cu, c => c.sourcePath);
await q.getAndSend(cu, c => c.charsetName);
await q.getAndSend(cu, c => c.charsetBomMarked);
await q.getAndSend(cu, c => c.checksum);
await q.getAndSend(cu, c => c.fileAttributes);
await q.getAndSend(cu, c => c.packageDeclaration, pkg => this.visitRightPadded(pkg, q));
await q.getAndSendList(cu, c => c.imports, imp => imp.element.id, imp => this.visitRightPadded(imp, q));
await q.getAndSendList(cu, c => c.classes, cls => cls.id, cls => this.visit(cls, q));
await q.getAndSend(cu, c => c.eof, space => this.visitSpace(space, q));
return cu;
}
protected async visitPackage(pkg: J.Package, q: RpcSendQueue): Promise {
await q.getAndSend(pkg, p => p.expression, expr => this.visit(expr, q));
await q.getAndSendList(pkg, p => p.annotations, annot => annot.id, annot => this.visit(annot, q));
return pkg;
}
protected async visitClassDeclaration(cls: J.ClassDeclaration, q: RpcSendQueue): Promise {
await q.getAndSendList(cls, c => c.leadingAnnotations, annot => annot.id, annot => this.visit(annot, q));
await q.getAndSendList(cls, c => c.modifiers, mod => mod.id, mod => this.visit(mod, q));
await q.getAndSend(cls, c => c.classKind, kind => this.visit(kind, q));
await q.getAndSend(cls, c => c.name, name => this.visit(name, q));
await q.getAndSend(cls, c => c.typeParameters, params => this.visitContainer(params, q));
await q.getAndSend(cls, c => c.primaryConstructor, cons => this.visitContainer(cons, q));
await q.getAndSend(cls, c => c.extends, ext => this.visitLeftPadded(ext, q));
await q.getAndSend(cls, c => c.implements, impl => this.visitContainer(impl, q));
await q.getAndSend(cls, c => c.permitting, perm => this.visitContainer(perm, q));
await q.getAndSend(cls, c => c.body, body => this.visit(body, q));
await q.getAndSend(cls, c => asRef(c.type), type => this.visitType(type, q));
return cls;
}
protected async visitClassDeclarationKind(kind: J.ClassDeclaration.Kind, q: RpcSendQueue): Promise {
await q.getAndSendList(kind, k => k.annotations, annot => annot.id, annot => this.visit(annot, q));
await q.getAndSend(kind, k => k.type);
return kind;
}
protected async visitBlock(block: J.Block, q: RpcSendQueue): Promise {
await q.getAndSend(block, b => b.static, s => this.visitRightPadded(s, q));
await q.getAndSendList(block, b => b.statements, stmt => stmt.element.id, stmt => this.visitRightPadded(stmt, q));
await q.getAndSend(block, b => b.end, space => this.visitSpace(space, q));
return block;
}
protected async visitMethodDeclaration(method: J.MethodDeclaration, q: RpcSendQueue): Promise {
await q.getAndSendList(method, m => m.leadingAnnotations, annot => annot.id, annot => this.visit(annot, q));
await q.getAndSendList(method, m => m.modifiers, mod => mod.id, mod => this.visit(mod, q));
await q.getAndSend(method, m => m.typeParameters, params => this.visit(params, q));
await q.getAndSend(method, m => m.returnTypeExpression, type => this.visit(type, q));
await q.getAndSendList(method, m => m.nameAnnotations, a => a.id, name => this.visit(name, q));
await q.getAndSend(method, m => m.name, name => this.visit(name, q));
await q.getAndSend(method, m => m.parameters, params => this.visitContainer(params, q));
await q.getAndSendList(method, m => m.dimensionsAfterName, d => JSON.stringify(d.element), dims => this.visitLeftPadded(dims, q));
await q.getAndSend(method, m => m.throws, throws => this.visitContainer(throws, q));
await q.getAndSend(method, m => m.body, body => this.visit(body, q));
await q.getAndSend(method, m => m.defaultValue, def => this.visitLeftPadded(def, q));
await q.getAndSend(method, m => asRef(m.methodType), type => this.visitType(type, q));
return method;
}
protected async visitVariableDeclarations(varDecls: J.VariableDeclarations, q: RpcSendQueue): Promise {
await q.getAndSendList(varDecls, v => v.leadingAnnotations, annot => annot.id, annot => this.visit(annot, q));
await q.getAndSendList(varDecls, v => v.modifiers, mod => mod.id, mod => this.visit(mod, q));
await q.getAndSend(varDecls, v => v.typeExpression, type => this.visit(type, q));
await q.getAndSend(varDecls, v => v.varargs, space => this.visitSpace(space, q));
await q.getAndSendList(varDecls, v => v.variables, variable => variable.element.id, variable => this.visitRightPadded(variable, q));
return varDecls;
}
protected async visitIdentifier(ident: J.Identifier, q: RpcSendQueue): Promise {
await q.getAndSendList(ident, id => id.annotations, annot => annot.id, annot => this.visit(annot, q));
await q.getAndSend(ident, id => id.simpleName);
await q.getAndSend(ident, id => asRef(id.type), type => this.visitType(type, q));
await q.getAndSend(ident, id => asRef(id.fieldType), type => this.visitType(type, q));
return ident;
}
public override async visitSpace(space: J.Space, q: RpcSendQueue): Promise {
await q.getAndSendList(space, s => s.comments,
c => {
if (c.kind === J.Kind.TextComment) {
return (c as TextComment).text + c.suffix;
}
throw new Error(`Unexpected comment type ${c.kind}`);
},
async c => {
if (c.kind === J.Kind.TextComment) {
const tc = c as TextComment;
await q.getAndSend(tc, c2 => c2.multiline);
await q.getAndSend(tc, c2 => c2.text);
} else {
throw new Error(`Unexpected comment type ${c.kind}`);
}
await q.getAndSend(c, c2 => c2.suffix);
await q.getAndSend(c, c2 => c2.markers);
});
await q.getAndSend(space, s => s.whitespace);
return space;
}
public override async visitLeftPadded(left: J.LeftPadded, q: RpcSendQueue): Promise> {
await q.getAndSend(left, l => l.before, space => this.visitSpace(space, q));
if (isTree(left.element)) {
await q.getAndSend(left, l => l.element, elem => this.visit(elem as J, q));
} else if (isSpace(left.element)) {
await q.getAndSend(left, l => l.element, space => this.visitSpace(space as J.Space, q));
} else {
await q.getAndSend(left, l => l.element);
}
await q.getAndSend(left, l => l.markers);
return left;
}
public override async visitRightPadded(right: J.RightPadded, q: RpcSendQueue): Promise> {
if (isTree(right.element)) {
await q.getAndSend(right, r => r.element, elem => this.visit(elem as J, q));
} else {
await q.getAndSend(right, r => r.element);
}
await q.getAndSend(right, r => r.after, space => this.visitSpace(space, q));
await q.getAndSend(right, r => r.markers);
return right;
}
public override async visitContainer(container: J.Container, q: RpcSendQueue): Promise> {
await q.getAndSend(container, c => c.before, space => this.visitSpace(space, q));
await q.getAndSendList(container, c => c.elements, elem => elem.element.id, elem => this.visitRightPadded(elem, q));
await q.getAndSend(container, c => c.markers);
return container;
}
private typeVisitor = new TypeSender();
public override async visitType(javaType: Type | undefined, q: RpcSendQueue): Promise {
if (!javaType) {
return undefined;
}
return await this.typeVisitor.visit(javaType, q);
}
}
export class JavaReceiver extends JavaVisitor {
protected async preVisit(j: J, q: RpcReceiveQueue): Promise {
try {
const updates = {
id: await q.receive(j.id),
prefix: await q.receive(j.prefix, space => this.visitSpace(space, q)),
markers: await q.receive(j.markers)
};
return updateIfChanged(j, updates);
} catch (e: any) {
throw e;
}
}
protected async visitAnnotatedType(annotatedType: J.AnnotatedType, q: RpcReceiveQueue): Promise {
const updates = {
annotations: await q.receiveListDefined(annotatedType.annotations, annot => this.visit(annot, q)),
typeExpression: await q.receive(annotatedType.typeExpression, type => this.visit(type, q))
};
return updateIfChanged(annotatedType, updates);
}
protected async visitAnnotation(annotation: J.Annotation, q: RpcReceiveQueue): Promise {
const updates = {
annotationType: await q.receive(annotation.annotationType, type => this.visit(type, q)),
arguments: await q.receive(annotation.arguments, args => this.visitContainer(args, q))
};
return updateIfChanged(annotation, updates);
}
protected async visitArrayAccess(arrayAccess: J.ArrayAccess, q: RpcReceiveQueue): Promise {
const updates = {
indexed: await q.receive(arrayAccess.indexed, indexed => this.visit(indexed, q)),
dimension: await q.receive(arrayAccess.dimension, dim => this.visit(dim, q))
};
return updateIfChanged(arrayAccess, updates);
}
protected async visitArrayDimension(dimension: J.ArrayDimension, q: RpcReceiveQueue): Promise {
const updates = {
index: await q.receive(dimension.index, idx => this.visitRightPadded(idx, q))
};
return updateIfChanged(dimension, updates);
}
protected async visitArrayType(arrayType: J.ArrayType, q: RpcReceiveQueue): Promise {
const updates = {
elementType: await q.receive(arrayType.elementType, type => this.visit(type, q)),
annotations: await q.receiveListDefined(arrayType.annotations || [], annot => this.visit(annot, q)),
dimension: await q.receive(arrayType.dimension, d => this.visitLeftPadded(d, q)),
type: await q.receive(arrayType.type, type => this.visitType(type, q))
};
return updateIfChanged(arrayType, updates);
}
protected async visitAssert(assert: J.Assert, q: RpcReceiveQueue): Promise {
const updates = {
condition: await q.receive(assert.condition, cond => this.visit(cond, q)),
detail: await q.receive(assert.detail, detail => this.visitOptionalLeftPadded(detail, q))
};
return updateIfChanged(assert, updates);
}
protected async visitAssignment(assignment: J.Assignment, q: RpcReceiveQueue): Promise {
const updates = {
variable: await q.receive(assignment.variable, variable => this.visit(variable, q)),
assignment: await q.receive(assignment.assignment, assign => this.visitLeftPadded(assign, q)),
type: await q.receive(assignment.type, type => this.visitType(type, q))
};
return updateIfChanged(assignment, updates);
}
protected async visitAssignmentOperation(assignOp: J.AssignmentOperation, q: RpcReceiveQueue): Promise {
const updates = {
variable: await q.receive(assignOp.variable, variable => this.visit(variable, q)),
operator: await q.receive(assignOp.operator, op => this.visitLeftPadded(op, q)),
assignment: await q.receive(assignOp.assignment, assign => this.visit(assign, q)),
type: await q.receive(assignOp.type, type => this.visitType(type, q))
};
return updateIfChanged(assignOp, updates);
}
protected async visitBinary(binary: J.Binary, q: RpcReceiveQueue): Promise {
const updates = {
left: await q.receive(binary.left, left => this.visit(left, q)),
operator: await q.receive(binary.operator, op => this.visitLeftPadded(op, q)),
right: await q.receive(binary.right, right => this.visit(right, q)),
type: await q.receive(binary.type, type => this.visitType(type, q))
};
return updateIfChanged(binary, updates);
}
protected async visitBreak(breakStmt: J.Break, q: RpcReceiveQueue): Promise {
const updates = {
label: await q.receive(breakStmt.label, label => this.visit(label, q))
};
return updateIfChanged(breakStmt, updates);
}
protected async visitCase(caseStmt: J.Case, q: RpcReceiveQueue): Promise {
const updates = {
type: await q.receive(caseStmt.type),
caseLabels: await q.receive(caseStmt.caseLabels, labels => this.visitContainer(labels, q)),
statements: await q.receive(caseStmt.statements, stmts => this.visitContainer(stmts, q)),
body: await q.receive(caseStmt.body, body => this.visitRightPadded(body, q)),
guard: await q.receive(caseStmt.guard, guard => this.visit(guard, q))
};
return updateIfChanged(caseStmt, updates);
}
protected async visitContinue(continueStmt: J.Continue, q: RpcReceiveQueue): Promise {
const updates = {
label: await q.receive(continueStmt.label, label => this.visit(label, q))
};
return updateIfChanged(continueStmt, updates);
}
protected async visitControlParentheses(controlParens: J.ControlParentheses, q: RpcReceiveQueue): Promise {
const updates = {
tree: await q.receive(controlParens.tree, tree => this.visitRightPadded(tree, q))
};
return updateIfChanged(controlParens, updates);
}
protected async visitDeconstructionPattern(pattern: J.DeconstructionPattern, q: RpcReceiveQueue): Promise {
const updates = {
deconstructor: await q.receive(pattern.deconstructor, deconstructor => this.visit(deconstructor, q)),
nested: await q.receive(pattern.nested, nested => this.visitContainer(nested, q)),
type: await q.receive(pattern.type, type => this.visitType(type, q))
};
return updateIfChanged(pattern, updates);
}
protected async visitDoWhileLoop(doWhile: J.DoWhileLoop, q: RpcReceiveQueue): Promise {
const updates = {
body: await q.receive(doWhile.body, body => this.visitOptionalRightPadded(body, q)),
whileCondition: await q.receive(doWhile.whileCondition, cond => this.visitLeftPadded(cond, q))
};
return updateIfChanged(doWhile, updates);
}
protected async visitEmpty(empty: J.Empty): Promise {
// no additional properties to receive
return empty;
}
protected async visitEnumValueSet(enumValueSet: J.EnumValueSet, q: RpcReceiveQueue): Promise {
const updates = {
enums: await q.receiveListDefined(enumValueSet.enums, enumValue => this.visitRightPadded(enumValue, q)),
terminatedWithSemicolon: await q.receive(enumValueSet.terminatedWithSemicolon)
};
return updateIfChanged(enumValueSet, updates);
}
protected async visitEnumValue(enumValue: J.EnumValue, q: RpcReceiveQueue): Promise {
const updates = {
annotations: await q.receiveListDefined(enumValue.annotations, annot => this.visit(annot, q)),
name: await q.receive(enumValue.name, name => this.visit(name, q)),
initializer: await q.receive(enumValue.initializer, init => this.visit(init, q))
};
return updateIfChanged(enumValue, updates);
}
protected async visitErroneous(erroneous: J.Erroneous, q: RpcReceiveQueue): Promise {
const updates = {
text: await q.receive(erroneous.text)
};
return updateIfChanged(erroneous, updates);
}
protected async visitFieldAccess(fieldAccess: J.FieldAccess, q: RpcReceiveQueue): Promise {
const updates = {
target: await q.receive(fieldAccess.target, target => this.visit(target, q)),
name: await q.receive(fieldAccess.name, name => this.visitLeftPadded(name, q)),
type: await q.receive(fieldAccess.type, type => this.visitType(type, q))
};
return updateIfChanged(fieldAccess, updates);
}
protected async visitForEachLoop(forEachLoop: J.ForEachLoop, q: RpcReceiveQueue): Promise {
const updates = {
control: await q.receive(forEachLoop.control, c => this.visit(c, q)),
body: await q.receive(forEachLoop.body, body => this.visitRightPadded(body, q))
};
return updateIfChanged(forEachLoop, updates);
}
protected async visitForEachLoopControl(control: J.ForEachLoop.Control, q: RpcReceiveQueue): Promise {
const updates = {
variable: await q.receive(control.variable, variable => this.visitRightPadded(variable, q)),
iterable: await q.receive(control.iterable, expr => this.visitRightPadded(expr, q))
};
return updateIfChanged(control, updates);
}
protected async visitForLoop(forLoop: J.ForLoop, q: RpcReceiveQueue): Promise {
const updates = {
control: await q.receive(forLoop.control, c => this.visit(c, q)),
body: await q.receive(forLoop.body, body => this.visitRightPadded(body, q))
};
return updateIfChanged(forLoop, updates);
}
protected async visitForLoopControl(control: J.ForLoop.Control, q: RpcReceiveQueue): Promise {
const updates = {
init: await q.receiveListDefined(control.init, init => this.visitRightPadded(init, q)),
condition: await q.receive(control.condition, cond => this.visitRightPadded(cond, q)),
update: await q.receiveListDefined(control.update, update => this.visitRightPadded(update, q))
};
return updateIfChanged(control, updates);
}
protected async visitIf(ifStmt: J.If, q: RpcReceiveQueue): Promise {
const updates = {
ifCondition: await q.receive(ifStmt.ifCondition, cond => this.visit(cond, q)),
thenPart: await q.receive(ifStmt.thenPart, thenPart => this.visitRightPadded(thenPart, q)),
elsePart: await q.receive(ifStmt.elsePart, elsePart => this.visit(elsePart, q))
};
return updateIfChanged(ifStmt, updates);
}
protected async visitElse(ifElse: J.If.Else, q: RpcReceiveQueue): Promise {
const updates = {
body: await q.receive(ifElse.body, body => this.visitRightPadded(body, q))
};
return updateIfChanged(ifElse, updates);
}
protected async visitImport(importStmt: J.Import, q: RpcReceiveQueue): Promise {
const updates = {
static: await q.receive(importStmt.static, s => this.visitLeftPadded(s, q)),
qualid: await q.receive(importStmt.qualid, qualid => this.visit(qualid, q)),
alias: await q.receive(importStmt.alias, alias => this.visitLeftPadded(alias, q))
};
return updateIfChanged(importStmt, updates);
}
protected async visitInstanceOf(instanceOf: J.InstanceOf, q: RpcReceiveQueue): Promise {
const updates = {
expression: await q.receive(instanceOf.expression, expr => this.visitRightPadded(expr, q)),
class: await q.receive(instanceOf.class, clazz => this.visit(clazz, q)),
pattern: await q.receive(instanceOf.pattern, pattern => this.visit(pattern, q)),
type: await q.receive(instanceOf.type, type => this.visitType(type, q)),
modifier: await q.receive(instanceOf.modifier, mod => this.visit(mod, q))
};
return updateIfChanged(instanceOf, updates);
}
protected async visitIntersectionType(intersectionType: J.IntersectionType, q: RpcReceiveQueue): Promise {
const updates = {
bounds: await q.receive(intersectionType.bounds, bounds => this.visitContainer(bounds, q))
};
return updateIfChanged(intersectionType, updates);
}
protected async visitLabel(label: J.Label, q: RpcReceiveQueue): Promise {
const updates = {
label: await q.receive(label.label, lbl => this.visitRightPadded(lbl, q)),
statement: await q.receive(label.statement, stmt => this.visit(stmt, q))
};
return updateIfChanged(label, updates);
}
protected async visitLambda(lambda: J.Lambda, q: RpcReceiveQueue): Promise {
const updates = {
parameters: await q.receive(lambda.parameters, params => this.visit(params, q)),
arrow: await q.receive(lambda.arrow, arrow => this.visitSpace(arrow, q)),
body: await q.receive(lambda.body, body => this.visit(body, q)),
type: await q.receive(lambda.type, type => this.visitType(type, q))
};
return updateIfChanged(lambda, updates);
}
protected async visitLambdaParameters(params: J.Lambda.Parameters, q: RpcReceiveQueue): Promise {
const updates = {
parenthesized: await q.receive(params.parenthesized),
parameters: await q.receiveListDefined(params.parameters, param => this.visitRightPadded(param, q))
};
return updateIfChanged(params, updates);
}
protected async visitLiteral(literal: J.Literal, q: RpcReceiveQueue): Promise {
const updates = {
value: await q.receive(literal.value),
valueSource: await q.receive(literal.valueSource),
unicodeEscapes: await q.receiveList(literal.unicodeEscapes, async (e) => ({
valueSourceIndex: await q.receive(e?.valueSourceIndex),
codePoint: await q.receive(e?.codePoint),
})),
type: await q.receive(literal.type, type => this.visitType(type, q) as unknown as Type.Primitive)
};
return updateIfChanged(literal, updates);
}
protected async visitMemberReference(memberRef: J.MemberReference, q: RpcReceiveQueue): Promise {
const updates = {
containing: await q.receive(memberRef.containing, container => this.visitRightPadded(container, q)),
typeParameters: await q.receive(memberRef.typeParameters, typeParams => this.visitContainer(typeParams, q)),
reference: await q.receive(memberRef.reference, ref => this.visitLeftPadded(ref, q)),
type: await q.receive(memberRef.type, type => this.visitType(type, q)),
methodType: await q.receive(memberRef.methodType, type => this.visitType(type, q) as unknown as Type.Method),
variableType: await q.receive(memberRef.variableType, type => this.visitType(type, q) as unknown as Type.Variable)
};
return updateIfChanged(memberRef, updates);
}
protected async visitMethodInvocation(methodInvoc: J.MethodInvocation, q: RpcReceiveQueue): Promise {
const updates = {
select: await q.receive(methodInvoc.select, select => this.visitRightPadded(select, q)),
typeParameters: await q.receive(methodInvoc.typeParameters, typeParams => this.visitContainer(typeParams, q)),
name: await q.receive(methodInvoc.name, name => this.visit(name, q)),
arguments: await q.receive(methodInvoc.arguments, args => this.visitContainer(args, q)),
methodType: await q.receive(methodInvoc.methodType, type => this.visitType(type, q) as unknown as Type.Method)
};
return updateIfChanged(methodInvoc, updates);
}
protected async visitModifier(modifier: J.Modifier, q: RpcReceiveQueue): Promise {
const updates = {
keyword: await q.receive(modifier.keyword),
type: await q.receive(modifier.type),
annotations: await q.receiveListDefined(modifier.annotations, annot => this.visit(annot, q))
};
return updateIfChanged(modifier, updates);
}
protected async visitMultiCatch(multiCatch: J.MultiCatch, q: RpcReceiveQueue): Promise {
const updates = {
alternatives: await q.receiveListDefined(multiCatch.alternatives, alt => this.visitRightPadded(alt, q))
};
return updateIfChanged(multiCatch, updates);
}
protected async visitNewArray(newArray: J.NewArray, q: RpcReceiveQueue): Promise {
const updates = {
typeExpression: await q.receive(newArray.typeExpression, type => this.visit(type, q)),
dimensions: await q.receiveListDefined(newArray.dimensions, dim => this.visit(dim, q)),
initializer: await q.receive(newArray.initializer, init => this.visitContainer(init, q)),
type: await q.receive(newArray.type, type => this.visitType(type, q))
};
return updateIfChanged(newArray, updates);
}
protected async visitNewClass(newClass: J.NewClass, q: RpcReceiveQueue): Promise {
const updates = {
enclosing: await q.receive(newClass.enclosing, encl => this.visitRightPadded(encl, q)),
new: await q.receive(newClass.new, new_ => this.visitSpace(new_, q)),
class: await q.receive(newClass.class, clazz => this.visit(clazz, q)),
arguments: await q.receive(newClass.arguments, args => this.visitContainer(args, q)),
body: await q.receive(newClass.body, body => this.visit(body, q)),
constructorType: await q.receive(newClass.constructorType, type => this.visitType(type, q) as unknown as Type.Method)
};
return updateIfChanged(newClass, updates);
}
protected async visitNullableType(nullableType: J.NullableType, q: RpcReceiveQueue): Promise {
const updates = {
annotations: await q.receiveListDefined(nullableType.annotations, annot => this.visit(annot, q)),
typeTree: await q.receive(nullableType.typeTree, type => this.visitRightPadded(type, q))
};
return updateIfChanged(nullableType, updates);
}
protected async visitParameterizedType(paramType: J.ParameterizedType, q: RpcReceiveQueue): Promise {
const updates = {
class: await q.receive(paramType.class, clazz => this.visit(clazz, q)),
typeParameters: await q.receive(paramType.typeParameters, params => this.visitContainer(params, q)),
type: await q.receive(paramType.type, type => this.visitType(type, q))
};
return updateIfChanged(paramType, updates);
}
protected async visitParentheses(parentheses: J.Parentheses, q: RpcReceiveQueue): Promise {
const updates = {
tree: await q.receive(parentheses.tree, tree => this.visitRightPadded(tree, q))
};
return updateIfChanged(parentheses, updates);
}
protected async visitParenthesizedTypeTree(parenthesizedType: J.ParenthesizedTypeTree, q: RpcReceiveQueue): Promise {
const updates = {
annotations: await q.receiveListDefined(parenthesizedType.annotations, annot => this.visit(annot, q)),
parenthesizedType: await q.receive(parenthesizedType.parenthesizedType, tree => this.visit(tree, q))
};
return updateIfChanged(parenthesizedType, updates);
}
protected async visitPrimitive(primitive: J.Primitive, q: RpcReceiveQueue): Promise {
const updates = {
type: await q.receive(primitive.type, type => this.visitType(type, q) as unknown as Type.Primitive)
};
return updateIfChanged(primitive, updates);
}
protected async visitSwitch(switchStmt: J.Switch, q: RpcReceiveQueue): Promise {
const updates = {
selector: await q.receive(switchStmt.selector, selector => this.visit(selector, q)),
cases: await q.receive(switchStmt.cases, cases => this.visit(cases, q))
};
return updateIfChanged(switchStmt, updates);
}
protected async visitSwitchExpression(switchExpr: J.SwitchExpression, q: RpcReceiveQueue): Promise {
const updates = {
selector: await q.receive(switchExpr.selector, selector => this.visit(selector, q)),
cases: await q.receive(switchExpr.cases, cases => this.visit(cases, q)),
type: await q.receive(switchExpr.type, type => this.visitType(type, q))
};
return updateIfChanged(switchExpr, updates);
}
protected async visitTernary(ternary: J.Ternary, q: RpcReceiveQueue): Promise {
const updates = {
condition: await q.receive(ternary.condition, cond => this.visit(cond, q)),
truePart: await q.receive(ternary.truePart, truePart => this.visitLeftPadded(truePart, q)),
falsePart: await q.receive(ternary.falsePart, falsePart => this.visitLeftPadded(falsePart, q)),
type: await q.receive(ternary.type, type => this.visitType(type, q))
};
return updateIfChanged(ternary, updates);
}
protected async visitThrow(throwStmt: J.Throw, q: RpcReceiveQueue): Promise {
const updates = {
exception: await q.receive(throwStmt.exception, exception => this.visit(exception, q))
};
return updateIfChanged(throwStmt, updates);
}
protected async visitTry(tryStmt: J.Try, q: RpcReceiveQueue): Promise {
const updates = {
resources: await q.receive(tryStmt.resources, resources => this.visitContainer(resources, q)),
body: await q.receive(tryStmt.body, body => this.visit(body, q)),
catches: await q.receiveListDefined(tryStmt.catches, catchBlock => this.visit(catchBlock, q)),
finally: await q.receive(tryStmt.finally, finallyBlock => this.visitOptionalLeftPadded(finallyBlock, q))
};
return updateIfChanged(tryStmt, updates);
}
protected async visitTryResource(resource: J.Try.Resource, q: RpcReceiveQueue): Promise {
const updates = {
variableDeclarations: await q.receive(resource.variableDeclarations, variables => this.visit(variables, q)),
terminatedWithSemicolon: await q.receive(resource.terminatedWithSemicolon)
};
return updateIfChanged(resource, updates);
}
protected async visitTryCatch(tryCatch: J.Try.Catch, q: RpcReceiveQueue): Promise {
const updates = {
parameter: await q.receive(tryCatch.parameter, param => this.visit(param, q)),
body: await q.receive(tryCatch.body, body => this.visit(body, q))
};
return updateIfChanged(tryCatch, updates);
}
protected async visitUnary(unary: J.Unary, q: RpcReceiveQueue): Promise {
const updates = {
operator: await q.receive(unary.operator, op => this.visitLeftPadded(op, q)),
expression: await q.receive(unary.expression, expr => this.visit(expr, q)),
type: await q.receive(unary.type, type => this.visitType(type, q))
};
return updateIfChanged(unary, updates);
}
protected async visitUnknown(unknown: J.Unknown, q: RpcReceiveQueue): Promise {
const updates = {
source: await q.receive(unknown.source, source => this.visit(source, q))
};
return updateIfChanged(unknown, updates);
}
protected async visitUnknownSource(unknownSource: J.UnknownSource, q: RpcReceiveQueue): Promise {
const updates = {
text: await q.receive(unknownSource.text)
};
return updateIfChanged(unknownSource, updates);
}
protected async visitVariable(variable: J.VariableDeclarations.NamedVariable, q: RpcReceiveQueue): Promise {
const updates = {
name: await q.receive(variable.name, name => this.visit(name, q)),
dimensionsAfterName: await q.receiveListDefined(variable.dimensionsAfterName, dim => this.visitLeftPadded(dim, q)),
initializer: await q.receive(variable.initializer, init => this.visitOptionalLeftPadded(init, q)),
variableType: await q.receive(variable.variableType, type => this.visitType(type, q) as unknown as Type.Variable)
};
return updateIfChanged(variable, updates);
}
protected async visitYield(yieldStmt: J.Yield, q: RpcReceiveQueue): Promise {
const updates = {
implicit: await q.receive(yieldStmt.implicit),
value: await q.receive(yieldStmt.value, value => this.visit(value, q))
};
return updateIfChanged(yieldStmt, updates);
}
protected async visitTypeParameters(typeParams: J.TypeParameters, q: RpcReceiveQueue): Promise {
const updates = {
annotations: await q.receiveListDefined(typeParams.annotations, annot => this.visit(annot, q)),
typeParameters: await q.receiveListDefined(typeParams.typeParameters, param => this.visitRightPadded(param, q))
};
return updateIfChanged(typeParams, updates);
}
protected async visitReturn(returnStmt: J.Return, q: RpcReceiveQueue): Promise {
const updates = {
expression: await q.receive(returnStmt.expression, expr => this.visit(expr, q))
};
return updateIfChanged(returnStmt, updates);
}
protected async visitSynchronized(synchronizedStmt: J.Synchronized, q: RpcReceiveQueue): Promise {
const updates = {
lock: await q.receive(synchronizedStmt.lock, lock => this.visit(lock, q)),
body: await q.receive(synchronizedStmt.body, body => this.visit(body, q))
};
return updateIfChanged(synchronizedStmt, updates);
}
protected async visitTypeCast(typeCast: J.TypeCast, q: RpcReceiveQueue): Promise {
const updates = {
class: await q.receive(typeCast.class, typeExpr => this.visit(typeExpr, q)),
expression: await q.receive(typeCast.expression, expr => this.visit(expr, q))
};
return updateIfChanged(typeCast, updates);
}
protected async visitTypeParameter(typeParameter: J.TypeParameter, q: RpcReceiveQueue): Promise {
const updates = {
annotations: await q.receiveListDefined(typeParameter.annotations, annot => this.visit(annot, q)),
modifiers: await q.receiveListDefined(typeParameter.modifiers, annot => this.visit(annot, q)),
name: await q.receive(typeParameter.name, name => this.visit(name, q)),
bounds: await q.receive(typeParameter.bounds, bounds => this.visitContainer(bounds, q))
};
return updateIfChanged(typeParameter, updates);
}
protected async visitWhileLoop(whileLoop: J.WhileLoop, q: RpcReceiveQueue): Promise {
const updates = {
condition: await q.receive(whileLoop.condition, cond => this.visit(cond, q)),
body: await q.receive(whileLoop.body, body => this.visitOptionalRightPadded(body, q))
};
return updateIfChanged(whileLoop, updates);
}
protected async visitWildcard(wildcard: J.Wildcard, q: RpcReceiveQueue): Promise {
const updates = {
bound: await q.receive(wildcard.bound, bound => this.visitLeftPadded(bound, q)),
boundedType: await q.receive(wildcard.boundedType, type => this.visit(type, q))
};
return updateIfChanged(wildcard, updates);
}
protected async visitCompilationUnit(cu: J.CompilationUnit, q: RpcReceiveQueue): Promise {
const updates = {
sourcePath: await q.receive(cu.sourcePath),
charsetName: await q.receive(cu.charsetName),
charsetBomMarked: await q.receive(cu.charsetBomMarked),
checksum: await q.receive(cu.checksum),
fileAttributes: await q.receive(cu.fileAttributes),
packageDeclaration: await q.receive(cu.packageDeclaration, pkg => this.visitRightPadded(pkg, q)),
imports: await q.receiveListDefined(cu.imports, imp => this.visitRightPadded(imp, q)),
classes: await q.receiveListDefined(cu.classes, cls => this.visit(cls, q)),
eof: await q.receive(cu.eof, space => this.visitSpace(space, q))
};
return updateIfChanged(cu, updates);
}
protected async visitPackage(pkg: J.Package, q: RpcReceiveQueue): Promise {
const updates = {
expression: await q.receive(pkg.expression, expr => this.visit(expr, q)),
annotations: await q.receiveListDefined(pkg.annotations, annot => this.visit(annot, q))
};
return updateIfChanged(pkg, updates);
}
protected async visitClassDeclaration(cls: J.ClassDeclaration, q: RpcReceiveQueue): Promise {
const updates = {
leadingAnnotations: await q.receiveListDefined(cls.leadingAnnotations, annot => this.visit(annot, q)),
modifiers: await q.receiveListDefined(cls.modifiers, mod => this.visit(mod, q)),
classKind: await q.receive(cls.classKind, kind => this.visit(kind, q)),
name: await q.receive(cls.name, name => this.visit(name, q)),
typeParameters: await q.receive(cls.typeParameters, params => this.visitContainer(params, q)),
primaryConstructor: await q.receive(cls.primaryConstructor, cons => this.visitContainer(cons, q)),
extends: await q.receive(cls.extends, ext => this.visitLeftPadded(ext, q)),
implements: await q.receive(cls.implements, impl => this.visitContainer(impl, q)),
permitting: await q.receive(cls.permitting, perm => this.visitContainer(perm, q)),
body: await q.receive(cls.body, body => this.visit(body, q)),
type: await q.receive(cls.type, type => this.visitType(type, q)) as Type.Class
};
return updateIfChanged(cls, updates);
}
protected async visitClassDeclarationKind(kind: J.ClassDeclaration.Kind, q: RpcReceiveQueue): Promise {
const updates = {
annotations: await q.receiveListDefined(kind.annotations, annot => this.visit(annot, q)),
type: await q.receive(kind.type)
};
return updateIfChanged(kind, updates);
}
protected async visitBlock(block: J.Block, q: RpcReceiveQueue): Promise {
const updates = {
static: await q.receive(block.static, s => this.visitRightPadded(s, q)),
statements: await q.receiveListDefined(block.statements, stmt => this.visitRightPadded(stmt, q)),
end: await q.receive(block.end, space => this.visitSpace(space, q))
};
return updateIfChanged(block, updates);
}
protected async visitMethodDeclaration(method: J.MethodDeclaration, q: RpcReceiveQueue): Promise {
const updates = {
leadingAnnotations: await q.receiveListDefined(method.leadingAnnotations, annot => this.visit(annot, q)),
modifiers: await q.receiveListDefined(method.modifiers, mod => this.visit(mod, q)),
typeParameters: await q.receive(method.typeParameters, params => this.visit(params, q)),
returnTypeExpression: await q.receive(method.returnTypeExpression, type => this.visit(type, q)),
nameAnnotations: (await q.receiveList(method.nameAnnotations, name => this.visit(name, q)))!,
name: await q.receive(method.name, name => this.visit(name, q)),
parameters: await q.receive(method.parameters, params => this.visitContainer(params, q)),
dimensionsAfterName: await q.receiveListDefined(method.dimensionsAfterName, dim => this.visitLeftPadded(dim, q)),
throws: await q.receive(method.throws, throws => this.visitContainer(throws, q)),
body: await q.receive(method.body, body => this.visit(body, q)),
defaultValue: await q.receive(method.defaultValue, def => this.visitLeftPadded(def, q)),
methodType: await q.receive(method.methodType, type => this.visitType(type, q) as unknown as Type.Method)
};
return updateIfChanged(method, updates);
}
protected async visitVariableDeclarations(varDecls: J.VariableDeclarations, q: RpcReceiveQueue): Promise {
const updates = {
leadingAnnotations: await q.receiveListDefined(varDecls.leadingAnnotations, annot => this.visit(annot, q)),
modifiers: await q.receiveListDefined(varDecls.modifiers, mod => this.visit(mod, q)),
typeExpression: await q.receive(varDecls.typeExpression, type => this.visit(type, q)),
varargs: await q.receive(varDecls.varargs, space => this.visitSpace(space, q)),
variables: await q.receiveListDefined(varDecls.variables, variable => this.visitRightPadded(variable, q))
};
return updateIfChanged(varDecls, updates);
}
protected async visitIdentifier(ident: J.Identifier, q: RpcReceiveQueue): Promise {
const updates = {
annotations: await q.receiveListDefined(ident.annotations, annot => this.visit(annot, q)),
simpleName: await q.receive(ident.simpleName),
type: await q.receive(ident.type, type => this.visitType(type, q)),
fieldType: await q.receive(ident.fieldType, type => this.visitType(type, q) as any as Type.Variable)
};
return updateIfChanged(ident, updates);
}
public override async visitSpace(space: J.Space, q: RpcReceiveQueue): Promise {
const updates = {
comments: await q.receiveListDefined(space.comments, async c => {
if (c.kind === J.Kind.TextComment) {
const tc = c as TextComment;
const commentUpdates = {
multiline: await q.receive(tc.multiline),
text: await q.receive(tc.text),
suffix: await q.receive(c.suffix),
markers: await q.receive(c.markers)
};
return updateIfChanged(tc, commentUpdates);
} else {
throw new Error(`Unexpected comment type ${c.kind}`);
}
}),
whitespace: await q.receive(space.whitespace)
};
return updateIfChanged(space, updates);
}
public override async visitLeftPadded(left: J.LeftPadded, q: RpcReceiveQueue): Promise> {
if (!left) {
throw new Error("TreeDataReceiveQueue should have instantiated an empty left padding");
}
const updates = {
before: await q.receive(left.before, space => this.visitSpace(space, q)),
element: await q.receive(left.element, elem => {
if (isSpace(elem)) {
return this.visitSpace(elem as J.Space, q) as any as T;
} else if (typeof elem === 'object' && elem.kind) {
// FIXME find a better way to check if it is a `Tree`
return this.visit(elem as J, q) as any as T;
}
return elem;
}),
markers: await q.receive(left.markers)
};
return updateIfChanged(left, updates) as J.LeftPadded;
}
public override async visitRightPadded(right: J.RightPadded, q: RpcReceiveQueue): Promise> {
if (!right) {
throw new Error("TreeDataReceiveQueue should have instantiated an empty right padding");
}
const updates = {
element: await q.receive(right.element, elem => {
if (isSpace(elem)) {
return this.visitSpace(elem as J.Space, q) as any as T;
} else if (typeof elem === 'object' && elem.kind) {
// FIXME find a better way to check if it is a `Tree`
return this.visit(elem as J, q) as any as T;
}
return elem as any as T;
}),
after: await q.receive(right.after, space => this.visitSpace(space, q)),
markers: await q.receive(right.markers)
};
return updateIfChanged(right, updates) as J.RightPadded;
}
public override async visitContainer(container: J.Container, q: RpcReceiveQueue): Promise> {
const updates = {
before: await q.receive(container.before, space => this.visitSpace(space, q)),
elements: await q.receiveListDefined(container.elements, elem => this.visitRightPadded(elem, q)),
markers: await q.receive(container.markers)
};
return updateIfChanged(container, updates) as J.Container;
}
private typeVisitor = new TypeReceiver();
public override async visitType(javaType: Type | undefined, q: RpcReceiveQueue): Promise {
if (!javaType) {
return undefined;
} else if (javaType.kind === Type.Kind.Unknown) {
return Type.unknownType;
}
return await this.typeVisitor.visit(javaType, q);
}
}
export function registerJLanguageCodecs(sourceFileType: string,
receiver: JavaVisitor,
sender: JavaVisitor,
extendedKinds?: any) {
const kinds = new Set([
...Object.values(J.Kind),
...(extendedKinds ? Object.values(extendedKinds) : [])
]);
// Register codec for all Java AST node types
for (const kind of kinds) {
if (kind === J.Kind.Space) {
RpcCodecs.registerCodec(kind, {
async rpcReceive(before: J.Space, q: RpcReceiveQueue): Promise {
return (await receiver.visitSpace(before, q))!;
},
async rpcSend(after: J.Space, q: RpcSendQueue): Promise {
await sender.visitSpace(after, q);
}
}, sourceFileType);
} else if (kind === J.Kind.RightPadded) {
RpcCodecs.registerCodec(kind, {
async rpcReceive(before: J.RightPadded, q: RpcReceiveQueue): Promise> {
return (await receiver.visitRightPadded(before, q))!;
},
async rpcSend(after: J.RightPadded, q: RpcSendQueue): Promise {
await sender.visitRightPadded(after, q);
}
}, sourceFileType);
} else if (kind === J.Kind.LeftPadded) {
RpcCodecs.registerCodec(kind, {
async rpcReceive(before: J.LeftPadded, q: RpcReceiveQueue): Promise> {
return (await receiver.visitLeftPadded(before, q))!;
},
async rpcSend(after: J.LeftPadded, q: RpcSendQueue): Promise {
await sender.visitLeftPadded(after, q);
}
}, sourceFileType);
} else if (kind === J.Kind.Container) {
RpcCodecs.registerCodec(kind, {
async rpcReceive(before: J.Container, q: RpcReceiveQueue): Promise> {
return (await receiver.visitContainer(before, q))!;
},
async rpcSend(after: J.Container, q: RpcSendQueue): Promise {
await sender.visitContainer(after, q);
}
}, sourceFileType);
} else {
RpcCodecs.registerCodec(kind as string, {
async rpcReceive(before: J, q: RpcReceiveQueue): Promise {
return (await receiver.visit(before, q))!;
},
async rpcSend(after: J, q: RpcSendQueue): Promise {
await sender.visit(after, q);
}
}, sourceFileType);
}
}
}
registerJLanguageCodecs(J.Kind.CompilationUnit, new JavaReceiver(), new JavaSender());