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:
Denis Zharkov
2017-08-30 15:03:35 +03:00
parent 742fecf69c
commit 80a90572d6
7 changed files with 183 additions and 47 deletions
@@ -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"
}
@@ -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");
@@ -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");