Path: blob/master/src/jdk.jdeps/share/classes/com/sun/tools/javap/AnnotationWriter.java
58461 views
/*1* Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.tools.javap;2627import com.sun.tools.classfile.Annotation;28import com.sun.tools.classfile.TypeAnnotation;29import com.sun.tools.classfile.Annotation.Annotation_element_value;30import com.sun.tools.classfile.Annotation.Array_element_value;31import com.sun.tools.classfile.Annotation.Class_element_value;32import com.sun.tools.classfile.Annotation.Enum_element_value;33import com.sun.tools.classfile.Annotation.Primitive_element_value;34import com.sun.tools.classfile.ConstantPool;35import com.sun.tools.classfile.ConstantPoolException;36import com.sun.tools.classfile.Descriptor;37import com.sun.tools.classfile.Descriptor.InvalidDescriptor;3839/**40* A writer for writing annotations as text.41*42* <p><b>This is NOT part of any supported API.43* If you write code that depends on this, you do so at your own risk.44* This code and its internal interfaces are subject to change or45* deletion without notice.</b>46*/47public class AnnotationWriter extends BasicWriter {48static AnnotationWriter instance(Context context) {49AnnotationWriter instance = context.get(AnnotationWriter.class);50if (instance == null)51instance = new AnnotationWriter(context);52return instance;53}5455protected AnnotationWriter(Context context) {56super(context);57classWriter = ClassWriter.instance(context);58constantWriter = ConstantWriter.instance(context);59}6061public void write(Annotation annot) {62write(annot, false);63println();64indent(+1);65write(annot, true);66indent(-1);67}6869public void write(Annotation annot, boolean resolveIndices) {70writeDescriptor(annot.type_index, resolveIndices);71if (resolveIndices) {72boolean showParens = annot.num_element_value_pairs > 0;73if (showParens) {74println("(");75indent(+1);76}77for (int i = 0; i < annot.num_element_value_pairs; i++) {78write(annot.element_value_pairs[i], true);79println();80}81if (showParens) {82indent(-1);83print(")");84}85} else {86print("(");87for (int i = 0; i < annot.num_element_value_pairs; i++) {88if (i > 0)89print(",");90write(annot.element_value_pairs[i], false);91}92print(")");93}94}9596public void write(TypeAnnotation annot) {97write(annot, true, false);98println();99indent(+1);100write(annot.annotation, true);101indent(-1);102}103104public void write(TypeAnnotation annot, boolean showOffsets, boolean resolveIndices) {105write(annot.annotation, resolveIndices);106print(": ");107write(annot.position, showOffsets);108}109110public void write(TypeAnnotation.Position pos, boolean showOffsets) {111print(pos.type);112113switch (pos.type) {114// instanceof115case INSTANCEOF:116// new expression117case NEW:118// constructor/method reference receiver119case CONSTRUCTOR_REFERENCE:120case METHOD_REFERENCE:121if (showOffsets) {122print(", offset=");123print(pos.offset);124}125break;126// local variable127case LOCAL_VARIABLE:128// resource variable129case RESOURCE_VARIABLE:130if (pos.lvarOffset == null) {131print(", lvarOffset is Null!");132break;133}134print(", {");135for (int i = 0; i < pos.lvarOffset.length; ++i) {136if (i != 0) print("; ");137if (showOffsets) {138print("start_pc=");139print(pos.lvarOffset[i]);140}141print(", length=");142print(pos.lvarLength[i]);143print(", index=");144print(pos.lvarIndex[i]);145}146print("}");147break;148// exception parameter149case EXCEPTION_PARAMETER:150print(", exception_index=");151print(pos.exception_index);152break;153// method receiver154case METHOD_RECEIVER:155// Do nothing156break;157// type parameter158case CLASS_TYPE_PARAMETER:159case METHOD_TYPE_PARAMETER:160print(", param_index=");161print(pos.parameter_index);162break;163// type parameter bound164case CLASS_TYPE_PARAMETER_BOUND:165case METHOD_TYPE_PARAMETER_BOUND:166print(", param_index=");167print(pos.parameter_index);168print(", bound_index=");169print(pos.bound_index);170break;171// class extends or implements clause172case CLASS_EXTENDS:173print(", type_index=");174print(pos.type_index);175break;176// throws177case THROWS:178print(", type_index=");179print(pos.type_index);180break;181// method parameter182case METHOD_FORMAL_PARAMETER:183print(", param_index=");184print(pos.parameter_index);185break;186// type cast187case CAST:188// method/constructor/reference type argument189case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:190case METHOD_INVOCATION_TYPE_ARGUMENT:191case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:192case METHOD_REFERENCE_TYPE_ARGUMENT:193if (showOffsets) {194print(", offset=");195print(pos.offset);196}197print(", type_index=");198print(pos.type_index);199break;200// We don't need to worry about these201case METHOD_RETURN:202case FIELD:203break;204case UNKNOWN:205throw new AssertionError("AnnotationWriter: UNKNOWN target type should never occur!");206default:207throw new AssertionError("AnnotationWriter: Unknown target type for position: " + pos);208}209210// Append location data for generics/arrays.211if (!pos.location.isEmpty()) {212print(", location=");213print(pos.location);214}215}216217public void write(Annotation.element_value_pair pair, boolean resolveIndices) {218writeIndex(pair.element_name_index, resolveIndices);219print("=");220write(pair.value, resolveIndices);221}222223public void write(Annotation.element_value value) {224write(value, false);225println();226indent(+1);227write(value, true);228indent(-1);229}230231public void write(Annotation.element_value value, boolean resolveIndices) {232ev_writer.write(value, resolveIndices);233}234235private void writeDescriptor(int index, boolean resolveIndices) {236if (resolveIndices) {237try {238ConstantPool constant_pool = classWriter.getClassFile().constant_pool;239Descriptor d = new Descriptor(index);240print(d.getFieldType(constant_pool));241return;242} catch (ConstantPoolException | InvalidDescriptor ignore) {243}244}245246print("#" + index);247}248249private void writeIndex(int index, boolean resolveIndices) {250if (resolveIndices) {251print(constantWriter.stringValue(index));252} else253print("#" + index);254}255256element_value_Writer ev_writer = new element_value_Writer();257258class element_value_Writer implements Annotation.element_value.Visitor<Void,Boolean> {259public void write(Annotation.element_value value, boolean resolveIndices) {260value.accept(this, resolveIndices);261}262263@Override264public Void visitPrimitive(Primitive_element_value ev, Boolean resolveIndices) {265if (resolveIndices) {266int index = ev.const_value_index;267switch (ev.tag) {268case 'B':269print("(byte) ");270print(constantWriter.stringValue(index));271break;272case 'C':273print("'");274print(constantWriter.charValue(index));275print("'");276break;277case 'D':278case 'F':279case 'I':280case 'J':281print(constantWriter.stringValue(index));282break;283case 'S':284print("(short) ");285print(constantWriter.stringValue(index));286break;287case 'Z':288print(constantWriter.booleanValue(index));289break;290case 's':291print("\"");292print(constantWriter.stringValue(index));293print("\"");294break;295default:296print(((char) ev.tag) + "#" + ev.const_value_index);297break;298}299} else {300print(((char) ev.tag) + "#" + ev.const_value_index);301}302return null;303}304305@Override306public Void visitEnum(Enum_element_value ev, Boolean resolveIndices) {307if (resolveIndices) {308writeIndex(ev.type_name_index, resolveIndices);309print(".");310writeIndex(ev.const_name_index, resolveIndices);311} else {312print(((char) ev.tag) + "#" + ev.type_name_index + ".#" + ev.const_name_index);313}314return null;315}316317@Override318public Void visitClass(Class_element_value ev, Boolean resolveIndices) {319if (resolveIndices) {320print("class ");321writeIndex(ev.class_info_index, resolveIndices);322} else {323print(((char) ev.tag) + "#" + ev.class_info_index);324}325return null;326}327328@Override329public Void visitAnnotation(Annotation_element_value ev, Boolean resolveIndices) {330print((char) ev.tag);331AnnotationWriter.this.write(ev.annotation_value, resolveIndices);332return null;333}334335@Override336public Void visitArray(Array_element_value ev, Boolean resolveIndices) {337print("[");338for (int i = 0; i < ev.num_values; i++) {339if (i > 0)340print(",");341write(ev.values[i], resolveIndices);342}343print("]");344return null;345}346347}348349private final ClassWriter classWriter;350private final ConstantWriter constantWriter;351}352353354