From a14b301f31c3da0692a71eaebd644f49b6c69ac6 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 20 Jan 2015 20:59:49 +0300 Subject: [PATCH] Resolve annotations on all reflected elements Annotation in NestedEnumArgument test is made public, because we try to load annotation argument values eagerly and fail, since you can't invoke methods reflectively on an object of a non-effectively-public class --- .../annotations/NestedEnumArgument.java | 2 +- .../annotations/NestedEnumArgument.txt | 4 +- .../reflect/ReflectJavaAnnotationOwner.kt | 37 +++++++++++++++++++ .../structure/reflect/ReflectJavaClass.kt | 22 ++++------- .../reflect/ReflectJavaConstructor.kt | 25 +++---------- .../structure/reflect/ReflectJavaField.kt | 23 ++---------- .../structure/reflect/ReflectJavaMember.kt | 7 +++- .../structure/reflect/ReflectJavaMethod.kt | 29 +++------------ .../reflect/ReflectJavaValueParameter.kt | 13 ++----- 9 files changed, 71 insertions(+), 91 deletions(-) create mode 100644 core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaAnnotationOwner.kt diff --git a/compiler/testData/loadJava/compiledJava/annotations/NestedEnumArgument.java b/compiler/testData/loadJava/compiledJava/annotations/NestedEnumArgument.java index 34643a58a4f..4a13e72bced 100644 --- a/compiler/testData/loadJava/compiledJava/annotations/NestedEnumArgument.java +++ b/compiler/testData/loadJava/compiledJava/annotations/NestedEnumArgument.java @@ -5,7 +5,7 @@ public class NestedEnumArgument { FIRST } - @interface Anno { + public @interface Anno { E value(); } diff --git a/compiler/testData/loadJava/compiledJava/annotations/NestedEnumArgument.txt b/compiler/testData/loadJava/compiledJava/annotations/NestedEnumArgument.txt index be2df6427cc..835f24604e6 100644 --- a/compiler/testData/loadJava/compiledJava/annotations/NestedEnumArgument.txt +++ b/compiler/testData/loadJava/compiledJava/annotations/NestedEnumArgument.txt @@ -4,8 +4,8 @@ public open class NestedEnumArgument { public constructor NestedEnumArgument() test.NestedEnumArgument.Anno(value = E.FIRST: test.NestedEnumArgument.E) public/*package*/ open fun foo(): kotlin.Unit - public/*package*/ final annotation class Anno : kotlin.Annotation { - public/*package*/ constructor Anno(/*0*/ value: test.NestedEnumArgument.E) + public final annotation class Anno : kotlin.Annotation { + public constructor Anno(/*0*/ value: test.NestedEnumArgument.E) public abstract fun value(): test.NestedEnumArgument.E } 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 new file mode 100644 index 00000000000..78843c3d9c0 --- /dev/null +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaAnnotationOwner.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2015 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.kotlin.load.java.structure.reflect + +import org.jetbrains.kotlin.load.java.structure.JavaAnnotationOwner +import org.jetbrains.kotlin.name.FqName +import java.lang.reflect.AnnotatedElement + +public trait ReflectJavaAnnotationOwner : JavaAnnotationOwner { + val element: AnnotatedElement + + override fun getAnnotations() = getAnnotations(element.getDeclaredAnnotations()) + + override fun findAnnotation(fqName: FqName) = findAnnotation(element.getDeclaredAnnotations(), fqName) +} + +fun getAnnotations(annotations: Array): List { + return annotations.map { ReflectJavaAnnotation(it) } +} + +fun findAnnotation(annotations: Array, fqName: FqName): ReflectJavaAnnotation? { + return annotations.firstOrNull { it.annotationType().fqName == fqName }?.let { ReflectJavaAnnotation(it) } +} diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaClass.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaClass.kt index 63481553395..8944c7c6454 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaClass.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaClass.kt @@ -16,15 +16,20 @@ package org.jetbrains.kotlin.load.java.structure.reflect -import org.jetbrains.kotlin.load.java.structure.* -import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.load.java.structure.JavaClass +import org.jetbrains.kotlin.load.java.structure.JavaClassifierType +import org.jetbrains.kotlin.load.java.structure.JavaType +import org.jetbrains.kotlin.load.java.structure.JavaTypeSubstitutor import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.utils.emptyOrSingletonList +import java.lang.reflect.AnnotatedElement import java.lang.reflect.Method import java.lang.reflect.Modifier import java.util.Arrays -public class ReflectJavaClass(private val klass: Class<*>) : ReflectJavaElement(), JavaClass { +public class ReflectJavaClass(private val klass: Class<*>) : ReflectJavaElement(), ReflectJavaAnnotationOwner, JavaClass { + override val element: AnnotatedElement get() = klass + override fun getInnerClasses() = klass.getDeclaredClasses() .stream() .filterNot { @@ -86,17 +91,6 @@ public class ReflectJavaClass(private val klass: Class<*>) : ReflectJavaElement( override fun getName(): Name = Name.identifier(klass.getSimpleName()) - override fun getAnnotations() = klass.getDeclaredAnnotations().map { ReflectJavaAnnotation(it) } - - override fun findAnnotation(fqName: FqName): JavaAnnotation? { - for (annotation in klass.getDeclaredAnnotations()) { - if (annotation.annotationType().fqName == fqName) { - return ReflectJavaAnnotation(annotation) - } - } - return null - } - override fun getTypeParameters() = klass.getTypeParameters().map { ReflectJavaTypeParameter(it) } override fun isInterface() = klass.isInterface() diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaConstructor.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaConstructor.kt index f603bb93017..544d4343b05 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaConstructor.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaConstructor.kt @@ -16,40 +16,25 @@ package org.jetbrains.kotlin.load.java.structure.reflect -import org.jetbrains.kotlin.load.java.structure.JavaAnnotation import org.jetbrains.kotlin.load.java.structure.JavaConstructor import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter import org.jetbrains.kotlin.load.java.structure.JavaValueParameter -import org.jetbrains.kotlin.name.FqName import java.lang.reflect.Constructor import java.lang.reflect.Modifier import java.util.Arrays -public class ReflectJavaConstructor(constructor: Constructor<*>) : ReflectJavaMember(constructor), JavaConstructor { - private val constructor: Constructor<*> - get() = member as Constructor<*> - - override fun getAnnotations(): Collection { - // TODO - return listOf() - } - - override fun findAnnotation(fqName: FqName): JavaAnnotation? { - // TODO - return null - } - +public class ReflectJavaConstructor(override val member: Constructor<*>) : ReflectJavaMember(), JavaConstructor { override fun getValueParameters(): List = getValueParameters( - dropSynthetic(constructor.getGenericParameterTypes()), - dropSynthetic(constructor.getParameterAnnotations()), - constructor.isVarArgs() + dropSynthetic(member.getGenericParameterTypes()), + dropSynthetic(member.getParameterAnnotations()), + member.isVarArgs() ) // Constructors of inner classes have one additional synthetic parameter // TODO: test this code with annotations on constructor parameters of enums and inner classes private inline fun dropSynthetic(array: Array): Array { - val klass = constructor.getDeclaringClass() + val klass = member.getDeclaringClass() return if (klass.getDeclaringClass() != null && !Modifier.isStatic(klass.getModifiers())) { Arrays.copyOfRange(array, 1, array.size()) } diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaField.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaField.kt index a03fa3bd8b4..553e816279f 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaField.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaField.kt @@ -16,26 +16,11 @@ package org.jetbrains.kotlin.load.java.structure.reflect -import java.lang.reflect.Field import org.jetbrains.kotlin.load.java.structure.JavaField -import org.jetbrains.kotlin.load.java.structure.JavaAnnotation -import org.jetbrains.kotlin.name.FqName +import java.lang.reflect.Field -public class ReflectJavaField(field: Field) : ReflectJavaMember(field), JavaField { - val field: Field - get() = member as Field +public class ReflectJavaField(override val member: Field) : ReflectJavaMember(), JavaField { + override fun isEnumEntry() = member.isEnumConstant() - override fun getAnnotations(): Collection { - // TODO - return listOf() - } - - override fun findAnnotation(fqName: FqName): JavaAnnotation? { - // TODO - return null - } - - override fun isEnumEntry() = field.isEnumConstant() - - override fun getType() = ReflectJavaType.create(field.getGenericType()!!) + override fun getType() = ReflectJavaType.create(member.getGenericType()) } diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaMember.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaMember.kt index bfac1f6b8c4..b8316aba2e9 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaMember.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaMember.kt @@ -20,12 +20,17 @@ import org.jetbrains.kotlin.load.java.structure.JavaMember import org.jetbrains.kotlin.load.java.structure.JavaValueParameter import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames +import java.lang.reflect.AnnotatedElement import java.lang.reflect.Member import java.lang.reflect.Modifier import java.lang.reflect.Type import java.util.ArrayList -public abstract class ReflectJavaMember(protected val member: Member) : ReflectJavaElement(), JavaMember { +public abstract class ReflectJavaMember : ReflectJavaElement(), ReflectJavaAnnotationOwner, JavaMember { + protected abstract val member: Member + + override val element: AnnotatedElement get() = member as AnnotatedElement + override fun getName() = member.getName()?.let { Name.identifier(it) } ?: SpecialNames.NO_NAME_PROVIDED override fun getContainingClass() = ReflectJavaClass(member.getDeclaringClass()) diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaMethod.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaMethod.kt index 68891b0e4ca..e45135ce817 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaMethod.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaMethod.kt @@ -16,36 +16,17 @@ package org.jetbrains.kotlin.load.java.structure.reflect -import org.jetbrains.kotlin.load.java.structure.JavaAnnotation import org.jetbrains.kotlin.load.java.structure.JavaMethod -import org.jetbrains.kotlin.load.java.structure.JavaType import org.jetbrains.kotlin.load.java.structure.JavaValueParameter -import org.jetbrains.kotlin.name.FqName import java.lang.reflect.Method -public class ReflectJavaMethod(method: Method) : ReflectJavaMember(method), JavaMethod { - private val method: Method - get() = member as Method - - override fun getAnnotations(): Collection { - // TODO - return listOf() - } - - override fun findAnnotation(fqName: FqName): JavaAnnotation? { - // TODO - return null - } - +public class ReflectJavaMethod(override val member: Method) : ReflectJavaMember(), JavaMethod { override fun getValueParameters(): List = - getValueParameters(method.getGenericParameterTypes(), method.getParameterAnnotations(), method.isVarArgs()) + getValueParameters(member.getGenericParameterTypes(), member.getParameterAnnotations(), member.isVarArgs()) - override fun getReturnType(): JavaType? { - // TODO - return ReflectJavaType.create(method.getGenericReturnType()!!) - } + override fun getReturnType() = ReflectJavaType.create(member.getGenericReturnType()) - override fun hasAnnotationParameterDefaultValue() = method.getDefaultValue() != null + override fun hasAnnotationParameterDefaultValue() = member.getDefaultValue() != null - override fun getTypeParameters() = method.getTypeParameters().map { ReflectJavaTypeParameter(it) } + override fun getTypeParameters() = member.getTypeParameters().map { ReflectJavaTypeParameter(it) } } 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 1a01a4cb999..6cae4b3cb82 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 @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.load.java.structure.reflect import org.jetbrains.kotlin.load.java.structure.JavaValueParameter -import org.jetbrains.kotlin.load.java.structure.JavaAnnotation import org.jetbrains.kotlin.name.FqName public class ReflectJavaValueParameter( @@ -25,17 +24,11 @@ public class ReflectJavaValueParameter( private val annotations: Array, private val isVararg: Boolean ) : ReflectJavaElement(), JavaValueParameter { - override fun getAnnotations(): Collection { - // TODO - return listOf() - } + override fun getAnnotations() = getAnnotations(annotations) - override fun findAnnotation(fqName: FqName): JavaAnnotation? { - // TODO - return null - } + override fun findAnnotation(fqName: FqName) = findAnnotation(annotations, fqName) override fun getName() = null // TODO: use ParameterNames on JDK 8 override fun getType() = returnType override fun isVararg() = isVararg -} \ No newline at end of file +}