From b7789da3b9c501781b911ccad6c846da6317e4d8 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 16 Oct 2013 21:49:27 +0400 Subject: [PATCH] Load annotations on properties declared in traits --- .../jet/codegen/ClassBodyCodegen.java | 8 ++-- .../jet/codegen/FunctionCodegen.java | 2 +- .../codegen/ImplementationBodyCodegen.java | 6 --- .../jet/codegen/JavaSerializerExtension.java | 8 ++-- .../org/jetbrains/jet/codegen/MemberMap.java | 16 +++---- .../jet/codegen/PropertyCodegen.java | 15 ++++-- .../jet/codegen/TraitImplBodyCodegen.java | 12 +++++ .../NestedTrait.kt | 9 ++++ .../NestedTrait.txt | 14 ++++++ .../propertiesWithoutBackingFields/Trait.kt | 7 +++ .../propertiesWithoutBackingFields/Trait.txt | 10 ++++ .../TraitClassObject.kt | 10 ++++ .../TraitClassObject.txt | 14 ++++++ .../LoadCompiledKotlinTestGenerated.java | 15 ++++++ ...esolveNamespaceComparingTestGenerated.java | 15 ++++++ .../lang/resolve/java/JvmAnnotationNames.java | 3 ++ .../AnnotationDescriptorDeserializer.java | 47 ++++++++++++------- ...eadKotlinClassHeaderAnnotationVisitor.java | 9 ++-- .../kotlin/header/TraitImplClassHeader.java | 23 +++++++++ .../src/java_descriptors.proto | 8 +++- .../serialization/JavaProtoBuf.java | 6 +-- 21 files changed, 204 insertions(+), 53 deletions(-) create mode 100644 compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/NestedTrait.kt create mode 100644 compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/NestedTrait.txt create mode 100644 compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/Trait.kt create mode 100644 compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/Trait.txt create mode 100644 compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/TraitClassObject.kt create mode 100644 compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/TraitClassObject.txt create mode 100644 core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/header/TraitImplClassHeader.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java index a1454300aab..f0f7bb7d2a5 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java @@ -35,6 +35,7 @@ import java.util.List; import static org.jetbrains.asm4.Opcodes.ACC_STATIC; import static org.jetbrains.asm4.Opcodes.RETURN; import static org.jetbrains.jet.codegen.binding.CodegenBinding.enumEntryNeedSubclass; +import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isTopLevelOrInnerClass; public abstract class ClassBodyCodegen extends MemberCodegen { protected final JetClassOrObject myClass; @@ -71,13 +72,14 @@ public abstract class ClassBodyCodegen extends MemberCodegen { generateStaticInitializer(); - generateKotlinAnnotation(); + if (state.getClassBuilderMode() == ClassBuilderMode.FULL && isTopLevelOrInnerClass(descriptor)) { + generateKotlinAnnotation(); + } } protected abstract void generateDeclaration(); - protected void generateKotlinAnnotation() { - } + protected abstract void generateKotlinAnnotation(); protected abstract void generateSyntheticParts(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 8fc7e2d806c..4dd9a03a06c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -111,7 +111,7 @@ public class FunctionCodegen extends ParentCodegenAwareImpl { if (owner instanceof NamespaceFacadeContext) { Type ownerType = ((NamespaceFacadeContext) owner).getDelegateToClassType(); - v.getMemberMap().recordSrcClassNameForCallable(functionDescriptor, shortNameByAsmType(ownerType)); + v.getMemberMap().recordImplClassNameForCallable(functionDescriptor, shortNameByAsmType(ownerType)); } else { v.getMemberMap().recordMethodOfDescriptor(functionDescriptor, asmMethod); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index d9e832368a3..e2d70050bb6 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -213,12 +213,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { @Override protected void generateKotlinAnnotation() { - if (state.getClassBuilderMode() != ClassBuilderMode.FULL) { - return; - } - - if (!isTopLevelOrInnerClass(descriptor)) return; - DescriptorSerializer serializer = new DescriptorSerializer(new JavaSerializerExtension(v.getMemberMap())); ProtoBuf.Class classProto = serializer.classProto(descriptor).build(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JavaSerializerExtension.java b/compiler/backend/src/org/jetbrains/jet/codegen/JavaSerializerExtension.java index 428098941aa..754c7e44681 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JavaSerializerExtension.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JavaSerializerExtension.java @@ -45,7 +45,7 @@ public class JavaSerializerExtension extends SerializerExtension { @NotNull NameTable nameTable ) { saveSignature(callable, proto, nameTable); - saveSrcClassName(callable, proto, nameTable); + saveImplClassName(callable, proto, nameTable); } private void saveSignature( @@ -91,14 +91,14 @@ public class JavaSerializerExtension extends SerializerExtension { } } - private void saveSrcClassName( + private void saveImplClassName( @NotNull CallableMemberDescriptor callable, @NotNull ProtoBuf.Callable.Builder proto, @NotNull NameTable nameTable ) { - String name = memberMap.getSrcClassNameOfCallable(callable); + String name = memberMap.getImplClassNameOfCallable(callable); if (name != null) { - proto.setExtension(JavaProtoBuf.srcClassName, nameTable.getSimpleNameIndex(Name.identifier(name))); + proto.setExtension(JavaProtoBuf.implClassName, nameTable.getSimpleNameIndex(Name.identifier(name))); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/MemberMap.java b/compiler/backend/src/org/jetbrains/jet/codegen/MemberMap.java index 6b85c0d3172..6914750cb2a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/MemberMap.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/MemberMap.java @@ -31,7 +31,7 @@ public final class MemberMap { private final Map methodForFunction = new HashMap(); private final Map> fieldForProperty = new HashMap>(); private final Map syntheticMethodForProperty = new HashMap(); - private final Map srcClassNameForCallable = new HashMap(); + private final Map implClassNameForCallable = new HashMap(); private final Set staticFieldInOuterClass = new HashSet(); @NotNull @@ -50,8 +50,8 @@ public final class MemberMap { result.recordSyntheticMethodOfProperty(entry.getKey(), entry.getValue()); } - for (Map.Entry entry : map.srcClassNameForCallable.entrySet()) { - result.recordSrcClassNameForCallable(entry.getKey(), entry.getValue()); + for (Map.Entry entry : map.implClassNameForCallable.entrySet()) { + result.recordImplClassNameForCallable(entry.getKey(), entry.getValue()); } for (PropertyDescriptor property : map.staticFieldInOuterClass) { @@ -77,8 +77,8 @@ public final class MemberMap { assert old == null : "Duplicate synthetic method for property: " + descriptor + "; " + old; } - public void recordSrcClassNameForCallable(@NotNull CallableMemberDescriptor descriptor, @NotNull String name) { - String old = srcClassNameForCallable.put(descriptor, name); + public void recordImplClassNameForCallable(@NotNull CallableMemberDescriptor descriptor, @NotNull String name) { + String old = implClassNameForCallable.put(descriptor, name); assert old == null : "Duplicate src class name for callable: " + descriptor + "; " + old; } @@ -103,8 +103,8 @@ public final class MemberMap { } @Nullable - public String getSrcClassNameOfCallable(@NotNull CallableMemberDescriptor descriptor) { - return srcClassNameForCallable.get(descriptor); + public String getImplClassNameOfCallable(@NotNull CallableMemberDescriptor descriptor) { + return implClassNameForCallable.get(descriptor); } public boolean isStaticFieldInOuterClass(@NotNull PropertyDescriptor property) { @@ -116,6 +116,6 @@ public final class MemberMap { return "Functions: " + methodForFunction.size() + ", fields: " + fieldForProperty.size() + ", synthetic methods: " + syntheticMethodForProperty.size() + - ", src class names: " + srcClassNameForCallable.size(); + ", impl class names: " + implClassNameForCallable.size(); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java index a44f0b9bd1a..35dba84e684 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java @@ -92,7 +92,7 @@ public class PropertyCodegen extends GenerationStateAware { if (context instanceof NamespaceFacadeContext) { Type ownerType = ((NamespaceFacadeContext) context).getDelegateToClassType(); - v.getMemberMap().recordSrcClassNameForCallable(propertyDescriptor, shortNameByAsmType(ownerType)); + v.getMemberMap().recordImplClassNameForCallable(propertyDescriptor, shortNameByAsmType(ownerType)); } else if (kind != OwnerKind.TRAIT_IMPL) { generateBackingField(p, propertyDescriptor); @@ -142,11 +142,16 @@ public class PropertyCodegen extends GenerationStateAware { AnnotationCodegen.forField(fieldVisitor, typeMapper).genAnnotations(propertyDescriptor); } else if (!propertyDescriptor.getAnnotations().isEmpty()) { - if (!isTrait(context.getContextDescriptor())) { - Method method = getSyntheticMethodSignature(typeMapper, propertyDescriptor); - generateSyntheticMethodForAnnotatedProperty(v, typeMapper, propertyDescriptor, method); - v.getMemberMap().recordSyntheticMethodOfProperty(propertyDescriptor, method); + Method method = getSyntheticMethodSignature(typeMapper, propertyDescriptor); + DeclarationDescriptor descriptor = context.getContextDescriptor(); + if (isTrait(descriptor)) { + Type tImplType = typeMapper.mapTraitImpl((ClassDescriptor) descriptor); + v.getMemberMap().recordImplClassNameForCallable(propertyDescriptor, shortNameByAsmType(tImplType)); } + else { + generateSyntheticMethodForAnnotatedProperty(v, typeMapper, propertyDescriptor, method); + } + v.getMemberMap().recordSyntheticMethodOfProperty(propertyDescriptor, method); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java index f8423832fe3..899c9c1db9c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java @@ -18,6 +18,7 @@ package org.jetbrains.jet.codegen; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.asm4.AnnotationVisitor; import org.jetbrains.asm4.commons.Method; import org.jetbrains.jet.codegen.context.ClassContext; import org.jetbrains.jet.codegen.state.GenerationState; @@ -27,8 +28,11 @@ import org.jetbrains.jet.lang.psi.JetClassOrObject; import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetProperty; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.java.JvmAbi; +import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames; import static org.jetbrains.asm4.Opcodes.*; +import static org.jetbrains.jet.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses; public class TraitImplBodyCodegen extends ClassBodyCodegen { @@ -54,6 +58,14 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen { v.visitSource(myClass.getContainingFile().getName(), null); } + @Override + protected void generateKotlinAnnotation() { + AnnotationVisitor av = + v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_TRAIT_IMPL), true); + av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION); + av.visitEnd(); + } + @Override protected void generateSyntheticParts() { generateSyntheticMethodsForAnnotatedProperties(); diff --git a/compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/NestedTrait.kt b/compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/NestedTrait.kt new file mode 100644 index 00000000000..4b3be4fdcc7 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/NestedTrait.kt @@ -0,0 +1,9 @@ +package test + +annotation class Anno + +class Class { + trait Trait { + [Anno] val property: Int + } +} diff --git a/compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/NestedTrait.txt b/compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/NestedTrait.txt new file mode 100644 index 00000000000..e5c0ca78764 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/NestedTrait.txt @@ -0,0 +1,14 @@ +package test + +internal final annotation class Anno : jet.Annotation { + /*primary*/ public constructor Anno() +} + +internal final class Class { + /*primary*/ public constructor Class() + + internal trait Trait { + test.Anno() internal abstract val property: jet.Int + internal abstract fun (): jet.Int + } +} diff --git a/compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/Trait.kt b/compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/Trait.kt new file mode 100644 index 00000000000..0454006a9cd --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/Trait.kt @@ -0,0 +1,7 @@ +package test + +annotation class Anno + +trait Trait { + [Anno] val property: Int +} diff --git a/compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/Trait.txt b/compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/Trait.txt new file mode 100644 index 00000000000..ce135f1b0d7 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/Trait.txt @@ -0,0 +1,10 @@ +package test + +internal final annotation class Anno : jet.Annotation { + /*primary*/ public constructor Anno() +} + +internal trait Trait { + test.Anno() internal abstract val property: jet.Int + internal abstract fun (): jet.Int +} diff --git a/compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/TraitClassObject.kt b/compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/TraitClassObject.kt new file mode 100644 index 00000000000..4cdc0a48063 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/TraitClassObject.kt @@ -0,0 +1,10 @@ +package test + +annotation class Anno + +trait Trait { + class object { + [Anno] val property: Int + get() = 42 + } +} diff --git a/compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/TraitClassObject.txt b/compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/TraitClassObject.txt new file mode 100644 index 00000000000..54cb5abcbe1 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/TraitClassObject.txt @@ -0,0 +1,14 @@ +package test + +internal final annotation class Anno : jet.Annotation { + /*primary*/ public constructor Anno() +} + +internal trait Trait { + + internal class object { + /*primary*/ private constructor () + test.Anno() internal final val property: jet.Int + internal final fun (): jet.Int + } +} diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java index d1d2d893d00..90b7246382a 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java @@ -209,11 +209,26 @@ public class LoadCompiledKotlinTestGenerated extends AbstractLoadCompiledKotlinT doTestWithAccessors("compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/ExtensionsWithSameNamePackage.kt"); } + @TestMetadata("NestedTrait.kt") + public void testNestedTrait() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/NestedTrait.kt"); + } + @TestMetadata("TopLevel.kt") public void testTopLevel() throws Exception { doTestWithAccessors("compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/TopLevel.kt"); } + @TestMetadata("Trait.kt") + public void testTrait() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/Trait.kt"); + } + + @TestMetadata("TraitClassObject.kt") + public void testTraitClassObject() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/TraitClassObject.kt"); + } + } public static Test innerSuite() { diff --git a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java index 5852fbbf7b3..8b451f091c2 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java @@ -211,11 +211,26 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/ExtensionsWithSameNamePackage.kt"); } + @TestMetadata("NestedTrait.kt") + public void testNestedTrait() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/NestedTrait.kt"); + } + @TestMetadata("TopLevel.kt") public void testTopLevel() throws Exception { doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/TopLevel.kt"); } + @TestMetadata("Trait.kt") + public void testTrait() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/Trait.kt"); + } + + @TestMetadata("TraitClassObject.kt") + public void testTraitClassObject() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/propertiesWithoutBackingFields/TraitClassObject.kt"); + } + } public static Test innerSuite() { diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/JvmAnnotationNames.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/JvmAnnotationNames.java index 291324e39c0..8445ee4cb59 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/JvmAnnotationNames.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/JvmAnnotationNames.java @@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.resolve.java; import jet.KotlinClass; import jet.KotlinPackage; import jet.KotlinPackageFragment; +import jet.KotlinTraitImpl; import org.jetbrains.jet.lang.resolve.name.FqName; import static org.jetbrains.jet.lang.resolve.java.resolver.DescriptorResolverUtils.fqNameByClass; @@ -30,6 +31,8 @@ public final class JvmAnnotationNames { public static final FqName KOTLIN_PACKAGE_FRAGMENT = fqNameByClass(KotlinPackageFragment.class); + public static final FqName KOTLIN_TRAIT_IMPL = fqNameByClass(KotlinTraitImpl.class); + public static final String ABI_VERSION_FIELD_NAME = "abiVersion"; public static final String DATA_FIELD_NAME = "data"; diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java index aad9d30cf54..bebcfdfb586 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java @@ -47,6 +47,8 @@ import javax.inject.Inject; import java.io.IOException; import java.util.*; +import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject; +import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isTrait; import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.IGNORE_KOTLIN_SOURCES; import static org.jetbrains.jet.lang.resolve.kotlin.DeserializedResolverUtils.kotlinFqNameToJavaFqName; import static org.jetbrains.jet.lang.resolve.kotlin.DeserializedResolverUtils.naiveKotlinFqName; @@ -231,7 +233,7 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer MemberSignature signature = getCallableSignature(proto, nameResolver, kind); if (signature == null) return Collections.emptyList(); - KotlinJvmBinaryClass kotlinClass = findClassWithMemberAnnotations(container, proto, nameResolver); + KotlinJvmBinaryClass kotlinClass = findClassWithMemberAnnotations(container, proto, nameResolver, kind); if (kotlinClass == null) { errorReporter.reportAnnotationLoadingError("Kotlin class for loading member annotations is not found: " + container, null); return Collections.emptyList(); @@ -245,33 +247,42 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer private KotlinJvmBinaryClass findClassWithMemberAnnotations( @NotNull ClassOrNamespaceDescriptor container, @NotNull ProtoBuf.Callable proto, - @NotNull NameResolver nameResolver + @NotNull NameResolver nameResolver, + @NotNull AnnotatedCallableKind kind ) { if (container instanceof NamespaceDescriptor) { - Name name = loadSrcClassName(proto, nameResolver); - if (name != null) { - return kotlinClassFinder.find(getSrcClassFqName((NamespaceDescriptor) container, name)); + return loadPackageFragmentClassFqName((NamespaceDescriptor) container, proto, nameResolver); + } + else if (isClassObject(container) && isStaticFieldInOuter(proto)) { + // Backing fields of properties of a class object are generated in the outer class + return findKotlinClassByDescriptor((ClassOrNamespaceDescriptor) container.getContainingDeclaration()); + } + else if (isTrait(container) && kind == AnnotatedCallableKind.PROPERTY) { + NamespaceDescriptor containingPackage = DescriptorUtils.getParentOfType(container, NamespaceDescriptor.class); + assert containingPackage != null : "Trait must have a namespace among his parents: " + container; + + if (proto.hasExtension(JavaProtoBuf.implClassName)) { + Name tImplName = nameResolver.getName(proto.getExtension(JavaProtoBuf.implClassName)); + return kotlinClassFinder.find(containingPackage.getFqName().child(tImplName)); } return null; } - else if (container instanceof ClassDescriptor && ((ClassDescriptor) container).getKind() == ClassKind.CLASS_OBJECT) { - // Backing fields of properties of a class object are generated in the outer class - if (isStaticFieldInOuter(proto)) { - return findKotlinClassByDescriptor((ClassOrNamespaceDescriptor) container.getContainingDeclaration()); - } - } return findKotlinClassByDescriptor(container); } - @NotNull - private static FqName getSrcClassFqName(@NotNull NamespaceDescriptor container, @NotNull Name name) { - return PackageClassUtils.getPackageClassFqName(DescriptorUtils.getFQName(container).toSafe()).parent().child(name); - } - @Nullable - private static Name loadSrcClassName(@NotNull ProtoBuf.Callable proto, @NotNull NameResolver nameResolver) { - return proto.hasExtension(JavaProtoBuf.srcClassName) ? nameResolver.getName(proto.getExtension(JavaProtoBuf.srcClassName)) : null; + private KotlinJvmBinaryClass loadPackageFragmentClassFqName( + @NotNull NamespaceDescriptor container, + @NotNull ProtoBuf.Callable proto, + @NotNull NameResolver nameResolver + ) { + if (proto.hasExtension(JavaProtoBuf.implClassName)) { + Name name = nameResolver.getName(proto.getExtension(JavaProtoBuf.implClassName)); + FqName fqName = PackageClassUtils.getPackageClassFqName(container.getFqName()).parent().child(name); + return kotlinClassFinder.find(fqName); + } + return null; } private static boolean isStaticFieldInOuter(@NotNull ProtoBuf.Callable proto) { diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java index b2ef4813e9e..4c59ea7f008 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java @@ -38,6 +38,7 @@ import static org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass.Annotat CLASS(JvmAnnotationNames.KOTLIN_CLASS), PACKAGE(JvmAnnotationNames.KOTLIN_PACKAGE), PACKAGE_FRAGMENT(JvmAnnotationNames.KOTLIN_PACKAGE_FRAGMENT), + TRAIT_IMPL(JvmAnnotationNames.KOTLIN_TRAIT_IMPL), OLD_CLASS(JvmAnnotationNames.OLD_JET_CLASS_ANNOTATION), OLD_PACKAGE(JvmAnnotationNames.OLD_JET_PACKAGE_CLASS_ANNOTATION); @@ -92,6 +93,8 @@ import static org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass.Annotat return serializedDataHeader(SerializedDataHeader.Kind.PACKAGE); case PACKAGE_FRAGMENT: return new PackageFragmentClassHeader(version); + case TRAIT_IMPL: + return new TraitImplClassHeader(version); default: throw new UnsupportedOperationException("Unknown compatible HeaderType: " + foundType); } @@ -123,8 +126,8 @@ import static org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass.Annotat if (newType == HeaderType.CLASS || newType == HeaderType.PACKAGE) { return kotlinClassOrPackageVisitor(annotationClassName); } - else if (newType == HeaderType.PACKAGE_FRAGMENT) { - return kotlinPackageFragmentVisitor(annotationClassName); + else if (newType == HeaderType.PACKAGE_FRAGMENT || newType == HeaderType.TRAIT_IMPL) { + return annotationWithAbiVersionVisitor(annotationClassName); } return null; @@ -198,7 +201,7 @@ import static org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass.Annotat } @NotNull - private AnnotationArgumentVisitor kotlinPackageFragmentVisitor(@NotNull final JvmClassName annotationClassName) { + private AnnotationArgumentVisitor annotationWithAbiVersionVisitor(@NotNull final JvmClassName annotationClassName) { return new AnnotationArgumentVisitor() { @Override public void visit(@Nullable Name name, @Nullable Object value) { diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/header/TraitImplClassHeader.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/header/TraitImplClassHeader.java new file mode 100644 index 00000000000..5fa4eb7d9d7 --- /dev/null +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/header/TraitImplClassHeader.java @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.resolve.kotlin.header; + +/* package */ class TraitImplClassHeader extends KotlinClassHeader { + protected TraitImplClassHeader(int version) { + super(version); + } +} diff --git a/core/serialization.java/src/java_descriptors.proto b/core/serialization.java/src/java_descriptors.proto index 40de1bf98cd..1988f103cdb 100644 --- a/core/serialization.java/src/java_descriptors.proto +++ b/core/serialization.java/src/java_descriptors.proto @@ -74,6 +74,10 @@ extend Callable { optional JavaPropertySignature property_signature = 101; - // For top-level callables, short name of "...Package$src$..." class with the callable's body and annotations - optional int32 src_class_name = 102; + // Package-less name of the class with the callable's body and annotations, if it differs from the class it's serialized into. + // E.g. for a class "A/B/C$D" this would be "C$D". + // This is needed to find the class to load annotations from in the following cases: + // 1) annotations on top-level members are written to compiled package fragment classes + // 2) annotations on properties in traits are written to TImpl classes + optional int32 impl_class_name = 102; } diff --git a/core/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBuf.java b/core/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBuf.java index b356eff5890..245b9b7b9eb 100644 --- a/core/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBuf.java +++ b/core/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBuf.java @@ -9,7 +9,7 @@ public final class JavaProtoBuf { com.google.protobuf.ExtensionRegistryLite registry) { registry.add(org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.methodSignature); registry.add(org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.propertySignature); - registry.add(org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.srcClassName); + registry.add(org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.implClassName); } public interface JavaTypeOrBuilder extends com.google.protobuf.MessageLiteOrBuilder { @@ -2825,14 +2825,14 @@ public final class JavaProtoBuf { null, 101, com.google.protobuf.WireFormat.FieldType.MESSAGE); - public static final int SRC_CLASS_NAME_FIELD_NUMBER = 102; + public static final int IMPL_CLASS_NAME_FIELD_NUMBER = 102; /** * extend .org.jetbrains.jet.descriptors.serialization.Callable { ... } */ public static final com.google.protobuf.GeneratedMessageLite.GeneratedExtension< org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable, - java.lang.Integer> srcClassName = com.google.protobuf.GeneratedMessageLite + java.lang.Integer> implClassName = com.google.protobuf.GeneratedMessageLite .newSingularGeneratedExtension( org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable.getDefaultInstance(), 0,