Skip to content

Commit a2987bf

Browse files
committed
Add driver-based boolean/non-boolean hosted option mismatch detection
1 parent 1c9f5c6 commit a2987bf

File tree

3 files changed

+29
-15
lines changed

3 files changed

+29
-15
lines changed

substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/CommonOptionParser.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ public class CommonOptionParser {
5959
public static final String HOSTED_OPTION_PREFIX = "-H:";
6060
public static final String RUNTIME_OPTION_PREFIX = "-R:";
6161
public static final char PLUS_MINUS_BOOLEAN_OPTION_PREFIX = '\u00b1';
62+
public static final String MISMATCH_BOOLEAN_OPTION = "Boolean option %s must have " + PLUS_MINUS_BOOLEAN_OPTION_PREFIX + " prefix. Use '" + PLUS_MINUS_BOOLEAN_OPTION_PREFIX + "%s' format.";
63+
public static final String MISMATCH_NON_BOOLEAN_OPTION = "Non-boolean option %s can not use " + PLUS_MINUS_BOOLEAN_OPTION_PREFIX + " prefix. Use '%s=<value>' format.";
6264

6365
public static final int PRINT_OPTION_INDENTATION = 2;
6466
public static final int PRINT_OPTION_WIDTH = 45;
@@ -244,7 +246,7 @@ public static OptionParseResult parseOption(EconomicMap<String, OptionDescriptor
244246

245247
if (value == null) {
246248
if (optionType == Boolean.class && booleanOptionFormat == BooleanOptionFormat.PLUS_MINUS) {
247-
return OptionParseResult.error("Boolean option " + current + " must have +/- prefix");
249+
return OptionParseResult.error(MISMATCH_BOOLEAN_OPTION.formatted(current, current.name));
248250
}
249251
if (valueString == null) {
250252
return OptionParseResult.error("Missing value for option " + current);
@@ -259,7 +261,7 @@ public static OptionParseResult parseOption(EconomicMap<String, OptionDescriptor
259261
}
260262
} else {
261263
if (optionType != Boolean.class) {
262-
return OptionParseResult.error("Non-boolean option " + current + " can not use +/- prefix. Use '" + current.name + "=<value>' format");
264+
return OptionParseResult.error(MISMATCH_NON_BOOLEAN_OPTION.formatted(current, current.name));
263265
}
264266
}
265267

substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/APIOptionHandler.java

+23-11
Original file line numberDiff line numberDiff line change
@@ -355,17 +355,8 @@ private void validateHostedOption(String hostedOptionArg, String argumentOrigin)
355355
if (info == null) {
356356
List<String> matches = new ArrayList<>();
357357
OptionsParser.collectFuzzyMatches(() -> allOptionNames.keySet().iterator(), optionName, matches, Function.identity());
358-
StringBuilder msg = new StringBuilder();
359-
msg.append("Unrecognized option '").append(NativeImage.oH);
360-
if (booleanPrefix != 0) {
361-
msg.append(booleanPrefix);
362-
}
363-
msg.append(optionName);
364-
if (booleanPrefix == 0) {
365-
msg.append("=...");
366-
}
367-
OptionOrigin optionOrigin = OptionOrigin.from(argumentOrigin);
368-
msg.append("' from ").append(optionOrigin).append('.');
358+
StringBuilder msg = new StringBuilder("Unrecognized option ");
359+
msg.append(optionDescription(optionName, booleanPrefix, argumentOrigin)).append('.');
369360
if (!matches.isEmpty()) {
370361
msg.append(" Did you mean one of these:");
371362
for (var match : matches) {
@@ -385,11 +376,32 @@ private void validateHostedOption(String hostedOptionArg, String argumentOrigin)
385376
msg.append(" Use '--expert-options' (see also '--help-extra') to list all available options.");
386377
throw NativeImage.showError(msg.toString());
387378
}
379+
if ((booleanPrefix != 0) != info.isBoolean()) {
380+
var optionDescription = optionDescription(optionName, booleanPrefix, argumentOrigin);
381+
if (info.isBoolean()) {
382+
throw NativeImage.showError(CommonOptionParser.MISMATCH_BOOLEAN_OPTION.formatted(optionDescription, optionName));
383+
} else {
384+
throw NativeImage.showError(CommonOptionParser.MISMATCH_NON_BOOLEAN_OPTION.formatted(optionDescription, optionName));
385+
}
386+
}
388387
if (numberOfActiveUnlockExperimentalVMOptions == 0 && !info.isStable()) {
389388
illegalExperimentalOptions.add(hostedOptionArg);
390389
}
391390
}
392391

392+
private static String optionDescription(String optionName, char booleanPrefix, String argumentOrigin) {
393+
var result = new StringBuilder("'" + NativeImage.oH);
394+
if (booleanPrefix != 0) {
395+
result.append(booleanPrefix);
396+
}
397+
result.append(optionName);
398+
if (booleanPrefix == 0) {
399+
result.append("=...");
400+
}
401+
result.append("' from ").append(OptionOrigin.from(argumentOrigin));
402+
return result.toString();
403+
}
404+
393405
String translateOption(ArgumentQueue argQueue) {
394406
OptionInfo option = null;
395407
boolean whitespaceSeparated = false;

substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1059,12 +1059,12 @@ private static String injectHostedOptionOrigin(String option, String origin) {
10591059
char boolPrefix = option.length() > oH.length() ? option.charAt(oH.length()) : 0;
10601060
if (boolPrefix == '-' || boolPrefix == '+') {
10611061
if (eqIndex != -1) {
1062-
showError("Malformed boolean native-image hosted-option '" + option + "' (boolean option with extraneous '=') from " + OptionOrigin.from(origin));
1062+
showError("Malformed boolean native-image hosted-option '" + option + "' (boolean option with extraneous '=') from " + OptionOrigin.from(origin) + ".");
10631063
}
10641064
return option + optionOriginSeparator + origin;
10651065
} else {
10661066
if (eqIndex == -1) {
1067-
showError("Malformed native-image hosted-option '" + option + "' ('=' missing after option name) from " + OptionOrigin.from(origin));
1067+
showError("Malformed native-image hosted-option '" + option + "' ('=' missing after option name) from " + OptionOrigin.from(origin) + ".");
10681068
}
10691069
String front = option.substring(0, eqIndex);
10701070
String back = option.substring(eqIndex);

0 commit comments

Comments
 (0)