From 4aeeafdff0b9d14dbb3254aa2bbcf6f280aa4c7f Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 4 Jul 2013 21:04:53 +0400 Subject: [PATCH] Deserialize annotations on classes First version, not all kinds of value arguments of annotations are supported --- .../di/InjectorForJavaDescriptorResolver.java | 7 + .../di/InjectorForJavaSemanticServices.java | 7 + .../di/InjectorForTopDownAnalyzerForJvm.java | 7 + .../AnnotationDescriptorDeserializer.java | 164 ++++++++++++++++++ .../DeserializedDescriptorResolver.java | 98 ++--------- .../resolver/DeserializedResolverUtils.java | 94 ++++++++++ .../JavaCompileTimeConstResolver.java | 64 ++++--- .../java/resolver/JavaPropertyResolver.java | 11 +- .../descriptors/AnnotationDeserializer.java | 7 +- .../DeserializedClassDescriptor.java | 2 +- .../lang/resolve/constants/BooleanValue.java | 5 + .../annotations/classes/ClassInClassObject.kt | 11 ++ .../classes/ClassInClassObject.txt | 21 +++ .../annotations/classes/ClassObject.kt | 7 + .../annotations/classes/ClassObject.txt | 13 ++ .../annotations/classes/Deprecated.kt | 9 + .../annotations/classes/Deprecated.txt | 17 ++ .../classes/MultipleAnnotations.kt | 7 + .../classes/MultipleAnnotations.txt | 17 ++ .../annotations/classes/NestedClass.kt | 9 + .../annotations/classes/NestedClass.txt | 17 ++ .../loadKotlin/annotations/classes/Simple.kt | 5 + .../loadKotlin/annotations/classes/Simple.txt | 9 + .../annotations/classes/WithArgument.kt | 20 +++ .../annotations/classes/WithArgument.txt | 53 ++++++ .../classes/WithMultipleArguments.kt | 5 + .../classes/WithMultipleArguments.txt | 15 ++ .../AbstractDescriptorSerializationTest.java | 57 +++--- .../DescriptorSerializationTestGenerated.java | 66 ++++++- .../LoadCompiledKotlinTestGenerated.java | 66 ++++++- ...esolveNamespaceComparingTestGenerated.java | 66 ++++++- 31 files changed, 804 insertions(+), 152 deletions(-) create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/AnnotationDescriptorDeserializer.java create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/DeserializedResolverUtils.java create mode 100644 compiler/testData/loadKotlin/annotations/classes/ClassInClassObject.kt create mode 100644 compiler/testData/loadKotlin/annotations/classes/ClassInClassObject.txt create mode 100644 compiler/testData/loadKotlin/annotations/classes/ClassObject.kt create mode 100644 compiler/testData/loadKotlin/annotations/classes/ClassObject.txt create mode 100644 compiler/testData/loadKotlin/annotations/classes/Deprecated.kt create mode 100644 compiler/testData/loadKotlin/annotations/classes/Deprecated.txt create mode 100644 compiler/testData/loadKotlin/annotations/classes/MultipleAnnotations.kt create mode 100644 compiler/testData/loadKotlin/annotations/classes/MultipleAnnotations.txt create mode 100644 compiler/testData/loadKotlin/annotations/classes/NestedClass.kt create mode 100644 compiler/testData/loadKotlin/annotations/classes/NestedClass.txt create mode 100644 compiler/testData/loadKotlin/annotations/classes/Simple.kt create mode 100644 compiler/testData/loadKotlin/annotations/classes/Simple.txt create mode 100644 compiler/testData/loadKotlin/annotations/classes/WithArgument.kt create mode 100644 compiler/testData/loadKotlin/annotations/classes/WithArgument.txt create mode 100644 compiler/testData/loadKotlin/annotations/classes/WithMultipleArguments.kt create mode 100644 compiler/testData/loadKotlin/annotations/classes/WithMultipleArguments.txt diff --git a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaDescriptorResolver.java index 4a6c84bf16f..6a86f6e7178 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaDescriptorResolver.java @@ -34,6 +34,7 @@ import org.jetbrains.jet.lang.resolve.java.resolver.JavaFunctionResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaValueParameterResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaSignatureResolver; import org.jetbrains.jet.lang.resolve.java.resolver.DeserializedDescriptorResolver; +import org.jetbrains.jet.lang.resolve.java.resolver.AnnotationDescriptorDeserializer; import org.jetbrains.jet.lang.resolve.java.resolver.JavaNamespaceResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaConstructorResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaInnerClassResolver; @@ -62,6 +63,7 @@ public class InjectorForJavaDescriptorResolver { private final JavaValueParameterResolver javaValueParameterResolver; private final JavaSignatureResolver javaSignatureResolver; private final DeserializedDescriptorResolver deserializedDescriptorResolver; + private final AnnotationDescriptorDeserializer annotationDescriptorDeserializer; private final JavaNamespaceResolver javaNamespaceResolver; private final JavaConstructorResolver javaConstructorResolver; private final JavaInnerClassResolver javaInnerClassResolver; @@ -90,6 +92,7 @@ public class InjectorForJavaDescriptorResolver { this.javaValueParameterResolver = new JavaValueParameterResolver(); this.javaSignatureResolver = new JavaSignatureResolver(); this.deserializedDescriptorResolver = new DeserializedDescriptorResolver(); + this.annotationDescriptorDeserializer = new AnnotationDescriptorDeserializer(); this.javaNamespaceResolver = new JavaNamespaceResolver(); this.javaConstructorResolver = new JavaConstructorResolver(); this.javaInnerClassResolver = new JavaInnerClassResolver(); @@ -151,9 +154,13 @@ public class InjectorForJavaDescriptorResolver { javaSignatureResolver.setJavaSemanticServices(javaSemanticServices); + deserializedDescriptorResolver.setAnnotationDeserializer(annotationDescriptorDeserializer); deserializedDescriptorResolver.setJavaClassResolver(javaClassResolver); deserializedDescriptorResolver.setJavaNamespaceResolver(javaNamespaceResolver); + annotationDescriptorDeserializer.setJavaClassResolver(javaClassResolver); + annotationDescriptorDeserializer.setPsiClassFinder(psiClassFinder); + javaNamespaceResolver.setDeserializedDescriptorResolver(deserializedDescriptorResolver); javaNamespaceResolver.setJavaSemanticServices(javaSemanticServices); javaNamespaceResolver.setPsiClassFinder(psiClassFinder); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaSemanticServices.java b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaSemanticServices.java index 8fbd045eada..cd5b86fe6c9 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaSemanticServices.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaSemanticServices.java @@ -34,6 +34,7 @@ import org.jetbrains.jet.lang.resolve.java.resolver.JavaFunctionResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaValueParameterResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaSignatureResolver; import org.jetbrains.jet.lang.resolve.java.resolver.DeserializedDescriptorResolver; +import org.jetbrains.jet.lang.resolve.java.resolver.AnnotationDescriptorDeserializer; import org.jetbrains.jet.lang.resolve.java.resolver.JavaNamespaceResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaConstructorResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaInnerClassResolver; @@ -62,6 +63,7 @@ public class InjectorForJavaSemanticServices { private final JavaValueParameterResolver javaValueParameterResolver; private final JavaSignatureResolver javaSignatureResolver; private final DeserializedDescriptorResolver deserializedDescriptorResolver; + private final AnnotationDescriptorDeserializer annotationDescriptorDeserializer; private final JavaNamespaceResolver javaNamespaceResolver; private final JavaConstructorResolver javaConstructorResolver; private final JavaInnerClassResolver javaInnerClassResolver; @@ -88,6 +90,7 @@ public class InjectorForJavaSemanticServices { this.javaValueParameterResolver = new JavaValueParameterResolver(); this.javaSignatureResolver = new JavaSignatureResolver(); this.deserializedDescriptorResolver = new DeserializedDescriptorResolver(); + this.annotationDescriptorDeserializer = new AnnotationDescriptorDeserializer(); this.javaNamespaceResolver = new JavaNamespaceResolver(); this.javaConstructorResolver = new JavaConstructorResolver(); this.javaInnerClassResolver = new JavaInnerClassResolver(); @@ -151,9 +154,13 @@ public class InjectorForJavaSemanticServices { javaSignatureResolver.setJavaSemanticServices(javaSemanticServices); + deserializedDescriptorResolver.setAnnotationDeserializer(annotationDescriptorDeserializer); deserializedDescriptorResolver.setJavaClassResolver(javaClassResolver); deserializedDescriptorResolver.setJavaNamespaceResolver(javaNamespaceResolver); + annotationDescriptorDeserializer.setJavaClassResolver(javaClassResolver); + annotationDescriptorDeserializer.setPsiClassFinder(psiClassFinder); + javaNamespaceResolver.setDeserializedDescriptorResolver(deserializedDescriptorResolver); javaNamespaceResolver.setJavaSemanticServices(javaSemanticServices); javaNamespaceResolver.setPsiClassFinder(psiClassFinder); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java index fc6fa225988..28aacbca79c 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java @@ -59,6 +59,7 @@ import org.jetbrains.jet.lang.resolve.java.resolver.JavaFunctionResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaValueParameterResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaSignatureResolver; import org.jetbrains.jet.lang.resolve.java.resolver.DeserializedDescriptorResolver; +import org.jetbrains.jet.lang.resolve.java.resolver.AnnotationDescriptorDeserializer; import org.jetbrains.jet.lang.resolve.java.resolver.JavaNamespaceResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaConstructorResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaInnerClassResolver; @@ -112,6 +113,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly private final JavaValueParameterResolver javaValueParameterResolver; private final JavaSignatureResolver javaSignatureResolver; private final DeserializedDescriptorResolver deserializedDescriptorResolver; + private final AnnotationDescriptorDeserializer annotationDescriptorDeserializer; private final JavaNamespaceResolver javaNamespaceResolver; private final JavaConstructorResolver javaConstructorResolver; private final JavaInnerClassResolver javaInnerClassResolver; @@ -166,6 +168,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly this.javaValueParameterResolver = new JavaValueParameterResolver(); this.javaSignatureResolver = new JavaSignatureResolver(); this.deserializedDescriptorResolver = new DeserializedDescriptorResolver(); + this.annotationDescriptorDeserializer = new AnnotationDescriptorDeserializer(); this.javaNamespaceResolver = new JavaNamespaceResolver(); this.javaConstructorResolver = new JavaConstructorResolver(); this.javaInnerClassResolver = new JavaInnerClassResolver(); @@ -329,9 +332,13 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly javaSignatureResolver.setJavaSemanticServices(javaSemanticServices); + deserializedDescriptorResolver.setAnnotationDeserializer(annotationDescriptorDeserializer); deserializedDescriptorResolver.setJavaClassResolver(javaClassResolver); deserializedDescriptorResolver.setJavaNamespaceResolver(javaNamespaceResolver); + annotationDescriptorDeserializer.setJavaClassResolver(javaClassResolver); + annotationDescriptorDeserializer.setPsiClassFinder(psiClassFinder); + javaNamespaceResolver.setDeserializedDescriptorResolver(deserializedDescriptorResolver); javaNamespaceResolver.setJavaSemanticServices(javaSemanticServices); javaNamespaceResolver.setPsiClassFinder(psiClassFinder); 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 new file mode 100644 index 00000000000..bc236f3ec66 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/AnnotationDescriptorDeserializer.java @@ -0,0 +1,164 @@ +/* + * 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.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.jet.descriptors.serialization.ProtoBuf; +import org.jetbrains.jet.descriptors.serialization.descriptors.AnnotationDeserializer; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor; +import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; +import org.jetbrains.jet.lang.resolve.java.DescriptorResolverUtils; +import org.jetbrains.jet.lang.resolve.java.PsiClassFinder; +import org.jetbrains.jet.lang.resolve.name.FqName; +import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.utils.ExceptionUtils; + +import javax.inject.Inject; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import static org.jetbrains.asm4.ClassReader.*; +import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.ERROR_IF_FOUND_IN_KOTLIN; +import static org.jetbrains.jet.lang.resolve.java.resolver.DeserializedResolverUtils.*; + +public class AnnotationDescriptorDeserializer implements AnnotationDeserializer { + private PsiClassFinder psiClassFinder; + + private JavaClassResolver javaClassResolver; + + @Inject + public void setPsiClassFinder(PsiClassFinder psiClassFinder) { + this.psiClassFinder = psiClassFinder; + } + + @Inject + public void setJavaClassResolver(JavaClassResolver javaClassResolver) { + this.javaClassResolver = javaClassResolver; + } + + @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) ; + } + + try { + return loadClassAnnotationsFromFile(virtualFile); + } + catch (IOException e) { + throw ExceptionUtils.rethrow(e); + } + } + + @NotNull + private List loadClassAnnotationsFromFile(@NotNull VirtualFile virtualFile) throws IOException { + final List result = new ArrayList(); + + 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); + } + }, SKIP_CODE | SKIP_DEBUG | SKIP_FRAMES); + + return result; + } + + private static boolean ignoreAnnotation(@NotNull String desc) { + // TODO: JvmAbi.JETBRAINS_NOT_NULL_ANNOTATION ? + return desc.equals(DeserializedDescriptorResolver.KOTLIN_INFO_TYPE) || desc.startsWith("Ljet/runtime/typeinfo/"); + } + + @NotNull + private static FqName convertJvmDescriptorToFqName(@NotNull String desc) { + assert desc.startsWith("L") && desc.endsWith(";") : "Not a JVM descriptor: " + desc; + String fqName = desc.substring(1, desc.length() - 1).replace('$', '.').replace('/', '.'); + return new FqName(fqName); + } + + @NotNull + private static AnnotationVisitor resolveAnnotation( + @NotNull final ClassDescriptor annotationClass, + @NotNull final List result + ) { + final AnnotationDescriptor annotation = new AnnotationDescriptor(); + annotation.setAnnotationType(annotationClass.getDefaultType()); + + return new AnnotationVisitor(Opcodes.ASM4) { + // TODO: arrays, annotations, enums + @Override + public void visit(String name, Object value) { + ValueParameterDescriptor parameter = + DescriptorResolverUtils.getValueParameterDescriptorForAnnotationParameter(Name.identifier(name), annotationClass); + if (parameter != null) { + CompileTimeConstant argument = JavaCompileTimeConstResolver.resolveCompileTimeConstantValue(value, null); + if (argument != null) { + annotation.setValueArgument(parameter, argument); + } + } + } + + @Override + public void visitEnd() { + result.add(annotation); + } + }; + } + + @NotNull + @Override + public List loadCallableAnnotations(@NotNull ProtoBuf.Callable callableProto) { + throw new UnsupportedOperationException(); // TODO + } + + @NotNull + @Override + 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 3b282849d9d..51dd2fa5dcf 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,69 +24,36 @@ 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.*; -import org.jetbrains.jet.descriptors.serialization.descriptors.AnnotationDeserializer; +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.descriptors.DeserializedClassDescriptor; import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedPackageMemberScope; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; -import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames; import org.jetbrains.jet.lang.resolve.lazy.storage.LockBasedStorageManager; import org.jetbrains.jet.lang.resolve.name.FqName; -import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; -import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.JetScope; -import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.utils.ExceptionUtils; import javax.inject.Inject; import java.io.IOException; import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; import static org.jetbrains.asm4.ClassReader.*; import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.INCLUDE_KOTLIN; +import static org.jetbrains.jet.lang.resolve.java.resolver.DeserializedResolverUtils.getVirtualFile; +import static org.jetbrains.jet.lang.resolve.java.resolver.DeserializedResolverUtils.kotlinFqNameToJavaFqName; public final class DeserializedDescriptorResolver { + public static final String KOTLIN_INFO_TYPE = JvmStdlibNames.KOTLIN_INFO_CLASS.getAsmType().toString(); - private static final String KOTLIN_INFO_TYPE = JvmStdlibNames.KOTLIN_INFO_CLASS.getAsmType().toString(); + private AnnotationDescriptorDeserializer annotationDeserializer; - public static final AnnotationDeserializer DUMMY_ANNOTATION_DESERIALIZER = new AnnotationDeserializer() { - @NotNull - @Override - public List loadClassAnnotations(@NotNull ProtoBuf.Class classProto) { - // This is a hack for tests: only data annotations are present in test data so far - AnnotationDescriptor annotationDescriptor = new AnnotationDescriptor(); - annotationDescriptor.setAnnotationType(KotlinBuiltIns.getInstance().getDataClassAnnotation().getDefaultType()); - return Collections.singletonList(annotationDescriptor); - } - - @NotNull - @Override - public List loadCallableAnnotations(@NotNull ProtoBuf.Callable callableProto) { - throw new UnsupportedOperationException(); // TODO - } - - @NotNull - @Override - public List loadSetterAnnotations(@NotNull ProtoBuf.Callable callableProto) { - throw new UnsupportedOperationException(); // TODO - } - - @NotNull - @Override - public List loadValueParameterAnnotations(@NotNull ProtoBuf.Callable.ValueParameter parameterProto) { - throw new UnsupportedOperationException(); // TODO - } - }; - - @NotNull private final LockBasedStorageManager storageManager = new LockBasedStorageManager(); private JavaNamespaceResolver javaNamespaceResolver; @@ -102,6 +69,11 @@ public final class DeserializedDescriptorResolver { } }; + @Inject + public void setAnnotationDeserializer(AnnotationDescriptorDeserializer annotationDeserializer) { + this.annotationDeserializer = annotationDeserializer; + } + @Inject public void setJavaNamespaceResolver(JavaNamespaceResolver javaNamespaceResolver) { this.javaNamespaceResolver = javaNamespaceResolver; @@ -144,32 +116,7 @@ public final class DeserializedDescriptorResolver { throw new IllegalStateException("No KotlinInfo annotation stored for " + fqName.asString()); } return DeserializedPackageMemberScope.createScopeFromPackageData(packageDescriptor, packageData, javaDescriptorFinder, - DUMMY_ANNOTATION_DESERIALIZER, storageManager); - } - - @Nullable - private static VirtualFile getVirtualFile( - @NotNull PsiClass psiClass, - @NotNull FqName classFqName, - @NotNull ClassOrNamespaceDescriptor containingDeclaration - ) { - VirtualFile mostOuterClassVirtualFile = psiClass.getContainingFile().getVirtualFile(); - if (mostOuterClassVirtualFile == null) { - throw new IllegalStateException("Could not find virtual file for " + classFqName.asString()); - } - String fileExtension = mostOuterClassVirtualFile.getExtension(); - if (fileExtension == null || !fileExtension.equals("class")) { - return null; - } - ClassId id = ClassId.fromFqNameAndContainingDeclaration(classFqName, containingDeclaration); - FqNameUnsafe relativeClassName = id.getRelativeClassName(); - assert relativeClassName.isSafe() : "Relative class name " + relativeClassName.asString() + " should be safe at this point"; - String classNameWithBucks = relativeClassName.asString().replace(".", "$") + ".class"; - VirtualFile virtualFile = mostOuterClassVirtualFile.getParent().findChild(classNameWithBucks); - if (virtualFile == null) { - throw new IllegalStateException("No virtual file for " + classFqName.asString()); - } - return virtualFile; + annotationDeserializer, storageManager); } @Nullable @@ -187,7 +134,7 @@ public final class DeserializedDescriptorResolver { assert owner != null : "No owner found for " + classId; return new DeserializedClassDescriptor(classId, storageManager, owner, classData.getNameResolver(), - DUMMY_ANNOTATION_DESERIALIZER, javaDescriptorFinder, classData.getClassProto(), null); + annotationDeserializer, javaDescriptorFinder, classData.getClassProto(), null); } @Nullable @@ -267,19 +214,4 @@ public final class DeserializedDescriptorResolver { return data; } } - - @NotNull - private static FqName kotlinFqNameToJavaFqName(@NotNull FqNameUnsafe kotlinFqName) { - List correctedSegments = new ArrayList(); - for (Name segment : kotlinFqName.pathSegments()) { - if (segment.asString().startsWith(" correctedSegments = new ArrayList(); + for (Name segment : kotlinFqName.pathSegments()) { + if (segment.asString().startsWith(" getCompileTimeConstFromLiteralExpression(PsiLiteralExpression value) { - return getCompileTimeConstFromLiteralExpressionWithExpectedType(value, null); - } - - @Nullable - public static CompileTimeConstant getCompileTimeConstFromLiteralExpressionWithExpectedType( - @NotNull PsiLiteralExpression value, - @Nullable JetType expectedType - ) { - Object literalValue = value.getValue(); - if (literalValue instanceof String) { - return new StringValue((String) literalValue); + public static CompileTimeConstant resolveCompileTimeConstantValue(@Nullable Object value, @Nullable JetType expectedType) { + if (value instanceof String) { + return new StringValue((String) value); } - else if (literalValue instanceof Byte) { - return new ByteValue((Byte) literalValue); + else if (value instanceof Byte) { + return new ByteValue((Byte) value); } - else if (literalValue instanceof Short) { - return new ShortValue((Short) literalValue); + else if (value instanceof Short) { + return new ShortValue((Short) value); } - else if (literalValue instanceof Character) { - return new CharValue((Character) literalValue); + else if (value instanceof Character) { + return new CharValue((Character) value); } - else if (literalValue instanceof Integer) { + else if (value instanceof Integer) { KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); + Integer integer = (Integer) value; if (builtIns.getShortType().equals(expectedType)) { - return new ShortValue(((Integer) literalValue).shortValue()); + return new ShortValue(integer.shortValue()); } else if (builtIns.getByteType().equals(expectedType)) { - return new ByteValue(((Integer) literalValue).byteValue()); + return new ByteValue(integer.byteValue()); } else if (builtIns.getCharType().equals(expectedType)) { - return new CharValue((char) ((Integer)literalValue).intValue()); + return new CharValue((char) integer.intValue()); } - return new IntValue((Integer) literalValue); + return new IntValue(integer); } - else if (literalValue instanceof Long) { - return new LongValue((Long) literalValue); + else if (value instanceof Long) { + return new LongValue((Long) value); } - else if (literalValue instanceof Float) { - return new FloatValue((Float) literalValue); + else if (value instanceof Float) { + return new FloatValue((Float) value); } - else if (literalValue instanceof Double) { - return new DoubleValue((Double) literalValue); + else if (value instanceof Double) { + return new DoubleValue((Double) value); } - else if (literalValue instanceof Boolean) { - return ((Boolean) literalValue) ? BooleanValue.TRUE : BooleanValue.FALSE; + else if (value instanceof Boolean) { + return BooleanValue.valueOf((Boolean) value); } - else if (literalValue == null) { + else if (value == null) { return NullValue.NULL; } return null; diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaPropertyResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaPropertyResolver.java index 1fcb6a6da86..447286c7e7f 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaPropertyResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaPropertyResolver.java @@ -17,7 +17,10 @@ package org.jetbrains.jet.lang.resolve.java.resolver; import com.google.common.collect.Sets; -import com.intellij.psi.*; +import com.intellij.psi.PsiEnumConstant; +import com.intellij.psi.PsiExpression; +import com.intellij.psi.PsiField; +import com.intellij.psi.PsiLiteralExpression; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; @@ -29,8 +32,8 @@ import org.jetbrains.jet.lang.resolve.java.*; import org.jetbrains.jet.lang.resolve.java.kotlinSignature.AlternativeFieldSignatureData; import org.jetbrains.jet.lang.resolve.java.kt.DescriptorKindUtils; import org.jetbrains.jet.lang.resolve.java.kt.JetMethodAnnotation; -import org.jetbrains.jet.lang.resolve.java.provider.PsiDeclarationProvider; import org.jetbrains.jet.lang.resolve.java.provider.NamedMembers; +import org.jetbrains.jet.lang.resolve.java.provider.PsiDeclarationProvider; import org.jetbrains.jet.lang.resolve.java.wrapper.*; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.JetScope; @@ -217,8 +220,8 @@ public final class JavaPropertyResolver { if (AnnotationUtils.isPropertyAcceptableAsAnnotationParameter(propertyDescriptor) && psiData.getCharacteristicPsi() instanceof PsiField) { PsiExpression initializer = ((PsiField) psiData.getCharacteristicPsi()).getInitializer(); if (initializer instanceof PsiLiteralExpression) { - CompileTimeConstant constant = JavaCompileTimeConstResolver.getCompileTimeConstFromLiteralExpressionWithExpectedType( - (PsiLiteralExpression) initializer, propertyType); + CompileTimeConstant constant = JavaCompileTimeConstResolver + .resolveCompileTimeConstantValue(((PsiLiteralExpression) initializer).getValue(), propertyType); if (constant != null) { trace.record(BindingContext.COMPILE_TIME_INITIALIZER, propertyDescriptor, constant); } 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 ac8775318df..e26461ed511 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 @@ -2,6 +2,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.annotations.AnnotationDescriptor; import java.util.List; @@ -10,9 +11,7 @@ public interface AnnotationDeserializer { AnnotationDeserializer UNSUPPORTED = new AnnotationDeserializer() { @NotNull @Override - public List loadClassAnnotations( - @NotNull ProtoBuf.Class classProto - ) { + public List loadClassAnnotations(@NotNull ClassDescriptor descriptor, @NotNull ProtoBuf.Class classProto) { return notSupported(); } @@ -44,7 +43,7 @@ public interface AnnotationDeserializer { }; @NotNull - List loadClassAnnotations(@NotNull ProtoBuf.Class classProto); + List loadClassAnnotations(@NotNull ClassDescriptor descriptor, @NotNull ProtoBuf.Class classProto); @NotNull List loadCallableAnnotations( diff --git a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedClassDescriptor.java b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedClassDescriptor.java index 457108ed7c6..fe89dfb9ec3 100644 --- a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedClassDescriptor.java +++ b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedClassDescriptor.java @@ -203,7 +203,7 @@ public class DeserializedClassDescriptor extends ClassDescriptorBase implements if (!Flags.HAS_ANNOTATIONS.get(classProto.getFlags())) { return Collections.emptyList(); } - return annotationDeserializer.loadClassAnnotations(classProto); + return annotationDeserializer.loadClassAnnotations(this, classProto); } @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/BooleanValue.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/BooleanValue.java index 5e99b147bbc..6de2eff88ae 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/BooleanValue.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/BooleanValue.java @@ -32,6 +32,11 @@ public class BooleanValue implements CompileTimeConstant { this.value = value; } + @NotNull + public static BooleanValue valueOf(boolean value) { + return value ? TRUE : FALSE; + } + @Override public Boolean getValue() { return value; diff --git a/compiler/testData/loadKotlin/annotations/classes/ClassInClassObject.kt b/compiler/testData/loadKotlin/annotations/classes/ClassInClassObject.kt new file mode 100644 index 00000000000..8d71ea3f0c2 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/classes/ClassInClassObject.kt @@ -0,0 +1,11 @@ +package test + +annotation class Anno + +class Class { + class object { + Anno class Nested + + Anno inner class Inner + } +} diff --git a/compiler/testData/loadKotlin/annotations/classes/ClassInClassObject.txt b/compiler/testData/loadKotlin/annotations/classes/ClassInClassObject.txt new file mode 100644 index 00000000000..411d4578ce7 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/classes/ClassInClassObject.txt @@ -0,0 +1,21 @@ +package test + +internal final annotation class Anno : jet.Annotation { + /*primary*/ public constructor Anno() +} + +internal final class Class { + /*primary*/ public constructor Class() + + internal class object { + /*primary*/ private constructor () + + test.Anno() internal final inner class Inner { + /*primary*/ public constructor Inner() + } + + test.Anno() internal final class Nested { + /*primary*/ public constructor Nested() + } + } +} diff --git a/compiler/testData/loadKotlin/annotations/classes/ClassObject.kt b/compiler/testData/loadKotlin/annotations/classes/ClassObject.kt new file mode 100644 index 00000000000..009df0d3482 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/classes/ClassObject.kt @@ -0,0 +1,7 @@ +package test + +annotation class Anno + +class Class { + Anno class object +} diff --git a/compiler/testData/loadKotlin/annotations/classes/ClassObject.txt b/compiler/testData/loadKotlin/annotations/classes/ClassObject.txt new file mode 100644 index 00000000000..3a2179f2fca --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/classes/ClassObject.txt @@ -0,0 +1,13 @@ +package test + +internal final annotation class Anno : jet.Annotation { + /*primary*/ public constructor Anno() +} + +internal final class Class { + /*primary*/ public constructor Class() + + test.Anno() internal class object { + /*primary*/ private constructor () + } +} diff --git a/compiler/testData/loadKotlin/annotations/classes/Deprecated.kt b/compiler/testData/loadKotlin/annotations/classes/Deprecated.kt new file mode 100644 index 00000000000..e491204024f --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/classes/Deprecated.kt @@ -0,0 +1,9 @@ +package test + +deprecated("Class") class Class { + deprecated("Nested") class Nested + + deprecated("Inner") inner class Inner + + deprecated("class object") class object +} diff --git a/compiler/testData/loadKotlin/annotations/classes/Deprecated.txt b/compiler/testData/loadKotlin/annotations/classes/Deprecated.txt new file mode 100644 index 00000000000..e3b2e15539e --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/classes/Deprecated.txt @@ -0,0 +1,17 @@ +package test + +jet.deprecated(value = "Class": jet.String) internal final class Class { + /*primary*/ public constructor Class() + + jet.deprecated(value = "class object": jet.String) internal class object { + /*primary*/ private constructor () + } + + jet.deprecated(value = "Inner": jet.String) internal final inner class Inner { + /*primary*/ public constructor Inner() + } + + jet.deprecated(value = "Nested": jet.String) internal final class Nested { + /*primary*/ public constructor Nested() + } +} diff --git a/compiler/testData/loadKotlin/annotations/classes/MultipleAnnotations.kt b/compiler/testData/loadKotlin/annotations/classes/MultipleAnnotations.kt new file mode 100644 index 00000000000..ea080c2cb51 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/classes/MultipleAnnotations.kt @@ -0,0 +1,7 @@ +package test + +annotation class A1 +annotation class A2 +annotation class A3 + +A1 A2 A3 class Class diff --git a/compiler/testData/loadKotlin/annotations/classes/MultipleAnnotations.txt b/compiler/testData/loadKotlin/annotations/classes/MultipleAnnotations.txt new file mode 100644 index 00000000000..4f44b4383c1 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/classes/MultipleAnnotations.txt @@ -0,0 +1,17 @@ +package test + +internal final annotation class A1 : jet.Annotation { + /*primary*/ public constructor A1() +} + +internal final annotation class A2 : jet.Annotation { + /*primary*/ public constructor A2() +} + +internal final annotation class A3 : jet.Annotation { + /*primary*/ public constructor A3() +} + +test.A1() test.A2() test.A3() internal final class Class { + /*primary*/ public constructor Class() +} diff --git a/compiler/testData/loadKotlin/annotations/classes/NestedClass.kt b/compiler/testData/loadKotlin/annotations/classes/NestedClass.kt new file mode 100644 index 00000000000..3ff87b98f91 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/classes/NestedClass.kt @@ -0,0 +1,9 @@ +package test + +annotation class Anno + +class Class { + Anno class Nested + + Anno inner class Inner +} diff --git a/compiler/testData/loadKotlin/annotations/classes/NestedClass.txt b/compiler/testData/loadKotlin/annotations/classes/NestedClass.txt new file mode 100644 index 00000000000..5f5be306449 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/classes/NestedClass.txt @@ -0,0 +1,17 @@ +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 inner class Inner { + /*primary*/ public constructor Inner() + } + + test.Anno() internal final class Nested { + /*primary*/ public constructor Nested() + } +} diff --git a/compiler/testData/loadKotlin/annotations/classes/Simple.kt b/compiler/testData/loadKotlin/annotations/classes/Simple.kt new file mode 100644 index 00000000000..b8ff3970d67 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/classes/Simple.kt @@ -0,0 +1,5 @@ +package test + +annotation class Anno + +Anno class X diff --git a/compiler/testData/loadKotlin/annotations/classes/Simple.txt b/compiler/testData/loadKotlin/annotations/classes/Simple.txt new file mode 100644 index 00000000000..d7e67ea6484 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/classes/Simple.txt @@ -0,0 +1,9 @@ +package test + +internal final annotation class Anno : jet.Annotation { + /*primary*/ public constructor Anno() +} + +test.Anno() internal final class X { + /*primary*/ public constructor X() +} diff --git a/compiler/testData/loadKotlin/annotations/classes/WithArgument.kt b/compiler/testData/loadKotlin/annotations/classes/WithArgument.kt new file mode 100644 index 00000000000..67f60ca8863 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/classes/WithArgument.kt @@ -0,0 +1,20 @@ +package test + +annotation class IntAnno(val value: Int) +annotation class ShortAnno(val value: Short) +annotation class ByteAnno(val value: Byte) +annotation class LongAnno(val value: Long) +annotation class CharAnno(val value: Char) +annotation class BooleanAnno(val value: Boolean) +annotation class FloatAnno(val value: Float) +annotation class DoubleAnno(val value: Double) + +IntAnno(42) +ShortAnno(42) +ByteAnno(42) +LongAnno(42) +CharAnno('A') +BooleanAnno(false) +FloatAnno(3.14) +DoubleAnno(3.14) +class Class diff --git a/compiler/testData/loadKotlin/annotations/classes/WithArgument.txt b/compiler/testData/loadKotlin/annotations/classes/WithArgument.txt new file mode 100644 index 00000000000..38adc78e6fe --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/classes/WithArgument.txt @@ -0,0 +1,53 @@ +package test + +internal final annotation class BooleanAnno : jet.Annotation { + /*primary*/ public constructor BooleanAnno(/*0*/ value: jet.Boolean) + internal final val value: jet.Boolean + internal final fun (): jet.Boolean +} + +internal final annotation class ByteAnno : jet.Annotation { + /*primary*/ public constructor ByteAnno(/*0*/ value: jet.Byte) + internal final val value: jet.Byte + internal final fun (): jet.Byte +} + +internal final annotation class CharAnno : jet.Annotation { + /*primary*/ public constructor CharAnno(/*0*/ value: jet.Char) + internal final val value: jet.Char + internal final fun (): jet.Char +} + +test.IntAnno(value = 42.toInt(): jet.Int) test.ShortAnno(value = 42.toShort(): jet.Short) test.ByteAnno(value = 42.toByte(): jet.Byte) test.LongAnno(value = 42.toLong(): jet.Long) test.CharAnno(value = #65(A): jet.Char) test.BooleanAnno(value = false: jet.Boolean) test.FloatAnno(value = 3.14.toFloat(): jet.Float) test.DoubleAnno(value = 3.14.toDouble(): jet.Double) internal final class Class { + /*primary*/ public constructor Class() +} + +internal final annotation class DoubleAnno : jet.Annotation { + /*primary*/ public constructor DoubleAnno(/*0*/ value: jet.Double) + internal final val value: jet.Double + internal final fun (): jet.Double +} + +internal final annotation class FloatAnno : jet.Annotation { + /*primary*/ public constructor FloatAnno(/*0*/ value: jet.Float) + internal final val value: jet.Float + internal final fun (): jet.Float +} + +internal final annotation class IntAnno : jet.Annotation { + /*primary*/ public constructor IntAnno(/*0*/ value: jet.Int) + internal final val value: jet.Int + internal final fun (): jet.Int +} + +internal final annotation class LongAnno : jet.Annotation { + /*primary*/ public constructor LongAnno(/*0*/ value: jet.Long) + internal final val value: jet.Long + internal final fun (): jet.Long +} + +internal final annotation class ShortAnno : jet.Annotation { + /*primary*/ public constructor ShortAnno(/*0*/ value: jet.Short) + internal final val value: jet.Short + internal final fun (): jet.Short +} diff --git a/compiler/testData/loadKotlin/annotations/classes/WithMultipleArguments.kt b/compiler/testData/loadKotlin/annotations/classes/WithMultipleArguments.kt new file mode 100644 index 00000000000..d1d1204c5aa --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/classes/WithMultipleArguments.kt @@ -0,0 +1,5 @@ +package test + +annotation class Anno(val int: Int, val string: String, val double: Double) + +Anno(42, "OK", 3.14) class Class diff --git a/compiler/testData/loadKotlin/annotations/classes/WithMultipleArguments.txt b/compiler/testData/loadKotlin/annotations/classes/WithMultipleArguments.txt new file mode 100644 index 00000000000..54d9e437220 --- /dev/null +++ b/compiler/testData/loadKotlin/annotations/classes/WithMultipleArguments.txt @@ -0,0 +1,15 @@ +package test + +internal final annotation class Anno : jet.Annotation { + /*primary*/ public constructor Anno(/*0*/ int: jet.Int, /*1*/ string: jet.String, /*2*/ double: jet.Double) + internal final val double: jet.Double + internal final fun (): jet.Double + internal final val int: jet.Int + internal final fun (): jet.Int + internal final val string: jet.String + internal final fun (): jet.String +} + +test.Anno(double = 3.14.toDouble(): jet.Double, int = 42.toInt(): jet.Int, string = "OK": jet.String) internal final class Class { + /*primary*/ public constructor Class() +} diff --git a/compiler/tests/org/jetbrains/jet/descriptors/serialization/AbstractDescriptorSerializationTest.java b/compiler/tests/org/jetbrains/jet/descriptors/serialization/AbstractDescriptorSerializationTest.java index 8d587d5554c..e7f42d5179a 100644 --- a/compiler/tests/org/jetbrains/jet/descriptors/serialization/AbstractDescriptorSerializationTest.java +++ b/compiler/tests/org/jetbrains/jet/descriptors/serialization/AbstractDescriptorSerializationTest.java @@ -26,14 +26,15 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.ConfigurationKind; import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; +import org.jetbrains.jet.descriptors.serialization.descriptors.AnnotationDeserializer; import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedClassDescriptor; import org.jetbrains.jet.di.InjectorForJavaDescriptorResolver; import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorImpl; import org.jetbrains.jet.lang.resolve.BindingTraceContext; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; -import org.jetbrains.jet.lang.resolve.java.resolver.DeserializedDescriptorResolver; import org.jetbrains.jet.lang.resolve.lazy.KotlinTestWithEnvironment; import org.jetbrains.jet.lang.resolve.lazy.LazyResolveTestUtil; import org.jetbrains.jet.lang.resolve.lazy.storage.LockBasedStorageManager; @@ -44,17 +45,48 @@ import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; +import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.test.util.NamespaceComparator; import java.io.*; import java.util.*; import static org.jetbrains.jet.descriptors.serialization.descriptors.AnnotationDeserializer.UNSUPPORTED; +import static org.jetbrains.jet.lang.resolve.java.resolver.DeserializedResolverUtils.naiveKotlinFqName; public abstract class AbstractDescriptorSerializationTest extends KotlinTestWithEnvironment { public static final Name TEST_PACKAGE_NAME = Name.identifier("test"); + public static final AnnotationDeserializer DUMMY_ANNOTATION_DESERIALIZER = new AnnotationDeserializer() { + @NotNull + @Override + public List loadClassAnnotations(@NotNull ClassDescriptor descriptor, @NotNull ProtoBuf.Class classProto) { + // This is a hack for tests: only data annotations are present in test data so far + AnnotationDescriptor annotationDescriptor = new AnnotationDescriptor(); + annotationDescriptor.setAnnotationType(KotlinBuiltIns.getInstance().getDataClassAnnotation().getDefaultType()); + return Collections.singletonList(annotationDescriptor); + } + + @NotNull + @Override + public List loadCallableAnnotations(@NotNull ProtoBuf.Callable callableProto) { + throw new UnsupportedOperationException(); // TODO + } + + @NotNull + @Override + public List loadSetterAnnotations(@NotNull ProtoBuf.Callable callableProto) { + throw new UnsupportedOperationException(); // TODO + } + + @NotNull + @Override + public List loadValueParameterAnnotations(@NotNull ProtoBuf.Callable.ValueParameter parameterProto) { + throw new UnsupportedOperationException(); // TODO + } + }; + @Override protected JetCoreEnvironment createEnvironment() { return createEnvironmentWithMockJdk(ConfigurationKind.JDK_ONLY); @@ -124,7 +156,7 @@ public abstract class AbstractDescriptorSerializationTest extends KotlinTestWith ProtoBuf.QualifiedNameTable qualifiedNames = ProtoBuf.QualifiedNameTable.parseDelimitedFrom(in); ProtoBuf.Class proto = ProtoBuf.Class.parseFrom(in); - classMetadata.put(getNaiveFqName(classDescriptor), new ClassMetadata(simpleNames, qualifiedNames, proto)); + classMetadata.put(naiveKotlinFqName(classDescriptor).asString(), new ClassMetadata(simpleNames, qualifiedNames, proto)); } NamespaceDescriptorImpl namespace = JetTestUtils.createTestNamespace(TEST_PACKAGE_NAME); @@ -184,25 +216,6 @@ public abstract class AbstractDescriptorSerializationTest extends KotlinTestWith return namespace; } - private static String getNaiveFqName(ClassDescriptor classDescriptor) { - return getNaiveFqName(classDescriptor, new StringBuilder()).toString(); - } - - @NotNull - private static StringBuilder getNaiveFqName(@NotNull DeclarationDescriptor descriptor, @NotNull StringBuilder builder) { - DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); - if (containingDeclaration instanceof ClassDescriptor - || (containingDeclaration instanceof NamespaceDescriptor - && !DescriptorUtils.isRootNamespace((NamespaceDescriptor) containingDeclaration))) { - getNaiveFqName(containingDeclaration, builder); - builder.append("."); - } - - builder.append(descriptor.getName().asString()); - - return builder; - } - public static void serialize( List classes, List callables, Map serializedClasses, OutputStream serializedCallables @@ -309,7 +322,7 @@ public abstract class AbstractDescriptorSerializationTest extends KotlinTestWith NameResolver nameResolver = new NameResolver(classMetadata.simpleNames, classMetadata.qualifiedNames); return new DeserializedClassDescriptor(classId, new LockBasedStorageManager(), containingDeclaration, nameResolver, - DeserializedDescriptorResolver.DUMMY_ANNOTATION_DESERIALIZER, this, + DUMMY_ANNOTATION_DESERIALIZER, this, classMetadata.classProto, null); } diff --git a/compiler/tests/org/jetbrains/jet/descriptors/serialization/DescriptorSerializationTestGenerated.java b/compiler/tests/org/jetbrains/jet/descriptors/serialization/DescriptorSerializationTestGenerated.java index 3523accb49d..6de02405d5f 100644 --- a/compiler/tests/org/jetbrains/jet/descriptors/serialization/DescriptorSerializationTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/descriptors/serialization/DescriptorSerializationTestGenerated.java @@ -31,12 +31,75 @@ import org.jetbrains.jet.descriptors.serialization.AbstractDescriptorSerializati /** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") @TestMetadata("compiler/testData/loadKotlin") -@InnerTestClasses({DescriptorSerializationTestGenerated.Class.class, DescriptorSerializationTestGenerated.ClassFun.class, DescriptorSerializationTestGenerated.ClassObject.class, DescriptorSerializationTestGenerated.Constructor.class, DescriptorSerializationTestGenerated.DataClass.class, DescriptorSerializationTestGenerated.Fun.class, DescriptorSerializationTestGenerated.Prop.class, DescriptorSerializationTestGenerated.Type.class, DescriptorSerializationTestGenerated.Visibility.class}) +@InnerTestClasses({DescriptorSerializationTestGenerated.Annotations.class, DescriptorSerializationTestGenerated.Class.class, DescriptorSerializationTestGenerated.ClassFun.class, DescriptorSerializationTestGenerated.ClassObject.class, DescriptorSerializationTestGenerated.Constructor.class, DescriptorSerializationTestGenerated.DataClass.class, DescriptorSerializationTestGenerated.Fun.class, DescriptorSerializationTestGenerated.Prop.class, DescriptorSerializationTestGenerated.Type.class, DescriptorSerializationTestGenerated.Visibility.class}) public class DescriptorSerializationTestGenerated extends AbstractDescriptorSerializationTest { public void testAllFilesPresentInLoadKotlin() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadKotlin"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("compiler/testData/loadKotlin/annotations") + @InnerTestClasses({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/classes") + public static class Classes extends AbstractDescriptorSerializationTest { + public void testAllFilesPresentInClasses() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadKotlin/annotations/classes"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("ClassInClassObject.kt") + public void testClassInClassObject() throws Exception { + doTest("compiler/testData/loadKotlin/annotations/classes/ClassInClassObject.kt"); + } + + @TestMetadata("ClassObject.kt") + public void testClassObject() throws Exception { + doTest("compiler/testData/loadKotlin/annotations/classes/ClassObject.kt"); + } + + @TestMetadata("Deprecated.kt") + public void testDeprecated() throws Exception { + doTest("compiler/testData/loadKotlin/annotations/classes/Deprecated.kt"); + } + + @TestMetadata("MultipleAnnotations.kt") + public void testMultipleAnnotations() throws Exception { + doTest("compiler/testData/loadKotlin/annotations/classes/MultipleAnnotations.kt"); + } + + @TestMetadata("NestedClass.kt") + public void testNestedClass() throws Exception { + doTest("compiler/testData/loadKotlin/annotations/classes/NestedClass.kt"); + } + + @TestMetadata("Simple.kt") + public void testSimple() throws Exception { + doTest("compiler/testData/loadKotlin/annotations/classes/Simple.kt"); + } + + @TestMetadata("WithArgument.kt") + public void testWithArgument() throws Exception { + doTest("compiler/testData/loadKotlin/annotations/classes/WithArgument.kt"); + } + + @TestMetadata("WithMultipleArguments.kt") + public void testWithMultipleArguments() throws Exception { + doTest("compiler/testData/loadKotlin/annotations/classes/WithMultipleArguments.kt"); + } + + } + + public static Test innerSuite() { + TestSuite suite = new TestSuite("Annotations"); + suite.addTestSuite(Annotations.class); + suite.addTestSuite(Classes.class); + return suite; + } + } + @TestMetadata("compiler/testData/loadKotlin/class") public static class Class extends AbstractDescriptorSerializationTest { public void testAllFilesPresentInClass() throws Exception { @@ -1129,6 +1192,7 @@ public class DescriptorSerializationTestGenerated extends AbstractDescriptorSeri public static Test suite() { TestSuite suite = new TestSuite("DescriptorSerializationTestGenerated"); suite.addTestSuite(DescriptorSerializationTestGenerated.class); + suite.addTest(Annotations.innerSuite()); suite.addTestSuite(Class.class); suite.addTestSuite(ClassFun.class); suite.addTestSuite(ClassObject.class); diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java index 206b7283094..8689c36abb5 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java @@ -31,12 +31,75 @@ import org.jetbrains.jet.jvm.compiler.AbstractLoadCompiledKotlinTest; /** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") @TestMetadata("compiler/testData/loadKotlin") -@InnerTestClasses({LoadCompiledKotlinTestGenerated.Class.class, LoadCompiledKotlinTestGenerated.ClassFun.class, LoadCompiledKotlinTestGenerated.ClassObject.class, LoadCompiledKotlinTestGenerated.Constructor.class, LoadCompiledKotlinTestGenerated.DataClass.class, LoadCompiledKotlinTestGenerated.Fun.class, LoadCompiledKotlinTestGenerated.Prop.class, LoadCompiledKotlinTestGenerated.Type.class, LoadCompiledKotlinTestGenerated.Visibility.class}) +@InnerTestClasses({LoadCompiledKotlinTestGenerated.Annotations.class, LoadCompiledKotlinTestGenerated.Class.class, LoadCompiledKotlinTestGenerated.ClassFun.class, LoadCompiledKotlinTestGenerated.ClassObject.class, LoadCompiledKotlinTestGenerated.Constructor.class, LoadCompiledKotlinTestGenerated.DataClass.class, LoadCompiledKotlinTestGenerated.Fun.class, LoadCompiledKotlinTestGenerated.Prop.class, LoadCompiledKotlinTestGenerated.Type.class, LoadCompiledKotlinTestGenerated.Visibility.class}) public class LoadCompiledKotlinTestGenerated extends AbstractLoadCompiledKotlinTest { public void testAllFilesPresentInLoadKotlin() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadKotlin"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("compiler/testData/loadKotlin/annotations") + @InnerTestClasses({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/classes") + public static class Classes extends AbstractLoadCompiledKotlinTest { + public void testAllFilesPresentInClasses() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadKotlin/annotations/classes"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("ClassInClassObject.kt") + public void testClassInClassObject() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/classes/ClassInClassObject.kt"); + } + + @TestMetadata("ClassObject.kt") + public void testClassObject() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/classes/ClassObject.kt"); + } + + @TestMetadata("Deprecated.kt") + public void testDeprecated() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/classes/Deprecated.kt"); + } + + @TestMetadata("MultipleAnnotations.kt") + public void testMultipleAnnotations() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/classes/MultipleAnnotations.kt"); + } + + @TestMetadata("NestedClass.kt") + public void testNestedClass() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/classes/NestedClass.kt"); + } + + @TestMetadata("Simple.kt") + public void testSimple() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/classes/Simple.kt"); + } + + @TestMetadata("WithArgument.kt") + public void testWithArgument() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/classes/WithArgument.kt"); + } + + @TestMetadata("WithMultipleArguments.kt") + public void testWithMultipleArguments() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/annotations/classes/WithMultipleArguments.kt"); + } + + } + + public static Test innerSuite() { + TestSuite suite = new TestSuite("Annotations"); + suite.addTestSuite(Annotations.class); + suite.addTestSuite(Classes.class); + return suite; + } + } + @TestMetadata("compiler/testData/loadKotlin/class") public static class Class extends AbstractLoadCompiledKotlinTest { public void testAllFilesPresentInClass() throws Exception { @@ -1129,6 +1192,7 @@ public class LoadCompiledKotlinTestGenerated extends AbstractLoadCompiledKotlinT public static Test suite() { TestSuite suite = new TestSuite("LoadCompiledKotlinTestGenerated"); suite.addTestSuite(LoadCompiledKotlinTestGenerated.class); + suite.addTest(Annotations.innerSuite()); suite.addTestSuite(Class.class); suite.addTestSuite(ClassFun.class); suite.addTestSuite(ClassObject.class); 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 49fddcd3e18..b0e8dfcf556 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java @@ -33,12 +33,75 @@ import org.jetbrains.jet.lang.resolve.lazy.AbstractLazyResolveNamespaceComparing @InnerTestClasses({LazyResolveNamespaceComparingTestGenerated.LoadKotlin.class, LazyResolveNamespaceComparingTestGenerated.CompiledJavaCompareWithKotlin.class, LazyResolveNamespaceComparingTestGenerated.NamespaceComparator.class}) public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyResolveNamespaceComparingTest { @TestMetadata("compiler/testData/loadKotlin") - @InnerTestClasses({LoadKotlin.Class.class, LoadKotlin.ClassFun.class, LoadKotlin.ClassObject.class, LoadKotlin.Constructor.class, LoadKotlin.DataClass.class, LoadKotlin.Fun.class, LoadKotlin.Prop.class, LoadKotlin.Type.class, LoadKotlin.Visibility.class}) + @InnerTestClasses({LoadKotlin.Annotations.class, LoadKotlin.Class.class, LoadKotlin.ClassFun.class, LoadKotlin.ClassObject.class, LoadKotlin.Constructor.class, LoadKotlin.DataClass.class, LoadKotlin.Fun.class, LoadKotlin.Prop.class, LoadKotlin.Type.class, LoadKotlin.Visibility.class}) public static class LoadKotlin extends AbstractLazyResolveNamespaceComparingTest { public void testAllFilesPresentInLoadKotlin() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadKotlin"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("compiler/testData/loadKotlin/annotations") + @InnerTestClasses({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/classes") + public static class Classes extends AbstractLazyResolveNamespaceComparingTest { + public void testAllFilesPresentInClasses() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadKotlin/annotations/classes"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("ClassInClassObject.kt") + public void testClassInClassObject() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/classes/ClassInClassObject.kt"); + } + + @TestMetadata("ClassObject.kt") + public void testClassObject() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/classes/ClassObject.kt"); + } + + @TestMetadata("Deprecated.kt") + public void testDeprecated() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/classes/Deprecated.kt"); + } + + @TestMetadata("MultipleAnnotations.kt") + public void testMultipleAnnotations() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/classes/MultipleAnnotations.kt"); + } + + @TestMetadata("NestedClass.kt") + public void testNestedClass() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/classes/NestedClass.kt"); + } + + @TestMetadata("Simple.kt") + public void testSimple() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/classes/Simple.kt"); + } + + @TestMetadata("WithArgument.kt") + public void testWithArgument() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/classes/WithArgument.kt"); + } + + @TestMetadata("WithMultipleArguments.kt") + public void testWithMultipleArguments() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/annotations/classes/WithMultipleArguments.kt"); + } + + } + + public static Test innerSuite() { + TestSuite suite = new TestSuite("Annotations"); + suite.addTestSuite(Annotations.class); + suite.addTestSuite(Classes.class); + return suite; + } + } + @TestMetadata("compiler/testData/loadKotlin/class") public static class Class extends AbstractLazyResolveNamespaceComparingTest { public void testAllFilesPresentInClass() throws Exception { @@ -1131,6 +1194,7 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso public static Test innerSuite() { TestSuite suite = new TestSuite("LoadKotlin"); suite.addTestSuite(LoadKotlin.class); + suite.addTest(Annotations.innerSuite()); suite.addTestSuite(Class.class); suite.addTestSuite(ClassFun.class); suite.addTestSuite(ClassObject.class);