Skip to content

Commit 83b525e

Browse files
committed
Fixup the --future-defaults description
Improve verification of options: the list of options in help text is guaranteed to contain all options. Mentions that it should be used with `--future-defaults=all` in the first sentence. Removed enumeration from the list as it is not relevant and options are easier to read and copy/paste. Option misuse now prints the whole option help text.
1 parent e0c7443 commit 83b525e

File tree

2 files changed

+47
-21
lines changed

2 files changed

+47
-21
lines changed

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/FutureDefaultsOptions.java

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.List;
3030
import java.util.Objects;
3131
import java.util.Set;
32+
import java.util.stream.Collectors;
3233

3334
import org.graalvm.nativeimage.ImageInfo;
3435
import org.graalvm.nativeimage.Platform;
@@ -39,6 +40,7 @@
3940
import com.oracle.svm.core.option.HostedOptionKey;
4041
import com.oracle.svm.core.option.SubstrateOptionsParser;
4142
import com.oracle.svm.core.util.UserError;
43+
import com.oracle.svm.core.util.VMError;
4244
import com.oracle.svm.util.StringUtil;
4345

4446
import jdk.graal.compiler.options.Option;
@@ -73,12 +75,12 @@ public class FutureDefaultsOptions {
7375
* Macro commands: They enable or disable other defaults, but they are not future defaults
7476
* themselves.
7577
*/
76-
private static final Set<String> ALL_COMMANDS = Set.of(ALL_NAME, RUN_TIME_INITIALIZE_JDK, NONE_NAME);
78+
private static final List<String> ALL_COMMANDS = List.of(ALL_NAME, NONE_NAME, RUN_TIME_INITIALIZE_JDK);
7779

7880
private static final String RUN_TIME_INITIALIZE_SECURITY_PROVIDERS = "run-time-initialize-security-providers";
7981
private static final String RUN_TIME_INITIALIZE_FILE_SYSTEM_PROVIDERS = "run-time-initialize-file-system-providers";
8082
private static final String COMPLETE_REFLECTION_TYPES = "complete-reflection-types";
81-
private static final Set<String> ALL_FUTURE_DEFAULTS = Set.of(RUN_TIME_INITIALIZE_FILE_SYSTEM_PROVIDERS, RUN_TIME_INITIALIZE_SECURITY_PROVIDERS, COMPLETE_REFLECTION_TYPES);
83+
private static final List<String> ALL_FUTURE_DEFAULTS = List.of(RUN_TIME_INITIALIZE_FILE_SYSTEM_PROVIDERS, RUN_TIME_INITIALIZE_SECURITY_PROVIDERS, COMPLETE_REFLECTION_TYPES);
8284

8385
public static final String RUN_TIME_INITIALIZE_FILE_SYSTEM_PROVIDERS_REASON = "Initialize JDK classes at run time (--" + OPTION_NAME + " includes " + RUN_TIME_INITIALIZE_SECURITY_PROVIDERS + ")";
8486
public static final String RUN_TIME_INITIALIZE_SECURITY_PROVIDERS_REASON = "Initialize JDK classes at run time (--" + OPTION_NAME + " includes " + RUN_TIME_INITIALIZE_FILE_SYSTEM_PROVIDERS + ")";
@@ -89,43 +91,61 @@ private static String futureDefaultsAllValues() {
8991
return StringUtil.joinSingleQuoted(getAllValues());
9092
}
9193

92-
private static Set<String> getAllValues() {
93-
Set<String> result = new LinkedHashSet<>(ALL_FUTURE_DEFAULTS.size() + ALL_COMMANDS.size());
94-
result.addAll(ALL_FUTURE_DEFAULTS);
94+
private static LinkedHashSet<String> getAllValues() {
95+
LinkedHashSet<String> result = new LinkedHashSet<>(ALL_FUTURE_DEFAULTS.size() + ALL_COMMANDS.size());
9596
result.addAll(ALL_COMMANDS);
97+
result.addAll(ALL_FUTURE_DEFAULTS);
9698
return result;
9799
}
98100

99-
static {
100-
assert getAllValues().stream().allMatch(futureDefaultsAllValues()::contains) : "A value is missing in the user-facing help text";
101-
}
102-
103101
@APIOption(name = OPTION_NAME, defaultValue = DEFAULT_NAME) //
104102
@Option(help = "file:doc-files/FutureDefaultsHelp.txt", type = OptionType.User) //
105103
static final HostedOptionKey<AccumulatingLocatableMultiOptionValue.Strings> FutureDefaults = new HostedOptionKey<>(
106104
AccumulatingLocatableMultiOptionValue.Strings.buildWithCommaDelimiter());
107105

106+
private static String getOptionHelpText() {
107+
Objects.requireNonNull(FutureDefaultsOptions.FutureDefaults.getDescriptor(), "This must be called after the options are processed.");
108+
return FutureDefaultsOptions.FutureDefaults.getDescriptor().getHelp().stream()
109+
.collect(Collectors.joining(System.lineSeparator()));
110+
}
111+
112+
private static void verifyOptionDescription() {
113+
var optionHelpText = getOptionHelpText();
114+
VMError.guarantee(getAllValues().stream().allMatch(futureDefaultsAllValues()::contains), "A value is missing in the user-facing help text");
115+
for (String optionValue : getAllValues()) {
116+
if (!optionHelpText.contains(optionValue + "' -")) {
117+
throw VMError.shouldNotReachHere("Must mention all options in the list of options. Missing option: " + optionValue);
118+
}
119+
}
120+
if (!optionHelpText.contains(futureDefaultsAllValues())) {
121+
throw VMError.shouldNotReachHere("Must mention all options in a comma-separated sequence: " + futureDefaultsAllValues());
122+
}
123+
}
124+
108125
private static Set<String> futureDefaults;
109126

110127
@Platforms(Platform.HOSTED_ONLY.class)
111128
public static void parseAndVerifyOptions() {
129+
verifyOptionDescription();
112130
futureDefaults = new LinkedHashSet<>(getAllValues().size());
113131
var valuesWithOrigin = FutureDefaults.getValue().getValuesWithOrigins();
114132
valuesWithOrigin.forEach(valueWithOrigin -> {
115133
String value = valueWithOrigin.value();
116134
if (DEFAULT_NAME.equals(value)) {
117-
throw UserError.abort("The '%s' from %s is forbidden. It can only contain: %s.",
135+
throw UserError.abort("The '%s' from %s is forbidden. It can only contain: %s.%n%nUsage:%n%n%s",
118136
SubstrateOptionsParser.commandArgument(FutureDefaults, DEFAULT_NAME),
119137
valueWithOrigin.origin(),
120-
futureDefaultsAllValues());
138+
futureDefaultsAllValues(),
139+
getOptionHelpText());
121140
}
122141

123142
if (!getAllValues().contains(value)) {
124-
throw UserError.abort("The '%s' option from %s contains invalid value '%s'. It can only contain: %s.",
143+
throw UserError.abort("The '%s' option from %s contains invalid value '%s'. It can only contain: %s.%n%nUsage:%n%n%s",
125144
SubstrateOptionsParser.commandArgument(FutureDefaults, value),
126145
valueWithOrigin.origin(),
127146
value,
128-
futureDefaultsAllValues());
147+
futureDefaultsAllValues(),
148+
getOptionHelpText());
129149
}
130150

131151
if (value.equals(NONE_NAME)) {
Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1-
Enable options that are planned to become defaults in future releases. Comma-separated list can contain 'all', 'treat-name-as-type', 'run-time-initialize-security-providers', 'run-time-initialize-file-system-providers', and 'none'.
2-
3-
The preferred way to use this option is '--future-defaults=all'. The meaning of each possible option is as follows:
4-
1. 'all' is the preferred option, and it enables all other behaviors.
5-
2. 'complete-reflection-types' reflective registration of a type, via metadata files or the Feature API, always includes all type metadata. Now, all registered types behave the same as types defined in 'reachability-metadata.json'.
6-
3. 'run-time-initialize-security-providers' shifts away from build-time initialization for 'java.security.Provider'. Unless you store 'java.security.Provider'-related classes in the image heap, this option should not affect you. In case this option breaks your build, follow the suggestions in the error messages.
7-
4. 'run-time-initialize-file-system-providers' shifts away from build-time initialization for 'java.nio.file.spi.FileSystemProvider'. Unless you store 'FileSystemProvider'-related classes in the image heap, this option should not affect you. In case this option breaks your build, follow the suggestions in the error messages.
8-
5. 'none' forcefully disables all enabled options. This can be used only on the command line to override choices taken by inaccessible parts of the build process.
1+
Enable options that are planned to become defaults in future releases. Comma-separated list can contain 'all', 'none', 'run-time-initialize-jdk', 'run-time-initialize-file-system-providers', 'run-time-initialize-security-providers', 'complete-reflection-types'. The preferred usage is '--future-defaults=all'.
2+
3+
The meaning of each possible option is as follows:
4+
'all' - is the preferred option, and it enables all other behaviors.
5+
6+
'none' - forcefully disables all enabled options. This can be used only on the command line to override choices taken by inaccessible parts of the build process.
7+
8+
'run-time-initialize-jdk' - enables all behaviors related to run-time initialization of the JDK: ['run-time-initialize-security-providers', 'run-time-initialize-file-system-providers'].
9+
10+
'complete-reflection-types' - reflective registration of a type, via metadata files or the Feature API, always includes all type metadata. Now, all registered types behave the same as types defined in 'reachability-metadata.json'.
11+
12+
'run-time-initialize-security-providers' - shifts away from build-time initialization for 'java.security.Provider'. Unless you store 'java.security.Provider'-related classes in the image heap, this option should not affect you. In case this option breaks your build, follow the suggestions in the error messages.
13+
14+
'run-time-initialize-file-system-providers' - shifts away from build-time initialization for 'java.nio.file.spi.FileSystemProvider'. Unless you store 'FileSystemProvider'-related classes in the image heap, this option should not affect you. In case this option breaks your build, follow the suggestions in the error messages.

0 commit comments

Comments
 (0)