diff --git a/src/main/java/com/google/devtools/common/options/OptionsParserImpl.java b/src/main/java/com/google/devtools/common/options/OptionsParserImpl.java index 06d3dec65036c4..151d919362bfa1 100644 --- a/src/main/java/com/google/devtools/common/options/OptionsParserImpl.java +++ b/src/main/java/com/google/devtools/common/options/OptionsParserImpl.java @@ -545,7 +545,7 @@ private OptionsParserImplResult parse( parsedOption = result.parsedOptionDescription; } if (parsedOption.isPresent()) { - handleNewParsedOption(parsedOption.get()); + handleNewParsedOption(parsedOption.get(), fallbackData); } priority = OptionPriority.nextOptionPriority(priority); } @@ -645,7 +645,7 @@ void setOptionValueAtSpecificPriorityWithoutExpansion( } /** Takes care of tracking the parsed option's value in relation to other options. */ - private void handleNewParsedOption(ParsedOptionDescription parsedOption) + private void handleNewParsedOption(ParsedOptionDescription parsedOption, OptionsData fallbackData) throws OptionsParsingException { OptionDefinition optionDefinition = parsedOption.getOptionDefinition(); ExpansionBundle expansionBundle = setOptionValue(parsedOption); @@ -659,7 +659,7 @@ private void handleNewParsedOption(ParsedOptionDescription parsedOption) optionDefinition.hasImplicitRequirements() ? parsedOption : null, optionDefinition.isExpansionOption() ? parsedOption : null, expansionBundle.expansionArgs, - /* fallbackData= */ null); + fallbackData); if (!optionsParserImplResult.getResidue().isEmpty()) { // Throw an assertion here, because this indicates an error in the definition of this diff --git a/src/test/java/com/google/devtools/common/options/OptionsParserTest.java b/src/test/java/com/google/devtools/common/options/OptionsParserTest.java index 35eef8d372ce3d..64d78bb1b18dfe 100644 --- a/src/test/java/com/google/devtools/common/options/OptionsParserTest.java +++ b/src/test/java/com/google/devtools/common/options/OptionsParserTest.java @@ -2480,6 +2480,40 @@ public void fallbackOptions_optionsParsingDifferently() { assertThat(e).hasCauseThat().isInstanceOf(DuplicateOptionDeclarationException.class); } + public static class ExpandingOptions extends OptionsBase { + @Option( + name = "foo", + category = "one", + documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, + effectTags = {OptionEffectTag.NO_OP}, + expansion = {"--nobar"}, + defaultValue = "null") + public Void foo; + } + + public static class ExpandingOptionsFallback extends OptionsBase { + @Option( + name = "bar", + category = "one", + documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, + effectTags = {OptionEffectTag.NO_OP}, + defaultValue = "true") + public boolean bar; + } + + @Test + public void fallbackOptions_expansionToNegativeBooleanFlag() throws OptionsParsingException { + OpaqueOptionsData fallbackData = + OptionsParser.getFallbackOptionsData( + ImmutableList.of(ExpandingOptions.class, ExpandingOptionsFallback.class)); + OptionsParser parser = OptionsParser.builder().optionsClasses(ExpandingOptions.class).build(); + parser.parseWithSourceFunction( + PriorityCategory.RC_FILE, o -> ".bazelrc", ImmutableList.of("--foo"), fallbackData); + + assertThat(parser.getOptions(ExpandingOptions.class)).isNotNull(); + assertThat(parser.getOptions(ExpandingOptionsFallback.class)).isNull(); + } + private static OptionInstanceOrigin createInvocationPolicyOrigin() { return createInvocationPolicyOrigin(/*implicitDependent=*/ null, /*expandedFrom=*/ null); }