From 56b3edd3ca65328ac66c7c6181192269ce8d60e3 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 21 Oct 2014 20:49:51 +0400 Subject: [PATCH] decompiler: fixed line mapping in synchronized block --- .../java/decompiler/main/ClassWriter.java | 81 ++++++++---------- .../modules/decompiler/ExprProcessor.java | 46 ++-------- .../decompiler/stats/SequenceStatement.java | 15 +--- .../stats/SynchronizedStatement.java | 13 +-- .../BytecodeToSourceMappingTest.java | 1 + .../classes/pkg/TestSynchronizedMapping.class | Bin 0 -> 577 bytes testData/results/TestSynchronizedMapping.dec | 30 +++++++ testData/src/pkg/TestSynchronizedMapping.java | 16 ++++ 8 files changed, 98 insertions(+), 104 deletions(-) create mode 100644 testData/classes/pkg/TestSynchronizedMapping.class create mode 100644 testData/results/TestSynchronizedMapping.dec create mode 100644 testData/src/pkg/TestSynchronizedMapping.java diff --git a/src/org/jetbrains/java/decompiler/main/ClassWriter.java b/src/org/jetbrains/java/decompiler/main/ClassWriter.java index ad6a952..8c45ff9 100644 --- a/src/org/jetbrains/java/decompiler/main/ClassWriter.java +++ b/src/org/jetbrains/java/decompiler/main/ClassWriter.java @@ -142,8 +142,7 @@ public class ClassWriter { buffer.append(") ->"); } - buffer.append(" {"); - buffer.append(DecompilerContext.getNewLineSeparator()); + buffer.append(" {").appendLineSeparator(); 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); if (isEnum) { if (enumFields) { - buffer.append(','); - buffer.appendLineSeparator(); + buffer.append(',').appendLineSeparator(); } enumFields = true; } @@ -211,8 +209,7 @@ public class ClassWriter { } if (enumFields) { - buffer.append(';'); - buffer.appendLineSeparator(); + buffer.append(';').appendLineSeparator(); } // FIXME: fields don't matter at the moment @@ -226,6 +223,7 @@ public class ClassWriter { if (hide) continue; int position = buffer.length(); + int storedLine = startLine; if (hasContent) { buffer.appendLineSeparator(); startLine++; @@ -236,10 +234,11 @@ public class ClassWriter { hasContent = true; DecompilerContext.getBytecodeSourceMapper().addTracer(cl.qualifiedName, InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor()), method_tracer); - startLine = method_tracer.getCurrentSourceLine()+1; // zero-based line index + startLine = method_tracer.getCurrentSourceLine(); } else { buffer.setLength(position); + startLine = storedLine; } } @@ -278,11 +277,8 @@ public class ClassWriter { } private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent) { - String lineSeparator = DecompilerContext.getNewLineSeparator(); - if (node.type == ClassNode.CLASS_ANONYMOUS) { - buffer.append(" {"); - buffer.append(lineSeparator); + buffer.append(" {").appendLineSeparator(); return; } @@ -297,19 +293,19 @@ public class ClassWriter { boolean isAnnotation = (flags & CodeConstants.ACC_ANNOTATION) != 0; if (isDeprecated) { - appendDeprecation(buffer, indent, lineSeparator); + appendDeprecation(buffer, indent); } if (interceptor != null) { String oldName = interceptor.getOldName(cl.qualifiedName); - appendRenameComment(buffer, oldName, MType.CLASS, indent, lineSeparator); + appendRenameComment(buffer, oldName, MType.CLASS, indent); } 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); @@ -383,31 +379,28 @@ public class ClassWriter { } } - buffer.append('{'); - buffer.append(lineSeparator); + buffer.append('{').appendLineSeparator(); } 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 isDeprecated = fd.getAttributes().containsKey("Deprecated"); boolean isEnum = fd.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM); if (isDeprecated) { - appendDeprecation(buffer, indent, lineSeparator); + appendDeprecation(buffer, indent); } if (interceptor != null) { 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()) { - appendComment(buffer, "synthetic field", indent, lineSeparator); + appendComment(buffer, "synthetic field", indent); } - appendAnnotations(buffer, fd, indent, lineSeparator); + appendAnnotations(buffer, fd, indent); buffer.appendIndent(indent); @@ -467,8 +460,7 @@ public class ClassWriter { } if (!isEnum) { - buffer.append(";"); - buffer.append(lineSeparator); + buffer.append(";").appendLineSeparator(); } } @@ -523,8 +515,7 @@ public class ClassWriter { index += md_content.params[i].stack_size; } - buffer.append(") {"); - buffer.append(DecompilerContext.getNewLineSeparator()); + buffer.append(") {").appendLineSeparator(); indent += 1; } @@ -545,7 +536,7 @@ public class ClassWriter { if (methodWrapper.decompiledWithErrors) { buffer.appendIndent(indent); buffer.append("// $FF: Couldn't be decompiled"); - buffer.append(DecompilerContext.getNewLineSeparator()); + buffer.appendLineSeparator(); } if (!codeOnly) { @@ -553,7 +544,7 @@ public class ClassWriter { buffer.appendIndent(indent); buffer.append('}'); - buffer.append(DecompilerContext.getNewLineSeparator()); + buffer.appendLineSeparator(); } } finally { @@ -569,8 +560,6 @@ public class ClassWriter { boolean hideMethod = false; int start_index_method = buffer.length(); - String lineSeparator = DecompilerContext.getNewLineSeparator(); - MethodWrapper outerWrapper = (MethodWrapper)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_WRAPPER); DecompilerContext.setProperty(DecompilerContext.CURRENT_METHOD_WRAPPER, methodWrapper); @@ -596,24 +585,24 @@ public class ClassWriter { } if (isDeprecated) { - appendDeprecation(buffer, indent, lineSeparator); + appendDeprecation(buffer, indent); } if (interceptor != null) { 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 isBridge = (flags & CodeConstants.ACC_BRIDGE) != 0; if (isSynthetic) { - appendComment(buffer, "synthetic method", indent, lineSeparator); + appendComment(buffer, "synthetic method", indent); } 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); @@ -831,10 +820,12 @@ public class ClassWriter { if (methodWrapper.decompiledWithErrors) { buffer.appendIndent(indent + 1); buffer.append("// $FF: Couldn't be decompiled"); - buffer.append(lineSeparator); + buffer.appendLineSeparator(); + tracer.incrementCurrentSourceLine(); } buffer.appendIndent(indent).append('}').appendLineSeparator(); + tracer.incrementCurrentSourceLine(); } } finally { @@ -897,13 +888,13 @@ public class ClassWriter { return true; } - private static void appendDeprecation(TextBuffer buffer, int indent, String lineSeparator) { - buffer.appendIndent(indent).append("/** @deprecated */").append(lineSeparator); + private static void appendDeprecation(TextBuffer buffer, int indent) { + buffer.appendIndent(indent).append("/** @deprecated */").appendLineSeparator(); } 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; buffer.appendIndent(indent); @@ -939,7 +930,7 @@ public class ClassWriter { buffer.append(getTypePrintOut(md.ret)); } - buffer.append(lineSeparator); + buffer.appendLineSeparator(); } private static String getTypePrintOut(VarType type) { @@ -951,14 +942,14 @@ public class ClassWriter { return typeText; } - private static void appendComment(TextBuffer buffer, String comment, int indent, String lineSeparator) { - buffer.appendIndent(indent).append("// $FF: ").append(comment).append(lineSeparator); + private static void appendComment(TextBuffer buffer, String comment, int indent) { + buffer.appendIndent(indent).append("// $FF: ").append(comment).appendLineSeparator(); } private static final String[] ANNOTATION_ATTRIBUTES = { 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 @@ -966,7 +957,7 @@ public class ClassWriter { StructAnnotationAttribute attribute = (StructAnnotationAttribute)mb.getAttributes().getWithKey(name); if (attribute != null) { for (AnnotationExprent annotation : attribute.getAnnotations()) { - buffer.append(annotation.toJava(indent, tracer_dummy)).append(lineSeparator); + buffer.append(annotation.toJava(indent, tracer_dummy)).appendLineSeparator(); } } } diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java b/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java index 214f760..6bf8072 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java @@ -15,14 +15,6 @@ */ 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.Instruction; 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.TextBuffer; 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.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.exps.*; 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.FlattenStatementsHelper; 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.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.stats.*; import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor; import org.jetbrains.java.decompiler.struct.StructClass; 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.gen.MethodDescriptor; import org.jetbrains.java.decompiler.struct.gen.VarType; -import org.jetbrains.java.decompiler.util.InterpreterUtil; + +import java.util.*; 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) { TextBuffer buf = stat.toJava(indent, tracer); - String new_line_separator = DecompilerContext.getNewLineSeparator(); - List lstSuccs = stat.getSuccessorEdges(Statement.STATEDGE_DIRECT_ALL); if (lstSuccs.size() == 1) { StatEdge edge = lstSuccs.get(0); 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()) { case StatEdge.TYPE_BREAK: @@ -803,13 +778,13 @@ public class ExprProcessor implements CodeConstants { if (edge.labeled) { buf.append(" label").append(edge.closure.id.toString()); } - buf.append(";").append(new_line_separator); + buf.append(";").appendLineSeparator(); tracer.incrementCurrentSourceLine(); } } if (buf.length() == 0 && semicolon) { - buf.append(InterpreterUtil.getIndentString(indent)).append(";").append(new_line_separator); + buf.appendIndent(indent).append(";").appendLineSeparator(); tracer.incrementCurrentSourceLine(); } @@ -835,16 +810,13 @@ public class ExprProcessor implements CodeConstants { return new TextBuffer(); } - String indstr = InterpreterUtil.getIndentString(indent); - String new_line_separator = DecompilerContext.getNewLineSeparator(); - TextBuffer buf = new TextBuffer(); for (Exprent expr : lst) { TextBuffer content = expr.toJava(indent, tracer); if (content.length() > 0) { if (expr.type != Exprent.EXPRENT_VAR || !((VarExprent)expr).isClassdef()) { - buf.append(indstr); + buf.appendIndent(indent); } buf.append(content); if (expr.type == Exprent.EXPRENT_MONITOR && ((MonitorExprent)expr).getMontype() == MonitorExprent.MONITOR_ENTER) { @@ -853,7 +825,7 @@ public class ExprProcessor implements CodeConstants { if (endsWithSemikolon(expr)) { buf.append(";"); } - buf.append(new_line_separator); + buf.appendLineSeparator(); tracer.incrementCurrentSourceLine(); } } diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SequenceStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SequenceStatement.java index 6636bec..7d2ee43 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SequenceStatement.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SequenceStatement.java @@ -15,13 +15,11 @@ */ 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.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.modules.decompiler.DecHelper; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.StatEdge; -import org.jetbrains.java.decompiler.util.InterpreterUtil; import java.util.Arrays; import java.util.List; @@ -101,20 +99,13 @@ public class SequenceStatement extends Statement { } public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { - TextBuffer buf = new TextBuffer(); - - String indstr = null; boolean islabeled = isLabeled(); - String new_line_separator = DecompilerContext.getNewLineSeparator(); - buf.append(ExprProcessor.listToJava(varDefinitions, indent, tracer)); if (islabeled) { - indstr = InterpreterUtil.getIndentString(indent); - indent++; - 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(); } @@ -125,7 +116,7 @@ public class SequenceStatement extends Statement { Statement st = stats.get(i); if (i > 0 && notempty) { - buf.append(new_line_separator); + buf.appendLineSeparator(); tracer.incrementCurrentSourceLine(); } @@ -136,7 +127,7 @@ public class SequenceStatement extends Statement { } if (islabeled) { - buf.append(indstr).append("}").append(new_line_separator); + buf.appendIndent(indent-1).append("}").appendLineSeparator(); tracer.incrementCurrentSourceLine(); } diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SynchronizedStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SynchronizedStatement.java index 6a9c6f8..d32b9d7 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SynchronizedStatement.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SynchronizedStatement.java @@ -15,14 +15,12 @@ */ 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.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.SequenceHelper; import org.jetbrains.java.decompiler.modules.decompiler.StatEdge; import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent; -import org.jetbrains.java.decompiler.util.InterpreterUtil; import java.util.ArrayList; import java.util.List; @@ -71,26 +69,21 @@ public class SynchronizedStatement extends Statement { // ***************************************************************************** public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { - String indstr = InterpreterUtil.getIndentString(indent); - - String new_line_separator = DecompilerContext.getNewLineSeparator(); - TextBuffer buf = new TextBuffer(); buf.append(ExprProcessor.listToJava(varDefinitions, indent, tracer)); buf.append(first.toJava(indent, tracer)); 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(); } - 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(); 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(); return buf; diff --git a/test/org/jetbrains/java/decompiler/BytecodeToSourceMappingTest.java b/test/org/jetbrains/java/decompiler/BytecodeToSourceMappingTest.java index 2c1beb1..a258ca0 100644 --- a/test/org/jetbrains/java/decompiler/BytecodeToSourceMappingTest.java +++ b/test/org/jetbrains/java/decompiler/BytecodeToSourceMappingTest.java @@ -30,4 +30,5 @@ public class BytecodeToSourceMappingTest extends SingleClassesTestBase { } @Test public void testSimpleBytecodeMapping() { doTest("pkg/TestClassSimpleBytecodeMapping"); } + @Test public void testSynchronizedMapping() { doTest("pkg/TestSynchronizedMapping"); } } diff --git a/testData/classes/pkg/TestSynchronizedMapping.class b/testData/classes/pkg/TestSynchronizedMapping.class new file mode 100644 index 0000000000000000000000000000000000000000..4691cfd73b71245676afb1d365d86eb3f6efac4c GIT binary patch literal 577 zcmZ`#%Sr=55Uk!jM%NglF}~sxJj7=}yeVD;LGT3|1dp3I#MNXs#Eqh7KgWw66g(*C z&5u%RHcIs1z;`4h8Ye z;8+X#c06D2wd!TvEV<^kB~e52)Y@Q5on@~9!5hwf<+M^Gk>)E zn!gcQe7oISd|P^naKi(?bd;?~CCy=AZ=6*Rl~Sy-kWUsdg 5 +9 <-> 6 +14 <-> 11 diff --git a/testData/src/pkg/TestSynchronizedMapping.java b/testData/src/pkg/TestSynchronizedMapping.java new file mode 100644 index 0000000..37f0282 --- /dev/null +++ b/testData/src/pkg/TestSynchronizedMapping.java @@ -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); + } +}