diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/PrimitiveCompanionLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/PrimitiveCompanionLowering.kt index 0a4b3503d4d..c345d0d4056 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/PrimitiveCompanionLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/PrimitiveCompanionLowering.kt @@ -9,27 +9,73 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrGetObjectValue import org.jetbrains.kotlin.ir.expressions.impl.IrGetObjectValueImpl import org.jetbrains.kotlin.ir.types.isPrimitiveType import org.jetbrains.kotlin.ir.types.isString import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.util.irCall import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid class PrimitiveCompanionLowering(val context: JsIrBackendContext) : FileLoweringPass { + + private fun getActualPrimitiveCompanion(irClass: IrClass): IrClass? { + if (!irClass.isCompanion) + return null + + val parent = irClass.parent as IrClass + + if (!parent.defaultType.isPrimitiveType() && !parent.defaultType.isString()) + return null + + return context.primitiveCompanionObjects[parent.name]?.owner + } + + private fun getActualPrimitiveCompanionPropertyAccessor(function: IrSimpleFunction): IrSimpleFunction? { + val property = function.correspondingPropertySymbol?.owner + ?: return null + + val companion = property.parent as? IrClass + ?: return null + + val actualCompanion = getActualPrimitiveCompanion(companion) + ?: return null + + val actualFunction = + actualCompanion.declarations + .filterIsInstance() + .find { it.name == function.name } + + return actualFunction!! + } + override fun lower(irFile: IrFile) { irFile.transformChildrenVoid(object : IrElementTransformerVoid() { override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression { - val symbol = expression.symbol - if (!symbol.isBound) return expression - val declaration = symbol.owner - if (!declaration.isCompanion) return expression - val parent = declaration.parent as IrClass - if (!parent.defaultType.isPrimitiveType() && !parent.defaultType.isString()) return expression - val actualCompanion = context.primitiveCompanionObjects[parent.name] ?: return expression - return expression.run { IrGetObjectValueImpl(startOffset, endOffset, actualCompanion.owner.defaultType, actualCompanion) } + val irClass = expression.symbol.owner + val actualCompanion = getActualPrimitiveCompanion(irClass) ?: return expression + return IrGetObjectValueImpl( + expression.startOffset, + expression.endOffset, + actualCompanion.defaultType, + actualCompanion.symbol + ) + } + + override fun visitCall(expression: IrCall): IrExpression { + val newCall = super.visitCall(expression) as IrCall + + val function = expression.symbol.owner as? IrSimpleFunction + ?: return newCall + + val actualFunction = getActualPrimitiveCompanionPropertyAccessor(function) + ?: return newCall + + return irCall(newCall, actualFunction) } }) }