Java: load annotations methods as properties

This commit is contained in:
Denis Zharkov
2015-04-20 18:48:10 +03:00
parent a0502d99f4
commit 93bbd2cbbc
2 changed files with 52 additions and 20 deletions
@@ -21,22 +21,23 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.load.java.components.TypeUsage
import org.jetbrains.kotlin.descriptors.impl.ConstructorDescriptorImpl
import java.util.Collections
import org.jetbrains.kotlin.utils.*
import java.util.ArrayList
import org.jetbrains.kotlin.load.java.lazy.types.toAttributes
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.*
import org.jetbrains.kotlin.load.java.lazy.resolveAnnotations
import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.java.descriptors.JavaConstructorDescriptor
import org.jetbrains.kotlin.load.java.components.DescriptorResolverUtils
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor
import org.jetbrains.kotlin.load.java.lazy.child
import org.jetbrains.kotlin.resolve.DescriptorFactory
import org.jetbrains.kotlin.types.JetType
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import java.util.LinkedHashSet
@@ -78,12 +79,36 @@ public class LazyJavaClassMemberScope(
}
override fun computeNonDeclaredProperties(name: Name, result: MutableCollection<PropertyDescriptor>) {
if (jClass.isAnnotationType()) {
computeAnnotationProperties(name, result)
}
val propertiesFromSupertypes = getPropertiesFromSupertypes(name, getContainingDeclaration())
result.addAll(DescriptorResolverUtils.resolveOverrides(name, propertiesFromSupertypes, result, getContainingDeclaration(),
c.errorReporter))
}
private fun computeAnnotationProperties(name: Name, result: MutableCollection<PropertyDescriptor>) {
val method = memberIndex().findMethodsByName(name).singleOrNull() ?: return
val annotations = c.resolveAnnotations(method)
val propertyDescriptor = JavaPropertyDescriptor(
getContainingDeclaration(), annotations, method.getVisibility(),
/* isVar = */ false, method.getName(), c.sourceElementFactory.source(method)
)
// default getter is necessary because there is no real field in annotation
val getter = DescriptorFactory.createDefaultGetter(propertyDescriptor)
propertyDescriptor.initialize(getter, null)
val returnType = computeMethodReturnType(method, annotations, c.child(propertyDescriptor, method))
propertyDescriptor.setType(returnType, listOf(), getDispatchReceiverParameter(), null : JetType?)
getter.initialize(returnType)
result.add(propertyDescriptor)
}
private fun getPropertiesFromSupertypes(name: Name, descriptor: ClassDescriptor): Set<PropertyDescriptor> {
return descriptor.getTypeConstructor().getSupertypes().flatMap {
it.getMemberScope().getProperties(name).map { p -> p as PropertyDescriptor }
@@ -295,13 +320,16 @@ public class LazyJavaClassMemberScope(
override fun getClassNames(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<Name>
= nestedClassIndex().keySet() + enumEntryIndex().keySet()
override fun getPropertyNames(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<Name> =
memberIndex().getAllFieldNames() +
getContainingDeclaration().getTypeConstructor().getSupertypes().flatMapTo(LinkedHashSet<Name>()) { supertype ->
supertype.getMemberScope().getDescriptors(kindFilter, nameFilter).map { variable ->
variable.getName()
}
override fun getPropertyNames(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<Name> {
if (jClass.isAnnotationType()) return memberIndex().getMethodNames(nameFilter)
return memberIndex().getAllFieldNames() +
getContainingDeclaration().getTypeConstructor().getSupertypes().flatMapTo(LinkedHashSet<Name>()) { supertype ->
supertype.getMemberScope().getDescriptors(kindFilter, nameFilter).map { variable ->
variable.getName()
}
}
}
// TODO
override fun getImplicitReceiversHierarchy(): List<ReceiverParameterDescriptor> = listOf()
@@ -119,17 +119,7 @@ public abstract class LazyJavaMemberScope(
val methodTypeParameters = method.getTypeParameters().map { p -> c.typeParameterResolver.resolveTypeParameter(p)!! }
val valueParameters = resolveValueParameters(c, functionDescriptorImpl, method.getValueParameters())
val annotationMethod = method.getContainingClass().isAnnotationType()
val returnTypeAttrs = LazyJavaTypeAttributes(
c, method, TypeUsage.MEMBER_SIGNATURE_COVARIANT, annotations,
allowFlexible = !annotationMethod,
isForAnnotationParameter = annotationMethod
)
val returnJavaType = method.getReturnType() ?: throw IllegalStateException("Constructor passed as method: $method")
// Annotation arguments are never null in Java
val returnType = c.typeResolver.transformJavaType(returnJavaType, returnTypeAttrs).let {
if (annotationMethod) TypeUtils.makeNotNullable(it) else it
}
val returnType = computeMethodReturnType(method, annotations, c)
val (effectiveSignature, superFunctions, signatureErrors) = resolveMethodSignature(method, methodTypeParameters, returnType, valueParameters)
@@ -155,6 +145,20 @@ public abstract class LazyJavaMemberScope(
return functionDescriptorImpl
}
protected fun computeMethodReturnType(method: JavaMethod, annotations: Annotations, c: LazyJavaResolverContext): JetType {
val annotationMethod = method.getContainingClass().isAnnotationType()
val returnTypeAttrs = LazyJavaTypeAttributes(
c, method, TypeUsage.MEMBER_SIGNATURE_COVARIANT, annotations,
allowFlexible = !annotationMethod,
isForAnnotationParameter = annotationMethod
)
val returnJavaType = method.getReturnType() ?: throw IllegalStateException("Constructor passed as method: $method")
// Annotation arguments are never null in Java
return c.typeResolver.transformJavaType(returnJavaType, returnTypeAttrs).let {
if (annotationMethod) TypeUtils.makeNotNullable(it) else it
}
}
protected class ResolvedValueParameters(val descriptors: List<ValueParameterDescriptor>, val hasSynthesizedNames: Boolean)
protected fun resolveValueParameters(