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.name.Name
import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext 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.load.java.components.TypeUsage
import org.jetbrains.kotlin.descriptors.impl.ConstructorDescriptorImpl
import java.util.Collections import java.util.Collections
import org.jetbrains.kotlin.utils.* import org.jetbrains.kotlin.utils.*
import java.util.ArrayList import java.util.ArrayList
import org.jetbrains.kotlin.load.java.lazy.types.toAttributes import org.jetbrains.kotlin.load.java.lazy.types.toAttributes
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.descriptors.annotations.Annotations 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.lazy.resolveAnnotations
import org.jetbrains.kotlin.load.java.JavaVisibilities import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.java.descriptors.JavaConstructorDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaConstructorDescriptor
import org.jetbrains.kotlin.load.java.components.DescriptorResolverUtils 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.types.JetType
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import java.util.LinkedHashSet import java.util.LinkedHashSet
@@ -78,12 +79,36 @@ public class LazyJavaClassMemberScope(
} }
override fun computeNonDeclaredProperties(name: Name, result: MutableCollection<PropertyDescriptor>) { override fun computeNonDeclaredProperties(name: Name, result: MutableCollection<PropertyDescriptor>) {
if (jClass.isAnnotationType()) {
computeAnnotationProperties(name, result)
}
val propertiesFromSupertypes = getPropertiesFromSupertypes(name, getContainingDeclaration()) val propertiesFromSupertypes = getPropertiesFromSupertypes(name, getContainingDeclaration())
result.addAll(DescriptorResolverUtils.resolveOverrides(name, propertiesFromSupertypes, result, getContainingDeclaration(), result.addAll(DescriptorResolverUtils.resolveOverrides(name, propertiesFromSupertypes, result, getContainingDeclaration(),
c.errorReporter)) 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> { private fun getPropertiesFromSupertypes(name: Name, descriptor: ClassDescriptor): Set<PropertyDescriptor> {
return descriptor.getTypeConstructor().getSupertypes().flatMap { return descriptor.getTypeConstructor().getSupertypes().flatMap {
it.getMemberScope().getProperties(name).map { p -> p as PropertyDescriptor } 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> override fun getClassNames(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<Name>
= nestedClassIndex().keySet() + enumEntryIndex().keySet() = nestedClassIndex().keySet() + enumEntryIndex().keySet()
override fun getPropertyNames(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<Name> = override fun getPropertyNames(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<Name> {
memberIndex().getAllFieldNames() + if (jClass.isAnnotationType()) return memberIndex().getMethodNames(nameFilter)
getContainingDeclaration().getTypeConstructor().getSupertypes().flatMapTo(LinkedHashSet<Name>()) { supertype ->
supertype.getMemberScope().getDescriptors(kindFilter, nameFilter).map { variable -> return memberIndex().getAllFieldNames() +
variable.getName() getContainingDeclaration().getTypeConstructor().getSupertypes().flatMapTo(LinkedHashSet<Name>()) { supertype ->
} supertype.getMemberScope().getDescriptors(kindFilter, nameFilter).map { variable ->
variable.getName()
} }
}
}
// TODO // TODO
override fun getImplicitReceiversHierarchy(): List<ReceiverParameterDescriptor> = listOf() 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 methodTypeParameters = method.getTypeParameters().map { p -> c.typeParameterResolver.resolveTypeParameter(p)!! }
val valueParameters = resolveValueParameters(c, functionDescriptorImpl, method.getValueParameters()) val valueParameters = resolveValueParameters(c, functionDescriptorImpl, method.getValueParameters())
val annotationMethod = method.getContainingClass().isAnnotationType() val returnType = computeMethodReturnType(method, annotations, c)
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 (effectiveSignature, superFunctions, signatureErrors) = resolveMethodSignature(method, methodTypeParameters, returnType, valueParameters) val (effectiveSignature, superFunctions, signatureErrors) = resolveMethodSignature(method, methodTypeParameters, returnType, valueParameters)
@@ -155,6 +145,20 @@ public abstract class LazyJavaMemberScope(
return functionDescriptorImpl 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 class ResolvedValueParameters(val descriptors: List<ValueParameterDescriptor>, val hasSynthesizedNames: Boolean)
protected fun resolveValueParameters( protected fun resolveValueParameters(