From 26081bf8179f5ee06532590c209f4b7a48c47b4f Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Wed, 16 Mar 2016 15:56:25 +0300 Subject: [PATCH] Support loading Java annotations with TYPE_PARAMETER target --- .../load/java/structure/impl/JavaClassImpl.java | 6 ++++++ .../java/structure/impl/JavaClassifierImpl.java | 7 ------- .../structure/impl/JavaTypeParameterImpl.java | 6 ++++++ .../jvm/compiler/LoadJava8TestGenerated.java | 12 ++++++++++++ .../Jvm8RuntimeDescriptorLoaderTestGenerated.java | 6 ++++++ .../compiledJava/TypeParameterAnnotations.java | 15 +++++++++++++++ .../TypeParameterAnnotations.runtime.txt | 14 ++++++++++++++ .../compiledJava/TypeParameterAnnotations.txt | 14 ++++++++++++++ .../sourceJava/TypeParameterAnnotations.java | 14 ++++++++++++++ .../sourceJava/TypeParameterAnnotations.txt | 14 ++++++++++++++ .../AbstractJvm8RuntimeDescriptorLoaderTest.kt | 2 +- .../LazyJavaTypeParameterDescriptor.kt | 5 +++++ .../kotlin/load/java/structure/JavaClass.java | 2 +- .../load/java/structure/JavaClassifier.java | 2 +- .../reflect/ReflectJavaAnnotationOwner.kt | 14 +++++++------- .../structure/reflect/ReflectJavaTypeParameter.kt | 12 +++++++----- .../reflect/ReflectJavaValueParameter.kt | 4 ++-- 17 files changed, 125 insertions(+), 24 deletions(-) create mode 100644 compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.java create mode 100644 compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.runtime.txt create mode 100644 compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.txt create mode 100644 compiler/testData/loadJava8/sourceJava/TypeParameterAnnotations.java create mode 100644 compiler/testData/loadJava8/sourceJava/TypeParameterAnnotations.txt diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassImpl.java b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassImpl.java index 5e0c868f5ce..a437bd57a2d 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassImpl.java @@ -197,4 +197,10 @@ public class JavaClassImpl extends JavaClassifierImpl implements JavaC return PsiSubstitutorImpl.createSubstitutor(substMap); } + + @Nullable + @Override + public PsiAnnotationOwner getAnnotationOwnerPsi() { + return getPsi().getModifierList(); + } } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassifierImpl.java b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassifierImpl.java index 5a93091e9ec..39977543f42 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassifierImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassifierImpl.java @@ -16,7 +16,6 @@ package org.jetbrains.kotlin.load.java.structure.impl; -import com.intellij.psi.PsiAnnotationOwner; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiTypeParameter; import org.jetbrains.annotations.NotNull; @@ -32,12 +31,6 @@ public abstract class JavaClassifierImpl extends JavaEleme super(psiClass); } - @Nullable - @Override - public PsiAnnotationOwner getAnnotationOwnerPsi() { - return getPsi().getModifierList(); - } - @NotNull /* package */ static JavaClassifier create(@NotNull PsiClass psiClass) { if (psiClass instanceof PsiTypeParameter) { diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaTypeParameterImpl.java b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaTypeParameterImpl.java index 85964c9526b..9376ef44b98 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaTypeParameterImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaTypeParameterImpl.java @@ -73,4 +73,10 @@ public class JavaTypeParameterImpl extends JavaClassifierImpl public JavaTypeProvider getTypeProvider() { return new JavaTypeProviderImpl(getPsi().getManager()); } + + @Nullable + @Override + public PsiAnnotationOwner getAnnotationOwnerPsi() { + return getPsi(); + } } diff --git a/compiler/java8-tests/tests/org/jetbrains/kotlin/jvm/compiler/LoadJava8TestGenerated.java b/compiler/java8-tests/tests/org/jetbrains/kotlin/jvm/compiler/LoadJava8TestGenerated.java index ea007b6b68c..14855abf7a8 100644 --- a/compiler/java8-tests/tests/org/jetbrains/kotlin/jvm/compiler/LoadJava8TestGenerated.java +++ b/compiler/java8-tests/tests/org/jetbrains/kotlin/jvm/compiler/LoadJava8TestGenerated.java @@ -42,6 +42,12 @@ public class LoadJava8TestGenerated extends AbstractLoadJava8Test { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava8/compiledJava/TypeAnnotations.java"); doTestCompiledJava(fileName); } + + @TestMetadata("TypeParameterAnnotations.java") + public void testTypeParameterAnnotations() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.java"); + doTestCompiledJava(fileName); + } } @TestMetadata("compiler/testData/loadJava8/sourceJava") @@ -57,5 +63,11 @@ public class LoadJava8TestGenerated extends AbstractLoadJava8Test { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava8/sourceJava/TypeAnnotations.java"); doTestSourceJava(fileName); } + + @TestMetadata("TypeParameterAnnotations.java") + public void testTypeParameterAnnotations() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava8/sourceJava/TypeParameterAnnotations.java"); + doTestSourceJava(fileName); + } } } diff --git a/compiler/java8-tests/tests/org/jetbrains/kotlin/jvm/runtime/Jvm8RuntimeDescriptorLoaderTestGenerated.java b/compiler/java8-tests/tests/org/jetbrains/kotlin/jvm/runtime/Jvm8RuntimeDescriptorLoaderTestGenerated.java index 4dc5b9bf637..6adb497435a 100644 --- a/compiler/java8-tests/tests/org/jetbrains/kotlin/jvm/runtime/Jvm8RuntimeDescriptorLoaderTestGenerated.java +++ b/compiler/java8-tests/tests/org/jetbrains/kotlin/jvm/runtime/Jvm8RuntimeDescriptorLoaderTestGenerated.java @@ -40,4 +40,10 @@ public class Jvm8RuntimeDescriptorLoaderTestGenerated extends AbstractJvm8Runtim String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava8/compiledJava/TypeAnnotations.java"); doTest(fileName); } + + @TestMetadata("TypeParameterAnnotations.java") + public void testTypeParameterAnnotations() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.java"); + doTest(fileName); + } } diff --git a/compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.java b/compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.java new file mode 100644 index 00000000000..304375846db --- /dev/null +++ b/compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.java @@ -0,0 +1,15 @@ +package test; + +import java.lang.annotation.*; +public class TypeParameterAnnotations { + @Target(ElementType.TYPE_PARAMETER) + public @interface A { + String value() default ""; + } + + // Currently annotations on type parameters and arguments are not loaded from compiled code because of IDEA-153093 + // Once it will be fixed check if KT-11454 is ready to be resolved + public interface G<@A T> { + <@A("abc") R> void foo(R r); + } +} diff --git a/compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.runtime.txt b/compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.runtime.txt new file mode 100644 index 00000000000..98273e896e2 --- /dev/null +++ b/compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.runtime.txt @@ -0,0 +1,14 @@ +package test + +public open class TypeParameterAnnotations { + public constructor TypeParameterAnnotations() + + @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE_PARAMETER}) @kotlin.annotation.Retention(value = ...) public final annotation class A : kotlin.Annotation { + public final val value: kotlin.String + public final fun (): kotlin.String + } + + public interface G { + public abstract fun foo(/*0*/ R!): kotlin.Unit + } +} diff --git a/compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.txt b/compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.txt new file mode 100644 index 00000000000..1be3aa442f1 --- /dev/null +++ b/compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.txt @@ -0,0 +1,14 @@ +package test + +public open class TypeParameterAnnotations { + public constructor TypeParameterAnnotations() + + @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE_PARAMETER}) public final annotation class A : kotlin.Annotation { + public constructor A(/*0*/ value: kotlin.String = ...) + public final val value: kotlin.String + } + + public interface G { + public abstract fun foo(/*0*/ p0: R!): kotlin.Unit + } +} diff --git a/compiler/testData/loadJava8/sourceJava/TypeParameterAnnotations.java b/compiler/testData/loadJava8/sourceJava/TypeParameterAnnotations.java new file mode 100644 index 00000000000..cd4cee82cd0 --- /dev/null +++ b/compiler/testData/loadJava8/sourceJava/TypeParameterAnnotations.java @@ -0,0 +1,14 @@ +package test; + +import java.lang.annotation.*; +public class TypeParameterAnnotations { + @Target(ElementType.TYPE_PARAMETER) + @Retention(RetentionPolicy.RUNTIME) + @interface A { + String value() default ""; + } + + interface G<@A T> { + <@A("abc") R> void foo(R r); + } +} diff --git a/compiler/testData/loadJava8/sourceJava/TypeParameterAnnotations.txt b/compiler/testData/loadJava8/sourceJava/TypeParameterAnnotations.txt new file mode 100644 index 00000000000..2d5f7734808 --- /dev/null +++ b/compiler/testData/loadJava8/sourceJava/TypeParameterAnnotations.txt @@ -0,0 +1,14 @@ +package test + +public open class TypeParameterAnnotations { + public constructor TypeParameterAnnotations() + + @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE_PARAMETER}) @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) public/*package*/ final annotation class A : kotlin.Annotation { + public/*package*/ constructor A(/*0*/ value: kotlin.String = ...) + public final val value: kotlin.String + } + + public/*package*/ interface G { + public abstract fun foo(/*0*/ r: R!): kotlin.Unit + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvm8RuntimeDescriptorLoaderTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvm8RuntimeDescriptorLoaderTest.kt index b892241c71a..ce5111e5c3b 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvm8RuntimeDescriptorLoaderTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvm8RuntimeDescriptorLoaderTest.kt @@ -19,5 +19,5 @@ package org.jetbrains.kotlin.jvm.runtime import org.jetbrains.kotlin.test.TestJdkKind abstract class AbstractJvm8RuntimeDescriptorLoaderTest : AbstractJvmRuntimeDescriptorLoaderTest() { - override val defaultJdkKind: TestJdkKind = TestJdkKind.MOCK_JDK + override val defaultJdkKind: TestJdkKind = TestJdkKind.FULL_JDK } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaTypeParameterDescriptor.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaTypeParameterDescriptor.kt index 0a7bfb937c7..cc99ee25712 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaTypeParameterDescriptor.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaTypeParameterDescriptor.kt @@ -19,8 +19,10 @@ package org.jetbrains.kotlin.load.java.lazy.descriptors import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.SourceElement import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker +import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.AbstractLazyTypeParameterDescriptor import org.jetbrains.kotlin.load.java.components.TypeUsage +import org.jetbrains.kotlin.load.java.lazy.LazyJavaAnnotations import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext import org.jetbrains.kotlin.load.java.lazy.types.LazyJavaTypeResolver import org.jetbrains.kotlin.load.java.lazy.types.toAttributes @@ -42,6 +44,9 @@ class LazyJavaTypeParameterDescriptor( index, SourceElement.NO_SOURCE, c.components.supertypeLoopChecker ) { + private val annotations = LazyJavaAnnotations(c, javaTypeParameter) + + override fun getAnnotations() = annotations override fun resolveUpperBounds(): List { val bounds = javaTypeParameter.upperBounds diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/structure/JavaClass.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/structure/JavaClass.java index 746f41d5598..8244591b770 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/structure/JavaClass.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/structure/JavaClass.java @@ -22,7 +22,7 @@ import org.jetbrains.kotlin.name.FqName; import java.util.Collection; -public interface JavaClass extends JavaClassifier, JavaTypeParameterListOwner, JavaModifierListOwner, JavaAnnotationOwner { +public interface JavaClass extends JavaClassifier, JavaTypeParameterListOwner, JavaModifierListOwner { @NotNull Collection getInnerClasses(); diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/structure/JavaClassifier.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/structure/JavaClassifier.java index cd261d31217..ef1a7239365 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/structure/JavaClassifier.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/structure/JavaClassifier.java @@ -16,5 +16,5 @@ package org.jetbrains.kotlin.load.java.structure; -public interface JavaClassifier extends JavaNamedElement { +public interface JavaClassifier extends JavaNamedElement, JavaAnnotationOwner { } diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaAnnotationOwner.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaAnnotationOwner.kt index 2dd04ec2dc8..e45f59c96e9 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaAnnotationOwner.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaAnnotationOwner.kt @@ -21,19 +21,19 @@ import org.jetbrains.kotlin.name.FqName import java.lang.reflect.AnnotatedElement interface ReflectJavaAnnotationOwner : JavaAnnotationOwner { - val element: AnnotatedElement + val element: AnnotatedElement? - override fun getAnnotations() = getAnnotations(element.declaredAnnotations) + override fun getAnnotations() = element?.declaredAnnotations?.getAnnotations() ?: emptyList() - override fun findAnnotation(fqName: FqName) = findAnnotation(element.declaredAnnotations, fqName) + override fun findAnnotation(fqName: FqName) = element?.declaredAnnotations?.findAnnotation(fqName) override fun isDeprecatedInJavaDoc() = false } -fun getAnnotations(annotations: Array): List { - return annotations.map { ReflectJavaAnnotation(it) } +fun Array.getAnnotations(): List { + return map { ReflectJavaAnnotation(it) } } -fun findAnnotation(annotations: Array, fqName: FqName): ReflectJavaAnnotation? { - return annotations.firstOrNull { it.annotationClass.java.classId.asSingleFqName() == fqName }?.let { ReflectJavaAnnotation(it) } +fun Array.findAnnotation(fqName: FqName): ReflectJavaAnnotation? { + return firstOrNull { it.annotationClass.java.classId.asSingleFqName() == fqName }?.let { ReflectJavaAnnotation(it) } } diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaTypeParameter.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaTypeParameter.kt index df33739a257..71dca7f153d 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaTypeParameter.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaTypeParameter.kt @@ -16,24 +16,26 @@ package org.jetbrains.kotlin.load.java.structure.reflect -import org.jetbrains.kotlin.load.java.structure.JavaType -import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter -import org.jetbrains.kotlin.load.java.structure.JavaTypeParameterListOwner -import org.jetbrains.kotlin.load.java.structure.JavaTypeProvider +import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.name.Name +import java.lang.reflect.AnnotatedElement import java.lang.reflect.Constructor import java.lang.reflect.Method import java.lang.reflect.TypeVariable class ReflectJavaTypeParameter( val typeVariable: TypeVariable<*> -) : ReflectJavaElement(), JavaTypeParameter { +) : ReflectJavaElement(), JavaTypeParameter, ReflectJavaAnnotationOwner { override fun getUpperBounds(): List { val bounds = typeVariable.bounds.map { bound -> ReflectJavaClassifierType(bound) } if (bounds.singleOrNull()?.type == Any::class.java) return emptyList() return bounds } + override val element: AnnotatedElement? + // TypeVariable is AnnotatedElement only in JDK8 + get() = typeVariable as? AnnotatedElement + override fun getOwner(): JavaTypeParameterListOwner? { val owner = typeVariable.genericDeclaration return when (owner) { diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaValueParameter.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaValueParameter.kt index 9fcd236aecd..a0b19517b16 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaValueParameter.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaValueParameter.kt @@ -26,9 +26,9 @@ class ReflectJavaValueParameter( private val name: String?, private val isVararg: Boolean ) : ReflectJavaElement(), JavaValueParameter { - override fun getAnnotations() = getAnnotations(annotations) + override fun getAnnotations() = annotations.getAnnotations() - override fun findAnnotation(fqName: FqName) = findAnnotation(annotations, fqName) + override fun findAnnotation(fqName: FqName) = annotations.findAnnotation(fqName) override fun isDeprecatedInJavaDoc() = false