Add SourceElement to AnnotationDescriptor

Use KotlinSourceElement in the compiler for annotations resolved from PSI,
introduce ReflectAnnotationSource for reflection
This commit is contained in:
Alexander Udalov
2015-07-24 02:07:42 +03:00
parent ef4a5e78ed
commit d0562b7b90
17 changed files with 110 additions and 58 deletions
@@ -18,29 +18,22 @@ package org.jetbrains.kotlin.load.java.components
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
import org.jetbrains.kotlin.load.java.lazy.descriptors.resolveAnnotation
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
import org.jetbrains.kotlin.load.java.structure.JavaAnnotationArgument
import org.jetbrains.kotlin.load.java.structure.JavaArrayAnnotationArgument
import org.jetbrains.kotlin.load.java.structure.JavaEnumValueAnnotationArgument
import org.jetbrains.kotlin.resolve.constants.ArrayValue
import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.EnumValue
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.resolve.constants.*
import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory
import org.jetbrains.kotlin.types.ErrorUtils
import java.lang.annotation.Retention
import java.lang.annotation.Target
import java.util.*
import java.util.EnumSet
public object JavaAnnotationMapper {
@@ -93,11 +86,16 @@ public object JavaAnnotationMapper {
}
abstract class AbstractJavaAnnotationDescriptor(
c: LazyJavaResolverContext,
annotation: JavaAnnotation?,
private val kotlinAnnotationClassDescriptor: ClassDescriptor
): AnnotationDescriptor {
private val source = annotation?.let { c.sourceElementFactory.source(it) } ?: SourceElement.NO_SOURCE
override fun getType() = kotlinAnnotationClassDescriptor.defaultType
override fun getSource() = source
protected val valueParameters: List<ValueParameterDescriptor>
get() = kotlinAnnotationClassDescriptor.constructors.single().valueParameters
@@ -107,7 +105,7 @@ abstract class AbstractJavaAnnotationDescriptor(
class JavaDeprecatedAnnotationDescriptor(
annotation: JavaAnnotation,
c: LazyJavaResolverContext
): AbstractJavaAnnotationDescriptor(annotation, c.module.builtIns.deprecatedAnnotation) {
): AbstractJavaAnnotationDescriptor(c, annotation, c.module.builtIns.deprecatedAnnotation) {
private val valueArguments = c.storageManager.createLazyValue {
val parameterDescriptor = valueParameters.firstOrNull {
@@ -123,7 +121,7 @@ class JavaRetentionRepeatableAnnotationDescriptor(
retentionAnnotation: JavaAnnotation?,
repeatable: Boolean,
c: LazyJavaResolverContext
): AbstractJavaAnnotationDescriptor(retentionAnnotation, c.module.builtIns.annotationAnnotation) {
): AbstractJavaAnnotationDescriptor(c, retentionAnnotation, c.module.builtIns.annotationAnnotation) {
private val valueArguments = c.storageManager.createLazyValue {
val retentionArgument = when (firstArgument) {
@@ -147,7 +145,7 @@ class JavaRetentionRepeatableAnnotationDescriptor(
class JavaTargetAnnotationDescriptor(
annotation: JavaAnnotation,
c: LazyJavaResolverContext
): AbstractJavaAnnotationDescriptor(annotation, c.module.builtIns.targetAnnotation) {
): AbstractJavaAnnotationDescriptor(c, annotation, c.module.builtIns.targetAnnotation) {
private val valueArguments = c.storageManager.createLazyValue {
val targetArgument = when (firstArgument) {
@@ -60,6 +60,8 @@ class LazyJavaAnnotationDescriptor(
annotationClass?.getDefaultType() ?: ErrorUtils.createErrorType(fqName.asString())
}
private val source = c.sourceElementFactory.source(javaAnnotation)
private val factory = ConstantValueFactory(c.module.builtIns)
override fun getType(): JetType = type()
@@ -70,6 +72,8 @@ class LazyJavaAnnotationDescriptor(
override fun getAllValueArguments() = allValueArguments()
override fun getSource() = source
private fun computeValueArguments(): Map<ValueParameterDescriptor, ConstantValue<*>> {
val constructors = getAnnotationClass().getConstructors()
if (constructors.isEmpty()) return mapOf()
@@ -18,19 +18,16 @@ package org.jetbrains.kotlin.load.java.typeEnhacement
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.annotations.CompositeAnnotations
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.java.typeEnhacement.JavaTypeQualifiers
import org.jetbrains.kotlin.load.java.typeEnhacement.MutabilityQualifier.MUTABLE
import org.jetbrains.kotlin.load.java.typeEnhacement.MutabilityQualifier.READ_ONLY
import org.jetbrains.kotlin.load.java.typeEnhacement.NullabilityQualifier.NOT_NULL
import org.jetbrains.kotlin.load.java.typeEnhacement.NullabilityQualifier.NULLABLE
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
import org.jetbrains.kotlin.types.*
// The index in the lambda is the position of the type component:
@@ -177,8 +174,9 @@ private class EnhancedTypeAnnotations(private val fqNameToMatch: FqName) : Annot
}
private object EnhancedTypeAnnotationDescriptor : AnnotationDescriptor {
private fun throwError() = error("No methods should be called on this descriptor. Only it's presence matters")
private fun throwError() = error("No methods should be called on this descriptor. Only its presence matters")
override fun getType() = throwError()
override fun getAllValueArguments() = throwError()
override fun getSource() = throwError()
override fun toString() = "[EnhancedType]"
}
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.load.kotlin
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
@@ -47,6 +48,7 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C
protected abstract fun loadAnnotation(
annotationClassId: ClassId,
source: SourceElement,
result: MutableList<A>
): KotlinJvmBinaryClass.AnnotationArgumentVisitor?
@@ -54,11 +56,12 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C
private fun loadAnnotationIfNotSpecial(
annotationClassId: ClassId,
source: SourceElement,
result: MutableList<A>
): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
if (JvmAnnotationNames.isSpecialAnnotation(annotationClassId, true)) return null
return loadAnnotation(annotationClassId, result)
return loadAnnotation(annotationClassId, source, result)
}
override fun loadClassAnnotations(classProto: ProtoBuf.Class, nameResolver: NameResolver): List<A> {
@@ -74,8 +77,8 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C
val result = ArrayList<A>(1)
kotlinClass.loadClassAnnotations(object : KotlinJvmBinaryClass.AnnotationVisitor {
override fun visitAnnotation(classId: ClassId): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
return loadAnnotationIfNotSpecial(classId, result)
override fun visitAnnotation(classId: ClassId, source: SourceElement): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
return loadAnnotationIfNotSpecial(classId, source, result)
}
override fun visitEnd() {
@@ -220,22 +223,24 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C
inner class AnnotationVisitorForMethod(signature: MemberSignature) : MemberAnnotationVisitor(signature), KotlinJvmBinaryClass.MethodAnnotationVisitor {
override fun visitParameterAnnotation(index: Int, classId: ClassId): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
override fun visitParameterAnnotation(
index: Int, classId: ClassId, source: SourceElement
): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
val paramSignature = MemberSignature.fromMethodSignatureAndParameterIndex(signature, index)
var result = memberAnnotations[paramSignature]
if (result == null) {
result = ArrayList<A>()
memberAnnotations[paramSignature] = result
}
return loadAnnotationIfNotSpecial(classId, result)
return loadAnnotationIfNotSpecial(classId, source, result)
}
}
open inner class MemberAnnotationVisitor(protected val signature: MemberSignature) : KotlinJvmBinaryClass.AnnotationVisitor {
private val result = ArrayList<A>()
override fun visitAnnotation(classId: ClassId): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
return loadAnnotationIfNotSpecial(classId, result)
override fun visitAnnotation(classId: ClassId, source: SourceElement): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
return loadAnnotationIfNotSpecial(classId, source, result)
}
override fun visitEnd() {
@@ -16,10 +16,7 @@
package org.jetbrains.kotlin.load.kotlin
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
import org.jetbrains.kotlin.load.java.components.DescriptorResolverUtils
@@ -86,6 +83,7 @@ public class BinaryClassAnnotationAndConstantLoaderImpl(
override fun loadAnnotation(
annotationClassId: ClassId,
source: SourceElement,
result: MutableList<AnnotationDescriptor>
): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
val annotationClass = resolveClass(annotationClassId)
@@ -127,7 +125,7 @@ public class BinaryClassAnnotationAndConstantLoaderImpl(
override fun visitAnnotation(name: Name, classId: ClassId): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
val list = ArrayList<AnnotationDescriptor>()
val visitor = loadAnnotation(classId, list)!!
val visitor = loadAnnotation(classId, SourceElement.NO_SOURCE, list)!!
return object: KotlinJvmBinaryClass.AnnotationArgumentVisitor by visitor {
override fun visitEnd() {
visitor.visitEnd()
@@ -149,7 +147,7 @@ public class BinaryClassAnnotationAndConstantLoaderImpl(
}
override fun visitEnd() {
result.add(AnnotationDescriptorImpl(annotationClass.getDefaultType(), arguments))
result.add(AnnotationDescriptorImpl(annotationClass.getDefaultType(), arguments, source))
}
private fun createConstant(name: Name?, value: Any?): ConstantValue<*> {
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.load.kotlin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.SourceElement;
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader;
import org.jetbrains.kotlin.name.ClassId;
import org.jetbrains.kotlin.name.Name;
@@ -51,14 +52,14 @@ public interface KotlinJvmBinaryClass {
interface AnnotationVisitor {
@Nullable
AnnotationArgumentVisitor visitAnnotation(@NotNull ClassId classId);
AnnotationArgumentVisitor visitAnnotation(@NotNull ClassId classId, @NotNull SourceElement source);
void visitEnd();
}
interface MethodAnnotationVisitor extends AnnotationVisitor {
@Nullable
AnnotationArgumentVisitor visitParameterAnnotation(int index, @NotNull ClassId classId);
AnnotationArgumentVisitor visitParameterAnnotation(int index, @NotNull ClassId classId, @NotNull SourceElement source);
}
interface AnnotationArgumentVisitor {
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.load.kotlin.header;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.SourceElement;
import org.jetbrains.kotlin.load.java.AbiVersionUtil;
import org.jetbrains.kotlin.name.ClassId;
import org.jetbrains.kotlin.name.Name;
@@ -88,7 +89,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
@Nullable
@Override
public AnnotationArgumentVisitor visitAnnotation(@NotNull ClassId classId) {
public AnnotationArgumentVisitor visitAnnotation(@NotNull ClassId classId, @NotNull SourceElement source) {
if (headerKind != null) {
// Ignore all Kotlin annotations except the first found
return null;