Fri, 26 Jun 2009 18:51:39 -0700
6843077: JSR 308: Annotations on types
Reviewed-by: jjg, mcimadamore, darcy
Contributed-by: mernst@cs.washington.edu, mali@csail.mit.edu, mpapi@csail.mit.edu
2 /*
3 * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation. Sun designates this
9 * particular file as subject to the "Classpath" exception as provided
10 * by Sun in the LICENSE file that accompanied this code.
11 *
12 * This code is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * version 2 for more details (a copy is included in the LICENSE file that
16 * accompanied this code).
17 *
18 * You should have received a copy of the GNU General Public License version
19 * 2 along with this work; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
24 * have any questions.
25 */
27 package com.sun.tools.classfile;
29 import java.io.ByteArrayOutputStream;
30 import java.io.DataOutputStream;
31 import java.io.File;
32 import java.io.FileOutputStream;
33 import java.io.IOException;
34 import java.io.OutputStream;
36 import static com.sun.tools.classfile.Annotation.*;
37 import static com.sun.tools.classfile.ConstantPool.*;
38 import static com.sun.tools.classfile.StackMapTable_attribute.*;
39 import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.*;
41 /**
42 * Write a ClassFile data structure to a file or stream.
43 *
44 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
45 * you write code that depends on this, you do so at your own risk.
46 * This code and its internal interfaces are subject to change or
47 * deletion without notice.</b>
48 */
49 public class ClassWriter {
50 public ClassWriter() {
51 attributeWriter = new AttributeWriter();
52 constantPoolWriter = new ConstantPoolWriter();
53 out = new ClassOutputStream();
54 }
56 /**
57 * Write a ClassFile data structure to a file.
58 */
59 public void write(ClassFile classFile, File f) throws IOException {
60 FileOutputStream f_out = new FileOutputStream(f);
61 try {
62 write(classFile, f_out);
63 } finally {
64 f_out.close();
65 }
66 }
68 /**
69 * Write a ClassFile data structure to a stream.
70 */
71 public void write(ClassFile classFile, OutputStream s) throws IOException {
72 this.classFile = classFile;
73 out.reset();
74 write();
75 out.writeTo(s);
76 }
78 protected void write() throws IOException {
79 writeHeader();
80 writeConstantPool();
81 writeAccessFlags(classFile.access_flags);
82 writeClassInfo();
83 writeFields();
84 writeMethods();
85 writeAttributes(classFile.attributes);
86 }
88 protected void writeHeader() {
89 out.writeInt(classFile.magic);
90 out.writeShort(classFile.minor_version);
91 out.writeShort(classFile.major_version);
92 }
94 protected void writeAccessFlags(AccessFlags flags) {
95 out.writeShort(flags.flags);
96 }
98 protected void writeAttributes(Attributes attributes) {
99 int size = attributes.size();
100 out.writeShort(size);
101 for (Attribute attr: attributes)
102 attributeWriter.write(attr, out);
103 }
105 protected void writeClassInfo() {
106 out.writeShort(classFile.this_class);
107 out.writeShort(classFile.super_class);
108 int[] interfaces = classFile.interfaces;
109 out.writeShort(interfaces.length);
110 for (int i: interfaces)
111 out.writeShort(i);
112 }
114 protected void writeDescriptor(Descriptor d) {
115 out.writeShort(d.index);
116 }
118 protected void writeConstantPool() {
119 ConstantPool pool = classFile.constant_pool;
120 int size = pool.size();
121 out.writeShort(size);
122 for (CPInfo cpInfo: pool.entries())
123 constantPoolWriter.write(cpInfo, out);
124 }
126 protected void writeFields() throws IOException {
127 Field[] fields = classFile.fields;
128 out.writeShort(fields.length);
129 for (Field f: fields)
130 writeField(f);
131 }
133 protected void writeField(Field f) throws IOException {
134 writeAccessFlags(f.access_flags);
135 out.writeShort(f.name_index);
136 writeDescriptor(f.descriptor);
137 writeAttributes(f.attributes);
138 }
140 protected void writeMethods() throws IOException {
141 Method[] methods = classFile.methods;
142 out.writeShort(methods.length);
143 for (Method m: methods) {
144 writeMethod(m);
145 }
146 }
148 protected void writeMethod(Method m) throws IOException {
149 writeAccessFlags(m.access_flags);
150 out.writeShort(m.name_index);
151 writeDescriptor(m.descriptor);
152 writeAttributes(m.attributes);
153 }
155 protected ClassFile classFile;
156 protected ClassOutputStream out;
157 protected AttributeWriter attributeWriter;
158 protected ConstantPoolWriter constantPoolWriter;
160 /**
161 * Subtype of ByteArrayOutputStream with the convenience methods of
162 * a DataOutputStream. Since ByteArrayOutputStream does not throw
163 * IOException, there are no exceptions from the additional
164 * convenience methods either,
165 */
166 protected static class ClassOutputStream extends ByteArrayOutputStream {
167 public ClassOutputStream() {
168 d = new DataOutputStream(this);
169 }
171 public void writeByte(int value) {
172 try {
173 d.writeByte(value);
174 } catch (IOException ignore) {
175 }
176 }
178 public void writeShort(int value) {
179 try {
180 d.writeShort(value);
181 } catch (IOException ignore) {
182 }
183 }
185 public void writeInt(int value) {
186 try {
187 d.writeInt(value);
188 } catch (IOException ignore) {
189 }
190 }
192 public void writeLong(long value) {
193 try {
194 d.writeLong(value);
195 } catch (IOException ignore) {
196 }
197 }
199 public void writeFloat(float value) {
200 try {
201 d.writeFloat(value);
202 } catch (IOException ignore) {
203 }
204 }
206 public void writeDouble(double value) {
207 try {
208 d.writeDouble(value);
209 } catch (IOException ignore) {
210 }
211 }
213 public void writeUTF(String value) {
214 try {
215 d.writeUTF(value);
216 } catch (IOException ignore) {
217 }
218 }
220 public void writeTo(ClassOutputStream s) {
221 try {
222 super.writeTo(s);
223 } catch (IOException ignore) {
224 }
225 }
227 private DataOutputStream d;
228 }
230 /**
231 * Writer for the entries in the constant pool.
232 */
233 protected static class ConstantPoolWriter
234 implements ConstantPool.Visitor<Integer,ClassOutputStream> {
235 protected int write(CPInfo info, ClassOutputStream out) {
236 out.writeByte(info.getTag());
237 return info.accept(this, out);
238 }
240 public Integer visitClass(CONSTANT_Class_info info, ClassOutputStream out) {
241 out.writeShort(info.name_index);
242 return 1;
243 }
245 public Integer visitDouble(CONSTANT_Double_info info, ClassOutputStream out) {
246 out.writeDouble(info.value);
247 return 2;
248 }
250 public Integer visitFieldref(CONSTANT_Fieldref_info info, ClassOutputStream out) {
251 writeRef(info, out);
252 return 1;
253 }
255 public Integer visitFloat(CONSTANT_Float_info info, ClassOutputStream out) {
256 out.writeFloat(info.value);
257 return 1;
258 }
260 public Integer visitInteger(CONSTANT_Integer_info info, ClassOutputStream out) {
261 out.writeInt(info.value);
262 return 1;
263 }
265 public Integer visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, ClassOutputStream out) {
266 writeRef(info, out);
267 return 1;
268 }
270 public Integer visitLong(CONSTANT_Long_info info, ClassOutputStream out) {
271 out.writeLong(info.value);
272 return 2;
273 }
275 public Integer visitNameAndType(CONSTANT_NameAndType_info info, ClassOutputStream out) {
276 out.writeShort(info.name_index);
277 out.writeShort(info.type_index);
278 return 1;
279 }
281 public Integer visitMethodref(CONSTANT_Methodref_info info, ClassOutputStream out) {
282 return writeRef(info, out);
283 }
285 public Integer visitString(CONSTANT_String_info info, ClassOutputStream out) {
286 out.writeShort(info.string_index);
287 return 1;
288 }
290 public Integer visitUtf8(CONSTANT_Utf8_info info, ClassOutputStream out) {
291 out.writeUTF(info.value);
292 return 1;
293 }
295 protected Integer writeRef(CPRefInfo info, ClassOutputStream out) {
296 out.writeShort(info.class_index);
297 out.writeShort(info.name_and_type_index);
298 return 1;
299 }
300 }
302 /**
303 * Writer for the different types of attribute.
304 */
305 protected static class AttributeWriter implements Attribute.Visitor<Void,ClassOutputStream> {
306 public void write(Attributes attributes, ClassOutputStream out) {
307 int size = attributes.size();
308 out.writeShort(size);
309 for (Attribute a: attributes)
310 write(a, out);
311 }
313 // Note: due to the use of shared resources, this method is not reentrant.
314 public void write(Attribute attr, ClassOutputStream out) {
315 out.writeShort(attr.attribute_name_index);
316 sharedOut.reset();
317 attr.accept(this, sharedOut);
318 out.writeInt(sharedOut.size());
319 sharedOut.writeTo(out);
320 }
322 protected ClassOutputStream sharedOut = new ClassOutputStream();
323 protected AnnotationWriter annotationWriter = new AnnotationWriter();
325 public Void visitDefault(DefaultAttribute attr, ClassOutputStream out) {
326 out.write(attr.info, 0, attr.info.length);
327 return null;
328 }
330 public Void visitAnnotationDefault(AnnotationDefault_attribute attr, ClassOutputStream out) {
331 annotationWriter.write(attr.default_value, out);
332 return null;
333 }
335 public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, ClassOutputStream out) {
336 out.writeShort(attr.character_range_table.length);
337 for (CharacterRangeTable_attribute.Entry e: attr.character_range_table)
338 writeCharacterRangeTableEntry(e, out);
339 return null;
340 }
342 protected void writeCharacterRangeTableEntry(CharacterRangeTable_attribute.Entry entry, ClassOutputStream out) {
343 out.writeShort(entry.start_pc);
344 out.writeShort(entry.end_pc);
345 out.writeInt(entry.character_range_start);
346 out.writeInt(entry.character_range_end);
347 out.writeShort(entry.flags);
348 }
350 public Void visitCode(Code_attribute attr, ClassOutputStream out) {
351 out.writeShort(attr.max_stack);
352 out.writeShort(attr.max_locals);
353 out.writeInt(attr.code.length);
354 out.write(attr.code, 0, attr.code.length);
355 out.writeShort(attr.exception_table.length);
356 for (Code_attribute.Exception_data e: attr.exception_table)
357 writeExceptionTableEntry(e, out);
358 new AttributeWriter().write(attr.attributes, out);
359 return null;
360 }
362 protected void writeExceptionTableEntry(Code_attribute.Exception_data exception_data, ClassOutputStream out) {
363 out.writeShort(exception_data.start_pc);
364 out.writeShort(exception_data.end_pc);
365 out.writeShort(exception_data.handler_pc);
366 out.writeShort(exception_data.catch_type);
367 }
369 public Void visitCompilationID(CompilationID_attribute attr, ClassOutputStream out) {
370 out.writeShort(attr.compilationID_index);
371 return null;
372 }
374 public Void visitConstantValue(ConstantValue_attribute attr, ClassOutputStream out) {
375 out.writeShort(attr.constantvalue_index);
376 return null;
377 }
379 public Void visitDeprecated(Deprecated_attribute attr, ClassOutputStream out) {
380 return null;
381 }
383 public Void visitEnclosingMethod(EnclosingMethod_attribute attr, ClassOutputStream out) {
384 out.writeShort(attr.class_index);
385 out.writeShort(attr.method_index);
386 return null;
387 }
389 public Void visitExceptions(Exceptions_attribute attr, ClassOutputStream out) {
390 out.writeShort(attr.exception_index_table.length);
391 for (int i: attr.exception_index_table)
392 out.writeShort(i);
393 return null;
394 }
396 public Void visitInnerClasses(InnerClasses_attribute attr, ClassOutputStream out) {
397 out.writeShort(attr.classes.length);
398 for (InnerClasses_attribute.Info info: attr.classes)
399 writeInnerClassesInfo(info, out);
400 return null;
401 }
403 protected void writeInnerClassesInfo(InnerClasses_attribute.Info info, ClassOutputStream out) {
404 out.writeShort(info.inner_class_info_index);
405 out.writeShort(info.outer_class_info_index);
406 out.writeShort(info.inner_name_index);
407 writeAccessFlags(info.inner_class_access_flags, out);
408 }
410 public Void visitLineNumberTable(LineNumberTable_attribute attr, ClassOutputStream out) {
411 out.writeShort(attr.line_number_table.length);
412 for (LineNumberTable_attribute.Entry e: attr.line_number_table)
413 writeLineNumberTableEntry(e, out);
414 return null;
415 }
417 protected void writeLineNumberTableEntry(LineNumberTable_attribute.Entry entry, ClassOutputStream out) {
418 out.writeShort(entry.start_pc);
419 out.writeShort(entry.line_number);
420 }
422 public Void visitLocalVariableTable(LocalVariableTable_attribute attr, ClassOutputStream out) {
423 out.writeShort(attr.local_variable_table.length);
424 for (LocalVariableTable_attribute.Entry e: attr.local_variable_table)
425 writeLocalVariableTableEntry(e, out);
426 return null;
427 }
429 protected void writeLocalVariableTableEntry(LocalVariableTable_attribute.Entry entry, ClassOutputStream out) {
430 out.writeShort(entry.start_pc);
431 out.writeShort(entry.length);
432 out.writeShort(entry.name_index);
433 out.writeShort(entry.descriptor_index);
434 out.writeShort(entry.index);
435 }
437 public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, ClassOutputStream out) {
438 out.writeByte(attr.local_variable_table.length);
439 for (LocalVariableTypeTable_attribute.Entry e: attr.local_variable_table)
440 writeLocalVariableTypeTableEntry(e, out);
441 return null;
442 }
444 protected void writeLocalVariableTypeTableEntry(LocalVariableTypeTable_attribute.Entry entry, ClassOutputStream out) {
445 out.writeShort(entry.start_pc);
446 out.writeShort(entry.length);
447 out.writeShort(entry.name_index);
448 out.writeShort(entry.signature_index);
449 out.writeShort(entry.index);
450 }
452 public Void visitModule(Module_attribute attr, ClassOutputStream out) {
453 out.writeShort(attr.module_name);
454 return null;
455 }
457 public Void visitModuleExportTable(ModuleExportTable_attribute attr, ClassOutputStream out) {
458 out.writeShort(attr.export_type_table.length);
459 for (int i: attr.export_type_table)
460 out.writeShort(i);
461 return null;
462 }
464 public Void visitModuleMemberTable(ModuleMemberTable_attribute attr, ClassOutputStream out) {
465 out.writeShort(attr.package_member_table.length);
466 for (int i: attr.package_member_table)
467 out.writeShort(i);
468 return null;
469 }
471 public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, ClassOutputStream out) {
472 annotationWriter.write(attr.annotations, out);
473 return null;
474 }
476 public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, ClassOutputStream out) {
477 annotationWriter.write(attr.annotations, out);
478 return null;
479 }
481 public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, ClassOutputStream out) {
482 annotationWriter.write(attr.annotations, out);
483 return null;
484 }
486 public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, ClassOutputStream out) {
487 annotationWriter.write(attr.annotations, out);
488 return null;
489 }
491 public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, ClassOutputStream out) {
492 out.writeByte(attr.parameter_annotations.length);
493 for (Annotation[] annos: attr.parameter_annotations)
494 annotationWriter.write(annos, out);
495 return null;
496 }
498 public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, ClassOutputStream out) {
499 out.writeByte(attr.parameter_annotations.length);
500 for (Annotation[] annos: attr.parameter_annotations)
501 annotationWriter.write(annos, out);
502 return null;
503 }
505 public Void visitSignature(Signature_attribute attr, ClassOutputStream out) {
506 out.writeShort(attr.signature_index);
507 return null;
508 }
510 public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, ClassOutputStream out) {
511 out.write(attr.debug_extension, 0, attr.debug_extension.length);
512 return null;
513 }
515 public Void visitSourceFile(SourceFile_attribute attr, ClassOutputStream out) {
516 out.writeShort(attr.sourcefile_index);
517 return null;
518 }
520 public Void visitSourceID(SourceID_attribute attr, ClassOutputStream out) {
521 out.writeShort(attr.sourceID_index);
522 return null;
523 }
525 public Void visitStackMap(StackMap_attribute attr, ClassOutputStream out) {
526 if (stackMapWriter == null)
527 stackMapWriter = new StackMapTableWriter();
529 out.writeShort(attr.entries.length);
530 for (stack_map_frame f: attr.entries)
531 stackMapWriter.write(f, out);
532 return null;
533 }
535 public Void visitStackMapTable(StackMapTable_attribute attr, ClassOutputStream out) {
536 if (stackMapWriter == null)
537 stackMapWriter = new StackMapTableWriter();
539 out.writeShort(attr.entries.length);
540 for (stack_map_frame f: attr.entries)
541 stackMapWriter.write(f, out);
542 return null;
543 }
545 public Void visitSynthetic(Synthetic_attribute attr, ClassOutputStream out) {
546 return null;
547 }
549 protected void writeAccessFlags(AccessFlags flags, ClassOutputStream p) {
550 sharedOut.writeShort(flags.flags);
551 }
553 protected StackMapTableWriter stackMapWriter;
554 }
556 /**
557 * Writer for the frames of StackMap and StackMapTable attributes.
558 */
559 protected static class StackMapTableWriter
560 implements stack_map_frame.Visitor<Void,ClassOutputStream> {
562 public void write(stack_map_frame frame, ClassOutputStream out) {
563 out.write(frame.frame_type);
564 frame.accept(this, out);
565 }
567 public Void visit_same_frame(same_frame frame, ClassOutputStream p) {
568 return null;
569 }
571 public Void visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, ClassOutputStream out) {
572 writeVerificationTypeInfo(frame.stack[0], out);
573 return null;
574 }
576 public Void visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, ClassOutputStream out) {
577 out.writeShort(frame.offset_delta);
578 writeVerificationTypeInfo(frame.stack[0], out);
579 return null;
580 }
582 public Void visit_chop_frame(chop_frame frame, ClassOutputStream out) {
583 out.writeShort(frame.offset_delta);
584 return null;
585 }
587 public Void visit_same_frame_extended(same_frame_extended frame, ClassOutputStream out) {
588 out.writeShort(frame.offset_delta);
589 return null;
590 }
592 public Void visit_append_frame(append_frame frame, ClassOutputStream out) {
593 out.writeShort(frame.offset_delta);
594 for (verification_type_info l: frame.locals)
595 writeVerificationTypeInfo(l, out);
596 return null;
597 }
599 public Void visit_full_frame(full_frame frame, ClassOutputStream out) {
600 out.writeShort(frame.offset_delta);
601 out.writeShort(frame.locals.length);
602 for (verification_type_info l: frame.locals)
603 writeVerificationTypeInfo(l, out);
604 out.writeShort(frame.stack.length);
605 for (verification_type_info s: frame.stack)
606 writeVerificationTypeInfo(s, out);
607 return null;
608 }
610 protected void writeVerificationTypeInfo(verification_type_info info,
611 ClassOutputStream out) {
612 out.write(info.tag);
613 switch (info.tag) {
614 case ITEM_Top:
615 case ITEM_Integer:
616 case ITEM_Float:
617 case ITEM_Long:
618 case ITEM_Double:
619 case ITEM_Null:
620 case ITEM_UninitializedThis:
621 break;
623 case ITEM_Object:
624 Object_variable_info o = (Object_variable_info) info;
625 out.writeShort(o.cpool_index);
626 break;
628 case ITEM_Uninitialized:
629 Uninitialized_variable_info u = (Uninitialized_variable_info) info;
630 out.writeShort(u.offset);
631 break;
633 default:
634 throw new Error();
635 }
636 }
637 }
639 /**
640 * Writer for annotations and the values they contain.
641 */
642 protected static class AnnotationWriter
643 implements Annotation.element_value.Visitor<Void,ClassOutputStream> {
644 public void write(Annotation[] annos, ClassOutputStream out) {
645 out.writeShort(annos.length);
646 for (Annotation anno: annos)
647 write(anno, out);
648 }
650 public void write(ExtendedAnnotation[] annos, ClassOutputStream out) {
651 out.writeShort(annos.length);
652 for (ExtendedAnnotation anno: annos)
653 write(anno, out);
654 }
656 public void write(Annotation anno, ClassOutputStream out) {
657 out.writeShort(anno.type_index);
658 out.writeShort(anno.element_value_pairs.length);
659 for (element_value_pair p: anno.element_value_pairs)
660 write(p, out);
661 }
663 public void write(ExtendedAnnotation anno, ClassOutputStream out) {
664 write(anno.annotation, out);
665 write(anno.position, out);
666 }
668 public void write(element_value_pair pair, ClassOutputStream out) {
669 out.writeShort(pair.element_name_index);
670 write(pair.value, out);
671 }
673 public void write(element_value ev, ClassOutputStream out) {
674 out.writeByte(ev.tag);
675 ev.accept(this, out);
676 }
678 public Void visitPrimitive(Primitive_element_value ev, ClassOutputStream out) {
679 out.writeShort(ev.const_value_index);
680 return null;
681 }
683 public Void visitEnum(Enum_element_value ev, ClassOutputStream out) {
684 out.writeShort(ev.type_name_index);
685 out.writeShort(ev.const_name_index);
686 return null;
687 }
689 public Void visitClass(Class_element_value ev, ClassOutputStream out) {
690 out.writeShort(ev.class_info_index);
691 return null;
692 }
694 public Void visitAnnotation(Annotation_element_value ev, ClassOutputStream out) {
695 write(ev.annotation_value, out);
696 return null;
697 }
699 public Void visitArray(Array_element_value ev, ClassOutputStream out) {
700 out.writeShort(ev.num_values);
701 for (element_value v: ev.values)
702 write(v, out);
703 return null;
704 }
706 private void write(ExtendedAnnotation.Position p, ClassOutputStream out) {
707 out.writeByte(p.type.targetTypeValue());
708 switch (p.type) {
709 // type case
710 case TYPECAST:
711 case TYPECAST_GENERIC_OR_ARRAY:
712 // object creation
713 case INSTANCEOF:
714 case INSTANCEOF_GENERIC_OR_ARRAY:
715 // new expression
716 case NEW:
717 case NEW_GENERIC_OR_ARRAY:
718 case NEW_TYPE_ARGUMENT:
719 case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
720 out.writeShort(p.offset);
721 break;
722 // local variable
723 case LOCAL_VARIABLE:
724 case LOCAL_VARIABLE_GENERIC_OR_ARRAY:
725 int table_length = p.lvarOffset.length;
726 out.writeShort(table_length);
727 for (int i = 0; i < table_length; ++i) {
728 out.writeShort(1); // for table length
729 out.writeShort(p.lvarOffset[i]);
730 out.writeShort(p.lvarLength[i]);
731 out.writeShort(p.lvarIndex[i]);
732 }
733 break;
734 // method receiver
735 case METHOD_RECEIVER:
736 // Do nothing
737 break;
738 // type parameters
739 case CLASS_TYPE_PARAMETER:
740 case METHOD_TYPE_PARAMETER:
741 out.writeByte(p.parameter_index);
742 break;
743 // type parameters bounds
744 case CLASS_TYPE_PARAMETER_BOUND:
745 case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
746 case METHOD_TYPE_PARAMETER_BOUND:
747 case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
748 out.writeByte(p.parameter_index);
749 out.writeByte(p.bound_index);
750 break;
751 // wildcards
752 case WILDCARD_BOUND:
753 case WILDCARD_BOUND_GENERIC_OR_ARRAY:
754 write(p.wildcard_position, out);
755 break;
756 // Class extends and implements clauses
757 case CLASS_EXTENDS:
758 case CLASS_EXTENDS_GENERIC_OR_ARRAY:
759 out.writeByte(p.type_index);
760 break;
761 // throws
762 case THROWS:
763 out.writeByte(p.type_index);
764 break;
765 case CLASS_LITERAL:
766 out.writeShort(p.offset);
767 break;
768 // method parameter: not specified
769 case METHOD_PARAMETER_GENERIC_OR_ARRAY:
770 out.writeByte(p.parameter_index);
771 break;
772 // method type argument: wasn't specified
773 case METHOD_TYPE_ARGUMENT:
774 case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
775 out.writeShort(p.offset);
776 out.writeByte(p.type_index);
777 break;
778 // We don't need to worry abut these
779 case METHOD_RETURN_GENERIC_OR_ARRAY:
780 case FIELD_GENERIC_OR_ARRAY:
781 break;
782 case UNKNOWN:
783 break;
784 default:
785 throw new AssertionError("unknown type: " + p);
786 }
788 // Append location data for generics/arrays.
789 if (p.type.hasLocation()) {
790 out.writeShort(p.location.size());
791 for (int i : p.location)
792 out.writeByte((byte)i);
793 }
794 }
795 }
796 }