1 16 17 package com.google.inject.util; 18 19 import java.io.IOException ; 20 import java.io.InputStream ; 21 import java.lang.reflect.*; 22 import java.util.HashMap ; 23 import java.util.Map ; 24 import org.objectweb.asm.*; 25 import org.objectweb.asm.Type; 26 27 32 public class LineNumbers { 33 34 private final Class cls; 35 private Map <String , Integer > lines = new HashMap <String , Integer >(); 36 private String source; 37 private int firstLine = Integer.MAX_VALUE; 38 39 47 public LineNumbers(Class cls) throws IOException { 48 this.cls = cls; 49 InputStream in = cls 50 .getResourceAsStream("/" + cls.getName().replace('.', '/') + ".class"); 51 if (in == null) { 52 throw new IllegalArgumentException ("Cannot find bytecode for " + cls); 53 } 54 new ClassReader(in).accept(new LineNumberReader(), 0); 55 } 56 57 62 public String getSource() { 63 return source; 64 } 65 66 75 public Integer getLineNumber(Member member) { 76 if (!cls.equals(member.getDeclaringClass())) { 77 throw new IllegalArgumentException ("Member " + member + " belongs to " 78 + member.getDeclaringClass() + ", not " + cls); 79 } 80 return lines.get(getKey(member)); 81 } 82 83 86 public int getFirstLine() { 87 return firstLine == Integer.MAX_VALUE ? 1 : firstLine; 88 } 89 90 private static String getKey(Member member) { 91 if (member instanceof Field) { 92 return member.getName(); 93 } 94 else if (member instanceof Method) { 95 return member.getName() + Type.getMethodDescriptor((Method) member); 96 } 97 else { 98 return "<init>" + Type.getConstructorDescriptor((Constructor) member); 99 } 100 } 101 102 private class LineNumberReader implements ClassVisitor, MethodVisitor { 103 104 private int line = -1; 105 private String pendingMethod; 106 private String name; 107 108 public void visit(int version, int access, String name, String signature, 109 String superName, String [] interfaces) { 110 this.name = name; 111 } 112 113 public MethodVisitor visitMethod(int access, String name, String desc, 114 String signature, String [] exceptions) { 115 if ((access & Opcodes.ACC_PRIVATE) != 0) { 116 return null; 117 } 118 pendingMethod = name + desc; 119 line = -1; 120 return this; 121 } 122 123 public void visitSource(String source, String debug) { 124 LineNumbers.this.source = source; 125 } 126 127 public void visitLineNumber(int line, Label start) { 128 if (line < firstLine) { 129 firstLine = line; 130 } 131 132 this.line = line; 133 if (pendingMethod != null) { 134 lines.put(pendingMethod, line); 135 pendingMethod = null; 136 } 137 } 138 139 public void visitFieldInsn(int opcode, String owner, String name, 140 String desc) { 141 if (opcode == Opcodes.PUTFIELD && this.name.equals(owner) 142 && !lines.containsKey(name) && line != -1) { 143 lines.put(name, line); 144 } 145 } 146 147 public void visitEnd() { 148 } 149 150 public void visitInnerClass(String name, String outerName, String innerName, 151 int access) { 152 } 153 154 public void visitOuterClass(String owner, String name, String desc) { 155 } 156 157 public void visitAttribute(Attribute attr) { 158 } 159 160 public FieldVisitor visitField(int access, String name, String desc, 161 String signature, Object value) { 162 return null; 163 } 164 165 public AnnotationVisitor visitAnnotation(String desc, boolean visible) { 166 return null; 167 } 168 169 public AnnotationVisitor visitAnnotationDefault() { 170 return null; 171 } 172 173 public AnnotationVisitor visitParameterAnnotation(int parameter, 174 String desc, boolean visible) { 175 return null; 176 } 177 178 public void visitCode() { 179 } 180 181 public void visitFrame(int type, int nLocal, Object [] local, int nStack, 182 Object [] stack) { 183 } 184 185 public void visitIincInsn(int var, int increment) { 186 } 187 188 public void visitInsn(int opcode) { 189 } 190 191 public void visitIntInsn(int opcode, int operand) { 192 } 193 194 public void visitJumpInsn(int opcode, Label label) { 195 } 196 197 public void visitLabel(Label label) { 198 } 199 200 public void visitLdcInsn(Object cst) { 201 } 202 203 public void visitLocalVariable(String name, String desc, String signature, 204 Label start, Label end, int index) { 205 } 206 207 public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { 208 } 209 210 public void visitMaxs(int maxStack, int maxLocals) { 211 } 212 213 public void visitMethodInsn(int opcode, String owner, String name, 214 String desc) { 215 } 216 217 public void visitMultiANewArrayInsn(String desc, int dims) { 218 } 219 220 public void visitTableSwitchInsn(int min, int max, Label dflt, 221 Label[] labels) { 222 } 223 224 public void visitTryCatchBlock(Label start, Label end, Label handler, 225 String type) { 226 } 227 228 public void visitTypeInsn(int opcode, String desc) { 229 } 230 231 public void visitVarInsn(int opcode, int var) { 232 } 233 } 234 } 235 | Popular Tags |