Change format of -X arguments to require value after '='

Report a warning when an argument is passed in the old form (with the
whitespace)

 #KT-17264 Fixed
This commit is contained in:
Alexander Udalov
2017-04-05 16:42:43 +03:00
parent 78c0111c6e
commit f4b6db4dc0
22 changed files with 100 additions and 73 deletions
@@ -104,6 +104,9 @@ public abstract class CommonCompilerArguments implements Serializable {
public List<String> unknownExtraFlags = new SmartList<>();
// Names of extra (-X...) arguments which have been passed in an obsolete form ("-Xaaa bbb", instead of "-Xaaa=bbb")
public List<String> extraArgumentsPassedInObsoleteForm = new SmartList<>();
@NotNull
public static CommonCompilerArguments createDefaultInstance() {
DummyImpl arguments = new DummyImpl();
@@ -22,16 +22,15 @@ import java.util.*
@JvmOverloads
fun <A : CommonCompilerArguments> parseArguments(args: Array<String>, arguments: A, ignoreInvalidArguments: Boolean = false) {
val unparsedArgs = parseCommandLineArguments(args, arguments)
val (unknownExtraArgs, unknownArgs) = unparsedArgs.partition { it.startsWith("-X") }
arguments.unknownExtraFlags = unknownExtraArgs
arguments.freeArgs = if (ignoreInvalidArguments) unknownArgs.filterNot { it.startsWith("-") } else unknownArgs
parseCommandLineArguments(args, arguments)
if (!ignoreInvalidArguments) {
for (argument in unknownArgs) {
if (argument.startsWith("-")) {
throw IllegalArgumentException("Invalid argument: " + argument)
}
if (ignoreInvalidArguments) {
arguments.freeArgs.removeAll { it.startsWith("-") }
}
for (argument in arguments.freeArgs) {
if (argument.startsWith("-")) {
throw IllegalArgumentException("Invalid argument: " + argument)
}
}
}
@@ -26,41 +26,56 @@ annotation class Argument(
)
val Argument.isAdvanced: Boolean
get() = value.startsWith("-X") && value.length > 2
get() = value.startsWith(ADVANCED_ARGUMENT_PREFIX) && value.length > ADVANCED_ARGUMENT_PREFIX.length
fun <A : CommonCompilerArguments> parseCommandLineArguments(args: Array<String>, result: A): List<String> {
data class ArgumentField(val field: Field, val argumentNames: List<String>)
private val ADVANCED_ARGUMENT_PREFIX = "-X"
fun <A : CommonCompilerArguments> parseCommandLineArguments(args: Array<String>, result: A) {
data class ArgumentField(val field: Field, val argument: Argument)
val fields = result::class.java.fields.mapNotNull { field ->
val argument = field.getAnnotation(Argument::class.java)
if (argument != null)
ArgumentField(field, listOfNotNull(argument.value, argument.shortName.takeUnless(String::isEmpty)))
else null
if (argument != null) ArgumentField(field, argument) else null
}
val freeArgs = mutableListOf<String>()
var i = 0
while (i < args.size) {
val arg = args[i++]
val field = fields.firstOrNull { (_, names) -> arg in names }?.field
if (field == null) {
freeArgs.add(arg)
val argumentField = fields.firstOrNull { (_, argument) ->
argument.value == arg ||
argument.shortName.takeUnless(String::isEmpty) == arg ||
(argument.isAdvanced && arg.startsWith(argument.value + "="))
}
if (argumentField == null) {
if (arg.startsWith(ADVANCED_ARGUMENT_PREFIX)) {
result.unknownExtraFlags.add(arg)
}
else {
result.freeArgs.add(arg)
}
continue
}
val value: Any =
if (field.type == Boolean::class.java) true
else {
if (i == args.size) {
throw IllegalArgumentException("No value passed for argument $arg")
}
args[i++]
val (field, argument) = argumentField
val value: Any = when {
field.type == Boolean::class.java -> true
argument.isAdvanced && arg.startsWith(argument.value + "=") -> {
arg.substring(argument.value.length + 1)
}
else -> {
if (i == args.size) {
throw IllegalArgumentException("No value passed for argument $arg")
}
if (argument.isAdvanced) {
result.extraArgumentsPassedInObsoleteForm.add(arg)
}
args[i++]
}
}
updateField(field, result, value)
}
return freeArgs
}
private fun <A : CommonCompilerArguments> updateField(field: Field, result: A, value: Any) {
@@ -51,8 +51,7 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> {
return exec(errStream, Services.EMPTY, MessageRenderer.PLAIN_RELATIVE_PATHS, args);
}
// Used via reflection in CompilerRunnerUtil#invokeExecMethod and in Eclipse plugin (see KotlinCLICompiler)
@SuppressWarnings("UnusedDeclaration")
// Used in CompilerRunnerUtil#invokeExecMethod, in Eclipse plugin (KotlinCLICompiler) and in kotlin-gradle-plugin (GradleCompilerRunner)
@NotNull
public ExitCode execAndOutputXml(@NotNull PrintStream errStream, @NotNull Services services, @NotNull String... args) {
return exec(errStream, services, MessageRenderer.XML, args);
@@ -82,7 +81,7 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> {
return null;
}
@SuppressWarnings("WeakerAccess") // Used in maven (see KotlinCompileMojoBase.java)
// Used in kotlin-maven-plugin (KotlinCompileMojoBase) and in kotlin-gradle-plugin (KotlinJvmOptionsImpl, KotlinJsOptionsImpl)
public void parseArguments(@NotNull String[] args, @NotNull A arguments) {
ArgumentUtilsKt.parseArguments(args, arguments);
}
@@ -128,7 +127,7 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> {
}
}
@SuppressWarnings("WeakerAccess") // Used in maven (see KotlinCompileMojoBase.java)
// Used in kotlin-maven-plugin (KotlinCompileMojoBase)
@NotNull
public ExitCode exec(@NotNull MessageCollector messageCollector, @NotNull Services services, @NotNull A arguments) {
printVersionIfNeeded(messageCollector, arguments);
@@ -137,7 +136,7 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> {
messageCollector = new FilteringMessageCollector(messageCollector, Predicate.isEqual(WARNING));
}
reportUnknownExtraFlags(messageCollector, arguments);
reportUnknownAndObsoleteExtraFlags(messageCollector, arguments);
GroupingMessageCollector groupingCollector = new GroupingMessageCollector(messageCollector);
@@ -314,10 +313,14 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> {
@NotNull CompilerConfiguration configuration, @NotNull A arguments, @NotNull Services services
);
private void reportUnknownExtraFlags(@NotNull MessageCollector collector, @NotNull A arguments) {
private void reportUnknownAndObsoleteExtraFlags(@NotNull MessageCollector collector, @NotNull A arguments) {
for (String flag : arguments.unknownExtraFlags) {
collector.report(STRONG_WARNING, "Flag is not supported by this version of the compiler: " + flag, null);
}
for (String argument : arguments.extraArgumentsPassedInObsoleteForm) {
collector.report(STRONG_WARNING, "Advanced option value is passed in an obsolete form. Please use the '=' character " +
"to specify the value: " + argument + "=...", null);
}
}
@NotNull
@@ -75,7 +75,7 @@ class Usage {
}
if (!argument.valueDescription().isEmpty()) {
sb.append(" ");
sb.append(ParseCommandLineArgumentsKt.isAdvanced(argument) ? "=" : " ");
sb.append(argument.valueDescription());
}