@@ -142,7 +142,7 @@ private static void extractOption(String optionPrefix, OptionDescriptor optionDe
142142 Map <String , GroupInfo > groupInfos , Map <Class <? extends APIOptionGroup >, APIOptionGroup > groupInstances , Map <String , HostedOptionInfo > allOptionNames ) {
143143
144144 Class <?> optionValueType = optionDescriptor .getOptionValueType ();
145- boolean booleanOption = optionValueType .equals (Boolean .class );
145+ boolean isBooleanOption = optionValueType .equals (Boolean .class );
146146
147147 for (APIOption apiAnnotation : OptionUtils .getAnnotationsByType (optionDescriptor , APIOption .class )) {
148148 String builderOption = optionPrefix ;
@@ -159,7 +159,7 @@ private static void extractOption(String optionPrefix, OptionDescriptor optionDe
159159 optionValueType = optionValueType .getComponentType ();
160160 }
161161 boolean hasFixedValue = apiAnnotation .fixedValue ().length > 0 ;
162- if (booleanOption ) {
162+ if (isBooleanOption ) {
163163 if (!apiAnnotation .group ().equals (APIOption .NullGroup .class )) {
164164 try {
165165 Class <? extends APIOptionGroup > groupClass = apiAnnotation .group ();
@@ -247,7 +247,7 @@ private static void extractOption(String optionPrefix, OptionDescriptor optionDe
247247 for (char valueSeparator : apiAnnotation .valueSeparator ()) {
248248 if (valueSeparator == APIOption .WHITESPACE_SEPARATOR ) {
249249 String msgTail = " cannot use APIOption.WHITESPACE_SEPARATOR as value separator" ;
250- if (booleanOption ) {
250+ if (isBooleanOption ) {
251251 throw VMError .shouldNotReachHere (String .format ("Boolean APIOption %s(%s)" + msgTail , apiOptionName , rawOptionName ));
252252 }
253253 if (hasFixedValue ) {
@@ -258,13 +258,13 @@ private static void extractOption(String optionPrefix, OptionDescriptor optionDe
258258 }
259259 }
260260 }
261- boolean defaultFinal = booleanOption || hasFixedValue ;
261+ boolean defaultFinal = isBooleanOption || hasFixedValue ;
262262 apiOptions .put (apiOptionName ,
263263 new APIOptionHandler .OptionInfo (apiAnnotation .name (), apiAnnotation .valueSeparator (), builderOption , defaultValue , helpText ,
264264 defaultFinal , apiAnnotation .deprecated (), valueTransformers , group , apiAnnotation .extra (), apiAnnotation .launcherOption ()));
265265 }
266266
267- allOptionNames .put (optionDescriptor .getName (), new HostedOptionInfo (optionDescriptor .getStability () == OptionStability .STABLE , booleanOption ));
267+ allOptionNames .put (optionDescriptor .getName (), new HostedOptionInfo (optionDescriptor .getStability () == OptionStability .STABLE , isBooleanOption ));
268268 }
269269
270270 private static void extractPathOption (String optionPrefix , OptionDescriptor optionDescriptor , Map <String , PathsOptionInfo > pathOptions ) {
@@ -317,52 +317,7 @@ boolean consume(ArgumentQueue args) {
317317 }
318318 numberOfActiveUnlockExperimentalVMOptions --;
319319 } else if (!OptionOrigin .isAPI (args .argumentOrigin ) && headArg .startsWith (NativeImage .oH )) {
320- String optionName = headArg .substring (NativeImage .oH .length ()).split ("=" , 2 )[0 ].split ("@" , 2 )[0 ];
321- char booleanPrefix = 0 ;
322- if (!optionName .isEmpty ()) {
323- char first = optionName .charAt (0 );
324- if (first == '+' || first == '-' ) {
325- optionName = optionName .substring (1 );
326- booleanPrefix = first ;
327- }
328- }
329- HostedOptionInfo info = allOptionNames .get (optionName );
330- if (info == null ) {
331- List <String > matches = new ArrayList <>();
332- OptionsParser .collectFuzzyMatches (() -> allOptionNames .keySet ().iterator (), optionName , matches , Function .identity ());
333- StringBuilder msg = new StringBuilder ();
334- msg .append ("Unrecognized option '" ).append (NativeImage .oH );
335- if (booleanPrefix != 0 ) {
336- msg .append (booleanPrefix );
337- }
338- msg .append (optionName );
339- if (booleanPrefix == 0 ) {
340- msg .append ("=..." );
341- }
342- OptionOrigin optionOrigin = OptionOrigin .from (args .argumentOrigin );
343- msg .append ("' from " ).append (optionOrigin ).append ('.' );
344- if (!matches .isEmpty ()) {
345- msg .append (" Did you mean one of these:" );
346- for (var match : matches ) {
347- msg .append (' ' ).append ('\'' ).append (NativeImage .oH );
348- boolean matchIsBoolean = allOptionNames .get (match ).isBoolean ;
349- if (matchIsBoolean ) {
350- msg .append (CommonOptionParser .PLUS_MINUS_BOOLEAN_OPTION_PREFIX );
351- }
352- msg .append (match );
353- if (!matchIsBoolean ) {
354- msg .append ("=..." );
355- }
356- msg .append ('\'' );
357- }
358- msg .append ('.' );
359- }
360- msg .append (" Use '--expert-options' (see also '--help-extra') to list all available options." );
361- throw NativeImage .showError (msg .toString ());
362- }
363- if (numberOfActiveUnlockExperimentalVMOptions == 0 && !info .isStable ()) {
364- illegalExperimentalOptions .add (headArg );
365- }
320+ validateHostedOption (headArg , args .argumentOrigin );
366321 }
367322 for (Entry <String , GroupInfo > entry : groupInfos .entrySet ()) {
368323 String groupNameAndSeparator = entry .getKey ();
@@ -376,6 +331,55 @@ boolean consume(ArgumentQueue args) {
376331 return false ;
377332 }
378333
334+ private void validateHostedOption (String hostedOptionArg , String argumentOrigin ) {
335+ String optionName = hostedOptionArg .substring (NativeImage .oH .length ()).split ("=" , 2 )[0 ].split ("@" , 2 )[0 ];
336+ char booleanPrefix = 0 ;
337+ if (!optionName .isEmpty ()) {
338+ char first = optionName .charAt (0 );
339+ if (first == '+' || first == '-' ) {
340+ optionName = optionName .substring (1 );
341+ booleanPrefix = first ;
342+ }
343+ }
344+ HostedOptionInfo info = allOptionNames .get (optionName );
345+ if (info == null ) {
346+ List <String > matches = new ArrayList <>();
347+ OptionsParser .collectFuzzyMatches (() -> allOptionNames .keySet ().iterator (), optionName , matches , Function .identity ());
348+ StringBuilder msg = new StringBuilder ();
349+ msg .append ("Unrecognized option '" ).append (NativeImage .oH );
350+ if (booleanPrefix != 0 ) {
351+ msg .append (booleanPrefix );
352+ }
353+ msg .append (optionName );
354+ if (booleanPrefix == 0 ) {
355+ msg .append ("=..." );
356+ }
357+ OptionOrigin optionOrigin = OptionOrigin .from (argumentOrigin );
358+ msg .append ("' from " ).append (optionOrigin ).append ('.' );
359+ if (!matches .isEmpty ()) {
360+ msg .append (" Did you mean one of these:" );
361+ for (var match : matches ) {
362+ msg .append (' ' ).append ('\'' ).append (NativeImage .oH );
363+ boolean matchIsBoolean = allOptionNames .get (match ).isBoolean ;
364+ if (matchIsBoolean ) {
365+ msg .append (CommonOptionParser .PLUS_MINUS_BOOLEAN_OPTION_PREFIX );
366+ }
367+ msg .append (match );
368+ if (!matchIsBoolean ) {
369+ msg .append ("=..." );
370+ }
371+ msg .append ('\'' );
372+ }
373+ msg .append ('.' );
374+ }
375+ msg .append (" Use '--expert-options' (see also '--help-extra') to list all available options." );
376+ throw NativeImage .showError (msg .toString ());
377+ }
378+ if (numberOfActiveUnlockExperimentalVMOptions == 0 && !info .isStable ()) {
379+ illegalExperimentalOptions .add (hostedOptionArg );
380+ }
381+ }
382+
379383 String translateOption (ArgumentQueue argQueue ) {
380384 OptionInfo option = null ;
381385 boolean whitespaceSeparated = false ;
0 commit comments