[IR] Support type arguments in psi2ir
This commit is contained in:
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.constants.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeConstructorSubstitution
|
||||
import org.jetbrains.kotlin.types.isError
|
||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
|
||||
@@ -36,7 +37,7 @@ abstract class ConstantValueGenerator(
|
||||
varargElementType: KotlinType? = null
|
||||
): IrExpression =
|
||||
// Assertion is safe here because annotation calls and class literals are not allowed in constant initializers
|
||||
generateConstantOrAnnotationValueAsExpression(startOffset, endOffset, constantValue, varargElementType)!!
|
||||
generateConstantOrAnnotationValueAsExpression(startOffset, endOffset, constantValue, null, varargElementType)!!
|
||||
|
||||
/**
|
||||
* @return null if the constant value is an unresolved annotation or an unresolved class literal
|
||||
@@ -45,9 +46,11 @@ abstract class ConstantValueGenerator(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
constantValue: ConstantValue<*>,
|
||||
realType: KotlinType?,
|
||||
varargElementType: KotlinType? = null
|
||||
): IrExpression? {
|
||||
val constantKtType = constantValue.getType(moduleDescriptor)
|
||||
val constantValueType = constantValue.getType(moduleDescriptor)
|
||||
val constantKtType = realType ?: constantValueType
|
||||
val constantType = constantKtType.toIrType()
|
||||
|
||||
return when (constantValue) {
|
||||
@@ -67,20 +70,20 @@ abstract class ConstantValueGenerator(
|
||||
is UShortValue -> IrConstImpl.short(startOffset, endOffset, constantType, constantValue.value)
|
||||
|
||||
is ArrayValue -> {
|
||||
val arrayElementType = varargElementType ?: constantKtType.getArrayElementType()
|
||||
val arrayElementType = varargElementType ?: constantValueType.getArrayElementType()
|
||||
IrVarargImpl(
|
||||
startOffset, endOffset,
|
||||
constantType,
|
||||
arrayElementType.toIrType(),
|
||||
constantValue.value.mapNotNull {
|
||||
generateConstantOrAnnotationValueAsExpression(startOffset, endOffset, it, null)
|
||||
generateConstantOrAnnotationValueAsExpression(startOffset, endOffset, it, arrayElementType)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
is EnumValue -> {
|
||||
val enumEntryDescriptor =
|
||||
constantKtType.memberScope.getContributedClassifier(constantValue.enumEntryName, NoLookupLocation.FROM_BACKEND)
|
||||
constantValueType.memberScope.getContributedClassifier(constantValue.enumEntryName, NoLookupLocation.FROM_BACKEND)
|
||||
?: throw AssertionError("No such enum entry ${constantValue.enumEntryName} in $constantType")
|
||||
if (enumEntryDescriptor !is ClassDescriptor) {
|
||||
throw AssertionError("Enum entry $enumEntryDescriptor should be a ClassDescriptor")
|
||||
@@ -100,7 +103,7 @@ abstract class ConstantValueGenerator(
|
||||
)
|
||||
}
|
||||
|
||||
is AnnotationValue -> generateAnnotationConstructorCall(constantValue.value)
|
||||
is AnnotationValue -> generateAnnotationConstructorCall(constantValue.value, constantKtType)
|
||||
|
||||
is KClassValue -> {
|
||||
val classifierKtType = constantValue.getArgumentType(moduleDescriptor)
|
||||
@@ -124,8 +127,8 @@ abstract class ConstantValueGenerator(
|
||||
}
|
||||
}
|
||||
|
||||
fun generateAnnotationConstructorCall(annotationDescriptor: AnnotationDescriptor): IrConstructorCall? {
|
||||
val annotationType = annotationDescriptor.type
|
||||
fun generateAnnotationConstructorCall(annotationDescriptor: AnnotationDescriptor, realType: KotlinType? = null): IrConstructorCall? {
|
||||
val annotationType = realType ?: annotationDescriptor.type
|
||||
val annotationClassDescriptor = annotationType.constructor.declarationDescriptor
|
||||
if (annotationClassDescriptor !is ClassDescriptor) return null
|
||||
if (annotationClassDescriptor is NotFoundClasses.MockClassDescriptor) return null
|
||||
@@ -146,17 +149,29 @@ abstract class ConstantValueGenerator(
|
||||
annotationType.toIrType(),
|
||||
primaryConstructorSymbol,
|
||||
valueArgumentsCount = primaryConstructorDescriptor.valueParameters.size,
|
||||
typeArgumentsCount = 0,
|
||||
typeArgumentsCount = annotationClassDescriptor.declaredTypeParameters.size,
|
||||
constructorTypeArgumentsCount = 0
|
||||
)
|
||||
|
||||
for (valueParameter in primaryConstructorDescriptor.valueParameters) {
|
||||
val substitutor = TypeConstructorSubstitution.create(annotationType).buildSubstitutor()
|
||||
val substitutedConstructor = primaryConstructorDescriptor.substitute(substitutor) ?: error("Cannot substitute constructor")
|
||||
|
||||
val typeArguments = annotationType.arguments
|
||||
assert(typeArguments.size == annotationClassDescriptor.declaredTypeParameters.size)
|
||||
|
||||
for (i in typeArguments.indices) {
|
||||
val typeArgument = typeArguments[i]
|
||||
irCall.putTypeArgument(i, typeArgument.type.toIrType())
|
||||
}
|
||||
|
||||
for (valueParameter in substitutedConstructor.valueParameters) {
|
||||
val argumentIndex = valueParameter.index
|
||||
val argumentValue = annotationDescriptor.allValueArguments[valueParameter.name] ?: continue
|
||||
val irArgument = generateConstantOrAnnotationValueAsExpression(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
argumentValue,
|
||||
valueParameter.type,
|
||||
valueParameter.varargElementType
|
||||
)
|
||||
if (irArgument != null) {
|
||||
|
||||
Reference in New Issue
Block a user