diff --git a/build-common/src/org/jetbrains/kotlin/compilerRunner/argumentsToStrings.kt b/build-common/src/org/jetbrains/kotlin/compilerRunner/argumentsToStrings.kt index b197f3b80fb..8c69d338aed 100644 --- a/build-common/src/org/jetbrains/kotlin/compilerRunner/argumentsToStrings.kt +++ b/build-common/src/org/jetbrains/kotlin/compilerRunner/argumentsToStrings.kt @@ -10,6 +10,7 @@ package org.jetbrains.kotlin.compilerRunner import org.jetbrains.kotlin.cli.common.arguments.Argument import org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments import org.jetbrains.kotlin.cli.common.arguments.isAdvanced +import org.jetbrains.kotlin.cli.common.arguments.resolvedDelimiter import kotlin.reflect.KClass import kotlin.reflect.full.findAnnotation import kotlin.reflect.full.memberProperties @@ -31,8 +32,8 @@ internal fun toArgumentStrings(thisArguments: T, type: val rawPropertyValue = property.get(thisArguments) val rawDefaultValue = property.get(defaultArguments) - /* Default value can be omitted when not marked as 'isExplicit' */ - if (rawPropertyValue == rawDefaultValue && !argumentAnnotation.isExplicit) { + /* Default value can be omitted */ + if (rawPropertyValue == rawDefaultValue) { return@forEach } @@ -78,8 +79,8 @@ internal fun toArgumentStrings(thisArguments: T, type: private fun getArgumentStringValue(argumentAnnotation: Argument, values: Array<*>?): List { if (values.isNullOrEmpty()) return emptyList() - val delimiter = argumentAnnotation.delimiter - return if (delimiter.isEmpty()) values.map { it.toString() } + val delimiter = argumentAnnotation.resolvedDelimiter + return if (delimiter.isNullOrEmpty()) values.map { it.toString() } else listOf(values.joinToString(delimiter)) } diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt index 9f374c67666..eeb28c2093c 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt @@ -188,7 +188,7 @@ abstract class CommonCompilerArguments : CommonToolArguments() { value = "-Xcompiler-plugin", valueDescription = ",:=,=", description = "Register compiler plugin", - delimiter = "" + delimiter = Argument.Delimiters.none ) var pluginConfigurations: Array? = null set(value) { diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2NativeCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2NativeCompilerArguments.kt index 74f37d0dbe7..80e9a8a99fc 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2NativeCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2NativeCompilerArguments.kt @@ -44,7 +44,7 @@ class K2NativeCompilerArguments : CommonCompilerArguments() { @Argument(value="-include-binary", deprecatedName = "-includeBinary", shortName = "-ib", valueDescription = "", description = "Pack external binary within the klib") var includeBinaries: Array? = null - @Argument(value = "-library", shortName = "-l", valueDescription = "", description = "Link with the library", delimiter = "") + @Argument(value = "-library", shortName = "-l", valueDescription = "", description = "Link with the library", delimiter = Argument.Delimiters.none) var libraries: Array? = null @Argument(value = "-library-version", shortName = "-lv", valueDescription = "", description = "Set library version") @@ -76,7 +76,7 @@ class K2NativeCompilerArguments : CommonCompilerArguments() { deprecatedName = "-nativelibrary", shortName = "-nl", valueDescription = "", - description = "Include the native bitcode library", delimiter = "" + description = "Include the native bitcode library", delimiter = Argument.Delimiters.none ) var nativeLibraries: Array? = null @@ -95,7 +95,7 @@ class K2NativeCompilerArguments : CommonCompilerArguments() { @Argument(value="-linker-options", deprecatedName = "-linkerOpts", valueDescription = "", description = "Pass arguments to linker", delimiter = " ") var linkerArguments: Array? = null - @Argument(value="-linker-option", valueDescription = "", description = "Pass argument to linker", delimiter = "") + @Argument(value="-linker-option", valueDescription = "", description = "Pass argument to linker", delimiter = Argument.Delimiters.none) var singleLinkerArguments: Array? = null @Argument(value = "-nostdlib", description = "Don't link with stdlib") @@ -138,7 +138,7 @@ class K2NativeCompilerArguments : CommonCompilerArguments() { value = "-Xcache-directory", valueDescription = "", description = "Path to the directory containing caches", - delimiter = "" + delimiter = Argument.Delimiters.none ) var cacheDirectories: Array? = null @@ -146,7 +146,7 @@ class K2NativeCompilerArguments : CommonCompilerArguments() { value = CACHED_LIBRARY, valueDescription = ",", description = "Comma-separated paths of a library and its cache", - delimiter = "" + delimiter = Argument.Delimiters.none ) var cachedLibraries: Array? = null @@ -155,7 +155,7 @@ class K2NativeCompilerArguments : CommonCompilerArguments() { valueDescription = "", description = "Path to the root directory from which dependencies are to be cached automatically.\n" + "By default caches will be placed into the kotlin-native system cache directory.", - delimiter = "" + delimiter = Argument.Delimiters.none ) var autoCacheableFrom: Array? = null @@ -163,7 +163,7 @@ class K2NativeCompilerArguments : CommonCompilerArguments() { value = "-Xauto-cache-dir", valueDescription = "", description = "Path to the directory where to put caches for auto-cacheable dependencies", - delimiter = "" + delimiter = Argument.Delimiters.none ) var autoCacheDir: String? = null @@ -184,7 +184,7 @@ class K2NativeCompilerArguments : CommonCompilerArguments() { valueDescription = "", description = "A library to be included into produced framework API.\n" + "Must be one of libraries passed with '-library'", - delimiter = "" + delimiter = Argument.Delimiters.none ) var exportedLibraries: Array? = null @@ -232,7 +232,7 @@ class K2NativeCompilerArguments : CommonCompilerArguments() { value = ADD_CACHE, valueDescription = "", description = "Path to the library to be added to cache", - delimiter = "" + delimiter = Argument.Delimiters.none ) var libraryToAddToCache: String? = null @@ -240,7 +240,7 @@ class K2NativeCompilerArguments : CommonCompilerArguments() { value = "-Xfile-to-cache", valueDescription = "", description = "Path to file to cache", - delimiter = "" + delimiter = Argument.Delimiters.none ) var filesToCache: Array? = null @@ -341,7 +341,7 @@ class K2NativeCompilerArguments : CommonCompilerArguments() { valueDescription = "", description = "Provide code coverage for the given library.\n" + "Must be one of libraries passed with '-library'", - delimiter = "" + delimiter = Argument.Delimiters.none ) var coveredLibraries: Array? = null diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/parseCommandLineArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/parseCommandLineArguments.kt index ca49a3fc950..5384afd0290 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/parseCommandLineArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/parseCommandLineArguments.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.cli.common.arguments import org.jetbrains.kotlin.cli.common.CompilerSystemProperties +import org.jetbrains.kotlin.konan.file.File import org.jetbrains.kotlin.utils.SmartList import kotlin.reflect.KClass import kotlin.reflect.KMutableProperty1 @@ -28,14 +29,35 @@ annotation class Argument( val value: String, val shortName: String = "", val deprecatedName: String = "", - val delimiter: String = ",", + @property:RawDelimiter + val delimiter: String = Delimiters.default, val valueDescription: String = "", val description: String -) +) { + @RequiresOptIn( + message = "The raw delimiter value needs to be resolved. See 'resolvedDelimiter'. Using the raw value requires opt-in", + level = RequiresOptIn.Level.ERROR + ) + annotation class RawDelimiter + + object Delimiters { + const val default = "," + const val none = "" + const val pathSeparator = "" + } +} val Argument.isAdvanced: Boolean get() = value.startsWith(ADVANCED_ARGUMENT_PREFIX) && value.length > ADVANCED_ARGUMENT_PREFIX.length +@OptIn(Argument.RawDelimiter::class) +val Argument.resolvedDelimiter: String? + get() = when (delimiter) { + Argument.Delimiters.none -> null + Argument.Delimiters.pathSeparator -> File.pathSeparator + else -> delimiter + } + private const val ADVANCED_ARGUMENT_PREFIX = "-X" private const val FREE_ARGS_DELIMITER = "--" @@ -211,7 +233,7 @@ private fun parsePreprocessedCommandLineArguments( errors.value.duplicateArguments[argument.value] = value } - updateField(property, result, value, argument.delimiter, overrideArguments) + updateField(property, result, value, argument.resolvedDelimiter, overrideArguments) } result.freeArgs += freeArgs @@ -238,13 +260,13 @@ private fun updateField( property: KMutableProperty1, result: A, value: Any, - delimiter: String, + delimiter: String?, overrideArguments: Boolean ) { when (property.returnType.classifier) { Boolean::class, String::class -> property.set(result, value) Array::class -> { - val newElements = if (delimiter.isEmpty()) { + val newElements = if (delimiter.isNullOrEmpty()) { arrayOf(value as String) } else { (value as String).split(delimiter).toTypedArray()