Fix for KT-10259: Proguard can't find generated lambda class of lambda nested inside object?.let lambda

#Fixed KT-10259
This commit is contained in:
Michael Bogdanov
2015-12-10 16:19:41 +03:00
parent 9452c200a0
commit b950bf0e6e
10 changed files with 166 additions and 1 deletions
@@ -81,6 +81,7 @@ public class AnonymousObjectTransformer {
@NotNull
public InlineResult doTransform(@NotNull AnonymousObjectGeneration anonymousObjectGen, @NotNull FieldRemapper parentRemapper) {
final List<InnerClassNode> innerClassNodes = new ArrayList<InnerClassNode>();
ClassBuilder classBuilder = createClassBuilder();
final List<MethodNode> methodsToTransform = new ArrayList<MethodNode>();
@@ -95,6 +96,11 @@ public class AnonymousObjectTransformer {
super.visit(version, access, name, signature, superName, interfaces);
}
@Override
public void visitInnerClass(String name, String outerName, String innerName, int access) {
innerClassNodes.add(new InnerClassNode(name, outerName, innerName, access));
}
@Override
public void visitOuterClass(@NotNull String owner, String name, String desc) {
InliningContext parent = inliningContext.getParent();
@@ -200,6 +206,10 @@ public class AnonymousObjectTransformer {
SourceMapper.Companion.flushToClassBuilder(sourceMapper, classBuilder);
for (InnerClassNode node : innerClassNodes) {
classBuilder.getVisitor().visitInnerClass(node.name, node.outerName, node.innerName, node.access);
}
classBuilder.done();
anonymousObjectGen.setNewLambdaType(newLambdaType);
@@ -262,7 +262,14 @@ public class MethodInliner {
visitFieldInsn(Opcodes.GETSTATIC, capturedParamDesc.getContainingLambdaName(),
"$$$" + capturedParamDesc.getFieldName(), capturedParamDesc.getType().getDescriptor());
}
super.visitMethodInsn(opcode, anonymousObjectGen.getNewLambdaType().getInternalName(), name, anonymousObjectGen.getNewConstructorDescriptor(), itf);
String newInternalName = anonymousObjectGen.getNewLambdaType().getInternalName();
super.visitMethodInsn(opcode, newInternalName, name, anonymousObjectGen.getNewConstructorDescriptor(), itf);
//TODO: add new inner class also for other contexts
if (inliningContext.getParent() instanceof RegeneratedClassContext) {
inliningContext.getParent().typeRemapper.addAdditionalMappings(anonymousObjectGen.getOwnerInternalName(), newInternalName);
}
anonymousObjectGen = null;
} else {
super.visitMethodInsn(opcode, changeOwnerForExternalPackage(owner, opcode), name, desc, itf);
@@ -0,0 +1,22 @@
import test.*
fun box(): String {
var encl1 = "fail";
var encl2 = "fail";
test {
{
val p = object {}
encl1 = p.javaClass.enclosingMethod.declaringClass.name
{
val p = object {}
encl2 = p.javaClass.enclosingMethod.declaringClass.name
}()
}()
}
if (encl1 != "Kt10259_1Kt\$box\$\$inlined\$test\$lambda$1") return "fail 1: $encl1"
if (encl2 != "Kt10259_1Kt\$box\$\$inlined\$test\$lambda\$lambda$2") return "fail 2: $encl2"
return "OK"
}
@@ -0,0 +1,5 @@
package test
inline fun test(s: () -> Unit) {
s()
}
+22
View File
@@ -0,0 +1,22 @@
fun box(): String {
var encl1 = "fail";
var encl2 = "fail";
test {
{
encl1 = "OK"
{
encl2 = "OK"
}()
}()
}
return "OK"
}
inline fun test(s: () -> Unit) {
s()
}
// 2 INNERCLASS Kt10259Kt\$box\$\$inlined\$test\$lambda\$1
// 2 INNERCLASS Kt10259Kt\$box\$\$inlined\$test\$lambda\$lambda\$1
// 4 INNERCLASS
+22
View File
@@ -0,0 +1,22 @@
fun box(): String {
var encl1 = "fail";
test {
encl1 = "OK"
}
return encl1
}
inline fun test(crossinline s: () -> Unit) {
{
{
s()
}()
}()
}
// 3 INNERCLASS Kt10259_2Kt\$test\$1 null
// 2 INNERCLASS Kt10259_2Kt\$test\$1\$1
// 2 INNERCLASS Kt10259_2Kt\$box\$\$inlined\$test\$1
// 2 INNERCLASS Kt10259_2Kt\$box\$\$inlined\$test\$lambda\$1
// 9 INNERCLASS
+29
View File
@@ -0,0 +1,29 @@
fun box(): String {
var encl1 = "fail";
test {
{
{
encl1 = "OK"
}()
}()
}
return encl1
}
inline fun test(crossinline s: () -> Unit) {
{
{
s()
}()
}()
}
// 3 INNERCLASS Kt10259_3Kt\$test\$1 null
// 2 INNERCLASS Kt10259_3Kt\$test\$1\$1
// 2 INNERCLASS Kt10259_3Kt\$box\$\$inlined\$test\$1
// 2 INNERCLASS Kt10259_3Kt\$box\$\$inlined\$test\$lambda\$1
// inlined:
// 2 INNERCLASS Kt10259_3Kt\$box\$\$inlined\$test\$lambda\$lambda\$lambda\$1
// 2 INNERCLASS Kt10259_3Kt\$box\$\$inlined\$test\$lambda\$lambda\$lambda\$lambda\$1
// 13 INNERCLASS
@@ -167,6 +167,24 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
doTest(fileName);
}
@TestMetadata("kt10259.kt")
public void testKt10259() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/kt10259.kt");
doTest(fileName);
}
@TestMetadata("kt10259_2.kt")
public void testKt10259_2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/kt10259_2.kt");
doTest(fileName);
}
@TestMetadata("kt10259_3.kt")
public void testKt10259_3() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/kt10259_3.kt");
doTest(fileName);
}
@TestMetadata("kt2202.kt")
public void testKt2202() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/kt2202.kt");
@@ -602,6 +602,21 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
}
}
@TestMetadata("compiler/testData/codegen/boxInline/innerClasses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class InnerClasses extends AbstractBlackBoxInlineCodegenTest {
public void testAllFilesPresentInInnerClasses() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/innerClasses"), Pattern.compile("^(.+)\\.1.kt$"), true);
}
@TestMetadata("kt10259.1.kt")
public void testKt10259() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/innerClasses/kt10259.1.kt");
doTestMultiFileWithInlineCheck(fileName);
}
}
@TestMetadata("compiler/testData/codegen/boxInline/lambdaClassClash")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -602,6 +602,21 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
}
}
@TestMetadata("compiler/testData/codegen/boxInline/innerClasses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class InnerClasses extends AbstractCompileKotlinAgainstInlineKotlinTest {
public void testAllFilesPresentInInnerClasses() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/innerClasses"), Pattern.compile("^(.+)\\.1.kt$"), true);
}
@TestMetadata("kt10259.1.kt")
public void testKt10259() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/innerClasses/kt10259.1.kt");
doBoxTestWithInlineCheck(fileName);
}
}
@TestMetadata("compiler/testData/codegen/boxInline/lambdaClassClash")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)