aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/common
diff options
context:
space:
mode:
authorGravatar ccalvarin <ccalvarin@google.com>2017-10-17 23:27:19 +0200
committerGravatar Jakob Buchgraber <buchgr@google.com>2017-10-18 10:28:26 +0200
commit34a9fea78f201caed8ace5c714a0cf288cb97c65 (patch)
treec3bf1099536ea9b4160c346822833ac47dd56554 /src/main/java/com/google/devtools/common
parent1606cf208cc5194b13ca212819371f7e4ba43a6b (diff)
Remove feature to allow expansion flags to have values.
It was added as a potential fix for --config (an expansion flag with values), but this would have required forcing the parser to know the config's expansions at parsing time, which is not currently possible. Instead, we will use the new addition of option-location tracking to make sure we expand options at a the correct place, even if the expansion is triggered after the fact. This is mostly a straight forward undoing of https://github.com/bazelbuild/bazel/commit/7c7255ec8d6da20526c2c4078c57aadaf3dd3612, except where the context has changed. Notably, implicit requirements are effectively treated like expansion flags, so special casing in OptionDescription could be removed. RELNOTES: None. PiperOrigin-RevId: 172514997
Diffstat (limited to 'src/main/java/com/google/devtools/common')
-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
8 files changed, 103 insertions, 382 deletions
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");