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 FIRST
} }
@interface Anno { public @interface Anno {
E value(); E value();
} }
@@ -4,8 +4,8 @@ public open class NestedEnumArgument {
public constructor NestedEnumArgument() public constructor NestedEnumArgument()
test.NestedEnumArgument.Anno(value = E.FIRST: test.NestedEnumArgument.E) public/*package*/ open fun foo(): kotlin.Unit 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 final annotation class Anno : kotlin.Annotation {
public/*package*/ constructor Anno(/*0*/ value: test.NestedEnumArgument.E) public constructor Anno(/*0*/ value: test.NestedEnumArgument.E)
public abstract fun 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 package org.jetbrains.kotlin.load.java.structure.reflect
import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.name.FqName 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.name.Name
import org.jetbrains.kotlin.utils.emptyOrSingletonList import org.jetbrains.kotlin.utils.emptyOrSingletonList
import java.lang.reflect.AnnotatedElement
import java.lang.reflect.Method import java.lang.reflect.Method
import java.lang.reflect.Modifier import java.lang.reflect.Modifier
import java.util.Arrays 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() override fun getInnerClasses() = klass.getDeclaredClasses()
.stream() .stream()
.filterNot { .filterNot {
@@ -86,17 +91,6 @@ public class ReflectJavaClass(private val klass: Class<*>) : ReflectJavaElement(
override fun getName(): Name = Name.identifier(klass.getSimpleName()) 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 getTypeParameters() = klass.getTypeParameters().map { ReflectJavaTypeParameter(it) }
override fun isInterface() = klass.isInterface() override fun isInterface() = klass.isInterface()
@@ -16,40 +16,25 @@
package org.jetbrains.kotlin.load.java.structure.reflect 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.JavaConstructor
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
import org.jetbrains.kotlin.load.java.structure.JavaValueParameter import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
import org.jetbrains.kotlin.name.FqName
import java.lang.reflect.Constructor import java.lang.reflect.Constructor
import java.lang.reflect.Modifier import java.lang.reflect.Modifier
import java.util.Arrays import java.util.Arrays
public class ReflectJavaConstructor(constructor: Constructor<*>) : ReflectJavaMember(constructor), JavaConstructor { public class ReflectJavaConstructor(override val member: Constructor<*>) : ReflectJavaMember(), 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
}
override fun getValueParameters(): List<JavaValueParameter> = override fun getValueParameters(): List<JavaValueParameter> =
getValueParameters( getValueParameters(
dropSynthetic(constructor.getGenericParameterTypes()), dropSynthetic(member.getGenericParameterTypes()),
dropSynthetic(constructor.getParameterAnnotations()), dropSynthetic(member.getParameterAnnotations()),
constructor.isVarArgs() member.isVarArgs()
) )
// Constructors of inner classes have one additional synthetic parameter // Constructors of inner classes have one additional synthetic parameter
// TODO: test this code with annotations on constructor parameters of enums and inner classes // 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> { 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())) { return if (klass.getDeclaringClass() != null && !Modifier.isStatic(klass.getModifiers())) {
Arrays.copyOfRange(array, 1, array.size()) Arrays.copyOfRange(array, 1, array.size())
} }
@@ -16,26 +16,11 @@
package org.jetbrains.kotlin.load.java.structure.reflect 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.JavaField
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation import java.lang.reflect.Field
import org.jetbrains.kotlin.name.FqName
public class ReflectJavaField(field: Field) : ReflectJavaMember(field), JavaField { public class ReflectJavaField(override val member: Field) : ReflectJavaMember(), JavaField {
val field: Field override fun isEnumEntry() = member.isEnumConstant()
get() = member as Field
override fun getAnnotations(): Collection<JavaAnnotation> { override fun getType() = ReflectJavaType.create(member.getGenericType())
// TODO
return listOf()
}
override fun findAnnotation(fqName: FqName): JavaAnnotation? {
// TODO
return null
}
override fun isEnumEntry() = field.isEnumConstant()
override fun getType() = ReflectJavaType.create(field.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.load.java.structure.JavaValueParameter
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.name.SpecialNames
import java.lang.reflect.AnnotatedElement
import java.lang.reflect.Member import java.lang.reflect.Member
import java.lang.reflect.Modifier import java.lang.reflect.Modifier
import java.lang.reflect.Type import java.lang.reflect.Type
import java.util.ArrayList 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 getName() = member.getName()?.let { Name.identifier(it) } ?: SpecialNames.NO_NAME_PROVIDED
override fun getContainingClass() = ReflectJavaClass(member.getDeclaringClass()) override fun getContainingClass() = ReflectJavaClass(member.getDeclaringClass())
@@ -16,36 +16,17 @@
package org.jetbrains.kotlin.load.java.structure.reflect 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.JavaMethod
import org.jetbrains.kotlin.load.java.structure.JavaType
import org.jetbrains.kotlin.load.java.structure.JavaValueParameter import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
import org.jetbrains.kotlin.name.FqName
import java.lang.reflect.Method import java.lang.reflect.Method
public class ReflectJavaMethod(method: Method) : ReflectJavaMember(method), JavaMethod { public class ReflectJavaMethod(override val member: Method) : ReflectJavaMember(), 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
}
override fun getValueParameters(): List<JavaValueParameter> = override fun getValueParameters(): List<JavaValueParameter> =
getValueParameters(method.getGenericParameterTypes(), method.getParameterAnnotations(), method.isVarArgs()) getValueParameters(member.getGenericParameterTypes(), member.getParameterAnnotations(), member.isVarArgs())
override fun getReturnType(): JavaType? { override fun getReturnType() = ReflectJavaType.create(member.getGenericReturnType())
// TODO
return ReflectJavaType.create(method.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 package org.jetbrains.kotlin.load.java.structure.reflect
import org.jetbrains.kotlin.load.java.structure.JavaValueParameter import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
public class ReflectJavaValueParameter( public class ReflectJavaValueParameter(
@@ -25,17 +24,11 @@ public class ReflectJavaValueParameter(
private val annotations: Array<Annotation>, private val annotations: Array<Annotation>,
private val isVararg: Boolean private val isVararg: Boolean
) : ReflectJavaElement(), JavaValueParameter { ) : ReflectJavaElement(), JavaValueParameter {
override fun getAnnotations(): Collection<JavaAnnotation> { override fun getAnnotations() = getAnnotations(annotations)
// TODO
return listOf()
}
override fun findAnnotation(fqName: FqName): JavaAnnotation? { override fun findAnnotation(fqName: FqName) = findAnnotation(annotations, fqName)
// TODO
return null
}
override fun getName() = null // TODO: use ParameterNames on JDK 8 override fun getName() = null // TODO: use ParameterNames on JDK 8
override fun getType() = returnType override fun getType() = returnType
override fun isVararg() = isVararg override fun isVararg() = isVararg
} }