1 19 20 package edu.umd.cs.findbugs.ba; 21 22 import java.util.IdentityHashMap ; 23 24 import org.apache.bcel.classfile.LineNumber; 25 import org.apache.bcel.classfile.LineNumberTable; 26 import org.apache.bcel.generic.InstructionHandle; 27 import org.apache.bcel.generic.MethodGen; 28 29 import edu.umd.cs.findbugs.SystemProperties; 30 31 35 public class LineNumberMap { 36 39 private static final boolean DEBUG = SystemProperties.getBoolean("lnm.debug"); 40 41 45 private static final boolean LINE_NUMBER_BUG = SystemProperties.getBoolean("lineNumberBug"); 46 47 private MethodGen methodGen; 48 private IdentityHashMap <InstructionHandle, LineNumber> lineNumberMap; 49 private boolean hasLineNumbers; 50 51 56 public LineNumberMap(MethodGen methodGen) { 57 this.methodGen = methodGen; 58 lineNumberMap = new IdentityHashMap <InstructionHandle, LineNumber>(); 59 hasLineNumbers = false; 60 } 61 62 66 public void build() { 67 int numGood = 0, numBytecodes = 0; 68 69 if (DEBUG) { 70 System.out.println("Method: " + methodGen.getName() + " - " + methodGen.getSignature() + 71 "in class " + methodGen.getClassName()); 72 } 73 74 LineNumberTable table = methodGen.getLineNumberTable(methodGen.getConstantPool()); 76 77 if (table != null && table.getTableLength() > 0) { 78 checkTable(table); 79 InstructionHandle handle = methodGen.getInstructionList().getStart(); 80 while (handle != null) { 81 int bytecodeOffset = handle.getPosition(); 82 if (bytecodeOffset < 0) 83 throw new IllegalStateException ("Bad bytecode offset: " + bytecodeOffset); 84 if (DEBUG) System.out.println("Looking for source line for bytecode offset " + bytecodeOffset); 85 int sourceLine; 86 try { 87 sourceLine = table.getSourceLine(bytecodeOffset); 88 } catch (ArrayIndexOutOfBoundsException e) { 89 if (LINE_NUMBER_BUG) 90 throw e; 91 else 92 sourceLine = -1; 93 } 94 if (sourceLine >= 0) 95 ++numGood; 96 lineNumberMap.put(handle, 97 new LineNumber(bytecodeOffset, sourceLine)); 98 handle = handle.getNext(); 99 ++numBytecodes; 100 } 101 hasLineNumbers = true; 102 103 if (DEBUG) System.out.println("\t" + numGood + "/" + numBytecodes + " had valid line numbers"); 104 } 105 } 106 107 private void checkTable(LineNumberTable table) { 108 if (DEBUG) System.out.println("line number table has length " + table.getTableLength()); 109 LineNumber[] entries = table.getLineNumberTable(); 110 int lastBytecode = -1; 111 for (int i = 0; i < entries.length; ++i) { 112 LineNumber ln = entries[i]; 113 if (DEBUG) System.out.println("Entry " + i + ": pc=" + ln.getStartPC() + ", line=" + ln.getLineNumber()); 114 int pc = ln.getStartPC(); 115 if (pc <= lastBytecode) throw new IllegalStateException ("LineNumberTable is not sorted"); 116 } 117 } 118 119 122 public boolean hasLineNumbers() { 123 return hasLineNumbers; 124 } 125 126 133 public LineNumber lookupLineNumber(InstructionHandle handle) { 134 return lineNumberMap.get(handle); 135 } 136 } 137 | Popular Tags |