commonMain.co.touchlab.skie.phases.features.defaultarguments.delegate.BaseDefaultArgumentGeneratorDelegate.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-compiler-linker-plugin-kgp_1.9.20 Show documentation
Show all versions of kotlin-compiler-linker-plugin-kgp_1.9.20 Show documentation
Kotlin compiler plugin that improves Swift interface of a Kotlin Multiplatform framework.
The newest version!
package co.touchlab.skie.phases.features.defaultarguments.delegate
import co.touchlab.skie.configuration.DefaultArgumentInterop
import co.touchlab.skie.configuration.SkieConfigurationFlag
import co.touchlab.skie.configuration.provider.descriptor.configuration
import co.touchlab.skie.kir.descriptor.DescriptorProvider
import co.touchlab.skie.kir.irbuilder.DeclarationBuilder
import co.touchlab.skie.phases.FrontendIrPhase
import co.touchlab.skie.phases.declarationBuilder
import co.touchlab.skie.phases.descriptorProvider
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
import org.jetbrains.kotlin.ir.builders.irGet
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.declaresOrInheritsDefaultValue
abstract class BaseDefaultArgumentGeneratorDelegate(
val context: FrontendIrPhase.Context,
) : DefaultArgumentGeneratorDelegate {
protected val descriptorProvider: DescriptorProvider = context.descriptorProvider
protected val declarationBuilder: DeclarationBuilder = context.declarationBuilder
protected val uniqueNameSubstring = "__Skie_DefaultArguments__"
protected val FunctionDescriptor.hasDefaultArguments: Boolean
get() = this.valueParameters.any { it.declaresOrInheritsDefaultValue() }
private val isInteropEnabledForExternalModules: Boolean =
SkieConfigurationFlag.Feature_DefaultArgumentsInExternalLibraries in context.globalConfiguration.enabledFlags
context(FrontendIrPhase.Context)
protected val FunctionDescriptor.isInteropEnabled: Boolean
get() = this.configuration[DefaultArgumentInterop.Enabled] &&
this.satisfiesMaximumDefaultArgumentCount &&
(descriptorProvider.isFromLocalModule(this) || isInteropEnabledForExternalModules)
context(FrontendIrPhase.Context)
private val FunctionDescriptor.satisfiesMaximumDefaultArgumentCount: Boolean
get() = this.defaultArgumentCount <= this.configuration[DefaultArgumentInterop.MaximumDefaultArgumentCount]
private val FunctionDescriptor.defaultArgumentCount: Int
get() = this.valueParameters.count { it.declaresOrInheritsDefaultValue() }
protected fun FunctionDescriptor.forEachDefaultArgumentOverload(
action: (overloadParameters: List) -> Unit,
) {
val parametersWithDefaultValues = this.valueParameters.filter { it.declaresOrInheritsDefaultValue() }
parametersWithDefaultValues.forEachSubset { omittedParameters ->
if (omittedParameters.isNotEmpty()) {
@Suppress("ConvertArgumentToSet")
val overloadParameters = this.valueParameters - omittedParameters
action(overloadParameters)
}
}
}
private fun Iterable.forEachSubset(action: (List) -> Unit) {
var bitmap = 0
do {
val subset = this.dropIndices(bitmap)
action(subset)
bitmap++
} while (subset.isNotEmpty())
}
private fun Iterable.dropIndices(bitmap: Int): List =
this.filterIndexed { index, _ ->
!bitmap.testBit(index)
}
private fun Int.testBit(n: Int): Boolean =
(this shr n) and 1 == 1
context(IrBuilderWithScope) protected fun IrFunctionAccessExpression.passArgumentsWithMatchingNames(from: IrFunction) {
from.valueParameters.forEach { valueParameter: IrValueParameter ->
val indexInCalledFunction = this.symbol.owner.indexOfValueParameterByName(valueParameter.name)
check(indexInCalledFunction != -1) {
"Could not find value parameter with name ${valueParameter.name} in ${this.symbol.owner} (from $from)\n\nThis dump:\n${this.dump()}\n\nFrom dump:\n${from.dump()}"
}
putValueArgument(indexInCalledFunction, irGet(valueParameter))
}
}
protected open fun IrFunction.indexOfValueParameterByName(name: Name): Int =
this.valueParameters.indexOfFirst { it.name == name }
}