TypeAnnotationWriter.java revision 3170:dc017a37aac5
1/* 2 * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.tools.javap; 27 28import com.sun.tools.classfile.Attribute; 29import com.sun.tools.classfile.Code_attribute; 30import com.sun.tools.classfile.TypeAnnotation; 31import com.sun.tools.classfile.TypeAnnotation.Position; 32import com.sun.tools.classfile.Instruction; 33import com.sun.tools.classfile.Method; 34import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute; 35import com.sun.tools.classfile.RuntimeTypeAnnotations_attribute; 36import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute; 37import java.util.ArrayList; 38import java.util.HashMap; 39import java.util.List; 40import java.util.Map; 41import com.sun.tools.javac.util.StringUtils; 42 43/** 44 * Annotate instructions with details about type annotations. 45 * 46 * <p><b>This is NOT part of any supported API. 47 * If you write code that depends on this, you do so at your own risk. 48 * This code and its internal interfaces are subject to change or 49 * deletion without notice.</b> 50 */ 51public class TypeAnnotationWriter extends InstructionDetailWriter { 52 public enum NoteKind { VISIBLE, INVISIBLE } 53 54 public static class Note { 55 Note(NoteKind kind, TypeAnnotation anno) { 56 this.kind = kind; 57 this.anno = anno; 58 } 59 public final NoteKind kind; 60 public final TypeAnnotation anno; 61 } 62 63 static TypeAnnotationWriter instance(Context context) { 64 TypeAnnotationWriter instance = context.get(TypeAnnotationWriter.class); 65 if (instance == null) 66 instance = new TypeAnnotationWriter(context); 67 return instance; 68 } 69 70 protected TypeAnnotationWriter(Context context) { 71 super(context); 72 context.put(TypeAnnotationWriter.class, this); 73 annotationWriter = AnnotationWriter.instance(context); 74 classWriter = ClassWriter.instance(context); 75 } 76 77 public void reset(Code_attribute attr) { 78 Method m = classWriter.getMethod(); 79 pcMap = new HashMap<>(); 80 check(NoteKind.VISIBLE, (RuntimeVisibleTypeAnnotations_attribute) m.attributes.get(Attribute.RuntimeVisibleTypeAnnotations)); 81 check(NoteKind.INVISIBLE, (RuntimeInvisibleTypeAnnotations_attribute) m.attributes.get(Attribute.RuntimeInvisibleTypeAnnotations)); 82 } 83 84 private void check(NoteKind kind, RuntimeTypeAnnotations_attribute attr) { 85 if (attr == null) 86 return; 87 88 for (TypeAnnotation anno: attr.annotations) { 89 Position p = anno.position; 90 Note note = null; 91 if (p.offset != -1) 92 addNote(p.offset, note = new Note(kind, anno)); 93 if (p.lvarOffset != null) { 94 for (int i = 0; i < p.lvarOffset.length; i++) { 95 if (note == null) 96 note = new Note(kind, anno); 97 addNote(p.lvarOffset[i], note); 98 } 99 } 100 } 101 } 102 103 private void addNote(int pc, Note note) { 104 List<Note> list = pcMap.get(pc); 105 if (list == null) 106 pcMap.put(pc, list = new ArrayList<>()); 107 list.add(note); 108 } 109 110 @Override 111 void writeDetails(Instruction instr) { 112 String indent = space(2); // get from Options? 113 int pc = instr.getPC(); 114 List<Note> notes = pcMap.get(pc); 115 if (notes != null) { 116 for (Note n: notes) { 117 print(indent); 118 print("@"); 119 annotationWriter.write(n.anno, false, true); 120 print(", "); 121 println(StringUtils.toLowerCase(n.kind.toString())); 122 } 123 } 124 } 125 126 private AnnotationWriter annotationWriter; 127 private ClassWriter classWriter; 128 private Map<Integer, List<Note>> pcMap; 129} 130