diff --git a/.idea/modules.xml b/.idea/modules.xml index 4d1846a6f2a..05cd23eb300 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -30,6 +30,7 @@ + diff --git a/build.xml b/build.xml index 95fb1869d3e..8915bfb077f 100644 --- a/build.xml +++ b/build.xml @@ -26,6 +26,7 @@ + diff --git a/compiler/backend/backend.iml b/compiler/backend/backend.iml index d6c4b6e6622..0d10715226e 100644 --- a/compiler/backend/backend.iml +++ b/compiler/backend/backend.iml @@ -14,6 +14,7 @@ + diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 5071c5c067d..7f4e4f83e6e 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -41,9 +41,7 @@ import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter; import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.JetTypeMapper; import org.jetbrains.jet.codegen.state.JetTypeMapperMode; -import org.jetbrains.jet.descriptors.serialization.DescriptorSerializer; -import org.jetbrains.jet.descriptors.serialization.NameSerializationUtil; -import org.jetbrains.jet.descriptors.serialization.ProtoBuf; +import org.jetbrains.jet.descriptors.serialization.*; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; import org.jetbrains.jet.lang.psi.*; @@ -223,7 +221,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { private void writeKotlinInfo() { AnnotationVisitor av = v.getVisitor().visitAnnotation(JvmStdlibNames.KOTLIN_INFO_CLASS.getDescriptor(), true); - DescriptorSerializer serializer = new DescriptorSerializer(); + + DescriptorSerializer serializer = new DescriptorSerializer(new JavaSerializerExtension(typeMapper)); ProtoBuf.Class classProto = serializer.classProto(descriptor).build(); @@ -1844,5 +1843,4 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } - } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JavaSerializerExtension.java b/compiler/backend/src/org/jetbrains/jet/codegen/JavaSerializerExtension.java new file mode 100644 index 00000000000..ec9617a7c14 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JavaSerializerExtension.java @@ -0,0 +1,52 @@ +/* + * 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.codegen; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.codegen.signature.JvmMethodSignature; +import org.jetbrains.jet.codegen.state.JetTypeMapper; +import org.jetbrains.jet.descriptors.serialization.JavaProtoBufUtil; +import org.jetbrains.jet.descriptors.serialization.ProtoBuf; +import org.jetbrains.jet.descriptors.serialization.SerializerExtension; +import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; + +public class JavaSerializerExtension extends SerializerExtension { + private final JetTypeMapper typeMapper; + + public JavaSerializerExtension(@NotNull JetTypeMapper typeMapper) { + this.typeMapper = typeMapper; + } + + @Override + public void serializeCallable(@NotNull CallableMemberDescriptor callable, @NotNull ProtoBuf.Callable.Builder proto) { + JvmMethodSignature signature = mapSignature(callable); + if (signature != null) { + JavaProtoBufUtil.saveJavaSignature(proto, signature.getAsmMethod().toString()); + } + } + + // TODO: this should be done upon generation of the member instead, because we don't know enough at this point to map correctly + @Nullable + private JvmMethodSignature mapSignature(@NotNull CallableMemberDescriptor descriptor) { + if (descriptor instanceof FunctionDescriptor) { + return typeMapper.mapSignature((FunctionDescriptor) descriptor); + } + return null; + } +} diff --git a/compiler/frontend.java/frontend.java.iml b/compiler/frontend.java/frontend.java.iml index b979014c075..26f992661ef 100644 --- a/compiler/frontend.java/frontend.java.iml +++ b/compiler/frontend.java/frontend.java.iml @@ -13,6 +13,7 @@ + diff --git a/compiler/frontend.java/serialization.java/serialization.java.iml b/compiler/frontend.java/serialization.java/serialization.java.iml new file mode 100644 index 00000000000..0a493903138 --- /dev/null +++ b/compiler/frontend.java/serialization.java/serialization.java.iml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/compiler/frontend.java/serialization.java/src/java_descriptors.proto b/compiler/frontend.java/serialization.java/src/java_descriptors.proto new file mode 100644 index 00000000000..1248d0edd8e --- /dev/null +++ b/compiler/frontend.java/serialization.java/src/java_descriptors.proto @@ -0,0 +1,26 @@ +/* + * 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.descriptors.serialization; + +import "compiler/frontend/serialization/src/descriptors.proto"; + +option java_outer_classname = "JavaProtoBuf"; +option optimize_for = LITE_RUNTIME; + +extend Callable { + optional string java_signature = 100; +} 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 new file mode 100644 index 00000000000..9e7df4210cc --- /dev/null +++ b/compiler/frontend.java/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBuf.java @@ -0,0 +1,29 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: compiler/frontend.java/serialization.java/src/java_descriptors.proto + +package org.jetbrains.jet.descriptors.serialization; + +public final class JavaProtoBuf { + private JavaProtoBuf() {} + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistryLite registry) { + registry.add(org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.javaSignature); + } + public static final int JAVA_SIGNATURE_FIELD_NUMBER = 100; + public static final + com.google.protobuf.GeneratedMessageLite.GeneratedExtension< + org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable, + java.lang.String> javaSignature = com.google.protobuf.GeneratedMessageLite + .newSingularGeneratedExtension( + org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable.getDefaultInstance(), + "", + null, + null, + 100, + com.google.protobuf.WireFormat.FieldType.STRING); + + static { + } + + // @@protoc_insertion_point(outer_class_scope) +} 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 new file mode 100644 index 00000000000..d5acb121547 --- /dev/null +++ b/compiler/frontend.java/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBufUtil.java @@ -0,0 +1,44 @@ +/* + * 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.descriptors.serialization; + +import com.google.protobuf.ExtensionRegistryLite; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static org.jetbrains.jet.descriptors.serialization.JavaProtoBuf.javaSignature; + +public class JavaProtoBufUtil { + private JavaProtoBufUtil() { + } + + @Nullable + public static String loadJavaSignature(@NotNull ProtoBuf.Callable callable) { + return callable.hasExtension(javaSignature) ? callable.getExtension(javaSignature) : null; + } + + public static void saveJavaSignature(@NotNull ProtoBuf.Callable.Builder callable, @NotNull String signature) { + callable.setExtension(javaSignature, signature); + } + + @NotNull + public static ClassData readJavaClassDataFrom(@NotNull byte[] data) { + ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance(); + JavaProtoBuf.registerAllExtensions(registry); + return ClassData.read(data, registry); + } +} 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 bc236f3ec66..196fea06465 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 @@ -19,10 +19,9 @@ package org.jetbrains.jet.lang.resolve.java.resolver; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiClass; import org.jetbrains.annotations.NotNull; -import org.jetbrains.asm4.AnnotationVisitor; -import org.jetbrains.asm4.ClassReader; -import org.jetbrains.asm4.ClassVisitor; -import org.jetbrains.asm4.Opcodes; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.asm4.*; +import org.jetbrains.jet.descriptors.serialization.JavaProtoBufUtil; import org.jetbrains.jet.descriptors.serialization.ProtoBuf; import org.jetbrains.jet.descriptors.serialization.descriptors.AnnotationDeserializer; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; @@ -38,8 +37,7 @@ import org.jetbrains.jet.utils.ExceptionUtils; import javax.inject.Inject; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; +import java.util.*; import static org.jetbrains.asm4.ClassReader.*; import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.ERROR_IF_FOUND_IN_KOTLIN; @@ -62,20 +60,8 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer @NotNull @Override - public List loadClassAnnotations( - @NotNull ClassDescriptor descriptor, - @NotNull ProtoBuf.Class classProto - ) { - FqName fqName = kotlinFqNameToJavaFqName(naiveKotlinFqName(descriptor)); - PsiClass psiClass = psiClassFinder.findPsiClass(fqName, PsiClassFinder.RuntimeClassesHandleMode.IGNORE /* TODO: ?! */); - if (psiClass == null) { - throw new IllegalStateException("Psi class is not found for class: " + descriptor); - } - VirtualFile virtualFile = getVirtualFile(psiClass, fqName, (ClassOrNamespaceDescriptor) descriptor.getContainingDeclaration()); - if (virtualFile == null) { - throw new IllegalStateException("Virtual file is not found for class: " + descriptor) ; - } - + public List loadClassAnnotations(@NotNull ClassDescriptor descriptor, @NotNull ProtoBuf.Class classProto) { + VirtualFile virtualFile = findVirtualFileByDescriptor(descriptor); try { return loadClassAnnotationsFromFile(virtualFile); } @@ -84,6 +70,20 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer } } + @NotNull + private VirtualFile findVirtualFileByDescriptor(@NotNull ClassDescriptor descriptor) { + FqName fqName = kotlinFqNameToJavaFqName(naiveKotlinFqName(descriptor)); + PsiClass psiClass = psiClassFinder.findPsiClass(fqName, PsiClassFinder.RuntimeClassesHandleMode.IGNORE /* TODO: ?! */); + if (psiClass == null) { + throw new IllegalStateException("Psi class is not found for class: " + descriptor); + } + VirtualFile virtualFile = getVirtualFile(psiClass, fqName, (ClassOrNamespaceDescriptor) descriptor.getContainingDeclaration()); + if (virtualFile == null) { + throw new IllegalStateException("Virtual file is not found for class: " + descriptor) ; + } + return virtualFile; + } + @NotNull private List loadClassAnnotationsFromFile(@NotNull VirtualFile virtualFile) throws IOException { final List result = new ArrayList(); @@ -91,12 +91,7 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer new ClassReader(virtualFile.getInputStream()).accept(new ClassVisitor(Opcodes.ASM4) { @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - if (ignoreAnnotation(desc)) return null; - - FqName annotationFqName = convertJvmDescriptorToFqName(desc); - ClassDescriptor annotationClass = javaClassResolver.resolveClass(annotationFqName, ERROR_IF_FOUND_IN_KOTLIN); - assert annotationClass != null : "Annotation class is not found: " + desc; - return resolveAnnotation(annotationClass, result); + return resolveAnnotation(desc, result); } }, SKIP_CODE | SKIP_DEBUG | SKIP_FRAMES); @@ -115,11 +110,13 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer return new FqName(fqName); } - @NotNull - private static AnnotationVisitor resolveAnnotation( - @NotNull final ClassDescriptor annotationClass, - @NotNull final List result - ) { + @Nullable + private AnnotationVisitor resolveAnnotation(@NotNull String desc, @NotNull final List result) { + if (ignoreAnnotation(desc)) return null; + + FqName annotationFqName = convertJvmDescriptorToFqName(desc); + final ClassDescriptor annotationClass = javaClassResolver.resolveClass(annotationFqName, ERROR_IF_FOUND_IN_KOTLIN); + assert annotationClass != null : "Annotation class is not found: " + desc; final AnnotationDescriptor annotation = new AnnotationDescriptor(); annotation.setAnnotationType(annotationClass.getDefaultType()); @@ -146,8 +143,56 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer @NotNull @Override - public List loadCallableAnnotations(@NotNull ProtoBuf.Callable callableProto) { - throw new UnsupportedOperationException(); // TODO + public List loadCallableAnnotations( + @NotNull ClassOrNamespaceDescriptor container, + @NotNull ProtoBuf.Callable callableProto + ) { + if (!(container instanceof ClassDescriptor)) return Collections.emptyList(); // TODO: NamespaceDescriptor + + VirtualFile file = findVirtualFileByDescriptor((ClassDescriptor) container); + + try { + // TODO: calculate this only once for each container + Map> memberAnnotations = loadMemberAnnotationsFromFile(file); + + String signature = JavaProtoBufUtil.loadJavaSignature(callableProto); + if (signature == null) return Collections.emptyList(); + + List annotations = memberAnnotations.get(signature); + return annotations == null ? Collections.emptyList() : annotations; + } + catch (IOException e) { + throw ExceptionUtils.rethrow(e); + } + } + + @NotNull + private Map> loadMemberAnnotationsFromFile(@NotNull VirtualFile file) throws IOException { + final Map> memberAnnotations = new HashMap>(); + + new ClassReader(file.getInputStream()).accept(new ClassVisitor(Opcodes.ASM4) { + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + final String methodSignature = name + desc; + final List result = new ArrayList(); + + return new MethodVisitor(Opcodes.ASM4) { + @Override + public AnnotationVisitor visitAnnotation(String desc, boolean visible) { + return resolveAnnotation(desc, result); + } + + @Override + public void visitEnd() { + if (!result.isEmpty()) { + memberAnnotations.put(methodSignature, result); + } + } + }; + } + }, SKIP_CODE | SKIP_DEBUG | SKIP_FRAMES); + + return memberAnnotations; } @NotNull @@ -155,10 +200,4 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer public List loadValueParameterAnnotations(@NotNull ProtoBuf.Callable.ValueParameter parameterProto) { throw new UnsupportedOperationException(); // TODO } - - @NotNull - @Override - public List loadSetterAnnotations(@NotNull ProtoBuf.Callable callableProto) { - throw new UnsupportedOperationException(); // TODO - } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/DeserializedDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/DeserializedDescriptorResolver.java index 51dd2fa5dcf..61835dee81b 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/DeserializedDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/DeserializedDescriptorResolver.java @@ -24,10 +24,7 @@ import org.jetbrains.asm4.AnnotationVisitor; import org.jetbrains.asm4.ClassReader; import org.jetbrains.asm4.ClassVisitor; import org.jetbrains.asm4.Opcodes; -import org.jetbrains.jet.descriptors.serialization.ClassData; -import org.jetbrains.jet.descriptors.serialization.ClassId; -import org.jetbrains.jet.descriptors.serialization.DescriptorFinder; -import org.jetbrains.jet.descriptors.serialization.PackageData; +import org.jetbrains.jet.descriptors.serialization.*; import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedClassDescriptor; import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedPackageMemberScope; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; @@ -141,7 +138,7 @@ public final class DeserializedDescriptorResolver { private static ClassData readClassDataFromClassFile(@NotNull VirtualFile virtualFile) { byte[] data = getKotlinInfoDataFromClassFile(virtualFile); if (data == null) return null; - return ClassData.read(data); + return JavaProtoBufUtil.readJavaClassDataFrom(data); } @Nullable diff --git a/compiler/frontend/serialization/src/descriptors.proto b/compiler/frontend/serialization/src/descriptors.proto index fa4bba55af6..544e674d7f3 100644 --- a/compiler/frontend/serialization/src/descriptors.proto +++ b/compiler/frontend/serialization/src/descriptors.proto @@ -196,6 +196,8 @@ message Callable { repeated ValueParameter value_parameter = 7; required Type return_type = 8; + + extensions 100 to 199; } enum Modality { diff --git a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/ClassData.java b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/ClassData.java index 29ee4e5632d..c3afeb59107 100644 --- a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/ClassData.java +++ b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/ClassData.java @@ -16,6 +16,7 @@ package org.jetbrains.jet.descriptors.serialization; +import com.google.protobuf.ExtensionRegistryLite; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.utils.ExceptionUtils; @@ -24,11 +25,11 @@ import java.io.IOException; public final class ClassData { @NotNull - public static ClassData read(@NotNull byte[] bytes) { + public static ClassData read(@NotNull byte[] bytes, @NotNull ExtensionRegistryLite registry) { try { ByteArrayInputStream in = new ByteArrayInputStream(bytes); NameResolver nameResolver = NameSerializationUtil.deserializeNameResolver(in); - ProtoBuf.Class classProto = ProtoBuf.Class.parseFrom(in); + ProtoBuf.Class classProto = ProtoBuf.Class.parseFrom(in, registry); return new ClassData(nameResolver, classProto); } catch (IOException e) { diff --git a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorDeserializer.java b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorDeserializer.java index 7f980a492cb..e7209ff85e8 100644 --- a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorDeserializer.java +++ b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorDeserializer.java @@ -169,7 +169,7 @@ public class DescriptorDeserializer { boolean isNotDefault = proto.hasSetterFlags() && Flags.IS_NOT_DEFAULT.get(setterFlags); if (isNotDefault) { setter = new PropertySetterDescriptorImpl( - property, getSetterAnnotations(proto, setterFlags), + property, getAnnotations(proto, setterFlags), modality(Flags.MODALITY.get(setterFlags)), visibility(Flags.VISIBILITY.get(setterFlags)), isNotDefault, !isNotDefault, property.getKind() ); @@ -192,13 +192,11 @@ public class DescriptorDeserializer { private PropertyDescriptorImpl createPropertyDescriptor(@NotNull Callable proto) { int flags = proto.getFlags(); Name name = nameResolver.getName(proto.getName()); - List annotations = getAnnotations(proto); + List annotations = getAnnotations(proto, proto.getFlags()); Visibility visibility = visibility(Flags.VISIBILITY.get(flags)); Callable.CallableKind callableKind = Flags.CALLABLE_KIND.get(flags); if (callableKind == Callable.CallableKind.OBJECT_PROPERTY) { - assert containingDeclaration instanceof ClassOrNamespaceDescriptor - : "Properties for objects can only exist in class or namespace: " + name; FqNameUnsafe fqName = DescriptorUtils.getFQName(containingDeclaration).child(name); ClassId objectId = ClassId.fromFqNameAndContainingDeclaration(fqName, (ClassOrNamespaceDescriptor) containingDeclaration); ClassDescriptor objectClass = typeDeserializer.getDescriptorFinder().findClass(objectId); @@ -223,7 +221,7 @@ public class DescriptorDeserializer { int flags = proto.getFlags(); SimpleFunctionDescriptorImpl function = new SimpleFunctionDescriptorImpl( containingDeclaration, - getAnnotations(proto), + getAnnotations(proto, proto.getFlags()), nameResolver.getName(proto.getName()), memberKind(Flags.MEMBER_KIND.get(flags)) ); @@ -254,7 +252,7 @@ public class DescriptorDeserializer { ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration; ConstructorDescriptorImpl descriptor = new ConstructorDescriptorImpl( classDescriptor, - getAnnotations(proto), + getAnnotations(proto, proto.getFlags()), // TODO: primary true); List typeParameters = new ArrayList(proto.getTypeParameterCount()); @@ -269,17 +267,15 @@ public class DescriptorDeserializer { return descriptor; } - private List getAnnotations(Callable proto) { - return Flags.HAS_ANNOTATIONS.get(proto.getFlags()) - ? annotationDeserializer.loadCallableAnnotations(proto) + @NotNull + private List getAnnotations(@NotNull Callable proto, int flags) { + assert containingDeclaration instanceof ClassOrNamespaceDescriptor + : "Only members in classes or namespaces should be serialized: " + containingDeclaration; + return Flags.HAS_ANNOTATIONS.get(flags) + ? annotationDeserializer.loadCallableAnnotations((ClassOrNamespaceDescriptor) containingDeclaration, proto) : Collections.emptyList(); } - private List getSetterAnnotations(Callable proto, int setterFlags) { - return Flags.HAS_ANNOTATIONS.get(setterFlags) ? annotationDeserializer.loadSetterAnnotations(proto) : Collections - .emptyList(); - } - private static CallableMemberDescriptor.Kind memberKind(Callable.MemberKind memberKind) { switch (memberKind) { case DECLARATION: diff --git a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorSerializer.java b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorSerializer.java index b5a1c02f6c4..5414d89616f 100644 --- a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorSerializer.java +++ b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorSerializer.java @@ -212,6 +212,8 @@ public class DescriptorSerializer { builder.setReturnType(local.type(getSerializableReturnType(descriptor.getReturnType()))); + extension.serializeCallable(descriptor, builder); + return builder; } diff --git a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/ProtoBuf.java b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/ProtoBuf.java index ea21b87889a..a021c573aed 100644 --- a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/ProtoBuf.java +++ b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/ProtoBuf.java @@ -5262,8 +5262,9 @@ public final class ProtoBuf { // @@protoc_insertion_point(class_scope:org.jetbrains.jet.descriptors.serialization.Package) } - public interface CallableOrBuilder - extends com.google.protobuf.MessageLiteOrBuilder { + public interface CallableOrBuilder extends + com.google.protobuf.GeneratedMessageLite. + ExtendableMessageOrBuilder { // optional int32 flags = 1; boolean hasFlags(); @@ -5310,8 +5311,8 @@ public final class ProtoBuf { org.jetbrains.jet.descriptors.serialization.ProtoBuf.Type getReturnType(); } public static final class Callable extends - com.google.protobuf.GeneratedMessageLite - implements CallableOrBuilder { + com.google.protobuf.GeneratedMessageLite.ExtendableMessage< + Callable> implements CallableOrBuilder { // Use Callable.newBuilder() to construct. private Callable(Builder builder) { super(builder); @@ -6158,6 +6159,10 @@ public final class ProtoBuf { memoizedIsInitialized = 0; return false; } + if (!extensionsAreInitialized()) { + memoizedIsInitialized = 0; + return false; + } memoizedIsInitialized = 1; return true; } @@ -6165,6 +6170,9 @@ public final class ProtoBuf { public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { getSerializedSize(); + com.google.protobuf.GeneratedMessageLite + .ExtendableMessage.ExtensionWriter extensionWriter = + newExtensionWriter(); if (((bitField0_ & 0x00000001) == 0x00000001)) { output.writeInt32(1, flags_); } @@ -6195,6 +6203,7 @@ public final class ProtoBuf { if (((bitField0_ & 0x00000010) == 0x00000010)) { output.writeInt32(11, setterParameterName_); } + extensionWriter.writeUntil(200, output); } private int memoizedSerializedSize = -1; @@ -6243,6 +6252,7 @@ public final class ProtoBuf { size += com.google.protobuf.CodedOutputStream .computeInt32Size(11, setterParameterName_); } + size += extensionsSerializedSize(); memoizedSerializedSize = size; return size; } @@ -6329,9 +6339,8 @@ public final class ProtoBuf { public Builder toBuilder() { return newBuilder(this); } public static final class Builder extends - com.google.protobuf.GeneratedMessageLite.Builder< - org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable, Builder> - implements org.jetbrains.jet.descriptors.serialization.ProtoBuf.CallableOrBuilder { + com.google.protobuf.GeneratedMessageLite.ExtendableBuilder< + org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable, Builder> implements org.jetbrains.jet.descriptors.serialization.ProtoBuf.CallableOrBuilder { // Construct using org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable.newBuilder() private Builder() { maybeForceBuilderInitialization(); @@ -6490,6 +6499,7 @@ public final class ProtoBuf { if (other.hasReturnType()) { mergeReturnType(other.getReturnType()); } + this.mergeExtensionFields(other); return this; } @@ -6524,6 +6534,10 @@ public final class ProtoBuf { return false; } + if (!extensionsAreInitialized()) { + + return false; + } return true; } diff --git a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/SerializerExtension.java b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/SerializerExtension.java index 7a10a3fb1c8..cb19039ca5c 100644 --- a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/SerializerExtension.java +++ b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/SerializerExtension.java @@ -17,6 +17,7 @@ package org.jetbrains.jet.descriptors.serialization; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; public abstract class SerializerExtension { @@ -25,4 +26,7 @@ public abstract class SerializerExtension { public boolean hasSupertypes(@NotNull ClassDescriptor descriptor) { return true; } + + public void serializeCallable(@NotNull CallableMemberDescriptor callable, @NotNull ProtoBuf.Callable.Builder proto) { + } } diff --git a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/AnnotationDeserializer.java b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/AnnotationDeserializer.java index e26461ed511..a726690deda 100644 --- a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/AnnotationDeserializer.java +++ b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/AnnotationDeserializer.java @@ -3,6 +3,7 @@ package org.jetbrains.jet.descriptors.serialization.descriptors; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.descriptors.serialization.ProtoBuf; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import java.util.List; @@ -18,22 +19,14 @@ public interface AnnotationDeserializer { @NotNull @Override public List loadCallableAnnotations( - @NotNull ProtoBuf.Callable callableProto + @NotNull ClassOrNamespaceDescriptor container, @NotNull ProtoBuf.Callable callableProto ) { return notSupported(); } @NotNull @Override - public List loadSetterAnnotations(@NotNull ProtoBuf.Callable callableProto) { - return notSupported(); - } - - @NotNull - @Override - public List loadValueParameterAnnotations( - @NotNull ProtoBuf.Callable.ValueParameter parameterProto - ) { + public List loadValueParameterAnnotations(@NotNull ProtoBuf.Callable.ValueParameter parameterProto) { return notSupported(); } @@ -47,14 +40,10 @@ public interface AnnotationDeserializer { @NotNull List loadCallableAnnotations( + @NotNull ClassOrNamespaceDescriptor container, @NotNull ProtoBuf.Callable callableProto ); @NotNull - List loadValueParameterAnnotations( - @NotNull ProtoBuf.Callable.ValueParameter parameterProto - ); - - @NotNull - List loadSetterAnnotations(@NotNull ProtoBuf.Callable callableProto); + List loadValueParameterAnnotations(@NotNull ProtoBuf.Callable.ValueParameter parameterProto); } diff --git a/compiler/testData/loadKotlin/annotations/classMembers/Function.kt b/compiler/testData/loadKotlin/annotations/classMembers/Function.kt new file mode 100644 index 00000000000..ecb1631416f --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/classMembers/Function.kt @@ -0,0 +1,7 @@ +package test + +annotation class Anno + +class Class { + Anno fun foo() { } +} diff --git a/compiler/testData/loadKotlin/annotations/classMembers/Function.txt b/compiler/testData/loadKotlin/annotations/classMembers/Function.txt new file mode 100644 index 00000000000..04d14bc8372 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/classMembers/Function.txt @@ -0,0 +1,10 @@ +package test + +internal final annotation class Anno : jet.Annotation { + /*primary*/ public constructor Anno() +} + +internal final class Class { + /*primary*/ public constructor Class() + test.Anno() internal final fun foo(): jet.Unit +} diff --git a/compiler/tests/org/jetbrains/jet/descriptors/serialization/AbstractDescriptorSerializationTest.java b/compiler/tests/org/jetbrains/jet/descriptors/serialization/AbstractDescriptorSerializationTest.java index e7f42d5179a..5f8398843fa 100644 --- a/compiler/tests/org/jetbrains/jet/descriptors/serialization/AbstractDescriptorSerializationTest.java +++ b/compiler/tests/org/jetbrains/jet/descriptors/serialization/AbstractDescriptorSerializationTest.java @@ -70,13 +70,9 @@ public abstract class AbstractDescriptorSerializationTest extends KotlinTestWith @NotNull @Override - public List loadCallableAnnotations(@NotNull ProtoBuf.Callable callableProto) { - throw new UnsupportedOperationException(); // TODO - } - - @NotNull - @Override - public List loadSetterAnnotations(@NotNull ProtoBuf.Callable callableProto) { + public List loadCallableAnnotations( + @NotNull ClassOrNamespaceDescriptor container, @NotNull ProtoBuf.Callable callableProto + ) { throw new UnsupportedOperationException(); // TODO } diff --git a/compiler/tests/org/jetbrains/jet/descriptors/serialization/DescriptorSerializationTestGenerated.java b/compiler/tests/org/jetbrains/jet/descriptors/serialization/DescriptorSerializationTestGenerated.java index 6de02405d5f..3baa7af4c19 100644 --- a/compiler/tests/org/jetbrains/jet/descriptors/serialization/DescriptorSerializationTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/descriptors/serialization/DescriptorSerializationTestGenerated.java @@ -38,12 +38,25 @@ public class DescriptorSerializationTestGenerated extends AbstractDescriptorSeri } @TestMetadata("compiler/testData/loadKotlin/annotations") - @InnerTestClasses({Annotations.Classes.class}) + @InnerTestClasses({Annotations.ClassMembers.class, Annotations.Classes.class}) public static class Annotations extends AbstractDescriptorSerializationTest { public void testAllFilesPresentInAnnotations() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadKotlin/annotations"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("compiler/testData/loadKotlin/annotations/classMembers") + public static class ClassMembers extends AbstractDescriptorSerializationTest { + public void testAllFilesPresentInClassMembers() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadKotlin/annotations/classMembers"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("Function.kt") + public void testFunction() throws Exception { + doTest("compiler/testData/loadKotlin/annotations/classMembers/Function.kt"); + } + + } + @TestMetadata("compiler/testData/loadKotlin/annotations/classes") public static class Classes extends AbstractDescriptorSerializationTest { public void testAllFilesPresentInClasses() throws Exception { @@ -95,6 +108,7 @@ public class DescriptorSerializationTestGenerated extends AbstractDescriptorSeri public static Test innerSuite() { TestSuite suite = new TestSuite("Annotations"); suite.addTestSuite(Annotations.class); + suite.addTestSuite(ClassMembers.class); suite.addTestSuite(Classes.class); return suite; } diff --git a/compiler/tests/org/jetbrains/jet/descriptors/serialization/KotlinInfoForClassTest.java b/compiler/tests/org/jetbrains/jet/descriptors/serialization/KotlinInfoForClassTest.java index 2c486604b30..844f4cc9878 100644 --- a/compiler/tests/org/jetbrains/jet/descriptors/serialization/KotlinInfoForClassTest.java +++ b/compiler/tests/org/jetbrains/jet/descriptors/serialization/KotlinInfoForClassTest.java @@ -32,6 +32,8 @@ import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; import java.io.IOException; +import static com.google.protobuf.ExtensionRegistryLite.getEmptyRegistry; + public class KotlinInfoForClassTest extends CodegenTestCase { public static final FqName NAMESPACE_NAME = new FqName("test"); public static final FqNameUnsafe CLASS_NAME = new FqNameUnsafe("A"); @@ -68,7 +70,7 @@ public class KotlinInfoForClassTest extends CodegenTestCase { public KotlinInfoBasedDescriptorFinder(@NotNull KotlinInfo kotlinInfo) throws IOException { super(new LockBasedStorageManager(), AnnotationDeserializer.UNSUPPORTED); - this.classData = ClassData.read(kotlinInfo.data()); + this.classData = ClassData.read(kotlinInfo.data(), getEmptyRegistry()); this.namespace = JetTestUtils.createTestNamespace(NAMESPACE_NAME.shortName()); } diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java index 8689c36abb5..14150f8a231 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java @@ -38,12 +38,25 @@ public class LoadCompiledKotlinTestGenerated extends AbstractLoadCompiledKotlinT } @TestMetadata("compiler/testData/loadKotlin/annotations") - @InnerTestClasses({Annotations.Classes.class}) + @InnerTestClasses({Annotations.ClassMembers.class, Annotations.Classes.class}) public static class Annotations extends AbstractLoadCompiledKotlinTest { public void testAllFilesPresentInAnnotations() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadKotlin/annotations"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("compiler/testData/loadKotlin/annotations/classMembers") + public static class ClassMembers extends AbstractLoadCompiledKotlinTest { + public void testAllFilesPresentInClassMembers() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadKotlin/annotations/classMembers"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("Function.kt") + public void testFunction() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/classMembers/Function.kt"); + } + + } + @TestMetadata("compiler/testData/loadKotlin/annotations/classes") public static class Classes extends AbstractLoadCompiledKotlinTest { public void testAllFilesPresentInClasses() throws Exception { @@ -95,6 +108,7 @@ public class LoadCompiledKotlinTestGenerated extends AbstractLoadCompiledKotlinT public static Test innerSuite() { TestSuite suite = new TestSuite("Annotations"); suite.addTestSuite(Annotations.class); + suite.addTestSuite(ClassMembers.class); suite.addTestSuite(Classes.class); return suite; } 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 b0e8dfcf556..667f1d70c4b 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java @@ -40,12 +40,25 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso } @TestMetadata("compiler/testData/loadKotlin/annotations") - @InnerTestClasses({Annotations.Classes.class}) + @InnerTestClasses({Annotations.ClassMembers.class, Annotations.Classes.class}) public static class Annotations extends AbstractLazyResolveNamespaceComparingTest { public void testAllFilesPresentInAnnotations() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadKotlin/annotations"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("compiler/testData/loadKotlin/annotations/classMembers") + public static class ClassMembers extends AbstractLazyResolveNamespaceComparingTest { + public void testAllFilesPresentInClassMembers() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadKotlin/annotations/classMembers"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("Function.kt") + public void testFunction() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/classMembers/Function.kt"); + } + + } + @TestMetadata("compiler/testData/loadKotlin/annotations/classes") public static class Classes extends AbstractLazyResolveNamespaceComparingTest { public void testAllFilesPresentInClasses() throws Exception { @@ -97,6 +110,7 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso public static Test innerSuite() { TestSuite suite = new TestSuite("Annotations"); suite.addTestSuite(Annotations.class); + suite.addTestSuite(ClassMembers.class); suite.addTestSuite(Classes.class); return suite; }