Switch invocation policy enforcer to use behavior enum instead of the old boolean flags.
We have recently added a new enum to express the intended behavior for `SetValue` invocation policy entries. This enum replaces the `overridable` and `append` boolean flags and offers significant advantages over those -- does not have a usable default value, thus must be explicitly set, and does not allow combination of `overridable && append` which is semantically contradictory (`overridable` only applies to non-repetable flags and `append` to repeatable flags).
Deprecate the boolean flags which are superseded by the new enum and use the enum instead of the boolean flags in invocation policy enforcer.
PiperOrigin-RevId: 405924139
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 886793c..136769b 100644
--- a/src/main/java/com/google/devtools/common/options/InvocationPolicyEnforcer.java
+++ b/src/main/java/com/google/devtools/common/options/InvocationPolicyEnforcer.java
@@ -13,7 +13,6 @@
// limitations under the License.
package com.google.devtools.common.options;
-import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.stream.Collectors.joining;
import com.google.common.base.Verify;
@@ -92,6 +91,7 @@
}
}
+ @Nullable
public InvocationPolicy getInvocationPolicy() {
return invocationPolicy;
}
@@ -121,15 +121,6 @@
return;
}
- // TODO(b/186167747): Remove the warning once we migrate to the new enum.
- invocationPolicy.getFlagPoliciesList().stream()
- .filter(p -> p.hasSetValue() && p.getSetValue().getBehavior() == Behavior.UNDEFINED)
- .findFirst()
- .ifPresent(
- policy ->
- logger.atWarning().atMostEvery(5, MINUTES).log(
- "Invocation policy has missing/undefined behavior: %s", policy));
-
// The effective policy returned is expanded, filtered for applicable commands, and cleaned of
// redundancies and conflicts.
List<FlagPolicyWithContext> effectivePolicies =
@@ -314,6 +305,13 @@
String.format("Disallow_Values on expansion flags like %s is not allowed.", flagName));
}
+ private static OptionsParsingException throwUndefinedBehaviorException(FlagPolicy policy)
+ throws OptionsParsingException {
+ throw new OptionsParsingException(
+ String.format(
+ "SetValue operation from invocation policy for has an undefined behavior: %s", policy));
+ }
+
/**
* 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
@@ -425,7 +423,8 @@
OptionDescription subflagDesc,
List<String> subflagValue,
OptionInstanceOrigin subflagOrigin,
- FlagPolicyWithContext originalPolicy) {
+ FlagPolicyWithContext originalPolicy)
+ throws OptionsParsingException {
// Some checks.
OptionDefinition subflag = subflagDesc.getOptionDefinition();
Verify.verify(originalPolicy.policy.getOperationCase().equals(OperationCase.SET_VALUE));
@@ -439,10 +438,18 @@
for (String value : subflagValue) {
setValueExpansion.addFlagValue(value);
}
- if (subflag.allowsMultiple()) {
- setValueExpansion.setAppend(originalPolicy.policy.getSetValue().getOverridable());
- } else {
- setValueExpansion.setOverridable(originalPolicy.policy.getSetValue().getOverridable());
+
+ switch (originalPolicy.policy.getSetValue().getBehavior()) {
+ case UNDEFINED:
+ throw throwUndefinedBehaviorException(originalPolicy.policy);
+ case FINAL_VALUE_IGNORE_OVERRIDES:
+ case APPEND:
+ setValueExpansion.setBehavior(Behavior.FINAL_VALUE_IGNORE_OVERRIDES);
+ break;
+ case ALLOW_OVERRIDES:
+ setValueExpansion.setBehavior(
+ subflag.allowsMultiple() ? Behavior.APPEND : Behavior.ALLOW_OVERRIDES);
+ break;
}
// Commands from the original policy, flag name of the expansion
@@ -554,43 +561,51 @@
optionDefinition));
}
- if (setValue.getOverridable() && valueDescription != null) {
- // The user set the value for the flag but the flag policy is overridable, so keep the user's
- // value.
- logger.at(loglevel).log(
- "Keeping value '%s' from source '%s' for %s because the invocation policy specifying "
- + "the value(s) '%s' is overridable",
- valueDescription.getValue(),
- valueDescription.getSourceString(),
- optionDefinition,
- setValue.getFlagValueList());
- } else {
-
- if (!setValue.getAppend()) {
+ switch (setValue.getBehavior()) {
+ case UNDEFINED:
+ throw throwUndefinedBehaviorException(flagPolicy.policy);
+ case ALLOW_OVERRIDES:
+ if (valueDescription != null) {
+ // The user set the value for the flag but the flag policy is overridable, so keep the
+ // user's
+ // value.
+ logger.at(loglevel).log(
+ "Keeping value '%s' from source '%s' for %s because the invocation policy specifying "
+ + "the value(s) '%s' is overridable",
+ valueDescription.getValue(),
+ valueDescription.getSourceString(),
+ optionDefinition,
+ setValue.getFlagValueList());
+ // Nothing to do -- the value already has an override.
+ return;
+ }
+ break;
+ case FINAL_VALUE_IGNORE_OVERRIDES:
// Clear the value in case the flag is a repeated flag so that values don't accumulate.
parser.clearValue(flagPolicy.description.getOptionDefinition());
- }
+ break;
+ case APPEND:
+ break;
+ }
- // Set all the flag values from the policy.
- for (String flagValue : setValue.getFlagValueList()) {
- if (valueDescription == null) {
- logger.at(loglevel).log(
- "Setting value for %s from invocation policy to '%s', overriding the default value "
- + "'%s'",
- optionDefinition, flagValue, optionDefinition.getDefaultValue());
- } else {
- logger.at(loglevel).log(
- "Setting value for %s from invocation policy to '%s', overriding value '%s' from "
- + "'%s'",
- optionDefinition,
- flagValue,
- valueDescription.getValue(),
- valueDescription.getSourceString());
- }
+ // Set all the flag values from the policy.
+ for (String flagValue : setValue.getFlagValueList()) {
+ if (valueDescription == null) {
+ logger.at(loglevel).log(
+ "Setting value for %s from invocation policy to '%s', overriding the default value "
+ + "'%s'",
+ optionDefinition, flagValue, optionDefinition.getDefaultValue());
+ } else {
+ logger.at(loglevel).log(
+ "Setting value for %s from invocation policy to '%s', overriding value '%s' from '%s'",
+ optionDefinition,
+ flagValue,
+ valueDescription.getValue(),
+ valueDescription.getSourceString());
+ }
parser.setOptionValueAtSpecificPriorityWithoutExpansion(
flagPolicy.origin, optionDefinition, flagValue);
- }
}
}