diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 093f85a0292..0ad9efed524 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -46,6 +46,7 @@ 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.java.kt.DescriptorKindUtils; +import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; import java.util.*; @@ -112,7 +113,15 @@ public class FunctionCodegen extends GenerationStateAware { asmMethod.getDescriptor(), jvmSignature.getGenericsSignature(), null); - v.getMemberMap().recordMethodOfDescriptor(functionDescriptor, asmMethod); + + OwnerKind contextKind = owner.getContextKind(); + if (contextKind instanceof OwnerKind.StaticDelegateKind) { + FqName fqName = ((OwnerKind.StaticDelegateKind) contextKind).getOwnerClass().getFqName(); + v.getMemberMap().recordSrcClassNameForCallable(functionDescriptor, fqName.shortName()); + } + else { + v.getMemberMap().recordMethodOfDescriptor(functionDescriptor, asmMethod); + } AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor); if (state.getClassBuilderMode() == ClassBuilderMode.SIGNATURES) return; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JavaSerializerExtension.java b/compiler/backend/src/org/jetbrains/jet/codegen/JavaSerializerExtension.java index c966b2adcf2..ff3b77704dc 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JavaSerializerExtension.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JavaSerializerExtension.java @@ -25,6 +25,7 @@ import org.jetbrains.jet.descriptors.serialization.NameTable; import org.jetbrains.jet.descriptors.serialization.ProtoBuf; import org.jetbrains.jet.descriptors.serialization.SerializerExtension; import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.resolve.name.Name; public class JavaSerializerExtension extends SerializerExtension { private final MemberMap memberMap; @@ -38,9 +39,18 @@ public class JavaSerializerExtension extends SerializerExtension { @NotNull CallableMemberDescriptor callable, @NotNull ProtoBuf.Callable.Builder proto, @NotNull NameTable nameTable + ) { + saveSignature(callable, proto, nameTable); + saveSrcClassName(callable, proto, nameTable); + } + + private void saveSignature( + @NotNull CallableMemberDescriptor callable, + @NotNull ProtoBuf.Callable.Builder proto, + @NotNull NameTable nameTable ) { if (callable instanceof FunctionDescriptor) { - Method method = memberMap.getMethodOfDescriptor(callable); + Method method = memberMap.getMethodOfDescriptor((FunctionDescriptor) callable); if (method != null) { JavaProtoBufUtil.saveMethodSignature(proto, method, nameTable); } @@ -71,4 +81,15 @@ public class JavaSerializerExtension extends SerializerExtension { JavaProtoBufUtil.savePropertySignature(proto, fieldType, fieldName, syntheticMethodName, getterMethod, setterMethod, nameTable); } } + + private void saveSrcClassName( + @NotNull CallableMemberDescriptor callable, + @NotNull ProtoBuf.Callable.Builder proto, + @NotNull NameTable nameTable + ) { + Name name = memberMap.getSrcClassNameOfCallable(callable); + if (name != null) { + JavaProtoBufUtil.saveSrcClassName(proto, name, nameTable); + } + } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/MemberMap.java b/compiler/backend/src/org/jetbrains/jet/codegen/MemberMap.java index 7fa37b431d7..65f2452804b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/MemberMap.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/MemberMap.java @@ -22,22 +22,25 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.asm4.Type; import org.jetbrains.asm4.commons.Method; import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; +import org.jetbrains.jet.lang.resolve.name.Name; import java.util.Collection; import java.util.HashMap; import java.util.Map; public final class MemberMap { - private final Map methodForFunction = new HashMap(); + private final Map methodForFunction = new HashMap(); private final Map> fieldForProperty = new HashMap>(); private final Map syntheticMethodNameForProperty = new HashMap(); + private final Map srcClassNameForCallable = new HashMap(); @NotNull public static MemberMap union(@NotNull Collection maps) { MemberMap result = new MemberMap(); for (MemberMap map : maps) { - for (Map.Entry entry : map.methodForFunction.entrySet()) { + for (Map.Entry entry : map.methodForFunction.entrySet()) { result.recordMethodOfDescriptor(entry.getKey(), entry.getValue()); } @@ -48,12 +51,16 @@ public final class MemberMap { for (Map.Entry entry : map.syntheticMethodNameForProperty.entrySet()) { result.recordSyntheticMethodNameOfProperty(entry.getKey(), entry.getValue()); } + + for (Map.Entry entry : map.srcClassNameForCallable.entrySet()) { + result.recordSrcClassNameForCallable(entry.getKey(), entry.getValue()); + } } return result; } - public void recordMethodOfDescriptor(@NotNull CallableMemberDescriptor descriptor, @NotNull Method method) { + public void recordMethodOfDescriptor(@NotNull FunctionDescriptor descriptor, @NotNull Method method) { Method old = methodForFunction.put(descriptor, method); assert old == null : "Duplicate method for callable member: " + descriptor + "; " + old; } @@ -68,8 +75,13 @@ public final class MemberMap { assert old == null : "Duplicate synthetic method for property: " + descriptor + "; " + old; } + public void recordSrcClassNameForCallable(@NotNull CallableMemberDescriptor descriptor, @NotNull Name name) { + Name old = srcClassNameForCallable.put(descriptor, name); + assert old == null : "Duplicate src class name for callable: " + descriptor + "; " + old; + } + @Nullable - public Method getMethodOfDescriptor(@NotNull CallableMemberDescriptor descriptor) { + public Method getMethodOfDescriptor(@NotNull FunctionDescriptor descriptor) { return methodForFunction.get(descriptor); } @@ -83,10 +95,16 @@ public final class MemberMap { return syntheticMethodNameForProperty.get(descriptor); } + @Nullable + public Name getSrcClassNameOfCallable(@NotNull CallableMemberDescriptor descriptor) { + return srcClassNameForCallable.get(descriptor); + } + @Override public String toString() { return "Functions: " + methodForFunction.size() + ", fields: " + fieldForProperty.size() + - ", synthetic methods: " + syntheticMethodNameForProperty.size(); + ", synthetic methods: " + syntheticMethodNameForProperty.size() + + ", src class names: " + srcClassNameForCallable.size(); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index 4a3919d55ea..9ca0a52c127 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -99,14 +99,17 @@ public class NamespaceCodegen extends MemberCodegen { } public void generate(@NotNull CompilationErrorHandler errorHandler) { + List namespaceMembers = new ArrayList(files.size() + 1); + if (shouldGenerateNSClass(files)) { - AnnotationVisitor packageClassAnnotation = - v.getClassBuilder().newAnnotation(JvmStdlibNames.JET_PACKAGE_CLASS.getDescriptor(), true); + ClassBuilder cv = v.getClassBuilder(); + + AnnotationVisitor packageClassAnnotation = cv.newAnnotation(JvmStdlibNames.JET_PACKAGE_CLASS.getDescriptor(), true); packageClassAnnotation.visit(JvmStdlibNames.ABI_VERSION_NAME, JvmAbi.VERSION); packageClassAnnotation.visitEnd(); - } - List namespaceMembers = new ArrayList(); + namespaceMembers.add(cv.getMemberMap()); + } for (JetFile file : files) { try { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java index c5d10137b7b..e147ce9be3c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java @@ -42,6 +42,7 @@ import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames; import org.jetbrains.jet.lang.resolve.java.kt.DescriptorKindUtils; +import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.JetType; @@ -88,9 +89,14 @@ public class PropertyCodegen extends GenerationStateAware { assert kind instanceof OwnerKind.StaticDelegateKind || kind == OwnerKind.NAMESPACE || kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.TRAIT_IMPL : "Generating property with a wrong kind (" + kind + "): " + propertyDescriptor; - if (kind != OwnerKind.TRAIT_IMPL && !(kind instanceof OwnerKind.StaticDelegateKind)) { + if (kind instanceof OwnerKind.StaticDelegateKind) { + FqName fqName = ((OwnerKind.StaticDelegateKind) kind).getOwnerClass().getFqName(); + v.getMemberMap().recordSrcClassNameForCallable(propertyDescriptor, fqName.shortName()); + } + else if (kind != OwnerKind.TRAIT_IMPL) { generateBackingField(p, propertyDescriptor); } + generateGetter(p, propertyDescriptor, p.getGetter()); generateSetter(p, propertyDescriptor, p.getSetter()); diff --git a/compiler/frontend.java/serialization.java/src/java_descriptors.proto b/compiler/frontend.java/serialization.java/src/java_descriptors.proto index d209f14d4b4..569d01f9bac 100644 --- a/compiler/frontend.java/serialization.java/src/java_descriptors.proto +++ b/compiler/frontend.java/serialization.java/src/java_descriptors.proto @@ -69,4 +69,7 @@ extend Callable { optional JavaMethodSignature method_signature = 100; 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; } diff --git a/compiler/frontend.java/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBuf.java b/compiler/frontend.java/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBuf.java index a75b8a8d717..44fcdc57522 100644 --- a/compiler/frontend.java/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBuf.java +++ b/compiler/frontend.java/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBuf.java @@ -9,6 +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); } public interface JavaTypeOrBuilder extends com.google.protobuf.MessageLiteOrBuilder { @@ -1979,6 +1980,18 @@ 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 + com.google.protobuf.GeneratedMessageLite.GeneratedExtension< + org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable, + java.lang.Integer> srcClassName = com.google.protobuf.GeneratedMessageLite + .newSingularGeneratedExtension( + org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable.getDefaultInstance(), + 0, + null, + null, + 102, + com.google.protobuf.WireFormat.FieldType.INT32); static { } diff --git a/compiler/frontend.java/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBufUtil.java b/compiler/frontend.java/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBufUtil.java index 56f90c3bf14..ba2c12b8310 100644 --- a/compiler/frontend.java/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBufUtil.java +++ b/compiler/frontend.java/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBufUtil.java @@ -105,6 +105,12 @@ public class JavaProtoBufUtil { } } + @Nullable + public static Name loadSrcClassName(@NotNull ProtoBuf.Callable proto, @NotNull NameResolver nameResolver) { + if (!proto.hasExtension(JavaProtoBuf.srcClassName)) return null; + return nameResolver.getName(proto.getExtension(JavaProtoBuf.srcClassName)); + } + public static void saveMethodSignature(@NotNull ProtoBuf.Callable.Builder proto, @NotNull Method method, @NotNull NameTable nameTable) { proto.setExtension(JavaProtoBuf.methodSignature, new Serializer(nameTable).methodSignature(method)); } @@ -122,6 +128,14 @@ public class JavaProtoBufUtil { new Serializer(nameTable).propertySignature(fieldType, fieldName, syntheticMethodName, getter, setter)); } + public static void saveSrcClassName( + @NotNull ProtoBuf.Callable.Builder proto, + @NotNull Name name, + @NotNull NameTable nameTable + ) { + proto.setExtension(JavaProtoBuf.srcClassName, nameTable.getSimpleNameIndex(name)); + } + private static class Serializer { private final NameTable nameTable; diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/AnnotationDescriptorDeserializer.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/AnnotationDescriptorDeserializer.java index dd74aa0369f..0bf92913b36 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/AnnotationDescriptorDeserializer.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/AnnotationDescriptorDeserializer.java @@ -184,7 +184,7 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer MemberSignature signature = getCallableSignature(proto, nameResolver, kind); if (signature == null) return Collections.emptyList(); - VirtualFile file = findVirtualFileByDescriptor(container); + VirtualFile file = getVirtualFileWithMemberAnnotations(container, proto, nameResolver); try { // TODO: calculate this only once for each container @@ -198,6 +198,29 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer } } + @NotNull + private VirtualFile getVirtualFileWithMemberAnnotations( + @NotNull ClassOrNamespaceDescriptor container, + @NotNull ProtoBuf.Callable proto, + @NotNull NameResolver nameResolver + ) { + if (container instanceof NamespaceDescriptor) { + Name name = JavaProtoBufUtil.loadSrcClassName(proto, nameResolver); + if (name != null) { + // To locate a package$src class, we first find the facade virtual file (*Package.class) and then look up the $src file in + // the same directory. This hack is needed because FileManager doesn't find classfiles for $src classes + VirtualFile facadeFile = findVirtualFileByPackage((NamespaceDescriptor) container); + + VirtualFile srcFile = facadeFile.getParent().findChild(name + ".class"); + if (srcFile != null) { + return srcFile; + } + } + } + + return findVirtualFileByDescriptor(container); + } + @Nullable private static MemberSignature getCallableSignature( @NotNull ProtoBuf.Callable proto, diff --git a/compiler/testData/loadKotlin/annotations/packageMembers/PropertyField.kt b/compiler/testData/loadKotlin/annotations/packageMembers/PropertyField.kt new file mode 100644 index 00000000000..7f822db3f1e --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/packageMembers/PropertyField.kt @@ -0,0 +1,5 @@ +package test + +annotation class Anno + +[Anno] var property: Int = 42 diff --git a/compiler/testData/loadKotlin/annotations/packageMembers/PropertyField.txt b/compiler/testData/loadKotlin/annotations/packageMembers/PropertyField.txt new file mode 100644 index 00000000000..1a61271ee8b --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/packageMembers/PropertyField.txt @@ -0,0 +1,9 @@ +package test + +test.Anno() internal var property: jet.Int + internal fun (): jet.Int + internal fun (/*0*/ : jet.Int): jet.Unit + +internal final annotation class Anno : jet.Annotation { + /*primary*/ public constructor Anno() +} diff --git a/compiler/testData/loadKotlin/annotations/packageMembers/PropertyNoField.kt b/compiler/testData/loadKotlin/annotations/packageMembers/PropertyNoField.kt new file mode 100644 index 00000000000..dcd02fd78d2 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/packageMembers/PropertyNoField.kt @@ -0,0 +1,6 @@ +package test + +annotation class Anno + +[Anno] val property: Int + get() = 42 diff --git a/compiler/testData/loadKotlin/annotations/packageMembers/PropertyNoField.txt b/compiler/testData/loadKotlin/annotations/packageMembers/PropertyNoField.txt new file mode 100644 index 00000000000..4b34a72e986 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/packageMembers/PropertyNoField.txt @@ -0,0 +1,8 @@ +package test + +test.Anno() internal val property: jet.Int + internal fun (): jet.Int + +internal final annotation class Anno : jet.Annotation { + /*primary*/ public constructor Anno() +} diff --git a/compiler/tests/org/jetbrains/jet/descriptors/serialization/DescriptorSerializationTestGenerated.java b/compiler/tests/org/jetbrains/jet/descriptors/serialization/DescriptorSerializationTestGenerated.java index bbe5c7107e6..704806c8907 100644 --- a/compiler/tests/org/jetbrains/jet/descriptors/serialization/DescriptorSerializationTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/descriptors/serialization/DescriptorSerializationTestGenerated.java @@ -141,6 +141,16 @@ public class DescriptorSerializationTestGenerated extends AbstractDescriptorSeri doTest("compiler/testData/loadKotlin/annotations/packageMembers/Getter.kt"); } + @TestMetadata("PropertyField.kt") + public void testPropertyField() throws Exception { + doTest("compiler/testData/loadKotlin/annotations/packageMembers/PropertyField.kt"); + } + + @TestMetadata("PropertyNoField.kt") + public void testPropertyNoField() throws Exception { + doTest("compiler/testData/loadKotlin/annotations/packageMembers/PropertyNoField.kt"); + } + @TestMetadata("Setter.kt") public void testSetter() throws Exception { doTest("compiler/testData/loadKotlin/annotations/packageMembers/Setter.kt"); diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java index 339ee94de4e..19ab79154eb 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java @@ -141,6 +141,16 @@ public class LoadCompiledKotlinTestGenerated extends AbstractLoadCompiledKotlinT doTestWithAccessors("compiler/testData/loadKotlin/annotations/packageMembers/Getter.kt"); } + @TestMetadata("PropertyField.kt") + public void testPropertyField() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/packageMembers/PropertyField.kt"); + } + + @TestMetadata("PropertyNoField.kt") + public void testPropertyNoField() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/packageMembers/PropertyNoField.kt"); + } + @TestMetadata("Setter.kt") public void testSetter() throws Exception { doTestWithAccessors("compiler/testData/loadKotlin/annotations/packageMembers/Setter.kt"); 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 67b35560ac6..8406792ebd1 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java @@ -143,6 +143,16 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/packageMembers/Getter.kt"); } + @TestMetadata("PropertyField.kt") + public void testPropertyField() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/packageMembers/PropertyField.kt"); + } + + @TestMetadata("PropertyNoField.kt") + public void testPropertyNoField() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/packageMembers/PropertyNoField.kt"); + } + @TestMetadata("Setter.kt") public void testSetter() throws Exception { doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/packageMembers/Setter.kt");