Support constant evaluation of unsigned type constructors

#KT-23816 In Progress
This commit is contained in:
Mikhail Zarechenskiy
2018-05-21 17:30:30 +03:00
parent bf5f710f39
commit 656f6cbded
24 changed files with 569 additions and 11 deletions
@@ -20,6 +20,7 @@ import kotlin.collections.SetsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.builtins.UnsignedTypes;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.VariableDescriptor;
import org.jetbrains.kotlin.psi.KtExpression;
@@ -89,7 +90,8 @@ public class CompileTimeConstantUtils {
KotlinBuiltIns.isKClass(typeDescriptor) ||
KotlinBuiltIns.isPrimitiveArray(parameterType) ||
KotlinBuiltIns.isPrimitiveType(parameterType) ||
KotlinBuiltIns.isString(parameterType)) {
KotlinBuiltIns.isString(parameterType) ||
UnsignedTypes.INSTANCE.isUnsignedType(parameterType)) {
return true;
}
@@ -11,6 +11,7 @@ import com.intellij.psi.util.TypeConversionUtil
import com.intellij.util.text.LiteralFormatUtil
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.UnsignedTypes
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
@@ -759,20 +760,51 @@ private class ConstantExpressionEvaluatorVisitor(
// Ann()
if (resultingDescriptor is ConstructorDescriptor) {
val classDescriptor: ClassDescriptor = resultingDescriptor.constructedClass
if (DescriptorUtils.isAnnotationClass(classDescriptor)) {
val descriptor = AnnotationDescriptorImpl(
classDescriptor.defaultType,
constantExpressionEvaluator.resolveAnnotationArguments(call, trace),
SourceElement.NO_SOURCE
)
return AnnotationValue(descriptor).wrap()
val classDescriptor = resultingDescriptor.constructedClass
return when {
DescriptorUtils.isAnnotationClass(classDescriptor) -> {
val descriptor = AnnotationDescriptorImpl(
classDescriptor.defaultType,
constantExpressionEvaluator.resolveAnnotationArguments(call, trace),
SourceElement.NO_SOURCE
)
AnnotationValue(descriptor).wrap()
}
classDescriptor.isInlineClass() && UnsignedTypes.isUnsignedClass(classDescriptor) ->
createConstantValueForUnsignedTypeConstructor(call, resultingDescriptor, classDescriptor)
else -> null
}
}
return null
}
private fun createConstantValueForUnsignedTypeConstructor(
call: ResolvedCall<*>,
constructorDescriptor: ConstructorDescriptor,
classDescriptor: ClassDescriptor
): TypedCompileTimeConstant<*>? {
assert(classDescriptor.isInlineClass()) { "Unsigned type should be an inline class type, but it is: $classDescriptor" }
if (!constructorDescriptor.isPrimary) return null
val valueArguments = call.valueArguments
if (valueArguments.size > 1) return null
val underlyingType = classDescriptor.underlyingRepresentation()?.type ?: return null
val argument = valueArguments.values.single().arguments.single()
val argumentExpression = argument.getArgumentExpression() ?: return null
val compileTimeConstant = evaluate(argumentExpression, underlyingType)
val evaluatedArgument = compileTimeConstant?.toConstantValue(underlyingType) ?: return null
val unsignedValue = ConstantValueFactory.createUnsignedValue(evaluatedArgument, classDescriptor.defaultType) ?: return null
return unsignedValue.wrap(compileTimeConstant.parameters)
}
private fun createConstantValueForArrayFunctionCall(
call: ResolvedCall<*>
): TypedCompileTimeConstant<List<ConstantValue<*>>>? {