mirror of
https://github.com/moparisthebest/fernflower
synced 2024-08-13 17:03:46 -04: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.struct.gen.generics.*;
|
||||||
import org.jetbrains.java.decompiler.util.InterpreterUtil;
|
import org.jetbrains.java.decompiler.util.InterpreterUtil;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -581,13 +582,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;
|
||||||
|
|
||||||
int startLine = -1;
|
StructLineNumberTableAttribute lineNumberTable = null;
|
||||||
if (DecompilerContext.getOption(IFernflowerPreferences.USE_DEBUG_LINE_NUMBERS)) {
|
if (DecompilerContext.getOption(IFernflowerPreferences.USE_DEBUG_LINE_NUMBERS)) {
|
||||||
StructLineNumberTableAttribute lineNumberTable =
|
lineNumberTable = (StructLineNumberTableAttribute)mt.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE);
|
||||||
(StructLineNumberTableAttribute)mt.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE);
|
|
||||||
if (lineNumberTable != null) {
|
|
||||||
startLine = lineNumberTable.getFirstLine();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor());
|
MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor());
|
||||||
@ -804,8 +801,10 @@ public class ClassWriter {
|
|||||||
buffer.append(' ');
|
buffer.append(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: for now only start line set
|
// We do not have line information for method start, lets have it here for now
|
||||||
buffer.setCurrentLine(startLine-1);
|
if (lineNumberTable != null) {
|
||||||
|
buffer.setCurrentLine(lineNumberTable.getFirstLine() - 1);
|
||||||
|
}
|
||||||
buffer.append('{').appendLineSeparator();
|
buffer.append('{').appendLineSeparator();
|
||||||
|
|
||||||
RootStatement root = wrapper.getMethodWrapper(mt.getName(), mt.getDescriptor()).root;
|
RootStatement root = wrapper.getMethodWrapper(mt.getName(), mt.getDescriptor()).root;
|
||||||
@ -813,11 +812,16 @@ public class ClassWriter {
|
|||||||
if (root != null && !methodWrapper.decompiledWithErrors) { // check for existence
|
if (root != null && !methodWrapper.decompiledWithErrors) { // check for existence
|
||||||
try {
|
try {
|
||||||
tracer.incrementCurrentSourceLine(buffer.count(lineSeparator, start_index_method));
|
tracer.incrementCurrentSourceLine(buffer.count(lineSeparator, start_index_method));
|
||||||
|
int startLine = tracer.getCurrentSourceLine();
|
||||||
|
|
||||||
TextBuffer code = root.toJava(indent + 1, tracer);
|
TextBuffer code = root.toJava(indent + 1, tracer);
|
||||||
|
|
||||||
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) {
|
||||||
|
mapLines(code, lineNumberTable, tracer, startLine);
|
||||||
|
}
|
||||||
|
|
||||||
buffer.append(code);
|
buffer.append(code);
|
||||||
}
|
}
|
||||||
catch (Throwable ex) {
|
catch (Throwable ex) {
|
||||||
@ -846,6 +850,33 @@ public class ClassWriter {
|
|||||||
return !hideMethod;
|
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) {
|
private static boolean hideConstructor(ClassWrapper wrapper, boolean init, boolean throwsExceptions, int paramCount) {
|
||||||
if (!init || throwsExceptions || paramCount > 0 || !DecompilerContext.getOption(IFernflowerPreferences.HIDE_DEFAULT_CONSTRUCTOR)) {
|
if (!init || throwsExceptions || paramCount > 0 || !DecompilerContext.getOption(IFernflowerPreferences.HIDE_DEFAULT_CONSTRUCTOR)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -43,9 +43,13 @@ public class TextBuffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setCurrentLine(int line) {
|
public void setCurrentLine(int line) {
|
||||||
|
setLineMapping(line, myStringBuilder.length()+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLineMapping(int line, int offset) {
|
||||||
if (line >= 0) {
|
if (line >= 0) {
|
||||||
checkMapCreated();
|
checkMapCreated();
|
||||||
myLineToOffsetMapping.put(line, myStringBuilder.length()+1);
|
myLineToOffsetMapping.put(line, offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,4 +261,8 @@ public class TextBuffer {
|
|||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public StringBuilder getOriginalText() {
|
||||||
|
return myStringBuilder;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,9 +54,11 @@ public class StructLineNumberTableAttribute extends StructGeneralAttribute {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int findLineNumber(int pc) {
|
public int findLineNumber(int pc) {
|
||||||
for (int i = 0; i < myLineInfo.length; i += 2) {
|
if (myLineInfo.length >= 2) {
|
||||||
if (pc >= myLineInfo[i]) {
|
for (int i = myLineInfo.length - 2; i >= 0; i -= 2) {
|
||||||
return myLineInfo[i + 1];
|
if (pc >= myLineInfo[i]) {
|
||||||
|
return myLineInfo[i + 1];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
Loading…
Reference in New Issue
Block a user