decompiler: build original lines mapping

master
Egor.Ushakov 10 years ago
parent fdc75e3c80
commit 1a183952b4
  1. 11
      src/org/jetbrains/java/decompiler/main/ClassWriter.java
  2. 5
      src/org/jetbrains/java/decompiler/main/TextBuffer.java
  3. 32
      src/org/jetbrains/java/decompiler/main/collectors/BytecodeMappingTracer.java
  4. 24
      src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java
  5. 4
      src/org/jetbrains/java/decompiler/struct/attr/StructLineNumberTableAttribute.java
  6. 10
      testData/results/TestClassSimpleBytecodeMapping.dec

@ -577,10 +577,9 @@ public class ClassWriter {
boolean isDeprecated = mt.getAttributes().containsKey("Deprecated"); boolean isDeprecated = mt.getAttributes().containsKey("Deprecated");
boolean clinit = false, init = false, dinit = false; boolean clinit = false, init = false, dinit = false;
StructLineNumberTableAttribute lineNumberTable = null; StructLineNumberTableAttribute lineNumberTable =
if (DecompilerContext.getOption(IFernflowerPreferences.USE_DEBUG_LINE_NUMBERS)) { (StructLineNumberTableAttribute)mt.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE);
lineNumberTable = (StructLineNumberTableAttribute)mt.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE); tracer.setLineNumberTable(lineNumberTable);
}
MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor()); MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor());
@ -797,7 +796,7 @@ public class ClassWriter {
} }
// We do not have line information for method start, lets have it here for now // We do not have line information for method start, lets have it here for now
if (lineNumberTable != null) { if (lineNumberTable != null && DecompilerContext.getOption(IFernflowerPreferences.USE_DEBUG_LINE_NUMBERS)) {
buffer.setCurrentLine(lineNumberTable.getFirstLine() - 1); buffer.setCurrentLine(lineNumberTable.getFirstLine() - 1);
} }
buffer.append('{').appendLineSeparator(); buffer.append('{').appendLineSeparator();
@ -813,7 +812,7 @@ public class ClassWriter {
hideMethod = (clinit || dinit || hideConstructor(wrapper, init, throwsExceptions, paramCount)) && code.length() == 0; hideMethod = (clinit || dinit || hideConstructor(wrapper, init, throwsExceptions, paramCount)) && code.length() == 0;
if (!hideMethod && lineNumberTable != null) { if (!hideMethod && lineNumberTable != null && DecompilerContext.getOption(IFernflowerPreferences.USE_DEBUG_LINE_NUMBERS)) {
mapLines(code, lineNumberTable, tracer, startLine); mapLines(code, lineNumberTable, tracer, startLine);
} }

@ -63,6 +63,11 @@ public class TextBuffer {
return this; return this;
} }
public TextBuffer append(int i) {
myStringBuilder.append(i);
return this;
}
public TextBuffer appendLineSeparator() { public TextBuffer appendLineSeparator() {
myStringBuilder.append(myLineSeparator); myStringBuilder.append(myLineSeparator);
return this; return this;

@ -1,6 +1,10 @@
package org.jetbrains.java.decompiler.main.collectors; package org.jetbrains.java.decompiler.main.collectors;
import org.jetbrains.java.decompiler.struct.attr.StructLineNumberTableAttribute;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
@ -8,6 +12,8 @@ public class BytecodeMappingTracer {
private int current_sourceline; private int current_sourceline;
private StructLineNumberTableAttribute myLineNumberTable = null;
// bytecode offset, source line // bytecode offset, source line
private HashMap<Integer, Integer> mapping = new HashMap<Integer, Integer>(); private HashMap<Integer, Integer> mapping = new HashMap<Integer, Integer>();
@ -67,4 +73,30 @@ public class BytecodeMappingTracer {
this.current_sourceline = current_sourceline; this.current_sourceline = current_sourceline;
} }
public void setLineNumberTable(StructLineNumberTableAttribute lineNumberTable) {
myLineNumberTable = lineNumberTable;
}
public Map<Integer, Integer> getOriginalLinesMapping() {
if (myLineNumberTable == null) {
return Collections.emptyMap();
}
HashMap<Integer, Integer> res = new HashMap<Integer, Integer>();
int[] data = myLineNumberTable.getRawData();
for (int i = 0; i < data.length; i+=2) {
int originalOffset = data[i];
int originalLine = data[i+1];
Integer newLine = mapping.get(originalOffset);
if (newLine != null) {
res.put(originalLine, newLine);
}
}
for (Entry<Integer, Integer> entry : mapping.entrySet()) {
int originalLine = myLineNumberTable.findLineNumber(entry.getKey());
if (originalLine > -1) {
res.put(originalLine, entry.getValue());
}
}
return res;
}
} }

@ -10,6 +10,8 @@ public class BytecodeSourceMapper {
private int offset_total; private int offset_total;
private final HashMap<Integer, Integer> myOriginalLinesMapping = new HashMap<Integer, Integer>();
// class, method, bytecode offset, source line // class, method, bytecode offset, source line
private final HashMap<String, HashMap<String, HashMap<Integer, Integer>>> mapping = new LinkedHashMap<String, HashMap<String, HashMap<Integer, Integer>>>(); // need to preserve order private final HashMap<String, HashMap<String, HashMap<Integer, Integer>>> mapping = new LinkedHashMap<String, HashMap<String, HashMap<Integer, Integer>>>(); // need to preserve order
@ -35,6 +37,7 @@ public class BytecodeSourceMapper {
for(Entry<Integer, Integer> entry : tracer.getMapping().entrySet()) { for(Entry<Integer, Integer> entry : tracer.getMapping().entrySet()) {
addMapping(classname, methodname, entry.getKey(), entry.getValue()); addMapping(classname, methodname, entry.getKey(), entry.getValue());
} }
myOriginalLinesMapping.putAll(tracer.getOriginalLinesMapping());
} }
public void dumpMapping(TextBuffer buffer, boolean offsetsToHex) { public void dumpMapping(TextBuffer buffer, boolean offsetsToHex) {
@ -69,6 +72,13 @@ public class BytecodeSourceMapper {
} }
buffer.append("}").appendLineSeparator(); buffer.append("}").appendLineSeparator();
} }
// lines mapping
buffer.append("Lines mapping:").appendLineSeparator();
int[] mapping = getOriginalLinesMapping();
for (int i = 0; i < mapping.length; i+=2) {
buffer.append(mapping[i]).append(" <-> ").append(mapping[i+1]).appendLineSeparator();
}
} }
public int getTotalOffset() { public int getTotalOffset() {
@ -83,5 +93,17 @@ public class BytecodeSourceMapper {
this.offset_total += offset_total; this.offset_total += offset_total;
} }
/**
* original to our line mapping
*/
public int[] getOriginalLinesMapping() {
int[] res = new int[myOriginalLinesMapping.size()*2];
int i = 0;
for (Entry<Integer, Integer> entry : myOriginalLinesMapping.entrySet()) {
res[i] = entry.getKey();
res[i+1] = entry.getValue() + offset_total + 1; // make it 1 based
i+=2;
}
return res;
}
} }

@ -63,4 +63,8 @@ public class StructLineNumberTableAttribute extends StructGeneralAttribute {
} }
return -1; return -1;
} }
public int[] getRawData() {
return myLineInfo;
}
} }

@ -55,3 +55,13 @@ class pkg/TestClassSimpleBytecodeMapping{
1 20 1 20
} }
} }
Lines mapping:
17 <-> 8
21 <-> 11
22 <-> 12
23 <-> 13
25 <-> 15
26 <-> 16
12 <-> 5
14 <-> 6
31 <-> 21

Loading…
Cancel
Save