aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/AllIncompatibleChangesExpansion.java7
-rw-r--r--src/main/java/com/google/devtools/common/options/ExpansionContext.java56
-rw-r--r--src/main/java/com/google/devtools/common/options/ExpansionFunction.java2
-rw-r--r--src/main/java/com/google/devtools/common/options/ExpansionNeedsValueException.java25
-rw-r--r--src/main/java/com/google/devtools/common/options/InvocationPolicyEnforcer.java140
-rw-r--r--src/main/java/com/google/devtools/common/options/OptionsData.java102
-rw-r--r--src/main/java/com/google/devtools/common/options/OptionsParser.java60
-rw-r--r--src/main/java/com/google/devtools/common/options/OptionsParserImpl.java89
-rw-r--r--src/main/java/com/google/devtools/common/options/OptionsUsage.java11
9 files changed, 106 insertions, 386 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/AllIncompatibleChangesExpansion.java b/src/main/java/com/google/devtools/build/lib/runtime/AllIncompatibleChangesExpansion.java
index b6861545ec..87235dbc1b 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/AllIncompatibleChangesExpansion.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/AllIncompatibleChangesExpansion.java
@@ -16,8 +16,8 @@ package com.google.devtools.build.lib.runtime;
import com.google.common.collect.ImmutableList;
import com.google.devtools.common.options.Converter;
-import com.google.devtools.common.options.ExpansionContext;
import com.google.devtools.common.options.ExpansionFunction;
+import com.google.devtools.common.options.IsolatedOptionsData;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionDefinition;
import com.google.devtools.common.options.OptionMetadataTag;
@@ -153,12 +153,11 @@ public class AllIncompatibleChangesExpansion implements ExpansionFunction {
}
@Override
- public ImmutableList<String> getExpansion(ExpansionContext context) {
+ public ImmutableList<String> getExpansion(IsolatedOptionsData optionsData) {
// Grab all registered options that are identified as incompatible changes by either name or
// by category. Ensure they satisfy our requirements.
ArrayList<String> incompatibleChanges = new ArrayList<>();
- for (Map.Entry<String, OptionDefinition> entry :
- context.getOptionsData().getAllOptionDefinitions()) {
+ for (Map.Entry<String, OptionDefinition> entry : optionsData.getAllOptionDefinitions()) {
OptionDefinition optionDefinition = entry.getValue();
if (optionDefinition.getOptionName().startsWith(INCOMPATIBLE_NAME_PREFIX)
|| optionDefinition.getOptionCategory().equals(INCOMPATIBLE_CATEGORY)) {
diff --git a/src/main/java/com/google/devtools/common/options/ExpansionContext.java b/src/main/java/com/google/devtools/common/options/ExpansionContext.java
deleted file mode 100644
index c6aecc7a44..0000000000
--- a/src/main/java/com/google/devtools/common/options/ExpansionContext.java
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2017 The Bazel Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.devtools.common.options;
-
-import java.lang.reflect.Field;
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.ThreadSafe;
-
-/**
- * Encapsulates the data given to {@link ExpansionFunction} objects. This lets {@link
- * ExpansionFunction} objects change how it expands flags based on the arguments given to the {@link
- * OptionsParser}.
- */
-@ThreadSafe
-public final class ExpansionContext {
- private final IsolatedOptionsData optionsData;
- private final OptionDefinition optionDefinition;
- @Nullable private final String unparsedValue;
-
- public ExpansionContext(
- IsolatedOptionsData optionsData,
- OptionDefinition optionDefinition,
- @Nullable String unparsedValue) {
- this.optionsData = optionsData;
- this.optionDefinition = optionDefinition;
- this.unparsedValue = unparsedValue;
- }
-
- /** Metadata for the option that is being expanded. */
- public IsolatedOptionsData getOptionsData() {
- return optionsData;
- }
-
- /** {@link Field} object for option that is being expanded. */
- public OptionDefinition getOptionDefinition() {
- return optionDefinition;
- }
-
- /** Argument given to this flag during options parsing. Will be null if no argument was given. */
- @Nullable
- public String getUnparsedValue() {
- return unparsedValue;
- }
-}
diff --git a/src/main/java/com/google/devtools/common/options/ExpansionFunction.java b/src/main/java/com/google/devtools/common/options/ExpansionFunction.java
index 09119b2dc4..d2c2693da2 100644
--- a/src/main/java/com/google/devtools/common/options/ExpansionFunction.java
+++ b/src/main/java/com/google/devtools/common/options/ExpansionFunction.java
@@ -30,5 +30,5 @@ public interface ExpansionFunction {
* information is computed
* @return An expansion to use on an empty list
*/
- ImmutableList<String> getExpansion(ExpansionContext context) throws OptionsParsingException;
+ ImmutableList<String> getExpansion(IsolatedOptionsData optionsData);
}
diff --git a/src/main/java/com/google/devtools/common/options/ExpansionNeedsValueException.java b/src/main/java/com/google/devtools/common/options/ExpansionNeedsValueException.java
deleted file mode 100644
index d63b988570..0000000000
--- a/src/main/java/com/google/devtools/common/options/ExpansionNeedsValueException.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2017 The Bazel Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package com.google.devtools.common.options;
-
-/**
- * Exception specific to evaluating {@link ExpansionFunction} objects. Used when expansion isn't
- * possible because of a missing input.
- */
-public final class ExpansionNeedsValueException extends OptionsParsingException {
-
- public ExpansionNeedsValueException(String message) {
- super(message);
- }
-}
diff --git a/src/main/java/com/google/devtools/common/options/InvocationPolicyEnforcer.java b/src/main/java/com/google/devtools/common/options/InvocationPolicyEnforcer.java
index 37af8b5fdb..a53ff5b7f6 100644
--- a/src/main/java/com/google/devtools/common/options/InvocationPolicyEnforcer.java
+++ b/src/main/java/com/google/devtools/common/options/InvocationPolicyEnforcer.java
@@ -14,7 +14,6 @@
package com.google.devtools.common.options;
import com.google.common.base.Joiner;
-import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
@@ -38,6 +37,7 @@ import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
+import java.util.stream.Collectors;
import javax.annotation.Nullable;
/**
@@ -259,8 +259,7 @@ public final class InvocationPolicyEnforcer {
continue;
}
- OptionDescription optionDescription =
- parser.getOptionDescription(policy.getFlagName(), origin);
+ OptionDescription optionDescription = parser.getOptionDescription(policy.getFlagName());
if (optionDescription == null) {
// InvocationPolicy ignores policy on non-existing flags by design, for version
// compatibility.
@@ -273,8 +272,7 @@ public final class InvocationPolicyEnforcer {
}
FlagPolicyWithContext policyWithContext =
new FlagPolicyWithContext(policy, optionDescription, origin);
- List<FlagPolicyWithContext> policies =
- expandPolicy(policyWithContext, currentPriority, parser, loglevel);
+ List<FlagPolicyWithContext> policies = expandPolicy(policyWithContext, parser, loglevel);
expandedPolicies.addAll(policies);
}
@@ -300,75 +298,6 @@ public final class InvocationPolicyEnforcer {
String.format("Disallow_Values on expansion flags like %s is not allowed.", flagName));
}
- private static ImmutableList<ParsedOptionDescription> getExpansionsFromFlagPolicy(
- FlagPolicyWithContext expansionPolicy, OptionPriority priority, OptionsParser parser)
- throws OptionsParsingException {
- if (!expansionPolicy.description.isExpansion()) {
- return ImmutableList.of();
- }
- String policyFlagName = expansionPolicy.policy.getFlagName();
- String optionName = expansionPolicy.description.getOptionDefinition().getOptionName();
- Preconditions.checkArgument(
- policyFlagName.equals(optionName),
- "The optionDescription provided (for flag %s) does not match the policy for flag %s.",
- optionName, policyFlagName);
-
- ImmutableList.Builder<ParsedOptionDescription> resultsBuilder = ImmutableList.builder();
- switch (expansionPolicy.policy.getOperationCase()) {
- case SET_VALUE:
- {
- SetValue setValue = expansionPolicy.policy.getSetValue();
- if (setValue.getFlagValueCount() > 0) {
- for (String value : setValue.getFlagValueList()) {
- resultsBuilder.addAll(
- parser.getExpansionOptionValueDescriptions(
- expansionPolicy.description.getOptionDefinition(),
- value,
- priority,
- INVOCATION_POLICY_SOURCE));
- }
- } else {
- resultsBuilder.addAll(
- parser.getExpansionOptionValueDescriptions(
- expansionPolicy.description.getOptionDefinition(),
- null,
- priority,
- INVOCATION_POLICY_SOURCE));
- }
- }
- break;
- case USE_DEFAULT:
- resultsBuilder.addAll(
- parser.getExpansionOptionValueDescriptions(
- expansionPolicy.description.getOptionDefinition(),
- null,
- priority,
- INVOCATION_POLICY_SOURCE));
- break;
- case ALLOW_VALUES:
- // All expansions originally given to the parser have been expanded by now, so these two
- // cases aren't necessary (the values given in the flag policy shouldn't need to be
- // checked). If you care about blocking specific flag values you should block the behavior
- // on the specific ones, not the expansion that contains them.
- throwAllowValuesOnExpansionFlagException(optionName);
- break;
- case DISALLOW_VALUES:
- throwDisallowValuesOnExpansionFlagException(optionName);
- break;
- case OPERATION_NOT_SET:
- throw new PolicyOperationNotSetException(optionName);
- default:
- logger.warning(
- String.format(
- "Unknown operation '%s' from invocation policy for flag '%s'",
- expansionPolicy.policy.getOperationCase(),
- optionName));
- break;
- }
-
- return resultsBuilder.build();
- }
-
/**
* Expand a single policy. If the policy is not about an expansion flag, this will simply return a
* list with a single element, oneself. If the policy is for an expansion flag, the policy will
@@ -378,47 +307,20 @@ public final class InvocationPolicyEnforcer {
*/
private static List<FlagPolicyWithContext> expandPolicy(
FlagPolicyWithContext originalPolicy,
- OptionPriority priority,
OptionsParser parser,
Level loglevel)
throws OptionsParsingException {
List<FlagPolicyWithContext> expandedPolicies = new ArrayList<>();
- OptionInstanceOrigin originOfSubflags;
- ImmutableList<ParsedOptionDescription> subflags;
- if (originalPolicy.description.getOptionDefinition().hasImplicitRequirements()) {
- originOfSubflags =
- new OptionInstanceOrigin(
- originalPolicy.origin.getPriority(),
- String.format(
- "implicitly required by %s (source: %s)",
- originalPolicy.description.getOptionDefinition(),
- originalPolicy.origin.getSource()),
- originalPolicy.description.getOptionDefinition(),
- null);
- subflags = originalPolicy.description.getImplicitRequirements();
- } else if (originalPolicy.description.getOptionDefinition().isExpansionOption()) {
- subflags = getExpansionsFromFlagPolicy(originalPolicy, priority, parser);
- originOfSubflags =
- new OptionInstanceOrigin(
- originalPolicy.origin.getPriority(),
- String.format(
- "expanded by %s (source: %s)",
- originalPolicy.description.getOptionDefinition(),
- originalPolicy.origin.getSource()),
- null,
- originalPolicy.description.getOptionDefinition());
- } else {
+ boolean isExpansion = originalPolicy.description.isExpansion();
+ ImmutableList<ParsedOptionDescription> subflags =
+ parser.getExpansionValueDescriptions(
+ originalPolicy.description.getOptionDefinition(), originalPolicy.origin);
+
+ // If we have nothing to expand to, no need to do any further work.
+ if (subflags.isEmpty()) {
return ImmutableList.of(originalPolicy);
}
- boolean isExpansion = originalPolicy.description.isExpansion();
- // We do not get to this point unless there are flags to expand to.
- boolean hasFlagsToExpandTo = !subflags.isEmpty();
- Preconditions.checkArgument(
- hasFlagsToExpandTo,
- "The only policies that need expanding are those with expansions or implicit requirements, "
- + "%s has neither yet was not returned as-is.",
- originalPolicy.description.getOptionDefinition());
if (logger.isLoggable(loglevel)) {
// Log the expansion. This is only really useful for understanding the invocation policy
@@ -450,8 +352,7 @@ public final class InvocationPolicyEnforcer {
// UseDefault, when preventing it from being set.
for (ParsedOptionDescription currentSubflag : subflags) {
OptionDescription subflagOptionDescription =
- parser.getOptionDescription(
- currentSubflag.getOptionDefinition().getOptionName(), originOfSubflags);
+ parser.getOptionDescription(currentSubflag.getOptionDefinition().getOptionName());
if (currentSubflag.getOptionDefinition().allowsMultiple()
&& originalPolicy.policy.getOperationCase().equals(OperationCase.SET_VALUE)) {
@@ -461,7 +362,7 @@ public final class InvocationPolicyEnforcer {
getSingleValueSubflagAsPolicy(
subflagOptionDescription, currentSubflag, originalPolicy, isExpansion);
// In case any of the expanded flags are themselves expansions, recurse.
- expandedPolicies.addAll(expandPolicy(subflagAsPolicy, priority, parser, loglevel));
+ expandedPolicies.addAll(expandPolicy(subflagAsPolicy, parser, loglevel));
}
}
@@ -471,9 +372,26 @@ public final class InvocationPolicyEnforcer {
for (OptionDescription repeatableFlag : repeatableSubflagsInSetValues.keySet()) {
int numValues = repeatableSubflagsInSetValues.get(repeatableFlag).size();
ArrayList<String> newValues = new ArrayList<>(numValues);
+ ArrayList<OptionInstanceOrigin> origins = new ArrayList<>(numValues);
for (ParsedOptionDescription setValue : repeatableSubflagsInSetValues.get(repeatableFlag)) {
newValues.add(setValue.getUnconvertedValue());
+ origins.add(setValue.getOrigin());
}
+ // These options come from expanding a single policy, so they have effectively the same
+ // priority. They could have come from different expansions or implicit requirements in the
+ // recursive resolving of the option list, so just pick the first one. Do collapse the source
+ // strings though, in case there are different sources.
+ OptionInstanceOrigin arbitraryFirstOptionOrigin = origins.get(0);
+ OptionInstanceOrigin originOfSubflags =
+ new OptionInstanceOrigin(
+ arbitraryFirstOptionOrigin.getPriority(),
+ origins
+ .stream()
+ .map(OptionInstanceOrigin::getSource)
+ .distinct()
+ .collect(Collectors.joining(", ")),
+ arbitraryFirstOptionOrigin.getImplicitDependent(),
+ arbitraryFirstOptionOrigin.getExpandedFrom());
expandedPolicies.add(
getSetValueSubflagAsPolicy(repeatableFlag, newValues, originOfSubflags, originalPolicy));
}
diff --git a/src/main/java/com/google/devtools/common/options/OptionsData.java b/src/main/java/com/google/devtools/common/options/OptionsData.java
index 69f360ad71..63cac249c2 100644
--- a/src/main/java/com/google/devtools/common/options/OptionsData.java
+++ b/src/main/java/com/google/devtools/common/options/OptionsData.java
@@ -14,14 +14,12 @@
package com.google.devtools.common.options;
-import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Map;
-import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
/**
@@ -32,86 +30,26 @@ import javax.annotation.concurrent.Immutable;
@Immutable
final class OptionsData extends IsolatedOptionsData {
- /**
- * Keeps track of all the information needed to calculate expansion flags, whether they come from
- * a static list or a @{link ExpansionFunction} object.
- */
- static class ExpansionData {
- private final ImmutableList<String> staticExpansion;
- @Nullable private final ExpansionFunction dynamicExpansions;
-
- ExpansionData(ImmutableList<String> staticExpansion) {
- Preconditions.checkArgument(staticExpansion != null);
- this.staticExpansion = staticExpansion;
- this.dynamicExpansions = null;
- }
-
- ExpansionData(ExpansionFunction dynamicExpansions) {
- Preconditions.checkArgument(dynamicExpansions != null);
- this.staticExpansion = EMPTY_EXPANSION;
- this.dynamicExpansions = dynamicExpansions;
- }
-
- ImmutableList<String> getExpansion(ExpansionContext context) throws OptionsParsingException {
- Preconditions.checkArgument(context != null);
- if (dynamicExpansions != null) {
- ImmutableList<String> result = dynamicExpansions.getExpansion(context);
- if (result == null) {
- String valueString =
- context.getUnparsedValue() != null ? context.getUnparsedValue() : "(null)";
- String name = context.getOptionDefinition().getOptionName();
- throw new OptionsParsingException(
- String.format(
- "Error expanding %s: no expansions defined for value: %s",
- context.getOptionDefinition(), valueString),
- name);
- }
- return result;
- } else {
- return staticExpansion;
- }
- }
-
- boolean isEmpty() {
- return staticExpansion.isEmpty() && (dynamicExpansions == null);
- }
- }
-
- /**
- * Mapping from each Option-annotated field with expansion information to the {@link
- * ExpansionData} needed to caclulate it.
- */
- private final ImmutableMap<OptionDefinition, ExpansionData> expansionDataForFields;
+ /** Mapping from each option to the (unparsed) options it expands to, if any. */
+ private final ImmutableMap<OptionDefinition, ImmutableList<String>> evaluatedExpansions;
/** Construct {@link OptionsData} by extending an {@link IsolatedOptionsData} with new info. */
private OptionsData(
- IsolatedOptionsData base, Map<OptionDefinition, ExpansionData> expansionDataForFields) {
+ IsolatedOptionsData base, Map<OptionDefinition, ImmutableList<String>> evaluatedExpansions) {
super(base);
- this.expansionDataForFields = ImmutableMap.copyOf(expansionDataForFields);
+ this.evaluatedExpansions = ImmutableMap.copyOf(evaluatedExpansions);
}
private static final ImmutableList<String> EMPTY_EXPANSION = ImmutableList.<String>of();
- private static final ExpansionData EMPTY_EXPANSION_DATA = new ExpansionData(EMPTY_EXPANSION);
/**
* Returns the expansion of an options field, regardless of whether it was defined using {@link
* Option#expansion} or {@link Option#expansionFunction}. If the field is not an expansion option,
* returns an empty array.
*/
- public ImmutableList<String> getEvaluatedExpansion(
- OptionDefinition optionDefinition, @Nullable String unparsedValue)
- throws OptionsParsingException {
- ExpansionData expansionData = expansionDataForFields.get(optionDefinition);
- if (expansionData == null) {
- return EMPTY_EXPANSION;
- }
-
- return expansionData.getExpansion(new ExpansionContext(this, optionDefinition, unparsedValue));
- }
-
- ExpansionData getExpansionDataForField(OptionDefinition optionDefinition) {
- ExpansionData result = expansionDataForFields.get(optionDefinition);
- return result != null ? result : EMPTY_EXPANSION_DATA;
+ public ImmutableList<String> getEvaluatedExpansion(OptionDefinition optionDefinition) {
+ ImmutableList<String> result = evaluatedExpansions.get(optionDefinition);
+ return result != null ? result : EMPTY_EXPANSION;
}
/**
@@ -125,8 +63,8 @@ final class OptionsData extends IsolatedOptionsData {
IsolatedOptionsData isolatedData = IsolatedOptionsData.from(classes);
// All that's left is to compute expansions.
- ImmutableMap.Builder<OptionDefinition, ExpansionData> expansionDataBuilder =
- ImmutableMap.<OptionDefinition, ExpansionData>builder();
+ ImmutableMap.Builder<OptionDefinition, ImmutableList<String>> evaluatedExpansionsBuilder =
+ ImmutableMap.builder();
for (Map.Entry<String, OptionDefinition> entry : isolatedData.getAllOptionDefinitions()) {
OptionDefinition optionDefinition = entry.getValue();
// Determine either the hard-coded expansion, or the ExpansionFunction class. The
@@ -135,8 +73,7 @@ final class OptionsData extends IsolatedOptionsData {
Class<? extends ExpansionFunction> expansionFunctionClass =
optionDefinition.getExpansionFunction();
if (constExpansion.length > 0) {
- expansionDataBuilder.put(
- optionDefinition, new ExpansionData(ImmutableList.copyOf(constExpansion)));
+ evaluatedExpansionsBuilder.put(optionDefinition, ImmutableList.copyOf(constExpansion));
} else if (optionDefinition.usesExpansionFunction()) {
if (Modifier.isAbstract(expansionFunctionClass.getModifiers())) {
throw new AssertionError(
@@ -152,23 +89,10 @@ final class OptionsData extends IsolatedOptionsData {
// time it is used.
throw new AssertionError(e);
}
-
- ImmutableList<String> staticExpansion;
- try {
- staticExpansion =
- instance.getExpansion(new ExpansionContext(isolatedData, optionDefinition, null));
- Preconditions.checkState(
- staticExpansion != null, "Error calling expansion function for %s", optionDefinition);
- expansionDataBuilder.put(optionDefinition, new ExpansionData(staticExpansion));
- } catch (ExpansionNeedsValueException e) {
- // This expansion function needs data that isn't available yet. Save the instance and call
- // it later.
- expansionDataBuilder.put(optionDefinition, new ExpansionData(instance));
- } catch (OptionsParsingException e) {
- throw new IllegalStateException("Error expanding void expansion function: ", e);
- }
+ ImmutableList<String> expansion = instance.getExpansion(isolatedData);
+ evaluatedExpansionsBuilder.put(optionDefinition, expansion);
}
}
- return new OptionsData(isolatedData, expansionDataBuilder.build());
+ return new OptionsData(isolatedData, evaluatedExpansionsBuilder.build());
}
}
diff --git a/src/main/java/com/google/devtools/common/options/OptionsParser.java b/src/main/java/com/google/devtools/common/options/OptionsParser.java
index ba3e57a237..f84ee474a2 100644
--- a/src/main/java/com/google/devtools/common/options/OptionsParser.java
+++ b/src/main/java/com/google/devtools/common/options/OptionsParser.java
@@ -39,7 +39,6 @@ import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
-import javax.annotation.Nullable;
/**
* A parser for options. Typical use case in a main method:
@@ -153,11 +152,9 @@ public class OptionsParser implements OptionsProvider {
return newOptionsParser(ImmutableList.<Class<? extends OptionsBase>>of(class1));
}
- /**
- * @see #newOptionsParser(Iterable)
- */
- public static OptionsParser newOptionsParser(Class<? extends OptionsBase> class1,
- Class<? extends OptionsBase> class2)
+ /** @see #newOptionsParser(Iterable) */
+ public static OptionsParser newOptionsParser(
+ Class<? extends OptionsBase> class1, Class<? extends OptionsBase> class2)
throws ConstructionException {
return newOptionsParser(ImmutableList.of(class1, class2));
}
@@ -240,52 +237,41 @@ public class OptionsParser implements OptionsProvider {
/** The metadata about an option, in the context of this options parser. */
public static final class OptionDescription {
-
private final OptionDefinition optionDefinition;
- private final OptionsData.ExpansionData expansionData;
- private final ImmutableList<ParsedOptionDescription> implicitRequirements;
+ private final ImmutableList<String> evaluatedExpansion;
- OptionDescription(
- OptionDefinition definition,
- OptionsData.ExpansionData expansionData,
- ImmutableList<ParsedOptionDescription> implicitRequirements) {
+ OptionDescription(OptionDefinition definition, OptionsData optionsData) {
this.optionDefinition = definition;
- this.expansionData = expansionData;
- this.implicitRequirements = implicitRequirements;
+ this.evaluatedExpansion = optionsData.getEvaluatedExpansion(optionDefinition);
}
public OptionDefinition getOptionDefinition() {
return optionDefinition;
}
- public ImmutableList<ParsedOptionDescription> getImplicitRequirements() {
- return implicitRequirements;
- }
-
public boolean isExpansion() {
- return !expansionData.isEmpty();
+ return optionDefinition.isExpansionOption();
}
/** Return a list of flags that this option expands to. */
- public ImmutableList<String> getExpansion(ExpansionContext context)
- throws OptionsParsingException {
- return expansionData.getExpansion(context);
+ public ImmutableList<String> getExpansion() throws OptionsParsingException {
+ return evaluatedExpansion;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof OptionDescription) {
OptionDescription other = (OptionDescription) obj;
- // Check that the option is the same and that it is in the same context (expansionData)
+ // Check that the option is the same, with the same expansion.
return other.optionDefinition.equals(optionDefinition)
- && other.expansionData.equals(expansionData);
+ && other.evaluatedExpansion.equals(evaluatedExpansion);
}
return false;
}
@Override
public int hashCode() {
- return optionDefinition.hashCode() + expansionData.hashCode();
+ return optionDefinition.hashCode() + evaluatedExpansion.hashCode();
}
}
@@ -534,22 +520,23 @@ public class OptionsParser implements OptionsProvider {
* @return The {@link OptionDescription} for the option, or null if there is no option by the
* given name.
*/
- OptionDescription getOptionDescription(String name, OptionInstanceOrigin origin)
- throws OptionsParsingException {
- return impl.getOptionDescription(name, origin);
+ OptionDescription getOptionDescription(String name) throws OptionsParsingException {
+ return impl.getOptionDescription(name);
}
/**
- * Returns a description of the options values that get expanded from this option with the given
- * value.
+ * Returns the parsed options that get expanded from this option, whether it expands due to an
+ * implicit requirement or expansion.
*
- * @return The {@link com.google.devtools.common.options.OptionValueDescription>} for the option,
- * or null if there is no option by the given name.
+ * @param expansionOption the option that might need to be expanded. If this option does not
+ * expand to other options, the empty list will be returned.
+ * @param originOfExpansionOption the origin of the option that's being expanded. This function
+ * will take care of adjusting the source messages as necessary.
*/
- ImmutableList<ParsedOptionDescription> getExpansionOptionValueDescriptions(
- OptionDefinition option, @Nullable String optionValue, OptionPriority priority, String source)
+ ImmutableList<ParsedOptionDescription> getExpansionValueDescriptions(
+ OptionDefinition expansionOption, OptionInstanceOrigin originOfExpansionOption)
throws OptionsParsingException {
- return impl.getExpansionOptionValueDescriptions(option, optionValue, priority, source);
+ return impl.getExpansionValueDescriptions(expansionOption, originOfExpansionOption);
}
/**
@@ -845,4 +832,3 @@ public class OptionsParser implements OptionsProvider {
+ "}");
}
}
-
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 96f4c16649..78bfa07ac5 100644
--- a/src/main/java/com/google/devtools/common/options/OptionsParserImpl.java
+++ b/src/main/java/com/google/devtools/common/options/OptionsParserImpl.java
@@ -208,77 +208,58 @@ class OptionsParserImpl {
return optionValues.get(optionDefinition);
}
- OptionDescription getOptionDescription(String name, OptionInstanceOrigin origin)
- throws OptionsParsingException {
+ OptionDescription getOptionDescription(String name) throws OptionsParsingException {
OptionDefinition optionDefinition = optionsData.getOptionDefinitionFromName(name);
if (optionDefinition == null) {
return null;
}
-
- return new OptionDescription(
- optionDefinition,
- optionsData.getExpansionDataForField(optionDefinition),
- getImplicitDependentDescriptions(
- ImmutableList.copyOf(optionDefinition.getImplicitRequirements()),
- optionDefinition,
- origin));
- }
-
- /** @return A list of the descriptions corresponding to the implicit dependent flags passed in. */
- private ImmutableList<ParsedOptionDescription> getImplicitDependentDescriptions(
- ImmutableList<String> options,
- OptionDefinition implicitDependent,
- OptionInstanceOrigin dependentsOrigin)
- throws OptionsParsingException {
- ImmutableList.Builder<ParsedOptionDescription> builder = ImmutableList.builder();
- Iterator<String> optionsIterator = options.iterator();
-
- Function<OptionDefinition, String> sourceFunction =
- o ->
- String.format(
- "implicitely required for %s (source: %s)",
- implicitDependent, dependentsOrigin.getSource());
- while (optionsIterator.hasNext()) {
- String unparsedFlagExpression = optionsIterator.next();
- ParsedOptionDescription parsedOption =
- identifyOptionAndPossibleArgument(
- unparsedFlagExpression,
- optionsIterator,
- dependentsOrigin.getPriority(),
- sourceFunction,
- implicitDependent,
- null);
- builder.add(parsedOption);
- }
- return builder.build();
+ return new OptionDescription(optionDefinition, optionsData);
}
/**
- * @return A list of the descriptions corresponding to options expanded from the flag for the
- * given value. The value itself is a string, no conversion has taken place.
+ * Implementation of {@link OptionsParser#getExpansionValueDescriptions(OptionDefinition,
+ * OptionInstanceOrigin)}
*/
- ImmutableList<ParsedOptionDescription> getExpansionOptionValueDescriptions(
- OptionDefinition expansionFlag,
- @Nullable String flagValue,
- OptionPriority priority,
- String source)
+ ImmutableList<ParsedOptionDescription> getExpansionValueDescriptions(
+ OptionDefinition expansionFlag, OptionInstanceOrigin originOfExpansionFlag)
throws OptionsParsingException {
ImmutableList.Builder<ParsedOptionDescription> builder = ImmutableList.builder();
+ OptionInstanceOrigin originOfSubflags;
+ ImmutableList<String> options;
+ if (expansionFlag.hasImplicitRequirements()) {
+ options = ImmutableList.copyOf(expansionFlag.getImplicitRequirements());
+ originOfSubflags =
+ new OptionInstanceOrigin(
+ originOfExpansionFlag.getPriority(),
+ String.format(
+ "implicitly required by %s (source: %s)",
+ expansionFlag, originOfExpansionFlag.getSource()),
+ expansionFlag,
+ null);
+ } else if (expansionFlag.isExpansionOption()) {
+ options = optionsData.getEvaluatedExpansion(expansionFlag);
+ originOfSubflags =
+ new OptionInstanceOrigin(
+ originOfExpansionFlag.getPriority(),
+ String.format(
+ "expanded by %s (source: %s)", expansionFlag, originOfExpansionFlag.getSource()),
+ null,
+ expansionFlag);
+ } else {
+ return ImmutableList.of();
+ }
- ImmutableList<String> options = optionsData.getEvaluatedExpansion(expansionFlag, flagValue);
Iterator<String> optionsIterator = options.iterator();
- Function<OptionDefinition, String> sourceFunction =
- o -> String.format("expanded from %s (source: %s)", expansionFlag, source);
while (optionsIterator.hasNext()) {
String unparsedFlagExpression = optionsIterator.next();
ParsedOptionDescription parsedOption =
identifyOptionAndPossibleArgument(
unparsedFlagExpression,
optionsIterator,
- priority,
- sourceFunction,
- null,
- expansionFlag);
+ originOfSubflags.getPriority(),
+ o -> originOfSubflags.getSource(),
+ originOfSubflags.getImplicitDependent(),
+ originOfSubflags.getExpandedFrom());
builder.add(parsedOption);
}
return builder.build();
@@ -431,7 +412,7 @@ class OptionsParserImpl {
StringBuilder sourceMessage = new StringBuilder();
ImmutableList<String> expansionArgs;
if (optionDefinition.isExpansionOption()) {
- expansionArgs = optionsData.getEvaluatedExpansion(optionDefinition, unconvertedValue);
+ expansionArgs = optionsData.getEvaluatedExpansion(optionDefinition);
sourceMessage.append("expanded from option ");
} else if (optionDefinition.hasImplicitRequirements()) {
expansionArgs = ImmutableList.copyOf(optionDefinition.getImplicitRequirements());
diff --git a/src/main/java/com/google/devtools/common/options/OptionsUsage.java b/src/main/java/com/google/devtools/common/options/OptionsUsage.java
index ecc7a6b61b..6dee0eb7ac 100644
--- a/src/main/java/com/google/devtools/common/options/OptionsUsage.java
+++ b/src/main/java/com/google/devtools/common/options/OptionsUsage.java
@@ -89,14 +89,7 @@ class OptionsUsage {
private static @Nullable ImmutableList<String> getExpansionIfKnown(
OptionDefinition optionDefinition, OptionsData optionsData) {
Preconditions.checkNotNull(optionDefinition);
- try {
- return optionsData.getEvaluatedExpansion(optionDefinition, null);
- } catch (ExpansionNeedsValueException e) {
- return null;
- } catch (OptionsParsingException e) {
- throw new IllegalStateException("Error expanding void expansion function: ", e);
- }
-
+ return optionsData.getEvaluatedExpansion(optionDefinition);
}
// Placeholder tag "UNKNOWN" is ignored.
@@ -244,7 +237,7 @@ class OptionsUsage {
usage.append('\n');
}
- if (!optionsData.getExpansionDataForField(optionDefinition).isEmpty()) {
+ if (!optionsData.getEvaluatedExpansion(optionDefinition).isEmpty()) {
// If this is an expansion option, list the expansion if known, or at least specify that we
// don't know.
usage.append("<br/>\n");