Started work on mapping bytecode instructions to source code lines

master
Stiver 10 years ago
parent 91c64c5a94
commit f735cbc7ea
  1. 42
      src/org/jetbrains/java/decompiler/main/ClassWriter.java
  2. 7
      src/org/jetbrains/java/decompiler/main/ClassesProcessor.java
  3. 10
      src/org/jetbrains/java/decompiler/main/DecompilerContext.java
  4. 26
      src/org/jetbrains/java/decompiler/main/collectors/BytecodeMappingTracer.java
  5. 75
      src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java
  6. 4
      src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java
  7. 21
      src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java
  8. 8
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/AnnotationExprent.java
  9. 8
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/ArrayExprent.java
  10. 9
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssertExprent.java
  11. 8
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssignmentExprent.java
  12. 12
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java
  13. 10
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/ExitExprent.java
  14. 3
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/Exprent.java
  15. 6
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java
  16. 62
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java
  17. 6
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/IfExprent.java
  18. 10
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java
  19. 6
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/MonitorExprent.java
  20. 22
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java
  21. 6
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/SwitchExprent.java
  22. 4
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java
  23. 7
      src/org/jetbrains/java/decompiler/modules/decompiler/stats/BasicBlockStatement.java
  24. 21
      src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java
  25. 18
      src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java
  26. 30
      src/org/jetbrains/java/decompiler/modules/decompiler/stats/DoStatement.java
  27. 5
      src/org/jetbrains/java/decompiler/modules/decompiler/stats/GeneralStatement.java
  28. 21
      src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java
  29. 7
      src/org/jetbrains/java/decompiler/modules/decompiler/stats/RootStatement.java
  30. 10
      src/org/jetbrains/java/decompiler/modules/decompiler/stats/SequenceStatement.java
  31. 9
      src/org/jetbrains/java/decompiler/modules/decompiler/stats/Statement.java
  32. 18
      src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java
  33. 17
      src/org/jetbrains/java/decompiler/modules/decompiler/stats/SynchronizedStatement.java

@ -17,6 +17,7 @@ package org.jetbrains.java.decompiler.main;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; 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.IFernflowerLogger;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.jetbrains.java.decompiler.main.rels.ClassWrapper; import org.jetbrains.java.decompiler.main.rels.ClassWrapper;
@ -90,6 +91,8 @@ public class ClassWriter {
ClassNode outerNode = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE); ClassNode outerNode = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE);
DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, node); DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, node);
BytecodeMappingTracer tracer = new BytecodeMappingTracer();
try { try {
ClassWrapper wrapper = classNode.wrapper; ClassWrapper wrapper = classNode.wrapper;
StructClass cl = wrapper.getClassStruct(); StructClass cl = wrapper.getClassStruct();
@ -99,7 +102,7 @@ public class ClassWriter {
if (node.lambda_information.is_method_reference) { if (node.lambda_information.is_method_reference) {
if (!node.lambda_information.is_content_method_static && method_object != null) { if (!node.lambda_information.is_content_method_static && method_object != null) {
// reference to a virtual method // reference to a virtual method
buffer.append(method_object.toJava(indent)); buffer.append(method_object.toJava(indent, tracer));
} }
else { else {
// reference to a static method // reference to a static method
@ -144,7 +147,7 @@ public class ClassWriter {
buffer.append(" {"); buffer.append(" {");
buffer.append(DecompilerContext.getNewLineSeparator()); 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); InterpreterUtil.appendIndent(buffer, indent);
buffer.append("}"); buffer.append("}");
@ -161,6 +164,8 @@ public class ClassWriter {
ClassNode outerNode = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE); ClassNode outerNode = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE);
DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, node); DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, node);
BytecodeMappingTracer tracer = new BytecodeMappingTracer();
try { try {
// last minute processing // last minute processing
invokeProcessors(node); invokeProcessors(node);
@ -199,7 +204,7 @@ public class ClassWriter {
enumFields = false; enumFields = false;
} }
fieldToJava(wrapper, cl, fd, buffer, indent + 1); fieldToJava(wrapper, cl, fd, buffer, indent + 1, tracer);
hasContent = true; hasContent = true;
} }
@ -220,7 +225,7 @@ public class ClassWriter {
if (hasContent) { if (hasContent) {
buffer.append(lineSeparator); buffer.append(lineSeparator);
} }
boolean methodSkipped = !methodToJava(node, mt, buffer, indent + 1); boolean methodSkipped = !methodToJava(node, mt, buffer, indent + 1, tracer);
if (!methodSkipped) { if (!methodSkipped) {
hasContent = true; hasContent = true;
} }
@ -372,7 +377,7 @@ public class ClassWriter {
buffer.append(lineSeparator); 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 indentString = InterpreterUtil.getIndentString(indent);
String lineSeparator = DecompilerContext.getNewLineSeparator(); String lineSeparator = DecompilerContext.getNewLineSeparator();
@ -434,11 +439,12 @@ public class ClassWriter {
if (isEnum && initializer.type == Exprent.EXPRENT_NEW) { if (isEnum && initializer.type == Exprent.EXPRENT_NEW) {
NewExprent nexpr = (NewExprent)initializer; NewExprent nexpr = (NewExprent)initializer;
nexpr.setEnumconst(true); nexpr.setEnumconst(true);
buffer.append(nexpr.toJava(indent)); buffer.append(nexpr.toJava(indent, tracer));
} }
else { else {
buffer.append(" = "); 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)) { else if (fd.hasModifier(CodeConstants.ACC_FINAL) && fd.hasModifier(CodeConstants.ACC_STATIC)) {
@ -447,7 +453,7 @@ public class ClassWriter {
if (attr != null) { if (attr != null) {
PrimitiveConstant constant = cl.getPool().getPrimitiveConstant(attr.getIndex()); PrimitiveConstant constant = cl.getPool().getPrimitiveConstant(attr.getIndex());
buffer.append(" = "); 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, StructMethod mt,
StringBuilder buffer, StringBuilder buffer,
int indent, int indent,
boolean codeOnly) { boolean codeOnly, BytecodeMappingTracer tracer) {
ClassWrapper classWrapper = classNode.wrapper; ClassWrapper classWrapper = classNode.wrapper;
MethodWrapper methodWrapper = classWrapper.getMethodWrapper(mt.getName(), mt.getDescriptor()); MethodWrapper methodWrapper = classWrapper.getMethodWrapper(mt.getName(), mt.getDescriptor());
@ -518,7 +524,7 @@ public class ClassWriter {
RootStatement root = classWrapper.getMethodWrapper(mt.getName(), mt.getDescriptor()).root; RootStatement root = classWrapper.getMethodWrapper(mt.getName(), mt.getDescriptor()).root;
if (root != null) { // check for existence if (root != null) { // check for existence
try { try {
buffer.append(root.toJava(indent)); buffer.append(root.toJava(indent, tracer));
} }
catch (Throwable ex) { catch (Throwable ex) {
DecompilerContext.getLogger().writeMessage("Method " + mt.getName() + " " + mt.getDescriptor() + " couldn't be written.", 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; ClassWrapper wrapper = node.wrapper;
StructClass cl = wrapper.getClassStruct(); StructClass cl = wrapper.getClassStruct();
MethodWrapper methodWrapper = wrapper.getMethodWrapper(mt.getName(), mt.getDescriptor()); MethodWrapper methodWrapper = wrapper.getMethodWrapper(mt.getName(), mt.getDescriptor());
@ -768,7 +774,7 @@ public class ClassWriter {
StructAnnDefaultAttribute attr = (StructAnnDefaultAttribute)mt.getAttributes().getWithKey("AnnotationDefault"); StructAnnDefaultAttribute attr = (StructAnnDefaultAttribute)mt.getAttributes().getWithKey("AnnotationDefault");
if (attr != null) { if (attr != null) {
buffer.append(" default "); 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 if (root != null && !methodWrapper.decompiledWithErrors) { // check for existence
try { 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; 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}; StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS};
private static void appendAnnotations(StringBuilder buffer, StructMember mb, int indent, String lineSeparator) { 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) { for (String name : ANNOTATION_ATTRIBUTES) {
StructAnnotationAttribute attribute = (StructAnnotationAttribute)mb.getAttributes().getWithKey(name); StructAnnotationAttribute attribute = (StructAnnotationAttribute)mb.getAttributes().getWithKey(name);
if (attribute != null) { if (attribute != null) {
for (AnnotationExprent annotation : attribute.getAnnotations()) { 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}; StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS};
private static void appendParameterAnnotations(StringBuilder buffer, StructMethod mt, int param) { 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) { for (String name : PARAMETER_ANNOTATION_ATTRIBUTES) {
StructAnnotationParameterAttribute attribute = (StructAnnotationParameterAttribute)mt.getAttributes().getWithKey(name); StructAnnotationParameterAttribute attribute = (StructAnnotationParameterAttribute)mt.getAttributes().getWithKey(name);
if (attribute != null) { if (attribute != null) {
List<List<AnnotationExprent>> annotations = attribute.getParamAnnotations(); List<List<AnnotationExprent>> annotations = attribute.getParamAnnotations();
if (param < annotations.size()) { if (param < annotations.size()) {
for (AnnotationExprent annotation : annotations.get(param)) { for (AnnotationExprent annotation : annotations.get(param)) {
buffer.append(annotation.toJava(0)).append(' '); buffer.append(annotation.toJava(0, tracer_dummy)).append(' ');
} }
} }
} }

@ -16,6 +16,7 @@
package org.jetbrains.java.decompiler.main; package org.jetbrains.java.decompiler.main;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.collectors.BytecodeSourceMapper;
import org.jetbrains.java.decompiler.main.collectors.CounterContainer; import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
import org.jetbrains.java.decompiler.main.collectors.ImportCollector; import org.jetbrains.java.decompiler.main.collectors.ImportCollector;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
@ -243,6 +244,7 @@ public class ClassesProcessor {
ImportCollector importCollector = new ImportCollector(root); ImportCollector importCollector = new ImportCollector(root);
DecompilerContext.setImportCollector(importCollector); DecompilerContext.setImportCollector(importCollector);
DecompilerContext.setCounterContainer(new CounterContainer()); DecompilerContext.setCounterContainer(new CounterContainer());
DecompilerContext.setBytecodeSourceMapper(new BytecodeSourceMapper());
new LambdaProcessor().processClass(root); new LambdaProcessor().processClass(root);
@ -276,6 +278,11 @@ public class ClassesProcessor {
} }
buffer.append(classBuffer); buffer.append(classBuffer);
if(DecompilerContext.getOption(IFernflowerPreferences.BYTECODE_SOURCE_MAPPING)) {
buffer.append(lineSeparator);
DecompilerContext.getBytecodeSourceMapper().dumpMapping(classBuffer);
}
} }
finally { finally {
destroyWrappers(root); destroyWrappers(root);

@ -15,6 +15,7 @@
*/ */
package org.jetbrains.java.decompiler.main; package org.jetbrains.java.decompiler.main;
import org.jetbrains.java.decompiler.main.collectors.BytecodeSourceMapper;
import org.jetbrains.java.decompiler.main.collectors.CounterContainer; import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
import org.jetbrains.java.decompiler.main.collectors.ImportCollector; import org.jetbrains.java.decompiler.main.collectors.ImportCollector;
import org.jetbrains.java.decompiler.main.collectors.VarNamesCollector; import org.jetbrains.java.decompiler.main.collectors.VarNamesCollector;
@ -45,6 +46,7 @@ public class DecompilerContext {
private ClassesProcessor classProcessor; private ClassesProcessor classProcessor;
private PoolInterceptor poolInterceptor; private PoolInterceptor poolInterceptor;
private IFernflowerLogger logger; private IFernflowerLogger logger;
private BytecodeSourceMapper bytecodeSourceMapper;
private DecompilerContext(Map<String, Object> properties) { private DecompilerContext(Map<String, Object> properties) {
this.properties = properties; this.properties = properties;
@ -126,6 +128,14 @@ public class DecompilerContext {
getCurrentContext().poolInterceptor = poolinterceptor; getCurrentContext().poolInterceptor = poolinterceptor;
} }
public static BytecodeSourceMapper getBytecodeSourceMapper() {
return getCurrentContext().bytecodeSourceMapper;
}
public static void setBytecodeSourceMapper(BytecodeSourceMapper bytecodeSourceMapper) {
getCurrentContext().bytecodeSourceMapper = bytecodeSourceMapper;
}
public static IFernflowerLogger getLogger() { public static IFernflowerLogger getLogger() {
return getCurrentContext().logger; return getCurrentContext().logger;
} }

@ -0,0 +1,26 @@
package org.jetbrains.java.decompiler.main.collectors;
import java.util.HashMap;
public class BytecodeMappingTracer {
private int current_sourceline;
// bytecode offset, source line
private HashMap<Integer, Integer> mapping;
public void incrementSourceLine() {
current_sourceline++;
}
public void addMapping(int bytecode_offset) {
if(!mapping.containsKey(bytecode_offset)) {
mapping.put(bytecode_offset, current_sourceline);
}
}
public HashMap<Integer, Integer> getMapping() {
return mapping;
}
}

@ -0,0 +1,75 @@
package org.jetbrains.java.decompiler.main.collectors;
import java.util.HashMap;
import java.util.Map.Entry;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
public class BytecodeSourceMapper {
private int offset_total;
// class, method, bytecode offset, source line
private HashMap<String, HashMap<String, HashMap<Integer, Integer>>> mapping;
public void addMapping(String classname, String methodname, int bytecode_offset, int source_line) {
HashMap<String, HashMap<Integer, Integer>> class_mapping = mapping.get(classname);
if(class_mapping == null) {
mapping.put(classname, class_mapping = new HashMap<String, HashMap<Integer, Integer>>());
}
HashMap<Integer, Integer> method_mapping = class_mapping.get(methodname);
if(method_mapping == null) {
class_mapping.put(methodname, method_mapping = new HashMap<Integer, Integer>());
}
// don't overwrite
if(!method_mapping.containsKey(bytecode_offset)) {
method_mapping.put(bytecode_offset, source_line);
}
}
public void dumpMapping(StringBuilder buffer) {
String lineSeparator = DecompilerContext.getNewLineSeparator();
String indentstr1 = InterpreterUtil.getIndentString(1);
String indentstr2 = InterpreterUtil.getIndentString(2);
for(Entry<String, HashMap<String, HashMap<Integer, Integer>>> class_entry : mapping.entrySet()) {
HashMap<String, HashMap<Integer, Integer>> class_mapping = class_entry.getValue();
buffer.append("class " + class_entry.getKey() + "{" + lineSeparator);
boolean is_first_method = true;
for(Entry<String, HashMap<Integer, Integer>> method_entry : class_mapping.entrySet()) {
HashMap<Integer, Integer> method_mapping = method_entry.getValue();
if(!is_first_method) {
buffer.append(lineSeparator);
}
buffer.append(indentstr1 + "method " + method_entry.getKey() + "{" + lineSeparator);
for(Entry<Integer, Integer> line : method_mapping.entrySet()) {
buffer.append(indentstr2 + line.getKey() + indentstr2 + line.getValue() + lineSeparator);
}
buffer.append(indentstr1 + "}" + lineSeparator);
is_first_method = false;
}
buffer.append("}" + lineSeparator);
}
}
public int getTotalOffset() {
return offset_total;
}
public void setTotalOffset(int offset_total) {
this.offset_total = offset_total;
}
}

@ -44,6 +44,8 @@ public interface IFernflowerPreferences {
String IDEA_NOT_NULL_ANNOTATION = "inn"; String IDEA_NOT_NULL_ANNOTATION = "inn";
String LAMBDA_TO_ANONYMOUS_CLASS = "lac"; String LAMBDA_TO_ANONYMOUS_CLASS = "lac";
String BYTECODE_SOURCE_MAPPING = "bsm";
String LOG_LEVEL = "log"; String LOG_LEVEL = "log";
String MAX_PROCESSING_METHOD = "mpm"; String MAX_PROCESSING_METHOD = "mpm";
String RENAME_ENTITIES = "ren"; String RENAME_ENTITIES = "ren";
@ -77,6 +79,8 @@ public interface IFernflowerPreferences {
put(IDEA_NOT_NULL_ANNOTATION, "1"); put(IDEA_NOT_NULL_ANNOTATION, "1");
put(LAMBDA_TO_ANONYMOUS_CLASS, "0"); put(LAMBDA_TO_ANONYMOUS_CLASS, "0");
put(BYTECODE_SOURCE_MAPPING, "0");
put(LOG_LEVEL, IFernflowerLogger.Severity.INFO.name()); put(LOG_LEVEL, IFernflowerLogger.Severity.INFO.name());
put(MAX_PROCESSING_METHOD, "0"); put(MAX_PROCESSING_METHOD, "0");
put(RENAME_ENTITIES, "0"); put(RENAME_ENTITIES, "0");

@ -20,6 +20,7 @@ import org.jetbrains.java.decompiler.code.Instruction;
import org.jetbrains.java.decompiler.code.InstructionSequence; import org.jetbrains.java.decompiler.code.InstructionSequence;
import org.jetbrains.java.decompiler.code.cfg.BasicBlock; import org.jetbrains.java.decompiler.code.cfg.BasicBlock;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.modules.decompiler.exps.*; import org.jetbrains.java.decompiler.modules.decompiler.exps.*;
import org.jetbrains.java.decompiler.modules.decompiler.sforms.DirectGraph; import org.jetbrains.java.decompiler.modules.decompiler.sforms.DirectGraph;
import org.jetbrains.java.decompiler.modules.decompiler.sforms.DirectNode; import org.jetbrains.java.decompiler.modules.decompiler.sforms.DirectNode;
@ -753,8 +754,8 @@ public class ExprProcessor implements CodeConstants {
.isClassdef())); .isClassdef()));
} }
public static String jmpWrapper(Statement stat, int indent, boolean semicolon) { public static String jmpWrapper(Statement stat, int indent, boolean semicolon, BytecodeMappingTracer tracer) {
StringBuilder buf = new StringBuilder(stat.toJava(indent)); StringBuilder buf = new StringBuilder(stat.toJava(indent, tracer));
String new_line_separator = DecompilerContext.getNewLineSeparator(); String new_line_separator = DecompilerContext.getNewLineSeparator();
@ -776,11 +777,13 @@ public class ExprProcessor implements CodeConstants {
buf.append(" label").append(edge.closure.id); buf.append(" label").append(edge.closure.id);
} }
buf.append(";").append(new_line_separator); buf.append(";").append(new_line_separator);
tracer.incrementSourceLine();
} }
} }
if (buf.length() == 0 && semicolon) { if (buf.length() == 0 && semicolon) {
buf.append(InterpreterUtil.getIndentString(indent)).append(";").append(new_line_separator); buf.append(InterpreterUtil.getIndentString(indent)).append(";").append(new_line_separator);
tracer.incrementSourceLine();
} }
return buf.toString(); return buf.toString();
@ -800,7 +803,7 @@ public class ExprProcessor implements CodeConstants {
return res; return res;
} }
public static String listToJava(List<Exprent> lst, int indent) { public static String listToJava(List<Exprent> lst, int indent, BytecodeMappingTracer tracer) {
if (lst == null || lst.isEmpty()) { if (lst == null || lst.isEmpty()) {
return ""; return "";
} }
@ -811,7 +814,7 @@ public class ExprProcessor implements CodeConstants {
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
for (Exprent expr : lst) { for (Exprent expr : lst) {
String content = expr.toJava(indent); String content = expr.toJava(indent, tracer);
if (content.length() > 0) { if (content.length() > 0) {
if (expr.type != Exprent.EXPRENT_VAR || !((VarExprent)expr).isClassdef()) { if (expr.type != Exprent.EXPRENT_VAR || !((VarExprent)expr).isClassdef()) {
buf.append(indstr); buf.append(indstr);
@ -824,6 +827,7 @@ public class ExprProcessor implements CodeConstants {
buf.append(";"); buf.append(";");
} }
buf.append(new_line_separator); buf.append(new_line_separator);
tracer.incrementSourceLine();
} }
} }
@ -852,8 +856,9 @@ public class ExprProcessor implements CodeConstants {
return defaultval; return defaultval;
} }
public static boolean getCastedExprent(Exprent exprent, VarType leftType, StringBuilder buffer, int indent, boolean castNull) { public static boolean getCastedExprent(Exprent exprent, VarType leftType, StringBuilder buffer, int indent,
return getCastedExprent(exprent, leftType, buffer, indent, castNull, false); boolean castNull, BytecodeMappingTracer tracer) {
return getCastedExprent(exprent, leftType, buffer, indent, castNull, false, tracer);
} }
public static boolean getCastedExprent(Exprent exprent, public static boolean getCastedExprent(Exprent exprent,
@ -861,12 +866,12 @@ public class ExprProcessor implements CodeConstants {
StringBuilder buffer, StringBuilder buffer,
int indent, int indent,
boolean castNull, boolean castNull,
boolean castAlways) { boolean castAlways, BytecodeMappingTracer tracer) {
boolean ret = false; boolean ret = false;
VarType rightType = exprent.getExprType(); VarType rightType = exprent.getExprType();
String res = exprent.toJava(indent); String res = exprent.toJava(indent, tracer);
boolean cast = boolean cast =
!leftType.isSuperset(rightType) && (rightType.equals(VarType.VARTYPE_OBJECT) || leftType.type != CodeConstants.TYPE_OBJECT); !leftType.isSuperset(rightType) && (rightType.equals(VarType.VARTYPE_OBJECT) || leftType.type != CodeConstants.TYPE_OBJECT);

@ -16,6 +16,7 @@
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
@ -45,7 +46,8 @@ public class AnnotationExprent extends Exprent {
this.parvalues = parvalues; this.parvalues = parvalues;
} }
public String toJava(int indent) { @Override
public String toJava(int indent, BytecodeMappingTracer tracer) {
String new_line_separator = DecompilerContext.getNewLineSeparator(); String new_line_separator = DecompilerContext.getNewLineSeparator();
@ -59,7 +61,7 @@ public class AnnotationExprent extends Exprent {
if (!parnames.isEmpty()) { if (!parnames.isEmpty()) {
buffer.append("("); buffer.append("(");
if (parnames.size() == 1 && "value".equals(parnames.get(0))) { if (parnames.size() == 1 && "value".equals(parnames.get(0))) {
buffer.append(parvalues.get(0).toJava(indent + 1)); buffer.append(parvalues.get(0).toJava(indent + 1, tracer));
} }
else { else {
String indstr1 = InterpreterUtil.getIndentString(indent + 1); String indstr1 = InterpreterUtil.getIndentString(indent + 1);
@ -68,7 +70,7 @@ public class AnnotationExprent extends Exprent {
buffer.append(new_line_separator).append(indstr1); buffer.append(new_line_separator).append(indstr1);
buffer.append(parnames.get(i)); buffer.append(parnames.get(i));
buffer.append(" = "); buffer.append(" = ");
buffer.append(parvalues.get(i).toJava(indent + 2)); buffer.append(parvalues.get(i).toJava(indent + 2, tracer));
if (i < parnames.size() - 1) { if (i < parnames.size() - 1) {
buffer.append(","); buffer.append(",");

@ -15,6 +15,7 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult; import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
@ -79,8 +80,9 @@ public class ArrayExprent extends Exprent {
} }
public String toJava(int indent) { @Override
String res = array.toJava(indent); public String toJava(int indent, BytecodeMappingTracer tracer) {
String res = array.toJava(indent, tracer);
if (array.getPrecedence() > getPrecedence()) { // array precedence equals 0 if (array.getPrecedence() > getPrecedence()) { // array precedence equals 0
res = "(" + res + ")"; res = "(" + res + ")";
@ -94,7 +96,7 @@ public class ArrayExprent extends Exprent {
res = "((" + ExprProcessor.getCastTypeName(objarr) + ")" + res + ")"; res = "((" + ExprProcessor.getCastTypeName(objarr) + ")" + res + ")";
} }
return res + "[" + index.toJava(indent) + "]"; return res + "[" + index.toJava(indent, tracer) + "]";
} }
public boolean equals(Object o) { public boolean equals(Object o) {

@ -17,6 +17,8 @@ package org.jetbrains.java.decompiler.modules.decompiler.exps;
import java.util.List; import java.util.List;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
public class AssertExprent extends Exprent { public class AssertExprent extends Exprent {
private List<Exprent> parameters; private List<Exprent> parameters;
@ -29,7 +31,8 @@ public class AssertExprent extends Exprent {
this.parameters = parameters; this.parameters = parameters;
} }
public String toJava(int indent) { @Override
public String toJava(int indent, BytecodeMappingTracer tracer) {
StringBuilder buffer = new StringBuilder(); StringBuilder buffer = new StringBuilder();
@ -39,11 +42,11 @@ public class AssertExprent extends Exprent {
buffer.append("false"); buffer.append("false");
} }
else { else {
buffer.append(parameters.get(0).toJava(indent)); buffer.append(parameters.get(0).toJava(indent, tracer));
} }
if (parameters.size() > 1) { if (parameters.size() > 1) {
buffer.append(" : "); buffer.append(" : ");
buffer.append(parameters.get(1).toJava(indent)); buffer.append(parameters.get(1).toJava(indent, tracer));
} }
return buffer.toString(); return buffer.toString();

@ -17,6 +17,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult; import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult;
@ -103,7 +104,8 @@ public class AssignmentExprent extends Exprent {
return 13; return 13;
} }
public String toJava(int indent) { @Override
public String toJava(int indent, BytecodeMappingTracer tracer) {
VarType leftType = left.getExprType(); VarType leftType = left.getExprType();
VarType rightType = right.getExprType(); VarType rightType = right.getExprType();
@ -134,10 +136,10 @@ public class AssignmentExprent extends Exprent {
buffer.append(((FieldExprent)left).getName()); buffer.append(((FieldExprent)left).getName());
} }
else { else {
buffer.append(left.toJava(indent)); buffer.append(left.toJava(indent, tracer));
} }
String res = right.toJava(indent); String res = right.toJava(indent, tracer);
if (condtype == CONDITION_NONE && if (condtype == CONDITION_NONE &&
!leftType.isSuperset(rightType) && !leftType.isSuperset(rightType) &&

@ -17,6 +17,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor; import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor;
@ -106,7 +107,8 @@ public class ConstExprent extends Exprent {
return new ArrayList<Exprent>(); return new ArrayList<Exprent>();
} }
public String toJava(int indent) { @Override
public String toJava(int indent, BytecodeMappingTracer tracer) {
boolean literal = DecompilerContext.getOption(IFernflowerPreferences.LITERALS_AS_IS); boolean literal = DecompilerContext.getOption(IFernflowerPreferences.LITERALS_AS_IS);
boolean ascii = DecompilerContext.getOption(IFernflowerPreferences.ASCII_STRING_CHARACTERS); boolean ascii = DecompilerContext.getOption(IFernflowerPreferences.ASCII_STRING_CHARACTERS);
@ -150,7 +152,7 @@ public class ConstExprent extends Exprent {
else { else {
return value.toString(); return value.toString();
} }
return new FieldExprent(intfield, "java/lang/Integer", true, null, FieldDescriptor.INTEGER_DESCRIPTOR).toJava(0); return new FieldExprent(intfield, "java/lang/Integer", true, null, FieldDescriptor.INTEGER_DESCRIPTOR).toJava(0, tracer);
case CodeConstants.TYPE_LONG: case CodeConstants.TYPE_LONG:
long lval = ((Long)value).longValue(); long lval = ((Long)value).longValue();
@ -167,7 +169,7 @@ public class ConstExprent extends Exprent {
else { else {
return value.toString() + "L"; return value.toString() + "L";
} }
return new FieldExprent(longfield, "java/lang/Long", true, null, FieldDescriptor.LONG_DESCRIPTOR).toJava(0); return new FieldExprent(longfield, "java/lang/Long", true, null, FieldDescriptor.LONG_DESCRIPTOR).toJava(0, tracer);
case CodeConstants.TYPE_DOUBLE: case CodeConstants.TYPE_DOUBLE:
double dval = ((Double)value).doubleValue(); double dval = ((Double)value).doubleValue();
@ -204,7 +206,7 @@ public class ConstExprent extends Exprent {
else { else {
return value.toString() + "D"; return value.toString() + "D";
} }
return new FieldExprent(doublefield, "java/lang/Double", true, null, FieldDescriptor.DOUBLE_DESCRIPTOR).toJava(0); return new FieldExprent(doublefield, "java/lang/Double", true, null, FieldDescriptor.DOUBLE_DESCRIPTOR).toJava(0, tracer);
case CodeConstants.TYPE_FLOAT: case CodeConstants.TYPE_FLOAT:
float fval = ((Float)value).floatValue(); float fval = ((Float)value).floatValue();
@ -241,7 +243,7 @@ public class ConstExprent extends Exprent {
else { else {
return value.toString() + "F"; return value.toString() + "F";
} }
return new FieldExprent(floatfield, "java/lang/Float", true, null, FieldDescriptor.FLOAT_DESCRIPTOR).toJava(0); return new FieldExprent(floatfield, "java/lang/Float", true, null, FieldDescriptor.FLOAT_DESCRIPTOR).toJava(0, tracer);
case CodeConstants.TYPE_NULL: case CodeConstants.TYPE_NULL:
return "null"; return "null";
case CodeConstants.TYPE_OBJECT: case CodeConstants.TYPE_OBJECT:

@ -18,6 +18,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.main.rels.MethodWrapper; import org.jetbrains.java.decompiler.main.rels.MethodWrapper;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult; import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult;
@ -74,13 +75,14 @@ public class ExitExprent extends Exprent {
return lst; return lst;
} }
public String toJava(int indent) { @Override
public String toJava(int indent, BytecodeMappingTracer tracer) {
if (exittype == EXIT_RETURN) { if (exittype == EXIT_RETURN) {
StringBuilder buffer = new StringBuilder(); StringBuilder buffer = new StringBuilder();
if (rettype.type != CodeConstants.TYPE_VOID) { if (rettype.type != CodeConstants.TYPE_VOID) {
buffer.append(" "); buffer.append(" ");
ExprProcessor.getCastedExprent(value, rettype, buffer, indent, false); ExprProcessor.getCastedExprent(value, rettype, buffer, indent, false, tracer);
} }
return "return" + buffer.toString(); return "return" + buffer.toString();
@ -111,14 +113,14 @@ public class ExitExprent extends Exprent {
VarType exctype = new VarType(classname, true); VarType exctype = new VarType(classname, true);
StringBuilder buffer = new StringBuilder(); StringBuilder buffer = new StringBuilder();
ExprProcessor.getCastedExprent(value, exctype, buffer, indent, false); ExprProcessor.getCastedExprent(value, exctype, buffer, indent, false, tracer);
return "throw " + buffer.toString(); return "throw " + buffer.toString();
} }
} }
} }
return "throw " + value.toJava(indent); return "throw " + value.toJava(indent, tracer);
} }
} }

@ -16,6 +16,7 @@
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.main.collectors.CounterContainer; import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult; import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPaar; import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPaar;
@ -124,7 +125,7 @@ public class Exprent {
throw new RuntimeException("not implemented"); throw new RuntimeException("not implemented");
} }
public String toJava(int indent) { public String toJava(int indent, BytecodeMappingTracer tracer) {
throw new RuntimeException("not implemented"); throw new RuntimeException("not implemented");
} }

@ -18,6 +18,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.main.rels.MethodWrapper; import org.jetbrains.java.decompiler.main.rels.MethodWrapper;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPaar; import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPaar;
@ -93,7 +94,8 @@ public class FieldExprent extends Exprent {
return new FieldExprent(name, classname, isStatic, instance == null ? null : instance.copy(), descriptor); return new FieldExprent(name, classname, isStatic, instance == null ? null : instance.copy(), descriptor);
} }
public String toJava(int indent) { @Override
public String toJava(int indent, BytecodeMappingTracer tracer) {
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
@ -136,7 +138,7 @@ public class FieldExprent extends Exprent {
} }
else { else {
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
boolean casted = ExprProcessor.getCastedExprent(instance, new VarType(CodeConstants.TYPE_OBJECT, 0, classname), buff, indent, true); boolean casted = ExprProcessor.getCastedExprent(instance, new VarType(CodeConstants.TYPE_OBJECT, 0, classname), buff, indent, true, tracer);
String res = buff.toString(); String res = buff.toString();
if (casted || instance.getPrecedence() > getPrecedence()) { if (casted || instance.getPrecedence() > getPrecedence()) {

@ -16,6 +16,7 @@
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult; import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
@ -446,31 +447,32 @@ public class FunctionExprent extends Exprent {
} }
} }
public String toJava(int indent) { @Override
public String toJava(int indent, BytecodeMappingTracer tracer) {
if (functype <= FUNCTION_USHR) { if (functype <= FUNCTION_USHR) {
return wrapOperandString(lstOperands.get(0), false, indent) + operators[functype] + return wrapOperandString(lstOperands.get(0), false, indent, tracer) + operators[functype] +
wrapOperandString(lstOperands.get(1), true, indent); wrapOperandString(lstOperands.get(1), true, indent, tracer);
} }
if (functype >= FUNCTION_EQ) { if (functype >= FUNCTION_EQ) {
return wrapOperandString(lstOperands.get(0), false, indent) + operators[functype - FUNCTION_EQ + 11] + return wrapOperandString(lstOperands.get(0), false, indent, tracer) + operators[functype - FUNCTION_EQ + 11] +
wrapOperandString(lstOperands.get(1), true, indent); wrapOperandString(lstOperands.get(1), true, indent, tracer);
} }
switch (functype) { switch (functype) {
case FUNCTION_BITNOT: case FUNCTION_BITNOT:
return "~" + wrapOperandString(lstOperands.get(0), true, indent); return "~" + wrapOperandString(lstOperands.get(0), true, indent, tracer);
case FUNCTION_BOOLNOT: case FUNCTION_BOOLNOT:
return "!" + wrapOperandString(lstOperands.get(0), true, indent); return "!" + wrapOperandString(lstOperands.get(0), true, indent, tracer);
case FUNCTION_NEG: case FUNCTION_NEG:
return "-" + wrapOperandString(lstOperands.get(0), true, indent); return "-" + wrapOperandString(lstOperands.get(0), true, indent, tracer);
case FUNCTION_CAST: case FUNCTION_CAST:
return "(" + lstOperands.get(1).toJava(indent) + ")" + wrapOperandString(lstOperands.get(0), true, indent); return "(" + lstOperands.get(1).toJava(indent, tracer) + ")" + wrapOperandString(lstOperands.get(0), true, indent, tracer);
case FUNCTION_ARRAYLENGTH: case FUNCTION_ARRAYLENGTH:
Exprent arr = lstOperands.get(0); Exprent arr = lstOperands.get(0);
String res = wrapOperandString(arr, false, indent); String res = wrapOperandString(arr, false, indent, tracer);
if (arr.getExprType().arraydim == 0) { if (arr.getExprType().arraydim == 0) {
VarType objarr = VarType.VARTYPE_OBJECT.copy(); VarType objarr = VarType.VARTYPE_OBJECT.copy();
objarr.arraydim = 1; // type family does not change objarr.arraydim = 1; // type family does not change
@ -479,52 +481,52 @@ public class FunctionExprent extends Exprent {
} }
return res + ".length"; return res + ".length";
case FUNCTION_IIF: case FUNCTION_IIF:
return wrapOperandString(lstOperands.get(0), true, indent) + "?" + wrapOperandString(lstOperands.get(1), true, indent) + ":" + return wrapOperandString(lstOperands.get(0), true, indent, tracer) + "?" + wrapOperandString(lstOperands.get(1), true, indent, tracer) + ":" +
wrapOperandString(lstOperands.get(2), true, indent); wrapOperandString(lstOperands.get(2), true, indent, tracer);
case FUNCTION_IPP: case FUNCTION_IPP:
return wrapOperandString(lstOperands.get(0), true, indent) + "++"; return wrapOperandString(lstOperands.get(0), true, indent, tracer) + "++";
case FUNCTION_PPI: case FUNCTION_PPI:
return "++" + wrapOperandString(lstOperands.get(0), true, indent); return "++" + wrapOperandString(lstOperands.get(0), true, indent, tracer);
case FUNCTION_IMM: case FUNCTION_IMM:
return wrapOperandString(lstOperands.get(0), true, indent) + "--"; return wrapOperandString(lstOperands.get(0), true, indent, tracer) + "--";
case FUNCTION_MMI: case FUNCTION_MMI:
return "--" + wrapOperandString(lstOperands.get(0), true, indent); return "--" + wrapOperandString(lstOperands.get(0), true, indent, tracer);
case FUNCTION_INSTANCEOF: case FUNCTION_INSTANCEOF:
return wrapOperandString(lstOperands.get(0), true, indent) + " instanceof " + wrapOperandString(lstOperands.get(1), true, indent); return wrapOperandString(lstOperands.get(0), true, indent, tracer) + " instanceof " + wrapOperandString(lstOperands.get(1), true, indent, tracer);
case FUNCTION_LCMP: // shouldn't appear in the final code case FUNCTION_LCMP: // shouldn't appear in the final code
return "__lcmp__(" + return "__lcmp__(" +
wrapOperandString(lstOperands.get(0), true, indent) + wrapOperandString(lstOperands.get(0), true, indent, tracer) +
"," + "," +
wrapOperandString(lstOperands.get(1), true, indent) + wrapOperandString(lstOperands.get(1), true, indent, tracer) +
")"; ")";
case FUNCTION_FCMPL: // shouldn't appear in the final code case FUNCTION_FCMPL: // shouldn't appear in the final code
return "__fcmpl__(" + return "__fcmpl__(" +
wrapOperandString(lstOperands.get(0), true, indent) + wrapOperandString(lstOperands.get(0), true, indent, tracer) +
"," + "," +
wrapOperandString(lstOperands.get(1), true, indent) + wrapOperandString(lstOperands.get(1), true, indent, tracer) +
")"; ")";
case FUNCTION_FCMPG: // shouldn't appear in the final code case FUNCTION_FCMPG: // shouldn't appear in the final code
return "__fcmpg__(" + return "__fcmpg__(" +
wrapOperandString(lstOperands.get(0), true, indent) + wrapOperandString(lstOperands.get(0), true, indent, tracer) +
"," + "," +
wrapOperandString(lstOperands.get(1), true, indent) + wrapOperandString(lstOperands.get(1), true, indent, tracer) +
")"; ")";
case FUNCTION_DCMPL: // shouldn't appear in the final code case FUNCTION_DCMPL: // shouldn't appear in the final code
return "__dcmpl__(" + return "__dcmpl__(" +
wrapOperandString(lstOperands.get(0), true, indent) + wrapOperandString(lstOperands.get(0), true, indent, tracer) +
"," + "," +
wrapOperandString(lstOperands.get(1), true, indent) + wrapOperandString(lstOperands.get(1), true, indent, tracer) +
")"; ")";
case FUNCTION_DCMPG: // shouldn't appear in the final code case FUNCTION_DCMPG: // shouldn't appear in the final code
return "__dcmpg__(" + return "__dcmpg__(" +
wrapOperandString(lstOperands.get(0), true, indent) + wrapOperandString(lstOperands.get(0), true, indent, tracer) +
"," + "," +
wrapOperandString(lstOperands.get(1), true, indent) + wrapOperandString(lstOperands.get(1), true, indent, tracer) +
")"; ")";
} }
if (functype <= FUNCTION_I2S) { if (functype <= FUNCTION_I2S) {
return "(" + ExprProcessor.getTypeName(types[functype - FUNCTION_I2L]) + ")" + wrapOperandString(lstOperands.get(0), true, indent); return "(" + ExprProcessor.getTypeName(types[functype - FUNCTION_I2L]) + ")" + wrapOperandString(lstOperands.get(0), true, indent, tracer);
} }
// return "<unknown function>"; // return "<unknown function>";
@ -543,7 +545,7 @@ public class FunctionExprent extends Exprent {
return types[functype - FUNCTION_I2L]; return types[functype - FUNCTION_I2L];
} }
private String wrapOperandString(Exprent expr, boolean eq, int indent) { private String wrapOperandString(Exprent expr, boolean eq, int indent, BytecodeMappingTracer tracer) {
int myprec = getPrecedence(); int myprec = getPrecedence();
int exprprec = expr.getPrecedence(); int exprprec = expr.getPrecedence();
@ -559,7 +561,7 @@ public class FunctionExprent extends Exprent {
} }
} }
String res = expr.toJava(indent); String res = expr.toJava(indent, tracer);
if (parentheses) { if (parentheses) {
res = "(" + res + ")"; res = "(" + res + ")";

@ -15,6 +15,7 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import org.jetbrains.java.decompiler.util.ListStack; import org.jetbrains.java.decompiler.util.ListStack;
@ -111,8 +112,9 @@ public class IfExprent extends Exprent {
return lst; return lst;
} }
public String toJava(int indent) { @Override
return "if(" + condition.toJava(indent) + ")"; public String toJava(int indent, BytecodeMappingTracer tracer) {
return "if(" + condition.toJava(indent, tracer) + ")";
} }
public boolean equals(Object o) { public boolean equals(Object o) {

@ -18,6 +18,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.jetbrains.java.decompiler.main.rels.MethodWrapper; import org.jetbrains.java.decompiler.main.rels.MethodWrapper;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
@ -186,7 +187,8 @@ public class InvocationExprent extends Exprent {
return new InvocationExprent(this); return new InvocationExprent(this);
} }
public String toJava(int indent) { @Override
public String toJava(int indent, BytecodeMappingTracer tracer) {
StringBuilder buf = new StringBuilder(""); StringBuilder buf = new StringBuilder("");
String super_qualifier = null; String super_qualifier = null;
@ -271,7 +273,7 @@ public class InvocationExprent extends Exprent {
buf.append("super"); buf.append("super");
} }
else { else {
String res = instance.toJava(indent); String res = instance.toJava(indent, tracer);
VarType rightType = instance.getExprType(); VarType rightType = instance.getExprType();
VarType leftType = new VarType(CodeConstants.TYPE_OBJECT, 0, classname); VarType leftType = new VarType(CodeConstants.TYPE_OBJECT, 0, classname);
@ -321,7 +323,7 @@ public class InvocationExprent extends Exprent {
buf.append("this("); buf.append("this(");
} }
else { else {
buf.append(instance.toJava(indent)); buf.append(instance.toJava(indent, tracer));
buf.append(".<init>("); buf.append(".<init>(");
// throw new RuntimeException("Unrecognized invocation of <init>"); // FIXME: activate // throw new RuntimeException("Unrecognized invocation of <init>"); // FIXME: activate
} }
@ -357,7 +359,7 @@ public class InvocationExprent extends Exprent {
} }
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
ExprProcessor.getCastedExprent(lstParameters.get(i), descriptor.params[i], buff, indent, true, setAmbiguousParameters.contains(i)); ExprProcessor.getCastedExprent(lstParameters.get(i), descriptor.params[i], buff, indent, true, setAmbiguousParameters.contains(i), tracer);
buf.append(buff); buf.append(buff);
firstpar = false; firstpar = false;

@ -15,6 +15,7 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.ArrayList; import java.util.ArrayList;
@ -49,9 +50,10 @@ public class MonitorExprent extends Exprent {
return lst; return lst;
} }
public String toJava(int indent) { @Override
public String toJava(int indent, BytecodeMappingTracer tracer) {
if (montype == MONITOR_ENTER) { if (montype == MONITOR_ENTER) {
return "synchronized(" + value.toJava(indent) + ")"; return "synchronized(" + value.toJava(indent, tracer) + ")";
} }
else { else {
return ""; return "";

@ -19,6 +19,7 @@ import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassWriter; import org.jetbrains.java.decompiler.main.ClassWriter;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult; import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult;
@ -169,7 +170,8 @@ public class NewExprent extends Exprent {
return 1; // precedence of new return 1; // precedence of new
} }
public String toJava(int indent) { @Override
public String toJava(int indent, BytecodeMappingTracer tracer) {
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
if (anonymous) { if (anonymous) {
@ -219,7 +221,7 @@ public class NewExprent extends Exprent {
} }
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
ExprProcessor.getCastedExprent(param, invsuper.getDescriptor().params[i], buff, indent, true); ExprProcessor.getCastedExprent(param, invsuper.getDescriptor().params[i], buff, indent, true, tracer);
buf.append(buff); buf.append(buff);
firstpar = false; firstpar = false;
@ -230,7 +232,7 @@ public class NewExprent extends Exprent {
if (!enumconst) { if (!enumconst) {
String enclosing = null; String enclosing = null;
if (!lambda && constructor != null) { if (!lambda && constructor != null) {
enclosing = getQualifiedNewInstance(child.anonimousClassType.value, constructor.getLstParameters(), indent); enclosing = getQualifiedNewInstance(child.anonimousClassType.value, constructor.getLstParameters(), indent, tracer);
} }
String typename = ExprProcessor.getCastTypeName(child.anonimousClassType); String typename = ExprProcessor.getCastTypeName(child.anonimousClassType);
@ -277,7 +279,7 @@ public class NewExprent extends Exprent {
if (i > 0) { if (i > 0) {
buf.append(", "); buf.append(", ");
} }
ExprProcessor.getCastedExprent(lstArrayElements.get(i), leftType, buf, indent, false); ExprProcessor.getCastedExprent(lstArrayElements.get(i), leftType, buf, indent, false, tracer);
} }
buf.append("}"); buf.append("}");
} }
@ -316,7 +318,7 @@ public class NewExprent extends Exprent {
} }
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
ExprProcessor.getCastedExprent(lstParameters.get(i), constructor.getDescriptor().params[i], buff, indent, true); ExprProcessor.getCastedExprent(lstParameters.get(i), constructor.getDescriptor().params[i], buff, indent, true, tracer);
buf.append(buff); buf.append(buff);
firstpar = false; firstpar = false;
@ -329,7 +331,7 @@ public class NewExprent extends Exprent {
if (!enumconst) { if (!enumconst) {
String enclosing = null; String enclosing = null;
if (constructor != null) { if (constructor != null) {
enclosing = getQualifiedNewInstance(newtype.value, constructor.getLstParameters(), indent); enclosing = getQualifiedNewInstance(newtype.value, constructor.getLstParameters(), indent, tracer);
} }
String typename = ExprProcessor.getTypeName(newtype); String typename = ExprProcessor.getTypeName(newtype);
@ -355,7 +357,7 @@ public class NewExprent extends Exprent {
if (lstArrayElements.isEmpty()) { if (lstArrayElements.isEmpty()) {
for (int i = 0; i < newtype.arraydim; i++) { for (int i = 0; i < newtype.arraydim; i++) {
buf.append("[").append(i < lstDims.size() ? lstDims.get(i).toJava(indent) : "").append("]"); buf.append("[").append(i < lstDims.size() ? lstDims.get(i).toJava(indent, tracer) : "").append("]");
} }
} }
else { else {
@ -372,7 +374,7 @@ public class NewExprent extends Exprent {
buf.append(", "); buf.append(", ");
} }
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
ExprProcessor.getCastedExprent(lstArrayElements.get(i), leftType, buff, indent, false); ExprProcessor.getCastedExprent(lstArrayElements.get(i), leftType, buff, indent, false, tracer);
buf.append(buff); buf.append(buff);
} }
@ -383,7 +385,7 @@ public class NewExprent extends Exprent {
return buf.toString(); return buf.toString();
} }
private static String getQualifiedNewInstance(String classname, List<Exprent> lstParams, int indent) { private static String getQualifiedNewInstance(String classname, List<Exprent> lstParams, int indent, BytecodeMappingTracer tracer) {
ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(classname); ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(classname);
@ -408,7 +410,7 @@ public class NewExprent extends Exprent {
} }
if (isQualifiedNew) { if (isQualifiedNew) {
return enclosing.toJava(indent); return enclosing.toJava(indent, tracer);
} }
} }
} }

@ -15,6 +15,7 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult; import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
@ -81,8 +82,9 @@ public class SwitchExprent extends Exprent {
return lst; return lst;
} }
public String toJava(int indent) { @Override
return "switch(" + value.toJava(indent) + ")"; public String toJava(int indent, BytecodeMappingTracer tracer) {
return "switch(" + value.toJava(indent, tracer) + ")";
} }
public boolean equals(Object o) { public boolean equals(Object o) {

@ -18,6 +18,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassWriter; import org.jetbrains.java.decompiler.main.ClassWriter;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor; import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor;
@ -80,7 +81,8 @@ public class VarExprent extends Exprent {
return var; return var;
} }
public String toJava(int indent) { @Override
public String toJava(int indent, BytecodeMappingTracer tracer) {
StringBuilder buffer = new StringBuilder(); StringBuilder buffer = new StringBuilder();
if (classdef) { if (classdef) {

@ -20,6 +20,7 @@ import org.jetbrains.java.decompiler.code.Instruction;
import org.jetbrains.java.decompiler.code.SimpleInstructionSequence; import org.jetbrains.java.decompiler.code.SimpleInstructionSequence;
import org.jetbrains.java.decompiler.code.cfg.BasicBlock; import org.jetbrains.java.decompiler.code.cfg.BasicBlock;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.main.collectors.CounterContainer; import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
@ -65,9 +66,9 @@ public class BasicBlockStatement extends Statement {
// public methods // public methods
// ***************************************************************************** // *****************************************************************************
public String toJava(int indent) { public String toJava(int indent, BytecodeMappingTracer tracer) {
return ExprProcessor.listToJava(varDefinitions, indent) + return ExprProcessor.listToJava(varDefinitions, indent, tracer) +
ExprProcessor.listToJava(exprents, indent); ExprProcessor.listToJava(exprents, indent, tracer);
} }
public Statement getSimpleCopy() { public Statement getSimpleCopy() {

@ -17,6 +17,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.stats;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.main.collectors.CounterContainer; import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
import org.jetbrains.java.decompiler.modules.decompiler.DecHelper; import org.jetbrains.java.decompiler.modules.decompiler.DecHelper;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
@ -110,7 +111,7 @@ public class CatchAllStatement extends Statement {
return null; return null;
} }
public String toJava(int indent) { public String toJava(int indent, BytecodeMappingTracer tracer) {
String indstr = InterpreterUtil.getIndentString(indent); String indstr = InterpreterUtil.getIndentString(indent);
String indstr1 = null; String indstr1 = null;
@ -118,42 +119,48 @@ public class CatchAllStatement extends Statement {
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
buf.append(ExprProcessor.listToJava(varDefinitions, indent)); buf.append(ExprProcessor.listToJava(varDefinitions, indent, tracer));
boolean labeled = isLabeled(); boolean labeled = isLabeled();
if (labeled) { if (labeled) {
buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator); buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator);
tracer.incrementSourceLine();
} }
List<StatEdge> lstSuccs = first.getSuccessorEdges(STATEDGE_DIRECT_ALL); List<StatEdge> lstSuccs = first.getSuccessorEdges(STATEDGE_DIRECT_ALL);
if (first.type == TYPE_TRYCATCH && first.varDefinitions.isEmpty() && isFinally && if (first.type == TYPE_TRYCATCH && first.varDefinitions.isEmpty() && isFinally &&
!labeled && !first.isLabeled() && (lstSuccs.isEmpty() || !lstSuccs.get(0).explicit)) { !labeled && !first.isLabeled() && (lstSuccs.isEmpty() || !lstSuccs.get(0).explicit)) {
String content = ExprProcessor.jmpWrapper(first, indent, true); String content = ExprProcessor.jmpWrapper(first, indent, true, tracer);
content = content.substring(0, content.length() - new_line_separator.length()); content = content.substring(0, content.length() - new_line_separator.length());
buf.append(content); buf.append(content);
} }
else { else {
buf.append(indstr).append("try {").append(new_line_separator); buf.append(indstr).append("try {").append(new_line_separator);
buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true)); tracer.incrementSourceLine();
buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true, tracer));
buf.append(indstr).append("}"); buf.append(indstr).append("}");
} }
buf.append(isFinally ? " finally" : buf.append(isFinally ? " finally" :
" catch (" + vars.get(0).toJava(indent) + ")").append(" {").append(new_line_separator); " catch (" + vars.get(0).toJava(indent, tracer) + ")").append(" {").append(new_line_separator);
tracer.incrementSourceLine();
if (monitor != null) { if (monitor != null) {
indstr1 = InterpreterUtil.getIndentString(indent + 1); indstr1 = InterpreterUtil.getIndentString(indent + 1);
buf.append(indstr1).append("if(").append(monitor.toJava(indent)).append(") {").append(new_line_separator); buf.append(indstr1).append("if(").append(monitor.toJava(indent, tracer)).append(") {").append(new_line_separator);
tracer.incrementSourceLine();
} }
buf.append(ExprProcessor.jmpWrapper(handler, indent + 1 + (monitor != null ? 1 : 0), true)); buf.append(ExprProcessor.jmpWrapper(handler, indent + 1 + (monitor != null ? 1 : 0), true, tracer));
if (monitor != null) { if (monitor != null) {
buf.append(indstr1).append("}").append(new_line_separator); buf.append(indstr1).append("}").append(new_line_separator);
tracer.incrementSourceLine();
} }
buf.append(indstr).append("}").append(new_line_separator); buf.append(indstr).append("}").append(new_line_separator);
tracer.incrementSourceLine();
return buf.toString(); return buf.toString();
} }

@ -17,6 +17,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.stats;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.main.collectors.CounterContainer; import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
import org.jetbrains.java.decompiler.modules.decompiler.DecHelper; import org.jetbrains.java.decompiler.modules.decompiler.DecHelper;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
@ -149,20 +150,23 @@ public class CatchStatement extends Statement {
return null; return null;
} }
public String toJava(int indent) { public String toJava(int indent, BytecodeMappingTracer tracer) {
String indstr = InterpreterUtil.getIndentString(indent); String indstr = InterpreterUtil.getIndentString(indent);
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
String new_line_separator = DecompilerContext.getNewLineSeparator(); String new_line_separator = DecompilerContext.getNewLineSeparator();
buf.append(ExprProcessor.listToJava(varDefinitions, indent)); buf.append(ExprProcessor.listToJava(varDefinitions, indent, tracer));
if (isLabeled()) { if (isLabeled()) {
buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator); buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator);
tracer.incrementSourceLine();
} }
buf.append(indstr).append("try {").append(new_line_separator); buf.append(indstr).append("try {").append(new_line_separator);
buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true)); tracer.incrementSourceLine();
buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true, tracer));
buf.append(indstr).append("}"); buf.append(indstr).append("}");
for (int i = 1; i < stats.size(); i++) { for (int i = 1; i < stats.size(); i++) {
@ -177,12 +181,16 @@ public class CatchStatement extends Statement {
buf.append(exc_type_name).append(" | "); buf.append(exc_type_name).append(" | ");
} }
} }
buf.append(vars.get(i - 1).toJava(indent)); buf.append(vars.get(i - 1).toJava(indent, tracer));
buf.append(") {").append(new_line_separator).append(ExprProcessor.jmpWrapper(stats.get(i), indent + 1, true)).append(indstr) buf.append(") {").append(new_line_separator);
tracer.incrementSourceLine();
buf.append(ExprProcessor.jmpWrapper(stats.get(i), indent + 1, true, tracer)).append(indstr)
.append("}"); .append("}");
tracer.incrementSourceLine();
} }
buf.append(new_line_separator); buf.append(new_line_separator);
tracer.incrementSourceLine();
return buf.toString(); return buf.toString();
} }

@ -16,6 +16,7 @@
package org.jetbrains.java.decompiler.modules.decompiler.stats; package org.jetbrains.java.decompiler.modules.decompiler.stats;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.StatEdge; import org.jetbrains.java.decompiler.modules.decompiler.StatEdge;
import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent; import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent;
@ -91,40 +92,49 @@ public class DoStatement extends Statement {
return null; return null;
} }
public String toJava(int indent) { public String toJava(int indent, BytecodeMappingTracer tracer) {
String indstr = InterpreterUtil.getIndentString(indent); String indstr = InterpreterUtil.getIndentString(indent);
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
String new_line_separator = DecompilerContext.getNewLineSeparator(); String new_line_separator = DecompilerContext.getNewLineSeparator();
buf.append(ExprProcessor.listToJava(varDefinitions, indent)); buf.append(ExprProcessor.listToJava(varDefinitions, indent, tracer));
if (isLabeled()) { if (isLabeled()) {
buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator); buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator);
tracer.incrementSourceLine();
} }
switch (looptype) { switch (looptype) {
case LOOP_DO: case LOOP_DO:
buf.append(indstr).append("while(true) {").append(new_line_separator); buf.append(indstr).append("while(true) {").append(new_line_separator);
buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true)); tracer.incrementSourceLine();
buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true, tracer));
buf.append(indstr).append("}").append(new_line_separator); buf.append(indstr).append("}").append(new_line_separator);
tracer.incrementSourceLine();
break; break;
case LOOP_DOWHILE: case LOOP_DOWHILE:
buf.append(indstr).append("do {").append(new_line_separator); buf.append(indstr).append("do {").append(new_line_separator);
buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true)); tracer.incrementSourceLine();
buf.append(indstr).append("} while(").append(conditionExprent.get(0).toJava(indent)).append(");").append(new_line_separator); buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true, tracer));
buf.append(indstr).append("} while(").append(conditionExprent.get(0).toJava(indent, tracer)).append(");").append(new_line_separator);
tracer.incrementSourceLine();
break; break;
case LOOP_WHILE: case LOOP_WHILE:
buf.append(indstr).append("while(").append(conditionExprent.get(0).toJava(indent)).append(") {").append(new_line_separator); buf.append(indstr).append("while(").append(conditionExprent.get(0).toJava(indent, tracer)).append(") {").append(new_line_separator);
buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true)); tracer.incrementSourceLine();
buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true, tracer));
buf.append(indstr).append("}").append(new_line_separator); buf.append(indstr).append("}").append(new_line_separator);
tracer.incrementSourceLine();
break; break;
case LOOP_FOR: case LOOP_FOR:
buf.append(indstr).append("for(").append(initExprent.get(0) == null ? "" : initExprent.get(0).toJava(indent)).append("; ") buf.append(indstr).append("for(").append(initExprent.get(0) == null ? "" : initExprent.get(0).toJava(indent, tracer)).append("; ")
.append(conditionExprent.get(0).toJava(indent)).append("; ").append(incExprent.get(0).toJava(indent)).append(") {") .append(conditionExprent.get(0).toJava(indent, tracer)).append("; ").append(incExprent.get(0).toJava(indent, tracer)).append(") {")
.append(new_line_separator); .append(new_line_separator);
buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true)); tracer.incrementSourceLine();
buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true, tracer));
buf.append(indstr).append("}").append(new_line_separator); buf.append(indstr).append("}").append(new_line_separator);
tracer.incrementSourceLine();
} }
return buf.toString(); return buf.toString();

@ -16,6 +16,7 @@
package org.jetbrains.java.decompiler.modules.decompiler.stats; package org.jetbrains.java.decompiler.modules.decompiler.stats;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.Collection; import java.util.Collection;
@ -53,7 +54,7 @@ public class GeneralStatement extends Statement {
// public methods // public methods
// ***************************************************************************** // *****************************************************************************
public String toJava(int indent) { public String toJava(int indent, BytecodeMappingTracer tracer) {
String indstr = InterpreterUtil.getIndentString(indent); String indstr = InterpreterUtil.getIndentString(indent);
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
@ -65,7 +66,7 @@ public class GeneralStatement extends Statement {
buf.append(indstr).append("abstract statement {").append(new_line_separator); buf.append(indstr).append("abstract statement {").append(new_line_separator);
for (int i = 0; i < stats.size(); i++) { for (int i = 0; i < stats.size(); i++) {
buf.append(stats.get(i).toJava(indent + 1)); buf.append(stats.get(i).toJava(indent + 1, tracer));
} }
buf.append(indstr).append("}"); buf.append(indstr).append("}");

@ -16,6 +16,7 @@
package org.jetbrains.java.decompiler.modules.decompiler.stats; package org.jetbrains.java.decompiler.modules.decompiler.stats;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.modules.decompiler.DecHelper; import org.jetbrains.java.decompiler.modules.decompiler.DecHelper;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.StatEdge; import org.jetbrains.java.decompiler.modules.decompiler.StatEdge;
@ -199,20 +200,22 @@ public class IfStatement extends Statement {
return null; return null;
} }
public String toJava(int indent) { public String toJava(int indent, BytecodeMappingTracer tracer) {
String indstr = InterpreterUtil.getIndentString(indent); String indstr = InterpreterUtil.getIndentString(indent);
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
String new_line_separator = DecompilerContext.getNewLineSeparator(); String new_line_separator = DecompilerContext.getNewLineSeparator();
buf.append(ExprProcessor.listToJava(varDefinitions, indent)); buf.append(ExprProcessor.listToJava(varDefinitions, indent, tracer));
buf.append(first.toJava(indent)); buf.append(first.toJava(indent, tracer));
if (isLabeled()) { if (isLabeled()) {
buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator); buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator);
tracer.incrementSourceLine();
} }
buf.append(indstr).append(headexprent.get(0).toJava(indent)).append(" {").append(new_line_separator); buf.append(indstr).append(headexprent.get(0).toJava(indent, tracer)).append(" {").append(new_line_separator);
tracer.incrementSourceLine();
if (ifstat == null) { if (ifstat == null) {
buf.append(InterpreterUtil.getIndentString(indent + 1)); buf.append(InterpreterUtil.getIndentString(indent + 1));
@ -232,9 +235,10 @@ public class IfStatement extends Statement {
} }
} }
buf.append(";").append(new_line_separator); buf.append(";").append(new_line_separator);
tracer.incrementSourceLine();
} }
else { else {
buf.append(ExprProcessor.jmpWrapper(ifstat, indent + 1, true)); buf.append(ExprProcessor.jmpWrapper(ifstat, indent + 1, true, tracer));
} }
boolean elseif = false; boolean elseif = false;
@ -245,7 +249,7 @@ public class IfStatement extends Statement {
!elsestat.isLabeled() && !elsestat.isLabeled() &&
(elsestat.getSuccessorEdges(STATEDGE_DIRECT_ALL).isEmpty() (elsestat.getSuccessorEdges(STATEDGE_DIRECT_ALL).isEmpty()
|| !elsestat.getSuccessorEdges(STATEDGE_DIRECT_ALL).get(0).explicit)) { // else if || !elsestat.getSuccessorEdges(STATEDGE_DIRECT_ALL).get(0).explicit)) { // else if
String content = ExprProcessor.jmpWrapper(elsestat, indent, false); String content = ExprProcessor.jmpWrapper(elsestat, indent, false, tracer);
content = content.substring(indstr.length()); content = content.substring(indstr.length());
buf.append(indstr).append("} else "); buf.append(indstr).append("} else ");
@ -254,10 +258,12 @@ public class IfStatement extends Statement {
elseif = true; elseif = true;
} }
else { else {
String content = ExprProcessor.jmpWrapper(elsestat, indent + 1, false); String content = ExprProcessor.jmpWrapper(elsestat, indent + 1, false, tracer);
if (content.length() > 0) { if (content.length() > 0) {
buf.append(indstr).append("} else {").append(new_line_separator); buf.append(indstr).append("} else {").append(new_line_separator);
tracer.incrementSourceLine(); // FIXME: wrong order
buf.append(content); buf.append(content);
} }
} }
@ -265,6 +271,7 @@ public class IfStatement extends Statement {
if (!elseif) { if (!elseif) {
buf.append(indstr).append("}").append(new_line_separator); buf.append(indstr).append("}").append(new_line_separator);
tracer.incrementSourceLine();
} }
return buf.toString(); return buf.toString();

@ -15,6 +15,7 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler.stats; package org.jetbrains.java.decompiler.modules.decompiler.stats;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
@ -33,9 +34,9 @@ public class RootStatement extends Statement {
first.setParent(this); first.setParent(this);
} }
public String toJava(int indent) { public String toJava(int indent, BytecodeMappingTracer tracer) {
return ExprProcessor.listToJava(varDefinitions, indent) + return ExprProcessor.listToJava(varDefinitions, indent, tracer) +
first.toJava(indent); first.toJava(indent, tracer);
} }
public Statement getDummyExit() { public Statement getDummyExit() {

@ -16,6 +16,7 @@
package org.jetbrains.java.decompiler.modules.decompiler.stats; package org.jetbrains.java.decompiler.modules.decompiler.stats;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.modules.decompiler.DecHelper; import org.jetbrains.java.decompiler.modules.decompiler.DecHelper;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.StatEdge; import org.jetbrains.java.decompiler.modules.decompiler.StatEdge;
@ -98,7 +99,7 @@ public class SequenceStatement extends Statement {
return null; return null;
} }
public String toJava(int indent) { public String toJava(int indent, BytecodeMappingTracer tracer) {
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
@ -107,12 +108,13 @@ public class SequenceStatement extends Statement {
String new_line_separator = DecompilerContext.getNewLineSeparator(); String new_line_separator = DecompilerContext.getNewLineSeparator();
buf.append(ExprProcessor.listToJava(varDefinitions, indent)); buf.append(ExprProcessor.listToJava(varDefinitions, indent, tracer));
if (islabeled) { if (islabeled) {
indstr = InterpreterUtil.getIndentString(indent); indstr = InterpreterUtil.getIndentString(indent);
indent++; indent++;
buf.append(indstr).append("label").append(this.id).append(": {").append(new_line_separator); buf.append(indstr).append("label").append(this.id).append(": {").append(new_line_separator);
tracer.incrementSourceLine();
} }
boolean notempty = false; boolean notempty = false;
@ -123,9 +125,10 @@ public class SequenceStatement extends Statement {
if (i > 0 && notempty) { if (i > 0 && notempty) {
buf.append(new_line_separator); buf.append(new_line_separator);
tracer.incrementSourceLine();
} }
String str = ExprProcessor.jmpWrapper(st, indent, false); String str = ExprProcessor.jmpWrapper(st, indent, false, tracer);
buf.append(str); buf.append(str);
notempty = (str.trim().length() > 0); notempty = (str.trim().length() > 0);
@ -133,6 +136,7 @@ public class SequenceStatement extends Statement {
if (islabeled) { if (islabeled) {
buf.append(indstr).append("}").append(new_line_separator); buf.append(indstr).append("}").append(new_line_separator);
tracer.incrementSourceLine();
} }
return buf.toString(); return buf.toString();

@ -18,6 +18,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.stats;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.code.InstructionSequence; import org.jetbrains.java.decompiler.code.InstructionSequence;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.main.collectors.CounterContainer; import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
import org.jetbrains.java.decompiler.modules.decompiler.StatEdge; import org.jetbrains.java.decompiler.modules.decompiler.StatEdge;
import org.jetbrains.java.decompiler.modules.decompiler.StrongConnectivityHelper; import org.jetbrains.java.decompiler.modules.decompiler.StrongConnectivityHelper;
@ -488,11 +489,11 @@ public class Statement {
} }
// to be overwritten // to be overwritten
public String toJava() { //public String toJava() {
return toJava(0); // return toJava(0);
} //}
public String toJava(int indent) { public String toJava(int indent, BytecodeMappingTracer tracer) {
throw new RuntimeException("not implemented"); throw new RuntimeException("not implemented");
} }

@ -18,6 +18,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.stats;
import org.jetbrains.java.decompiler.code.SwitchInstruction; import org.jetbrains.java.decompiler.code.SwitchInstruction;
import org.jetbrains.java.decompiler.code.cfg.BasicBlock; import org.jetbrains.java.decompiler.code.cfg.BasicBlock;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.main.collectors.CounterContainer; import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
import org.jetbrains.java.decompiler.modules.decompiler.DecHelper; import org.jetbrains.java.decompiler.modules.decompiler.DecHelper;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
@ -106,21 +107,23 @@ public class SwitchStatement extends Statement {
return null; return null;
} }
public String toJava(int indent) { public String toJava(int indent, BytecodeMappingTracer tracer) {
String indstr = InterpreterUtil.getIndentString(indent); String indstr = InterpreterUtil.getIndentString(indent);
String new_line_separator = DecompilerContext.getNewLineSeparator(); String new_line_separator = DecompilerContext.getNewLineSeparator();
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
buf.append(ExprProcessor.listToJava(varDefinitions, indent)); buf.append(ExprProcessor.listToJava(varDefinitions, indent, tracer));
buf.append(first.toJava(indent)); buf.append(first.toJava(indent, tracer));
if (isLabeled()) { if (isLabeled()) {
buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator); buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator);
tracer.incrementSourceLine();
} }
buf.append(indstr).append(headexprent.get(0).toJava(indent)).append(" {").append(new_line_separator); buf.append(indstr).append(headexprent.get(0).toJava(indent, tracer)).append(" {").append(new_line_separator);
tracer.incrementSourceLine();
VarType switch_type = headexprent.get(0).getExprType(); VarType switch_type = headexprent.get(0).getExprType();
@ -133,19 +136,22 @@ public class SwitchStatement extends Statement {
for (int j = 0; j < edges.size(); j++) { for (int j = 0; j < edges.size(); j++) {
if (edges.get(j) == default_edge) { if (edges.get(j) == default_edge) {
buf.append(indstr).append("default:").append(new_line_separator); buf.append(indstr).append("default:").append(new_line_separator);
tracer.incrementSourceLine();
} }
else { else {
ConstExprent value = (ConstExprent)values.get(j).copy(); ConstExprent value = (ConstExprent)values.get(j).copy();
value.setConsttype(switch_type); value.setConsttype(switch_type);
buf.append(indstr).append("case ").append(value.toJava(indent)).append(":").append(new_line_separator); buf.append(indstr).append("case ").append(value.toJava(indent, tracer)).append(":").append(new_line_separator);
tracer.incrementSourceLine();
} }
} }
buf.append(ExprProcessor.jmpWrapper(stat, indent + 1, false)); buf.append(ExprProcessor.jmpWrapper(stat, indent + 1, false, tracer));
} }
buf.append(indstr).append("}").append(new_line_separator); buf.append(indstr).append("}").append(new_line_separator);
tracer.incrementSourceLine();
return buf.toString(); return buf.toString();
} }

@ -16,6 +16,7 @@
package org.jetbrains.java.decompiler.modules.decompiler.stats; package org.jetbrains.java.decompiler.modules.decompiler.stats;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.SequenceHelper; import org.jetbrains.java.decompiler.modules.decompiler.SequenceHelper;
import org.jetbrains.java.decompiler.modules.decompiler.StatEdge; import org.jetbrains.java.decompiler.modules.decompiler.StatEdge;
@ -68,22 +69,28 @@ public class SynchronizedStatement extends Statement {
// public methods // public methods
// ***************************************************************************** // *****************************************************************************
public String toJava(int indent) { public String toJava(int indent, BytecodeMappingTracer tracer) {
String indstr = InterpreterUtil.getIndentString(indent); String indstr = InterpreterUtil.getIndentString(indent);
String new_line_separator = DecompilerContext.getNewLineSeparator(); String new_line_separator = DecompilerContext.getNewLineSeparator();
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
buf.append(ExprProcessor.listToJava(varDefinitions, indent)); buf.append(ExprProcessor.listToJava(varDefinitions, indent, tracer));
buf.append(first.toJava(indent)); buf.append(first.toJava(indent, tracer));
if (isLabeled()) { if (isLabeled()) {
buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator); buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator);
tracer.incrementSourceLine();
} }
buf.append(indstr).append(headexprent.get(0).toJava(indent)).append(" {").append(new_line_separator); buf.append(indstr).append(headexprent.get(0).toJava(indent, tracer)).append(" {").append(new_line_separator);
buf.append(ExprProcessor.jmpWrapper(body, indent + 1, true)); tracer.incrementSourceLine();
buf.append(ExprProcessor.jmpWrapper(body, indent + 1, true, tracer));
tracer.incrementSourceLine();
buf.append(indstr).append("}").append(new_line_separator); buf.append(indstr).append("}").append(new_line_separator);
tracer.incrementSourceLine();
return buf.toString(); return buf.toString();
} }

Loading…
Cancel
Save