[CLI] argumentsToStrings: Add 'compactArgumentValues' option
Passing 'false' will pass Array or List based arguments multiple times instead of using the Delimiter. eg: compactArgumentValues = true: "-cp", "library1;library2;library3" compactArgumentValues = false: "-cp", "library1", "-cp", -"library2", "-cp", "library3" Using compactArgumentValues = false can be beneficial when the many compiler arguments are held in memory. In this case the raw arguments can intern individual string values, which is highly effective when the arguments refer to files on disk. KTIJ-24976
This commit is contained in:
committed by
Space Team
parent
fb66764c4d
commit
082a38216d
@@ -17,14 +17,20 @@ import kotlin.reflect.full.memberProperties
|
|||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun CommonToolArguments.toArgumentStrings(useShortNames: Boolean = false): List<String> {
|
fun CommonToolArguments.toArgumentStrings(shortArgumentKeys: Boolean = false, compactArgumentValues: Boolean = true): List<String> {
|
||||||
return toArgumentStrings(
|
return toArgumentStrings(
|
||||||
this, this::class as KClass<CommonToolArguments>, useShortNames = useShortNames
|
this, this::class as KClass<CommonToolArguments>,
|
||||||
|
shortArgumentKeys = shortArgumentKeys,
|
||||||
|
compactArgumentValues = compactArgumentValues
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
internal fun <T : CommonToolArguments> toArgumentStrings(thisArguments: T, type: KClass<T>, useShortNames: Boolean): List<String> {
|
internal fun <T : CommonToolArguments> toArgumentStrings(
|
||||||
|
thisArguments: T, type: KClass<T>,
|
||||||
|
shortArgumentKeys: Boolean,
|
||||||
|
compactArgumentValues: Boolean
|
||||||
|
): List<String> {
|
||||||
val defaultArguments = type.newArgumentsInstance()
|
val defaultArguments = type.newArgumentsInstance()
|
||||||
val result = mutableListOf<String>()
|
val result = mutableListOf<String>()
|
||||||
type.memberProperties.forEach { property ->
|
type.memberProperties.forEach { property ->
|
||||||
@@ -41,15 +47,15 @@ internal fun <T : CommonToolArguments> toArgumentStrings(thisArguments: T, type:
|
|||||||
property.returnType.classifier == Boolean::class -> listOf(rawPropertyValue?.toString() ?: false.toString())
|
property.returnType.classifier == Boolean::class -> listOf(rawPropertyValue?.toString() ?: false.toString())
|
||||||
|
|
||||||
(property.returnType.classifier as? KClass<*>)?.java?.isArray == true ->
|
(property.returnType.classifier as? KClass<*>)?.java?.isArray == true ->
|
||||||
getArgumentStringValue(argumentAnnotation, rawPropertyValue as Array<*>?)
|
getArgumentStringValue(argumentAnnotation, rawPropertyValue as Array<*>?, compactArgumentValues)
|
||||||
|
|
||||||
property.returnType.classifier == List::class ->
|
property.returnType.classifier == List::class ->
|
||||||
getArgumentStringValue(argumentAnnotation, (rawPropertyValue as List<*>?)?.toTypedArray())
|
getArgumentStringValue(argumentAnnotation, (rawPropertyValue as List<*>?)?.toTypedArray(), compactArgumentValues)
|
||||||
|
|
||||||
else -> listOf(rawPropertyValue.toString())
|
else -> listOf(rawPropertyValue.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
val argumentName = if (useShortNames && argumentAnnotation.shortName.isNotEmpty()) argumentAnnotation.shortName
|
val argumentName = if (shortArgumentKeys && argumentAnnotation.shortName.isNotEmpty()) argumentAnnotation.shortName
|
||||||
else argumentAnnotation.value
|
else argumentAnnotation.value
|
||||||
|
|
||||||
argumentStringValues.forEach { argumentStringValue ->
|
argumentStringValues.forEach { argumentStringValue ->
|
||||||
@@ -77,10 +83,10 @@ internal fun <T : CommonToolArguments> toArgumentStrings(thisArguments: T, type:
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getArgumentStringValue(argumentAnnotation: Argument, values: Array<*>?): List<String> {
|
private fun getArgumentStringValue(argumentAnnotation: Argument, values: Array<*>?, compactArgumentValues: Boolean): List<String> {
|
||||||
if (values.isNullOrEmpty()) return emptyList()
|
if (values.isNullOrEmpty()) return emptyList()
|
||||||
val delimiter = argumentAnnotation.resolvedDelimiter
|
val delimiter = argumentAnnotation.resolvedDelimiter
|
||||||
return if (delimiter.isNullOrEmpty()) values.map { it.toString() }
|
return if (delimiter.isNullOrEmpty() || !compactArgumentValues) values.map { it.toString() }
|
||||||
else listOf(values.joinToString(delimiter))
|
else listOf(values.joinToString(delimiter))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+28
-11
@@ -25,14 +25,28 @@ class CompilerArgumentParsingTest {
|
|||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("parameters")
|
@MethodSource("parameters")
|
||||||
fun `test - parsing random compiler arguments`(type: KClass<out CommonToolArguments>, seed: Int, useShortNames: Boolean) {
|
fun `test - parsing random compiler arguments`(
|
||||||
|
type: KClass<out CommonToolArguments>,
|
||||||
|
seed: Int,
|
||||||
|
shortArgumentKeys: Boolean,
|
||||||
|
compactArgumentValues: Boolean
|
||||||
|
) {
|
||||||
val constructor = type.constructors.find { it.parameters.isEmpty() } ?: error("Missing empty constructor on $type")
|
val constructor = type.constructors.find { it.parameters.isEmpty() } ?: error("Missing empty constructor on $type")
|
||||||
val arguments = constructor.call()
|
val arguments = constructor.call()
|
||||||
arguments.fillRandomValues(Random(seed))
|
arguments.fillRandomValues(Random(seed))
|
||||||
val argumentsAsStrings = arguments.toArgumentStrings(useShortNames)
|
val argumentsAsStrings = arguments.toArgumentStrings(
|
||||||
|
shortArgumentKeys = shortArgumentKeys,
|
||||||
|
compactArgumentValues = compactArgumentValues
|
||||||
|
)
|
||||||
val parsedArguments = parseCommandLineArguments(type, argumentsAsStrings)
|
val parsedArguments = parseCommandLineArguments(type, argumentsAsStrings)
|
||||||
assertEqualArguments(arguments, parsedArguments)
|
assertEqualArguments(arguments, parsedArguments)
|
||||||
assertEquals(argumentsAsStrings, parsedArguments.toArgumentStrings(useShortNames))
|
assertEquals(
|
||||||
|
argumentsAsStrings,
|
||||||
|
parsedArguments.toArgumentStrings(
|
||||||
|
shortArgumentKeys = shortArgumentKeys,
|
||||||
|
compactArgumentValues = compactArgumentValues
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -40,12 +54,15 @@ class CompilerArgumentParsingTest {
|
|||||||
fun parameters(): List<Arguments> = getCompilerArgumentImplementations()
|
fun parameters(): List<Arguments> = getCompilerArgumentImplementations()
|
||||||
.flatMap { clazz ->
|
.flatMap { clazz ->
|
||||||
listOf(1002, 2803, 2411).flatMap { seed ->
|
listOf(1002, 2803, 2411).flatMap { seed ->
|
||||||
listOf(true, false).map { useShortNames ->
|
listOf(true, false).flatMap { shortArgumentKeys ->
|
||||||
Arguments.of(
|
listOf(true, false).map { compactArgumentValues ->
|
||||||
Named.of("${clazz.simpleName}", clazz),
|
Arguments.of(
|
||||||
Named.of("seed: $seed", seed),
|
Named.of("${clazz.simpleName}", clazz),
|
||||||
Named.of("useShortNames: $useShortNames", useShortNames)
|
Named.of("seed: $seed", seed),
|
||||||
)
|
Named.of("shortArgumentKeys: $shortArgumentKeys", shortArgumentKeys),
|
||||||
|
Named.of("compactArgumentValues: $compactArgumentValues", compactArgumentValues)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,14 +113,14 @@ private fun Random.randomString() = nextBytes(nextInt(8, 12)).let { data ->
|
|||||||
private fun Random.randomBoolean() = nextBoolean()
|
private fun Random.randomBoolean() = nextBoolean()
|
||||||
|
|
||||||
private fun Random.randomStringArray(): Array<String> {
|
private fun Random.randomStringArray(): Array<String> {
|
||||||
val size = nextInt(1, 5)
|
val size = nextInt(5, 10)
|
||||||
return Array(size) {
|
return Array(size) {
|
||||||
randomString()
|
randomString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Random.randomList(elementType: KType): List<Any>? {
|
private fun Random.randomList(elementType: KType): List<Any>? {
|
||||||
val size = nextInt(1, 5)
|
val size = nextInt(5, 10)
|
||||||
return List(size) {
|
return List(size) {
|
||||||
randomValue(elementType) ?: return null
|
randomValue(elementType) ?: return null
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user