decompiler: fixed line mapping in synchronized block

master
Egor.Ushakov 10 years ago
parent 0d80e663ae
commit 56b3edd3ca
  1. 81
      src/org/jetbrains/java/decompiler/main/ClassWriter.java
  2. 46
      src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java
  3. 15
      src/org/jetbrains/java/decompiler/modules/decompiler/stats/SequenceStatement.java
  4. 13
      src/org/jetbrains/java/decompiler/modules/decompiler/stats/SynchronizedStatement.java
  5. 1
      test/org/jetbrains/java/decompiler/BytecodeToSourceMappingTest.java
  6. BIN
      testData/classes/pkg/TestSynchronizedMapping.class
  7. 30
      testData/results/TestSynchronizedMapping.dec
  8. 16
      testData/src/pkg/TestSynchronizedMapping.java

@ -142,8 +142,7 @@ public class ClassWriter {
buffer.append(") ->"); buffer.append(") ->");
} }
buffer.append(" {"); buffer.append(" {").appendLineSeparator();
buffer.append(DecompilerContext.getNewLineSeparator());
methodLambdaToJava(node, classNode, mt, buffer, indent + 1, !lambdaToAnonymous, tracer); methodLambdaToJava(node, classNode, mt, buffer, indent + 1, !lambdaToAnonymous, tracer);
@ -193,8 +192,7 @@ public class ClassWriter {
boolean isEnum = fd.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM); boolean isEnum = fd.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM);
if (isEnum) { if (isEnum) {
if (enumFields) { if (enumFields) {
buffer.append(','); buffer.append(',').appendLineSeparator();
buffer.appendLineSeparator();
} }
enumFields = true; enumFields = true;
} }
@ -211,8 +209,7 @@ public class ClassWriter {
} }
if (enumFields) { if (enumFields) {
buffer.append(';'); buffer.append(';').appendLineSeparator();
buffer.appendLineSeparator();
} }
// FIXME: fields don't matter at the moment // FIXME: fields don't matter at the moment
@ -226,6 +223,7 @@ public class ClassWriter {
if (hide) continue; if (hide) continue;
int position = buffer.length(); int position = buffer.length();
int storedLine = startLine;
if (hasContent) { if (hasContent) {
buffer.appendLineSeparator(); buffer.appendLineSeparator();
startLine++; startLine++;
@ -236,10 +234,11 @@ public class ClassWriter {
hasContent = true; hasContent = true;
DecompilerContext.getBytecodeSourceMapper().addTracer(cl.qualifiedName, DecompilerContext.getBytecodeSourceMapper().addTracer(cl.qualifiedName,
InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor()), method_tracer); InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor()), method_tracer);
startLine = method_tracer.getCurrentSourceLine()+1; // zero-based line index startLine = method_tracer.getCurrentSourceLine();
} }
else { else {
buffer.setLength(position); buffer.setLength(position);
startLine = storedLine;
} }
} }
@ -278,11 +277,8 @@ public class ClassWriter {
} }
private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent) { private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent) {
String lineSeparator = DecompilerContext.getNewLineSeparator();
if (node.type == ClassNode.CLASS_ANONYMOUS) { if (node.type == ClassNode.CLASS_ANONYMOUS) {
buffer.append(" {"); buffer.append(" {").appendLineSeparator();
buffer.append(lineSeparator);
return; return;
} }
@ -297,19 +293,19 @@ public class ClassWriter {
boolean isAnnotation = (flags & CodeConstants.ACC_ANNOTATION) != 0; boolean isAnnotation = (flags & CodeConstants.ACC_ANNOTATION) != 0;
if (isDeprecated) { if (isDeprecated) {
appendDeprecation(buffer, indent, lineSeparator); appendDeprecation(buffer, indent);
} }
if (interceptor != null) { if (interceptor != null) {
String oldName = interceptor.getOldName(cl.qualifiedName); String oldName = interceptor.getOldName(cl.qualifiedName);
appendRenameComment(buffer, oldName, MType.CLASS, indent, lineSeparator); appendRenameComment(buffer, oldName, MType.CLASS, indent);
} }
if (isSynthetic) { if (isSynthetic) {
appendComment(buffer, "synthetic class", indent, lineSeparator); appendComment(buffer, "synthetic class", indent);
} }
appendAnnotations(buffer, cl, indent, lineSeparator); appendAnnotations(buffer, cl, indent);
buffer.appendIndent(indent); buffer.appendIndent(indent);
@ -383,31 +379,28 @@ public class ClassWriter {
} }
} }
buffer.append('{'); buffer.append('{').appendLineSeparator();
buffer.append(lineSeparator);
} }
private void fieldToJava(ClassWrapper wrapper, StructClass cl, StructField fd, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) { private void fieldToJava(ClassWrapper wrapper, StructClass cl, StructField fd, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) {
String lineSeparator = DecompilerContext.getNewLineSeparator();
boolean isInterface = cl.hasModifier(CodeConstants.ACC_INTERFACE); boolean isInterface = cl.hasModifier(CodeConstants.ACC_INTERFACE);
boolean isDeprecated = fd.getAttributes().containsKey("Deprecated"); boolean isDeprecated = fd.getAttributes().containsKey("Deprecated");
boolean isEnum = fd.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM); boolean isEnum = fd.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM);
if (isDeprecated) { if (isDeprecated) {
appendDeprecation(buffer, indent, lineSeparator); appendDeprecation(buffer, indent);
} }
if (interceptor != null) { if (interceptor != null) {
String oldName = interceptor.getOldName(cl.qualifiedName + " " + fd.getName() + " " + fd.getDescriptor()); String oldName = interceptor.getOldName(cl.qualifiedName + " " + fd.getName() + " " + fd.getDescriptor());
appendRenameComment(buffer, oldName, MType.FIELD, indent, lineSeparator); appendRenameComment(buffer, oldName, MType.FIELD, indent);
} }
if (fd.isSynthetic()) { if (fd.isSynthetic()) {
appendComment(buffer, "synthetic field", indent, lineSeparator); appendComment(buffer, "synthetic field", indent);
} }
appendAnnotations(buffer, fd, indent, lineSeparator); appendAnnotations(buffer, fd, indent);
buffer.appendIndent(indent); buffer.appendIndent(indent);
@ -467,8 +460,7 @@ public class ClassWriter {
} }
if (!isEnum) { if (!isEnum) {
buffer.append(";"); buffer.append(";").appendLineSeparator();
buffer.append(lineSeparator);
} }
} }
@ -523,8 +515,7 @@ public class ClassWriter {
index += md_content.params[i].stack_size; index += md_content.params[i].stack_size;
} }
buffer.append(") {"); buffer.append(") {").appendLineSeparator();
buffer.append(DecompilerContext.getNewLineSeparator());
indent += 1; indent += 1;
} }
@ -545,7 +536,7 @@ public class ClassWriter {
if (methodWrapper.decompiledWithErrors) { if (methodWrapper.decompiledWithErrors) {
buffer.appendIndent(indent); buffer.appendIndent(indent);
buffer.append("// $FF: Couldn't be decompiled"); buffer.append("// $FF: Couldn't be decompiled");
buffer.append(DecompilerContext.getNewLineSeparator()); buffer.appendLineSeparator();
} }
if (!codeOnly) { if (!codeOnly) {
@ -553,7 +544,7 @@ public class ClassWriter {
buffer.appendIndent(indent); buffer.appendIndent(indent);
buffer.append('}'); buffer.append('}');
buffer.append(DecompilerContext.getNewLineSeparator()); buffer.appendLineSeparator();
} }
} }
finally { finally {
@ -569,8 +560,6 @@ public class ClassWriter {
boolean hideMethod = false; boolean hideMethod = false;
int start_index_method = buffer.length(); int start_index_method = buffer.length();
String lineSeparator = DecompilerContext.getNewLineSeparator();
MethodWrapper outerWrapper = (MethodWrapper)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_WRAPPER); MethodWrapper outerWrapper = (MethodWrapper)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_WRAPPER);
DecompilerContext.setProperty(DecompilerContext.CURRENT_METHOD_WRAPPER, methodWrapper); DecompilerContext.setProperty(DecompilerContext.CURRENT_METHOD_WRAPPER, methodWrapper);
@ -596,24 +585,24 @@ public class ClassWriter {
} }
if (isDeprecated) { if (isDeprecated) {
appendDeprecation(buffer, indent, lineSeparator); appendDeprecation(buffer, indent);
} }
if (interceptor != null) { if (interceptor != null) {
String oldName = interceptor.getOldName(cl.qualifiedName + " " + mt.getName() + " " + mt.getDescriptor()); String oldName = interceptor.getOldName(cl.qualifiedName + " " + mt.getName() + " " + mt.getDescriptor());
appendRenameComment(buffer, oldName, MType.METHOD, indent, lineSeparator); appendRenameComment(buffer, oldName, MType.METHOD, indent);
} }
boolean isSynthetic = (flags & CodeConstants.ACC_SYNTHETIC) != 0 || mt.getAttributes().containsKey("Synthetic"); boolean isSynthetic = (flags & CodeConstants.ACC_SYNTHETIC) != 0 || mt.getAttributes().containsKey("Synthetic");
boolean isBridge = (flags & CodeConstants.ACC_BRIDGE) != 0; boolean isBridge = (flags & CodeConstants.ACC_BRIDGE) != 0;
if (isSynthetic) { if (isSynthetic) {
appendComment(buffer, "synthetic method", indent, lineSeparator); appendComment(buffer, "synthetic method", indent);
} }
if (isBridge) { if (isBridge) {
appendComment(buffer, "bridge method", indent, lineSeparator); appendComment(buffer, "bridge method", indent);
} }
appendAnnotations(buffer, mt, indent, lineSeparator); appendAnnotations(buffer, mt, indent);
buffer.appendIndent(indent); buffer.appendIndent(indent);
@ -831,10 +820,12 @@ public class ClassWriter {
if (methodWrapper.decompiledWithErrors) { if (methodWrapper.decompiledWithErrors) {
buffer.appendIndent(indent + 1); buffer.appendIndent(indent + 1);
buffer.append("// $FF: Couldn't be decompiled"); buffer.append("// $FF: Couldn't be decompiled");
buffer.append(lineSeparator); buffer.appendLineSeparator();
tracer.incrementCurrentSourceLine();
} }
buffer.appendIndent(indent).append('}').appendLineSeparator(); buffer.appendIndent(indent).append('}').appendLineSeparator();
tracer.incrementCurrentSourceLine();
} }
} }
finally { finally {
@ -897,13 +888,13 @@ public class ClassWriter {
return true; return true;
} }
private static void appendDeprecation(TextBuffer buffer, int indent, String lineSeparator) { private static void appendDeprecation(TextBuffer buffer, int indent) {
buffer.appendIndent(indent).append("/** @deprecated */").append(lineSeparator); buffer.appendIndent(indent).append("/** @deprecated */").appendLineSeparator();
} }
private enum MType {CLASS, FIELD, METHOD} private enum MType {CLASS, FIELD, METHOD}
private static void appendRenameComment(TextBuffer buffer, String oldName, MType type, int indent, String lineSeparator) { private static void appendRenameComment(TextBuffer buffer, String oldName, MType type, int indent) {
if (oldName == null) return; if (oldName == null) return;
buffer.appendIndent(indent); buffer.appendIndent(indent);
@ -939,7 +930,7 @@ public class ClassWriter {
buffer.append(getTypePrintOut(md.ret)); buffer.append(getTypePrintOut(md.ret));
} }
buffer.append(lineSeparator); buffer.appendLineSeparator();
} }
private static String getTypePrintOut(VarType type) { private static String getTypePrintOut(VarType type) {
@ -951,14 +942,14 @@ public class ClassWriter {
return typeText; return typeText;
} }
private static void appendComment(TextBuffer buffer, String comment, int indent, String lineSeparator) { private static void appendComment(TextBuffer buffer, String comment, int indent) {
buffer.appendIndent(indent).append("// $FF: ").append(comment).append(lineSeparator); buffer.appendIndent(indent).append("// $FF: ").append(comment).appendLineSeparator();
} }
private static final String[] ANNOTATION_ATTRIBUTES = { private static final String[] ANNOTATION_ATTRIBUTES = {
StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS}; StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS};
private static void appendAnnotations(TextBuffer buffer, StructMember mb, int indent, String lineSeparator) { private static void appendAnnotations(TextBuffer buffer, StructMember mb, int indent) {
BytecodeMappingTracer tracer_dummy = new BytecodeMappingTracer(); // FIXME: replace with a real one BytecodeMappingTracer tracer_dummy = new BytecodeMappingTracer(); // FIXME: replace with a real one
@ -966,7 +957,7 @@ public class ClassWriter {
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, tracer_dummy)).append(lineSeparator); buffer.append(annotation.toJava(indent, tracer_dummy)).appendLineSeparator();
} }
} }
} }

@ -15,14 +15,6 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler; package org.jetbrains.java.decompiler.modules.decompiler;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.code.Instruction; import org.jetbrains.java.decompiler.code.Instruction;
import org.jetbrains.java.decompiler.code.InstructionSequence; import org.jetbrains.java.decompiler.code.InstructionSequence;
@ -30,28 +22,12 @@ 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.TextBuffer; import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.modules.decompiler.exps.ArrayExprent; import org.jetbrains.java.decompiler.modules.decompiler.exps.*;
import org.jetbrains.java.decompiler.modules.decompiler.exps.AssignmentExprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.ConstExprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.ExitExprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.FieldExprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.FunctionExprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.IfExprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.InvocationExprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.MonitorExprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.NewExprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.SwitchExprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.VarExprent;
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;
import org.jetbrains.java.decompiler.modules.decompiler.sforms.FlattenStatementsHelper; import org.jetbrains.java.decompiler.modules.decompiler.sforms.FlattenStatementsHelper;
import org.jetbrains.java.decompiler.modules.decompiler.sforms.FlattenStatementsHelper.FinallyPathWrapper; import org.jetbrains.java.decompiler.modules.decompiler.sforms.FlattenStatementsHelper.FinallyPathWrapper;
import org.jetbrains.java.decompiler.modules.decompiler.stats.BasicBlockStatement; import org.jetbrains.java.decompiler.modules.decompiler.stats.*;
import org.jetbrains.java.decompiler.modules.decompiler.stats.CatchAllStatement;
import org.jetbrains.java.decompiler.modules.decompiler.stats.CatchStatement;
import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement;
import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor; import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor;
import org.jetbrains.java.decompiler.struct.StructClass; import org.jetbrains.java.decompiler.struct.StructClass;
import org.jetbrains.java.decompiler.struct.attr.StructBootstrapMethodsAttribute; import org.jetbrains.java.decompiler.struct.attr.StructBootstrapMethodsAttribute;
@ -62,7 +38,8 @@ import org.jetbrains.java.decompiler.struct.consts.PooledConstant;
import org.jetbrains.java.decompiler.struct.consts.PrimitiveConstant; import org.jetbrains.java.decompiler.struct.consts.PrimitiveConstant;
import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor; import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.*;
public class ExprProcessor implements CodeConstants { public class ExprProcessor implements CodeConstants {
@ -784,13 +761,11 @@ public class ExprProcessor implements CodeConstants {
public static TextBuffer jmpWrapper(Statement stat, int indent, boolean semicolon, BytecodeMappingTracer tracer) { public static TextBuffer jmpWrapper(Statement stat, int indent, boolean semicolon, BytecodeMappingTracer tracer) {
TextBuffer buf = stat.toJava(indent, tracer); TextBuffer buf = stat.toJava(indent, tracer);
String new_line_separator = DecompilerContext.getNewLineSeparator();
List<StatEdge> lstSuccs = stat.getSuccessorEdges(Statement.STATEDGE_DIRECT_ALL); List<StatEdge> lstSuccs = stat.getSuccessorEdges(Statement.STATEDGE_DIRECT_ALL);
if (lstSuccs.size() == 1) { if (lstSuccs.size() == 1) {
StatEdge edge = lstSuccs.get(0); StatEdge edge = lstSuccs.get(0);
if (edge.getType() != StatEdge.TYPE_REGULAR && edge.explicit && edge.getDestination().type != Statement.TYPE_DUMMYEXIT) { if (edge.getType() != StatEdge.TYPE_REGULAR && edge.explicit && edge.getDestination().type != Statement.TYPE_DUMMYEXIT) {
buf.append(InterpreterUtil.getIndentString(indent)); buf.appendIndent(indent);
switch (edge.getType()) { switch (edge.getType()) {
case StatEdge.TYPE_BREAK: case StatEdge.TYPE_BREAK:
@ -803,13 +778,13 @@ public class ExprProcessor implements CodeConstants {
if (edge.labeled) { if (edge.labeled) {
buf.append(" label").append(edge.closure.id.toString()); buf.append(" label").append(edge.closure.id.toString());
} }
buf.append(";").append(new_line_separator); buf.append(";").appendLineSeparator();
tracer.incrementCurrentSourceLine(); tracer.incrementCurrentSourceLine();
} }
} }
if (buf.length() == 0 && semicolon) { if (buf.length() == 0 && semicolon) {
buf.append(InterpreterUtil.getIndentString(indent)).append(";").append(new_line_separator); buf.appendIndent(indent).append(";").appendLineSeparator();
tracer.incrementCurrentSourceLine(); tracer.incrementCurrentSourceLine();
} }
@ -835,16 +810,13 @@ public class ExprProcessor implements CodeConstants {
return new TextBuffer(); return new TextBuffer();
} }
String indstr = InterpreterUtil.getIndentString(indent);
String new_line_separator = DecompilerContext.getNewLineSeparator();
TextBuffer buf = new TextBuffer(); TextBuffer buf = new TextBuffer();
for (Exprent expr : lst) { for (Exprent expr : lst) {
TextBuffer content = expr.toJava(indent, tracer); TextBuffer 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.appendIndent(indent);
} }
buf.append(content); buf.append(content);
if (expr.type == Exprent.EXPRENT_MONITOR && ((MonitorExprent)expr).getMontype() == MonitorExprent.MONITOR_ENTER) { if (expr.type == Exprent.EXPRENT_MONITOR && ((MonitorExprent)expr).getMontype() == MonitorExprent.MONITOR_ENTER) {
@ -853,7 +825,7 @@ public class ExprProcessor implements CodeConstants {
if (endsWithSemikolon(expr)) { if (endsWithSemikolon(expr)) {
buf.append(";"); buf.append(";");
} }
buf.append(new_line_separator); buf.appendLineSeparator();
tracer.incrementCurrentSourceLine(); tracer.incrementCurrentSourceLine();
} }
} }

@ -15,13 +15,11 @@
*/ */
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.TextBuffer; import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; 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;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -101,20 +99,13 @@ public class SequenceStatement extends Statement {
} }
public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) {
TextBuffer buf = new TextBuffer(); TextBuffer buf = new TextBuffer();
String indstr = null;
boolean islabeled = isLabeled(); boolean islabeled = isLabeled();
String new_line_separator = DecompilerContext.getNewLineSeparator();
buf.append(ExprProcessor.listToJava(varDefinitions, indent, tracer)); buf.append(ExprProcessor.listToJava(varDefinitions, indent, tracer));
if (islabeled) { if (islabeled) {
indstr = InterpreterUtil.getIndentString(indent); buf.appendIndent(indent++).append("label").append(this.id.toString()).append(": {").appendLineSeparator();
indent++;
buf.append(indstr).append("label").append(this.id.toString()).append(": {").append(new_line_separator);
tracer.incrementCurrentSourceLine(); tracer.incrementCurrentSourceLine();
} }
@ -125,7 +116,7 @@ public class SequenceStatement extends Statement {
Statement st = stats.get(i); Statement st = stats.get(i);
if (i > 0 && notempty) { if (i > 0 && notempty) {
buf.append(new_line_separator); buf.appendLineSeparator();
tracer.incrementCurrentSourceLine(); tracer.incrementCurrentSourceLine();
} }
@ -136,7 +127,7 @@ public class SequenceStatement extends Statement {
} }
if (islabeled) { if (islabeled) {
buf.append(indstr).append("}").append(new_line_separator); buf.appendIndent(indent-1).append("}").appendLineSeparator();
tracer.incrementCurrentSourceLine(); tracer.incrementCurrentSourceLine();
} }

@ -15,14 +15,12 @@
*/ */
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.TextBuffer; import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; 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;
import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent; import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -71,26 +69,21 @@ public class SynchronizedStatement extends Statement {
// ***************************************************************************** // *****************************************************************************
public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) {
String indstr = InterpreterUtil.getIndentString(indent);
String new_line_separator = DecompilerContext.getNewLineSeparator();
TextBuffer buf = new TextBuffer(); TextBuffer buf = new TextBuffer();
buf.append(ExprProcessor.listToJava(varDefinitions, indent, tracer)); buf.append(ExprProcessor.listToJava(varDefinitions, indent, tracer));
buf.append(first.toJava(indent, tracer)); buf.append(first.toJava(indent, tracer));
if (isLabeled()) { if (isLabeled()) {
buf.append(indstr).append("label").append(this.id.toString()).append(":").append(new_line_separator); buf.appendIndent(indent).append("label").append(this.id.toString()).append(":").appendLineSeparator();
tracer.incrementCurrentSourceLine(); tracer.incrementCurrentSourceLine();
} }
buf.append(indstr).append(headexprent.get(0).toJava(indent, tracer)).append(" {").append(new_line_separator); buf.appendIndent(indent).append(headexprent.get(0).toJava(indent, tracer)).append(" {").appendLineSeparator();
tracer.incrementCurrentSourceLine(); tracer.incrementCurrentSourceLine();
buf.append(ExprProcessor.jmpWrapper(body, indent + 1, true, tracer)); buf.append(ExprProcessor.jmpWrapper(body, indent + 1, true, tracer));
tracer.incrementCurrentSourceLine();
buf.append(indstr).append("}").append(new_line_separator); buf.appendIndent(indent).append("}").appendLineSeparator();
tracer.incrementCurrentSourceLine(); tracer.incrementCurrentSourceLine();
return buf; return buf;

@ -30,4 +30,5 @@ public class BytecodeToSourceMappingTest extends SingleClassesTestBase {
} }
@Test public void testSimpleBytecodeMapping() { doTest("pkg/TestClassSimpleBytecodeMapping"); } @Test public void testSimpleBytecodeMapping() { doTest("pkg/TestClassSimpleBytecodeMapping"); }
@Test public void testSynchronizedMapping() { doTest("pkg/TestSynchronizedMapping"); }
} }

@ -0,0 +1,30 @@
package pkg;
public class TestSynchronizedMapping {
public int test(int var1) {
synchronized(this) {
return var1++;
}
}
public void test2(String var1) {
System.out.println(var1);
}
}
class 'pkg/TestSynchronizedMapping' {
method 'test (I)I' {
3 4
5 5
}
method 'test2 (Ljava/lang/String;)V' {
0 10
4 10
}
}
Lines mapping:
8 <-> 5
9 <-> 6
14 <-> 11

@ -0,0 +1,16 @@
package pkg;
import java.lang.Override;
import java.lang.Runnable;
public class TestSynchronizedMapping {
public int test(int a) {
synchronized (this) {
return a++;
}
}
public void test2(String a) {
System.out.println(a);
}
}
Loading…
Cancel
Save