diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index 60098bb4e2f..e9b1cbe4349 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -34,6 +34,7 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.OverrideResolver; +import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.java.alt.AltClassFinder; import org.jetbrains.jet.lang.resolve.java.kt.JetClassAnnotation; import org.jetbrains.jet.lang.types.*; @@ -282,7 +283,8 @@ public class JavaDescriptorResolver { DeclarationDescriptor containingDeclaration = resolveParentDescriptor(psiClass); classData.classDescriptor = new MutableClassDescriptorLite(containingDeclaration, kind); classData.classDescriptor.setName(name); - + classData.classDescriptor.setAnnotations(resolveAnnotations(psiClass)); + List supertypes = new ArrayList(); TypeVariableResolverFromOuters outerTypeVariableByNameResolver = new TypeVariableResolverFromOuters(containingDeclaration); @@ -297,10 +299,16 @@ public class JavaDescriptorResolver { classData.classDescriptor.setTypeParameterDescriptors(typeParameters); classData.classDescriptor.setSupertypes(supertypes); classData.classDescriptor.setVisibility(resolveVisibilityFromPsiModifiers(psiClass)); - classData.classDescriptor.setModality(Modality.convertFromFlags( - psiClass.hasModifierProperty(PsiModifier.ABSTRACT) || psiClass.isInterface(), - !psiClass.hasModifierProperty(PsiModifier.FINAL)) - ); + Modality modality; + if (classData.classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS) { + modality = Modality.FINAL; + } + else { + modality = Modality.convertFromFlags( + psiClass.hasModifierProperty(PsiModifier.ABSTRACT) || psiClass.isInterface(), + !psiClass.hasModifierProperty(PsiModifier.FINAL)); + } + classData.classDescriptor.setModality(modality); classData.classDescriptor.createTypeConstructor(); classData.classDescriptor.setScopeForMemberLookup(new JavaClassMembersScope(classData.classDescriptor, psiClass, semanticServices, false)); @@ -700,8 +708,8 @@ public class JavaDescriptorResolver { } }); } else { - transformSupertypeList(result, psiClass.getPsiClass().getExtendsListTypes(), new TypeVariableResolverFromTypeDescriptors(typeParameters, null)); - transformSupertypeList(result, psiClass.getPsiClass().getImplementsListTypes(), new TypeVariableResolverFromTypeDescriptors(typeParameters, null)); + transformSupertypeList(result, psiClass.getPsiClass().getExtendsListTypes(), new TypeVariableResolverFromTypeDescriptors(typeParameters, null), classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS); + transformSupertypeList(result, psiClass.getPsiClass().getImplementsListTypes(), new TypeVariableResolverFromTypeDescriptors(typeParameters, null), classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS); } for (JetType supertype : result) { @@ -716,12 +724,15 @@ public class JavaDescriptorResolver { return result; } - private void transformSupertypeList(List result, PsiClassType[] extendsListTypes, TypeVariableResolver typeVariableResolver) { + private void transformSupertypeList(List result, PsiClassType[] extendsListTypes, TypeVariableResolver typeVariableResolver, boolean annotation) { for (PsiClassType type : extendsListTypes) { PsiClass resolved = type.resolve(); if (resolved != null && resolved.getQualifiedName().equals(JvmStdlibNames.JET_OBJECT.getFqName())) { continue; } + if (annotation && resolved.getQualifiedName().equals("java.lang.annotation.Annotation")) { + continue; + } JetType transform = semanticServices.getTypeTransformer().transformToType(type, typeVariableResolver); @@ -1373,7 +1384,7 @@ public class JavaDescriptorResolver { NamedFunctionDescriptorImpl functionDescriptorImpl = new NamedFunctionDescriptorImpl( owner, - Collections.emptyList(), // TODO + resolveAnnotations(method.getPsiMethod()), method.getName(), CallableMemberDescriptor.Kind.DECLARATION ); @@ -1405,6 +1416,37 @@ public class JavaDescriptorResolver { return (FunctionDescriptorImpl) substitutedFunctionDescriptor; } + private List resolveAnnotations(PsiModifierListOwner owner) { + PsiAnnotation[] psiAnnotations = owner.getModifierList().getAnnotations(); + List r = Lists.newArrayListWithCapacity(psiAnnotations.length); + for (PsiAnnotation psiAnnotation : psiAnnotations) { + AnnotationDescriptor annotation = resolveAnnotation(psiAnnotation); + if (annotation != null) { + r.add(annotation); + } + } + return r; + } + + @Nullable + private AnnotationDescriptor resolveAnnotation(PsiAnnotation psiAnnotation) { + AnnotationDescriptor annotation = new AnnotationDescriptor(); + + String qname = psiAnnotation.getQualifiedName(); + if (qname.startsWith("java.lang.annotation.") || qname.startsWith("jet.runtime.typeinfo.") || qname.equals(JvmAbi.JETBRAINS_NOT_NULL_ANNOTATION.getFqName())) { + // TODO + return null; + } + + ClassDescriptor clazz = resolveClass(psiAnnotation.getQualifiedName()); + if (clazz == null) { + return null; + } + annotation.setAnnotationType(clazz.getDefaultType()); + annotation.setValueArguments(new ArrayList>()); // TODO + return annotation; + } + public List resolveMethods(PsiClass psiClass, ClassOrNamespaceDescriptor containingDeclaration) { ResolverScopeData scopeData = getResolverScopeData(containingDeclaration, new PsiClassWrapper(psiClass)); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java index 12024efc629..8f9a090902a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java @@ -133,7 +133,7 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor { @Override public List getAnnotations() { - throw new UnsupportedOperationException(); // TODO + return original.getAnnotations(); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptorLite.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptorLite.java index 3a46a60b582..1b1c21fa51b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptorLite.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptorLite.java @@ -40,7 +40,7 @@ public class MutableClassDescriptorLite extends MutableDeclarationDescriptor imp private ConstructorDescriptor primaryConstructor; private final Set constructors = Sets.newLinkedHashSet(); - private final List annotations = Lists.newArrayList(); + private List annotations = Lists.newArrayList(); private Map innerClassesAndObjects = Maps.newHashMap(); @@ -342,4 +342,8 @@ public class MutableClassDescriptorLite extends MutableDeclarationDescriptor imp public List getAnnotations() { return annotations; } + + public void setAnnotations(List annotations) { + this.annotations = annotations; + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/annotations/AnnotationDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/annotations/AnnotationDescriptor.java index 1653ebab559..be09c9892c4 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/annotations/AnnotationDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/annotations/AnnotationDescriptor.java @@ -17,9 +17,11 @@ package org.jetbrains.jet.lang.descriptors.annotations; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.types.JetType; +import javax.rmi.CORBA.ClassDesc; import java.util.List; /** @@ -40,6 +42,9 @@ public class AnnotationDescriptor { } public void setAnnotationType(@NotNull JetType annotationType) { + if (!(annotationType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor)) { + throw new IllegalStateException(); + } this.annotationType = annotationType; } diff --git a/compiler/testData/readJavaBinaryClass/annotation/AnnotatedMethod.java b/compiler/testData/readJavaBinaryClass/annotation/AnnotatedMethod.java new file mode 100644 index 00000000000..a370ecc04a6 --- /dev/null +++ b/compiler/testData/readJavaBinaryClass/annotation/AnnotatedMethod.java @@ -0,0 +1,12 @@ +package test; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.CLASS) +@interface Aaa { +} + +class HasAnnotatedMethod { + @Aaa + public void f() { } +} diff --git a/compiler/testData/readJavaBinaryClass/annotation/AnnotatedMethod.kt b/compiler/testData/readJavaBinaryClass/annotation/AnnotatedMethod.kt new file mode 100644 index 00000000000..fe2bd5bda84 --- /dev/null +++ b/compiler/testData/readJavaBinaryClass/annotation/AnnotatedMethod.kt @@ -0,0 +1,7 @@ +package test + +annotation class Aaa + +open class HasAnnotatedMethod() { + open Aaa fun f(): Unit { } +} diff --git a/compiler/testData/readJavaBinaryClass/annotation/AnnotatedMethod.txt b/compiler/testData/readJavaBinaryClass/annotation/AnnotatedMethod.txt new file mode 100644 index 00000000000..e672b9278c4 --- /dev/null +++ b/compiler/testData/readJavaBinaryClass/annotation/AnnotatedMethod.txt @@ -0,0 +1,9 @@ +namespace test + +open class test.HasAnnotatedMethod : jet.Any { + final /*constructor*/ fun (): test.HasAnnotatedMethod + open test.Aaa() fun f(): jet.Tuple0 +} +final annotation class test.Aaa : jet.Any { + final /*constructor*/ fun (): test.Aaa +} diff --git a/compiler/testData/readJavaBinaryClass/annotation/SimpleAnnotation.java b/compiler/testData/readJavaBinaryClass/annotation/SimpleAnnotation.java new file mode 100644 index 00000000000..a2b8b821a12 --- /dev/null +++ b/compiler/testData/readJavaBinaryClass/annotation/SimpleAnnotation.java @@ -0,0 +1,4 @@ +package test; + +@interface SimpleAnnotation { +} diff --git a/compiler/testData/readJavaBinaryClass/annotation/SimpleAnnotation.kt b/compiler/testData/readJavaBinaryClass/annotation/SimpleAnnotation.kt new file mode 100644 index 00000000000..a8a82d59a6c --- /dev/null +++ b/compiler/testData/readJavaBinaryClass/annotation/SimpleAnnotation.kt @@ -0,0 +1,3 @@ +package test + +annotation class SimpleAnnotation diff --git a/compiler/testData/readJavaBinaryClass/annotation/SimpleAnnotation.txt b/compiler/testData/readJavaBinaryClass/annotation/SimpleAnnotation.txt new file mode 100644 index 00000000000..923d4f9ce03 --- /dev/null +++ b/compiler/testData/readJavaBinaryClass/annotation/SimpleAnnotation.txt @@ -0,0 +1,5 @@ +namespace test + +final annotation class test.SimpleAnnotation : jet.Any { + final /*constructor*/ fun (): test.SimpleAnnotation +} diff --git a/compiler/tests/org/jetbrains/jet/compiler/NamespaceComparator.java b/compiler/tests/org/jetbrains/jet/compiler/NamespaceComparator.java index 082fec9edcf..73c590892fb 100644 --- a/compiler/tests/org/jetbrains/jet/compiler/NamespaceComparator.java +++ b/compiler/tests/org/jetbrains/jet/compiler/NamespaceComparator.java @@ -33,6 +33,7 @@ import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; +import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.JavaNamespaceDescriptor; import org.jetbrains.jet.lang.resolve.scopes.JetScope; @@ -200,6 +201,9 @@ class NamespaceComparator { case OBJECT: sb.append("object"); break; + case ANNOTATION_CLASS: + sb.append("annotation class"); + break; default: throw new IllegalStateException("unknown class kind: " + kind); } @@ -218,6 +222,11 @@ class NamespaceComparator { public void serialize(FunctionDescriptor fun) { serialize(fun.getModality()); sb.append(" "); + + if (!fun.getAnnotations().isEmpty()) { + new Serializer(sb).serializeSeparated(fun.getAnnotations(), " "); + sb.append(" "); + } if (!fun.getOverriddenDescriptors().isEmpty()) { sb.append("override /*" + fun.getOverriddenDescriptors().size() + "*/ "); @@ -250,6 +259,11 @@ class NamespaceComparator { } public void serialize(PropertyDescriptor prop) { + if (!prop.getAnnotations().isEmpty()) { + new Serializer(sb).serializeSeparated(prop.getAnnotations(), " "); + sb.append(" "); + } + if (prop.isVar()) { sb.append("var "); } else { @@ -322,6 +336,13 @@ class NamespaceComparator { } } + public void serialize(AnnotationDescriptor annotation) { + serialize(annotation.getType()); + sb.append("("); + serializeCommaSeparated(annotation.getValueArguments()); + sb.append(")"); + } + public void serializeCommaSeparated(List list) { serializeSeparated(list, ", "); } @@ -460,6 +481,10 @@ class NamespaceComparator { public void serialize(ClassDescriptor klass) { + if (!klass.getAnnotations().isEmpty()) { + new Serializer(sb).serializeSeparated(klass.getAnnotations(), " "); + sb.append(" "); + } serialize(klass.getModality()); sb.append(" ");