Fix for KT-13133: Incorrect InnerClasses attribute value for anonymous object copied from an inline function
#KT-13133 Fixed
This commit is contained in:
+1
-1
@@ -222,7 +222,7 @@ public class AnonymousObjectTransformer extends ObjectTransformer<AnonymousObjec
|
|||||||
MethodInliner inliner = new MethodInliner(
|
MethodInliner inliner = new MethodInliner(
|
||||||
sourceNode,
|
sourceNode,
|
||||||
parameters,
|
parameters,
|
||||||
inliningContext.subInline(inliningContext.nameGenerator.subGenerator("lambda")),
|
inliningContext.subInline(transformationInfo.getNameGenerator()),
|
||||||
remapper,
|
remapper,
|
||||||
isSameModule,
|
isSameModule,
|
||||||
"Transformer for " + transformationInfo.getOldClassName(),
|
"Transformer for " + transformationInfo.getOldClassName(),
|
||||||
|
|||||||
@@ -16,36 +16,52 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.codegen.inline;
|
package org.jetbrains.kotlin.codegen.inline;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class NameGenerator {
|
public class NameGenerator {
|
||||||
|
|
||||||
private final String ownerMethod;
|
private final String generatorClass;
|
||||||
|
|
||||||
private int nextLambdaIndex = 1;
|
private int nextLambdaIndex = 1;
|
||||||
private int nextWhenIndex = 1;
|
private int nextWhenIndex = 1;
|
||||||
|
|
||||||
private final Map<String, NameGenerator> subGenerators = new HashMap<String, NameGenerator>();
|
private final Map<String, NameGenerator> subGenerators = new HashMap<String, NameGenerator>();
|
||||||
|
|
||||||
public NameGenerator(String onwerMethod) {
|
public NameGenerator(String generatorClass) {
|
||||||
this.ownerMethod = onwerMethod;
|
this.generatorClass = generatorClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String genLambdaClassName() {
|
public String getGeneratorClass() {
|
||||||
return ownerMethod + "$" + nextLambdaIndex++;
|
return generatorClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String genWhenClassNamePrefix() {
|
private String genLambdaClassName() {
|
||||||
return ownerMethod + "$" + nextWhenIndex++;
|
return generatorClass + "$" + nextLambdaIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String genWhenClassName(@NotNull String original) {
|
||||||
|
return generatorClass + "$" + nextWhenIndex++ + WhenMappingTransformationInfo.TRANSFORMED_WHEN_MAPPING_MARKER + original;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NameGenerator subGenerator(String inliningMethod) {
|
public NameGenerator subGenerator(String inliningMethod) {
|
||||||
NameGenerator generator = subGenerators.get(inliningMethod);
|
NameGenerator generator = subGenerators.get(inliningMethod);
|
||||||
if (generator == null) {
|
if (generator == null) {
|
||||||
generator = new NameGenerator(ownerMethod+ "$" + inliningMethod);
|
generator = new NameGenerator(generatorClass + "$" + inliningMethod);
|
||||||
subGenerators.put(inliningMethod, generator);
|
subGenerators.put(inliningMethod, generator);
|
||||||
}
|
}
|
||||||
return generator;
|
return generator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public NameGenerator subGenerator(boolean lambdaNoWhen, @Nullable String nameSuffix) {
|
||||||
|
String generatorClass = lambdaNoWhen ? genLambdaClassName() : genWhenClassName(nameSuffix);
|
||||||
|
assert !subGenerators.containsKey(generatorClass) : "Name generator for regenerated class should be unique: " + generatorClass;
|
||||||
|
NameGenerator generator = new NameGenerator(generatorClass);
|
||||||
|
subGenerators.put(generatorClass, generator);
|
||||||
|
return generator;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ interface TransformationInfo {
|
|||||||
val oldClassName: String
|
val oldClassName: String
|
||||||
|
|
||||||
val newClassName: String
|
val newClassName: String
|
||||||
|
get() = nameGenerator.generatorClass
|
||||||
|
|
||||||
|
val nameGenerator: NameGenerator
|
||||||
|
|
||||||
fun shouldRegenerate(sameModule: Boolean): Boolean
|
fun shouldRegenerate(sameModule: Boolean): Boolean
|
||||||
|
|
||||||
@@ -32,13 +35,13 @@ interface TransformationInfo {
|
|||||||
|
|
||||||
class WhenMappingTransformationInfo(
|
class WhenMappingTransformationInfo(
|
||||||
override val oldClassName: String,
|
override val oldClassName: String,
|
||||||
val nameGenerator: NameGenerator,
|
parentNameGenerator: NameGenerator,
|
||||||
val alreadyRegenerated: Boolean,
|
val alreadyRegenerated: Boolean,
|
||||||
val fieldNode: FieldInsnNode
|
val fieldNode: FieldInsnNode
|
||||||
) : TransformationInfo {
|
) : TransformationInfo {
|
||||||
override val newClassName by lazy {
|
|
||||||
nameGenerator.genWhenClassNamePrefix() + TRANSFORMED_WHEN_MAPPING_MARKER +
|
override val nameGenerator by lazy {
|
||||||
oldClassName.substringAfterLast("/").substringAfterLast(TRANSFORMED_WHEN_MAPPING_MARKER)
|
parentNameGenerator.subGenerator(false, oldClassName.substringAfterLast("/").substringAfterLast(TRANSFORMED_WHEN_MAPPING_MARKER))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shouldRegenerate(sameModule: Boolean): Boolean = !alreadyRegenerated && !sameModule
|
override fun shouldRegenerate(sameModule: Boolean): Boolean = !alreadyRegenerated && !sameModule
|
||||||
@@ -61,10 +64,11 @@ class AnonymousObjectTransformationInfo internal constructor(
|
|||||||
private val alreadyRegenerated: Boolean,
|
private val alreadyRegenerated: Boolean,
|
||||||
val constructorDesc: String?,
|
val constructorDesc: String?,
|
||||||
private val isStaticOrigin: Boolean,
|
private val isStaticOrigin: Boolean,
|
||||||
nameGenerator: NameGenerator
|
parentNameGenerator: NameGenerator
|
||||||
) : TransformationInfo {
|
) : TransformationInfo {
|
||||||
override val newClassName: String by lazy {
|
|
||||||
nameGenerator.genLambdaClassName()
|
override val nameGenerator by lazy {
|
||||||
|
parentNameGenerator.subGenerator(true, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
lateinit var newConstructorDescriptor: String
|
lateinit var newConstructorDescriptor: String
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// WITH_REFLECT
|
||||||
|
// FILE: 1.kt
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
inline fun inf(crossinline cif: Any.() -> String): () -> String {
|
||||||
|
return {
|
||||||
|
object : () -> String {
|
||||||
|
override fun invoke() = cif()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
// FILE: 2.kt
|
||||||
|
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val simpleName = inf {
|
||||||
|
javaClass.simpleName
|
||||||
|
}()
|
||||||
|
|
||||||
|
if (simpleName != "" ) return "fail 1: $simpleName"
|
||||||
|
|
||||||
|
val name = inf {
|
||||||
|
javaClass.name
|
||||||
|
}()
|
||||||
|
|
||||||
|
if (name != "_2Kt\$box$\$inlined\$inf$2$1" ) return "fail 2: $name"
|
||||||
|
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ fun box(): String {
|
|||||||
if (enclosingMethod?.name != "invoke") return "fail 1: ${enclosingMethod?.name}"
|
if (enclosingMethod?.name != "invoke") return "fail 1: ${enclosingMethod?.name}"
|
||||||
|
|
||||||
enclosingClass = res2.javaClass.enclosingClass
|
enclosingClass = res2.javaClass.enclosingClass
|
||||||
if (enclosingClass?.name != "_2Kt\$box$\$inlined\$call\$lambda\$lambda$2") return "fail 2: ${enclosingClass?.name}"
|
if (enclosingClass?.name != "_2Kt\$box$\$inlined\$call$2\$lambda$1") return "fail 2: ${enclosingClass?.name}"
|
||||||
|
|
||||||
return res2()
|
return res2()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ fun box(): String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (encl1 != "_2Kt\$box\$\$inlined\$test\$lambda$1") return "fail 1: $encl1"
|
if (encl1 != "_2Kt\$box\$\$inlined\$test\$lambda$1") return "fail 1: $encl1"
|
||||||
if (encl2 != "_2Kt\$box\$\$inlined\$test\$lambda\$lambda$2") return "fail 2: $encl2"
|
if (encl2 != "_2Kt\$box\$\$inlined\$test\$lambda$1$2") return "fail 2: $encl2"
|
||||||
|
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -17,6 +17,6 @@ inline fun test(s: () -> Unit) {
|
|||||||
s()
|
s()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2 INNERCLASS Kt10259Kt\$box\$\$inlined\$test\$lambda\$1
|
// 2 INNERCLASS Kt10259Kt\$box\$\$inlined\$test\$lambda\$1\s
|
||||||
// 2 INNERCLASS Kt10259Kt\$box\$\$inlined\$test\$lambda\$lambda\$1
|
// 2 INNERCLASS Kt10259Kt\$box\$\$inlined\$test\$lambda\$1\$1
|
||||||
// 4 INNERCLASS
|
// 4 INNERCLASS
|
||||||
+2
-2
@@ -17,6 +17,6 @@ inline fun test(crossinline s: () -> Unit) {
|
|||||||
|
|
||||||
// 3 INNERCLASS Kt10259_2Kt\$test\$1 null
|
// 3 INNERCLASS Kt10259_2Kt\$test\$1 null
|
||||||
// 2 INNERCLASS Kt10259_2Kt\$test\$1\$1
|
// 2 INNERCLASS Kt10259_2Kt\$test\$1\$1
|
||||||
// 2 INNERCLASS Kt10259_2Kt\$box\$\$inlined\$test\$1
|
// 2 INNERCLASS Kt10259_2Kt\$box\$\$inlined\$test\$1\s
|
||||||
// 2 INNERCLASS Kt10259_2Kt\$box\$\$inlined\$test\$lambda\$1
|
// 2 INNERCLASS Kt10259_2Kt\$box\$\$inlined\$test\$1\$1
|
||||||
// 9 INNERCLASS
|
// 9 INNERCLASS
|
||||||
+4
-4
@@ -21,9 +21,9 @@ inline fun test(crossinline s: () -> Unit) {
|
|||||||
|
|
||||||
// 3 INNERCLASS Kt10259_3Kt\$test\$1 null
|
// 3 INNERCLASS Kt10259_3Kt\$test\$1 null
|
||||||
// 2 INNERCLASS Kt10259_3Kt\$test\$1\$1
|
// 2 INNERCLASS Kt10259_3Kt\$test\$1\$1
|
||||||
// 2 INNERCLASS Kt10259_3Kt\$box\$\$inlined\$test\$1
|
// 2 INNERCLASS Kt10259_3Kt\$box\$\$inlined\$test\$1\s
|
||||||
// 2 INNERCLASS Kt10259_3Kt\$box\$\$inlined\$test\$lambda\$1
|
// 2 INNERCLASS Kt10259_3Kt\$box\$\$inlined\$test\$1\$1\s
|
||||||
// inlined:
|
// inlined:
|
||||||
// 2 INNERCLASS Kt10259_3Kt\$box\$\$inlined\$test\$lambda\$lambda\$lambda\$1
|
// 2 INNERCLASS Kt10259_3Kt\$box\$\$inlined\$test\$1\$1\$lambda\$1\s
|
||||||
// 2 INNERCLASS Kt10259_3Kt\$box\$\$inlined\$test\$lambda\$lambda\$lambda\$lambda\$1
|
// 2 INNERCLASS Kt10259_3Kt\$box\$\$inlined\$test\$1\$1\$lambda\$1\$1\s
|
||||||
// 13 INNERCLASS
|
// 13 INNERCLASS
|
||||||
@@ -121,6 +121,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt13133.kt")
|
||||||
|
public void testKt13133() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt13133.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt6552.kt")
|
@TestMetadata("kt6552.kt")
|
||||||
public void testKt6552() throws Exception {
|
public void testKt6552() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt6552.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt6552.kt");
|
||||||
|
|||||||
+6
@@ -121,6 +121,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt13133.kt")
|
||||||
|
public void testKt13133() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt13133.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt6552.kt")
|
@TestMetadata("kt6552.kt")
|
||||||
public void testKt6552() throws Exception {
|
public void testKt6552() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt6552.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt6552.kt");
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ public class OuterClassGenTest extends CodegenTestCase {
|
|||||||
doCustomTest("foo/Bar\\$objectInLambdaInlinedIntoObject\\$\\$inlined\\$inlineFoo\\$1", intoObjectInfo, "inlineObject");
|
doCustomTest("foo/Bar\\$objectInLambdaInlinedIntoObject\\$\\$inlined\\$inlineFoo\\$1", intoObjectInfo, "inlineObject");
|
||||||
|
|
||||||
OuterClassInfo objectInLambda = new OuterClassInfo("foo/Bar$objectInLambdaInlinedIntoObject$$inlined$inlineFoo$1", "run", "()V");
|
OuterClassInfo objectInLambda = new OuterClassInfo("foo/Bar$objectInLambdaInlinedIntoObject$$inlined$inlineFoo$1", "run", "()V");
|
||||||
doCustomTest("foo/Bar\\$objectInLambdaInlinedIntoObject\\$\\$inlined\\$inlineFoo\\$lambda\\$lambda\\$1",
|
doCustomTest("foo/Bar\\$objectInLambdaInlinedIntoObject\\$\\$inlined\\$inlineFoo\\$1\\$lambda\\$1",
|
||||||
objectInLambda, "inlineObject");
|
objectInLambda, "inlineObject");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,7 +138,7 @@ public class OuterClassGenTest extends CodegenTestCase {
|
|||||||
doCustomTest("foo/Bar\\$objectInLambdaInlinedIntoObject\\$\\$inlined\\$inlineFoo\\$1", intoObjectInfo, "inlineLambda");
|
doCustomTest("foo/Bar\\$objectInLambdaInlinedIntoObject\\$\\$inlined\\$inlineFoo\\$1", intoObjectInfo, "inlineLambda");
|
||||||
|
|
||||||
OuterClassInfo objectInLambda = new OuterClassInfo("foo/Bar$objectInLambdaInlinedIntoObject$$inlined$inlineFoo$1", "invoke", "()V");
|
OuterClassInfo objectInLambda = new OuterClassInfo("foo/Bar$objectInLambdaInlinedIntoObject$$inlined$inlineFoo$1", "invoke", "()V");
|
||||||
doCustomTest("foo/Bar\\$objectInLambdaInlinedIntoObject\\$\\$inlined\\$inlineFoo\\$lambda\\$lambda\\$1",
|
doCustomTest("foo/Bar\\$objectInLambdaInlinedIntoObject\\$\\$inlined\\$inlineFoo\\$1\\$lambda\\$1",
|
||||||
objectInLambda, "inlineLambda");
|
objectInLambda, "inlineLambda");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user