@openrewrite/rewrite 8.63.0 → 8.63.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/dist/java/index.d.ts +1 -0
  2. package/dist/java/index.d.ts.map +1 -1
  3. package/dist/java/index.js +1 -0
  4. package/dist/java/index.js.map +1 -1
  5. package/dist/java/rpc.d.ts +2 -0
  6. package/dist/java/rpc.d.ts.map +1 -1
  7. package/dist/java/rpc.js +749 -410
  8. package/dist/java/rpc.js.map +1 -1
  9. package/dist/java/tree.d.ts +1 -1
  10. package/dist/java/tree.d.ts.map +1 -1
  11. package/dist/java/type-visitor.d.ts +48 -0
  12. package/dist/java/type-visitor.d.ts.map +1 -0
  13. package/dist/java/type-visitor.js +260 -0
  14. package/dist/java/type-visitor.js.map +1 -0
  15. package/dist/java/type.d.ts +2 -0
  16. package/dist/java/type.d.ts.map +1 -1
  17. package/dist/java/type.js +0 -317
  18. package/dist/java/type.js.map +1 -1
  19. package/dist/java/visitor.d.ts.map +1 -1
  20. package/dist/java/visitor.js +579 -363
  21. package/dist/java/visitor.js.map +1 -1
  22. package/dist/javascript/rpc.js +430 -350
  23. package/dist/javascript/rpc.js.map +1 -1
  24. package/dist/javascript/tree.d.ts +1 -1
  25. package/dist/javascript/tree.d.ts.map +1 -1
  26. package/dist/javascript/type-mapping.d.ts.map +1 -1
  27. package/dist/javascript/type-mapping.js +7 -0
  28. package/dist/javascript/type-mapping.js.map +1 -1
  29. package/dist/javascript/visitor.d.ts.map +1 -1
  30. package/dist/javascript/visitor.js +504 -309
  31. package/dist/javascript/visitor.js.map +1 -1
  32. package/dist/json/visitor.d.ts.map +1 -1
  33. package/dist/json/visitor.js +46 -21
  34. package/dist/json/visitor.js.map +1 -1
  35. package/dist/rpc/queue.d.ts +7 -4
  36. package/dist/rpc/queue.d.ts.map +1 -1
  37. package/dist/rpc/queue.js +22 -32
  38. package/dist/rpc/queue.js.map +1 -1
  39. package/dist/rpc/request/generate.d.ts.map +1 -1
  40. package/dist/rpc/request/generate.js +2 -3
  41. package/dist/rpc/request/generate.js.map +1 -1
  42. package/dist/rpc/request/get-languages.d.ts.map +1 -1
  43. package/dist/rpc/request/get-languages.js +4 -3
  44. package/dist/rpc/request/get-languages.js.map +1 -1
  45. package/dist/rpc/request/get-object.d.ts +1 -1
  46. package/dist/rpc/request/get-object.d.ts.map +1 -1
  47. package/dist/rpc/request/get-object.js +8 -7
  48. package/dist/rpc/request/get-object.js.map +1 -1
  49. package/dist/rpc/request/get-recipes.d.ts.map +1 -1
  50. package/dist/rpc/request/get-recipes.js +2 -2
  51. package/dist/rpc/request/get-recipes.js.map +1 -1
  52. package/dist/rpc/request/index.d.ts +1 -0
  53. package/dist/rpc/request/index.d.ts.map +1 -1
  54. package/dist/rpc/request/index.js +1 -0
  55. package/dist/rpc/request/index.js.map +1 -1
  56. package/dist/rpc/request/install-recipes.d.ts.map +1 -1
  57. package/dist/rpc/request/install-recipes.js +2 -3
  58. package/dist/rpc/request/install-recipes.js.map +1 -1
  59. package/dist/rpc/request/metrics.d.ts +10 -10
  60. package/dist/rpc/request/metrics.d.ts.map +1 -1
  61. package/dist/rpc/request/metrics.js +38 -31
  62. package/dist/rpc/request/metrics.js.map +1 -1
  63. package/dist/rpc/request/parse.d.ts.map +1 -1
  64. package/dist/rpc/request/parse.js +10 -12
  65. package/dist/rpc/request/parse.js.map +1 -1
  66. package/dist/rpc/request/prepare-recipe.d.ts.map +1 -1
  67. package/dist/rpc/request/prepare-recipe.js +4 -4
  68. package/dist/rpc/request/prepare-recipe.js.map +1 -1
  69. package/dist/rpc/request/print.d.ts +1 -1
  70. package/dist/rpc/request/print.d.ts.map +1 -1
  71. package/dist/rpc/request/print.js +10 -6
  72. package/dist/rpc/request/print.js.map +1 -1
  73. package/dist/rpc/request/trace-get-object.d.ts +5 -0
  74. package/dist/rpc/request/trace-get-object.d.ts.map +1 -0
  75. package/dist/rpc/request/trace-get-object.js +3 -0
  76. package/dist/rpc/request/trace-get-object.js.map +1 -0
  77. package/dist/rpc/request/visit.d.ts.map +1 -1
  78. package/dist/rpc/request/visit.js +2 -3
  79. package/dist/rpc/request/visit.js.map +1 -1
  80. package/dist/rpc/rewrite-rpc.d.ts +2 -3
  81. package/dist/rpc/rewrite-rpc.d.ts.map +1 -1
  82. package/dist/rpc/rewrite-rpc.js +13 -5
  83. package/dist/rpc/rewrite-rpc.js.map +1 -1
  84. package/dist/rpc/server.d.ts.map +1 -1
  85. package/dist/rpc/server.js +9 -38
  86. package/dist/rpc/server.js.map +1 -1
  87. package/dist/rpc/trace.d.ts +1 -1
  88. package/dist/rpc/trace.d.ts.map +1 -1
  89. package/dist/rpc/trace.js +3 -3
  90. package/dist/rpc/trace.js.map +1 -1
  91. package/dist/util.d.ts +6 -0
  92. package/dist/util.d.ts.map +1 -1
  93. package/dist/util.js +14 -0
  94. package/dist/util.js.map +1 -1
  95. package/dist/version.txt +1 -1
  96. package/package.json +1 -1
  97. package/src/java/index.ts +1 -0
  98. package/src/java/rpc.ts +726 -537
  99. package/src/java/tree.ts +1 -1
  100. package/src/java/type-visitor.ts +241 -0
  101. package/src/java/type.ts +13 -277
  102. package/src/java/visitor.ts +581 -378
  103. package/src/javascript/rpc.ts +431 -360
  104. package/src/javascript/tree.ts +1 -1
  105. package/src/javascript/type-mapping.ts +7 -0
  106. package/src/javascript/visitor.ts +505 -310
  107. package/src/json/visitor.ts +47 -22
  108. package/src/rpc/queue.ts +20 -17
  109. package/src/rpc/request/generate.ts +31 -25
  110. package/src/rpc/request/get-languages.ts +18 -10
  111. package/src/rpc/request/get-object.ts +42 -34
  112. package/src/rpc/request/get-recipes.ts +15 -8
  113. package/src/rpc/request/index.ts +1 -0
  114. package/src/rpc/request/install-recipes.ts +65 -59
  115. package/src/rpc/request/metrics.ts +54 -48
  116. package/src/rpc/request/parse.ts +31 -25
  117. package/src/rpc/request/prepare-recipe.ts +31 -23
  118. package/src/rpc/request/print.ts +28 -14
  119. package/src/rpc/request/trace-get-object.ts +4 -0
  120. package/src/rpc/request/visit.ts +22 -16
  121. package/src/rpc/rewrite-rpc.ts +22 -10
  122. package/src/rpc/server.ts +10 -45
  123. package/src/rpc/trace.ts +3 -3
  124. package/src/util.ts +14 -0
  125. package/dist/rpc/chrome-profiler.d.ts +0 -25
  126. package/dist/rpc/chrome-profiler.d.ts.map +0 -1
  127. package/dist/rpc/chrome-profiler.js +0 -405
  128. package/dist/rpc/chrome-profiler.js.map +0 -1
  129. package/src/rpc/chrome-profiler.ts +0 -373
package/src/java/rpc.ts CHANGED
@@ -16,12 +16,250 @@
16
16
  import {JavaVisitor} from "./visitor";
17
17
  import {asRef, RpcCodecs, RpcReceiveQueue, RpcSendQueue} from "../rpc";
18
18
  import {Expression, isSpace, J, TextComment} from "./tree";
19
- import {produceAsync} from "../visitor";
20
- import {createDraft, Draft, finishDraft, WritableDraft} from "immer";
21
19
  import {isTree} from "../tree";
22
20
  import {Type} from "./type";
21
+ import {TypeVisitor} from "./type-visitor";
22
+ import {updateIfChanged} from "../util";
23
23
  import Space = J.Space;
24
24
 
25
+ class TypeSender extends TypeVisitor<RpcSendQueue> {
26
+ protected async visitPrimitive(primitive: Type.Primitive, q: RpcSendQueue): Promise<Type | undefined> {
27
+ await q.getAndSend(primitive, p => p.keyword);
28
+ return primitive;
29
+ }
30
+
31
+ protected async visitClass(cls: Type.Class, q: RpcSendQueue): Promise<Type | undefined> {
32
+ await q.getAndSend(cls, c => c.flags);
33
+ await q.getAndSend(cls, c => c.classKind);
34
+ await q.getAndSend(cls, c => c.fullyQualifiedName);
35
+ await q.getAndSendList(cls, c => (c.typeParameters || []).map(t => asRef(t)), t => Type.signature(t), t => this.visit(t, q));
36
+ await q.getAndSend(cls, c => asRef(c.supertype), st => this.visit(st, q));
37
+ await q.getAndSend(cls, c => asRef(c.owningClass), oc => this.visit(oc, q));
38
+ await q.getAndSendList(cls, c => (c.annotations || []).map(a => asRef(a)), t => Type.signature(t), a => this.visit(a, q));
39
+ await q.getAndSendList(cls, c => (c.interfaces || []).map(i => asRef(i)), t => Type.signature(t), i => this.visit(i, q));
40
+ await q.getAndSendList(cls, c => (c.members || []).map(m => asRef(m)), t => Type.signature(t), m => this.visit(m, q));
41
+ await q.getAndSendList(cls, c => (c.methods || []).map(m => asRef(m)), t => Type.signature(t), m => this.visit(m, q));
42
+ return cls;
43
+ }
44
+
45
+ protected async visitVariable(variable: Type.Variable, q: RpcSendQueue): Promise<Type | undefined> {
46
+ await q.getAndSend(variable, v => v.name);
47
+ await q.getAndSend(variable, v => v.owner ? asRef(v.owner) : undefined, owner => this.visit(owner, q));
48
+ await q.getAndSend(variable, v => asRef(v.type), t => this.visit(t, q));
49
+ await q.getAndSendList(variable, v => (v.annotations || []).map(v2 => asRef(v2)), t => Type.signature(t), a => this.visit(a, q));
50
+ return variable;
51
+ }
52
+
53
+ protected async visitAnnotation(annotation: Type.Annotation, q: RpcSendQueue): Promise<Type | undefined> {
54
+ await q.getAndSend(annotation, a => asRef(a.type), t => this.visit(t, q));
55
+ // await q.getAndSendList(annotation, a => (a.values || []).map(v => asRef(v)), v => {
56
+ // let value: any;
57
+ // if (v.kind === Type.Kind.SingleElementValue) {
58
+ // const single = v as Type.Annotation.SingleElementValue;
59
+ // value = single.constantValue !== undefined ? single.constantValue : single.referenceValue;
60
+ // } else {
61
+ // const array = v as Type.Annotation.ArrayElementValue;
62
+ // value = array.constantValues || array.referenceValues;
63
+ // }
64
+ // return `${Type.signature(v.element)}:${value == null ? "null" : value.toString()}`;
65
+ // }, async v => {
66
+ // // Handle element values inline like the Java implementation
67
+ // await q.getAndSend(v, e => asRef(e.element), elem => this.visit(elem, q));
68
+ // if (v.kind === Type.Kind.SingleElementValue) {
69
+ // const single = v as Type.Annotation.SingleElementValue;
70
+ // await q.getAndSend(single, s => s.constantValue);
71
+ // await q.getAndSend(single, s => asRef(s.referenceValue), ref => this.visit(ref, q));
72
+ // } else if (v.kind === Type.Kind.ArrayElementValue) {
73
+ // const array = v as Type.Annotation.ArrayElementValue;
74
+ // await q.getAndSendList(array, a => a.constantValues || [], val => val == null ? "null" : val.toString());
75
+ // await q.getAndSendList(array, a => (a.referenceValues || []).map(r => asRef(r)), t => Type.signature(t), r => this.visit(r, q));
76
+ // }
77
+ // });
78
+ return annotation;
79
+ }
80
+
81
+ protected async visitMethod(method: Type.Method, q: RpcSendQueue): Promise<Type | undefined> {
82
+ await q.getAndSend(method, m => asRef(m.declaringType), dt => this.visit(dt, q));
83
+ await q.getAndSend(method, m => m.name);
84
+ await q.getAndSend(method, m => m.flags);
85
+ await q.getAndSend(method, m => asRef(m.returnType), rt => this.visit(rt, q));
86
+ await q.getAndSendList(method, m => m.parameterNames || [], v => v);
87
+ await q.getAndSendList(method, m => (m.parameterTypes || []).map(t => asRef(t)), t => Type.signature(t), pt => this.visit(pt, q));
88
+ await q.getAndSendList(method, m => (m.thrownExceptions || []).map(t => asRef(t)), t => Type.signature(t), et => this.visit(et, q));
89
+ await q.getAndSendList(method, m => (m.annotations || []).map(a => asRef(a)), t => Type.signature(t), a => this.visit(a, q));
90
+ await q.getAndSendList(method, m => m.defaultValue || undefined, v => v);
91
+ await q.getAndSendList(method, m => m.declaredFormalTypeNames || [], v => v);
92
+ return method;
93
+ }
94
+
95
+ protected async visitArray(array: Type.Array, q: RpcSendQueue): Promise<Type | undefined> {
96
+ await q.getAndSend(array, a => asRef(a.elemType), et => this.visit(et, q));
97
+ await q.getAndSendList(array, a => (a.annotations || []).map(ann => asRef(ann)), t => Type.signature(t), ann => this.visit(ann, q));
98
+ return array;
99
+ }
100
+
101
+ protected async visitParameterized(parameterized: Type.Parameterized, q: RpcSendQueue): Promise<Type | undefined> {
102
+ await q.getAndSend(parameterized, p => asRef(p.type), t => this.visit(t, q));
103
+ await q.getAndSendList(parameterized, p => (p.typeParameters || []).map(tp => asRef(tp)), t => Type.signature(t), tp => this.visit(tp, q));
104
+ return parameterized;
105
+ }
106
+
107
+ protected async visitGenericTypeVariable(generic: Type.GenericTypeVariable, q: RpcSendQueue): Promise<Type | undefined> {
108
+ await q.getAndSend(generic, g => g.name);
109
+ // Convert TypeScript enum to Java enum string
110
+ await q.getAndSend(generic, g => {
111
+ switch (g.variance) {
112
+ case Type.GenericTypeVariable.Variance.Covariant:
113
+ return 'COVARIANT';
114
+ case Type.GenericTypeVariable.Variance.Contravariant:
115
+ return 'CONTRAVARIANT';
116
+ case Type.GenericTypeVariable.Variance.Invariant:
117
+ default:
118
+ return 'INVARIANT';
119
+ }
120
+ });
121
+ await q.getAndSendList(generic, g => (g.bounds || []).map(b => asRef(b)), t => Type.signature(t), b => this.visit(b, q));
122
+ return generic;
123
+ }
124
+
125
+ protected async visitUnion(union: Type.Union, q: RpcSendQueue): Promise<Type | undefined> {
126
+ await q.getAndSendList(union, u => (u.bounds || []).map(b => asRef(b)), t => Type.signature(t), b => this.visit(b, q));
127
+ return union;
128
+ }
129
+
130
+ protected async visitIntersection(intersection: Type.Intersection, q: RpcSendQueue): Promise<Type | undefined> {
131
+ await q.getAndSendList(intersection, i => (i.bounds || []).map(b => asRef(b)), t => Type.signature(t), b => this.visit(b, q));
132
+ return intersection;
133
+ }
134
+ }
135
+
136
+ class TypeReceiver extends TypeVisitor<RpcReceiveQueue> {
137
+ async preVisit(_type: Type, _q: RpcReceiveQueue): Promise<Type | undefined> {
138
+ // Don't call default preVisit to avoid circular references
139
+ return _type;
140
+ }
141
+
142
+ async postVisit(_type: Type, _q: RpcReceiveQueue): Promise<Type | undefined> {
143
+ // Don't call default postVisit to avoid circular references
144
+ return _type;
145
+ }
146
+
147
+ protected async visitPrimitive(primitive: Type.Primitive, q: RpcReceiveQueue): Promise<Type | undefined> {
148
+ const keyword: string = await q.receive(primitive.keyword);
149
+ return Type.Primitive.fromKeyword(keyword)!;
150
+ }
151
+
152
+ protected async visitClass(cls: Type.Class, q: RpcReceiveQueue): Promise<Type | undefined> {
153
+ cls.flags = await q.receive(cls.flags);
154
+ cls.classKind = await q.receive(cls.classKind);
155
+ cls.fullyQualifiedName = await q.receive(cls.fullyQualifiedName);
156
+ cls.typeParameters = await q.receiveList(cls.typeParameters, tp => this.visit(tp, q)) || [];
157
+ cls.supertype = await q.receive(cls.supertype, st => this.visit(st, q));
158
+ cls.owningClass = await q.receive(cls.owningClass, oc => this.visit(oc, q));
159
+ cls.annotations = await q.receiveList(cls.annotations, a => this.visit(a, q)) || [];
160
+ cls.interfaces = await q.receiveList(cls.interfaces, i => this.visit(i, q)) || [];
161
+ cls.members = await q.receiveList(cls.members, m => this.visit(m, q)) || [];
162
+ cls.methods = await q.receiveList(cls.methods, m => this.visit(m, q)) || [];
163
+ return cls;
164
+ }
165
+
166
+ protected async visitVariable(variable: Type.Variable, q: RpcReceiveQueue): Promise<Type | undefined> {
167
+ variable.name = await q.receive(variable.name);
168
+ variable.owner = await q.receive(variable.owner, owner => this.visit(owner, q));
169
+ variable.type = await q.receive(variable.type, t => this.visit(t, q));
170
+ variable.annotations = await q.receiveList(variable.annotations, a => this.visit(a, q)) || [];
171
+ return variable;
172
+ }
173
+
174
+ protected async visitAnnotation(annotation: Type.Annotation, q: RpcReceiveQueue): Promise<Type | undefined> {
175
+ annotation.type = await q.receive(annotation.type, t => this.visit(t, q));
176
+ // annotation.values = await q.receiveList(annotation.values, async v => {
177
+ // // Handle element values inline like the Java implementation
178
+ // if (v.kind === Type.Kind.SingleElementValue) {
179
+ // const single = v as Type.Annotation.SingleElementValue;
180
+ // const element = await q.receive(single.element, elem => this.visit(elem, q));
181
+ // const constantValue = await q.receive(single.constantValue);
182
+ // const referenceValue = await q.receive(single.referenceValue, ref => this.visit(ref, q));
183
+ // return {
184
+ // kind: Type.Kind.SingleElementValue,
185
+ // element,
186
+ // constantValue,
187
+ // referenceValue
188
+ // } as Type.Annotation.SingleElementValue;
189
+ // } else if (v.kind === Type.Kind.ArrayElementValue) {
190
+ // const array = v as Type.Annotation.ArrayElementValue;
191
+ // const element = await q.receive(array.element, elem => this.visit(elem, q));
192
+ // const constantValues = await q.receiveList(array.constantValues);
193
+ // const referenceValues = await q.receiveList(array.referenceValues, r => this.visit(r, q));
194
+ // return {
195
+ // kind: Type.Kind.ArrayElementValue,
196
+ // element,
197
+ // constantValues,
198
+ // referenceValues
199
+ // } as Type.Annotation.ArrayElementValue;
200
+ // }
201
+ // return v;
202
+ // }) || [];
203
+ return annotation;
204
+ }
205
+
206
+ protected async visitMethod(method: Type.Method, q: RpcReceiveQueue): Promise<Type | undefined> {
207
+ method.declaringType = await q.receive(method.declaringType, dt => this.visit(dt, q));
208
+ method.name = await q.receive(method.name);
209
+ method.flags = await q.receive(method.flags);
210
+ method.returnType = await q.receive(method.returnType, rt => this.visit(rt, q));
211
+ method.parameterNames = await q.receiveList(method.parameterNames) || [];
212
+ method.parameterTypes = await q.receiveList(method.parameterTypes, pt => this.visit(pt, q)) || [];
213
+ method.thrownExceptions = await q.receiveList(method.thrownExceptions, et => this.visit(et, q)) || [];
214
+ method.annotations = await q.receiveList(method.annotations, a => this.visit(a, q)) || [];
215
+ method.defaultValue = await q.receiveList(method.defaultValue);
216
+ method.declaredFormalTypeNames = await q.receiveList(method.declaredFormalTypeNames) || [];
217
+ return method;
218
+ }
219
+
220
+ protected async visitArray(array: Type.Array, q: RpcReceiveQueue): Promise<Type | undefined> {
221
+ array.elemType = await q.receive(array.elemType, et => this.visit(et, q));
222
+ array.annotations = await q.receiveList(array.annotations, ann => this.visit(ann, q)) || [];
223
+ return array;
224
+ }
225
+
226
+ protected async visitParameterized(parameterized: Type.Parameterized, q: RpcReceiveQueue): Promise<Type | undefined> {
227
+ parameterized.type = await q.receive(parameterized.type, t => this.visit(t, q));
228
+ parameterized.typeParameters = await q.receiveList(parameterized.typeParameters, tp => this.visit(tp, q)) || [];
229
+ return parameterized;
230
+ }
231
+
232
+ protected async visitGenericTypeVariable(generic: Type.GenericTypeVariable, q: RpcReceiveQueue): Promise<Type | undefined> {
233
+ generic.name = await q.receive(generic.name);
234
+ const varianceStr = await q.receive(generic.variance) as any as string;
235
+ // Convert Java enum string to TypeScript enum
236
+ switch (varianceStr) {
237
+ case 'COVARIANT':
238
+ generic.variance = Type.GenericTypeVariable.Variance.Covariant;
239
+ break;
240
+ case 'CONTRAVARIANT':
241
+ generic.variance = Type.GenericTypeVariable.Variance.Contravariant;
242
+ break;
243
+ case 'INVARIANT':
244
+ default:
245
+ generic.variance = Type.GenericTypeVariable.Variance.Invariant;
246
+ break;
247
+ }
248
+ generic.bounds = await q.receiveList(generic.bounds, b => this.visit(b, q)) || [];
249
+ return generic;
250
+ }
251
+
252
+ protected async visitUnion(union: Type.Union, q: RpcReceiveQueue): Promise<Type | undefined> {
253
+ union.bounds = await q.receiveList(union.bounds, b => this.visit(b, q)) || [];
254
+ return union;
255
+ }
256
+
257
+ protected async visitIntersection(intersection: Type.Intersection, q: RpcReceiveQueue): Promise<Type | undefined> {
258
+ intersection.bounds = await q.receiveList(intersection.bounds, b => this.visit(b, q)) || [];
259
+ return intersection;
260
+ }
261
+ }
262
+
25
263
  export class JavaSender extends JavaVisitor<RpcSendQueue> {
26
264
 
27
265
  protected async preVisit(j: J, q: RpcSendQueue): Promise<J | undefined> {
@@ -574,10 +812,14 @@ export class JavaSender extends JavaVisitor<RpcSendQueue> {
574
812
  return container;
575
813
  }
576
814
 
815
+ private static typeVisitor = new TypeSender();
816
+
577
817
  public override async visitType(javaType: Type | undefined, q: RpcSendQueue): Promise<Type | undefined> {
578
- const codec = RpcCodecs.forInstance(javaType);
579
- await codec?.rpcSend(javaType, q);
580
- return javaType;
818
+ if (!javaType) {
819
+ return undefined;
820
+ }
821
+
822
+ return await JavaSender.typeVisitor.visit(javaType, q);
581
823
  }
582
824
  }
583
825
 
@@ -585,158 +827,153 @@ export class JavaReceiver extends JavaVisitor<RpcReceiveQueue> {
585
827
 
586
828
  protected async preVisit(j: J, q: RpcReceiveQueue): Promise<J | undefined> {
587
829
  try {
588
- const draft = createDraft(j);
589
-
590
- draft.id = await q.receive(j.id);
591
- draft.prefix = await q.receive(j.prefix, space => this.visitSpace(space, q));
592
- draft.markers = await q.receive(j.markers);
593
-
594
- return finishDraft(draft);
830
+ const updates = {
831
+ id: await q.receive(j.id),
832
+ prefix: await q.receive(j.prefix, space => this.visitSpace(space, q)),
833
+ markers: await q.receive(j.markers)
834
+ };
835
+ return updateIfChanged(j, updates);
595
836
  } catch (e: any) {
596
837
  throw e;
597
838
  }
598
839
  }
599
840
 
600
841
  protected async visitAnnotatedType(annotatedType: J.AnnotatedType, q: RpcReceiveQueue): Promise<J | undefined> {
601
- const draft = createDraft(annotatedType);
602
-
603
- draft.annotations = await q.receiveListDefined(annotatedType.annotations, annot => this.visit(annot, q));
604
- draft.typeExpression = await q.receive(annotatedType.typeExpression, type => this.visit(type, q));
605
-
606
- return finishDraft(draft);
842
+ const updates = {
843
+ annotations: await q.receiveListDefined(annotatedType.annotations, annot => this.visit(annot, q)),
844
+ typeExpression: await q.receive(annotatedType.typeExpression, type => this.visit(type, q))
845
+ };
846
+ return updateIfChanged(annotatedType, updates);
607
847
  }
608
848
 
609
849
  protected async visitAnnotation(annotation: J.Annotation, q: RpcReceiveQueue): Promise<J | undefined> {
610
- const draft = createDraft(annotation);
611
-
612
- draft.annotationType = await q.receive(annotation.annotationType, type => this.visit(type, q));
613
- draft.arguments = await q.receive(annotation.arguments, args => this.visitContainer(args, q));
614
-
615
- return finishDraft(draft);
850
+ const updates = {
851
+ annotationType: await q.receive(annotation.annotationType, type => this.visit(type, q)),
852
+ arguments: await q.receive(annotation.arguments, args => this.visitContainer(args, q))
853
+ };
854
+ return updateIfChanged(annotation, updates);
616
855
  }
617
856
 
618
857
  protected async visitArrayAccess(arrayAccess: J.ArrayAccess, q: RpcReceiveQueue): Promise<J | undefined> {
619
- const draft = createDraft(arrayAccess);
620
-
621
- draft.indexed = await q.receive(arrayAccess.indexed, indexed => this.visit(indexed, q));
622
- draft.dimension = await q.receive(arrayAccess.dimension, dim => this.visit(dim, q));
623
-
624
- return finishDraft(draft);
858
+ const updates = {
859
+ indexed: await q.receive(arrayAccess.indexed, indexed => this.visit(indexed, q)),
860
+ dimension: await q.receive(arrayAccess.dimension, dim => this.visit(dim, q))
861
+ };
862
+ return updateIfChanged(arrayAccess, updates);
625
863
  }
626
864
 
627
865
  protected async visitArrayDimension(dimension: J.ArrayDimension, q: RpcReceiveQueue): Promise<J | undefined> {
628
- const draft = createDraft(dimension);
629
-
630
- draft.index = await q.receive(dimension.index, idx => this.visitRightPadded(idx, q));
631
-
632
- return finishDraft(draft);
866
+ const updates = {
867
+ index: await q.receive(dimension.index, idx => this.visitRightPadded(idx, q))
868
+ };
869
+ return updateIfChanged(dimension, updates);
633
870
  }
634
871
 
635
872
  protected async visitArrayType(arrayType: J.ArrayType, q: RpcReceiveQueue): Promise<J | undefined> {
636
- const draft = createDraft(arrayType);
637
-
638
- draft.elementType = await q.receive(arrayType.elementType, type => this.visit(type, q));
639
- draft.annotations = await q.receiveListDefined(arrayType.annotations || [], annot => this.visit(annot, q));
640
- draft.dimension = await q.receive(arrayType.dimension, d => this.visitLeftPadded(d, q));
641
- draft.type = await q.receive(arrayType.type, type => this.visitType(type, q));
873
+ const updates = {
874
+ elementType: await q.receive(arrayType.elementType, type => this.visit(type, q)),
875
+ annotations: await q.receiveListDefined(arrayType.annotations || [], annot => this.visit(annot, q)),
876
+ dimension: await q.receive(arrayType.dimension, d => this.visitLeftPadded(d, q)),
877
+ type: await q.receive(arrayType.type, type => this.visitType(type, q))
878
+ };
642
879
 
643
- return finishDraft(draft);
880
+ return updateIfChanged(arrayType, updates);
644
881
  }
645
882
 
646
883
  protected async visitAssert(assert: J.Assert, q: RpcReceiveQueue): Promise<J | undefined> {
647
- const draft = createDraft(assert);
648
-
649
- draft.condition = await q.receive(assert.condition, cond => this.visit(cond, q));
650
- draft.detail = await q.receive(assert.detail, detail => this.visitOptionalLeftPadded(detail, q));
884
+ const updates = {
885
+ condition: await q.receive(assert.condition, cond => this.visit(cond, q)),
886
+ detail: await q.receive(assert.detail, detail => this.visitOptionalLeftPadded(detail, q))
887
+ };
651
888
 
652
- return finishDraft(draft);
889
+ return updateIfChanged(assert, updates);
653
890
  }
654
891
 
655
892
  protected async visitAssignment(assignment: J.Assignment, q: RpcReceiveQueue): Promise<J | undefined> {
656
- const draft = createDraft(assignment);
893
+ const updates = {
894
+ variable: await q.receive(assignment.variable, variable => this.visit(variable, q)),
895
+ assignment: await q.receive(assignment.assignment, assign => this.visitLeftPadded(assign, q)),
896
+ type: await q.receive(assignment.type, type => this.visitType(type, q))
897
+ };
657
898
 
658
- draft.variable = await q.receive(assignment.variable, variable => this.visit(variable, q));
659
- draft.assignment = await q.receive(assignment.assignment, assign => this.visitLeftPadded(assign, q));
660
- draft.type = await q.receive(assignment.type, type => this.visitType(type, q));
661
-
662
- return finishDraft(draft);
899
+ return updateIfChanged(assignment, updates);
663
900
  }
664
901
 
665
902
  protected async visitAssignmentOperation(assignOp: J.AssignmentOperation, q: RpcReceiveQueue): Promise<J | undefined> {
666
- const draft = createDraft(assignOp);
667
-
668
- draft.variable = await q.receive(assignOp.variable, variable => this.visit(variable, q));
669
- draft.operator = await q.receive(assignOp.operator, op => this.visitLeftPadded(op, q));
670
- draft.assignment = await q.receive(assignOp.assignment, assign => this.visit(assign, q));
671
- draft.type = await q.receive(assignOp.type, type => this.visitType(type, q));
903
+ const updates = {
904
+ variable: await q.receive(assignOp.variable, variable => this.visit(variable, q)),
905
+ operator: await q.receive(assignOp.operator, op => this.visitLeftPadded(op, q)),
906
+ assignment: await q.receive(assignOp.assignment, assign => this.visit(assign, q)),
907
+ type: await q.receive(assignOp.type, type => this.visitType(type, q))
908
+ };
672
909
 
673
- return finishDraft(draft);
910
+ return updateIfChanged(assignOp, updates);
674
911
  }
675
912
 
676
913
  protected async visitBinary(binary: J.Binary, q: RpcReceiveQueue): Promise<J | undefined> {
677
- const draft = createDraft(binary);
678
-
679
- draft.left = await q.receive(binary.left, left => this.visit(left, q));
680
- draft.operator = await q.receive(binary.operator, op => this.visitLeftPadded(op, q));
681
- draft.right = await q.receive(binary.right, right => this.visit(right, q));
682
- draft.type = await q.receive(binary.type, type => this.visitType(type, q));
914
+ const updates = {
915
+ left: await q.receive(binary.left, left => this.visit(left, q)),
916
+ operator: await q.receive(binary.operator, op => this.visitLeftPadded(op, q)),
917
+ right: await q.receive(binary.right, right => this.visit(right, q)),
918
+ type: await q.receive(binary.type, type => this.visitType(type, q))
919
+ };
683
920
 
684
- return finishDraft(draft);
921
+ return updateIfChanged(binary, updates);
685
922
  }
686
923
 
687
924
  protected async visitBreak(breakStmt: J.Break, q: RpcReceiveQueue): Promise<J | undefined> {
688
- const draft = createDraft(breakStmt);
925
+ const updates = {
926
+ label: await q.receive(breakStmt.label, label => this.visit(label, q))
927
+ };
689
928
 
690
- draft.label = await q.receive(breakStmt.label, label => this.visit(label, q));
691
-
692
- return finishDraft(draft);
929
+ return updateIfChanged(breakStmt, updates);
693
930
  }
694
931
 
695
932
  protected async visitCase(caseStmt: J.Case, q: RpcReceiveQueue): Promise<J | undefined> {
696
- const draft = createDraft(caseStmt);
697
-
698
- draft.type = await q.receive(caseStmt.type);
699
- draft.caseLabels = await q.receive(caseStmt.caseLabels, labels => this.visitContainer(labels, q));
700
- draft.statements = await q.receive(caseStmt.statements, stmts => this.visitContainer(stmts, q));
701
- draft.body = await q.receive(caseStmt.body, body => this.visitRightPadded(body, q));
702
- draft.guard = await q.receive(caseStmt.guard, guard => this.visit(guard, q));
933
+ const updates = {
934
+ type: await q.receive(caseStmt.type),
935
+ caseLabels: await q.receive(caseStmt.caseLabels, labels => this.visitContainer(labels, q)),
936
+ statements: await q.receive(caseStmt.statements, stmts => this.visitContainer(stmts, q)),
937
+ body: await q.receive(caseStmt.body, body => this.visitRightPadded(body, q)),
938
+ guard: await q.receive(caseStmt.guard, guard => this.visit(guard, q))
939
+ };
703
940
 
704
- return finishDraft(draft);
941
+ return updateIfChanged(caseStmt, updates);
705
942
  }
706
943
 
707
944
  protected async visitContinue(continueStmt: J.Continue, q: RpcReceiveQueue): Promise<J | undefined> {
708
- const draft = createDraft(continueStmt);
709
-
710
- draft.label = await q.receive(continueStmt.label, label => this.visit(label, q));
945
+ const updates = {
946
+ label: await q.receive(continueStmt.label, label => this.visit(label, q))
947
+ };
711
948
 
712
- return finishDraft(draft);
949
+ return updateIfChanged(continueStmt, updates);
713
950
  }
714
951
 
715
952
  protected async visitControlParentheses<T extends J>(controlParens: J.ControlParentheses<T>, q: RpcReceiveQueue): Promise<J | undefined> {
716
- const draft = createDraft(controlParens);
953
+ const updates = {
954
+ tree: await q.receive(controlParens.tree, tree => this.visitRightPadded(tree, q))
955
+ };
717
956
 
718
- draft.tree = await q.receive(controlParens.tree, tree => this.visitRightPadded(tree, q)) as unknown as WritableDraft<J.RightPadded<T>>;
719
-
720
- return finishDraft(draft);
957
+ return updateIfChanged(controlParens, updates);
721
958
  }
722
959
 
723
960
  protected async visitDeconstructionPattern(pattern: J.DeconstructionPattern, q: RpcReceiveQueue): Promise<J | undefined> {
724
- const draft = createDraft(pattern);
725
-
726
- draft.deconstructor = await q.receive(pattern.deconstructor, deconstructor => this.visit(deconstructor, q));
727
- draft.nested = await q.receive(pattern.nested, nested => this.visitContainer(nested, q));
728
- draft.type = await q.receive(pattern.type, type => this.visitType(type, q));
961
+ const updates = {
962
+ deconstructor: await q.receive(pattern.deconstructor, deconstructor => this.visit(deconstructor, q)),
963
+ nested: await q.receive(pattern.nested, nested => this.visitContainer(nested, q)),
964
+ type: await q.receive(pattern.type, type => this.visitType(type, q))
965
+ };
729
966
 
730
- return finishDraft(draft);
967
+ return updateIfChanged(pattern, updates);
731
968
  }
732
969
 
733
970
  protected async visitDoWhileLoop(doWhile: J.DoWhileLoop, q: RpcReceiveQueue): Promise<J | undefined> {
734
- const draft = createDraft(doWhile);
735
-
736
- draft.body = await q.receive(doWhile.body, body => this.visitOptionalRightPadded(body, q));
737
- draft.whileCondition = await q.receive(doWhile.whileCondition, cond => this.visitLeftPadded(cond, q));
971
+ const updates = {
972
+ body: await q.receive(doWhile.body, body => this.visitOptionalRightPadded(body, q)),
973
+ whileCondition: await q.receive(doWhile.whileCondition, cond => this.visitLeftPadded(cond, q))
974
+ };
738
975
 
739
- return finishDraft(draft);
976
+ return updateIfChanged(doWhile, updates);
740
977
  }
741
978
 
742
979
  protected async visitEmpty(empty: J.Empty): Promise<J | undefined> {
@@ -745,577 +982,532 @@ export class JavaReceiver extends JavaVisitor<RpcReceiveQueue> {
745
982
  }
746
983
 
747
984
  protected async visitEnumValueSet(enumValueSet: J.EnumValueSet, q: RpcReceiveQueue): Promise<J | undefined> {
748
- const draft = createDraft(enumValueSet);
985
+ const updates = {
986
+ enums: await q.receiveListDefined(enumValueSet.enums, enumValue => this.visitRightPadded(enumValue, q)),
987
+ terminatedWithSemicolon: await q.receive(enumValueSet.terminatedWithSemicolon)
988
+ };
749
989
 
750
- draft.enums = await q.receiveListDefined(enumValueSet.enums, enumValue => this.visitRightPadded(enumValue, q));
751
- draft.terminatedWithSemicolon = await q.receive(enumValueSet.terminatedWithSemicolon);
752
-
753
- return finishDraft(draft);
990
+ return updateIfChanged(enumValueSet, updates);
754
991
  }
755
992
 
756
993
  protected async visitEnumValue(enumValue: J.EnumValue, q: RpcReceiveQueue): Promise<J | undefined> {
757
- const draft = createDraft(enumValue);
758
-
759
- draft.annotations = await q.receiveListDefined(enumValue.annotations, annot => this.visit(annot, q));
760
- draft.name = await q.receive(enumValue.name, name => this.visit(name, q));
761
- draft.initializer = await q.receive(enumValue.initializer, init => this.visit(init, q));
994
+ const updates = {
995
+ annotations: await q.receiveListDefined(enumValue.annotations, annot => this.visit(annot, q)),
996
+ name: await q.receive(enumValue.name, name => this.visit(name, q)),
997
+ initializer: await q.receive(enumValue.initializer, init => this.visit(init, q))
998
+ };
762
999
 
763
- return finishDraft(draft);
1000
+ return updateIfChanged(enumValue, updates);
764
1001
  }
765
1002
 
766
1003
  protected async visitErroneous(erroneous: J.Erroneous, q: RpcReceiveQueue): Promise<J | undefined> {
767
- const draft = createDraft(erroneous);
768
-
769
- draft.text = await q.receive(erroneous.text);
1004
+ const updates = {
1005
+ text: await q.receive(erroneous.text)
1006
+ };
770
1007
 
771
- return finishDraft(draft);
1008
+ return updateIfChanged(erroneous, updates);
772
1009
  }
773
1010
 
774
1011
  protected async visitFieldAccess(fieldAccess: J.FieldAccess, q: RpcReceiveQueue): Promise<J | undefined> {
775
- const draft = createDraft(fieldAccess);
1012
+ const updates = {
1013
+ target: await q.receive(fieldAccess.target, target => this.visit(target, q)),
1014
+ name: await q.receive(fieldAccess.name, name => this.visitLeftPadded(name, q)),
1015
+ type: await q.receive(fieldAccess.type, type => this.visitType(type, q))
1016
+ };
776
1017
 
777
- draft.target = await q.receive(fieldAccess.target, target => this.visit(target, q));
778
- draft.name = await q.receive(fieldAccess.name, name => this.visitLeftPadded(name, q));
779
- draft.type = await q.receive(fieldAccess.type, type => this.visitType(type, q));
780
-
781
- return finishDraft(draft);
1018
+ return updateIfChanged(fieldAccess, updates);
782
1019
  }
783
1020
 
784
1021
  protected async visitForEachLoop(forEachLoop: J.ForEachLoop, q: RpcReceiveQueue): Promise<J | undefined> {
785
- const draft = createDraft(forEachLoop);
786
-
787
- draft.control = await q.receive(forEachLoop.control, c => this.visit(c, q));
788
- draft.body = await q.receive(forEachLoop.body, body => this.visitRightPadded(body, q));
1022
+ const updates = {
1023
+ control: await q.receive(forEachLoop.control, c => this.visit(c, q)),
1024
+ body: await q.receive(forEachLoop.body, body => this.visitRightPadded(body, q))
1025
+ };
789
1026
 
790
- return finishDraft(draft);
1027
+ return updateIfChanged(forEachLoop, updates);
791
1028
  }
792
1029
 
793
1030
  protected async visitForEachLoopControl(control: J.ForEachLoop.Control, q: RpcReceiveQueue): Promise<J | undefined> {
794
- const draft = createDraft(control);
795
-
796
- draft.variable = await q.receive(control.variable, variable => this.visitRightPadded(variable, q));
797
- draft.iterable = await q.receive(control.iterable, expr => this.visitRightPadded(expr, q));
1031
+ const updates = {
1032
+ variable: await q.receive(control.variable, variable => this.visitRightPadded(variable, q)),
1033
+ iterable: await q.receive(control.iterable, expr => this.visitRightPadded(expr, q))
1034
+ };
798
1035
 
799
- return finishDraft(draft);
1036
+ return updateIfChanged(control, updates);
800
1037
  }
801
1038
 
802
1039
  protected async visitForLoop(forLoop: J.ForLoop, q: RpcReceiveQueue): Promise<J | undefined> {
803
- const draft = createDraft(forLoop);
1040
+ const updates = {
1041
+ control: await q.receive(forLoop.control, c => this.visit(c, q)),
1042
+ body: await q.receive(forLoop.body, body => this.visitRightPadded(body, q))
1043
+ };
804
1044
 
805
- draft.control = await q.receive(forLoop.control, c => this.visit(c, q));
806
- draft.body = await q.receive(forLoop.body, body => this.visitRightPadded(body, q));
807
-
808
- return finishDraft(draft);
1045
+ return updateIfChanged(forLoop, updates);
809
1046
  }
810
1047
 
811
1048
  protected async visitForLoopControl(control: J.ForLoop.Control, q: RpcReceiveQueue): Promise<J | undefined> {
812
- const draft = createDraft(control);
813
-
814
- draft.init = await q.receiveListDefined(control.init, init => this.visitRightPadded(init, q));
815
- draft.condition = await q.receive(control.condition, cond => this.visitRightPadded(cond, q));
816
- draft.update = await q.receiveListDefined(control.update, update => this.visitRightPadded(update, q));
1049
+ const updates = {
1050
+ init: await q.receiveListDefined(control.init, init => this.visitRightPadded(init, q)),
1051
+ condition: await q.receive(control.condition, cond => this.visitRightPadded(cond, q)),
1052
+ update: await q.receiveListDefined(control.update, update => this.visitRightPadded(update, q))
1053
+ };
817
1054
 
818
- return finishDraft(draft);
1055
+ return updateIfChanged(control, updates);
819
1056
  }
820
1057
 
821
1058
  protected async visitIf(ifStmt: J.If, q: RpcReceiveQueue): Promise<J | undefined> {
822
- const draft = createDraft(ifStmt);
823
-
824
- draft.ifCondition = await q.receive(ifStmt.ifCondition, cond => this.visit(cond, q));
825
- draft.thenPart = await q.receive(ifStmt.thenPart, thenPart => this.visitRightPadded(thenPart, q));
826
- draft.elsePart = await q.receive(ifStmt.elsePart, elsePart => this.visit(elsePart, q));
1059
+ const updates = {
1060
+ ifCondition: await q.receive(ifStmt.ifCondition, cond => this.visit(cond, q)),
1061
+ thenPart: await q.receive(ifStmt.thenPart, thenPart => this.visitRightPadded(thenPart, q)),
1062
+ elsePart: await q.receive(ifStmt.elsePart, elsePart => this.visit(elsePart, q))
1063
+ };
827
1064
 
828
- return finishDraft(draft);
1065
+ return updateIfChanged(ifStmt, updates);
829
1066
  }
830
1067
 
831
1068
  protected async visitElse(ifElse: J.If.Else, q: RpcReceiveQueue): Promise<J | undefined> {
832
- const draft = createDraft(ifElse);
1069
+ const updates = {
1070
+ body: await q.receive(ifElse.body, body => this.visitRightPadded(body, q))
1071
+ };
833
1072
 
834
- draft.body = await q.receive(ifElse.body, body => this.visitRightPadded(body, q));
835
-
836
- return finishDraft(draft);
1073
+ return updateIfChanged(ifElse, updates);
837
1074
  }
838
1075
 
839
1076
  protected async visitImport(importStmt: J.Import, q: RpcReceiveQueue): Promise<J | undefined> {
840
- const draft = createDraft(importStmt);
841
-
842
- draft.static = await q.receive(importStmt.static, s => this.visitLeftPadded(s, q));
843
- draft.qualid = await q.receive(importStmt.qualid, qualid => this.visit(qualid, q));
844
- draft.alias = await q.receive(importStmt.alias, alias => this.visitLeftPadded(alias, q));
1077
+ const updates = {
1078
+ static: await q.receive(importStmt.static, s => this.visitLeftPadded(s, q)),
1079
+ qualid: await q.receive(importStmt.qualid, qualid => this.visit(qualid, q)),
1080
+ alias: await q.receive(importStmt.alias, alias => this.visitLeftPadded(alias, q))
1081
+ };
845
1082
 
846
- return finishDraft(draft);
1083
+ return updateIfChanged(importStmt, updates);
847
1084
  }
848
1085
 
849
1086
  protected async visitInstanceOf(instanceOf: J.InstanceOf, q: RpcReceiveQueue): Promise<J | undefined> {
850
- const draft = createDraft(instanceOf);
851
-
852
- draft.expression = await q.receive(instanceOf.expression, expr => this.visitRightPadded(expr, q));
853
- draft.class = await q.receive(instanceOf.class, clazz => this.visit(clazz, q));
854
- draft.pattern = await q.receive(instanceOf.pattern, pattern => this.visit(pattern, q));
855
- draft.type = await q.receive(instanceOf.type, type => this.visitType(type, q));
856
- draft.modifier = await q.receive(instanceOf.modifier, mod => this.visit(mod, q));
857
-
858
- return finishDraft(draft);
1087
+ const updates = {
1088
+ expression: await q.receive(instanceOf.expression, expr => this.visitRightPadded(expr, q)),
1089
+ class: await q.receive(instanceOf.class, clazz => this.visit(clazz, q)),
1090
+ pattern: await q.receive(instanceOf.pattern, pattern => this.visit(pattern, q)),
1091
+ modifier: await q.receive(instanceOf.modifier, mod => this.visit(mod, q)),
1092
+ type: await q.receive(instanceOf.type, type => this.visitType(type, q))
1093
+ };
1094
+ return updateIfChanged(instanceOf, updates);
859
1095
  }
860
1096
 
861
1097
  protected async visitIntersectionType(intersectionType: J.IntersectionType, q: RpcReceiveQueue): Promise<J | undefined> {
862
- const draft = createDraft(intersectionType);
863
-
864
- draft.bounds = await q.receive(intersectionType.bounds, bounds => this.visitContainer(bounds, q));
865
-
866
- return finishDraft(draft);
1098
+ const updates = {
1099
+ bounds: await q.receive(intersectionType.bounds, bounds => this.visitContainer(bounds, q))
1100
+ };
1101
+ return updateIfChanged(intersectionType, updates);
867
1102
  }
868
1103
 
869
1104
  protected async visitLabel(label: J.Label, q: RpcReceiveQueue): Promise<J | undefined> {
870
- const draft = createDraft(label);
871
-
872
- draft.label = await q.receive(label.label, lbl => this.visitRightPadded(lbl, q));
873
- draft.statement = await q.receive(label.statement, stmt => this.visit(stmt, q));
874
-
875
- return finishDraft(draft);
1105
+ const updates = {
1106
+ label: await q.receive(label.label, lbl => this.visitRightPadded(lbl, q)),
1107
+ statement: await q.receive(label.statement, stmt => this.visit(stmt, q))
1108
+ };
1109
+ return updateIfChanged(label, updates);
876
1110
  }
877
1111
 
878
1112
  protected async visitLambda(lambda: J.Lambda, q: RpcReceiveQueue): Promise<J | undefined> {
879
- const draft = createDraft(lambda);
880
-
881
- draft.parameters = await q.receive(lambda.parameters, params => this.visit(params, q));
882
- draft.arrow = await q.receive(lambda.arrow, arrow => this.visitSpace(arrow, q));
883
- draft.body = await q.receive(lambda.body, body => this.visit(body, q));
884
- draft.type = await q.receive(lambda.type, type => this.visitType(type, q));
885
-
886
- return finishDraft(draft);
1113
+ const updates = {
1114
+ parameters: await q.receive(lambda.parameters, params => this.visit(params, q)),
1115
+ arrow: await q.receive(lambda.arrow, arrow => this.visitSpace(arrow, q)),
1116
+ body: await q.receive(lambda.body, body => this.visit(body, q)),
1117
+ type: await q.receive(lambda.type, type => this.visitType(type, q))
1118
+ };
1119
+ return updateIfChanged(lambda, updates);
887
1120
  }
888
1121
 
889
1122
  protected async visitLambdaParameters(params: J.Lambda.Parameters, q: RpcReceiveQueue): Promise<J | undefined> {
890
- const draft = createDraft(params);
891
-
892
- draft.parenthesized = await q.receive(params.parenthesized);
893
- draft.parameters = await q.receiveListDefined(params.parameters, param => this.visitRightPadded(param, q));
894
-
895
- return finishDraft(draft);
1123
+ const updates = {
1124
+ parenthesized: await q.receive(params.parenthesized),
1125
+ parameters: await q.receiveListDefined(params.parameters, param => this.visitRightPadded(param, q))
1126
+ };
1127
+ return updateIfChanged(params, updates);
896
1128
  }
897
1129
 
898
1130
  protected async visitLiteral(literal: J.Literal, q: RpcReceiveQueue): Promise<J | undefined> {
899
- const draft = createDraft(literal);
900
-
901
- draft.value = await q.receive(literal.value);
902
- draft.valueSource = await q.receive(literal.valueSource);
903
- draft.unicodeEscapes = await q.receiveList(literal.unicodeEscapes);
904
- draft.type = await q.receive(literal.type, type => this.visitType(type, q) as unknown as Type.Primitive);
905
-
906
- return finishDraft(draft);
1131
+ const updates = {
1132
+ value: await q.receive(literal.value),
1133
+ valueSource: await q.receive(literal.valueSource),
1134
+ unicodeEscapes: await q.receiveList(literal.unicodeEscapes),
1135
+ type: await q.receive(literal.type, type => this.visitType(type, q) as unknown as Type.Primitive)
1136
+ };
1137
+ return updateIfChanged(literal, updates);
907
1138
  }
908
1139
 
909
1140
  protected async visitMemberReference(memberRef: J.MemberReference, q: RpcReceiveQueue): Promise<J | undefined> {
910
- const draft = createDraft(memberRef);
911
-
912
- draft.containing = await q.receive(memberRef.containing, container => this.visitRightPadded(container, q));
913
- draft.typeParameters = await q.receive(memberRef.typeParameters, typeParams => this.visitContainer(typeParams, q));
914
- draft.reference = await q.receive(memberRef.reference, ref => this.visitLeftPadded(ref, q));
915
- draft.type = await q.receive(memberRef.type, type => this.visitType(type, q));
916
- draft.methodType = await q.receive(memberRef.methodType, type => this.visitType(type, q) as unknown as Type.Method);
917
- draft.variableType = await q.receive(memberRef.variableType, type => this.visitType(type, q) as unknown as Type.Variable);
918
-
919
- return finishDraft(draft);
1141
+ const updates = {
1142
+ containing: await q.receive(memberRef.containing, container => this.visitRightPadded(container, q)),
1143
+ typeParameters: await q.receive(memberRef.typeParameters, typeParams => this.visitContainer(typeParams, q)),
1144
+ reference: await q.receive(memberRef.reference, ref => this.visitLeftPadded(ref, q)),
1145
+ type: await q.receive(memberRef.type, type => this.visitType(type, q)),
1146
+ methodType: await q.receive(memberRef.methodType, type => this.visitType(type, q) as unknown as Type.Method),
1147
+ variableType: await q.receive(memberRef.variableType, type => this.visitType(type, q) as unknown as Type.Variable)
1148
+ };
1149
+ return updateIfChanged(memberRef, updates);
920
1150
  }
921
1151
 
922
1152
  protected async visitMethodInvocation(methodInvoc: J.MethodInvocation, q: RpcReceiveQueue): Promise<J | undefined> {
923
- const draft = createDraft(methodInvoc);
924
-
925
- draft.select = await q.receive(methodInvoc.select, select => this.visitRightPadded(select, q));
926
- draft.typeParameters = await q.receive(methodInvoc.typeParameters, typeParams => this.visitContainer(typeParams, q));
927
- draft.name = await q.receive(methodInvoc.name, name => this.visit(name, q));
928
- draft.arguments = await q.receive(methodInvoc.arguments, args => this.visitContainer(args, q));
929
- draft.methodType = await q.receive(methodInvoc.methodType, type => this.visitType(type, q) as unknown as Type.Method);
930
-
931
- return finishDraft(draft);
1153
+ const updates = {
1154
+ select: await q.receive(methodInvoc.select, select => this.visitRightPadded(select, q)),
1155
+ typeParameters: await q.receive(methodInvoc.typeParameters, typeParams => this.visitContainer(typeParams, q)),
1156
+ name: await q.receive(methodInvoc.name, name => this.visit(name, q)),
1157
+ arguments: await q.receive(methodInvoc.arguments, args => this.visitContainer(args, q)),
1158
+ methodType: await q.receive(methodInvoc.methodType, type => this.visitType(type, q) as unknown as Type.Method)
1159
+ };
1160
+ return updateIfChanged(methodInvoc, updates);
932
1161
  }
933
1162
 
934
1163
  protected async visitModifier(modifier: J.Modifier, q: RpcReceiveQueue): Promise<J | undefined> {
935
- const draft = createDraft(modifier);
936
-
937
- draft.keyword = await q.receive(modifier.keyword);
938
- draft.type = await q.receive(modifier.type);
939
- draft.annotations = await q.receiveListDefined(modifier.annotations, annot => this.visit(annot, q));
940
-
941
- return finishDraft(draft);
1164
+ const updates = {
1165
+ keyword: await q.receive(modifier.keyword),
1166
+ type: await q.receive(modifier.type),
1167
+ annotations: await q.receiveListDefined(modifier.annotations, annot => this.visit(annot, q))
1168
+ };
1169
+ return updateIfChanged(modifier, updates);
942
1170
  }
943
1171
 
944
1172
  protected async visitMultiCatch(multiCatch: J.MultiCatch, q: RpcReceiveQueue): Promise<J | undefined> {
945
- const draft = createDraft(multiCatch);
946
-
947
- draft.alternatives = await q.receiveListDefined(multiCatch.alternatives, alt => this.visitRightPadded(alt, q));
948
-
949
- return finishDraft(draft);
1173
+ const updates = {
1174
+ alternatives: await q.receiveListDefined(multiCatch.alternatives, alt => this.visitRightPadded(alt, q))
1175
+ };
1176
+ return updateIfChanged(multiCatch, updates);
950
1177
  }
951
1178
 
952
1179
  protected async visitNewArray(newArray: J.NewArray, q: RpcReceiveQueue): Promise<J | undefined> {
953
- const draft = createDraft(newArray);
954
-
955
- draft.typeExpression = await q.receive(newArray.typeExpression, type => this.visit(type, q));
956
- draft.dimensions = await q.receiveListDefined(newArray.dimensions, dim => this.visit(dim, q));
957
- draft.initializer = await q.receive(newArray.initializer, init => this.visitContainer(init, q));
958
- draft.type = await q.receive(newArray.type, type => this.visitType(type, q));
959
-
960
- return finishDraft(draft);
1180
+ const updates = {
1181
+ typeExpression: await q.receive(newArray.typeExpression, type => this.visit(type, q)),
1182
+ dimensions: await q.receiveListDefined(newArray.dimensions, dim => this.visit(dim, q)),
1183
+ initializer: await q.receive(newArray.initializer, init => this.visitContainer(init, q)),
1184
+ type: await q.receive(newArray.type, type => this.visitType(type, q))
1185
+ };
1186
+ return updateIfChanged(newArray, updates);
961
1187
  }
962
1188
 
963
1189
  protected async visitNewClass(newClass: J.NewClass, q: RpcReceiveQueue): Promise<J | undefined> {
964
- const draft = createDraft(newClass);
965
-
966
- draft.enclosing = await q.receive(newClass.enclosing, encl => this.visitRightPadded(encl, q));
967
- draft.new = await q.receive(newClass.new, new_ => this.visitSpace(new_, q));
968
- draft.class = await q.receive(newClass.class, clazz => this.visit(clazz, q));
969
- draft.arguments = await q.receive(newClass.arguments, args => this.visitContainer(args, q));
970
- draft.body = await q.receive(newClass.body, body => this.visit(body, q));
971
- draft.constructorType = await q.receive(newClass.constructorType, type => this.visitType(type, q) as unknown as Type.Method);
972
-
973
- return finishDraft(draft);
1190
+ const updates = {
1191
+ enclosing: await q.receive(newClass.enclosing, encl => this.visitRightPadded(encl, q)),
1192
+ new: await q.receive(newClass.new, new_ => this.visitSpace(new_, q)),
1193
+ class: await q.receive(newClass.class, clazz => this.visit(clazz, q)),
1194
+ arguments: await q.receive(newClass.arguments, args => this.visitContainer(args, q)),
1195
+ body: await q.receive(newClass.body, body => this.visit(body, q)),
1196
+ constructorType: await q.receive(newClass.constructorType, type => this.visitType(type, q) as unknown as Type.Method)
1197
+ };
1198
+ return updateIfChanged(newClass, updates);
974
1199
  }
975
1200
 
976
1201
  protected async visitNullableType(nullableType: J.NullableType, q: RpcReceiveQueue): Promise<J | undefined> {
977
- const draft = createDraft(nullableType);
978
-
979
- draft.annotations = await q.receiveListDefined(nullableType.annotations, annot => this.visit(annot, q));
980
- draft.typeTree = await q.receive(nullableType.typeTree, type => this.visitRightPadded(type, q));
981
-
982
- return finishDraft(draft);
1202
+ const updates = {
1203
+ annotations: await q.receiveListDefined(nullableType.annotations, annot => this.visit(annot, q)),
1204
+ typeTree: await q.receive(nullableType.typeTree, type => this.visitRightPadded(type, q))
1205
+ };
1206
+ return updateIfChanged(nullableType, updates);
983
1207
  }
984
1208
 
985
1209
  protected async visitParameterizedType(paramType: J.ParameterizedType, q: RpcReceiveQueue): Promise<J | undefined> {
986
- const draft = createDraft(paramType);
987
-
988
- draft.class = await q.receive(paramType.class, clazz => this.visit(clazz, q));
989
- draft.typeParameters = await q.receive(paramType.typeParameters, params => this.visitContainer(params, q));
990
- draft.type = await q.receive(paramType.type, type => this.visitType(type, q));
991
-
992
- return finishDraft(draft);
1210
+ const updates = {
1211
+ class: await q.receive(paramType.class, clazz => this.visit(clazz, q)),
1212
+ typeParameters: await q.receive(paramType.typeParameters, params => this.visitContainer(params, q)),
1213
+ type: await q.receive(paramType.type, type => this.visitType(type, q))
1214
+ };
1215
+ return updateIfChanged(paramType, updates);
993
1216
  }
994
1217
 
995
1218
  protected async visitParentheses<T extends J>(parentheses: J.Parentheses<T>, q: RpcReceiveQueue): Promise<J | undefined> {
996
- const draft = createDraft(parentheses);
997
-
998
- draft.tree = await q.receive(parentheses.tree, tree =>
999
- this.visitRightPadded(tree, q)) as unknown as WritableDraft<J.RightPadded<T>>;
1000
-
1001
- return finishDraft(draft);
1219
+ const updates = {
1220
+ tree: await q.receive(parentheses.tree, tree => this.visitRightPadded(tree, q))
1221
+ };
1222
+ return updateIfChanged(parentheses, updates);
1002
1223
  }
1003
1224
 
1004
1225
  protected async visitParenthesizedTypeTree(parenthesizedType: J.ParenthesizedTypeTree, q: RpcReceiveQueue): Promise<J | undefined> {
1005
- const draft = createDraft(parenthesizedType);
1006
-
1007
- draft.annotations = await q.receiveListDefined(parenthesizedType.annotations, annot => this.visit(annot, q));
1008
- draft.parenthesizedType = await q.receive(parenthesizedType.parenthesizedType, tree => this.visit(tree, q));
1009
-
1010
- return finishDraft(draft);
1226
+ const updates = {
1227
+ annotations: await q.receiveListDefined(parenthesizedType.annotations, annot => this.visit(annot, q)),
1228
+ parenthesizedType: await q.receive(parenthesizedType.parenthesizedType, tree => this.visit(tree, q))
1229
+ };
1230
+ return updateIfChanged(parenthesizedType, updates);
1011
1231
  }
1012
1232
 
1013
1233
  protected async visitPrimitive(primitive: J.Primitive, q: RpcReceiveQueue): Promise<J | undefined> {
1014
- const draft = createDraft(primitive);
1015
-
1016
- draft.type = await q.receive(primitive.type, type => this.visitType(type, q) as unknown as Type.Primitive);
1017
-
1018
- return finishDraft(draft);
1234
+ const updates = {
1235
+ type: await q.receive(primitive.type, type => this.visitType(type, q) as unknown as Type.Primitive)
1236
+ };
1237
+ return updateIfChanged(primitive, updates);
1019
1238
  }
1020
1239
 
1021
1240
  protected async visitSwitch(switchStmt: J.Switch, q: RpcReceiveQueue): Promise<J | undefined> {
1022
- const draft = createDraft(switchStmt);
1023
-
1024
- draft.selector = await q.receive(switchStmt.selector, selector => this.visit(selector, q));
1025
- draft.cases = await q.receive(switchStmt.cases, cases => this.visit(cases, q));
1026
-
1027
- return finishDraft(draft);
1241
+ const updates = {
1242
+ selector: await q.receive(switchStmt.selector, selector => this.visit(selector, q)),
1243
+ cases: await q.receive(switchStmt.cases, cases => this.visit(cases, q))
1244
+ };
1245
+ return updateIfChanged(switchStmt, updates);
1028
1246
  }
1029
1247
 
1030
1248
  protected async visitSwitchExpression(switchExpr: J.SwitchExpression, q: RpcReceiveQueue): Promise<J | undefined> {
1031
- const draft = createDraft(switchExpr);
1032
-
1033
- draft.selector = await q.receive(switchExpr.selector, selector => this.visit(selector, q));
1034
- draft.cases = await q.receive(switchExpr.cases, cases => this.visit(cases, q));
1035
- draft.type = await q.receive(switchExpr.type, type => this.visitType(type, q));
1036
-
1037
- return finishDraft(draft);
1249
+ const updates = {
1250
+ selector: await q.receive(switchExpr.selector, selector => this.visit(selector, q)),
1251
+ cases: await q.receive(switchExpr.cases, cases => this.visit(cases, q)),
1252
+ type: await q.receive(switchExpr.type, type => this.visitType(type, q))
1253
+ };
1254
+ return updateIfChanged(switchExpr, updates);
1038
1255
  }
1039
1256
 
1040
1257
  protected async visitTernary(ternary: J.Ternary, q: RpcReceiveQueue): Promise<J | undefined> {
1041
- const draft = createDraft(ternary);
1042
-
1043
- draft.condition = await q.receive(ternary.condition, cond => this.visit(cond, q));
1044
- draft.truePart = await q.receive(ternary.truePart, truePart => this.visitLeftPadded(truePart, q));
1045
- draft.falsePart = await q.receive(ternary.falsePart, falsePart => this.visitLeftPadded(falsePart, q));
1046
- draft.type = await q.receive(ternary.type, type => this.visitType(type, q));
1047
-
1048
- return finishDraft(draft);
1258
+ const updates = {
1259
+ condition: await q.receive(ternary.condition, cond => this.visit(cond, q)),
1260
+ truePart: await q.receive(ternary.truePart, truePart => this.visitLeftPadded(truePart, q)),
1261
+ falsePart: await q.receive(ternary.falsePart, falsePart => this.visitLeftPadded(falsePart, q)),
1262
+ type: await q.receive(ternary.type, type => this.visitType(type, q))
1263
+ };
1264
+ return updateIfChanged(ternary, updates);
1049
1265
  }
1050
1266
 
1051
1267
  protected async visitThrow(throwStmt: J.Throw, q: RpcReceiveQueue): Promise<J | undefined> {
1052
- const draft = createDraft(throwStmt);
1053
-
1054
- draft.exception = await q.receive(throwStmt.exception, exception => this.visit(exception, q));
1055
-
1056
- return finishDraft(draft);
1268
+ const updates = {
1269
+ exception: await q.receive(throwStmt.exception, exception => this.visit(exception, q))
1270
+ };
1271
+ return updateIfChanged(throwStmt, updates);
1057
1272
  }
1058
1273
 
1059
1274
  protected async visitTry(tryStmt: J.Try, q: RpcReceiveQueue): Promise<J | undefined> {
1060
- const draft = createDraft(tryStmt);
1061
-
1062
- draft.resources = await q.receive(tryStmt.resources, resources => this.visitContainer(resources, q));
1063
- draft.body = await q.receive(tryStmt.body, body => this.visit(body, q));
1064
- draft.catches = await q.receiveListDefined(tryStmt.catches, catchBlock => this.visit(catchBlock, q));
1065
- draft.finally = await q.receive(tryStmt.finally, finallyBlock => this.visitOptionalLeftPadded(finallyBlock, q));
1066
-
1067
- return finishDraft(draft);
1275
+ const updates = {
1276
+ resources: await q.receive(tryStmt.resources, resources => this.visitContainer(resources, q)),
1277
+ body: await q.receive(tryStmt.body, body => this.visit(body, q)),
1278
+ catches: await q.receiveListDefined(tryStmt.catches, catchBlock => this.visit(catchBlock, q)),
1279
+ finally: await q.receive(tryStmt.finally, finallyBlock => this.visitOptionalLeftPadded(finallyBlock, q))
1280
+ };
1281
+ return updateIfChanged(tryStmt, updates);
1068
1282
  }
1069
1283
 
1070
1284
  protected async visitTryResource(resource: J.Try.Resource, q: RpcReceiveQueue): Promise<J | undefined> {
1071
- const draft = createDraft(resource);
1072
-
1073
- draft.variableDeclarations = await q.receive(resource.variableDeclarations, variables => this.visit(variables, q));
1074
- draft.terminatedWithSemicolon = await q.receive(resource.terminatedWithSemicolon);
1075
-
1076
- return finishDraft(draft);
1285
+ const updates = {
1286
+ variableDeclarations: await q.receive(resource.variableDeclarations, variables => this.visit(variables, q)),
1287
+ terminatedWithSemicolon: await q.receive(resource.terminatedWithSemicolon)
1288
+ };
1289
+ return updateIfChanged(resource, updates);
1077
1290
  }
1078
1291
 
1079
1292
  protected async visitTryCatch(tryCatch: J.Try.Catch, q: RpcReceiveQueue): Promise<J | undefined> {
1080
- const draft = createDraft(tryCatch);
1081
-
1082
- draft.parameter = await q.receive(tryCatch.parameter, param => this.visit(param, q));
1083
- draft.body = await q.receive(tryCatch.body, body => this.visit(body, q));
1084
-
1085
- return finishDraft(draft);
1293
+ const updates = {
1294
+ parameter: await q.receive(tryCatch.parameter, param => this.visit(param, q)),
1295
+ body: await q.receive(tryCatch.body, body => this.visit(body, q))
1296
+ };
1297
+ return updateIfChanged(tryCatch, updates);
1086
1298
  }
1087
1299
 
1088
1300
  protected async visitUnary(unary: J.Unary, q: RpcReceiveQueue): Promise<J | undefined> {
1089
- const draft = createDraft(unary);
1090
-
1091
- draft.operator = await q.receive(unary.operator, op => this.visitLeftPadded(op, q));
1092
- draft.expression = await q.receive(unary.expression, expr => this.visit(expr, q));
1093
- draft.type = await q.receive(unary.type, type => this.visitType(type, q));
1094
-
1095
- return finishDraft(draft);
1301
+ const updates = {
1302
+ operator: await q.receive(unary.operator, op => this.visitLeftPadded(op, q)),
1303
+ expression: await q.receive(unary.expression, expr => this.visit(expr, q)),
1304
+ type: await q.receive(unary.type, type => this.visitType(type, q))
1305
+ };
1306
+ return updateIfChanged(unary, updates);
1096
1307
  }
1097
1308
 
1098
1309
  protected async visitUnknown(unknown: J.Unknown, q: RpcReceiveQueue): Promise<J | undefined> {
1099
- const draft = createDraft(unknown);
1100
-
1101
- draft.source = await q.receive(unknown.source, source => this.visit(source, q));
1102
-
1103
- return finishDraft(draft);
1310
+ const updates = {
1311
+ source: await q.receive(unknown.source, source => this.visit(source, q))
1312
+ };
1313
+ return updateIfChanged(unknown, updates);
1104
1314
  }
1105
1315
 
1106
1316
  protected async visitUnknownSource(unknownSource: J.UnknownSource, q: RpcReceiveQueue): Promise<J | undefined> {
1107
- const draft = createDraft(unknownSource);
1108
-
1109
- draft.text = await q.receive(unknownSource.text);
1110
-
1111
- return finishDraft(draft);
1317
+ const updates = {
1318
+ text: await q.receive(unknownSource.text)
1319
+ };
1320
+ return updateIfChanged(unknownSource, updates);
1112
1321
  }
1113
1322
 
1114
1323
  protected async visitVariable(variable: J.VariableDeclarations.NamedVariable, q: RpcReceiveQueue): Promise<J | undefined> {
1115
- const draft = createDraft(variable);
1116
-
1117
- draft.name = await q.receive(variable.name, name => this.visit(name, q));
1118
- draft.dimensionsAfterName = await q.receiveListDefined(variable.dimensionsAfterName, dim => this.visitLeftPadded(dim, q));
1119
- draft.initializer = await q.receive(variable.initializer, init => this.visitOptionalLeftPadded(init, q));
1120
- draft.variableType = await q.receive(variable.variableType, type => this.visitType(type, q) as unknown as Type.Variable);
1121
-
1122
- return finishDraft(draft);
1324
+ const updates = {
1325
+ name: await q.receive(variable.name, name => this.visit(name, q)),
1326
+ dimensionsAfterName: await q.receiveListDefined(variable.dimensionsAfterName, dim => this.visitLeftPadded(dim, q)),
1327
+ initializer: await q.receive(variable.initializer, init => this.visitOptionalLeftPadded(init, q)),
1328
+ variableType: await q.receive(variable.variableType, type => this.visitType(type, q) as unknown as Type.Variable)
1329
+ };
1330
+ return updateIfChanged(variable, updates);
1123
1331
  }
1124
1332
 
1125
1333
  protected async visitYield(yieldStmt: J.Yield, q: RpcReceiveQueue): Promise<J | undefined> {
1126
- const draft = createDraft(yieldStmt);
1127
-
1128
- draft.implicit = await q.receive(yieldStmt.implicit);
1129
- draft.value = await q.receive(yieldStmt.value, value => this.visit(value, q));
1130
-
1131
- return finishDraft(draft);
1334
+ const updates = {
1335
+ implicit: await q.receive(yieldStmt.implicit),
1336
+ value: await q.receive(yieldStmt.value, value => this.visit(value, q))
1337
+ };
1338
+ return updateIfChanged(yieldStmt, updates);
1132
1339
  }
1133
1340
 
1134
1341
  protected async visitTypeParameters(typeParams: J.TypeParameters, q: RpcReceiveQueue): Promise<J | undefined> {
1135
- const draft = createDraft(typeParams);
1136
-
1137
- draft.annotations = await q.receiveListDefined(typeParams.annotations, annot => this.visit(annot, q));
1138
- draft.typeParameters = await q.receiveListDefined(typeParams.typeParameters, param => this.visitRightPadded(param, q));
1139
-
1140
- return finishDraft(draft);
1342
+ const updates = {
1343
+ annotations: await q.receiveListDefined(typeParams.annotations, annot => this.visit(annot, q)),
1344
+ typeParameters: await q.receiveListDefined(typeParams.typeParameters, param => this.visitRightPadded(param, q))
1345
+ };
1346
+ return updateIfChanged(typeParams, updates);
1141
1347
  }
1142
1348
 
1143
1349
  protected async visitReturn(returnStmt: J.Return, q: RpcReceiveQueue): Promise<J | undefined> {
1144
- const draft = createDraft(returnStmt);
1145
-
1146
- draft.expression = await q.receive(returnStmt.expression, expr => this.visit(expr, q));
1147
-
1148
- return finishDraft(draft);
1350
+ const updates = {
1351
+ expression: await q.receive(returnStmt.expression, expr => this.visit(expr, q))
1352
+ };
1353
+ return updateIfChanged(returnStmt, updates);
1149
1354
  }
1150
1355
 
1151
1356
  protected async visitSynchronized(synchronizedStmt: J.Synchronized, q: RpcReceiveQueue): Promise<J | undefined> {
1152
- const draft = createDraft(synchronizedStmt);
1153
-
1154
- draft.lock = await q.receive(synchronizedStmt.lock, lock => this.visit(lock, q));
1155
- draft.body = await q.receive(synchronizedStmt.body, body => this.visit(body, q));
1156
-
1157
- return finishDraft(draft);
1357
+ const updates = {
1358
+ lock: await q.receive(synchronizedStmt.lock, lock => this.visit(lock, q)),
1359
+ body: await q.receive(synchronizedStmt.body, body => this.visit(body, q))
1360
+ };
1361
+ return updateIfChanged(synchronizedStmt, updates);
1158
1362
  }
1159
1363
 
1160
1364
  protected async visitTypeCast(typeCast: J.TypeCast, q: RpcReceiveQueue): Promise<J | undefined> {
1161
- const draft = createDraft(typeCast);
1162
-
1163
- draft.class = await q.receive(typeCast.class, typeExpr => this.visit(typeExpr, q));
1164
- draft.expression = await q.receive(typeCast.expression, expr => this.visit(expr, q));
1165
-
1166
- return finishDraft(draft);
1365
+ const updates = {
1366
+ class: await q.receive(typeCast.class, typeExpr => this.visit(typeExpr, q)),
1367
+ expression: await q.receive(typeCast.expression, expr => this.visit(expr, q))
1368
+ };
1369
+ return updateIfChanged(typeCast, updates);
1167
1370
  }
1168
1371
 
1169
1372
  protected async visitTypeParameter(typeParameter: J.TypeParameter, q: RpcReceiveQueue): Promise<J | undefined> {
1170
- const draft = createDraft(typeParameter);
1171
-
1172
- draft.annotations = await q.receiveListDefined(typeParameter.annotations, annot => this.visit(annot, q));
1173
- draft.modifiers = await q.receiveListDefined(typeParameter.modifiers, annot => this.visit(annot, q));
1174
- draft.name = await q.receive(typeParameter.name, name => this.visit(name, q));
1175
- draft.bounds = await q.receive(typeParameter.bounds, bounds => this.visitContainer(bounds, q));
1176
-
1177
- return finishDraft(draft);
1373
+ const updates = {
1374
+ annotations: await q.receiveListDefined(typeParameter.annotations, annot => this.visit(annot, q)),
1375
+ modifiers: await q.receiveListDefined(typeParameter.modifiers, annot => this.visit(annot, q)),
1376
+ name: await q.receive(typeParameter.name, name => this.visit(name, q)),
1377
+ bounds: await q.receive(typeParameter.bounds, bounds => this.visitContainer(bounds, q))
1378
+ };
1379
+ return updateIfChanged(typeParameter, updates);
1178
1380
  }
1179
1381
 
1180
1382
  protected async visitWhileLoop(whileLoop: J.WhileLoop, q: RpcReceiveQueue): Promise<J | undefined> {
1181
- const draft = createDraft(whileLoop);
1182
-
1183
- draft.condition = await q.receive(whileLoop.condition, cond => this.visit(cond, q));
1184
- draft.body = await q.receive(whileLoop.body, body => this.visitOptionalRightPadded(body, q));
1185
-
1186
- return finishDraft(draft);
1383
+ const updates = {
1384
+ condition: await q.receive(whileLoop.condition, cond => this.visit(cond, q)),
1385
+ body: await q.receive(whileLoop.body, body => this.visitOptionalRightPadded(body, q))
1386
+ };
1387
+ return updateIfChanged(whileLoop, updates);
1187
1388
  }
1188
1389
 
1189
1390
  protected async visitWildcard(wildcard: J.Wildcard, q: RpcReceiveQueue): Promise<J | undefined> {
1190
- const draft = createDraft(wildcard);
1191
-
1192
- draft.bound = await q.receive(wildcard.bound, bound => this.visitLeftPadded(bound, q));
1193
- draft.boundedType = await q.receive(wildcard.boundedType, type => this.visit(type, q));
1194
-
1195
- return finishDraft(draft);
1391
+ const updates = {
1392
+ bound: await q.receive(wildcard.bound, bound => this.visitLeftPadded(bound, q)),
1393
+ boundedType: await q.receive(wildcard.boundedType, type => this.visit(type, q))
1394
+ };
1395
+ return updateIfChanged(wildcard, updates);
1196
1396
  }
1197
1397
 
1198
1398
  protected async visitCompilationUnit(cu: J.CompilationUnit, q: RpcReceiveQueue): Promise<J | undefined> {
1199
- const draft = createDraft(cu);
1200
-
1201
- draft.sourcePath = await q.receive(cu.sourcePath);
1202
- draft.charsetName = await q.receive(cu.charsetName);
1203
- draft.charsetBomMarked = await q.receive(cu.charsetBomMarked);
1204
- draft.checksum = await q.receive(cu.checksum);
1205
- draft.fileAttributes = await q.receive(cu.fileAttributes);
1206
- draft.packageDeclaration = await q.receive(cu.packageDeclaration, pkg => this.visitRightPadded(pkg, q));
1207
- draft.imports = await q.receiveListDefined(cu.imports, imp => this.visitRightPadded(imp, q));
1208
- draft.classes = await q.receiveListDefined(cu.classes, cls => this.visit(cls, q));
1209
- draft.eof = await q.receive(cu.eof, space => this.visitSpace(space, q));
1210
-
1211
- return finishDraft(draft);
1399
+ const updates = {
1400
+ sourcePath: await q.receive(cu.sourcePath),
1401
+ charsetName: await q.receive(cu.charsetName),
1402
+ charsetBomMarked: await q.receive(cu.charsetBomMarked),
1403
+ checksum: await q.receive(cu.checksum),
1404
+ fileAttributes: await q.receive(cu.fileAttributes),
1405
+ packageDeclaration: await q.receive(cu.packageDeclaration, pkg => this.visitRightPadded(pkg, q)),
1406
+ imports: await q.receiveListDefined(cu.imports, imp => this.visitRightPadded(imp, q)),
1407
+ classes: await q.receiveListDefined(cu.classes, cls => this.visit(cls, q)),
1408
+ eof: await q.receive(cu.eof, space => this.visitSpace(space, q))
1409
+ };
1410
+ return updateIfChanged(cu, updates);
1212
1411
  }
1213
1412
 
1214
1413
  protected async visitPackage(pkg: J.Package, q: RpcReceiveQueue): Promise<J | undefined> {
1215
- const draft = createDraft(pkg);
1216
-
1217
- draft.expression = await q.receive<Expression>(pkg.expression, expr => this.visit(expr, q));
1218
- draft.annotations = await q.receiveListDefined(pkg.annotations, annot => this.visit(annot, q));
1219
-
1220
- return finishDraft(draft);
1414
+ const updates = {
1415
+ expression: await q.receive<Expression>(pkg.expression, expr => this.visit(expr, q)),
1416
+ annotations: await q.receiveListDefined(pkg.annotations, annot => this.visit(annot, q))
1417
+ };
1418
+ return updateIfChanged(pkg, updates);
1221
1419
  }
1222
1420
 
1223
1421
  protected async visitClassDeclaration(cls: J.ClassDeclaration, q: RpcReceiveQueue): Promise<J | undefined> {
1224
- const draft = createDraft(cls);
1225
-
1226
- draft.leadingAnnotations = await q.receiveListDefined(cls.leadingAnnotations, annot => this.visit(annot, q));
1227
- draft.modifiers = await q.receiveListDefined(cls.modifiers, mod => this.visit(mod, q));
1228
- draft.classKind = await q.receive(cls.classKind, kind => this.visit(kind, q));
1229
- draft.name = await q.receive(cls.name, name => this.visit(name, q));
1230
- draft.typeParameters = await q.receive(cls.typeParameters, params => this.visitContainer(params, q));
1231
- draft.primaryConstructor = await q.receive(cls.primaryConstructor, cons => this.visitContainer(cons, q));
1232
- draft.extends = await q.receive(cls.extends, ext => this.visitLeftPadded(ext, q));
1233
- draft.implements = await q.receive(cls.implements, impl => this.visitContainer(impl, q));
1234
- draft.permitting = await q.receive(cls.permitting, perm => this.visitContainer(perm, q));
1235
- draft.body = await q.receive(cls.body, body => this.visit(body, q));
1236
-
1237
- return finishDraft(draft);
1422
+ const updates = {
1423
+ leadingAnnotations: await q.receiveListDefined(cls.leadingAnnotations, annot => this.visit(annot, q)),
1424
+ modifiers: await q.receiveListDefined(cls.modifiers, mod => this.visit(mod, q)),
1425
+ classKind: await q.receive(cls.classKind, kind => this.visit(kind, q)),
1426
+ name: await q.receive(cls.name, name => this.visit(name, q)),
1427
+ typeParameters: await q.receive(cls.typeParameters, params => this.visitContainer(params, q)),
1428
+ primaryConstructor: await q.receive(cls.primaryConstructor, cons => this.visitContainer(cons, q)),
1429
+ extends: await q.receive(cls.extends, ext => this.visitLeftPadded(ext, q)),
1430
+ implements: await q.receive(cls.implements, impl => this.visitContainer(impl, q)),
1431
+ permitting: await q.receive(cls.permitting, perm => this.visitContainer(perm, q)),
1432
+ body: await q.receive(cls.body, body => this.visit(body, q))
1433
+ };
1434
+ return updateIfChanged(cls, updates);
1238
1435
  }
1239
1436
 
1240
1437
  protected async visitClassDeclarationKind(kind: J.ClassDeclaration.Kind, q: RpcReceiveQueue): Promise<J | undefined> {
1241
- const draft = createDraft(kind);
1242
-
1243
- draft.annotations = await q.receiveListDefined(kind.annotations, annot => this.visit(annot, q));
1244
- draft.type = await q.receive(kind.type);
1245
-
1246
- return finishDraft(draft);
1438
+ const updates = {
1439
+ annotations: await q.receiveListDefined(kind.annotations, annot => this.visit(annot, q)),
1440
+ type: await q.receive(kind.type)
1441
+ };
1442
+ return updateIfChanged(kind, updates);
1247
1443
  }
1248
1444
 
1249
1445
  protected async visitBlock(block: J.Block, q: RpcReceiveQueue): Promise<J | undefined> {
1250
- const draft = createDraft(block);
1251
-
1252
- draft.static = await q.receive(block.static, s => this.visitRightPadded(s, q));
1253
- draft.statements = await q.receiveListDefined(block.statements, stmt => this.visitRightPadded(stmt, q));
1254
- draft.end = await q.receive(block.end, space => this.visitSpace(space, q));
1255
-
1256
- return finishDraft(draft);
1446
+ const updates = {
1447
+ static: await q.receive(block.static, s => this.visitRightPadded(s, q)),
1448
+ statements: await q.receiveListDefined(block.statements, stmt => this.visitRightPadded(stmt, q)),
1449
+ end: await q.receive(block.end, space => this.visitSpace(space, q))
1450
+ };
1451
+ return updateIfChanged(block, updates);
1257
1452
  }
1258
1453
 
1259
1454
  protected async visitMethodDeclaration(method: J.MethodDeclaration, q: RpcReceiveQueue): Promise<J | undefined> {
1260
- const draft = createDraft(method);
1261
-
1262
- draft.leadingAnnotations = await q.receiveListDefined(method.leadingAnnotations, annot => this.visit(annot, q));
1263
- draft.modifiers = await q.receiveListDefined(method.modifiers, mod => this.visit(mod, q));
1264
- draft.typeParameters = await q.receive(method.typeParameters, params => this.visit(params, q));
1265
- draft.returnTypeExpression = await q.receive(method.returnTypeExpression, type => this.visit(type, q));
1266
- draft.nameAnnotations = (await q.receiveList(method.nameAnnotations, name => this.visit(name, q)))!;
1267
- draft.name = await q.receive(method.name, name => this.visit(name, q));
1268
- draft.parameters = await q.receive(method.parameters, params => this.visitContainer(params, q));
1269
- draft.throws = await q.receive(method.throws, throws => this.visitContainer(throws, q));
1270
- draft.body = await q.receive(method.body, body => this.visit(body, q));
1271
- draft.defaultValue = await q.receive(method.defaultValue, def => this.visitLeftPadded(def, q));
1272
- draft.methodType = await q.receive(method.methodType, type => this.visitType(type, q) as unknown as Type.Method);
1273
-
1274
- return finishDraft(draft);
1455
+ const updates = {
1456
+ leadingAnnotations: await q.receiveListDefined(method.leadingAnnotations, annot => this.visit(annot, q)),
1457
+ modifiers: await q.receiveListDefined(method.modifiers, mod => this.visit(mod, q)),
1458
+ typeParameters: await q.receive(method.typeParameters, params => this.visit(params, q)),
1459
+ returnTypeExpression: await q.receive(method.returnTypeExpression, type => this.visit(type, q)),
1460
+ nameAnnotations: (await q.receiveList(method.nameAnnotations, name => this.visit(name, q)))!,
1461
+ name: await q.receive(method.name, name => this.visit(name, q)),
1462
+ parameters: await q.receive(method.parameters, params => this.visitContainer(params, q)),
1463
+ throws: await q.receive(method.throws, throws => this.visitContainer(throws, q)),
1464
+ body: await q.receive(method.body, body => this.visit(body, q)),
1465
+ defaultValue: await q.receive(method.defaultValue, def => this.visitLeftPadded(def, q)),
1466
+ methodType: await q.receive(method.methodType, type => this.visitType(type, q) as unknown as Type.Method)
1467
+ };
1468
+ return updateIfChanged(method, updates);
1275
1469
  }
1276
1470
 
1277
1471
  protected async visitVariableDeclarations(varDecls: J.VariableDeclarations, q: RpcReceiveQueue): Promise<J | undefined> {
1278
- const draft = createDraft(varDecls);
1279
-
1280
- draft.leadingAnnotations = await q.receiveListDefined(varDecls.leadingAnnotations, annot => this.visit(annot, q));
1281
- draft.modifiers = await q.receiveListDefined(varDecls.modifiers, mod => this.visit(mod, q));
1282
- draft.typeExpression = await q.receive(varDecls.typeExpression, type => this.visit(type, q));
1283
- draft.varargs = await q.receive(varDecls.varargs, space => this.visitSpace(space, q));
1284
- draft.variables = await q.receiveListDefined(varDecls.variables, variable => this.visitRightPadded(variable, q));
1285
-
1286
- return finishDraft(draft);
1472
+ const updates = {
1473
+ leadingAnnotations: await q.receiveListDefined(varDecls.leadingAnnotations, annot => this.visit(annot, q)),
1474
+ modifiers: await q.receiveListDefined(varDecls.modifiers, mod => this.visit(mod, q)),
1475
+ typeExpression: await q.receive(varDecls.typeExpression, type => this.visit(type, q)),
1476
+ varargs: await q.receive(varDecls.varargs, space => this.visitSpace(space, q)),
1477
+ variables: await q.receiveListDefined(varDecls.variables, variable => this.visitRightPadded(variable, q))
1478
+ };
1479
+ return updateIfChanged(varDecls, updates);
1287
1480
  }
1288
1481
 
1289
1482
  protected async visitIdentifier(ident: J.Identifier, q: RpcReceiveQueue): Promise<J | undefined> {
1290
- const draft = createDraft(ident);
1291
-
1292
- draft.annotations = await q.receiveListDefined(ident.annotations, annot => this.visit(annot, q));
1293
- draft.simpleName = await q.receive(ident.simpleName);
1294
- draft.type = await q.receive(ident.type, type => this.visitType(type, q));
1295
- draft.fieldType = await q.receive(ident.fieldType, type => this.visitType(type, q) as any as Type.Variable);
1296
-
1297
- return finishDraft(draft);
1483
+ const updates = {
1484
+ annotations: await q.receiveListDefined(ident.annotations, annot => this.visit(annot, q)),
1485
+ simpleName: await q.receive(ident.simpleName),
1486
+ type: await q.receive(ident.type, type => this.visitType(type, q)),
1487
+ fieldType: await q.receive(ident.fieldType, type => this.visitType(type, q) as any as Type.Variable)
1488
+ };
1489
+ return updateIfChanged(ident, updates);
1298
1490
  }
1299
1491
 
1300
1492
  public override async visitSpace(space: J.Space, q: RpcReceiveQueue): Promise<J.Space> {
1301
- const draft = createDraft(space);
1302
-
1303
- draft.comments = await q.receiveListDefined(space.comments, async c => {
1304
- if (c.kind === J.Kind.TextComment) {
1305
- const tc = c as TextComment;
1306
- return await produceAsync(tc, async draft => {
1307
- draft.multiline = await q.receive(tc.multiline);
1308
- draft.text = await q.receive(tc.text);
1309
- draft.suffix = await q.receive(c.suffix);
1310
- draft.markers = await q.receive(c.markers);
1311
- });
1312
- } else {
1313
- throw new Error(`Unexpected comment type ${c.kind}`);
1314
- }
1315
- });
1316
- draft.whitespace = await q.receive(space.whitespace);
1317
-
1318
- return finishDraft(draft);
1493
+ const updates = {
1494
+ comments: await q.receiveListDefined(space.comments, async c => {
1495
+ if (c.kind === J.Kind.TextComment) {
1496
+ const tc = c as TextComment;
1497
+ const commentUpdates = {
1498
+ multiline: await q.receive(tc.multiline),
1499
+ text: await q.receive(tc.text),
1500
+ suffix: await q.receive(c.suffix),
1501
+ markers: await q.receive(c.markers)
1502
+ };
1503
+ return updateIfChanged(tc, commentUpdates);
1504
+ } else {
1505
+ throw new Error(`Unexpected comment type ${c.kind}`);
1506
+ }
1507
+ }),
1508
+ whitespace: await q.receive(space.whitespace)
1509
+ };
1510
+ return updateIfChanged(space, updates);
1319
1511
  }
1320
1512
 
1321
1513
  public override async visitLeftPadded<T extends J | J.Space | number | string | boolean>(left: J.LeftPadded<T>, q: RpcReceiveQueue): Promise<J.LeftPadded<T>> {
@@ -1323,21 +1515,20 @@ export class JavaReceiver extends JavaVisitor<RpcReceiveQueue> {
1323
1515
  throw new Error("TreeDataReceiveQueue should have instantiated an empty left padding");
1324
1516
  }
1325
1517
 
1326
- const draft = createDraft(left);
1327
-
1328
- draft.before = await q.receive(left.before, space => this.visitSpace(space, q));
1329
- draft.element = await q.receive(left.element, elem => {
1330
- if (isSpace(elem)) {
1331
- return this.visitSpace(elem as J.Space, q) as any as T;
1332
- } else if (typeof elem === 'object' && elem.kind) {
1333
- // FIXME find a better way to check if it is a `Tree`
1334
- return this.visit(elem as J, q) as any as T;
1335
- }
1336
- return elem;
1337
- }) as Draft<T>;
1338
- draft.markers = await q.receive(left.markers);
1339
-
1340
- return finishDraft(draft) as J.LeftPadded<T>;
1518
+ const updates = {
1519
+ before: await q.receive(left.before, space => this.visitSpace(space, q)),
1520
+ element: await q.receive(left.element, elem => {
1521
+ if (isSpace(elem)) {
1522
+ return this.visitSpace(elem as J.Space, q) as any as T;
1523
+ } else if (typeof elem === 'object' && elem.kind) {
1524
+ // FIXME find a better way to check if it is a `Tree`
1525
+ return this.visit(elem as J, q) as any as T;
1526
+ }
1527
+ return elem;
1528
+ }),
1529
+ markers: await q.receive(left.markers)
1530
+ };
1531
+ return updateIfChanged(left, updates) as J.LeftPadded<T>;
1341
1532
  }
1342
1533
 
1343
1534
  public override async visitRightPadded<T extends J | boolean>(right: J.RightPadded<T>, q: RpcReceiveQueue): Promise<J.RightPadded<T>> {
@@ -1345,42 +1536,40 @@ export class JavaReceiver extends JavaVisitor<RpcReceiveQueue> {
1345
1536
  throw new Error("TreeDataReceiveQueue should have instantiated an empty right padding");
1346
1537
  }
1347
1538
 
1348
- const draft = createDraft(right);
1349
-
1350
- draft.element = await q.receive(right.element, elem => {
1351
- if (isSpace(elem)) {
1352
- return this.visitSpace(elem as J.Space, q) as any as T;
1353
- } else if (typeof elem === 'object' && elem.kind) {
1354
- // FIXME find a better way to check if it is a `Tree`
1355
- return this.visit(elem as J, q) as any as T;
1356
- }
1357
- return elem as any as T;
1358
- }) as Draft<T>;
1359
- draft.after = await q.receive(right.after, space => this.visitSpace(space, q));
1360
- draft.markers = await q.receive(right.markers);
1361
-
1362
- return finishDraft(draft) as J.RightPadded<T>;
1539
+ const updates = {
1540
+ element: await q.receive(right.element, elem => {
1541
+ if (isSpace(elem)) {
1542
+ return this.visitSpace(elem as J.Space, q) as any as T;
1543
+ } else if (typeof elem === 'object' && elem.kind) {
1544
+ // FIXME find a better way to check if it is a `Tree`
1545
+ return this.visit(elem as J, q) as any as T;
1546
+ }
1547
+ return elem as any as T;
1548
+ }),
1549
+ after: await q.receive(right.after, space => this.visitSpace(space, q)),
1550
+ markers: await q.receive(right.markers)
1551
+ };
1552
+ return updateIfChanged(right, updates) as J.RightPadded<T>;
1363
1553
  }
1364
1554
 
1365
1555
  public override async visitContainer<T extends J>(container: J.Container<T>, q: RpcReceiveQueue): Promise<J.Container<T>> {
1366
- const draft = createDraft(container);
1367
-
1368
- draft.before = await q.receive(container.before, space => this.visitSpace(space, q));
1369
- draft.elements = await q.receiveListDefined(container.elements, elem => this.visitRightPadded(elem, q)) as Draft<J.RightPadded<T>[]>;
1370
- draft.markers = await q.receive(container.markers);
1371
-
1372
- return finishDraft(draft) as J.Container<T>;
1556
+ const updates = {
1557
+ before: await q.receive(container.before, space => this.visitSpace(space, q)),
1558
+ elements: await q.receiveListDefined(container.elements, elem => this.visitRightPadded(elem, q)),
1559
+ markers: await q.receive(container.markers)
1560
+ };
1561
+ return updateIfChanged(container, updates) as J.Container<T>;
1373
1562
  }
1374
1563
 
1564
+ private static typeVisitor = new TypeReceiver();
1565
+
1375
1566
  public override async visitType(javaType: Type | undefined, q: RpcReceiveQueue): Promise<Type | undefined> {
1376
- const codec = RpcCodecs.forInstance(javaType);
1377
- if (codec) {
1378
- return await codec.rpcReceive(javaType, q);
1379
- }
1380
- if (javaType !== undefined) {
1381
- throw new Error("Missing codec for Type " + javaType.kind);
1567
+ if (!javaType) {
1568
+ return undefined;
1569
+ } else if (javaType.kind === Type.Kind.Unknown) {
1570
+ return Type.unknownType;
1382
1571
  }
1383
- return undefined;
1572
+ return await JavaReceiver.typeVisitor.visit(javaType, q);
1384
1573
  }
1385
1574
  }
1386
1575