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
This commit is contained in:
Alexander Udalov
2015-01-20 20:59:49 +03:00
parent c90f11b7e6
commit a14b301f31
9 changed files with 71 additions and 91 deletions
@@ -5,7 +5,7 @@ public class NestedEnumArgument {
FIRST
}
@interface Anno {
public @interface Anno {
E value();
}
@@ -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
}
@@ -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<Annotation>): List<ReflectJavaAnnotation> {
return annotations.map { ReflectJavaAnnotation(it) }
}
fun findAnnotation(annotations: Array<Annotation>, fqName: FqName): ReflectJavaAnnotation? {
return annotations.firstOrNull { it.annotationType().fqName == fqName }?.let { ReflectJavaAnnotation(it) }
}
@@ -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()
@@ -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<JavaAnnotation> {
// 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<JavaValueParameter> =
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 <reified T> dropSynthetic(array: Array<T>): Array<T> {
val klass = constructor.getDeclaringClass()
val klass = member.getDeclaringClass()
return if (klass.getDeclaringClass() != null && !Modifier.isStatic(klass.getModifiers())) {
Arrays.copyOfRange(array, 1, array.size())
}
@@ -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<JavaAnnotation> {
// 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())
}
@@ -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())
@@ -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<JavaAnnotation> {
// 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<JavaValueParameter> =
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) }
}
@@ -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<Annotation>,
private val isVararg: Boolean
) : ReflectJavaElement(), JavaValueParameter {
override fun getAnnotations(): Collection<JavaAnnotation> {
// 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
}
}