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.lexer.KtTokens
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.isSubpackageOf
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
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.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.constants.*
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
@@ -80,12 +78,12 @@ class ConstantExpressionEvaluator(
internal fun resolveAnnotationArguments(
resolvedCall: ResolvedCall<*>,
trace: BindingTrace
): Map<ValueParameterDescriptor, ConstantValue<*>> {
val arguments = HashMap<ValueParameterDescriptor, ConstantValue<*>>()
): Map<Name, ConstantValue<*>> {
val arguments = HashMap<Name, ConstantValue<*>>()
for ((parameterDescriptor, resolvedArgument) in resolvedCall.valueArguments.entries) {
val value = getAnnotationArgumentValue(trace, parameterDescriptor, resolvedArgument)
if (value != null) {
arguments.put(parameterDescriptor, value)
arguments.put(parameterDescriptor.name, value)
}
}
return arguments
@@ -89,16 +89,16 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
val annotationClass = resolveClass(annotationClassId)
return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor {
private val arguments = HashMap<ValueParameterDescriptor, ConstantValue<*>>()
private val arguments = HashMap<Name, ConstantValue<*>>()
override fun visit(name: Name?, value: Any?) {
if (name != null) {
setArgumentValueByName(name, createConstant(name, value))
arguments[name] = createConstant(name, value)
}
}
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? {
@@ -116,7 +116,7 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
override fun visitEnd() {
val parameter = DescriptorResolverUtils.getAnnotationParameterByName(name, annotationClass)
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 {
override fun visitEnd() {
visitor.visitEnd()
setArgumentValueByName(name, AnnotationValue(list.single()))
arguments[name] = AnnotationValue(list.single())
}
}
}
@@ -153,13 +153,6 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
return factory.createConstantValue(value) ?:
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 deprecationLevel = fqName("DeprecationLevel");
public final FqName replaceWith = fqName("ReplaceWith");
public final FqName extensionFunctionType = fqName("ExtensionFunctionType");
public final FqName parameterName = fqName("ParameterName");
public final FqName annotation = fqName("Annotation");
@@ -168,8 +168,8 @@ fun getFunctionTypeArgumentProjections(
val nameValue = ConstantValueFactory(builtIns).createStringValue(name.asString())
val parameterNameAnnotation = AnnotationDescriptorImpl(
annotationClass.defaultType,
mapOf(annotationClass.unsubstitutedPrimaryConstructor!!.valueParameters.single() to nameValue),
org.jetbrains.kotlin.descriptors.SourceElement.NO_SOURCE
mapOf(Name.identifier("name") to nameValue),
SourceElement.NO_SOURCE
)
type.replaceAnnotations(AnnotationsImpl(type.annotations + parameterNameAnnotation))
}
@@ -16,33 +16,29 @@
package org.jetbrains.kotlin.descriptors.annotations;
import kotlin.collections.MapsKt;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.SourceElement;
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
import org.jetbrains.kotlin.types.KotlinType;
import java.util.Collections;
import java.util.Map;
public class AnnotationDescriptorImpl implements AnnotationDescriptor {
private final KotlinType annotationType;
private final Map<ValueParameterDescriptor, ConstantValue<?>> valueArguments;
private final Map<Name, ConstantValue<?>> valueArguments;
private final SourceElement source;
public AnnotationDescriptorImpl(
@NotNull KotlinType annotationType,
@NotNull Map<ValueParameterDescriptor, ConstantValue<?>> valueArguments,
@NotNull Map<Name, ConstantValue<?>> valueArguments,
@NotNull SourceElement source
) {
this.annotationType = annotationType;
this.valueArguments = Collections.unmodifiableMap(valueArguments);
this.valueArguments = valueArguments;
this.source = source;
}
@@ -61,15 +57,7 @@ public class AnnotationDescriptorImpl implements AnnotationDescriptor {
@NotNull
@Override
public Map<Name, ConstantValue<?>> getAllValueArguments() {
return MapsKt.mapKeys(
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();
}
}
);
return valueArguments;
}
@Override
@@ -17,7 +17,10 @@
package org.jetbrains.kotlin.descriptors.annotations
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.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -33,42 +36,37 @@ fun KotlinBuiltIns.createDeprecatedAnnotation(
replaceWith: String = "",
level: String = "WARNING"
): AnnotationDescriptor {
val deprecatedAnnotation = deprecatedAnnotation
val parameters = deprecatedAnnotation.unsubstitutedPrimaryConstructor!!.valueParameters
val replaceWithAnnotation = AnnotationDescriptorImpl(
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(
deprecatedAnnotation.defaultType,
mapOf(
parameters["message"] to StringValue(message, this),
parameters["replaceWith"] to AnnotationValue(
AnnotationDescriptorImpl(
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"))
DEPRECATED_MESSAGE_NAME to StringValue(message, this),
DEPRECATED_REPLACE_WITH_NAME to AnnotationValue(replaceWithAnnotation),
DEPRECATED_LEVEL_NAME 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 {
val unsafeVarianceAnnotation = getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.unsafeVariance)
return AnnotationDescriptorImpl(
unsafeVarianceAnnotation.defaultType,
emptyMap(),
SourceElement.NO_SOURCE)
return AnnotationDescriptorImpl(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")
fun MemberDescriptor.isInlineOnlyOrReifiable(): Boolean =
@@ -46,7 +46,7 @@ class AnnotationDeserializer(private val module: ModuleDescriptor, private val n
fun deserializeAnnotation(proto: Annotation, nameResolver: NameResolver): AnnotationDescriptor {
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)) {
val constructor = annotationClass.constructors.singleOrNull()
if (constructor != null) {
@@ -62,9 +62,9 @@ class AnnotationDeserializer(private val module: ModuleDescriptor, private val n
proto: Argument,
parameterByName: Map<Name, ValueParameterDescriptor>,
nameResolver: NameResolver
): Pair<ValueParameterDescriptor, ConstantValue<*>>? {
): Pair<Name, ConstantValue<*>>? {
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(