Do not use parameter descriptors in AnnotationDescriptorImpl

This commit is contained in:
Alexander Udalov
2017-07-04 16:46:27 +03:00
parent eb205f620c
commit f39106f75c
7 changed files with 42 additions and 64 deletions
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.isSubpackageOf
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.*
@@ -39,7 +38,6 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.constants.* import org.jetbrains.kotlin.resolve.constants.*
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
@@ -80,12 +78,12 @@ class ConstantExpressionEvaluator(
internal fun resolveAnnotationArguments( internal fun resolveAnnotationArguments(
resolvedCall: ResolvedCall<*>, resolvedCall: ResolvedCall<*>,
trace: BindingTrace trace: BindingTrace
): Map<ValueParameterDescriptor, ConstantValue<*>> { ): Map<Name, ConstantValue<*>> {
val arguments = HashMap<ValueParameterDescriptor, ConstantValue<*>>() val arguments = HashMap<Name, ConstantValue<*>>()
for ((parameterDescriptor, resolvedArgument) in resolvedCall.valueArguments.entries) { for ((parameterDescriptor, resolvedArgument) in resolvedCall.valueArguments.entries) {
val value = getAnnotationArgumentValue(trace, parameterDescriptor, resolvedArgument) val value = getAnnotationArgumentValue(trace, parameterDescriptor, resolvedArgument)
if (value != null) { if (value != null) {
arguments.put(parameterDescriptor, value) arguments.put(parameterDescriptor.name, value)
} }
} }
return arguments return arguments
@@ -89,16 +89,16 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
val annotationClass = resolveClass(annotationClassId) val annotationClass = resolveClass(annotationClassId)
return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor { return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor {
private val arguments = HashMap<ValueParameterDescriptor, ConstantValue<*>>() private val arguments = HashMap<Name, ConstantValue<*>>()
override fun visit(name: Name?, value: Any?) { override fun visit(name: Name?, value: Any?) {
if (name != null) { if (name != null) {
setArgumentValueByName(name, createConstant(name, value)) arguments[name] = createConstant(name, value)
} }
} }
override fun visitEnum(name: Name, enumClassId: ClassId, enumEntryName: Name) { override fun visitEnum(name: Name, enumClassId: ClassId, enumEntryName: Name) {
setArgumentValueByName(name, enumEntryValue(enumClassId, enumEntryName)) arguments[name] = enumEntryValue(enumClassId, enumEntryName)
} }
override fun visitArray(name: Name): AnnotationArrayArgumentVisitor? { override fun visitArray(name: Name): AnnotationArrayArgumentVisitor? {
@@ -116,7 +116,7 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
override fun visitEnd() { override fun visitEnd() {
val parameter = DescriptorResolverUtils.getAnnotationParameterByName(name, annotationClass) val parameter = DescriptorResolverUtils.getAnnotationParameterByName(name, annotationClass)
if (parameter != null) { if (parameter != null) {
arguments[parameter] = factory.createArrayValue(elements.compact(), parameter.type) arguments[name] = factory.createArrayValue(elements.compact(), parameter.type)
} }
} }
} }
@@ -128,7 +128,7 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
return object: KotlinJvmBinaryClass.AnnotationArgumentVisitor by visitor { return object: KotlinJvmBinaryClass.AnnotationArgumentVisitor by visitor {
override fun visitEnd() { override fun visitEnd() {
visitor.visitEnd() visitor.visitEnd()
setArgumentValueByName(name, AnnotationValue(list.single())) arguments[name] = AnnotationValue(list.single())
} }
} }
} }
@@ -153,13 +153,6 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
return factory.createConstantValue(value) ?: return factory.createConstantValue(value) ?:
factory.createErrorValue("Unsupported annotation argument: $name") factory.createErrorValue("Unsupported annotation argument: $name")
} }
private fun setArgumentValueByName(name: Name, argumentValue: ConstantValue<*>) {
val parameter = DescriptorResolverUtils.getAnnotationParameterByName(name, annotationClass)
if (parameter != null) {
arguments[parameter] = argumentValue
}
}
} }
} }
@@ -283,6 +283,7 @@ public abstract class KotlinBuiltIns {
public final FqName deprecated = fqName("Deprecated"); public final FqName deprecated = fqName("Deprecated");
public final FqName deprecationLevel = fqName("DeprecationLevel"); public final FqName deprecationLevel = fqName("DeprecationLevel");
public final FqName replaceWith = fqName("ReplaceWith");
public final FqName extensionFunctionType = fqName("ExtensionFunctionType"); public final FqName extensionFunctionType = fqName("ExtensionFunctionType");
public final FqName parameterName = fqName("ParameterName"); public final FqName parameterName = fqName("ParameterName");
public final FqName annotation = fqName("Annotation"); public final FqName annotation = fqName("Annotation");
@@ -168,8 +168,8 @@ fun getFunctionTypeArgumentProjections(
val nameValue = ConstantValueFactory(builtIns).createStringValue(name.asString()) val nameValue = ConstantValueFactory(builtIns).createStringValue(name.asString())
val parameterNameAnnotation = AnnotationDescriptorImpl( val parameterNameAnnotation = AnnotationDescriptorImpl(
annotationClass.defaultType, annotationClass.defaultType,
mapOf(annotationClass.unsubstitutedPrimaryConstructor!!.valueParameters.single() to nameValue), mapOf(Name.identifier("name") to nameValue),
org.jetbrains.kotlin.descriptors.SourceElement.NO_SOURCE SourceElement.NO_SOURCE
) )
type.replaceAnnotations(AnnotationsImpl(type.annotations + parameterNameAnnotation)) type.replaceAnnotations(AnnotationsImpl(type.annotations + parameterNameAnnotation))
} }
@@ -16,33 +16,29 @@
package org.jetbrains.kotlin.descriptors.annotations; package org.jetbrains.kotlin.descriptors.annotations;
import kotlin.collections.MapsKt;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.SourceElement; import org.jetbrains.kotlin.descriptors.SourceElement;
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.renderer.DescriptorRenderer; import org.jetbrains.kotlin.renderer.DescriptorRenderer;
import org.jetbrains.kotlin.resolve.constants.ConstantValue; import org.jetbrains.kotlin.resolve.constants.ConstantValue;
import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.KotlinType;
import java.util.Collections;
import java.util.Map; import java.util.Map;
public class AnnotationDescriptorImpl implements AnnotationDescriptor { public class AnnotationDescriptorImpl implements AnnotationDescriptor {
private final KotlinType annotationType; private final KotlinType annotationType;
private final Map<ValueParameterDescriptor, ConstantValue<?>> valueArguments; private final Map<Name, ConstantValue<?>> valueArguments;
private final SourceElement source; private final SourceElement source;
public AnnotationDescriptorImpl( public AnnotationDescriptorImpl(
@NotNull KotlinType annotationType, @NotNull KotlinType annotationType,
@NotNull Map<ValueParameterDescriptor, ConstantValue<?>> valueArguments, @NotNull Map<Name, ConstantValue<?>> valueArguments,
@NotNull SourceElement source @NotNull SourceElement source
) { ) {
this.annotationType = annotationType; this.annotationType = annotationType;
this.valueArguments = Collections.unmodifiableMap(valueArguments); this.valueArguments = valueArguments;
this.source = source; this.source = source;
} }
@@ -61,15 +57,7 @@ public class AnnotationDescriptorImpl implements AnnotationDescriptor {
@NotNull @NotNull
@Override @Override
public Map<Name, ConstantValue<?>> getAllValueArguments() { public Map<Name, ConstantValue<?>> getAllValueArguments() {
return MapsKt.mapKeys( return valueArguments;
valueArguments,
new Function1<Map.Entry<? extends ValueParameterDescriptor, ? extends ConstantValue<?>>, Name>() {
@Override
public Name invoke(Map.Entry<? extends ValueParameterDescriptor, ? extends ConstantValue<?>> entry) {
return entry.getKey().getName();
}
}
);
} }
@Override @Override
@@ -17,7 +17,10 @@
package org.jetbrains.kotlin.descriptors.annotations package org.jetbrains.kotlin.descriptors.annotations
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.MemberDescriptor
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -33,42 +36,37 @@ fun KotlinBuiltIns.createDeprecatedAnnotation(
replaceWith: String = "", replaceWith: String = "",
level: String = "WARNING" level: String = "WARNING"
): AnnotationDescriptor { ): AnnotationDescriptor {
val deprecatedAnnotation = deprecatedAnnotation val replaceWithAnnotation = AnnotationDescriptorImpl(
val parameters = deprecatedAnnotation.unsubstitutedPrimaryConstructor!!.valueParameters getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.replaceWith).defaultType,
mapOf(
REPLACE_WITH_EXPRESSION_NAME to StringValue(replaceWith, this),
REPLACE_WITH_IMPORTS_NAME to ArrayValue(emptyList(), getArrayType(Variance.INVARIANT, stringType), this)
),
SourceElement.NO_SOURCE
)
val replaceWithClass = getBuiltInClassByName(Name.identifier("ReplaceWith"))
val replaceWithParameters = replaceWithClass.unsubstitutedPrimaryConstructor!!.valueParameters
return AnnotationDescriptorImpl( return AnnotationDescriptorImpl(
deprecatedAnnotation.defaultType, deprecatedAnnotation.defaultType,
mapOf( mapOf(
parameters["message"] to StringValue(message, this), DEPRECATED_MESSAGE_NAME to StringValue(message, this),
parameters["replaceWith"] to AnnotationValue( DEPRECATED_REPLACE_WITH_NAME to AnnotationValue(replaceWithAnnotation),
AnnotationDescriptorImpl( DEPRECATED_LEVEL_NAME to EnumValue(getDeprecationLevelEnumEntry(level) ?: error("Deprecation level $level not found"))
replaceWithClass.defaultType,
mapOf(
replaceWithParameters["expression"] to StringValue(replaceWith, this),
replaceWithParameters["imports"] to ArrayValue(
emptyList(), getArrayType(Variance.INVARIANT, stringType), this)
),
SourceElement.NO_SOURCE
)
),
parameters["level"] to EnumValue(getDeprecationLevelEnumEntry(level) ?: error("Deprecation level $level not found"))
), ),
SourceElement.NO_SOURCE) SourceElement.NO_SOURCE
)
} }
private val DEPRECATED_MESSAGE_NAME = Name.identifier("message")
private val DEPRECATED_REPLACE_WITH_NAME = Name.identifier("replaceWith")
private val DEPRECATED_LEVEL_NAME = Name.identifier("level")
private val REPLACE_WITH_EXPRESSION_NAME = Name.identifier("expression")
private val REPLACE_WITH_IMPORTS_NAME = Name.identifier("imports")
fun KotlinBuiltIns.createUnsafeVarianceAnnotation(): AnnotationDescriptor { fun KotlinBuiltIns.createUnsafeVarianceAnnotation(): AnnotationDescriptor {
val unsafeVarianceAnnotation = getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.unsafeVariance) val unsafeVarianceAnnotation = getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.unsafeVariance)
return AnnotationDescriptorImpl( return AnnotationDescriptorImpl(unsafeVarianceAnnotation.defaultType, emptyMap(), SourceElement.NO_SOURCE)
unsafeVarianceAnnotation.defaultType,
emptyMap(),
SourceElement.NO_SOURCE)
} }
private operator fun Collection<ValueParameterDescriptor>.get(parameterName: String) = single { it.name.asString() == parameterName }
private val INLINE_ONLY_ANNOTATION_FQ_NAME = FqName("kotlin.internal.InlineOnly") private val INLINE_ONLY_ANNOTATION_FQ_NAME = FqName("kotlin.internal.InlineOnly")
fun MemberDescriptor.isInlineOnlyOrReifiable(): Boolean = fun MemberDescriptor.isInlineOnlyOrReifiable(): Boolean =
@@ -46,7 +46,7 @@ class AnnotationDeserializer(private val module: ModuleDescriptor, private val n
fun deserializeAnnotation(proto: Annotation, nameResolver: NameResolver): AnnotationDescriptor { fun deserializeAnnotation(proto: Annotation, nameResolver: NameResolver): AnnotationDescriptor {
val annotationClass = resolveClass(nameResolver.getClassId(proto.id)) val annotationClass = resolveClass(nameResolver.getClassId(proto.id))
var arguments = emptyMap<ValueParameterDescriptor, ConstantValue<*>>() var arguments = emptyMap<Name, ConstantValue<*>>()
if (proto.argumentCount != 0 && !ErrorUtils.isError(annotationClass) && DescriptorUtils.isAnnotationClass(annotationClass)) { if (proto.argumentCount != 0 && !ErrorUtils.isError(annotationClass) && DescriptorUtils.isAnnotationClass(annotationClass)) {
val constructor = annotationClass.constructors.singleOrNull() val constructor = annotationClass.constructors.singleOrNull()
if (constructor != null) { if (constructor != null) {
@@ -62,9 +62,9 @@ class AnnotationDeserializer(private val module: ModuleDescriptor, private val n
proto: Argument, proto: Argument,
parameterByName: Map<Name, ValueParameterDescriptor>, parameterByName: Map<Name, ValueParameterDescriptor>,
nameResolver: NameResolver nameResolver: NameResolver
): Pair<ValueParameterDescriptor, ConstantValue<*>>? { ): Pair<Name, ConstantValue<*>>? {
val parameter = parameterByName[nameResolver.getName(proto.nameId)] ?: return null val parameter = parameterByName[nameResolver.getName(proto.nameId)] ?: return null
return Pair(parameter, resolveValue(parameter.type, proto.value, nameResolver)) return Pair(nameResolver.getName(proto.nameId), resolveValue(parameter.type, proto.value, nameResolver))
} }
fun resolveValue( fun resolveValue(