Started work on mapping bytecode instructions to source code lines
This commit is contained in:
@@ -17,6 +17,7 @@ package org.jetbrains.java.decompiler.main;
|
||||
|
||||
import org.jetbrains.java.decompiler.code.CodeConstants;
|
||||
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
|
||||
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
|
||||
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
|
||||
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
|
||||
import org.jetbrains.java.decompiler.main.rels.ClassWrapper;
|
||||
@@ -90,6 +91,8 @@ public class ClassWriter {
|
||||
ClassNode outerNode = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE);
|
||||
DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, node);
|
||||
|
||||
BytecodeMappingTracer tracer = new BytecodeMappingTracer();
|
||||
|
||||
try {
|
||||
ClassWrapper wrapper = classNode.wrapper;
|
||||
StructClass cl = wrapper.getClassStruct();
|
||||
@@ -99,7 +102,7 @@ public class ClassWriter {
|
||||
if (node.lambda_information.is_method_reference) {
|
||||
if (!node.lambda_information.is_content_method_static && method_object != null) {
|
||||
// reference to a virtual method
|
||||
buffer.append(method_object.toJava(indent));
|
||||
buffer.append(method_object.toJava(indent, tracer));
|
||||
}
|
||||
else {
|
||||
// reference to a static method
|
||||
@@ -144,7 +147,7 @@ public class ClassWriter {
|
||||
buffer.append(" {");
|
||||
buffer.append(DecompilerContext.getNewLineSeparator());
|
||||
|
||||
methodLambdaToJava(node, classNode, mt, buffer, indent + 1, !lambdaToAnonymous);
|
||||
methodLambdaToJava(node, classNode, mt, buffer, indent + 1, !lambdaToAnonymous, tracer);
|
||||
|
||||
InterpreterUtil.appendIndent(buffer, indent);
|
||||
buffer.append("}");
|
||||
@@ -161,6 +164,8 @@ public class ClassWriter {
|
||||
ClassNode outerNode = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE);
|
||||
DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, node);
|
||||
|
||||
BytecodeMappingTracer tracer = new BytecodeMappingTracer();
|
||||
|
||||
try {
|
||||
// last minute processing
|
||||
invokeProcessors(node);
|
||||
@@ -199,7 +204,7 @@ public class ClassWriter {
|
||||
enumFields = false;
|
||||
}
|
||||
|
||||
fieldToJava(wrapper, cl, fd, buffer, indent + 1);
|
||||
fieldToJava(wrapper, cl, fd, buffer, indent + 1, tracer);
|
||||
|
||||
hasContent = true;
|
||||
}
|
||||
@@ -220,7 +225,7 @@ public class ClassWriter {
|
||||
if (hasContent) {
|
||||
buffer.append(lineSeparator);
|
||||
}
|
||||
boolean methodSkipped = !methodToJava(node, mt, buffer, indent + 1);
|
||||
boolean methodSkipped = !methodToJava(node, mt, buffer, indent + 1, tracer);
|
||||
if (!methodSkipped) {
|
||||
hasContent = true;
|
||||
}
|
||||
@@ -372,7 +377,7 @@ public class ClassWriter {
|
||||
buffer.append(lineSeparator);
|
||||
}
|
||||
|
||||
private void fieldToJava(ClassWrapper wrapper, StructClass cl, StructField fd, StringBuilder buffer, int indent) {
|
||||
private void fieldToJava(ClassWrapper wrapper, StructClass cl, StructField fd, StringBuilder buffer, int indent, BytecodeMappingTracer tracer) {
|
||||
String indentString = InterpreterUtil.getIndentString(indent);
|
||||
String lineSeparator = DecompilerContext.getNewLineSeparator();
|
||||
|
||||
@@ -434,11 +439,12 @@ public class ClassWriter {
|
||||
if (isEnum && initializer.type == Exprent.EXPRENT_NEW) {
|
||||
NewExprent nexpr = (NewExprent)initializer;
|
||||
nexpr.setEnumconst(true);
|
||||
buffer.append(nexpr.toJava(indent));
|
||||
buffer.append(nexpr.toJava(indent, tracer));
|
||||
}
|
||||
else {
|
||||
buffer.append(" = ");
|
||||
buffer.append(initializer.toJava(indent));
|
||||
// FIXME: special case field initializer. Can map to more than one method (constructor) and bytecode intruction.
|
||||
buffer.append(initializer.toJava(indent, tracer));
|
||||
}
|
||||
}
|
||||
else if (fd.hasModifier(CodeConstants.ACC_FINAL) && fd.hasModifier(CodeConstants.ACC_STATIC)) {
|
||||
@@ -447,7 +453,7 @@ public class ClassWriter {
|
||||
if (attr != null) {
|
||||
PrimitiveConstant constant = cl.getPool().getPrimitiveConstant(attr.getIndex());
|
||||
buffer.append(" = ");
|
||||
buffer.append(new ConstExprent(fieldType, constant.value).toJava(indent));
|
||||
buffer.append(new ConstExprent(fieldType, constant.value).toJava(indent, tracer));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,7 +468,7 @@ public class ClassWriter {
|
||||
StructMethod mt,
|
||||
StringBuilder buffer,
|
||||
int indent,
|
||||
boolean codeOnly) {
|
||||
boolean codeOnly, BytecodeMappingTracer tracer) {
|
||||
ClassWrapper classWrapper = classNode.wrapper;
|
||||
MethodWrapper methodWrapper = classWrapper.getMethodWrapper(mt.getName(), mt.getDescriptor());
|
||||
|
||||
@@ -518,7 +524,7 @@ public class ClassWriter {
|
||||
RootStatement root = classWrapper.getMethodWrapper(mt.getName(), mt.getDescriptor()).root;
|
||||
if (root != null) { // check for existence
|
||||
try {
|
||||
buffer.append(root.toJava(indent));
|
||||
buffer.append(root.toJava(indent, tracer));
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
DecompilerContext.getLogger().writeMessage("Method " + mt.getName() + " " + mt.getDescriptor() + " couldn't be written.", ex);
|
||||
@@ -546,7 +552,7 @@ public class ClassWriter {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean methodToJava(ClassNode node, StructMethod mt, StringBuilder buffer, int indent) {
|
||||
private boolean methodToJava(ClassNode node, StructMethod mt, StringBuilder buffer, int indent, BytecodeMappingTracer tracer) {
|
||||
ClassWrapper wrapper = node.wrapper;
|
||||
StructClass cl = wrapper.getClassStruct();
|
||||
MethodWrapper methodWrapper = wrapper.getMethodWrapper(mt.getName(), mt.getDescriptor());
|
||||
@@ -768,7 +774,7 @@ public class ClassWriter {
|
||||
StructAnnDefaultAttribute attr = (StructAnnDefaultAttribute)mt.getAttributes().getWithKey("AnnotationDefault");
|
||||
if (attr != null) {
|
||||
buffer.append(" default ");
|
||||
buffer.append(attr.getDefaultValue().toJava(indent + 1));
|
||||
buffer.append(attr.getDefaultValue().toJava(indent + 1, new BytecodeMappingTracer())); // dummy tracer
|
||||
}
|
||||
}
|
||||
|
||||
@@ -787,7 +793,7 @@ public class ClassWriter {
|
||||
|
||||
if (root != null && !methodWrapper.decompiledWithErrors) { // check for existence
|
||||
try {
|
||||
String code = root.toJava(indent + 1);
|
||||
String code = root.toJava(indent + 1, tracer);
|
||||
|
||||
hideMethod = (clinit || dinit || hideConstructor(wrapper, init, throwsExceptions, paramCount)) && code.length() == 0;
|
||||
|
||||
@@ -896,11 +902,14 @@ public class ClassWriter {
|
||||
StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS};
|
||||
|
||||
private static void appendAnnotations(StringBuilder buffer, StructMember mb, int indent, String lineSeparator) {
|
||||
|
||||
BytecodeMappingTracer tracer_dummy = new BytecodeMappingTracer(); // FIXME: replace with a real one
|
||||
|
||||
for (String name : ANNOTATION_ATTRIBUTES) {
|
||||
StructAnnotationAttribute attribute = (StructAnnotationAttribute)mb.getAttributes().getWithKey(name);
|
||||
if (attribute != null) {
|
||||
for (AnnotationExprent annotation : attribute.getAnnotations()) {
|
||||
buffer.append(annotation.toJava(indent)).append(lineSeparator);
|
||||
buffer.append(annotation.toJava(indent, tracer_dummy)).append(lineSeparator);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -910,13 +919,16 @@ public class ClassWriter {
|
||||
StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS};
|
||||
|
||||
private static void appendParameterAnnotations(StringBuilder buffer, StructMethod mt, int param) {
|
||||
|
||||
BytecodeMappingTracer tracer_dummy = new BytecodeMappingTracer(); // FIXME: replace with a real one
|
||||
|
||||
for (String name : PARAMETER_ANNOTATION_ATTRIBUTES) {
|
||||
StructAnnotationParameterAttribute attribute = (StructAnnotationParameterAttribute)mt.getAttributes().getWithKey(name);
|
||||
if (attribute != null) {
|
||||
List<List<AnnotationExprent>> annotations = attribute.getParamAnnotations();
|
||||
if (param < annotations.size()) {
|
||||
for (AnnotationExprent annotation : annotations.get(param)) {
|
||||
buffer.append(annotation.toJava(0)).append(' ');
|
||||
buffer.append(annotation.toJava(0, tracer_dummy)).append(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user