Support loading Java annotations with TYPE_PARAMETER target

This commit is contained in:
Denis Zharkov
2016-03-16 15:56:25 +03:00
parent 04eb5ff4f7
commit 26081bf817
17 changed files with 125 additions and 24 deletions
@@ -197,4 +197,10 @@ public class JavaClassImpl extends JavaClassifierImpl<PsiClass> implements JavaC
return PsiSubstitutorImpl.createSubstitutor(substMap);
}
@Nullable
@Override
public PsiAnnotationOwner getAnnotationOwnerPsi() {
return getPsi().getModifierList();
}
}
@@ -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<Psi extends PsiClass> extends JavaEleme
super(psiClass);
}
@Nullable
@Override
public PsiAnnotationOwner getAnnotationOwnerPsi() {
return getPsi().getModifierList();
}
@NotNull
/* package */ static JavaClassifier create(@NotNull PsiClass psiClass) {
if (psiClass instanceof PsiTypeParameter) {
@@ -73,4 +73,10 @@ public class JavaTypeParameterImpl extends JavaClassifierImpl<PsiTypeParameter>
public JavaTypeProvider getTypeProvider() {
return new JavaTypeProviderImpl(getPsi().getManager());
}
@Nullable
@Override
public PsiAnnotationOwner getAnnotationOwnerPsi() {
return getPsi();
}
}
@@ -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);
}
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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 <get-value>(): kotlin.String
}
public interface G</*0*/ @test.TypeParameterAnnotations.A(value = "") T : kotlin.Any!> {
public abstract fun </*0*/ @test.TypeParameterAnnotations.A(value = "abc") R : kotlin.Any!> foo(/*0*/ R!): kotlin.Unit
}
}
@@ -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</*0*/ T : kotlin.Any!> {
public abstract fun </*0*/ R : kotlin.Any!> foo(/*0*/ p0: R!): kotlin.Unit
}
}
@@ -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);
}
}
@@ -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</*0*/ @test.TypeParameterAnnotations.A() T : kotlin.Any!> {
public abstract fun </*0*/ @test.TypeParameterAnnotations.A(value = "abc") R : kotlin.Any!> foo(/*0*/ r: R!): kotlin.Unit
}
}
@@ -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
}
@@ -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<KotlinType> {
val bounds = javaTypeParameter.upperBounds
@@ -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<JavaClass> getInnerClasses();
@@ -16,5 +16,5 @@
package org.jetbrains.kotlin.load.java.structure;
public interface JavaClassifier extends JavaNamedElement {
public interface JavaClassifier extends JavaNamedElement, JavaAnnotationOwner {
}
@@ -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<Annotation>): List<ReflectJavaAnnotation> {
return annotations.map { ReflectJavaAnnotation(it) }
fun Array<Annotation>.getAnnotations(): List<ReflectJavaAnnotation> {
return map { ReflectJavaAnnotation(it) }
}
fun findAnnotation(annotations: Array<Annotation>, fqName: FqName): ReflectJavaAnnotation? {
return annotations.firstOrNull { it.annotationClass.java.classId.asSingleFqName() == fqName }?.let { ReflectJavaAnnotation(it) }
fun Array<Annotation>.findAnnotation(fqName: FqName): ReflectJavaAnnotation? {
return firstOrNull { it.annotationClass.java.classId.asSingleFqName() == fqName }?.let { ReflectJavaAnnotation(it) }
}
@@ -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<ReflectJavaClassifierType> {
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) {
@@ -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