@@ -91,7 +91,7 @@ final class AnnotationWriter extends AnnotationVisitor {
91
91
private AnnotationWriter nextAnnotation ;
92
92
93
93
// -----------------------------------------------------------------------------------------------
94
- // Constructors
94
+ // Constructors and factories
95
95
// -----------------------------------------------------------------------------------------------
96
96
97
97
/**
@@ -104,15 +104,15 @@ final class AnnotationWriter extends AnnotationVisitor {
104
104
* the visited content must be stored. This ByteVector must already contain all the fields of
105
105
* the structure except the last one (the element_value_pairs array).
106
106
* @param previousAnnotation the previously visited annotation of the
107
- * Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or null in
108
- * other cases (e.g. nested or array annotations).
107
+ * Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or
108
+ * {@literal null} in other cases (e.g. nested or array annotations).
109
109
*/
110
110
AnnotationWriter (
111
111
final SymbolTable symbolTable ,
112
112
final boolean useNamedValues ,
113
113
final ByteVector annotation ,
114
114
final AnnotationWriter previousAnnotation ) {
115
- super (Opcodes .ASM6 );
115
+ super (/* latest api = */ Opcodes .ASM9 );
116
116
this .symbolTable = symbolTable ;
117
117
this .useNamedValues = useNamedValues ;
118
118
this .annotation = annotation ;
@@ -125,21 +125,61 @@ final class AnnotationWriter extends AnnotationVisitor {
125
125
}
126
126
127
127
/**
128
- * Constructs a new {@link AnnotationWriter} using named values.
128
+ * Creates a new {@link AnnotationWriter} using named values.
129
129
*
130
130
* @param symbolTable where the constants used in this AnnotationWriter must be stored.
131
- * @param annotation where the 'annotation' or 'type_annotation' JVMS structure corresponding to
132
- * the visited content must be stored. This ByteVector must already contain all the fields of
133
- * the structure except the last one (the element_value_pairs array).
131
+ * @param descriptor the class descriptor of the annotation class.
134
132
* @param previousAnnotation the previously visited annotation of the
135
- * Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or null in
136
- * other cases (e.g. nested or array annotations).
133
+ * Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or
134
+ * {@literal null} in other cases (e.g. nested or array annotations).
135
+ * @return a new {@link AnnotationWriter} for the given annotation descriptor.
137
136
*/
138
- AnnotationWriter (
137
+ static AnnotationWriter create (
139
138
final SymbolTable symbolTable ,
140
- final ByteVector annotation ,
139
+ final String descriptor ,
140
+ final AnnotationWriter previousAnnotation ) {
141
+ // Create a ByteVector to hold an 'annotation' JVMS structure.
142
+ // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.
143
+ ByteVector annotation = new ByteVector ();
144
+ // Write type_index and reserve space for num_element_value_pairs.
145
+ annotation .putShort (symbolTable .addConstantUtf8 (descriptor )).putShort (0 );
146
+ return new AnnotationWriter (
147
+ symbolTable , /* useNamedValues= */ true , annotation , previousAnnotation );
148
+ }
149
+
150
+ /**
151
+ * Creates a new {@link AnnotationWriter} using named values.
152
+ *
153
+ * @param symbolTable where the constants used in this AnnotationWriter must be stored.
154
+ * @param typeRef a reference to the annotated type. The sort of this type reference must be
155
+ * {@link TypeReference#CLASS_TYPE_PARAMETER}, {@link
156
+ * TypeReference#CLASS_TYPE_PARAMETER_BOUND} or {@link TypeReference#CLASS_EXTENDS}. See
157
+ * {@link TypeReference}.
158
+ * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
159
+ * static inner type within 'typeRef'. May be {@literal null} if the annotation targets
160
+ * 'typeRef' as a whole.
161
+ * @param descriptor the class descriptor of the annotation class.
162
+ * @param previousAnnotation the previously visited annotation of the
163
+ * Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or
164
+ * {@literal null} in other cases (e.g. nested or array annotations).
165
+ * @return a new {@link AnnotationWriter} for the given type annotation reference and descriptor.
166
+ */
167
+ static AnnotationWriter create (
168
+ final SymbolTable symbolTable ,
169
+ final int typeRef ,
170
+ final TypePath typePath ,
171
+ final String descriptor ,
141
172
final AnnotationWriter previousAnnotation ) {
142
- this (symbolTable , /* useNamedValues = */ true , annotation , previousAnnotation );
173
+ // Create a ByteVector to hold a 'type_annotation' JVMS structure.
174
+ // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20.
175
+ ByteVector typeAnnotation = new ByteVector ();
176
+ // Write target_type, target_info, and target_path.
177
+ TypeReference .putTarget (typeRef , typeAnnotation );
178
+ TypePath .put (typePath , typeAnnotation );
179
+ // Write type_index and reserve space for num_element_value_pairs.
180
+ typeAnnotation .putShort (symbolTable .addConstantUtf8 (descriptor )).putShort (0 );
181
+ return new AnnotationWriter (
182
+ symbolTable , /* useNamedValues= */ true , typeAnnotation , previousAnnotation );
143
183
}
144
184
145
185
// -----------------------------------------------------------------------------------------------
@@ -244,7 +284,7 @@ public AnnotationVisitor visitAnnotation(final String name, final String descrip
244
284
}
245
285
// Write tag and type_index, and reserve 2 bytes for num_element_value_pairs.
246
286
annotation .put12 ('@' , symbolTable .addConstantUtf8 (descriptor )).putShort (0 );
247
- return new AnnotationWriter (symbolTable , annotation , null );
287
+ return new AnnotationWriter (symbolTable , /* useNamedValues= */ true , annotation , null );
248
288
}
249
289
250
290
@ Override
@@ -263,7 +303,7 @@ public AnnotationVisitor visitArray(final String name) {
263
303
// visit the array elements. Its num_element_value_pairs will correspond to the number of array
264
304
// elements and will be stored in what is in fact num_values.
265
305
annotation .put12 ('[' , 0 );
266
- return new AnnotationWriter (symbolTable , /* useNamedValues = */ false , annotation , null );
306
+ return new AnnotationWriter (symbolTable , /* useNamedValues= */ false , annotation , null );
267
307
}
268
308
269
309
@ Override
@@ -284,7 +324,7 @@ public void visitEnd() {
284
324
* and all its <i>predecessors</i> (see {@link #previousAnnotation}. Also adds the attribute name
285
325
* to the constant pool of the class (if not null).
286
326
*
287
- * @param attributeName one of "Runtime[In]Visible[Type]Annotations", or null.
327
+ * @param attributeName one of "Runtime[In]Visible[Type]Annotations", or {@literal null} .
288
328
* @return the size in bytes of a Runtime[In]Visible[Type]Annotations attribute containing this
289
329
* annotation and all its predecessors. This includes the size of the attribute_name_index and
290
330
* attribute_length fields.
@@ -303,6 +343,56 @@ int computeAnnotationsSize(final String attributeName) {
303
343
return attributeSize ;
304
344
}
305
345
346
+ /**
347
+ * Returns the size of the Runtime[In]Visible[Type]Annotations attributes containing the given
348
+ * annotations and all their <i>predecessors</i> (see {@link #previousAnnotation}. Also adds the
349
+ * attribute names to the constant pool of the class (if not null).
350
+ *
351
+ * @param lastRuntimeVisibleAnnotation The last runtime visible annotation of a field, method or
352
+ * class. The previous ones can be accessed with the {@link #previousAnnotation} field. May be
353
+ * {@literal null}.
354
+ * @param lastRuntimeInvisibleAnnotation The last runtime invisible annotation of this a field,
355
+ * method or class. The previous ones can be accessed with the {@link #previousAnnotation}
356
+ * field. May be {@literal null}.
357
+ * @param lastRuntimeVisibleTypeAnnotation The last runtime visible type annotation of this a
358
+ * field, method or class. The previous ones can be accessed with the {@link
359
+ * #previousAnnotation} field. May be {@literal null}.
360
+ * @param lastRuntimeInvisibleTypeAnnotation The last runtime invisible type annotation of a
361
+ * field, method or class field. The previous ones can be accessed with the {@link
362
+ * #previousAnnotation} field. May be {@literal null}.
363
+ * @return the size in bytes of a Runtime[In]Visible[Type]Annotations attribute containing the
364
+ * given annotations and all their predecessors. This includes the size of the
365
+ * attribute_name_index and attribute_length fields.
366
+ */
367
+ static int computeAnnotationsSize (
368
+ final AnnotationWriter lastRuntimeVisibleAnnotation ,
369
+ final AnnotationWriter lastRuntimeInvisibleAnnotation ,
370
+ final AnnotationWriter lastRuntimeVisibleTypeAnnotation ,
371
+ final AnnotationWriter lastRuntimeInvisibleTypeAnnotation ) {
372
+ int size = 0 ;
373
+ if (lastRuntimeVisibleAnnotation != null ) {
374
+ size +=
375
+ lastRuntimeVisibleAnnotation .computeAnnotationsSize (
376
+ Constants .RUNTIME_VISIBLE_ANNOTATIONS );
377
+ }
378
+ if (lastRuntimeInvisibleAnnotation != null ) {
379
+ size +=
380
+ lastRuntimeInvisibleAnnotation .computeAnnotationsSize (
381
+ Constants .RUNTIME_INVISIBLE_ANNOTATIONS );
382
+ }
383
+ if (lastRuntimeVisibleTypeAnnotation != null ) {
384
+ size +=
385
+ lastRuntimeVisibleTypeAnnotation .computeAnnotationsSize (
386
+ Constants .RUNTIME_VISIBLE_TYPE_ANNOTATIONS );
387
+ }
388
+ if (lastRuntimeInvisibleTypeAnnotation != null ) {
389
+ size +=
390
+ lastRuntimeInvisibleTypeAnnotation .computeAnnotationsSize (
391
+ Constants .RUNTIME_INVISIBLE_TYPE_ANNOTATIONS );
392
+ }
393
+ return size ;
394
+ }
395
+
306
396
/**
307
397
* Puts a Runtime[In]Visible[Type]Annotations attribute containing this annotations and all its
308
398
* <i>predecessors</i> (see {@link #previousAnnotation} in the given ByteVector. Annotations are
@@ -335,6 +425,51 @@ void putAnnotations(final int attributeNameIndex, final ByteVector output) {
335
425
}
336
426
}
337
427
428
+ /**
429
+ * Puts the Runtime[In]Visible[Type]Annotations attributes containing the given annotations and
430
+ * all their <i>predecessors</i> (see {@link #previousAnnotation} in the given ByteVector.
431
+ * Annotations are put in the same order they have been visited.
432
+ *
433
+ * @param symbolTable where the constants used in the AnnotationWriter instances are stored.
434
+ * @param lastRuntimeVisibleAnnotation The last runtime visible annotation of a field, method or
435
+ * class. The previous ones can be accessed with the {@link #previousAnnotation} field. May be
436
+ * {@literal null}.
437
+ * @param lastRuntimeInvisibleAnnotation The last runtime invisible annotation of this a field,
438
+ * method or class. The previous ones can be accessed with the {@link #previousAnnotation}
439
+ * field. May be {@literal null}.
440
+ * @param lastRuntimeVisibleTypeAnnotation The last runtime visible type annotation of this a
441
+ * field, method or class. The previous ones can be accessed with the {@link
442
+ * #previousAnnotation} field. May be {@literal null}.
443
+ * @param lastRuntimeInvisibleTypeAnnotation The last runtime invisible type annotation of a
444
+ * field, method or class field. The previous ones can be accessed with the {@link
445
+ * #previousAnnotation} field. May be {@literal null}.
446
+ * @param output where the attributes must be put.
447
+ */
448
+ static void putAnnotations (
449
+ final SymbolTable symbolTable ,
450
+ final AnnotationWriter lastRuntimeVisibleAnnotation ,
451
+ final AnnotationWriter lastRuntimeInvisibleAnnotation ,
452
+ final AnnotationWriter lastRuntimeVisibleTypeAnnotation ,
453
+ final AnnotationWriter lastRuntimeInvisibleTypeAnnotation ,
454
+ final ByteVector output ) {
455
+ if (lastRuntimeVisibleAnnotation != null ) {
456
+ lastRuntimeVisibleAnnotation .putAnnotations (
457
+ symbolTable .addConstantUtf8 (Constants .RUNTIME_VISIBLE_ANNOTATIONS ), output );
458
+ }
459
+ if (lastRuntimeInvisibleAnnotation != null ) {
460
+ lastRuntimeInvisibleAnnotation .putAnnotations (
461
+ symbolTable .addConstantUtf8 (Constants .RUNTIME_INVISIBLE_ANNOTATIONS ), output );
462
+ }
463
+ if (lastRuntimeVisibleTypeAnnotation != null ) {
464
+ lastRuntimeVisibleTypeAnnotation .putAnnotations (
465
+ symbolTable .addConstantUtf8 (Constants .RUNTIME_VISIBLE_TYPE_ANNOTATIONS ), output );
466
+ }
467
+ if (lastRuntimeInvisibleTypeAnnotation != null ) {
468
+ lastRuntimeInvisibleTypeAnnotation .putAnnotations (
469
+ symbolTable .addConstantUtf8 (Constants .RUNTIME_INVISIBLE_TYPE_ANNOTATIONS ), output );
470
+ }
471
+ }
472
+
338
473
/**
339
474
* Returns the size of a Runtime[In]VisibleParameterAnnotations attribute containing all the
340
475
* annotation lists from the given AnnotationWriter sub-array. Also adds the attribute name to the
0 commit comments