mirror of
https://github.com/moparisthebest/fernflower
synced 2025-02-16 23:10:15 -05:00
decompiler: map all lines according to bytecode information
This commit is contained in:
parent
6d03229b91
commit
a182de6271
@ -43,6 +43,7 @@ import org.jetbrains.java.decompiler.struct.gen.VarType;
|
||||
import org.jetbrains.java.decompiler.struct.gen.generics.*;
|
||||
import org.jetbrains.java.decompiler.util.InterpreterUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -581,13 +582,9 @@ public class ClassWriter {
|
||||
boolean isDeprecated = mt.getAttributes().containsKey("Deprecated");
|
||||
boolean clinit = false, init = false, dinit = false;
|
||||
|
||||
int startLine = -1;
|
||||
StructLineNumberTableAttribute lineNumberTable = null;
|
||||
if (DecompilerContext.getOption(IFernflowerPreferences.USE_DEBUG_LINE_NUMBERS)) {
|
||||
StructLineNumberTableAttribute lineNumberTable =
|
||||
(StructLineNumberTableAttribute)mt.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE);
|
||||
if (lineNumberTable != null) {
|
||||
startLine = lineNumberTable.getFirstLine();
|
||||
}
|
||||
lineNumberTable = (StructLineNumberTableAttribute)mt.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE);
|
||||
}
|
||||
|
||||
MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor());
|
||||
@ -804,8 +801,10 @@ public class ClassWriter {
|
||||
buffer.append(' ');
|
||||
}
|
||||
|
||||
//TODO: for now only start line set
|
||||
buffer.setCurrentLine(startLine-1);
|
||||
// We do not have line information for method start, lets have it here for now
|
||||
if (lineNumberTable != null) {
|
||||
buffer.setCurrentLine(lineNumberTable.getFirstLine() - 1);
|
||||
}
|
||||
buffer.append('{').appendLineSeparator();
|
||||
|
||||
RootStatement root = wrapper.getMethodWrapper(mt.getName(), mt.getDescriptor()).root;
|
||||
@ -813,11 +812,16 @@ public class ClassWriter {
|
||||
if (root != null && !methodWrapper.decompiledWithErrors) { // check for existence
|
||||
try {
|
||||
tracer.incrementCurrentSourceLine(buffer.count(lineSeparator, start_index_method));
|
||||
int startLine = tracer.getCurrentSourceLine();
|
||||
|
||||
TextBuffer code = root.toJava(indent + 1, tracer);
|
||||
|
||||
hideMethod = (clinit || dinit || hideConstructor(wrapper, init, throwsExceptions, paramCount)) && code.length() == 0;
|
||||
|
||||
if (!hideMethod && lineNumberTable != null) {
|
||||
mapLines(code, lineNumberTable, tracer, startLine);
|
||||
}
|
||||
|
||||
buffer.append(code);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
@ -846,6 +850,33 @@ public class ClassWriter {
|
||||
return !hideMethod;
|
||||
}
|
||||
|
||||
private void mapLines(TextBuffer code, StructLineNumberTableAttribute table, BytecodeMappingTracer tracer, int startLine) {
|
||||
// build line start offsets map
|
||||
HashMap<Integer, Integer> lineStartOffsets = new HashMap<Integer, Integer>();
|
||||
for (Map.Entry<Integer, Integer> entry : tracer.getMapping().entrySet()) {
|
||||
Integer lineNumber = entry.getValue() - startLine;
|
||||
Integer curr = lineStartOffsets.get(lineNumber);
|
||||
if (curr == null || curr > entry.getKey()) {
|
||||
lineStartOffsets.put(lineNumber, entry.getKey());
|
||||
}
|
||||
}
|
||||
String lineSeparator = DecompilerContext.getNewLineSeparator();
|
||||
StringBuilder text = code.getOriginalText();
|
||||
int pos = text.indexOf(lineSeparator);
|
||||
int lineNumber = 0;
|
||||
while (pos != -1) {
|
||||
Integer startOffset = lineStartOffsets.get(lineNumber);
|
||||
if (startOffset != null) {
|
||||
int number = table.findLineNumber(startOffset);
|
||||
if (number >= 0) {
|
||||
code.setLineMapping(number, pos);
|
||||
}
|
||||
}
|
||||
pos = text.indexOf(lineSeparator, pos+1);
|
||||
lineNumber++;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hideConstructor(ClassWrapper wrapper, boolean init, boolean throwsExceptions, int paramCount) {
|
||||
if (!init || throwsExceptions || paramCount > 0 || !DecompilerContext.getOption(IFernflowerPreferences.HIDE_DEFAULT_CONSTRUCTOR)) {
|
||||
return false;
|
||||
|
@ -43,9 +43,13 @@ public class TextBuffer {
|
||||
}
|
||||
|
||||
public void setCurrentLine(int line) {
|
||||
setLineMapping(line, myStringBuilder.length()+1);
|
||||
}
|
||||
|
||||
public void setLineMapping(int line, int offset) {
|
||||
if (line >= 0) {
|
||||
checkMapCreated();
|
||||
myLineToOffsetMapping.put(line, myStringBuilder.length()+1);
|
||||
myLineToOffsetMapping.put(line, offset);
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,4 +261,8 @@ public class TextBuffer {
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public StringBuilder getOriginalText() {
|
||||
return myStringBuilder;
|
||||
}
|
||||
}
|
||||
|
@ -54,9 +54,11 @@ public class StructLineNumberTableAttribute extends StructGeneralAttribute {
|
||||
}
|
||||
|
||||
public int findLineNumber(int pc) {
|
||||
for (int i = 0; i < myLineInfo.length; i += 2) {
|
||||
if (pc >= myLineInfo[i]) {
|
||||
return myLineInfo[i + 1];
|
||||
if (myLineInfo.length >= 2) {
|
||||
for (int i = myLineInfo.length - 2; i >= 0; i -= 2) {
|
||||
if (pc >= myLineInfo[i]) {
|
||||
return myLineInfo[i + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
|
Loading…
Reference in New Issue
Block a user