Fix target for annotations/metadata on open suspend functions
Get rid of rewriting of vars in FunctionCodegen::generateMethod, just extracted generateMethodBody instead #KT-19814 Fixed
This commit is contained in:
@@ -204,53 +204,6 @@ public class FunctionCodegen {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isOpenSuspendInClass =
|
||||
functionDescriptor.isSuspend() &&
|
||||
functionDescriptor.getModality() != Modality.ABSTRACT && isOverridable(functionDescriptor) &&
|
||||
!isInterface(functionDescriptor.getContainingDeclaration()) &&
|
||||
origin.getOriginKind() != JvmDeclarationOriginKind.CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL;
|
||||
|
||||
if (isOpenSuspendInClass) {
|
||||
MethodVisitor mv =
|
||||
v.newMethod(origin,
|
||||
flags,
|
||||
asmMethod.getName(),
|
||||
asmMethod.getDescriptor(),
|
||||
jvmSignature.getGenericsSignature(),
|
||||
getThrownExceptions(functionDescriptor, typeMapper)
|
||||
);
|
||||
|
||||
mv.visitCode();
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
int index = 1;
|
||||
for (Type type : asmMethod.getArgumentTypes()) {
|
||||
mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), index);
|
||||
index += type.getSize();
|
||||
}
|
||||
|
||||
asmMethod = CoroutineCodegenUtilKt.getImplForOpenMethod(asmMethod, v.getThisName());
|
||||
// remove generic signature as it's unnecessary for synthetic methods
|
||||
jvmSignature =
|
||||
new JvmMethodGenericSignature(
|
||||
asmMethod,
|
||||
jvmSignature.getValueParameters(),
|
||||
null
|
||||
);
|
||||
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKESTATIC,
|
||||
v.getThisName(), asmMethod.getName(), asmMethod.getDescriptor(),
|
||||
false
|
||||
);
|
||||
|
||||
mv.visitInsn(Opcodes.ARETURN);
|
||||
mv.visitEnd();
|
||||
|
||||
flags |= Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC;
|
||||
flags &= ~getVisibilityAccessFlag(functionDescriptor);
|
||||
flags |= AsmUtil.NO_FLAG_PACKAGE_PRIVATE;
|
||||
}
|
||||
|
||||
MethodVisitor mv =
|
||||
strategy.wrapMethodVisitor(
|
||||
v.newMethod(origin,
|
||||
@@ -286,6 +239,79 @@ public class FunctionCodegen {
|
||||
parentBodyCodegen.addAdditionalTask(new JvmStaticInCompanionObjectGenerator(functionDescriptor, origin, state, parentBodyCodegen));
|
||||
}
|
||||
|
||||
boolean isOpenSuspendInClass =
|
||||
functionDescriptor.isSuspend() &&
|
||||
functionDescriptor.getModality() != Modality.ABSTRACT && isOverridable(functionDescriptor) &&
|
||||
!isInterface(functionDescriptor.getContainingDeclaration()) &&
|
||||
origin.getOriginKind() != JvmDeclarationOriginKind.CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL;
|
||||
|
||||
if (isOpenSuspendInClass) {
|
||||
mv.visitCode();
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
int index = 1;
|
||||
for (Type type : asmMethod.getArgumentTypes()) {
|
||||
mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), index);
|
||||
index += type.getSize();
|
||||
}
|
||||
|
||||
Method asmMethodForOpenSuspendImpl = CoroutineCodegenUtilKt.getImplForOpenMethod(asmMethod, v.getThisName());
|
||||
// remove generic signature as it's unnecessary for synthetic methods
|
||||
JvmMethodSignature jvmSignatureForOpenSuspendImpl =
|
||||
new JvmMethodGenericSignature(
|
||||
asmMethodForOpenSuspendImpl,
|
||||
jvmSignature.getValueParameters(),
|
||||
null
|
||||
);
|
||||
|
||||
mv.visitMethodInsn(
|
||||
Opcodes.INVOKESTATIC,
|
||||
v.getThisName(), asmMethodForOpenSuspendImpl.getName(), asmMethodForOpenSuspendImpl.getDescriptor(),
|
||||
false
|
||||
);
|
||||
|
||||
mv.visitInsn(Opcodes.ARETURN);
|
||||
mv.visitEnd();
|
||||
|
||||
int flagsForOpenSuspendImpl = flags;
|
||||
flagsForOpenSuspendImpl |= Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC;
|
||||
flagsForOpenSuspendImpl &= ~getVisibilityAccessFlag(functionDescriptor);
|
||||
flagsForOpenSuspendImpl |= AsmUtil.NO_FLAG_PACKAGE_PRIVATE;
|
||||
|
||||
MethodVisitor mvForOpenSuspendImpl = strategy.wrapMethodVisitor(
|
||||
v.newMethod(origin,
|
||||
flagsForOpenSuspendImpl,
|
||||
asmMethodForOpenSuspendImpl.getName(),
|
||||
asmMethodForOpenSuspendImpl.getDescriptor(),
|
||||
null,
|
||||
getThrownExceptions(functionDescriptor, typeMapper)
|
||||
),
|
||||
flagsForOpenSuspendImpl, asmMethodForOpenSuspendImpl.getName(),
|
||||
asmMethodForOpenSuspendImpl.getDescriptor()
|
||||
);
|
||||
|
||||
generateMethodBody(
|
||||
origin, functionDescriptor, methodContext, strategy, mvForOpenSuspendImpl, jvmSignatureForOpenSuspendImpl,
|
||||
staticInCompanionObject
|
||||
);
|
||||
}
|
||||
else {
|
||||
generateMethodBody(
|
||||
origin, functionDescriptor, methodContext, strategy, mv, jvmSignature, staticInCompanionObject
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void generateMethodBody(
|
||||
@NotNull JvmDeclarationOrigin origin,
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@NotNull MethodContext methodContext,
|
||||
@NotNull FunctionGenerationStrategy strategy,
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull JvmMethodSignature jvmSignature,
|
||||
boolean staticInCompanionObject
|
||||
) {
|
||||
OwnerKind contextKind = methodContext.getContextKind();
|
||||
if (!state.getClassBuilderMode().generateBodies || isAbstractMethod(functionDescriptor, contextKind, state)) {
|
||||
generateLocalVariableTable(
|
||||
mv,
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// WITH_REFLECT
|
||||
// IGNORE_BACKEND: JS, NATIVE
|
||||
|
||||
import kotlin.reflect.full.declaredMemberFunctions
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
annotation class Anno
|
||||
|
||||
open class Aaa {
|
||||
@Anno
|
||||
suspend open fun aaa() {}
|
||||
}
|
||||
|
||||
class Bbb {
|
||||
@Anno
|
||||
suspend fun bbb() {}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val bbb = Bbb::class.declaredMemberFunctions.first { it.name == "bbb" }.annotations
|
||||
assertEquals(1, bbb.size)
|
||||
assertTrue(bbb.single() is Anno)
|
||||
val aaa = Aaa::class.declaredMemberFunctions.first { it.name == "aaa" }.annotations
|
||||
assertEquals(1, aaa.size)
|
||||
assertTrue(aaa.single() is Anno)
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// WITH_REFLECT
|
||||
// IGNORE_BACKEND: JS, NATIVE
|
||||
|
||||
import kotlin.reflect.full.declaredMemberFunctions
|
||||
import kotlin.reflect.jvm.javaMethod
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
open class Aaa {
|
||||
suspend open fun aaa() {}
|
||||
}
|
||||
|
||||
class Bbb {
|
||||
suspend fun bbb() {}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val bbb = Bbb::class.declaredMemberFunctions.first { it.name == "bbb" }.javaMethod
|
||||
assertEquals("bbb", bbb!!.name)
|
||||
val aaa = Aaa::class.declaredMemberFunctions.first { it.name == "aaa" }.javaMethod
|
||||
assertEquals("aaa", aaa!!.name)
|
||||
return "OK"
|
||||
}
|
||||
+12
@@ -14419,6 +14419,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("openSuspendFun.kt")
|
||||
public void testOpenSuspendFun() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/annotations/openSuspendFun.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("privateAnnotation.kt")
|
||||
public void testPrivateAnnotation() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/annotations/privateAnnotation.kt");
|
||||
@@ -15547,6 +15553,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("openSuspendFun.kt")
|
||||
public void testOpenSuspendFun() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/mapping/openSuspendFun.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyAccessors.kt")
|
||||
public void testPropertyAccessors() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/mapping/propertyAccessors.kt");
|
||||
|
||||
@@ -14419,6 +14419,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("openSuspendFun.kt")
|
||||
public void testOpenSuspendFun() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/annotations/openSuspendFun.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("privateAnnotation.kt")
|
||||
public void testPrivateAnnotation() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/annotations/privateAnnotation.kt");
|
||||
@@ -15547,6 +15553,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("openSuspendFun.kt")
|
||||
public void testOpenSuspendFun() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/mapping/openSuspendFun.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyAccessors.kt")
|
||||
public void testPropertyAccessors() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/mapping/propertyAccessors.kt");
|
||||
|
||||
@@ -14419,6 +14419,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("openSuspendFun.kt")
|
||||
public void testOpenSuspendFun() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/annotations/openSuspendFun.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("privateAnnotation.kt")
|
||||
public void testPrivateAnnotation() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/annotations/privateAnnotation.kt");
|
||||
@@ -15547,6 +15553,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("openSuspendFun.kt")
|
||||
public void testOpenSuspendFun() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/mapping/openSuspendFun.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyAccessors.kt")
|
||||
public void testPropertyAccessors() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/mapping/propertyAccessors.kt");
|
||||
|
||||
+24
@@ -16309,6 +16309,18 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
||||
}
|
||||
|
||||
@TestMetadata("openSuspendFun.kt")
|
||||
public void testOpenSuspendFun() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/annotations/openSuspendFun.kt");
|
||||
try {
|
||||
doTest(fileName);
|
||||
}
|
||||
catch (Throwable ignore) {
|
||||
return;
|
||||
}
|
||||
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
||||
}
|
||||
|
||||
@TestMetadata("privateAnnotation.kt")
|
||||
public void testPrivateAnnotation() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/annotations/privateAnnotation.kt");
|
||||
@@ -18403,6 +18415,18 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
||||
}
|
||||
|
||||
@TestMetadata("openSuspendFun.kt")
|
||||
public void testOpenSuspendFun() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/mapping/openSuspendFun.kt");
|
||||
try {
|
||||
doTest(fileName);
|
||||
}
|
||||
catch (Throwable ignore) {
|
||||
return;
|
||||
}
|
||||
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
||||
}
|
||||
|
||||
@TestMetadata("propertyAccessors.kt")
|
||||
public void testPropertyAccessors() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/mapping/propertyAccessors.kt");
|
||||
|
||||
Reference in New Issue
Block a user