diff options
Diffstat (limited to 'src/main/java/com/google/devtools/common')
-rw-r--r-- | src/main/java/com/google/devtools/common/options/OptionValueDescription.java | 137 | ||||
-rw-r--r-- | src/main/java/com/google/devtools/common/options/OptionsParserImpl.java | 41 |
2 files changed, 106 insertions, 72 deletions
diff --git a/src/main/java/com/google/devtools/common/options/OptionValueDescription.java b/src/main/java/com/google/devtools/common/options/OptionValueDescription.java index ed03e9776a..0d31137fa4 100644 --- a/src/main/java/com/google/devtools/common/options/OptionValueDescription.java +++ b/src/main/java/com/google/devtools/common/options/OptionValueDescription.java @@ -15,7 +15,9 @@ package com.google.devtools.common.options; import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ListMultimap; import com.google.devtools.common.options.OptionsParser.ConstructionException; import java.util.Collection; @@ -47,10 +49,29 @@ public abstract class OptionValueDescription { /** Returns the source(s) of this option, if there were multiple, duplicates are removed. */ public abstract String getSourceString(); - abstract void addOptionInstance( - ParsedOptionDescription parsedOption, - List<String> warnings) - throws OptionsParsingException; + /** + * Add an instance of the option to this value. The various types of options are in charge of + * making sure that the value is correctly stored, with proper tracking of its priority and + * placement amongst other options. + * + * @return a bundle containing arguments that need to be parsed further. + */ + abstract ExpansionBundle addOptionInstance( + ParsedOptionDescription parsedOption, List<String> warnings) throws OptionsParsingException; + + /** + * Grouping of convenience for the options that expand to other options, to attach an + * option-appropriate source string along with the options that need to be parsed. + */ + public static class ExpansionBundle { + List<String> expansionArgs; + String sourceOfExpansionArgs; + + public ExpansionBundle(List<String> args, String source) { + expansionArgs = args; + sourceOfExpansionArgs = source; + } + } /** * For the given option, returns the correct type of OptionValueDescription, to which unparsed @@ -59,11 +80,12 @@ public abstract class OptionValueDescription { * <p>The categories of option types are non-overlapping, an invariant checked by the * OptionProcessor at compile time. */ - public static OptionValueDescription createOptionValueDescription(OptionDefinition option) { - if (option.allowsMultiple()) { + public static OptionValueDescription createOptionValueDescription( + OptionDefinition option, OptionsData optionsData) { + if (option.isExpansionOption()) { + return new ExpansionOptionValueDescription(option, optionsData); + } else if (option.allowsMultiple()) { return new RepeatableOptionValueDescription(option); - } else if (option.isExpansionOption()) { - return new ExpansionOptionValueDescription(option); } else if (option.hasImplicitRequirements()) { return new OptionWithImplicitRequirementsValueDescription(option); } else if (option.isWrapperOption()) { @@ -98,9 +120,7 @@ public abstract class OptionValueDescription { } @Override - void addOptionInstance( - ParsedOptionDescription parsedOption, - List<String> warnings) { + ExpansionBundle addOptionInstance(ParsedOptionDescription parsedOption, List<String> warnings) { throw new IllegalStateException( "Cannot add values to the default option value. Create a modifiable " + "OptionValueDescription using createOptionValueDescription() instead."); @@ -139,15 +159,13 @@ public abstract class OptionValueDescription { // Warnings should not end with a '.' because the internal reporter adds one automatically. @Override - void addOptionInstance( - ParsedOptionDescription parsedOption, - List<String> warnings) + ExpansionBundle addOptionInstance(ParsedOptionDescription parsedOption, List<String> warnings) throws OptionsParsingException { // This might be the first value, in that case, just store it! if (effectiveOptionInstance == null) { effectiveOptionInstance = parsedOption; effectiveValue = effectiveOptionInstance.getConvertedValue(); - return; + return null; } // If there was another value, check whether the new one will override it, and if so, @@ -190,8 +208,10 @@ public abstract class OptionValueDescription { // Create a warning if an expansion option overrides an explicit option: warnings.add( String.format( - "%s was expanded and now overrides a previous explicitly specified %s", - expandedFrom, optionDefinition)); + "%s was expanded and now overrides a previous explicitly specified %s with %s", + expandedFrom, + effectiveOptionInstance.getCommandLineForm(), + parsedOption.getCommandLineForm())); } else if ((optionThatExpandedToEffectiveValue != null) && (expandedFrom != null)) { warnings.add( String.format( @@ -204,6 +224,7 @@ public abstract class OptionValueDescription { effectiveOptionInstance = parsedOption; effectiveValue = newValue; } + return null; } @VisibleForTesting @@ -254,9 +275,7 @@ public abstract class OptionValueDescription { } @Override - void addOptionInstance( - ParsedOptionDescription parsedOption, - List<String> warnings) + ExpansionBundle addOptionInstance(ParsedOptionDescription parsedOption, List<String> warnings) throws OptionsParsingException { // For repeatable options, we allow flags that take both single values and multiple values, // potentially collapsing them down. @@ -268,6 +287,7 @@ public abstract class OptionValueDescription { } else { optionValues.put(priority, convertedValue); } + return null; } } @@ -277,9 +297,12 @@ public abstract class OptionValueDescription { * in {@link Option#expansion()} and flags with an {@link Option#expansionFunction()}. */ static class ExpansionOptionValueDescription extends OptionValueDescription { + private final List<String> expansion; - private ExpansionOptionValueDescription(OptionDefinition optionDefinition) { + private ExpansionOptionValueDescription( + OptionDefinition optionDefinition, OptionsData optionsData) { super(optionDefinition); + this.expansion = optionsData.getEvaluatedExpansion(optionDefinition); if (!optionDefinition.isExpansionOption()) { throw new ConstructionException( "Options without expansions can't be tracked using ExpansionOptionValueDescription"); @@ -297,11 +320,22 @@ public abstract class OptionValueDescription { } @Override - void addOptionInstance( - ParsedOptionDescription parsedOption, - List<String> warnings) { - // TODO(b/65540004) Deal with expansion options here instead of in parse(), and track their - // link to the options they expanded to to. + ExpansionBundle addOptionInstance(ParsedOptionDescription parsedOption, List<String> warnings) { + if (parsedOption.getUnconvertedValue() != null + && !parsedOption.getUnconvertedValue().isEmpty()) { + warnings.add( + String.format( + "%s is an expansion option. It does not accept values, and does not change its " + + "expansion based on the value provided. Value '%s' will be ignored.", + optionDefinition, parsedOption.getUnconvertedValue())); + } + + return new ExpansionBundle( + expansion, + (parsedOption.getSource() == null) + ? String.format("expanded from %s", optionDefinition) + : String.format( + "expanded from %s (source %s)", optionDefinition, parsedOption.getSource())); } } @@ -318,17 +352,34 @@ public abstract class OptionValueDescription { } @Override - void addOptionInstance( - ParsedOptionDescription parsedOption, - List<String> warnings) + ExpansionBundle addOptionInstance(ParsedOptionDescription parsedOption, List<String> warnings) throws OptionsParsingException { // This is a valued flag, its value is handled the same way as a normal - // SingleOptionValueDescription. - super.addOptionInstance(parsedOption, warnings); + // SingleOptionValueDescription. (We check at compile time that these flags aren't + // "allowMultiple") + ExpansionBundle superExpansion = super.addOptionInstance(parsedOption, warnings); + Preconditions.checkArgument( + superExpansion == null, "SingleOptionValueDescription should not expand to anything."); + if (parsedOption.getConvertedValue().equals(optionDefinition.getDefaultValue())) { + warnings.add( + String.format( + "%s sets %s to its default value. Since this option has implicit requirements that " + + "are set whenever the option is explicitly provided, regardless of the " + + "value, this will behave differently than letting a default be a default. " + + "Specifically, this options expands to {%s}.", + parsedOption.getCommandLineForm(), + optionDefinition, + String.join(" ", optionDefinition.getImplicitRequirements()))); + } // Now deal with the implicit requirements. - // TODO(b/65540004) Deal with options with implicit requirements here instead of in parse(), - // and track their link to the options they implicitly expanded to to. + return new ExpansionBundle( + ImmutableList.copyOf(optionDefinition.getImplicitRequirements()), + (parsedOption.getSource() == null) + ? String.format("implicit requirement of %s", optionDefinition) + : String.format( + "implicit requirement of %s (source %s)", + optionDefinition, parsedOption.getSource())); } } @@ -350,12 +401,22 @@ public abstract class OptionValueDescription { } @Override - void addOptionInstance( - ParsedOptionDescription parsedOption, - List<String> warnings) + ExpansionBundle addOptionInstance(ParsedOptionDescription parsedOption, List<String> warnings) throws OptionsParsingException { - // TODO(b/65540004) Deal with options with implicit requirements here instead of in parse(), - // and track their link to the options they implicitly expanded to to. + if (!parsedOption.getUnconvertedValue().startsWith("-")) { + throw new OptionsParsingException( + String.format( + "Invalid value format for %s. You may have meant --%s=--%s", + optionDefinition, + optionDefinition.getOptionName(), + parsedOption.getUnconvertedValue())); + } + return new ExpansionBundle( + ImmutableList.of(parsedOption.getUnconvertedValue()), + (parsedOption.getSource() == null) + ? String.format("unwrapped from %s", optionDefinition) + : String.format( + "unwrapped from %s (source %s)", optionDefinition, parsedOption.getSource())); } } } 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 78bfa07ac5..b543328c5c 100644 --- a/src/main/java/com/google/devtools/common/options/OptionsParserImpl.java +++ b/src/main/java/com/google/devtools/common/options/OptionsParserImpl.java @@ -24,6 +24,7 @@ import com.google.common.collect.Iterators; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Multimap; import com.google.devtools.common.options.OptionPriority.PriorityCategory; +import com.google.devtools.common.options.OptionValueDescription.ExpansionBundle; import com.google.devtools.common.options.OptionsParser.OptionDescription; import java.lang.reflect.Constructor; import java.util.ArrayList; @@ -381,8 +382,9 @@ class OptionsParserImpl { // the OptionValueDescription. OptionValueDescription entry = optionValues.computeIfAbsent( - optionDefinition, OptionValueDescription::createOptionValueDescription); - entry.addOptionInstance(parsedOption, warnings); + optionDefinition, + def -> OptionValueDescription.createOptionValueDescription(def, optionsData)); + ExpansionBundle expansionBundle = entry.addOptionInstance(parsedOption, warnings); @Nullable String unconvertedValue = parsedOption.getUnconvertedValue(); // There are 3 types of flags that expand to other flag values. Expansion flags are the @@ -406,43 +408,14 @@ class OptionsParserImpl { } } - if (optionDefinition.isExpansionOption() - || optionDefinition.hasImplicitRequirements() - || optionDefinition.isWrapperOption()) { - StringBuilder sourceMessage = new StringBuilder(); - ImmutableList<String> expansionArgs; - if (optionDefinition.isExpansionOption()) { - expansionArgs = optionsData.getEvaluatedExpansion(optionDefinition); - sourceMessage.append("expanded from option "); - } else if (optionDefinition.hasImplicitRequirements()) { - expansionArgs = ImmutableList.copyOf(optionDefinition.getImplicitRequirements()); - sourceMessage.append("implicit requirement of option "); - } else { - if (!unconvertedValue.startsWith("-")) { - // Wrapper options are the only "expansion" flag type that expand to other flags - // according to user input, so a malformed option is a user error in this case. - throw new OptionsParsingException( - String.format( - "Invalid value format for %s. You may have meant --%s=--%s", - optionDefinition, optionDefinition.getOptionName(), unconvertedValue)); - } else { - expansionArgs = ImmutableList.of(unconvertedValue); - sourceMessage.append("unwrapped from wrapper option "); - } - } - String source = parsedOption.getSource(); - sourceMessage.append( - (source == null) - ? String.format("--%s", optionDefinition.getOptionName()) - : String.format("--%s from %s", optionDefinition.getOptionName(), source)); - + if (expansionBundle != null) { List<String> unparsed = parse( parsedOption.getPriority(), - o -> sourceMessage.toString(), + o -> expansionBundle.sourceOfExpansionArgs, optionDefinition.hasImplicitRequirements() ? optionDefinition : null, optionDefinition.isExpansionOption() ? optionDefinition : null, - expansionArgs); + expansionBundle.expansionArgs); if (!unparsed.isEmpty()) { if (optionDefinition.isWrapperOption()) { throw new OptionsParsingException( |