From f83defaa7fb22e315f7b936a8287af0e2a1c48b3 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Fri, 8 Jun 2012 21:12:00 +0400 Subject: [PATCH] KT-2228 Open and final trait members are loaded as abstract from binary Kotlin classes. Added storing modality for trait members in @JetMethod annotations. #KT-2228 Fixed --- .../jet/codegen/FunctionCodegen.java | 21 +++++++++++---- .../codegen/ImplementationBodyCodegen.java | 8 ++++-- .../jet/codegen/PropertyCodegen.java | 20 +++++++++++--- .../resolve/java/JavaDescriptorResolver.java | 27 +++++++++++-------- .../jet/lang/resolve/java/JvmStdlibNames.java | 4 ++- .../classFun/TraitFinalFun.kt | 7 +++++ .../classFun/TraitFinalFun.txt | 5 ++++ .../classFun/TraitOpenFun.kt | 7 +++++ .../classFun/TraitOpenFun.txt | 5 ++++ .../prop/TraitFinalVar.kt | 11 ++++++++ .../prop/TraitFinalVar.txt | 5 ++++ .../prop/TraitOpenVal.kt | 8 ++++++ .../prop/TraitOpenVal.txt | 5 ++++ 13 files changed, 110 insertions(+), 23 deletions(-) create mode 100644 compiler/testData/readKotlinBinaryClass/classFun/TraitFinalFun.kt create mode 100644 compiler/testData/readKotlinBinaryClass/classFun/TraitFinalFun.txt create mode 100644 compiler/testData/readKotlinBinaryClass/classFun/TraitOpenFun.kt create mode 100644 compiler/testData/readKotlinBinaryClass/classFun/TraitOpenFun.txt create mode 100644 compiler/testData/readKotlinBinaryClass/prop/TraitFinalVar.kt create mode 100644 compiler/testData/readKotlinBinaryClass/prop/TraitFinalVar.txt create mode 100644 compiler/testData/readKotlinBinaryClass/prop/TraitOpenVal.kt create mode 100644 compiler/testData/readKotlinBinaryClass/prop/TraitOpenVal.txt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 87a6ae8c85b..f47fe2def07 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -29,6 +29,7 @@ import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmClassName; +import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.objectweb.asm.Label; @@ -97,8 +98,9 @@ public class FunctionCodegen { { flags |= ACC_VARARGS; } - - if (functionDescriptor.getModality() == Modality.FINAL) { + + Modality modality = functionDescriptor.getModality(); + if (modality == Modality.FINAL) { flags |= ACC_FINAL; } @@ -117,7 +119,7 @@ public class FunctionCodegen { flags |= ACC_STATIC; boolean isAbstract = ( - functionDescriptor.getModality() == Modality.ABSTRACT + modality == Modality.ABSTRACT || CodegenUtil.isInterface(functionDescriptor.getContainingDeclaration()) ) && !isStatic && kind != OwnerKind.TRAIT_IMPL; if (isAbstract) flags |= ACC_ABSTRACT; @@ -128,14 +130,23 @@ public class FunctionCodegen { int start = 0; if (needJetAnnotations) { if (functionDescriptor instanceof PropertyAccessorDescriptor) { - PropertyCodegen.generateJetPropertyAnnotation(mv, propertyTypeSignature, jvmSignature.getKotlinTypeParameter()); + PropertyCodegen.generateJetPropertyAnnotation(mv, propertyTypeSignature, jvmSignature.getKotlinTypeParameter(), + ((PropertyAccessorDescriptor) functionDescriptor) + .getCorrespondingProperty()); } else if (functionDescriptor instanceof SimpleFunctionDescriptor) { if (propertyTypeSignature != null) { throw new IllegalStateException(); } JetMethodAnnotationWriter aw = JetMethodAnnotationWriter.visitAnnotation(mv); - aw.writeFlags(); + if (CodegenUtil.isInterface(functionDescriptor.getContainingDeclaration()) && modality != Modality.ABSTRACT) { + aw.writeFlags(modality == Modality.FINAL + ? JvmStdlibNames.JET_METHOD_FLAG_FORCE_FINAL_BIT + : JvmStdlibNames.JET_METHOD_FLAG_FORCE_OPEN_BIT); + } + else { + aw.writeFlags(); + } aw.writeNullableReturnType(functionDescriptor.getReturnType().isNullable()); aw.writeTypeParameters(jvmSignature.getKotlinTypeParameter()); aw.writeReturnType(jvmSignature.getKotlinReturnType()); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 8bc7f6bdbec..cec73ebd275 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -334,7 +334,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { JvmPropertyAccessorSignature originalSignature = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION); Method originalMethod = originalSignature.getJvmMethodSignature().getAsmMethod(); MethodVisitor mv = v.newMethod(null, ACC_PUBLIC | ACC_BRIDGE | ACC_FINAL, method.getName(), method.getDescriptor(), null, null); - PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature.getPropertyTypeKotlinSignature(), originalSignature.getJvmMethodSignature().getKotlinTypeParameter()); + PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature.getPropertyTypeKotlinSignature(), + originalSignature.getJvmMethodSignature().getKotlinTypeParameter(), + original); if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { StubCodegen.generateStubCode(mv); } @@ -360,7 +362,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { JvmPropertyAccessorSignature originalSignature2 = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION); Method originalMethod = originalSignature2.getJvmMethodSignature().getAsmMethod(); MethodVisitor mv = v.newMethod(null, ACC_PUBLIC | ACC_BRIDGE | ACC_FINAL, method.getName(), method.getDescriptor(), null, null); - PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature2.getPropertyTypeKotlinSignature(), originalSignature2.getJvmMethodSignature().getKotlinTypeParameter()); + PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature2.getPropertyTypeKotlinSignature(), + originalSignature2.getJvmMethodSignature().getKotlinTypeParameter(), + original); if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { StubCodegen.generateStubCode(mv); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java index f00688c7bb4..96af2b74f2c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java @@ -178,7 +178,8 @@ public class PropertyCodegen { final String descriptor = signature.getJvmMethodSignature().getAsmMethod().getDescriptor(); String getterName = getterName(propertyDescriptor.getName()); MethodVisitor mv = v.newMethod(origin, flags, getterName, descriptor, null, null); - generateJetPropertyAnnotation(mv, signature.getPropertyTypeKotlinSignature(), signature.getJvmMethodSignature().getKotlinTypeParameter()); + generateJetPropertyAnnotation(mv, signature.getPropertyTypeKotlinSignature(), + signature.getJvmMethodSignature().getKotlinTypeParameter(), propertyDescriptor); if (propertyDescriptor.getGetter() != null) { assert !propertyDescriptor.getGetter().hasBody(); @@ -221,9 +222,19 @@ public class PropertyCodegen { FunctionCodegen.endVisit(mv, "getter", origin); } - public static void generateJetPropertyAnnotation(MethodVisitor mv, @NotNull String kotlinType, @NotNull String typeParameters) { + public static void generateJetPropertyAnnotation(MethodVisitor mv, @NotNull String kotlinType, @NotNull String typeParameters, + @NotNull PropertyDescriptor propertyDescriptor) { JetMethodAnnotationWriter aw = JetMethodAnnotationWriter.visitAnnotation(mv); - aw.writeFlags(JvmStdlibNames.JET_METHOD_FLAG_PROPERTY_BIT); + Modality modality = propertyDescriptor.getModality(); + if (CodegenUtil.isInterface(propertyDescriptor.getContainingDeclaration()) && modality != Modality.ABSTRACT) { + aw.writeFlags(JvmStdlibNames.JET_METHOD_FLAG_PROPERTY_BIT, + modality == Modality.FINAL + ? JvmStdlibNames.JET_METHOD_FLAG_FORCE_FINAL_BIT + : JvmStdlibNames.JET_METHOD_FLAG_FORCE_OPEN_BIT); + } + else { + aw.writeFlags(JvmStdlibNames.JET_METHOD_FLAG_PROPERTY_BIT); + } aw.writeTypeParameters(typeParameters); aw.writePropertyType(kotlinType); aw.visitEnd(); @@ -264,7 +275,8 @@ public class PropertyCodegen { JvmPropertyAccessorSignature signature = state.getInjector().getJetTypeMapper().mapSetterSignature(propertyDescriptor, kind); final String descriptor = signature.getJvmMethodSignature().getAsmMethod().getDescriptor(); MethodVisitor mv = v.newMethod(origin, flags, setterName(propertyDescriptor.getName()), descriptor, null, null); - generateJetPropertyAnnotation(mv, signature.getPropertyTypeKotlinSignature(), signature.getJvmMethodSignature().getKotlinTypeParameter()); + generateJetPropertyAnnotation(mv, signature.getPropertyTypeKotlinSignature(), + signature.getJvmMethodSignature().getKotlinTypeParameter(), propertyDescriptor); if (propertyDescriptor.getSetter() != null) { assert !propertyDescriptor.getSetter().hasBody(); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index e4628048c54..96128e81741 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -1340,19 +1340,10 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes isVar = members.setter != null; } - Modality modality; - if (isFinal) { - modality = Modality.FINAL; - } - else { - modality = anyMember.getMember().isAbstract() ? Modality.ABSTRACT : Modality.OPEN; - } - - PropertyDescriptor propertyDescriptor = new PropertyDescriptor( owner, resolveAnnotations(anyMember.getMember().psiMember), - modality, + resolveModality(anyMember.getMember(), isFinal), resolveVisibilityFromPsiModifiers(anyMember.getMember().psiMember), isVar, false, @@ -1658,7 +1649,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes methodTypeParameters, valueParameterDescriptors.descriptors, returnType, - Modality.convertFromFlags(method.getPsiMethod().hasModifierProperty(PsiModifier.ABSTRACT), !method.isFinal()), + resolveModality(method, method.isFinal()), resolveVisibilityFromPsiModifiers(method.getPsiMethod()), /*isInline = */ false ); @@ -1845,6 +1836,20 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes } } + private static Modality resolveModality(PsiMemberWrapper memberWrapper, boolean isFinal) { + if (memberWrapper instanceof PsiMethodWrapper) { + PsiMethodWrapper method = (PsiMethodWrapper) memberWrapper; + if (method.getJetMethod().flags().get(JvmStdlibNames.JET_METHOD_FLAG_FORCE_OPEN_BIT)) { + return Modality.OPEN; + } + if (method.getJetMethod().flags().get(JvmStdlibNames.JET_METHOD_FLAG_FORCE_FINAL_BIT)) { + return Modality.FINAL; + } + } + + return Modality.convertFromFlags(memberWrapper.isAbstract(), !isFinal); + } + private static Visibility resolveVisibilityFromPsiModifiers(PsiModifierListOwner modifierListOwner) { return modifierListOwner.hasModifierProperty(PsiModifier.PUBLIC) ? Visibilities.PUBLIC : (modifierListOwner.hasModifierProperty(PsiModifier.PRIVATE) ? Visibilities.PRIVATE : diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmStdlibNames.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmStdlibNames.java index c3a91cac4ec..b3386bff8ca 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmStdlibNames.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmStdlibNames.java @@ -49,8 +49,10 @@ public class JvmStdlibNames { public static final String JET_METHOD_PROPERTY_TYPE_FIELD = "propertyType"; public static final int JET_METHOD_FLAGS_DEFAULT_VALUE = 0; - public static final int JET_METHOD_FLAGS_BITS = 1; + public static final int JET_METHOD_FLAGS_BITS = 3; public static final int JET_METHOD_FLAG_PROPERTY_BIT = 0; + public static final int JET_METHOD_FLAG_FORCE_OPEN_BIT = 1; + public static final int JET_METHOD_FLAG_FORCE_FINAL_BIT = 2; public static final JvmClassName JET_CONSTRUCTOR = JvmClassName.byFqNameWithoutInnerClasses("jet.runtime.typeinfo.JetConstructor"); diff --git a/compiler/testData/readKotlinBinaryClass/classFun/TraitFinalFun.kt b/compiler/testData/readKotlinBinaryClass/classFun/TraitFinalFun.kt new file mode 100644 index 00000000000..d906faa3f09 --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/classFun/TraitFinalFun.kt @@ -0,0 +1,7 @@ +// KT-2228 + +package test + +trait A { + final fun f(): String = "test" +} \ No newline at end of file diff --git a/compiler/testData/readKotlinBinaryClass/classFun/TraitFinalFun.txt b/compiler/testData/readKotlinBinaryClass/classFun/TraitFinalFun.txt new file mode 100644 index 00000000000..f1bb74230bc --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/classFun/TraitFinalFun.txt @@ -0,0 +1,5 @@ +namespace test + +abstract trait test.A : jet.Any { + final fun f(): jet.String +} diff --git a/compiler/testData/readKotlinBinaryClass/classFun/TraitOpenFun.kt b/compiler/testData/readKotlinBinaryClass/classFun/TraitOpenFun.kt new file mode 100644 index 00000000000..719deb93964 --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/classFun/TraitOpenFun.kt @@ -0,0 +1,7 @@ +// KT-2228 + +package test + +trait A { + fun f(): String = "test" +} \ No newline at end of file diff --git a/compiler/testData/readKotlinBinaryClass/classFun/TraitOpenFun.txt b/compiler/testData/readKotlinBinaryClass/classFun/TraitOpenFun.txt new file mode 100644 index 00000000000..92776e23a73 --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/classFun/TraitOpenFun.txt @@ -0,0 +1,5 @@ +namespace test + +abstract trait test.A : jet.Any { + open fun f(): jet.String +} diff --git a/compiler/testData/readKotlinBinaryClass/prop/TraitFinalVar.kt b/compiler/testData/readKotlinBinaryClass/prop/TraitFinalVar.kt new file mode 100644 index 00000000000..82b6fac1f6e --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/prop/TraitFinalVar.kt @@ -0,0 +1,11 @@ +// KT-2228 + +package test + +trait A { + var v: String + get() = "test" + set(value) { + throw UnsupportedOperationException() + } +} \ No newline at end of file diff --git a/compiler/testData/readKotlinBinaryClass/prop/TraitFinalVar.txt b/compiler/testData/readKotlinBinaryClass/prop/TraitFinalVar.txt new file mode 100644 index 00000000000..5c1235faa28 --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/prop/TraitFinalVar.txt @@ -0,0 +1,5 @@ +namespace test + +abstract trait test.A : jet.Any { + open var v: jet.String +} diff --git a/compiler/testData/readKotlinBinaryClass/prop/TraitOpenVal.kt b/compiler/testData/readKotlinBinaryClass/prop/TraitOpenVal.kt new file mode 100644 index 00000000000..ec6bf93ad2e --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/prop/TraitOpenVal.kt @@ -0,0 +1,8 @@ +// KT-2228 + +package test + +trait A { + val v: String + get() = "test" +} \ No newline at end of file diff --git a/compiler/testData/readKotlinBinaryClass/prop/TraitOpenVal.txt b/compiler/testData/readKotlinBinaryClass/prop/TraitOpenVal.txt new file mode 100644 index 00000000000..4d934ee7346 --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/prop/TraitOpenVal.txt @@ -0,0 +1,5 @@ +namespace test + +abstract trait test.A : jet.Any { + open val v: jet.String +}