Rewrite interop tools command line options to have help messages without crashes (#2672)

This commit is contained in:
LepilkinaElena
2019-02-20 09:14:28 +03:00
committed by GitHub
parent 554348ace6
commit 75805b3528
11 changed files with 187 additions and 235 deletions
+28 -12
View File
@@ -60,7 +60,8 @@ abstract class Descriptor(val type: ArgType,
val longName: String,
val description: String? = null,
val defaultValue: String? = null,
val isRequired: Boolean = false) {
val isRequired: Boolean = false,
val deprecatedWarning: String? = null) {
abstract val textDescription: String
abstract val helpMessage: String
}
@@ -72,7 +73,9 @@ class OptionDescriptor(
description: String? = null,
defaultValue: String? = null,
isRequired: Boolean = false,
val isMultiple: Boolean = false) : Descriptor (type, longName, description, defaultValue, isRequired) {
val isMultiple: Boolean = false,
val delimiter: String? = null,
deprecatedWarning: String? = null) : Descriptor (type, longName, description, defaultValue, isRequired, deprecatedWarning) {
override val textDescription: String
get() = "option -$longName"
@@ -83,8 +86,9 @@ class OptionDescriptor(
shortName?.let { result.append(", -$it") }
defaultValue?.let { result.append(" [$it]") }
description?.let {result.append(" -> ${it}")}
if (!isRequired) result.append(" (optional)")
if (isRequired) result.append(" (always required)")
result.append(" ${type.description}")
deprecatedWarning?.let { result.append(" Warning: $it") }
result.append("\n")
return result.toString()
}
@@ -95,7 +99,8 @@ class ArgDescriptor(
longName: String,
description: String? = null,
defaultValue: String? = null,
isRequired: Boolean = true) : Descriptor (type, longName, description, defaultValue, isRequired) {
isRequired: Boolean = true,
deprecatedWarning: String? = null) : Descriptor (type, longName, description, defaultValue, isRequired, deprecatedWarning) {
override val textDescription: String
get() = "argument $longName"
@@ -107,16 +112,20 @@ class ArgDescriptor(
description?.let {result.append(" -> ${it}")}
if (!isRequired) result.append(" (optional)")
result.append(" ${type.description}")
deprecatedWarning?.let { result.append(" Warning: $it") }
result.append("\n")
return result.toString()
}
}
// Arguments parser.
class ArgParser(optionsList: List<OptionDescriptor>, argsList: List<ArgDescriptor> = listOf<ArgDescriptor>()) {
private val options = optionsList.union(listOf(OptionDescriptor(ArgType.Boolean(), "help",
"h", "Usage info")))
.toList()
class ArgParser(optionsList: List<OptionDescriptor>, argsList: List<ArgDescriptor> = listOf<ArgDescriptor>(),
useDefaultHelpShortName: Boolean = true) {
private val options = optionsList.union(if (useDefaultHelpShortName)
listOf(OptionDescriptor(ArgType.Boolean(), "help", "h", "Usage info"))
else
listOf(OptionDescriptor(ArgType.Boolean(), "help", description = "Usage info"))
).toList()
private val arguments = argsList
private lateinit var parsedValues: MutableMap<String, ParsedArg?>
@@ -153,7 +162,7 @@ class ArgParser(optionsList: List<OptionDescriptor>, argsList: List<ArgDescripto
}
// Output error. Also adds help usage information for easy understanding of problem.
private fun printError(message: String): Nothing {
fun printError(message: String): Nothing {
error("$message\n${makeUsage()}")
}
@@ -163,6 +172,7 @@ class ArgParser(optionsList: List<OptionDescriptor>, argsList: List<ArgDescripto
val name = nullArgs.firstOrNull()
name?. let {
argDescriptors.getValue(name).type.check(arg, name)
argDescriptors.getValue(name).deprecatedWarning?.let { println ("Warning: $it") }
processedValues.getValue(name).add(arg)
return true
}
@@ -173,8 +183,14 @@ class ArgParser(optionsList: List<OptionDescriptor>, argsList: List<ArgDescripto
if (!descriptor.isMultiple && !processedValues.getValue(descriptor.longName).isEmpty()) {
printError("Option ${descriptor.longName} is used more than one time!")
}
descriptor.type.check(value, descriptor.longName)
processedValues.getValue(descriptor.longName).add(value)
descriptor.deprecatedWarning?.let { if (processedValues.getValue(descriptor.longName).isEmpty()) println ("Warning: $it") }
val savedValues = descriptor.delimiter?.let { value.split(it) } ?: listOf(value)
savedValues.forEach {
descriptor.type.check(it, descriptor.longName)
processedValues.getValue(descriptor.longName).add(it)
}
}
// Parse arguments.
@@ -218,7 +234,7 @@ class ArgParser(optionsList: List<OptionDescriptor>, argsList: List<ArgDescripto
} else {
// Argument is found.
if (!saveAsArg(argDescriptors, arg, processedValues)) {
printError("Too many arguments!")
printError("Too many arguments! Couldn't proccess argument $arg!")
}
}
index++
@@ -95,7 +95,7 @@ open class CInteropTask @Inject constructor(val settings: CInteropSettingsImpl):
addArgIfNotNull("-def", defFile.canonicalPath)
addArgIfNotNull("-pkg", packageName)
addFileArgs("-h", headers)
addFileArgs("-header", headers)
compilerOpts.forEach {
addArg("-copt", it)
@@ -80,7 +80,7 @@ open class KonanInteropTask @Inject constructor(val workerExecutor: WorkerExecut
addArgIfNotNull("-def", defFile.canonicalPath)
addArgIfNotNull("-pkg", packageName)
addFileArgs("-h", headers)
addFileArgs("-header", headers)
compilerOpts.forEach {
addArg("-copt", it)