[Commonizer] Introduce commonizer settings

Add settings for a more fine-grained control over commonizer features
that will be added in the future

Add setting and KGP flag for optimistic number commonization

KT-51011
This commit is contained in:
Pavel Kirpichenkov
2022-01-17 12:11:22 +03:00
parent 1aea2d0437
commit 2609175d58
56 changed files with 615 additions and 237 deletions
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLI
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_GRANULAR_SOURCE_SETS_METADATA
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_HIERARCHICAL_STRUCTURE_BY_DEFAULT
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_HIERARCHICAL_STRUCTURE_SUPPORT
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_OPTIMISTIC_NUMBER_COMMONIZATION
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_NATIVE_DEPENDENCY_PROPAGATION
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPlugin
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
@@ -213,6 +214,9 @@ internal class PropertiesProvider private constructor(private val project: Proje
val mppStabilityNoWarn: Boolean?
get() = booleanProperty(KotlinMultiplatformPlugin.STABILITY_NOWARN_FLAG)
val mppEnableOptimisticNumberCommonization: Boolean
get() = booleanProperty(KOTLIN_MPP_ENABLE_OPTIMISTIC_NUMBER_COMMONIZATION) ?: false
val wasmStabilityNoWarn: Boolean
get() = booleanProperty("kotlin.wasm.stability.nowarn") ?: false
@@ -468,6 +472,7 @@ internal class PropertiesProvider private constructor(private val project: Proje
const val KOTLIN_MPP_HIERARCHICAL_STRUCTURE_BY_DEFAULT = "kotlin.internal.mpp.hierarchicalStructureByDefault"
const val KOTLIN_MPP_HIERARCHICAL_STRUCTURE_SUPPORT = "kotlin.mpp.hierarchicalStructureSupport"
const val KOTLIN_NATIVE_DEPENDENCY_PROPAGATION = "kotlin.native.enableDependencyPropagation"
const val KOTLIN_MPP_ENABLE_OPTIMISTIC_NUMBER_COMMONIZATION = "kotlin.mpp.enableOptimisticNumberCommonization"
}
companion object {
@@ -6,13 +6,16 @@
package org.jetbrains.kotlin.gradle.targets.native.internal
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.OutputDirectory
import org.jetbrains.kotlin.commonizer.CommonizerOutputFileLayout
import org.jetbrains.kotlin.commonizer.CommonizerOutputFileLayout.base64Hash
import org.jetbrains.kotlin.commonizer.CommonizerOutputFileLayout.ensureMaxFileNameLength
import org.jetbrains.kotlin.commonizer.AdditionalCommonizerSetting
import org.jetbrains.kotlin.commonizer.cli.OPTIMISTIC_NUMBER_COMMONIZATION_ENABLED_OPTION_ALIAS
import org.jetbrains.kotlin.commonizer.identityString
import org.jetbrains.kotlin.gradle.utils.filesProvider
import org.jetbrains.kotlin.commonizer.setTo
import org.jetbrains.kotlin.gradle.utils.outputFilesProvider
import java.io.File
@@ -84,7 +84,8 @@ internal open class CInteropCommonizerTask : AbstractCInteropCommonizerTask() {
inputLibraries = cinteropsForTarget.map { it.libraryFile.get() }.filter { it.exists() }.toSet(),
dependencyLibraries = getNativeDistributionDependencies(group),
outputDirectory = outputDirectory(group),
logLevel = project.commonizerLogLevel
logLevel = project.commonizerLogLevel,
additionalSettings = project.additionalCommonizerSettings,
)
}
@@ -6,7 +6,10 @@
package org.jetbrains.kotlin.gradle.targets.native.internal
import org.gradle.api.Project
import org.jetbrains.kotlin.commonizer.AdditionalCommonizerSetting
import org.jetbrains.kotlin.commonizer.CommonizerLogLevel
import org.jetbrains.kotlin.commonizer.cli.OPTIMISTIC_NUMBER_COMMONIZATION_ENABLED_OPTION_ALIAS
import org.jetbrains.kotlin.commonizer.setTo
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
internal val Project.commonizerLogLevel: CommonizerLogLevel
@@ -18,3 +21,8 @@ internal val Project.commonizerLogLevel: CommonizerLogLevel
return if (logger.isInfoEnabled) CommonizerLogLevel.Info else CommonizerLogLevel.Quiet
}
internal val Project.additionalCommonizerSettings: List<AdditionalCommonizerSetting>
get() = listOf(
OPTIMISTIC_NUMBER_COMMONIZATION_ENABLED_OPTION_ALIAS setTo isOptimisticNumberCommonizationEnabled
)
@@ -20,6 +20,9 @@ internal val Project.isCInteropCommonizationEnabled: Boolean get() = PropertiesP
internal val Project.isIntransitiveMetadataConfigurationEnabled: Boolean
get() = PropertiesProvider(this).enableIntransitiveMetadataConfiguration
internal val Project.isOptimisticNumberCommonizationEnabled: Boolean
get() = PropertiesProvider(this).mppEnableOptimisticNumberCommonization
internal val Project.commonizeTask: TaskProvider<Task>
get() = locateOrRegisterTask(
"commonize",
@@ -22,12 +22,12 @@ internal class NativeDistributionCommonizationCache(
private val commonizer: NativeDistributionCommonizer
) : NativeDistributionCommonizer {
override fun commonizeNativeDistribution(
konanHome: File,
outputDirectory: File,
outputTargets: Set<SharedCommonizerTarget>,
logLevel: CommonizerLogLevel
logLevel: CommonizerLogLevel,
additionalSettings: List<AdditionalCommonizerSetting>,
) {
if (!project.isNativeDistributionCommonizationCacheEnabled) {
logInfo("Cache disabled")
@@ -52,7 +52,7 @@ internal class NativeDistributionCommonizationCache(
.forEach { commonizedDirectory -> if (commonizedDirectory.exists()) commonizedDirectory.deleteRecursively() }
commonizer.commonizeNativeDistribution(
konanHome, outputDirectory, enqueuedOutputTargets, logLevel
konanHome, outputDirectory, enqueuedOutputTargets, logLevel, additionalSettings
)
enqueuedOutputTargets
@@ -54,7 +54,8 @@ internal open class NativeDistributionCommonizerTask : DefaultTask() {
konanHome = konanHome,
outputDirectory = getRootOutputDirectory(),
outputTargets = project.collectAllSharedCommonizerTargetsFromBuild(),
logLevel = project.commonizerLogLevel
logLevel = project.commonizerLogLevel,
additionalSettings = project.additionalCommonizerSettings,
)
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.commonizer
import org.jetbrains.kotlin.commonizer.cli.*
import java.io.File
import java.net.URLClassLoader
@@ -27,19 +28,23 @@ public class CliCommonizer(private val executor: Executor) : NativeDistributionC
dependencyLibraries: Set<CommonizerDependency>,
outputTargets: Set<SharedCommonizerTarget>,
outputDirectory: File,
logLevel: CommonizerLogLevel
logLevel: CommonizerLogLevel,
additionalSettings: List<AdditionalCommonizerSetting>,
) {
if (inputLibraries.isEmpty()) return
val arguments = mutableListOf<String>().apply {
add("native-klib-commonize")
add("-distribution-path"); add(konanHome.absolutePath)
add("-input-libraries"); add(inputLibraries.joinToString(";") { it.absolutePath })
add("-output-targets"); add(outputTargets.joinToString(";") { it.identityString })
add("-output-path"); add(outputDirectory.absolutePath)
add(NATIVE_DISTRIBUTION_OPTION_ALIAS.argumentString); add(konanHome.absolutePath)
add(INPUT_LIBRARIES_OPTION_ALIAS.argumentString); add(inputLibraries.joinToString(";") { it.absolutePath })
add(OUTPUT_COMMONIZER_TARGET_OPTION_ALIAS.argumentString); add(outputTargets.joinToString(";") { it.identityString })
add(OUTPUT_OPTION_ALIAS.argumentString); add(outputDirectory.absolutePath)
if (dependencyLibraries.isNotEmpty()) {
add("-dependency-libraries"); add(dependencyLibraries.joinToString(";"))
add(DEPENDENCY_LIBRARIES_OPTION_ALIAS.argumentString); add(dependencyLibraries.joinToString(";"))
}
add(LOG_LEVEL_OPTION_ALIAS.argumentString); add(logLevel.name.lowercase())
for ((settingArgument, settingValue) in additionalSettings) {
add(settingArgument); add(settingValue.toString())
}
add("-log-level"); add(logLevel.name.lowercase())
}
executor(arguments)
}
@@ -48,14 +53,18 @@ public class CliCommonizer(private val executor: Executor) : NativeDistributionC
konanHome: File,
outputDirectory: File,
outputTargets: Set<SharedCommonizerTarget>,
logLevel: CommonizerLogLevel
logLevel: CommonizerLogLevel,
additionalSettings: List<AdditionalCommonizerSetting>,
) {
val arguments = mutableListOf<String>().apply {
add("native-dist-commonize")
add("-distribution-path"); add(konanHome.absolutePath)
add("-output-path"); add(outputDirectory.absolutePath)
add("-output-targets"); add(outputTargets.joinToString(";") { it.identityString })
add("-log-level"); add(logLevel.name.lowercase())
add(NATIVE_DISTRIBUTION_OPTION_ALIAS.argumentString); add(konanHome.absolutePath)
add(OUTPUT_OPTION_ALIAS.argumentString); add(outputDirectory.absolutePath)
add(OUTPUT_COMMONIZER_TARGET_OPTION_ALIAS.argumentString); add(outputTargets.joinToString(";") { it.identityString })
add(LOG_LEVEL_OPTION_ALIAS.argumentString); add(logLevel.name.lowercase())
for ((settingArgument, settingValue) in additionalSettings) {
add(settingArgument); add(settingValue.toString())
}
}
executor(arguments)
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.commonizer
import org.jetbrains.kotlin.commonizer.cli.OptionAlias
import java.io.File
import java.io.Serializable
@@ -16,7 +17,8 @@ public interface CInteropCommonizer : Serializable {
dependencyLibraries: Set<CommonizerDependency>,
outputTargets: Set<SharedCommonizerTarget>,
outputDirectory: File,
logLevel: CommonizerLogLevel = CommonizerLogLevel.Quiet
logLevel: CommonizerLogLevel = CommonizerLogLevel.Quiet,
additionalSettings: List<AdditionalCommonizerSetting> = emptyList(),
)
}
@@ -26,6 +28,15 @@ public interface NativeDistributionCommonizer : Serializable {
konanHome: File,
outputDirectory: File,
outputTargets: Set<SharedCommonizerTarget>,
logLevel: CommonizerLogLevel = CommonizerLogLevel.Quiet
logLevel: CommonizerLogLevel = CommonizerLogLevel.Quiet,
additionalSettings: List<AdditionalCommonizerSetting> = emptyList(),
)
}
}
public data class AdditionalCommonizerSetting(
public val key: String,
public val value: Any,
)
public infix fun OptionAlias.setTo(settingValue: Any): AdditionalCommonizerSetting =
AdditionalCommonizerSetting(this.argumentString, settingValue)
@@ -0,0 +1,43 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.commonizer.cli
// General
private const val DEPENDENCY_LIBRARIES_ALIAS: String = "dependency-libraries"
private const val INPUT_LIBRARIES_ALIAS: String = "input-libraries"
private const val LOG_LEVEL_ALIAS: String = "log-level"
private const val NATIVE_DISTRIBUTION_PATH_ALIAS: String = "distribution-path"
private const val OUTPUT_COMMONIZER_TARGETS_ALIAS: String = "output-targets"
private const val OUTPUT_PATH_ALIAS: String = "output-path"
private const val STATS_TYPE_ALIAS: String = "log-stats"
private const val NATIVE_TARGETS_ALIAS: String = "targets"
private const val COPY_STDLIB_ALIAS: String = "copy-stdlib"
private const val COPY_ENDORSED_LIBS_ALIAS: String = "copy-endorsed-libs"
public val DEPENDENCY_LIBRARIES_OPTION_ALIAS: OptionAlias = OptionAlias(DEPENDENCY_LIBRARIES_ALIAS)
public val INPUT_LIBRARIES_OPTION_ALIAS: OptionAlias = OptionAlias(INPUT_LIBRARIES_ALIAS)
public val LOG_LEVEL_OPTION_ALIAS: OptionAlias = OptionAlias(LOG_LEVEL_ALIAS)
public val NATIVE_DISTRIBUTION_OPTION_ALIAS: OptionAlias = OptionAlias(NATIVE_DISTRIBUTION_PATH_ALIAS)
public val OUTPUT_COMMONIZER_TARGET_OPTION_ALIAS: OptionAlias = OptionAlias(OUTPUT_COMMONIZER_TARGETS_ALIAS)
public val OUTPUT_OPTION_ALIAS: OptionAlias = OptionAlias(OUTPUT_PATH_ALIAS)
public val STATS_TYPE_OPTION_ALIAS: OptionAlias = OptionAlias(STATS_TYPE_ALIAS)
public val NATIVE_TARGETS_OPTION_ALIAS: OptionAlias = OptionAlias(NATIVE_TARGETS_ALIAS)
public val COPY_STDLIB_OPTION_ALIAS: OptionAlias = OptionAlias(COPY_STDLIB_ALIAS)
public val COPY_ENDORSED_LIBS_OPTION_ALIAS: OptionAlias = OptionAlias(COPY_ENDORSED_LIBS_ALIAS)
// Commonizer settings
private const val OPTIMISTIC_NUMBER_COMMONIZATION_ENABLED_ALIAS: String = "optimistic-numbers"
public val OPTIMISTIC_NUMBER_COMMONIZATION_ENABLED_OPTION_ALIAS: OptionAlias = OptionAlias(OPTIMISTIC_NUMBER_COMMONIZATION_ENABLED_ALIAS)
@JvmInline
public value class OptionAlias(public val aliasString: String) {
public val argumentString: String
get() = "-$aliasString"
override fun toString(): String = aliasString
}
@@ -24,7 +24,8 @@ class CliCommonizerTest {
inputLibraries = emptySet(),
dependencyLibraries = emptySet(),
outputTargets = setOf(CommonizerTarget(KonanTarget.LINUX_X64, KonanTarget.MACOS_X64)),
outputDirectory = temporaryOutputDirectory.root
outputDirectory = temporaryOutputDirectory.root,
additionalSettings = emptyList(),
)
}
}
@@ -23,6 +23,7 @@ data class CommonizerParameters(
val storageManager: StorageManager = LockBasedStorageManager.NO_LOCKS,
val statsCollector: StatsCollector? = null,
val logger: Logger? = null,
val settings: CommonizerSettings,
)
internal fun CommonizerParameters.dependencyClassifiers(target: CommonizerTarget): CirProvidedClassifiers {
@@ -0,0 +1,41 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.commonizer
interface CommonizerSettings {
sealed class Key<T : Any> {
abstract val defaultValue: T
}
fun <T : Any> getSetting(key: Key<T>): T
}
object OptimisticNumberCommonizationEnabledKey : CommonizerSettings.Key<Boolean>() {
override val defaultValue: Boolean = true
}
internal object DefaultCommonizerSettings : CommonizerSettings {
override fun <T : Any> getSetting(key: CommonizerSettings.Key<T>): T {
return key.defaultValue
}
}
internal class MapBasedCommonizerSettings private constructor(
private val settings: Map<CommonizerSettings.Key<*>, Any>
) : CommonizerSettings {
constructor(vararg settings: Setting<*>) : this(settings.associate { (k, v) -> k to v })
override fun <T : Any> getSetting(key: CommonizerSettings.Key<T>): T {
@Suppress("UNCHECKED_CAST")
return settings[key] as? T ?: key.defaultValue
}
internal data class Setting<T : Any>(
internal val key: CommonizerSettings.Key<T>,
internal val settingValue: T,
)
}
@@ -1,29 +1,31 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.commonizer.cli
internal class BooleanOptionType(
alias: String,
alias: OptionAlias,
description: String,
mandatory: Boolean
) : OptionType<Boolean>(alias, description, mandatory) {
override fun parse(rawValue: String, onError: (reason: String) -> Nothing): Option<Boolean> {
val value = rawValue.lowercase().let {
when (it) {
in TRUE_TOKENS -> true
in FALSE_TOKENS -> false
else -> onError("Invalid boolean value: $it")
}
}
return Option(this, value)
return Option(this, parseBoolean(rawValue, onError))
}
companion object {
private val TRUE_TOKENS = setOf("1", "on", "yes", "true")
private val FALSE_TOKENS = setOf("0", "off", "no", "false")
internal val TRUE_TOKENS = setOf("1", "on", "yes", "true")
internal val FALSE_TOKENS = setOf("0", "off", "no", "false")
}
}
internal fun parseBoolean(rawValue: String, onError: (reason: String) -> Nothing): Boolean {
return rawValue.lowercase().let {
when (it) {
in BooleanOptionType.TRUE_TOKENS -> true
in BooleanOptionType.FALSE_TOKENS -> false
else -> onError("Invalid boolean value: $it")
}
}
}
@@ -0,0 +1,22 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.commonizer.cli
import org.jetbrains.kotlin.commonizer.CommonizerSettings
internal sealed class CommonizerSettingOptionType<T : Any>(
alias: OptionAlias,
description: String,
val commonizerSettingKey: CommonizerSettings.Key<T>
) : OptionType<T>(
alias,
description,
mandatory = false,
)
internal val ADDITIONAL_COMMONIZER_SETTINGS: List<CommonizerSettingOptionType<*>> = listOf(
OptimisticNumberCommonizationOptionType,
)
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.commonizer.parseCommonizerDependency
internal abstract class DependenciesLibrariesSetOptionType(
mandatory: Boolean,
alias: String,
alias: OptionAlias,
description: String
) : OptionType<List<CommonizerDependency>>(
mandatory = mandatory,
@@ -7,6 +7,6 @@ package org.jetbrains.kotlin.commonizer.cli
internal object DependencyLibrariesOptionType : DependenciesLibrariesSetOptionType(
mandatory = false,
alias = "dependency-libraries",
alias = DEPENDENCY_LIBRARIES_OPTION_ALIAS,
description = "';' separated list of klib file paths that can be used as dependency"
)
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -7,6 +7,6 @@ package org.jetbrains.kotlin.commonizer.cli
internal object InputLibrariesOptionType : LibrariesSetOptionType(
mandatory = true,
alias = "input-libraries",
alias = INPUT_LIBRARIES_OPTION_ALIAS,
description = "';' separated list of klib file paths that will get commonized"
)
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -9,7 +9,7 @@ import java.io.File
internal abstract class LibrariesSetOptionType(
mandatory: Boolean,
alias: String,
alias: OptionAlias,
description: String
) : OptionType<List<File>>(
mandatory = mandatory,
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.commonizer.cli
import org.jetbrains.kotlin.commonizer.CommonizerLogLevel
internal object LogLevelOptionType : OptionType<CommonizerLogLevel>("log-level", "{quiet, info}", false) {
internal object LogLevelOptionType : OptionType<CommonizerLogLevel>(LOG_LEVEL_OPTION_ALIAS, "{quiet, info}", false) {
override fun parse(rawValue: String, onError: (reason: String) -> Nothing): Option<CommonizerLogLevel> {
return when (rawValue.lowercase().trim()) {
"quiet" -> Option(this, CommonizerLogLevel.Quiet)
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.commonizer.cli
import java.io.File
internal object NativeDistributionOptionType : OptionType<File>("distribution-path", "Path to the Kotlin/Native distribution") {
internal object NativeDistributionOptionType : OptionType<File>(NATIVE_DISTRIBUTION_OPTION_ALIAS, "Path to the Kotlin/Native distribution") {
override fun parse(rawValue: String, onError: (reason: String) -> Nothing): Option<File> {
val file = File(rawValue)
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.konan.target.KonanTarget.Companion.predefinedTargets
internal object NativeTargetsOptionType : OptionType<List<KonanTarget>>(
"targets", "Comma-separated list of hardware targets", mandatory = false
NATIVE_TARGETS_OPTION_ALIAS, "Comma-separated list of hardware targets", mandatory = false
) {
override fun parse(rawValue: String, onError: (reason: String) -> Nothing): Option<List<KonanTarget>> {
val targetNames = rawValue.split(',')
@@ -0,0 +1,17 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.commonizer.cli
import org.jetbrains.kotlin.commonizer.OptimisticNumberCommonizationEnabledKey
internal object OptimisticNumberCommonizationOptionType : CommonizerSettingOptionType<Boolean>(
OPTIMISTIC_NUMBER_COMMONIZATION_ENABLED_OPTION_ALIAS,
"Boolean (default true)\nEnable commonization of integer types with different bit width to the most narrow among them",
OptimisticNumberCommonizationEnabledKey,
) {
override fun parse(rawValue: String, onError: (reason: String) -> Nothing): Option<Boolean> =
Option(this, parseBoolean(rawValue, onError))
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -1,12 +1,12 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.commonizer.cli
internal abstract class OptionType<T>(
val alias: String,
val alias: OptionAlias,
val description: String,
val mandatory: Boolean = true
) {
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.commonizer.SharedCommonizerTarget
import org.jetbrains.kotlin.commonizer.parseCommonizerTarget
internal object OutputCommonizerTargetsOptionType : OptionType<Set<SharedCommonizerTarget>>(
alias = "output-targets",
alias = OUTPUT_COMMONIZER_TARGET_OPTION_ALIAS,
description = "All output targets separated with ';'",
mandatory = true
) {
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.commonizer.cli
import java.io.File
internal object OutputOptionType : OptionType<File>("output-path", "Destination for commonized libraries") {
internal object OutputOptionType : OptionType<File>(OUTPUT_OPTION_ALIAS, "Destination for commonized libraries") {
override fun parse(rawValue: String, onError: (reason: String) -> Nothing): Option<File> {
val file = File(rawValue)
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.commonizer.cli
import org.jetbrains.kotlin.commonizer.stats.StatsType
internal object StatsTypeOptionType : OptionType<StatsType>("log-stats", DESCRIPTION, mandatory = false) {
internal object StatsTypeOptionType : OptionType<StatsType>(STATS_TYPE_OPTION_ALIAS, DESCRIPTION, mandatory = false) {
override fun parse(rawValue: String, onError: (reason: String) -> Nothing): Option<StatsType> {
val value = StatsType.values().firstOrNull { it.name.equals(rawValue, ignoreCase = true) }
?: onError("Invalid stats type: $rawValue")
@@ -5,6 +5,8 @@
package org.jetbrains.kotlin.commonizer.cli
import org.jetbrains.kotlin.commonizer.*
import org.jetbrains.kotlin.commonizer.MapBasedCommonizerSettings
import java.util.concurrent.atomic.AtomicInteger
internal abstract class Task(private val options: Collection<Option<*>>) : Comparable<Task> {
@@ -28,7 +30,7 @@ internal abstract class Task(private val options: Collection<Option<*>>) : Compa
abstract fun execute(logPrefix: String = "")
protected inline fun <reified T, reified O : OptionType<T>> getMandatory(nameFilter: (String) -> Boolean = { true }): T {
val option = options.filter { it.type is O }.single { nameFilter(it.type.alias) }
val option = options.filter { it.type is O }.single { nameFilter(it.type.alias.aliasString) }
check(option.type.mandatory)
@Suppress("UNCHECKED_CAST")
@@ -36,13 +38,30 @@ internal abstract class Task(private val options: Collection<Option<*>>) : Compa
}
internal inline fun <reified T, reified O : OptionType<T>> getOptional(nameFilter: (String) -> Boolean = { true }): T? {
val option = options.filter { it.type is O }.singleOrNull { nameFilter(it.type.alias) }
val option = options.filter { it.type is O }.singleOrNull { nameFilter(it.type.alias.aliasString) }
if (option != null) check(!option.type.mandatory)
@Suppress("UNCHECKED_CAST")
return option?.value as T?
}
protected fun getSettings(): CommonizerSettings {
val passedSettings = ADDITIONAL_COMMONIZER_SETTINGS.map { settingOptionType ->
settingOptionType.toCommonizerSetting()
}
return MapBasedCommonizerSettings(*passedSettings.toTypedArray())
}
private fun <T : Any> CommonizerSettingOptionType<T>.toCommonizerSetting(): MapBasedCommonizerSettings.Setting<T> {
val key = commonizerSettingKey
@Suppress("UNCHECKED_CAST")
val settingValue = options.singleOrNull { option -> option.type == this }?.value as? T ?: key.defaultValue
return MapBasedCommonizerSettings.Setting(key, settingValue)
}
override fun compareTo(other: Task): Int {
category.compareTo(other.category).let {
if (it != 0) return it
@@ -20,18 +20,18 @@ internal enum class TaskType(
NativeTargetsOptionType,
OutputCommonizerTargetsOptionType,
BooleanOptionType(
"copy-stdlib",
COPY_STDLIB_OPTION_ALIAS,
"Boolean (default false);\nwhether to copy Kotlin/Native endorsed libraries to the destination",
mandatory = false
),
BooleanOptionType(
"copy-endorsed-libs",
COPY_ENDORSED_LIBS_OPTION_ALIAS,
"Boolean (default false);\nwhether to copy Kotlin/Native endorsed libraries to the destination",
mandatory = false
),
StatsTypeOptionType,
LogLevelOptionType,
),
) + ADDITIONAL_COMMONIZER_SETTINGS,
::NativeDistributionCommonize
),
@@ -54,7 +54,7 @@ internal enum class TaskType(
DependencyLibrariesOptionType,
OutputCommonizerTargetsOptionType,
LogLevelOptionType
),
) + ADDITIONAL_COMMONIZER_SETTINGS,
::NativeKlibCommonize
)
;
@@ -46,7 +46,7 @@ private fun parseTask(
tasks: MutableList<Task>
): String? {
val taskType = TaskType.getByAlias(taskAlias) ?: printUsageAndExit("Unknown task $taskAlias")
val optionTypes = taskType.optionTypes.associateBy { it.alias }
val optionTypes = taskType.optionTypes.associateBy { it.alias.aliasString }
val options = mutableMapOf<String, Option<*>>()
fun buildOngoingTask() {
@@ -117,7 +117,7 @@ private fun printUsageAndExit(errorMessage: String? = null): Nothing {
println(formatLeft(1, if (taskType.optionTypes.isNotEmpty()) "Options:" else "No options."))
for (optionType in taskType.optionTypes) {
val lines = optionType.description.split('\n')
println(formatBoth(2, "-${optionType.alias}", lines.first()))
println(formatBoth(2, "-${optionType.alias.aliasString}", lines.first()))
lines.drop(1).forEach { println(StringBuilder().formatRight(it)) }
}
println()
@@ -56,6 +56,7 @@ internal class NativeKlibCommonize(options: Collection<Option<*>>) : Task(option
val konanTargets = outputTargets.konanTargets
val commonizerTargets = konanTargets.map(::CommonizerTarget)
val settings = getSettings()
val logger = CliLoggerAdapter(logLevel, 2)
val libraryLoader = DefaultNativeLibraryLoader(logger)
@@ -73,7 +74,8 @@ internal class NativeKlibCommonize(options: Collection<Option<*>>) : Task(option
CommonizerDependencyRepository(dependencyLibraries.toSet(), libraryLoader),
resultsConsumer = resultsConsumer,
statsCollector = statsCollector,
logger = logger
logger = logger,
settings = settings,
).run()
statsCollector?.writeTo(FileStatsOutput(destination, statsType.name.lowercase()))
@@ -96,6 +98,7 @@ internal class NativeDistributionCommonize(options: Collection<Option<*>>) : Tas
val libraryLoader = DefaultNativeLibraryLoader(logger)
val repository = KonanDistributionRepository(distribution, outputTargets.konanTargets, libraryLoader)
val statsCollector = StatsCollector(statsType, outputTargets.allLeaves().toList())
val settings = getSettings()
val resultsConsumer = buildResultsConsumer {
this add ModuleSerializer(destination)
@@ -110,7 +113,8 @@ internal class NativeDistributionCommonize(options: Collection<Option<*>>) : Tas
dependencies = StdlibRepository(distribution, libraryLoader),
resultsConsumer = resultsConsumer,
statsCollector = statsCollector,
logger = logger
logger = logger,
settings = settings,
).run()
statsCollector?.writeTo(FileStatsOutput(destination, statsType.name.lowercase()))
@@ -5,6 +5,8 @@
package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.CommonizerSettings
import org.jetbrains.kotlin.commonizer.OptimisticNumberCommonizationEnabledKey
import org.jetbrains.kotlin.commonizer.cir.*
import org.jetbrains.kotlin.commonizer.mergedtree.*
import org.jetbrains.kotlin.commonizer.utils.isUnderKotlinNativeSyntheticPackages
@@ -15,9 +17,14 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
internal class ClassOrTypeAliasTypeCommonizer(
private val typeCommonizer: TypeCommonizer,
private val classifiers: CirKnownClassifiers
private val classifiers: CirKnownClassifiers,
private val isOptimisticNumberTypeCommonizationEnabled: Boolean
) : NullableSingleInvocationCommonizer<CirClassOrTypeAliasType> {
constructor(typeCommonizer: TypeCommonizer, classifiers: CirKnownClassifiers, settings: CommonizerSettings) : this(
typeCommonizer, classifiers, settings.getSetting(OptimisticNumberCommonizationEnabledKey)
)
private val isMarkedNullableCommonizer = TypeNullabilityCommonizer(typeCommonizer.options)
private val typeDistanceMeasurement = TypeDistanceMeasurement(typeCommonizer.options)
@@ -27,7 +34,7 @@ internal class ClassOrTypeAliasTypeCommonizer(
val isMarkedNullable = isMarkedNullableCommonizer.commonize(expansions.map { it.isMarkedNullable }) ?: return null
val substitutedTypes = substituteTypesIfNecessary(values)
?: typeCommonizer.options.enableOptimisticNumberTypeCommonization.ifTrue {
?: isOptimisticNumberTypeCommonizationEnabled.ifTrue {
return OptimisticNumbersTypeCommonizer.commonize(expansions)?.makeNullableIfNecessary(isMarkedNullable)
} ?: return null
@@ -5,7 +5,9 @@
package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.CommonizerSettings
import org.jetbrains.kotlin.commonizer.CommonizerTarget
import org.jetbrains.kotlin.commonizer.OptimisticNumberCommonizationEnabledKey
import org.jetbrains.kotlin.commonizer.allLeaves
import org.jetbrains.kotlin.commonizer.cir.*
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
@@ -14,6 +16,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
class TypeAliasCommonizer(
typeCommonizer: TypeCommonizer,
private val classifiers: CirKnownClassifiers,
private val settings: CommonizerSettings,
) : NullableSingleInvocationCommonizer<CirTypeAlias> {
private val typeCommonizer = typeCommonizer.withOptions {
@@ -38,7 +41,7 @@ class TypeAliasCommonizer(
underlyingType = underlyingType,
expandedType = underlyingType.expandedType(),
annotations = listOfNotNull(
createUnsafeNumberAnnotationIfNecessary(classifiers.classifierIndices.targets, values)
createUnsafeNumberAnnotationIfNecessary(classifiers.classifierIndices.targets, settings, values)
)
)
}
@@ -46,8 +49,14 @@ class TypeAliasCommonizer(
private fun createUnsafeNumberAnnotationIfNecessary(
targets: List<CommonizerTarget>,
settings: CommonizerSettings,
values: List<CirTypeAlias>,
): CirAnnotation? {
val isOptimisticCommonizationEnabled = settings.getSetting(OptimisticNumberCommonizationEnabledKey)
if (!isOptimisticCommonizationEnabled)
return null
val expandedTypes = values.map { it.expandedType.classifierId }
// All typealias have to be potentially substitutable (aka have to be some kind of number type)
@@ -5,16 +5,18 @@
package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.CommonizerSettings
import org.jetbrains.kotlin.commonizer.cir.*
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.commonizer.utils.safeCastValues
class TypeCommonizer(
private val classifiers: CirKnownClassifiers,
val options: Options = Options.default
private val settings: CommonizerSettings,
val options: Options = Options.default,
) : NullableSingleInvocationCommonizer<CirType> {
private val classOrTypeAliasTypeCommonizer = ClassOrTypeAliasTypeCommonizer(this, classifiers)
private val classOrTypeAliasTypeCommonizer = ClassOrTypeAliasTypeCommonizer(this, classifiers, settings)
private val flexibleTypeCommonizer = FlexibleTypeAssociativeCommonizer(this)
override fun invoke(values: List<CirType>): CirType? {
@@ -34,17 +36,11 @@ class TypeCommonizer(
}
data class Options(
val enableOptimisticNumberTypeCommonization: Boolean = true,
val enableCovariantNullabilityCommonization: Boolean = false,
val enableForwardTypeAliasSubstitution: Boolean = true,
val enableBackwardsTypeAliasSubstitution: Boolean = true,
) {
fun withOptimisticNumberTypeCommonizationEnabled(enabled: Boolean = true): Options {
return if (enableOptimisticNumberTypeCommonization == enabled) this
else copy(enableOptimisticNumberTypeCommonization = enabled)
}
fun withCovariantNullabilityCommonizationEnabled(enabled: Boolean = true): Options {
return if (enableCovariantNullabilityCommonization == enabled) this
else copy(enableCovariantNullabilityCommonization = enabled)
@@ -71,7 +67,7 @@ class TypeCommonizer(
fun withOptions(options: Options): TypeCommonizer {
return if (this.options == options) this
else TypeCommonizer(classifiers, options)
else TypeCommonizer(classifiers, settings, options)
}
inline fun withOptions(createNewOptions: Options.() -> Options): TypeCommonizer {
@@ -61,17 +61,17 @@ internal fun commonizeTarget(
)
val mergedTree = mergeCirTree(parameters.storageManager, classifiers, availableTrees)
val mergedTree = mergeCirTree(parameters.storageManager, classifiers, availableTrees, parameters.settings)
InlineTypeAliasCirNodeTransformer(parameters.storageManager, classifiers).invoke(mergedTree)
InlineTypeAliasCirNodeTransformer(parameters.storageManager, classifiers, parameters.settings).invoke(mergedTree)
ReApproximationCirNodeTransformer(
parameters.storageManager, classifiers,
parameters.storageManager, classifiers, parameters.settings,
SignatureBuildingContextProvider(classifiers, typeAliasInvariant = true, skipArguments = false)
).invoke(mergedTree)
ReApproximationCirNodeTransformer(
parameters.storageManager, classifiers,
parameters.storageManager, classifiers, parameters.settings,
SignatureBuildingContextProvider(classifiers, typeAliasInvariant = true, skipArguments = true)
).invoke(mergedTree)
@@ -18,7 +18,8 @@ internal class LibraryCommonizer internal constructor(
private val dependencies: Repository,
private val resultsConsumer: ResultsConsumer,
private val statsCollector: StatsCollector?,
private val logger: Logger
private val logger: Logger,
private val settings: CommonizerSettings,
) {
fun run() {
@@ -54,7 +55,8 @@ internal class LibraryCommonizer internal constructor(
dependenciesProvider = createDependenciesProvider(),
resultsConsumer = resultsConsumer,
statsCollector = statsCollector,
logger = logger
logger = logger,
settings = settings,
)
)
}
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.commonizer.cir.CirDeclaration
import org.jetbrains.kotlin.commonizer.cir.CirEntityId
import org.jetbrains.kotlin.commonizer.cir.CirTypeAliasRecursionMarker
import org.jetbrains.kotlin.commonizer.core.*
import org.jetbrains.kotlin.commonizer.CommonizerSettings
import org.jetbrains.kotlin.commonizer.utils.CommonizedGroup
import org.jetbrains.kotlin.storage.NullableLazyValue
import org.jetbrains.kotlin.storage.StorageManager
@@ -52,12 +53,13 @@ internal fun buildPropertyNode(
storageManager: StorageManager,
size: Int,
classifiers: CirKnownClassifiers,
settings: CommonizerSettings,
nodeRelationship: CirNodeRelationship? = null,
): CirPropertyNode = buildNode(
storageManager = storageManager,
size = size,
nodeRelationship = nodeRelationship,
commonizerProducer = { PropertyCommonizer(FunctionOrPropertyBaseCommonizer(TypeCommonizer(classifiers))) },
commonizerProducer = { PropertyCommonizer(FunctionOrPropertyBaseCommonizer(TypeCommonizer(classifiers, settings))) },
nodeProducer = ::CirPropertyNode
)
@@ -65,13 +67,14 @@ internal fun buildFunctionNode(
storageManager: StorageManager,
size: Int,
classifiers: CirKnownClassifiers,
settings: CommonizerSettings,
nodeRelationship: CirNodeRelationship?,
): CirFunctionNode = buildNode(
storageManager = storageManager,
size = size,
nodeRelationship = nodeRelationship,
commonizerProducer = {
val typeCommonizer = TypeCommonizer(classifiers)
val typeCommonizer = TypeCommonizer(classifiers, settings)
FunctionCommonizer(typeCommonizer, FunctionOrPropertyBaseCommonizer(typeCommonizer)).asCommonizer()
},
nodeProducer = ::CirFunctionNode
@@ -81,14 +84,15 @@ internal fun buildClassNode(
storageManager: StorageManager,
size: Int,
classifiers: CirKnownClassifiers,
settings: CommonizerSettings,
nodeRelationship: CirNodeRelationship?,
classId: CirEntityId
classId: CirEntityId,
): CirClassNode = buildNode(
storageManager = storageManager,
size = size,
nodeRelationship = nodeRelationship,
commonizerProducer = {
val typeCommonizer = TypeCommonizer(classifiers)
val typeCommonizer = TypeCommonizer(classifiers, settings)
ClassCommonizer(typeCommonizer, ClassSuperTypeCommonizer(classifiers, typeCommonizer))
},
recursionMarker = CirClassRecursionMarker,
@@ -104,12 +108,13 @@ internal fun buildClassConstructorNode(
storageManager: StorageManager,
size: Int,
classifiers: CirKnownClassifiers,
settings: CommonizerSettings,
nodeRelationship: CirNodeRelationship?,
): CirClassConstructorNode = buildNode(
storageManager = storageManager,
size = size,
nodeRelationship = nodeRelationship,
commonizerProducer = { ClassConstructorCommonizer(TypeCommonizer(classifiers)) },
commonizerProducer = { ClassConstructorCommonizer(TypeCommonizer(classifiers, settings)) },
nodeProducer = ::CirClassConstructorNode
)
@@ -117,12 +122,13 @@ internal fun buildTypeAliasNode(
storageManager: StorageManager,
size: Int,
classifiers: CirKnownClassifiers,
typeAliasId: CirEntityId
settings: CommonizerSettings,
typeAliasId: CirEntityId,
): CirTypeAliasNode = buildNode(
storageManager = storageManager,
size = size,
nodeRelationship = null,
commonizerProducer = { TypeAliasCommonizer(TypeCommonizer(classifiers), classifiers).asCommonizer() },
commonizerProducer = { TypeAliasCommonizer(TypeCommonizer(classifiers, settings), classifiers, settings = settings).asCommonizer() },
recursionMarker = CirTypeAliasRecursionMarker,
nodeProducer = { targetDeclarations, commonDeclaration ->
CirTypeAliasNode(typeAliasId, targetDeclarations, commonDeclaration).also {
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.commonizer.transformer
import org.jetbrains.kotlin.commonizer.CommonizerSettings
import org.jetbrains.kotlin.commonizer.cir.*
import org.jetbrains.kotlin.commonizer.mergedtree.*
import org.jetbrains.kotlin.commonizer.mergedtree.CirNodeRelationship.Composite.Companion.plus
@@ -17,6 +18,7 @@ import org.jetbrains.kotlin.storage.StorageManager
internal class InlineTypeAliasCirNodeTransformer(
private val storageManager: StorageManager,
private val classifiers: CirKnownClassifiers,
private val settings: CommonizerSettings,
) : CirNodeTransformer {
override fun invoke(root: CirRootNode) {
root.modules.values.forEach(::invoke)
@@ -86,21 +88,21 @@ internal class InlineTypeAliasCirNodeTransformer(
fromAliasedClassNode.constructors.forEach { (key, aliasedConstructorNode) ->
val aliasedConstructor = aliasedConstructorNode.targetDeclarations[targetIndex] ?: return@forEach
intoClassNode.constructors.getOrPut(key) {
buildClassConstructorNode(storageManager, targetSize, classifiers, ParentNode(intoClassNode))
buildClassConstructorNode(storageManager, targetSize, classifiers, settings, ParentNode(intoClassNode))
}.targetDeclarations[targetIndex] = aliasedConstructor.withContainingClass(intoClass)
}
fromAliasedClassNode.functions.forEach { (key, aliasedFunctionNode) ->
val aliasedFunction = aliasedFunctionNode.targetDeclarations[targetIndex] ?: return@forEach
intoClassNode.functions.getOrPut(key) {
buildFunctionNode(storageManager, targetSize, classifiers, ParentNode(intoClassNode))
buildFunctionNode(storageManager, targetSize, classifiers, settings, ParentNode(intoClassNode))
}.targetDeclarations[targetIndex] = aliasedFunction.withContainingClass(intoClass)
}
fromAliasedClassNode.properties.forEach { (key, aliasedPropertyNode) ->
val aliasedProperty = aliasedPropertyNode.targetDeclarations[targetIndex] ?: return@forEach
intoClassNode.properties.getOrPut(key) {
buildPropertyNode(storageManager, targetSize, classifiers, ParentNode(intoClassNode))
buildPropertyNode(storageManager, targetSize, classifiers, settings, ParentNode(intoClassNode))
}.targetDeclarations[targetIndex] = aliasedProperty.withContainingClass(intoClass)
}
}
@@ -115,7 +117,8 @@ internal class InlineTypeAliasCirNodeTransformer(
// Therefore, this artificial class node acts as a fallback with the original type-alias being still the preferred
// option for commonization
nodeRelationship = ParentNode(this) + PreferredNode(typeAliasNode),
classId = typeAliasNode.id
classId = typeAliasNode.id,
settings = settings,
)
this.classes[typeAliasNode.classifierName] = classNode
return classNode
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.commonizer.transformer
import org.jetbrains.kotlin.commonizer.CommonizerSettings
import org.jetbrains.kotlin.commonizer.cir.CirHasTypeParameters
import org.jetbrains.kotlin.commonizer.mergedtree.*
import org.jetbrains.kotlin.commonizer.mergedtree.CirNodeRelationship.ParentNode
@@ -15,7 +16,8 @@ import org.jetbrains.kotlin.storage.StorageManager
internal class ReApproximationCirNodeTransformer(
private val storageManager: StorageManager,
private val classifiers: CirKnownClassifiers,
private val signatureBuildingContextProvider: SignatureBuildingContextProvider
private val settings: CommonizerSettings,
private val signatureBuildingContextProvider: SignatureBuildingContextProvider,
) : CirNodeTransformer {
internal class SignatureBuildingContextProvider(
@@ -65,7 +67,7 @@ internal class ReApproximationCirNodeTransformer(
val approximationKey = FunctionApproximationKey.create(functionAtIndex, signatureBuildingContextProvider(context, functionAtIndex))
val newNode = parent.functions.getOrPut(approximationKey) {
buildFunctionNode(storageManager, parent.targetDeclarations.size, classifiers, ParentNode(parent))
buildFunctionNode(storageManager, parent.targetDeclarations.size, classifiers, settings, ParentNode(parent))
}
// Move declaration
@@ -82,7 +84,7 @@ internal class ReApproximationCirNodeTransformer(
val approximationKey = PropertyApproximationKey.create(propertyAtIndex, signatureBuildingContextProvider(context, propertyAtIndex))
val newNode = parent.properties.getOrPut(approximationKey) {
buildPropertyNode(storageManager, parent.targetDeclarations.size, classifiers, ParentNode(parent))
buildPropertyNode(storageManager, parent.targetDeclarations.size, classifiers, settings, ParentNode(parent))
}
// Move declaration
@@ -103,7 +105,7 @@ internal class ReApproximationCirNodeTransformer(
ConstructorApproximationKey.create(constructorAtIndex, signatureBuildingContextProvider(context, constructorAtIndex))
val newNode = parent.constructors.getOrPut(approximationKey) {
buildClassConstructorNode(storageManager, parent.targetDeclarations.size, classifiers, ParentNode(parent))
buildClassConstructorNode(storageManager, parent.targetDeclarations.size, classifiers, settings, ParentNode(parent))
}
// Move declaration
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.commonizer.tree
import org.jetbrains.kotlin.commonizer.TargetDependent
import org.jetbrains.kotlin.commonizer.cir.*
import org.jetbrains.kotlin.commonizer.CommonizerSettings
import org.jetbrains.kotlin.commonizer.mergedtree.*
import org.jetbrains.kotlin.commonizer.mergedtree.CirNodeRelationship.Companion.ParentNode
import org.jetbrains.kotlin.commonizer.mergedtree.CirNodeRelationship.ParentNode
@@ -17,13 +18,17 @@ internal data class TargetBuildingContext(
val storageManager: StorageManager,
val classifiers: CirKnownClassifiers,
val memberContext: CirMemberContext = CirMemberContext.empty,
val commonizerSettings: CommonizerSettings,
val targets: Int, val targetIndex: Int
) {
fun withMemberContextOf(clazz: CirClass) = copy(memberContext = memberContext.withContextOf(clazz))
}
internal fun mergeCirTree(
storageManager: StorageManager, classifiers: CirKnownClassifiers, roots: TargetDependent<CirTreeRoot>
storageManager: StorageManager,
classifiers: CirKnownClassifiers,
roots: TargetDependent<CirTreeRoot>,
settings: CommonizerSettings,
): CirRootNode {
val node = buildRootNode(storageManager, classifiers.commonDependencies, roots.size)
roots.targets.withIndex().forEach { (targetIndex, target) ->
@@ -33,6 +38,7 @@ internal fun mergeCirTree(
storageManager = storageManager,
classifiers = classifiers,
memberContext = CirMemberContext.empty,
commonizerSettings = settings,
targets = roots.size,
targetIndex = targetIndex
), roots[target].modules
@@ -68,7 +74,14 @@ internal fun CirNodeWithMembers<*, *>.buildClass(
context: TargetBuildingContext, treeClass: CirTreeClass, parent: CirNode<*, *>? = null
) {
val classNode = classes.getOrPut(treeClass.clazz.name) {
buildClassNode(context.storageManager, context.targets, context.classifiers, ParentNode(parent), treeClass.id)
buildClassNode(
context.storageManager,
context.targets,
context.classifiers,
context.commonizerSettings,
ParentNode(parent),
treeClass.id,
)
}
classNode.targetDeclarations[context.targetIndex] = treeClass.clazz
val contextWithClass = context.withMemberContextOf(treeClass.clazz)
@@ -84,7 +97,7 @@ internal fun CirNodeWithMembers<*, *>.buildFunction(
val functionNode = functions.getOrPut(
FunctionApproximationKey.create(function, SignatureBuildingContext(context.memberContext, function))
) {
buildFunctionNode(context.storageManager, context.targets, context.classifiers, ParentNode(parent))
buildFunctionNode(context.storageManager, context.targets, context.classifiers, context.commonizerSettings, ParentNode(parent))
}
/* Multiple type substitutions could in result in the same commonization result */
functionNode.targetDeclarations.set(context.targetIndex, function)
@@ -96,7 +109,7 @@ internal fun CirNodeWithMembers<*, *>.buildProperty(
val propertyNode = properties.getOrPut(
PropertyApproximationKey.create(property, SignatureBuildingContext(context.memberContext, property))
) {
buildPropertyNode(context.storageManager, context.targets, context.classifiers, ParentNode(parent))
buildPropertyNode(context.storageManager, context.targets, context.classifiers, context.commonizerSettings, ParentNode(parent))
}
/* Multiple type substitutions could in result in the same commonization result */
propertyNode.targetDeclarations.set(context.targetIndex, property)
@@ -108,7 +121,13 @@ internal fun CirClassNode.buildConstructor(
val constructorNode = constructors.getOrPut(
ConstructorApproximationKey.create(constructor, SignatureBuildingContext(context.memberContext, constructor))
) {
buildClassConstructorNode(context.storageManager, context.targets, context.classifiers, ParentNode(parent))
buildClassConstructorNode(
context.storageManager,
context.targets,
context.classifiers,
context.commonizerSettings,
ParentNode(parent),
)
}
/* Multiple type substitutions could in result in the same commonization result */
constructorNode.targetDeclarations.set(context.targetIndex, constructor)
@@ -116,7 +135,7 @@ internal fun CirClassNode.buildConstructor(
internal fun CirPackageNode.buildTypeAlias(context: TargetBuildingContext, treeTypeAlias: CirTreeTypeAlias) {
val typeAliasNode = typeAliases.getOrPut(treeTypeAlias.typeAlias.name) {
buildTypeAliasNode(context.storageManager, context.targets, context.classifiers, treeTypeAlias.id)
buildTypeAliasNode(context.storageManager, context.targets, context.classifiers, context.commonizerSettings, treeTypeAlias.id)
}
typeAliasNode.targetDeclarations[context.targetIndex] = treeTypeAlias.typeAlias
}
@@ -194,7 +194,8 @@ private class AnalyzedModules(
fun toCommonizerParameters(
resultsConsumer: ResultsConsumer,
manifestDataProvider: (CommonizerTarget) -> NativeManifestDataProvider = { MockNativeManifestDataProvider(it) }
manifestDataProvider: (CommonizerTarget) -> NativeManifestDataProvider = { MockNativeManifestDataProvider(it) },
commonizerSettings: CommonizerSettings = DefaultCommonizerSettings,
) = CommonizerParameters(
outputTargets = setOf(SharedCommonizerTarget(leafTargets.toSet())),
manifestProvider = TargetDependent(sharedTarget.withAllLeaves(), manifestDataProvider),
@@ -211,6 +212,7 @@ private class AnalyzedModules(
)
},
resultsConsumer = resultsConsumer,
settings = commonizerSettings,
)
companion object {
@@ -27,7 +27,8 @@ abstract class AbstractInlineSourcesCommonizationTest : KtInlineSourceCommonizer
data class Parameters(
val outputTargets: Set<SharedCommonizerTarget>,
val dependencies: TargetDependent<List<InlineSourceBuilder.Module>>,
val targets: List<Target>
val targets: List<Target>,
val settings: CommonizerSettings,
)
data class Target(
@@ -105,10 +106,24 @@ abstract class AbstractInlineSourcesCommonizationTest : KtInlineSourceCommonizer
simpleSingleSourceTarget(parseCommonizerTarget(target), sourceCode)
}
@InlineSourcesCommonizationTestDsl
fun <T : Any> setting(type: CommonizerSettings.Key<T>, value: T) {
val setting = MapBasedCommonizerSettings.Setting(type, value)
check(setting.key !in settings.map { it.key }) {
"An attempt to add the same setting '${type::class.java.simpleName}' multiple times. " +
"Current value: '$value'; Previous value: '${settings.find { it.key == setting.key }!!.settingValue}'"
}
settings.add(setting)
}
private val settings: MutableSet<MapBasedCommonizerSettings.Setting<*>> = LinkedHashSet()
fun build(): Parameters = Parameters(
outputTargets = outputTargets ?: setOf(SharedCommonizerTarget(targets.map { it.target }.allLeaves())),
dependencies = dependencies.toTargetDependent(),
targets = targets.toList()
targets = targets.toList(),
settings = MapBasedCommonizerSettings(*settings.toTypedArray()),
)
}
@@ -162,7 +177,7 @@ abstract class AbstractInlineSourcesCommonizationTest : KtInlineSourceCommonizer
private fun Parameters.toCommonizerParameters(
resultsConsumer: ResultsConsumer,
manifestDataProvider: (CommonizerTarget) -> NativeManifestDataProvider = { MockNativeManifestDataProvider(it) }
manifestDataProvider: (CommonizerTarget) -> NativeManifestDataProvider = { MockNativeManifestDataProvider(it) },
): CommonizerParameters {
return CommonizerParameters(
outputTargets = outputTargets,
@@ -181,7 +196,8 @@ abstract class AbstractInlineSourcesCommonizationTest : KtInlineSourceCommonizer
modulesProvider = MockModulesProvider.create(target.modules.map { createModuleDescriptor(it) })
)
},
resultsConsumer = resultsConsumer
resultsConsumer = resultsConsumer,
settings = settings,
)
}
}
@@ -67,7 +67,8 @@ class CommonizerFacadeTest {
private fun Map<String, List<String>>.toCommonizerParameters(
resultsConsumer: ResultsConsumer,
manifestDataProvider: (CommonizerTarget) -> NativeManifestDataProvider = { MockNativeManifestDataProvider(it) }
manifestDataProvider: (CommonizerTarget) -> NativeManifestDataProvider = { MockNativeManifestDataProvider(it) },
commonizerSettings: CommonizerSettings = DefaultCommonizerSettings,
): CommonizerParameters {
val targetDependentModuleNames = mapKeys { (targetName, _) -> LeafCommonizerTarget(targetName) }.toTargetDependent()
val sharedTarget = SharedCommonizerTarget(targetDependentModuleNames.targets.allLeaves())
@@ -83,6 +84,7 @@ class CommonizerFacadeTest {
)
},
resultsConsumer = resultsConsumer,
settings = commonizerSettings,
)
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.commonizer
import kotlin.test.assertFails
import kotlin.test.assertFailsWith
class InlineSourceCommonizationHealthCheckTest : AbstractInlineSourcesCommonizationTest() {
fun `test reference module with error diagnostics breaks tests`() {
@@ -19,4 +20,14 @@ class InlineSourceCommonizationHealthCheckTest : AbstractInlineSourcesCommonizat
result.assertCommonized("(a, b)", "expect class X() : kotlin.MissingSupertype")
}
}
fun `test duplicated settings are forbidden`() {
assertFailsWith<IllegalStateException>("Defining a setting multiple times should be forbidden") {
commonize {
outputTarget("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
setting(OptimisticNumberCommonizationEnabledKey, false)
}
}
}
}
@@ -6,13 +6,14 @@
package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.AbstractInlineSourcesCommonizationTest
import org.jetbrains.kotlin.commonizer.DefaultCommonizerSettings
import org.jetbrains.kotlin.commonizer.core.ExtensionReceiverCommonizer.Commonized
import org.jetbrains.kotlin.commonizer.utils.MOCK_CLASSIFIERS
import org.jetbrains.kotlin.commonizer.utils.mockExtensionReceiver
class ExtensionReceiverCommonizerTest : AbstractInlineSourcesCommonizationTest() {
private val commonizer = ExtensionReceiverCommonizer(TypeCommonizer(MOCK_CLASSIFIERS))
private val commonizer = ExtensionReceiverCommonizer(TypeCommonizer(MOCK_CLASSIFIERS, DefaultCommonizerSettings))
fun `test null receiver`() {
assertEquals(
@@ -5,11 +5,8 @@
package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.AbstractInlineSourcesCommonizationTest
import org.jetbrains.kotlin.commonizer.LeafCommonizerTarget
import org.jetbrains.kotlin.commonizer.TargetDependent
import org.jetbrains.kotlin.commonizer.*
import org.jetbrains.kotlin.commonizer.cir.CirType
import org.jetbrains.kotlin.commonizer.mapValue
import org.jetbrains.kotlin.commonizer.mergedtree.CirClassifierIndex
import org.jetbrains.kotlin.commonizer.mergedtree.CirCommonizedClassifierNodes
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
@@ -107,10 +104,10 @@ class TypeCommonizerTest : AbstractInlineSourcesCommonizationTest() {
commonizedNodes = CirCommonizedClassifierNodes.default(),
commonDependencies = commonDependencies
).also { classifiers ->
mergeCirTree(LockBasedStorageManager.NO_LOCKS, classifiers, roots)
mergeCirTree(LockBasedStorageManager.NO_LOCKS, classifiers, roots, settings = DefaultCommonizerSettings)
}
return TypeCommonizer(classifiers)
return TypeCommonizer(classifiers, DefaultCommonizerSettings)
}
@@ -624,7 +621,7 @@ class TypeCommonizerTest : AbstractInlineSourcesCommonizationTest() {
companion object {
fun areEqual(classifiers: CirKnownClassifiers, a: CirType, b: CirType): Boolean =
TypeCommonizer(classifiers).invoke(listOf(a, b)) != null
TypeCommonizer(classifiers, DefaultCommonizerSettings).invoke(listOf(a, b)) != null
}
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.DefaultCommonizerSettings
import org.jetbrains.kotlin.commonizer.cir.CirName
import org.jetbrains.kotlin.commonizer.cir.CirTypeParameter
import org.jetbrains.kotlin.commonizer.utils.MOCK_CLASSIFIERS
@@ -13,7 +14,7 @@ import org.jetbrains.kotlin.types.Variance
import org.junit.Test
class TypeParameterCommonizerTest : AbstractCommonizerTest<CirTypeParameter, CirTypeParameter?>() {
override fun createCommonizer() = TypeParameterCommonizer(TypeCommonizer(MOCK_CLASSIFIERS))
override fun createCommonizer() = TypeParameterCommonizer(TypeCommonizer(MOCK_CLASSIFIERS, DefaultCommonizerSettings))
@Test
fun allAreReified() = doTestSuccess(
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.DefaultCommonizerSettings
import org.jetbrains.kotlin.commonizer.cir.CirTypeParameter
import org.jetbrains.kotlin.commonizer.utils.MOCK_CLASSIFIERS
import org.junit.Test
@@ -108,7 +109,7 @@ class TypeParameterListCommonizerTest : AbstractCommonizerTest<List<CirTypeParam
)
)
override fun createCommonizer() = TypeParameterListCommonizer(TypeCommonizer(MOCK_CLASSIFIERS))
override fun createCommonizer() = TypeParameterListCommonizer(TypeCommonizer(MOCK_CLASSIFIERS, DefaultCommonizerSettings))
private companion object {
fun mockTypeParams(vararg params: Pair<String, String>): List<CirTypeParameter> {
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.DefaultCommonizerSettings
import org.jetbrains.kotlin.commonizer.cir.CirName
import org.jetbrains.kotlin.commonizer.cir.CirValueParameter
import org.jetbrains.kotlin.commonizer.core.TypeCommonizerTest.Companion.areEqual
@@ -137,7 +138,7 @@ class ValueParameterCommonizerTest : AbstractCommonizerTest<CirValueParameter, C
mockValueParam("kotlin/String", declaresDefaultValue = true)
)
override fun createCommonizer() = ValueParameterCommonizer(TypeCommonizer(MOCK_CLASSIFIERS))
override fun createCommonizer() = ValueParameterCommonizer(TypeCommonizer(MOCK_CLASSIFIERS, DefaultCommonizerSettings))
override fun areEqual(a: CirValueParameter?, b: CirValueParameter?) =
(a === b) || (a != null && b != null && areEqual(MOCK_CLASSIFIERS, a, b))
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.DefaultCommonizerSettings
import org.jetbrains.kotlin.commonizer.cir.CirValueParameter
import org.jetbrains.kotlin.commonizer.utils.MOCK_CLASSIFIERS
import org.junit.Test
@@ -156,7 +157,7 @@ class ValueParameterListCommonizerTest : AbstractCommonizerTest<List<CirValuePar
)
}
override fun createCommonizer() = ValueParameterListCommonizer(TypeCommonizer(MOCK_CLASSIFIERS))
override fun createCommonizer() = ValueParameterListCommonizer(TypeCommonizer(MOCK_CLASSIFIERS, DefaultCommonizerSettings))
override fun areEqual(a: List<CirValueParameter>?, b: List<CirValueParameter>?): Boolean {
if (a === b)
@@ -0,0 +1,56 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.commonizer.hierarchical
import org.jetbrains.kotlin.commonizer.AbstractInlineSourcesCommonizationTest
import org.jetbrains.kotlin.commonizer.OptimisticNumberCommonizationEnabledKey
import org.jetbrains.kotlin.commonizer.assertCommonized
class DisabledOptimisticNumberCommonizationTest : AbstractInlineSourcesCommonizationTest() {
fun `test non-platform types`() {
val result = commonize {
outputTarget("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, false)
registerFakeStdlibIntegersDependency("(a, b)")
"a" withSource """
typealias X = Short
""".trimIndent()
"b" withSource """
typealias X = Int
""".trimIndent()
}
result.assertCommonized(
"(a, b)", """
expect class X : Number
""".trimIndent()
)
}
fun `test platform types`() {
val result = commonize {
outputTarget("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, false)
registerFakeStdlibIntegersDependency("(a, b)")
"a" withSource """
typealias X = Int
""".trimIndent()
"b" withSource """
typealias X = Long
""".trimIndent()
}
result.assertCommonized(
"(a, b)", """
expect class X : Number
""".trimIndent()
)
}
}
@@ -5,19 +5,15 @@
package org.jetbrains.kotlin.commonizer.hierarchical
import org.jetbrains.kotlin.commonizer.AbstractInlineSourcesCommonizationTest
import org.jetbrains.kotlin.commonizer.AbstractInlineSourcesCommonizationTest.ParametersBuilder
import org.jetbrains.kotlin.commonizer.assertCommonized
import org.jetbrains.kotlin.commonizer.parseCommonizerTarget
import org.jetbrains.kotlin.commonizer.utils.InlineSourceBuilder
import org.jetbrains.kotlin.commonizer.withAllLeaves
import org.jetbrains.kotlin.commonizer.*
class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCommonizationTest() {
fun `test Byte and Byte - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = Byte")
simpleSingleSourceTarget("b", "typealias X = Byte")
}
@@ -33,7 +29,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test Byte and Short - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = Byte")
simpleSingleSourceTarget("b", "typealias X = Short")
}
@@ -50,7 +47,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test Byte and Int - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = Byte")
simpleSingleSourceTarget("b", "typealias X = Int")
}
@@ -67,7 +65,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test Byte and Long - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = Byte")
simpleSingleSourceTarget("b", "typealias X = Long")
}
@@ -84,7 +83,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test Short and Byte - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = Short")
simpleSingleSourceTarget("b", "typealias X = Byte")
}
@@ -101,7 +101,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test Short and Short - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = Short")
simpleSingleSourceTarget("b", "typealias X = Short")
}
@@ -117,7 +118,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test Short and Int - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = Short")
simpleSingleSourceTarget("b", "typealias X = Int")
}
@@ -134,7 +136,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test Short and Long - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = Short")
simpleSingleSourceTarget("b", "typealias X = Long")
}
@@ -151,7 +154,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test Int and Byte - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = Int")
simpleSingleSourceTarget("b", "typealias X = Byte")
}
@@ -168,7 +172,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test Int and Short - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = Int")
simpleSingleSourceTarget("b", "typealias X = Short")
}
@@ -185,7 +190,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test Int and Int - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = Int")
simpleSingleSourceTarget("b", "typealias X = Int")
}
@@ -201,7 +207,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test Int and Long - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = Int")
simpleSingleSourceTarget("b", "typealias X = Long")
}
@@ -218,7 +225,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test Long and Byte - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = Long")
simpleSingleSourceTarget("b", "typealias X = Byte")
}
@@ -235,7 +243,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test Long and Short - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = Long")
simpleSingleSourceTarget("b", "typealias X = Short")
}
@@ -252,7 +261,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test Long and Int - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = Long")
simpleSingleSourceTarget("b", "typealias X = Int")
}
@@ -269,7 +279,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test Long and Long - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = Long")
simpleSingleSourceTarget("b", "typealias X = Long")
}
@@ -285,7 +296,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test UByte and UByte - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = UByte")
simpleSingleSourceTarget("b", "typealias X = UByte")
}
@@ -301,7 +313,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test UByte and UShort - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = UByte")
simpleSingleSourceTarget("b", "typealias X = UShort")
}
@@ -318,7 +331,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test UByte and UInt - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = UByte")
simpleSingleSourceTarget("b", "typealias X = UInt")
}
@@ -335,7 +349,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test UByte and ULong - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = UByte")
simpleSingleSourceTarget("b", "typealias X = ULong")
}
@@ -352,7 +367,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test UShort and UByte - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = UShort")
simpleSingleSourceTarget("b", "typealias X = UByte")
}
@@ -369,7 +385,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test UShort and UShort - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = UShort")
simpleSingleSourceTarget("b", "typealias X = UShort")
}
@@ -385,7 +402,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test UShort and UInt - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = UShort")
simpleSingleSourceTarget("b", "typealias X = UInt")
}
@@ -402,7 +420,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test UShort and ULong - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = UShort")
simpleSingleSourceTarget("b", "typealias X = ULong")
}
@@ -419,7 +438,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test UInt and UByte - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = UInt")
simpleSingleSourceTarget("b", "typealias X = UByte")
}
@@ -436,7 +456,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test UInt and UShort - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = UInt")
simpleSingleSourceTarget("b", "typealias X = UShort")
}
@@ -453,7 +474,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test UInt and UInt - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = UInt")
simpleSingleSourceTarget("b", "typealias X = UInt")
}
@@ -469,7 +491,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test UInt and ULong - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = UInt")
simpleSingleSourceTarget("b", "typealias X = ULong")
}
@@ -486,7 +509,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test ULong and UByte - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = ULong")
simpleSingleSourceTarget("b", "typealias X = UByte")
}
@@ -503,7 +527,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test ULong and UShort - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = ULong")
simpleSingleSourceTarget("b", "typealias X = UShort")
}
@@ -520,7 +545,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test ULong and UInt - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = ULong")
simpleSingleSourceTarget("b", "typealias X = UInt")
}
@@ -537,7 +563,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test ULong and ULong - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = ULong")
simpleSingleSourceTarget("b", "typealias X = ULong")
}
@@ -548,7 +575,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test UInt and Long - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = UInt")
simpleSingleSourceTarget("b", "typealias X = Long")
}
@@ -559,7 +587,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test UIntVarOf and ULongVarOf - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = kotlinx.cinterop.UIntVarOf")
simpleSingleSourceTarget("b", "typealias X = kotlinx.cinterop.ULongVarOf")
}
@@ -575,7 +604,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test IntVarOf and LongVarOf - typealias`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget("a", "typealias X = kotlinx.cinterop.IntVarOf")
simpleSingleSourceTarget("b", "typealias X = kotlinx.cinterop.LongVarOf")
}
@@ -591,7 +621,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test Int and Long - typealias chain`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget(
"a", """
@@ -626,6 +657,7 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test function with pure number types parameter`() {
val result = commonize {
outputTarget("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
simpleSingleSourceTarget("a", "fun x(p: Int) {}")
simpleSingleSourceTarget("b", "fun x(p: Long) {}")
}
@@ -644,7 +676,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test function with aliased number value parameter`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget(
"a", """
typealias A = Int
@@ -673,6 +706,7 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test property with pure number return type`() {
val result = commonize {
outputTarget("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerDependency("a", "b", "(a, b)") { unsignedIntegers() }
simpleSingleSourceTarget("a", "val x: UInt = null!!")
simpleSingleSourceTarget("b", "val x: ULong = null!!")
@@ -684,7 +718,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test property with aliased number return type`() {
val result = commonize {
outputTarget("(a, b)")
registerFakeStdlibDependency("(a, b)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)")
simpleSingleSourceTarget(
"a", """
typealias X = UShort
@@ -711,7 +746,8 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
fun `test multilevel hierarchy`() {
val result = commonize {
outputTarget("(a, b)", "(c, d)", "(e, f)", "(c, d, e, f)", "(a, b, c, d, e, f)")
registerFakeStdlibDependency("(a, b)", "(c, d)", "(e, f)", "(c, d, e, f)", "(a, b, c, d, e, f)")
setting(OptimisticNumberCommonizationEnabledKey, true)
registerFakeStdlibIntegersDependency("(a, b)", "(c, d)", "(e, f)", "(c, d, e, f)", "(a, b, c, d, e, f)")
simpleSingleSourceTarget("a", "typealias X = Short")
simpleSingleSourceTarget("b", "typealias X = Int")
simpleSingleSourceTarget("c", "typealias X = Int")
@@ -754,69 +790,4 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
""".trimIndent()
)
}
}
private fun ParametersBuilder.registerFakeStdlibDependency(vararg outputTarget: String) {
val allTargets = outputTarget.map { parseCommonizerTarget(it) }.withAllLeaves()
registerDependency(*allTargets.toTypedArray()) {
unsignedIntegers()
unsingedVarIntegers()
singedVarIntegers()
unsafeNumberAnnotationSource()
}
}
private fun InlineSourceBuilder.ModuleBuilder.unsignedIntegers() {
source(
"""
package kotlin
class UByte
class UShort
class UInt
class ULong
""".trimIndent(), "unsigned.kt"
)
}
private fun InlineSourceBuilder.ModuleBuilder.unsingedVarIntegers() {
source(
"""
package kotlinx.cinterop
class UByteVarOf
class UShortVarOf
class UIntVarOf
class ULongVarOf
""".trimIndent(), "UnsignedVarOf.kt"
)
}
private fun InlineSourceBuilder.ModuleBuilder.singedVarIntegers() {
source(
"""
package kotlinx.cinterop
class ByteVarOf
class ShortVarOf
class IntVarOf
class LongVarOf
""".trimIndent(), "SignedVarOf.kt"
)
}
internal fun InlineSourceBuilder.ModuleBuilder.unsafeNumberAnnotationSource() {
source(
"""
package kotlinx.cinterop
@Target(AnnotationTarget.TYPEALIAS)
@Retention(AnnotationRetention.BINARY)
annotation class UnsafeNumber(val actualPlatformTypes: Array<String>)
""".trimIndent(),
"UnsafeNumberAnnotation.kt"
)
source(
"""
typealias UnsafeNumber = kotlinx.cinterop.UnsafeNumber
""".trimIndent(),
"UnsafeNumberTypeAlias.kt"
)
}
@@ -0,0 +1,76 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.commonizer.hierarchical
import org.jetbrains.kotlin.commonizer.AbstractInlineSourcesCommonizationTest
import org.jetbrains.kotlin.commonizer.parseCommonizerTarget
import org.jetbrains.kotlin.commonizer.utils.InlineSourceBuilder
import org.jetbrains.kotlin.commonizer.withAllLeaves
internal fun AbstractInlineSourcesCommonizationTest.ParametersBuilder.registerFakeStdlibIntegersDependency(vararg outputTarget: String) {
val allTargets = outputTarget.map { parseCommonizerTarget(it) }.withAllLeaves()
registerDependency(*allTargets.toTypedArray()) {
unsignedIntegers()
unsingedVarIntegers()
singedVarIntegers()
unsafeNumberAnnotationSource()
}
}
internal fun InlineSourceBuilder.ModuleBuilder.unsignedIntegers() {
source(
"""
package kotlin
class UByte
class UShort
class UInt
class ULong
""".trimIndent(), "unsigned.kt"
)
}
private fun InlineSourceBuilder.ModuleBuilder.unsingedVarIntegers() {
source(
"""
package kotlinx.cinterop
class UByteVarOf
class UShortVarOf
class UIntVarOf
class ULongVarOf
""".trimIndent(), "UnsignedVarOf.kt"
)
}
private fun InlineSourceBuilder.ModuleBuilder.singedVarIntegers() {
source(
"""
package kotlinx.cinterop
class ByteVarOf
class ShortVarOf
class IntVarOf
class LongVarOf
""".trimIndent(), "SignedVarOf.kt"
)
}
internal fun InlineSourceBuilder.ModuleBuilder.unsafeNumberAnnotationSource() {
source(
"""
package kotlinx.cinterop
@Target(AnnotationTarget.TYPEALIAS)
@Retention(AnnotationRetention.BINARY)
annotation class UnsafeNumber(val actualPlatformTypes: Array<String>)
""".trimIndent(),
"UnsafeNumberAnnotation.kt"
)
source(
"""
typealias UnsafeNumber = kotlinx.cinterop.UnsafeNumber
""".trimIndent(),
"UnsafeNumberTypeAlias.kt"
)
}
@@ -1,5 +1,6 @@
package org.jetbrains.kotlin.commonizer.transformer
import org.jetbrains.kotlin.commonizer.DefaultCommonizerSettings
import org.jetbrains.kotlin.commonizer.LeafCommonizerTarget
import org.jetbrains.kotlin.commonizer.TargetDependent
import org.jetbrains.kotlin.commonizer.cir.*
@@ -92,8 +93,8 @@ class InlineTypeAliasCirNodeTransformerTest : KtInlineSourceCommonizerTestCase()
)
)
val mergedTree = mergeCirTree(LockBasedStorageManager.NO_LOCKS, classifiers, roots)
InlineTypeAliasCirNodeTransformer(LockBasedStorageManager.NO_LOCKS, classifiers).invoke(mergedTree)
val mergedTree = mergeCirTree(LockBasedStorageManager.NO_LOCKS, classifiers, roots, DefaultCommonizerSettings)
InlineTypeAliasCirNodeTransformer(LockBasedStorageManager.NO_LOCKS, classifiers, DefaultCommonizerSettings).invoke(mergedTree)
val pkg = mergedTree.modules.values.single().packages.getValue(CirPackageName.create("pkg"))
val xClassNode = kotlin.test.assertNotNull(pkg.classes[CirName.create("X")])
@@ -183,8 +184,8 @@ class InlineTypeAliasCirNodeTransformerTest : KtInlineSourceCommonizerTestCase()
commonDependencies = CirProvidedClassifiers.EMPTY
)
val mergedTree = mergeCirTree(LockBasedStorageManager.NO_LOCKS, classifiers, roots)
InlineTypeAliasCirNodeTransformer(LockBasedStorageManager.NO_LOCKS, classifiers).invoke(mergedTree)
val mergedTree = mergeCirTree(LockBasedStorageManager.NO_LOCKS, classifiers, roots, DefaultCommonizerSettings)
InlineTypeAliasCirNodeTransformer(LockBasedStorageManager.NO_LOCKS, classifiers, DefaultCommonizerSettings).invoke(mergedTree)
val pkg = mergedTree.modules.values.single().packages.getValue(CirPackageName.create("pkg"))
val xClassNode = kotlin.test.assertNotNull(pkg.classes[CirName.create("X")])
@@ -8,6 +8,7 @@
package org.jetbrains.kotlin.commonizer.tree.merge
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.commonizer.DefaultCommonizerSettings
import org.jetbrains.kotlin.commonizer.LeafCommonizerTarget
import org.jetbrains.kotlin.commonizer.TargetDependent
import org.jetbrains.kotlin.commonizer.mergedtree.*
@@ -22,7 +23,12 @@ abstract class AbstractMergeCirTreeTest : KtInlineSourceCommonizerTestCase() {
private val storageManager = LockBasedStorageManager(this::class.simpleName)
fun mergeCirTree(vararg modules: Pair<String, CirTreeModule>): CirRootNode {
return org.jetbrains.kotlin.commonizer.tree.mergeCirTree(storageManager, createDefaultKnownClassifiers(), TargetDependent(*modules))
return org.jetbrains.kotlin.commonizer.tree.mergeCirTree(
storageManager,
createDefaultKnownClassifiers(),
TargetDependent(*modules),
DefaultCommonizerSettings
)
}
fun CirRootNode.assertSingleModule(): CirModuleNode {