jjg@46: /* jjg@1521: * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. jjg@46: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jjg@46: * jjg@46: * This code is free software; you can redistribute it and/or modify it jjg@46: * under the terms of the GNU General Public License version 2 only, as ohair@554: * published by the Free Software Foundation. Oracle designates this jjg@46: * particular file as subject to the "Classpath" exception as provided ohair@554: * by Oracle in the LICENSE file that accompanied this code. jjg@46: * jjg@46: * This code is distributed in the hope that it will be useful, but WITHOUT jjg@46: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jjg@46: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jjg@46: * version 2 for more details (a copy is included in the LICENSE file that jjg@46: * accompanied this code). jjg@46: * jjg@46: * You should have received a copy of the GNU General Public License version jjg@46: * 2 along with this work; if not, write to the Free Software Foundation, jjg@46: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jjg@46: * ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@554: * or visit www.oracle.com if you need additional information or have any ohair@554: * questions. jjg@46: */ jjg@46: jjg@46: package com.sun.tools.javap; jjg@46: jjg@46: import com.sun.tools.classfile.Annotation; jjg@1521: import com.sun.tools.classfile.TypeAnnotation; jjg@46: import com.sun.tools.classfile.Annotation.Annotation_element_value; jjg@46: import com.sun.tools.classfile.Annotation.Array_element_value; jjg@46: import com.sun.tools.classfile.Annotation.Class_element_value; jjg@46: import com.sun.tools.classfile.Annotation.Enum_element_value; jjg@46: import com.sun.tools.classfile.Annotation.Primitive_element_value; jjg@338: import com.sun.tools.classfile.ConstantPool; jjg@338: import com.sun.tools.classfile.ConstantPoolException; jjg@338: import com.sun.tools.classfile.Descriptor; jjg@338: import com.sun.tools.classfile.Descriptor.InvalidDescriptor; jjg@46: jjg@46: /** jjg@46: * A writer for writing annotations as text. jjg@46: * jjg@581: *

This is NOT part of any supported API. jjg@581: * If you write code that depends on this, you do so at your own risk. jjg@46: * This code and its internal interfaces are subject to change or jjg@46: * deletion without notice. jjg@46: */ jjg@46: public class AnnotationWriter extends BasicWriter { jjg@46: static AnnotationWriter instance(Context context) { jjg@46: AnnotationWriter instance = context.get(AnnotationWriter.class); jjg@46: if (instance == null) jjg@46: instance = new AnnotationWriter(context); jjg@46: return instance; jjg@46: } jjg@46: jjg@46: protected AnnotationWriter(Context context) { jjg@46: super(context); jjg@338: classWriter = ClassWriter.instance(context); jjg@338: constantWriter = ConstantWriter.instance(context); jjg@46: } jjg@46: jjg@46: public void write(Annotation annot) { jjg@338: write(annot, false); jjg@338: } jjg@338: jjg@338: public void write(Annotation annot, boolean resolveIndices) { jjg@338: writeDescriptor(annot.type_index, resolveIndices); jjg@338: boolean showParens = annot.num_element_value_pairs > 0 || !resolveIndices; jjg@338: if (showParens) jjg@338: print("("); jjg@46: for (int i = 0; i < annot.num_element_value_pairs; i++) { jjg@46: if (i > 0) jjg@46: print(","); jjg@338: write(annot.element_value_pairs[i], resolveIndices); jjg@46: } jjg@338: if (showParens) jjg@338: print(")"); jjg@46: } jjg@46: jjg@1521: public void write(TypeAnnotation annot) { jjg@1521: write(annot, true, false); jjg@1521: } jjg@1521: jjg@1521: public void write(TypeAnnotation annot, boolean showOffsets, boolean resolveIndices) { jjg@1521: write(annot.annotation, resolveIndices); jjg@1521: print(": "); jjg@1521: write(annot.position, showOffsets); jjg@1521: } jjg@1521: jjg@1521: public void write(TypeAnnotation.Position pos, boolean showOffsets) { jjg@1521: print(pos.type); jjg@1521: jjg@1521: switch (pos.type) { jjg@1521: // instanceof jjg@1521: case INSTANCEOF: jjg@1521: // new expression jjg@1521: case NEW: jjg@1563: // constructor/method reference receiver jjg@1563: case CONSTRUCTOR_REFERENCE: jjg@1563: case METHOD_REFERENCE: jjg@1521: if (showOffsets) { jjg@1521: print(", offset="); jjg@1521: print(pos.offset); jjg@1521: } jjg@1521: break; jjg@1521: // local variable jjg@1521: case LOCAL_VARIABLE: jjg@1521: // resource variable jjg@1521: case RESOURCE_VARIABLE: jjg@1521: if (pos.lvarOffset == null) { jjg@1521: print(", lvarOffset is Null!"); jjg@1521: break; jjg@1521: } jjg@1521: print(", {"); jjg@1521: for (int i = 0; i < pos.lvarOffset.length; ++i) { jjg@1521: if (i != 0) print("; "); jjg@1521: if (showOffsets) { jjg@1521: print("start_pc="); jjg@1521: print(pos.lvarOffset[i]); jjg@1521: } jjg@1521: print(", length="); jjg@1521: print(pos.lvarLength[i]); jjg@1521: print(", index="); jjg@1521: print(pos.lvarIndex[i]); jjg@1521: } jjg@1521: print("}"); jjg@1521: break; jjg@1521: // exception parameter jjg@1521: case EXCEPTION_PARAMETER: jjg@1521: print(", exception_index="); jjg@1521: print(pos.exception_index); jjg@1521: break; jjg@1521: // method receiver jjg@1521: case METHOD_RECEIVER: jjg@1521: // Do nothing jjg@1521: break; jjg@1521: // type parameter jjg@1521: case CLASS_TYPE_PARAMETER: jjg@1521: case METHOD_TYPE_PARAMETER: jjg@1521: print(", param_index="); jjg@1521: print(pos.parameter_index); jjg@1521: break; jjg@1521: // type parameter bound jjg@1521: case CLASS_TYPE_PARAMETER_BOUND: jjg@1521: case METHOD_TYPE_PARAMETER_BOUND: jjg@1521: print(", param_index="); jjg@1521: print(pos.parameter_index); jjg@1521: print(", bound_index="); jjg@1521: print(pos.bound_index); jjg@1521: break; jjg@1521: // class extends or implements clause jjg@1521: case CLASS_EXTENDS: jjg@1521: print(", type_index="); jjg@1521: print(pos.type_index); jjg@1521: break; jjg@1521: // throws jjg@1521: case THROWS: jjg@1521: print(", type_index="); jjg@1521: print(pos.type_index); jjg@1521: break; jjg@1521: // method parameter jjg@1521: case METHOD_FORMAL_PARAMETER: jjg@1521: print(", param_index="); jjg@1521: print(pos.parameter_index); jjg@1521: break; jjg@1563: // type cast jjg@1563: case CAST: jjg@1521: // method/constructor/reference type argument jjg@1521: case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: jjg@1521: case METHOD_INVOCATION_TYPE_ARGUMENT: jjg@1563: case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: jjg@1521: case METHOD_REFERENCE_TYPE_ARGUMENT: jjg@1521: if (showOffsets) { jjg@1521: print(", offset="); jjg@1521: print(pos.offset); jjg@1521: } jjg@1521: print(", type_index="); jjg@1521: print(pos.type_index); jjg@1521: break; jjg@1521: // We don't need to worry about these jjg@1521: case METHOD_RETURN: jjg@1521: case FIELD: jjg@1521: break; jjg@1521: case UNKNOWN: jjg@1521: throw new AssertionError("AnnotationWriter: UNKNOWN target type should never occur!"); jjg@1521: default: jjg@1521: throw new AssertionError("AnnotationWriter: Unknown target type for position: " + pos); jjg@1521: } jjg@1521: jjg@1521: // Append location data for generics/arrays. jjg@1521: if (!pos.location.isEmpty()) { jjg@1521: print(", location="); jjg@1521: print(pos.location); jjg@1521: } jjg@1521: } jjg@1521: jjg@46: public void write(Annotation.element_value_pair pair) { jjg@338: write(pair, false); jjg@338: } jjg@338: jjg@338: public void write(Annotation.element_value_pair pair, boolean resolveIndices) { jjg@338: writeIndex(pair.element_name_index, resolveIndices); jjg@338: print("="); jjg@338: write(pair.value, resolveIndices); jjg@46: } jjg@46: jjg@46: public void write(Annotation.element_value value) { jjg@338: write(value, false); jjg@338: } jjg@338: jjg@338: public void write(Annotation.element_value value, boolean resolveIndices) { jjg@338: ev_writer.write(value, resolveIndices); jjg@338: } jjg@338: jjg@338: private void writeDescriptor(int index, boolean resolveIndices) { jjg@338: if (resolveIndices) { jjg@338: try { jjg@338: ConstantPool constant_pool = classWriter.getClassFile().constant_pool; jjg@338: Descriptor d = new Descriptor(index); jjg@338: print(d.getFieldType(constant_pool)); jjg@338: return; jjg@338: } catch (ConstantPoolException ignore) { jjg@338: } catch (InvalidDescriptor ignore) { jjg@338: } jjg@338: } jjg@338: jjg@338: print("#" + index); jjg@338: } jjg@338: jjg@338: private void writeIndex(int index, boolean resolveIndices) { jjg@338: if (resolveIndices) { jjg@338: print(constantWriter.stringValue(index)); jjg@338: } else jjg@338: print("#" + index); jjg@46: } jjg@46: jjg@46: element_value_Writer ev_writer = new element_value_Writer(); jjg@46: jjg@338: class element_value_Writer implements Annotation.element_value.Visitor { jjg@338: public void write(Annotation.element_value value, boolean resolveIndices) { jjg@338: value.accept(this, resolveIndices); jjg@46: } jjg@46: jjg@338: public Void visitPrimitive(Primitive_element_value ev, Boolean resolveIndices) { jjg@338: if (resolveIndices) jjg@338: writeIndex(ev.const_value_index, resolveIndices); jjg@338: else jjg@338: print(((char) ev.tag) + "#" + ev.const_value_index); jjg@46: return null; jjg@46: } jjg@46: jjg@338: public Void visitEnum(Enum_element_value ev, Boolean resolveIndices) { jjg@338: if (resolveIndices) { jjg@338: writeIndex(ev.type_name_index, resolveIndices); jjg@338: print("."); jjg@338: writeIndex(ev.const_name_index, resolveIndices); jjg@338: } else jjg@338: print(((char) ev.tag) + "#" + ev.type_name_index + ".#" + ev.const_name_index); jjg@46: return null; jjg@46: } jjg@46: jjg@338: public Void visitClass(Class_element_value ev, Boolean resolveIndices) { jjg@338: if (resolveIndices) { jjg@338: writeIndex(ev.class_info_index, resolveIndices); jjg@338: print(".class"); jjg@338: } else jjg@338: print(((char) ev.tag) + "#" + ev.class_info_index); jjg@46: return null; jjg@46: } jjg@46: jjg@338: public Void visitAnnotation(Annotation_element_value ev, Boolean resolveIndices) { jjg@46: print((char) ev.tag); jjg@338: AnnotationWriter.this.write(ev.annotation_value, resolveIndices); jjg@46: return null; jjg@46: } jjg@46: jjg@338: public Void visitArray(Array_element_value ev, Boolean resolveIndices) { jjg@46: print("["); jjg@46: for (int i = 0; i < ev.num_values; i++) { jjg@46: if (i > 0) jjg@46: print(","); jjg@338: write(ev.values[i], resolveIndices); jjg@46: } jjg@46: print("]"); jjg@46: return null; jjg@46: } jjg@46: jjg@46: } jjg@338: jjg@338: private ClassWriter classWriter; jjg@338: private ConstantWriter constantWriter; jjg@46: }