From 9ba9af54254d17423286f0fa73f6b38c7c89b771 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Wed, 21 Jan 2015 21:46:45 +0300 Subject: [PATCH] decompiler: provide line numbers mapping inside lambdas --- .../java/decompiler/main/ClassWriter.java | 25 +++++--- .../modules/decompiler/exps/NewExprent.java | 2 +- testData/results/TestClassLambda.dec | 64 +++++++++++++++++-- 3 files changed, 78 insertions(+), 13 deletions(-) diff --git a/src/org/jetbrains/java/decompiler/main/ClassWriter.java b/src/org/jetbrains/java/decompiler/main/ClassWriter.java index cc7f2dd..6c08ef8 100644 --- a/src/org/jetbrains/java/decompiler/main/ClassWriter.java +++ b/src/org/jetbrains/java/decompiler/main/ClassWriter.java @@ -74,7 +74,7 @@ public class ClassWriter { } } - public void classLambdaToJava(ClassNode node, TextBuffer buffer, Exprent method_object, int indent) { + public void classLambdaToJava(ClassNode node, TextBuffer buffer, Exprent method_object, int indent, BytecodeMappingTracer origTracer) { ClassWrapper wrapper = node.getWrapper(); if (wrapper == null) { return; @@ -85,7 +85,7 @@ public class ClassWriter { ClassNode outerNode = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE); DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, node); - BytecodeMappingTracer tracer = new BytecodeMappingTracer(); + BytecodeMappingTracer tracer = new BytecodeMappingTracer(origTracer.getCurrentSourceLine()); try { StructClass cl = wrapper.getClassStruct(); @@ -138,10 +138,13 @@ public class ClassWriter { } buffer.append(" {").appendLineSeparator(); + tracer.incrementCurrentSourceLine(); methodLambdaToJava(node, wrapper, mt, buffer, indent + 1, !lambdaToAnonymous, tracer); buffer.appendIndent(indent).append("}"); + + addTracer(cl, mt, tracer); } } finally { @@ -151,6 +154,15 @@ public class ClassWriter { DecompilerContext.getLogger().endWriteClass(); } + private static void addTracer(StructClass cls, StructMethod method, BytecodeMappingTracer tracer) { + StructLineNumberTableAttribute lineNumberTable = + (StructLineNumberTableAttribute)method.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE); + tracer.setLineNumberTable(lineNumberTable); + DecompilerContext.getBytecodeSourceMapper().addTracer(cls.qualifiedName, + InterpreterUtil.makeUniqueKey(method.getName(), method.getDescriptor()), + tracer); + } + public void classToJava(ClassNode node, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) { ClassNode outerNode = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE); DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, node); @@ -232,8 +244,7 @@ public class ClassWriter { boolean methodSkipped = !methodToJava(node, mt, buffer, indent + 1, method_tracer); if (!methodSkipped) { hasContent = true; - DecompilerContext.getBytecodeSourceMapper().addTracer(cl.qualifiedName, - InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor()), method_tracer); + addTracer(cl, mt, method_tracer); startLine = method_tracer.getCurrentSourceLine(); } else { @@ -573,10 +584,6 @@ public class ClassWriter { boolean isDeprecated = mt.getAttributes().containsKey("Deprecated"); boolean clinit = false, init = false, dinit = false; - StructLineNumberTableAttribute lineNumberTable = - (StructLineNumberTableAttribute)mt.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE); - tracer.setLineNumberTable(lineNumberTable); - MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor()); int flags = mt.getAccessFlags(); @@ -805,6 +812,8 @@ public class ClassWriter { } // We do not have line information for method start, lets have it here for now + StructLineNumberTableAttribute lineNumberTable = + (StructLineNumberTableAttribute)mt.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE); if (lineNumberTable != null && DecompilerContext.getOption(IFernflowerPreferences.USE_DEBUG_LINE_NUMBERS)) { buffer.setCurrentLine(lineNumberTable.getFirstLine() - 1); } diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java index 960f26b..5fe944d 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java @@ -253,7 +253,7 @@ public class NewExprent extends Exprent { } Exprent methodObject = constructor == null ? null : constructor.getInstance(); TextBuffer clsBuf = new TextBuffer(); - new ClassWriter().classLambdaToJava(child, clsBuf, methodObject, indent); + new ClassWriter().classLambdaToJava(child, clsBuf, methodObject, indent, tracer); buf.append(clsBuf); tracer.incrementCurrentSourceLine(clsBuf.countLines()); } diff --git a/testData/results/TestClassLambda.dec b/testData/results/TestClassLambda.dec index 5536579..7dcada9 100644 --- a/testData/results/TestClassLambda.dec +++ b/testData/results/TestClassLambda.dec @@ -18,8 +18,8 @@ public class TestClassLambda { List var1 = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3), Integer.valueOf(4), Integer.valueOf(5), Integer.valueOf(6), Integer.valueOf(7)});// 29 int var2 = (int)Math.random();// 30 var1.forEach((var2x) -> {// 32 - int var3 = 2 * var2x.intValue(); - System.out.println(var3 + var2 + this.field); + int var3 = 2 * var2x.intValue();// 33 + System.out.println(var3 + var2 + this.field);// 34 }); } @@ -82,13 +82,25 @@ public class TestClassLambda { Runnable var2 = () -> { Runnable var1x = () -> { System.out.println("hello2" + var1); - }; - System.out.println("hello1" + var1); + };// 87 + System.out.println("hello1" + var1);// 88 };// 86 } } class 'pkg/TestClassLambda' { + method 'lambda$testLambda$0 (ILjava/lang/Integer;)V' { + 0 20 + 2 20 + 5 20 + 6 20 + 7 21 + c 21 + e 21 + 11 21 + 12 21 + } + method 'testLambda ()V' { 7 17 8 17 @@ -112,6 +124,20 @@ class 'pkg/TestClassLambda' { 4a 19 } + method 'lambda$testLambda1$1 (I)V' { + 0 28 + a 28 + 13 28 + 16 28 + } + + method 'lambda$testLambda1$2 (I)V' { + 0 31 + a 31 + 13 31 + 16 31 + } + method 'testLambda1 ()V' { 0 26 3 26 @@ -120,6 +146,11 @@ class 'pkg/TestClassLambda' { 12 32 } + method 'lambda$testLambda2$3 (II)I' { + 2 37 + 5 37 + } + method 'testLambda2 ()V' { 5 36 } @@ -138,6 +169,12 @@ class 'pkg/TestClassLambda' { e 51 } + method 'lambda$testLambda6$4 (IILjava/lang/String;)Z' { + 2 59 + 9 59 + 15 59 + } + method 'testLambda6 ()V' { 7 55 9 56 @@ -172,6 +209,21 @@ class 'pkg/TestClassLambda' { 1 76 } + method 'lambda$null$5 (I)V' { + 0 83 + a 83 + 13 83 + 16 83 + } + + method 'lambda$nestedLambdas$6 (I)V' { + 6 84 + 7 85 + 11 85 + 1a 85 + 1d 85 + } + method 'nestedLambdas ()V' { 0 80 1 80 @@ -183,6 +235,8 @@ Lines mapping: 29 <-> 18 30 <-> 19 32 <-> 20 +33 <-> 21 +34 <-> 22 39 <-> 27 40 <-> 30 41 <-> 33 @@ -201,3 +255,5 @@ Lines mapping: 81 <-> 77 85 <-> 81 86 <-> 87 +87 <-> 85 +88 <-> 86