Allow IrConstTransformer to visit and evaluate vararg elements

This commit is contained in:
Ivan Kylchik
2020-06-26 14:43:42 +03:00
parent 6fa03297f9
commit de2b20482a
4 changed files with 27 additions and 11 deletions
@@ -55,19 +55,37 @@ class IrConstTransformer(irModuleFragment: IrModuleFragment) : IrElementTransfor
}
private fun transformAnnotations(annotationContainer: IrAnnotationContainer) {
annotationContainer.annotations.forEach {
for (i in 0 until it.valueArgumentsCount) {
val arg = it.getValueArgument(i) ?: continue
if (arg.accept(IrCompileTimeChecker(mode = EvaluationMode.ONLY_BUILTINS), null)) {
val const = interpreter.interpret(arg).replaceIfError(arg)
it.putValueArgument(i, const.convertToConstIfPossible(it.symbol.owner.valueParameters[i].type))
annotationContainer.annotations.forEach { annotation ->
// TODO this check can be removed after fix with annotation call arguments mapping
if ((0 until annotation.valueArgumentsCount).any { annotation.getValueArgument(it) == null }) return@forEach
for (i in 0 until annotation.valueArgumentsCount) {
val arg = annotation.getValueArgument(i) ?: continue
when (arg) {
is IrVararg -> arg.transformVarArg()
else -> annotation.putValueArgument(i, arg.transformSingleArg(annotation.symbol.owner.valueParameters[i].type))
}
}
}
}
private fun IrVararg.transformVarArg() {
for (i in this.elements.indices) {
val irVarargElement = this.elements[i] as? IrExpression ?: continue
this.putElement(i, irVarargElement.transformSingleArg(this.varargElementType))
}
}
private fun IrExpression.transformSingleArg(expectedType: IrType): IrExpression {
if (this.accept(IrCompileTimeChecker(mode = EvaluationMode.ONLY_BUILTINS), null)) {
val const = interpreter.interpret(this).replaceIfError(this)
return const.convertToConstIfPossible(expectedType)
}
return this
}
private fun IrExpression.convertToConstIfPossible(type: IrType): IrExpression {
if (this !is IrConst<*>) return this
if (this !is IrConst<*> || type is IrErrorType) return this
if (type.isArray()) return this.convertToConstIfPossible((type as IrSimpleType).arguments.single().typeOrNull!!)
return this.value.toIrConst(type, this.startOffset, this.endOffset)
}