Add a conversionContext parameter to option converters
We need to pass flag values through the repo mapping of the main repo, which means that at flag parsing time, we need access to the main repo mapping. To that end, we add a nullable untyped `conversionContext` parameter to the `Converter#convert` method, which is unused in this CL but will be used in a follow-up.
Note that we can't directly add a `RepositoryMapping` parameter because the c.g.devtools.common.options package is a transitive dependency of c.g.devtools.build.lib.cmdline (which RepositoryMapping lives in). So this `conversionContext` will unfortunately need to be an Object.
Reviewers: Please focus on reviewing changes in the c.g.devtools.common.options package. All the other changes in this CL are simply adding a `conversionContext` parameter to implementors of `Converter`, or passing this parameter to delegates, or superclasses.
Work towards https://github.com/bazelbuild/bazel/issues/14852
PiperOrigin-RevId: 459278433
Change-Id: I98b3842305c34d2d0c33e7411c1024897fb0170a
diff --git a/src/java_tools/import_deps_checker/java/com/google/devtools/build/importdeps/Main.java b/src/java_tools/import_deps_checker/java/com/google/devtools/build/importdeps/Main.java
index 4d7f179..f80ee5c 100644
--- a/src/java_tools/import_deps_checker/java/com/google/devtools/build/importdeps/Main.java
+++ b/src/java_tools/import_deps_checker/java/com/google/devtools/build/importdeps/Main.java
@@ -228,7 +228,7 @@
}
/** Validating converter for Paths. A Path is considered valid if it resolves to a file. */
- public static class PathConverter implements Converter<Path> {
+ public static class PathConverter extends Converter.Contextless<Path> {
private final boolean mustExist;
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ResourceSet.java b/src/main/java/com/google/devtools/build/lib/actions/ResourceSet.java
index 7bdfa2d..a0b6046 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ResourceSet.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ResourceSet.java
@@ -167,7 +167,8 @@
+ getLocalTestCount() * p * p;
}
- public static class ResourceSetConverter implements Converter<ResourceSet> {
+ /** Converter for {@link ResourceSet}. */
+ public static class ResourceSetConverter extends Converter.Contextless<ResourceSet> {
private static final Splitter SPLITTER = Splitter.on(',');
@Override
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/WorkspaceStatusAction.java b/src/main/java/com/google/devtools/build/lib/analysis/WorkspaceStatusAction.java
index 6c063d5..008b2b0 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/WorkspaceStatusAction.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/WorkspaceStatusAction.java
@@ -245,7 +245,7 @@
}
/** Converter for {@code --embed_label} which rejects strings that span multiple lines. */
- public static final class OneLineStringConverter implements Converter<String> {
+ public static final class OneLineStringConverter extends Converter.Contextless<String> {
@Override
public String convert(String input) throws OptionsParsingException {
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/AutoCpuConverter.java b/src/main/java/com/google/devtools/build/lib/analysis/config/AutoCpuConverter.java
index 031e783..4d5917a 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/AutoCpuConverter.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/AutoCpuConverter.java
@@ -26,7 +26,7 @@
* <p>If the compilation happens remotely then the cpu of the remote machine might be different from
* the auto-detected one and the --cpu and --host_cpu options must be set explicitly.
*/
-public class AutoCpuConverter implements Converter<String> {
+public class AutoCpuConverter extends Converter.Contextless<String> {
@Override
public String convert(String input) throws OptionsParsingException {
if (input.isEmpty()) {
@@ -83,7 +83,10 @@
return input;
}
- /** Reverses the conversion performed by {@link #convert} to return the matching OS, CPU pair. */
+ /**
+ * Reverses the conversion performed by {@link Converter#convert} to return the matching OS, CPU
+ * pair.
+ */
public static Pair<CPU, OS> reverse(String input) {
if (input == null || input.length() == 0 || "unknown".equals(input)) {
// Use the auto-detected values.
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/CoreOptionConverters.java b/src/main/java/com/google/devtools/build/lib/analysis/config/CoreOptionConverters.java
index 7a3e59b..dca99f3 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/CoreOptionConverters.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/CoreOptionConverters.java
@@ -63,7 +63,7 @@
.buildOrThrow();
/** A converter from strings to Starlark int values. */
- private static class StarlarkIntConverter implements Converter<StarlarkInt> {
+ private static class StarlarkIntConverter extends Converter.Contextless<StarlarkInt> {
@Override
public StarlarkInt convert(String input) throws OptionsParsingException {
// Note that Starlark rule attribute values are currently restricted
@@ -85,8 +85,8 @@
/** A converter from strings to Labels. */
public static class LabelConverter implements Converter<Label> {
@Override
- public Label convert(String input) throws OptionsParsingException {
- return convertOptionsLabel(input);
+ public Label convert(String input, Object conversionContext) throws OptionsParsingException {
+ return convertOptionsLabel(input, conversionContext);
}
@Override
@@ -98,10 +98,11 @@
/** A converter from comma-separated strings to Label lists. */
public static class LabelListConverter implements Converter<List<Label>> {
@Override
- public List<Label> convert(String input) throws OptionsParsingException {
+ public List<Label> convert(String input, Object conversionContext)
+ throws OptionsParsingException {
ImmutableList.Builder<Label> result = ImmutableList.builder();
for (String label : Splitter.on(",").omitEmptyStrings().split(input)) {
- result.add(convertOptionsLabel(label));
+ result.add(convertOptionsLabel(label, conversionContext));
}
return result.build();
}
@@ -119,8 +120,8 @@
public static class EmptyToNullLabelConverter implements Converter<Label> {
@Override
@Nullable
- public Label convert(String input) throws OptionsParsingException {
- return input.isEmpty() ? null : convertOptionsLabel(input);
+ public Label convert(String input, Object conversionContext) throws OptionsParsingException {
+ return input.isEmpty() ? null : convertOptionsLabel(input, conversionContext);
}
@Override
@@ -139,8 +140,8 @@
}
@Override
- public Label convert(String input) throws OptionsParsingException {
- return input.isEmpty() ? defaultValue : convertOptionsLabel(input);
+ public Label convert(String input, Object conversionContext) throws OptionsParsingException {
+ return input.isEmpty() ? defaultValue : convertOptionsLabel(input, conversionContext);
}
@Override
@@ -152,7 +153,8 @@
/** Flag converter for a map of unique keys with optional labels as values. */
public static class LabelMapConverter implements Converter<Map<String, Label>> {
@Override
- public Map<String, Label> convert(String input) throws OptionsParsingException {
+ public Map<String, Label> convert(String input, Object conversionContext)
+ throws OptionsParsingException {
// Use LinkedHashMap so we can report duplicate keys more easily while preserving order
Map<String, Label> result = new LinkedHashMap<>();
for (String entry : Splitter.on(",").omitEmptyStrings().trimResults().split(input)) {
@@ -165,7 +167,7 @@
} else {
key = entry.substring(0, sepIndex);
String value = entry.substring(sepIndex + 1);
- label = value.isEmpty() ? null : convertOptionsLabel(value);
+ label = value.isEmpty() ? null : convertOptionsLabel(value, conversionContext);
}
if (result.containsKey(key)) {
throw new OptionsParsingException("Key '" + key + "' appears twice");
@@ -202,7 +204,8 @@
}
}
- private static final Label convertOptionsLabel(String input) throws OptionsParsingException {
+ private static Label convertOptionsLabel(String input, @Nullable Object conversionContext)
+ throws OptionsParsingException {
try {
// Check if the input starts with '/'. We don't check for "//" so that
// we get a better error message if the user accidentally tries to use
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/CoreOptions.java b/src/main/java/com/google/devtools/build/lib/analysis/config/CoreOptions.java
index bc68d18..1eaff6f 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/CoreOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/CoreOptions.java
@@ -254,7 +254,7 @@
public boolean enableAspectHints;
/** Regardless of input, converts to an empty list. For use with affectedByStarlarkTransition */
- public static class EmptyListConverter implements Converter<List<String>> {
+ public static class EmptyListConverter extends Converter.Contextless<List<String>> {
@Override
public List<String> convert(String input) throws OptionsParsingException {
return ImmutableList.of();
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/ExecutionInfoModifier.java b/src/main/java/com/google/devtools/build/lib/analysis/config/ExecutionInfoModifier.java
index 3777ffc..2fbf328 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/ExecutionInfoModifier.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/ExecutionInfoModifier.java
@@ -58,7 +58,7 @@
/** Constructs an instance of ExecutionInfoModifier by parsing an option string. */
public static class Converter
- implements com.google.devtools.common.options.Converter<ExecutionInfoModifier> {
+ extends com.google.devtools.common.options.Converter.Contextless<ExecutionInfoModifier> {
@Override
public ExecutionInfoModifier convert(String input) throws OptionsParsingException {
if (Strings.isNullOrEmpty(input)) {
@@ -77,7 +77,7 @@
// Convert to get a useful exception if it's not a valid pattern, but use the regex
// (see comment in Expression)
new RegexPatternConverter()
- .convert(specMatcher.group("pattern"))
+ .convert(specMatcher.group("pattern"), /*conversionContext=*/ null)
.regexPattern()
.pattern(),
specMatcher.group("sign").equals("-"),
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/PerLabelOptions.java b/src/main/java/com/google/devtools/build/lib/analysis/config/PerLabelOptions.java
index 8fb1eea..a3f8bcf 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/PerLabelOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/PerLabelOptions.java
@@ -37,15 +37,13 @@
private final List<String> optionsList;
/**
- * Converts a String to a {@link PerLabelOptions} object. The syntax of the
- * string is {@code regex_filter@option_1,option_2,...,option_n}. Where
- * regex_filter stands for the String representation of a {@link RegexFilter},
- * and {@code option_1} to {@code option_n} stand for arbitrary command line
- * options. If an option contains a comma it has to be quoted with a
- * backslash. Options can contain @. Only the first @ is used to split the
- * string.
+ * Converts a String to a {@link PerLabelOptions} object. The syntax of the string is {@code
+ * regex_filter@option_1,option_2,...,option_n}. Where regex_filter stands for the String
+ * representation of a {@link RegexFilter}, and {@code option_1} to {@code option_n} stand for
+ * arbitrary command line options. If an option contains a comma it has to be quoted with a
+ * backslash. Options can contain @. Only the first @ is used to split the string.
*/
- public static class PerLabelOptionsConverter implements Converter<PerLabelOptions> {
+ public static class PerLabelOptionsConverter extends Converter.Contextless<PerLabelOptions> {
@Override
public PerLabelOptions convert(String input) throws OptionsParsingException {
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/RunUnderConverter.java b/src/main/java/com/google/devtools/build/lib/analysis/config/RunUnderConverter.java
index de029e6..a959e47 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/RunUnderConverter.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/RunUnderConverter.java
@@ -26,12 +26,11 @@
import java.util.Objects;
import javax.annotation.Nullable;
-/**
- * --run_under options converter.
- */
+/** --run_under options converter. */
public class RunUnderConverter implements Converter<RunUnder> {
@Override
- public RunUnder convert(final String input) throws OptionsParsingException {
+ public RunUnder convert(final String input, Object conversionContext)
+ throws OptionsParsingException {
final List<String> runUnderList = new ArrayList<>();
try {
ShellUtils.tokenize(runUnderList, input);
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/FunctionTransitionUtil.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/FunctionTransitionUtil.java
index e08529e..245b1d4 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/FunctionTransitionUtil.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/FunctionTransitionUtil.java
@@ -308,12 +308,13 @@
// of returning either a scalar or list.
List<?> optionValueAsList = (List<?>) optionValue;
if (optionValueAsList.isEmpty()) {
- convertedValue = def.getDefaultValue();
+ convertedValue = ImmutableList.of();
} else {
convertedValue =
def.getConverter()
.convert(
- optionValueAsList.stream().map(Object::toString).collect(joining(",")));
+ optionValueAsList.stream().map(Object::toString).collect(joining(",")),
+ /*conversionContext=*/ null);
}
} else if (def.getType() == List.class && optionValue == null) {
throw ValidationException.format(
@@ -325,7 +326,8 @@
} else if (def.getType().equals(boolean.class) && optionValue instanceof Boolean) {
convertedValue = optionValue;
} else if (optionValue instanceof String) {
- convertedValue = def.getConverter().convert((String) optionValue);
+ convertedValue =
+ def.getConverter().convert((String) optionValue, /*conversionContext=*/ null);
} else {
throw ValidationException.format("Invalid value type for option '%s'", optionName);
}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/commands/ModqueryOptions.java b/src/main/java/com/google/devtools/build/lib/bazel/commands/ModqueryOptions.java
index 7019a9c6..cbf1e70 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/commands/ModqueryOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/commands/ModqueryOptions.java
@@ -218,7 +218,7 @@
}
/** Converts a module target argument string to a properly typed {@link TargetModule} */
- static class TargetModuleConverter implements Converter<TargetModule> {
+ static class TargetModuleConverter extends Converter.Contextless<TargetModule> {
@Override
public TargetModule convert(String input) throws OptionsParsingException {
@@ -260,17 +260,19 @@
}
/** Converts a comma-separated module list argument (i.e. A@1.0,B@2.0) */
- public static class TargetModuleListConverter implements Converter<ImmutableList<TargetModule>> {
+ public static class TargetModuleListConverter
+ extends Converter.Contextless<ImmutableList<TargetModule>> {
@Override
public ImmutableList<TargetModule> convert(String input) throws OptionsParsingException {
CommaSeparatedNonEmptyOptionListConverter listConverter =
new CommaSeparatedNonEmptyOptionListConverter();
TargetModuleConverter targetModuleConverter = new TargetModuleConverter();
- ImmutableList<String> targetStrings = listConverter.convert(input);
+ ImmutableList<String> targetStrings =
+ listConverter.convert(input, /*conversionContext=*/ null);
ImmutableList.Builder<TargetModule> targetModules = new ImmutableList.Builder<>();
for (String targetInput : targetStrings) {
- targetModules.add(targetModuleConverter.convert(targetInput));
+ targetModules.add(targetModuleConverter.convert(targetInput, /*conversionContext=*/ null));
}
return targetModules.build();
}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/RepositoryOptions.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/RepositoryOptions.java
index 2dbc4b6..7905d31 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/RepositoryOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/RepositoryOptions.java
@@ -257,7 +257,8 @@
/**
* Converts from an equals-separated pair of strings into RepositoryName->PathFragment mapping.
*/
- public static class RepositoryOverrideConverter implements Converter<RepositoryOverride> {
+ public static class RepositoryOverrideConverter
+ extends Converter.Contextless<RepositoryOverride> {
@Override
public RepositoryOverride convert(String input) throws OptionsParsingException {
diff --git a/src/main/java/com/google/devtools/build/lib/packages/EnumFilterConverter.java b/src/main/java/com/google/devtools/build/lib/packages/EnumFilterConverter.java
index e3f2c2f..ebdf232 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/EnumFilterConverter.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/EnumFilterConverter.java
@@ -22,16 +22,16 @@
import java.util.Set;
/**
- * Converter that translates a string of the form "value1,value2,-value3,value4"
- * into a corresponding set of allowed Enum values.
+ * Converter that translates a string of the form "value1,value2,-value3,value4" into a
+ * corresponding set of allowed Enum values.
*
- * <p>Values preceded by '-' are excluded from this set. So "value1,-value2,value3"
- * translates to the set [EnumType.value1, EnumType.value3].
+ * <p>Values preceded by '-' are excluded from this set. So "value1,-value2,value3" translates to
+ * the set [EnumType.value1, EnumType.value3].
*
- * <p>If *all* values are exclusions (e.g. "-value1,-value2,-value3"), the returned
- * set contains all values for the Enum type *except* those specified.
+ * <p>If *all* values are exclusions (e.g. "-value1,-value2,-value3"), the returned set contains all
+ * values for the Enum type *except* those specified.
*/
-class EnumFilterConverter<E extends Enum<E>> implements Converter<Set<E>> {
+class EnumFilterConverter<E extends Enum<E>> extends Converter.Contextless<Set<E>> {
private final Set<String> allowedValues = new LinkedHashSet<>();
private final Class<E> typeClass;
@@ -54,7 +54,7 @@
/**
* Returns the set of allowed values for the option.
*
- * Implements {@link #convert(String)}.
+ * <p>Implements {@link Converter#convert(String, Object)}.
*/
@Override
public Set<E> convert(String input) throws OptionsParsingException {
diff --git a/src/main/java/com/google/devtools/build/lib/packages/TestSize.java b/src/main/java/com/google/devtools/build/lib/packages/TestSize.java
index 0b277eb..5e6e8d2 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/TestSize.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/TestSize.java
@@ -121,9 +121,9 @@
/**
* {@inheritDoc}
*
- * <p>This override is necessary to prevent OptionsData
- * from throwing a "must be assignable from the converter return type" exception.
- * OptionsData doesn't recognize the generic type and actual type are the same.
+ * <p>This override is necessary to prevent OptionsData from throwing a "must be assignable from
+ * the converter return type" exception. OptionsData doesn't recognize the generic type and
+ * actual type are the same.
*/
@Override
public final Set<TestSize> convert(String input) throws OptionsParsingException {
diff --git a/src/main/java/com/google/devtools/build/lib/packages/TestTimeout.java b/src/main/java/com/google/devtools/build/lib/packages/TestTimeout.java
index 9f67213..1c64df6 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/TestTimeout.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/TestTimeout.java
@@ -190,10 +190,9 @@
return SUGGESTED_TIMEOUT.get(timeInSeconds);
}
- /**
- * Converter for the --test_timeout option.
- */
- public static class TestTimeoutConverter implements Converter<Map<TestTimeout, Duration>> {
+ /** Converter for the --test_timeout option. */
+ public static class TestTimeoutConverter
+ extends Converter.Contextless<Map<TestTimeout, Duration>> {
public TestTimeoutConverter() {}
@Override
@@ -250,9 +249,9 @@
/**
* {@inheritDoc}
*
- * <p>This override is necessary to prevent OptionsData
- * from throwing a "must be assignable from the converter return type" exception.
- * OptionsData doesn't recognize the generic type and actual type are the same.
+ * <p>This override is necessary to prevent OptionsData from throwing a "must be assignable from
+ * the converter return type" exception. OptionsData doesn't recognize the generic type and
+ * actual type are the same.
*/
@Override
public final Set<TestTimeout> convert(String input) throws OptionsParsingException {
diff --git a/src/main/java/com/google/devtools/build/lib/pkgcache/PackageOptions.java b/src/main/java/com/google/devtools/build/lib/pkgcache/PackageOptions.java
index 3e85d8f..e0ae0ba 100644
--- a/src/main/java/com/google/devtools/build/lib/pkgcache/PackageOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/pkgcache/PackageOptions.java
@@ -38,10 +38,8 @@
/** Options for configuring Packages -- loading and default behaviors. */
public class PackageOptions extends OptionsBase {
- /**
- * Converter for the {@code --default_visibility} option.
- */
- public static class DefaultVisibilityConverter implements Converter<RuleVisibility> {
+ /** Converter for the {@code --default_visibility} option. */
+ public static class DefaultVisibilityConverter extends Converter.Contextless<RuleVisibility> {
@Override
public RuleVisibility convert(String input) throws OptionsParsingException {
if (input.equals("public")) {
@@ -194,11 +192,9 @@
+ "previous run's cache.")
public boolean checkOutputFiles;
- /**
- * A converter from strings containing comma-separated names of packages to lists of strings.
- */
+ /** A converter from strings containing comma-separated names of packages to lists of strings. */
public static class CommaSeparatedPackageNameListConverter
- implements Converter<List<PackageIdentifier>> {
+ extends Converter.Contextless<List<PackageIdentifier>> {
private static final Splitter COMMA_SPLITTER = Splitter.on(',');
diff --git a/src/main/java/com/google/devtools/build/lib/profiler/MemoryProfiler.java b/src/main/java/com/google/devtools/build/lib/profiler/MemoryProfiler.java
index a34af69..48c05b8 100644
--- a/src/main/java/com/google/devtools/build/lib/profiler/MemoryProfiler.java
+++ b/src/main/java/com/google/devtools/build/lib/profiler/MemoryProfiler.java
@@ -140,7 +140,8 @@
/** Converter for {@code MemoryProfileStableHeapParameters} option. */
public static class Converter
- implements com.google.devtools.common.options.Converter<MemoryProfileStableHeapParameters> {
+ extends com.google.devtools.common.options.Converter.Contextless<
+ MemoryProfileStableHeapParameters> {
private static final Splitter SPLITTER = Splitter.on(',');
@Override
diff --git a/src/main/java/com/google/devtools/build/lib/remote/options/RemoteOptions.java b/src/main/java/com/google/devtools/build/lib/remote/options/RemoteOptions.java
index 841df55..c8b3959 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/options/RemoteOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/options/RemoteOptions.java
@@ -218,7 +218,7 @@
public String remoteBytestreamUriPrefix;
/** Returns the specified duration. Assumes seconds if unitless. */
- public static class RemoteTimeoutConverter implements Converter<Duration> {
+ public static class RemoteTimeoutConverter extends Converter.Contextless<Duration> {
private static final Pattern UNITLESS_REGEX = Pattern.compile("^[0-9]+$");
@Override
@@ -226,7 +226,7 @@
if (UNITLESS_REGEX.matcher(input).matches()) {
input += "s";
}
- return new Converters.DurationConverter().convert(input);
+ return new Converters.DurationConverter().convert(input, /*conversionContext=*/ null);
}
@Override
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleBitcodeConverter.java b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleBitcodeConverter.java
index b5235ea..9fc053e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleBitcodeConverter.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleBitcodeConverter.java
@@ -28,7 +28,7 @@
* platform type and the bitcode mode to apply to builds targeting that platform.
*/
public final class AppleBitcodeConverter
- implements Converter<List<Map.Entry<ApplePlatform.PlatformType, AppleBitcodeMode>>> {
+ extends Converter.Contextless<List<Map.Entry<ApplePlatform.PlatformType, AppleBitcodeMode>>> {
/** Used to convert Bitcode mode strings to their enum value. */
private static final AppleBitcodeMode.Converter MODE_CONVERTER = new AppleBitcodeMode.Converter();
@@ -83,7 +83,7 @@
private static AppleBitcodeMode convertAppleBitcodeMode(String input)
throws OptionsParsingException {
try {
- return MODE_CONVERTER.convert(input);
+ return MODE_CONVERTER.convert(input, /*conversionContext=*/ null);
} catch (OptionsParsingException e) {
throw new OptionsParsingException(INVALID_APPLE_BITCODE_OPTION_FORMAT, e);
}
@@ -97,7 +97,7 @@
private static ApplePlatform.PlatformType convertPlatformType(String input)
throws OptionsParsingException {
try {
- return PLATFORM_TYPE_CONVERTER.convert(input);
+ return PLATFORM_TYPE_CONVERTER.convert(input, /*conversionContext=*/ null);
} catch (OptionsParsingException e) {
throw new OptionsParsingException(INVALID_APPLE_BITCODE_OPTION_FORMAT, e);
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/DottedVersionConverter.java b/src/main/java/com/google/devtools/build/lib/rules/apple/DottedVersionConverter.java
index cb26b3e..b51736f 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/DottedVersionConverter.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/DottedVersionConverter.java
@@ -17,10 +17,8 @@
import com.google.devtools.common.options.Converter;
import com.google.devtools.common.options.OptionsParsingException;
-/**
- * Converter for options representing {@link DottedVersion} values.
- */
-public class DottedVersionConverter implements Converter<DottedVersion.Option> {
+/** Converter for options representing {@link DottedVersion} values. */
+public class DottedVersionConverter extends Converter.Contextless<DottedVersion.Option> {
@Override
public DottedVersion.Option convert(String input) throws OptionsParsingException {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigSetting.java b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigSetting.java
index 6f8a3a1..a84de0a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigSetting.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigSetting.java
@@ -479,8 +479,12 @@
: provider.getDefaultValue();
Object convertedSpecifiedValue;
try {
+ // We don't need to supply a base package or repo mapping for the conversion here,
+ // because `specifiedValue` is already canonicalized.
convertedSpecifiedValue =
- BUILD_SETTING_CONVERTERS.get(provider.getType()).convert(specifiedValue);
+ BUILD_SETTING_CONVERTERS
+ .get(provider.getType())
+ .convert(specifiedValue, /*conversionContext=*/ null);
} catch (OptionsParsingException e) {
ruleContext.attributeError(
ConfigSettingRule.FLAG_SETTINGS_ATTRIBUTE,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java
index ebb2f90..da95bc9 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java
@@ -42,7 +42,7 @@
/** Command-line options for C++. */
public class CppOptions extends FragmentOptions {
/** Converts a comma-separated list of compilation mode settings to a properly typed List. */
- public static class FissionOptionConverter implements Converter<List<CompilationMode>> {
+ public static class FissionOptionConverter extends Converter.Contextless<List<CompilationMode>> {
@Override
public List<CompilationMode> convert(String input) throws OptionsParsingException {
ImmutableSet.Builder<CompilationMode> modes = ImmutableSet.builder();
@@ -51,7 +51,7 @@
} else if (!input.equals("no")) { // "no" is another special case that disables all modes.
CompilationMode.Converter modeConverter = new CompilationMode.Converter();
for (String mode : Splitter.on(',').split(input)) {
- modes.add(modeConverter.convert(mode));
+ modes.add(modeConverter.convert(mode, /*conversionContext=*/ null));
}
}
return modes.build().asList();
@@ -82,7 +82,7 @@
/**
* Converts a String, which is a package label into a label that can be used for a LibcTop object.
*/
- public static class LibcTopLabelConverter implements Converter<Label> {
+ public static class LibcTopLabelConverter extends Converter.Contextless<Label> {
@Nullable
@Override
public Label convert(String input) throws OptionsParsingException {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/PythonOptions.java b/src/main/java/com/google/devtools/build/lib/rules/python/PythonOptions.java
index 6795f35..7242c0d 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/python/PythonOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/python/PythonOptions.java
@@ -40,7 +40,7 @@
/** Converter for options that take ({@code PY2} or {@code PY3}). */
// We don't use EnumConverter because we want to disallow non-target PythonVersion values.
- public static class TargetPythonVersionConverter implements Converter<PythonVersion> {
+ public static class TargetPythonVersionConverter extends Converter.Contextless<PythonVersion> {
@Override
public PythonVersion convert(String input) throws OptionsParsingException {
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BlazeOptionHandler.java b/src/main/java/com/google/devtools/build/lib/runtime/BlazeOptionHandler.java
index 848bf66..35ef818 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/BlazeOptionHandler.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BlazeOptionHandler.java
@@ -171,6 +171,7 @@
* <p>For each command, the options are parsed in rc order. This uses the primary rc file first,
* and follows import statements. This is the order in which they were passed by the client.
*/
+ @VisibleForTesting
void parseRcOptions(
EventHandler eventHandler, ListMultimap<String, RcChunkOfArgs> commandToRcArgs)
throws OptionsParsingException {
@@ -325,7 +326,8 @@
.mergeFrom(invocationPolicy)
.build();
InvocationPolicyEnforcer optionsPolicyEnforcer =
- new InvocationPolicyEnforcer(combinedPolicy, Level.INFO);
+ new InvocationPolicyEnforcer(
+ combinedPolicy, Level.INFO, optionsParser.getConversionContext());
// Enforce the invocation policy. It is intentional that this is the last step in preparing
// the options. The invocation policy is used in security-critical contexts, and may be used
// as a last resort to override flags. That means that the policy can override flags set in
@@ -363,6 +365,7 @@
* Expand the values of --config according to the definitions provided in the rc files and the
* applicable command.
*/
+ @VisibleForTesting
void expandConfigOptions(
EventHandler eventHandler, ListMultimap<String, RcChunkOfArgs> commandToRcArgs)
throws OptionsParsingException {
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BlazeServerStartupOptions.java b/src/main/java/com/google/devtools/build/lib/runtime/BlazeServerStartupOptions.java
index 240836a..38cbff6 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/BlazeServerStartupOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BlazeServerStartupOptions.java
@@ -45,7 +45,7 @@
* "option_name1:source1:option_name2:source2:.." and converts it into an option name to source
* map.
*/
- public static class OptionSourcesConverter implements Converter<Map<String, String>> {
+ public static class OptionSourcesConverter extends Converter.Contextless<Map<String, String>> {
private String unescape(String input) {
return input.replace("_C", ":").replace("_U", "_");
}
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/ClientOptions.java b/src/main/java/com/google/devtools/build/lib/runtime/ClientOptions.java
index 7c442c9..5919a77 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/ClientOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/ClientOptions.java
@@ -55,7 +55,7 @@
}
/** Converter for --default_override. The format is: --default_override=blazerc:command=option. */
- public static class OptionOverrideConverter implements Converter<OptionOverride> {
+ public static class OptionOverrideConverter extends Converter.Contextless<OptionOverride> {
static final String ERROR_MESSAGE =
"option overrides must be in form rcfile:command=option, where rcfile is a nonzero integer";
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/CommandLineEvent.java b/src/main/java/com/google/devtools/build/lib/runtime/CommandLineEvent.java
index f1d0fd5..18ba246 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/CommandLineEvent.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/CommandLineEvent.java
@@ -456,7 +456,7 @@
* form and as unstructured strings.
*/
public static class Converter
- implements com.google.devtools.common.options.Converter<ToolCommandLineEvent> {
+ extends com.google.devtools.common.options.Converter.Contextless<ToolCommandLineEvent> {
@Override
public ToolCommandLineEvent convert(String input) throws OptionsParsingException {
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/CommonCommandOptions.java b/src/main/java/com/google/devtools/build/lib/runtime/CommonCommandOptions.java
index 20f98d9..fd60652 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/CommonCommandOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/CommonCommandOptions.java
@@ -118,7 +118,7 @@
public boolean alwaysProfileSlowOperations;
/** Converter for UUID. Accepts values as specified by {@link UUID#fromString(String)}. */
- public static class UUIDConverter implements Converter<UUID> {
+ public static class UUIDConverter extends Converter.Contextless<UUID> {
@Override
@Nullable
@@ -144,7 +144,7 @@
* Converter for options (--build_request_id) that accept prefixed UUIDs. Since we do not care
* about the structure of this value after validation, we store it as a string.
*/
- public static class PrefixedUUIDConverter implements Converter<String> {
+ public static class PrefixedUUIDConverter extends Converter.Contextless<String> {
@Override
@Nullable
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/StarlarkOptionsParser.java b/src/main/java/com/google/devtools/build/lib/runtime/StarlarkOptionsParser.java
index ca412a1..89a35f5 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/StarlarkOptionsParser.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/StarlarkOptionsParser.java
@@ -171,7 +171,7 @@
Converter<?> converter = BUILD_SETTING_CONVERTERS.get(type);
Object value;
try {
- value = converter.convert(unparsedValue);
+ value = converter.convert(unparsedValue, nativeOptionsParser.getConversionContext());
} catch (OptionsParsingException e) {
throw new OptionsParsingException(
String.format(
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/UiOptions.java b/src/main/java/com/google/devtools/build/lib/runtime/UiOptions.java
index 55240ab..ccbfe05 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/UiOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/UiOptions.java
@@ -46,7 +46,7 @@
}
/** Converter for {@link EventKind} filters * */
- public static class EventFiltersConverter implements Converter<List<EventKind>> {
+ public static class EventFiltersConverter extends Converter.Contextless<List<EventKind>> {
/** A converter for event kinds. */
public static class EventKindConverter extends EnumConverter<EventKind> {
@@ -69,7 +69,7 @@
// Empty list means that the user wants to filter all events
return new ArrayList<>(EventKind.ALL_EVENTS);
}
- List<String> filters = this.delegate.convert(input);
+ List<String> filters = this.delegate.convert(input, /*conversionContext=*/ null);
EnumConverter<EventKind> eventKindConverter = new EventKindConverter(input);
HashSet<EventKind> filteredEvents = new HashSet<>();
@@ -82,11 +82,13 @@
for (String filter : filters) {
if (filter.startsWith("+")) {
- filteredEvents.remove(eventKindConverter.convert(filter.substring(1)));
+ filteredEvents.remove(
+ eventKindConverter.convert(filter.substring(1), /*conversionContext=*/ null));
} else if (filter.startsWith("-")) {
- filteredEvents.add(eventKindConverter.convert(filter.substring(1)));
+ filteredEvents.add(
+ eventKindConverter.convert(filter.substring(1), /*conversionContext=*/ null));
} else {
- filteredEvents.remove(eventKindConverter.convert(filter));
+ filteredEvents.remove(eventKindConverter.convert(filter, /*conversionContext=*/ null));
}
}
return new ArrayList<>(filteredEvents);
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/CanonicalizeCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/CanonicalizeCommand.java
index 6984946..74a846f 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/CanonicalizeCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/CanonicalizeCommand.java
@@ -220,7 +220,7 @@
try {
InvocationPolicyEnforcer invocationPolicyEnforcer =
- new InvocationPolicyEnforcer(policy, Level.INFO);
+ new InvocationPolicyEnforcer(policy, Level.INFO, /*conversionContext=*/ null);
invocationPolicyEnforcer.enforce(parser, commandName);
if (canonicalizeOptions.showWarnings) {
diff --git a/src/main/java/com/google/devtools/build/lib/sandbox/SandboxOptions.java b/src/main/java/com/google/devtools/build/lib/sandbox/SandboxOptions.java
index 35b4213..c680220 100644
--- a/src/main/java/com/google/devtools/build/lib/sandbox/SandboxOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/sandbox/SandboxOptions.java
@@ -45,7 +45,7 @@
* invocation. Pairs are expected to have the form 'source:target'.
*/
public static final class MountPairConverter
- implements Converter<ImmutableMap.Entry<String, String>> {
+ extends Converter.Contextless<ImmutableMap.Entry<String, String>> {
@Override
public ImmutableMap.Entry<String, String> convert(String input) throws OptionsParsingException {
diff --git a/src/main/java/com/google/devtools/build/lib/util/OptionsUtils.java b/src/main/java/com/google/devtools/build/lib/util/OptionsUtils.java
index 01c2424..68f84d1 100644
--- a/src/main/java/com/google/devtools/build/lib/util/OptionsUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/util/OptionsUtils.java
@@ -95,7 +95,7 @@
}
/** Converter from String to PathFragment. */
- public static class PathFragmentConverter implements Converter<PathFragment> {
+ public static class PathFragmentConverter extends Converter.Contextless<PathFragment> {
@Override
public PathFragment convert(String input) {
@@ -109,7 +109,7 @@
}
/** Converter from String to PathFragment requiring the provided path to be absolute. */
- public static class AbsolutePathFragmentConverter implements Converter<PathFragment> {
+ public static class AbsolutePathFragmentConverter extends Converter.Contextless<PathFragment> {
@Override
public PathFragment convert(String input) throws OptionsParsingException {
@@ -127,7 +127,8 @@
}
/** Converter from String to PathFragment. If the input is empty returns {@code null} instead. */
- public static class EmptyToNullRelativePathFragmentConverter implements Converter<PathFragment> {
+ public static class EmptyToNullRelativePathFragmentConverter
+ extends Converter.Contextless<PathFragment> {
@Override
public PathFragment convert(String input) throws OptionsParsingException {
@@ -151,7 +152,8 @@
}
/** Converts from a colon-separated list of strings into a list of PathFragment instances. */
- public static class PathFragmentListConverter implements Converter<ImmutableList<PathFragment>> {
+ public static class PathFragmentListConverter
+ extends Converter.Contextless<ImmutableList<PathFragment>> {
@Override
public ImmutableList<PathFragment> convert(String input) {
diff --git a/src/main/java/com/google/devtools/build/lib/util/PathFragmentFilter.java b/src/main/java/com/google/devtools/build/lib/util/PathFragmentFilter.java
index f9368f4..3c6bf73 100644
--- a/src/main/java/com/google/devtools/build/lib/util/PathFragmentFilter.java
+++ b/src/main/java/com/google/devtools/build/lib/util/PathFragmentFilter.java
@@ -35,12 +35,12 @@
/**
* Converts from a colon-separated list of of paths with optional '-' prefix into the
- * PathFragmentFilter:
- * [-]path1[,[-]path2]...
+ * PathFragmentFilter: [-]path1[,[-]path2]...
*
- * Order of paths is not important. Empty entries are ignored. '-' marks an excluded path.
+ * <p>Order of paths is not important. Empty entries are ignored. '-' marks an excluded path.
*/
- public static class PathFragmentFilterConverter implements Converter<PathFragmentFilter> {
+ public static class PathFragmentFilterConverter
+ extends Converter.Contextless<PathFragmentFilter> {
@Override
public PathFragmentFilter convert(String input) {
diff --git a/src/main/java/com/google/devtools/build/lib/util/RegexFilter.java b/src/main/java/com/google/devtools/build/lib/util/RegexFilter.java
index b0fa3fa..f606c17 100644
--- a/src/main/java/com/google/devtools/build/lib/util/RegexFilter.java
+++ b/src/main/java/com/google/devtools/build/lib/util/RegexFilter.java
@@ -48,7 +48,7 @@
* <p>Order of expressions is not important. Empty entries are ignored. '-' marks an excluded
* expression.
*/
- public static class RegexFilterConverter implements Converter<RegexFilter> {
+ public static class RegexFilterConverter extends Converter.Contextless<RegexFilter> {
@Override
public RegexFilter convert(String input) throws OptionsParsingException {
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/DigestHashFunction.java b/src/main/java/com/google/devtools/build/lib/vfs/DigestHashFunction.java
index e760bb3..e279d7b 100644
--- a/src/main/java/com/google/devtools/build/lib/vfs/DigestHashFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/vfs/DigestHashFunction.java
@@ -128,7 +128,7 @@
}
/** Converts a string to its registered {@link DigestHashFunction}. */
- public static class DigestFunctionConverter implements Converter<DigestHashFunction> {
+ public static class DigestFunctionConverter extends Converter.Contextless<DigestHashFunction> {
@Override
public DigestHashFunction convert(String input) throws OptionsParsingException {
for (Entry<String, DigestHashFunction> possibleFunctions : hashFunctionRegistry.entrySet()) {
diff --git a/src/main/java/com/google/devtools/build/lib/worker/WorkerOptions.java b/src/main/java/com/google/devtools/build/lib/worker/WorkerOptions.java
index efc521d..cb3c456 100644
--- a/src/main/java/com/google/devtools/build/lib/worker/WorkerOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/worker/WorkerOptions.java
@@ -52,7 +52,7 @@
* the empty string is used as the key. The default value for unspecified mnemonics is {@value
* DEFAULT_VALUE}. "auto" currently returns the default.
*/
- public static class MultiResourceConverter implements Converter<Entry<String, Integer>> {
+ public static class MultiResourceConverter extends Converter.Contextless<Entry<String, Integer>> {
public static final int DEFAULT_VALUE = 4;
@@ -67,11 +67,11 @@
}
int pos = input.indexOf('=');
if (pos < 0) {
- return Maps.immutableEntry("", valueConverter.convert(input));
+ return Maps.immutableEntry("", valueConverter.convert(input, /*conversionContext=*/ null));
}
String name = input.substring(0, pos);
String value = input.substring(pos + 1);
- return Maps.immutableEntry(name, valueConverter.convert(value));
+ return Maps.immutableEntry(name, valueConverter.convert(value, /*conversionContext=*/ null));
}
@Override
diff --git a/src/main/java/com/google/devtools/common/options/BoolOrEnumConverter.java b/src/main/java/com/google/devtools/common/options/BoolOrEnumConverter.java
index aabddeb..a1f3d26a 100644
--- a/src/main/java/com/google/devtools/common/options/BoolOrEnumConverter.java
+++ b/src/main/java/com/google/devtools/common/options/BoolOrEnumConverter.java
@@ -55,7 +55,7 @@
} catch (OptionsParsingException eEnum) {
try {
BooleanConverter booleanConverter = new BooleanConverter();
- boolean value = booleanConverter.convert(input);
+ boolean value = booleanConverter.convert(input, /*conversionContext=*/ null);
return value ? trueValue : falseValue;
} catch (OptionsParsingException eBoolean) {
// TODO(b/111883901): Rethrowing the exception from the enum converter does not report the
diff --git a/src/main/java/com/google/devtools/common/options/Converter.java b/src/main/java/com/google/devtools/common/options/Converter.java
index f3e6ddd..aca5842 100644
--- a/src/main/java/com/google/devtools/common/options/Converter.java
+++ b/src/main/java/com/google/devtools/common/options/Converter.java
@@ -13,17 +13,20 @@
// limitations under the License.
package com.google.devtools.common.options;
+import javax.annotation.Nullable;
+
/**
- * A converter is a little helper object that can take a String and
- * turn it into an instance of type T (the type parameter to the converter).
+ * A converter is a little helper object that can take a String and turn it into an instance of type
+ * T (the type parameter to the converter). A context object is optionally provided.
*/
public interface Converter<T> {
/**
- * Convert a string into type T. Please note that we assume that converting the same string (if
- * successful) will produce objects which are equal ({@link Object#equals)}).
+ * Convert a string into type T, using the given conversion context. Please note that we assume
+ * that converting the same string (if successful) will produce objects which are equal ({@link
+ * Object#equals}).
*/
- T convert(String input) throws OptionsParsingException;
+ T convert(String input, @Nullable Object conversionContext) throws OptionsParsingException;
/**
* The type description appears in usage messages. E.g.: "a string",
@@ -31,4 +34,19 @@
*/
String getTypeDescription();
+ /** A converter that never reads its context parameter. */
+ abstract class Contextless<T> implements Converter<T> {
+
+ /**
+ * Actual implementation of {@link #convert(String, Object)} that just ignores the context
+ * parameter.
+ */
+ public abstract T convert(String input) throws OptionsParsingException;
+
+ @Override
+ public final T convert(String input, @Nullable Object conversionContext)
+ throws OptionsParsingException {
+ return convert(input);
+ }
+ }
}
diff --git a/src/main/java/com/google/devtools/common/options/Converters.java b/src/main/java/com/google/devtools/common/options/Converters.java
index 15e8b47..0a8a949 100644
--- a/src/main/java/com/google/devtools/common/options/Converters.java
+++ b/src/main/java/com/google/devtools/common/options/Converters.java
@@ -29,6 +29,7 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
+import javax.annotation.Nullable;
/** Some convenient converters used by blaze. Note: These are specific to blaze. */
public final class Converters {
@@ -46,7 +47,7 @@
ImmutableList.of("false", "0", "no", "f", "n");
/** Standard converter for booleans. Accepts common shorthands/synonyms. */
- public static class BooleanConverter implements Converter<Boolean> {
+ public static class BooleanConverter extends Converter.Contextless<Boolean> {
@Override
public Boolean convert(String input) throws OptionsParsingException {
if (input == null) {
@@ -69,7 +70,7 @@
}
/** Standard converter for Strings. */
- public static class StringConverter implements Converter<String> {
+ public static class StringConverter extends Converter.Contextless<String> {
@Override
public String convert(String input) {
return input;
@@ -82,7 +83,7 @@
}
/** Standard converter for integers. */
- public static class IntegerConverter implements Converter<Integer> {
+ public static class IntegerConverter extends Converter.Contextless<Integer> {
@Override
public Integer convert(String input) throws OptionsParsingException {
try {
@@ -99,7 +100,7 @@
}
/** Standard converter for longs. */
- public static class LongConverter implements Converter<Long> {
+ public static class LongConverter extends Converter.Contextless<Long> {
@Override
public Long convert(String input) throws OptionsParsingException {
try {
@@ -116,7 +117,7 @@
}
/** Standard converter for doubles. */
- public static class DoubleConverter implements Converter<Double> {
+ public static class DoubleConverter extends Converter.Contextless<Double> {
@Override
public Double convert(String input) throws OptionsParsingException {
try {
@@ -133,7 +134,7 @@
}
/** Standard converter for TriState values. */
- public static class TriStateConverter implements Converter<TriState> {
+ public static class TriStateConverter extends Converter.Contextless<TriState> {
@Override
public TriState convert(String input) throws OptionsParsingException {
if (input == null) {
@@ -162,7 +163,7 @@
* Standard "converter" for Void. Should not actually be invoked. For instance, expansion flags
* are usually Void-typed and do not invoke the converter.
*/
- public static class VoidConverter implements Converter<Void> {
+ public static class VoidConverter extends Converter.Contextless<Void> {
@Override
public Void convert(String input) throws OptionsParsingException {
if (input == null || input.equals("null")) {
@@ -178,7 +179,7 @@
}
/** Standard converter for the {@link java.time.Duration} type. */
- public static class DurationConverter implements Converter<Duration> {
+ public static class DurationConverter extends Converter.Contextless<Duration> {
private final Pattern durationRegex = Pattern.compile("^([0-9]+)(d|h|m|s|ms)$");
@Override
@@ -251,7 +252,8 @@
}
/** Converter for a list of options, separated by some separator character. */
- public static class SeparatedOptionListConverter implements Converter<ImmutableList<String>> {
+ public static class SeparatedOptionListConverter
+ extends Converter.Contextless<ImmutableList<String>> {
private final String separatorDescription;
private final Splitter splitter;
private final boolean allowEmptyValues;
@@ -305,7 +307,8 @@
}
}
- public static class LogLevelConverter implements Converter<Level> {
+ /** Converter for {@link Level}. */
+ public static class LogLevelConverter extends Converter.Contextless<Level> {
static final ImmutableList<Level> LEVELS =
ImmutableList.of(
@@ -334,7 +337,7 @@
}
/** Checks whether a string is part of a set of strings. */
- public static class StringSetConverter implements Converter<String> {
+ public static class StringSetConverter extends Converter.Contextless<String> {
// TODO(bazel-team): if this class never actually contains duplicates, we could s/List/Set/
// here.
@@ -360,7 +363,7 @@
}
/** Checks whether a string is a valid regex pattern and compiles it. */
- public static class RegexPatternConverter implements Converter<RegexPatternOption> {
+ public static class RegexPatternConverter extends Converter.Contextless<RegexPatternOption> {
@Override
public RegexPatternOption convert(String input) throws OptionsParsingException {
@@ -378,7 +381,7 @@
}
/** Limits the length of a string argument. */
- public static class LengthLimitingConverter implements Converter<String> {
+ public static class LengthLimitingConverter extends Converter.Contextless<String> {
private final int maxSize;
public LengthLimitingConverter(int maxSize) {
@@ -400,7 +403,7 @@
}
/** Checks whether an integer is in the given range. */
- public static class RangeConverter implements Converter<Integer> {
+ public static class RangeConverter extends Converter.Contextless<Integer> {
final int minValue;
final int maxValue;
@@ -449,7 +452,7 @@
* Assignments are expected to have the form "name=value", where names and values are defined to
* be as permissive as possible.
*/
- public static class AssignmentConverter implements Converter<Map.Entry<String, String>> {
+ public static class AssignmentConverter extends Converter.Contextless<Map.Entry<String, String>> {
@Override
public Map.Entry<String, String> convert(String input) throws OptionsParsingException {
@@ -536,7 +539,8 @@
}
@Override
- public Map.Entry<K, List<V>> convert(String input) throws OptionsParsingException {
+ public Map.Entry<K, List<V>> convert(String input, @Nullable Object conversionContext)
+ throws OptionsParsingException {
int pos = input.indexOf("=");
if (allowEmptyKeys == AllowEmptyKeys.NO && pos <= 0) {
throw new OptionsParsingException(
@@ -557,9 +561,10 @@
}
ImmutableList.Builder<V> convertedValues = ImmutableList.builder();
for (String value : values) {
- convertedValues.add(valueConverter.convert(value));
+ convertedValues.add(valueConverter.convert(value, conversionContext));
}
- return Maps.immutableEntry(keyConverter.convert(key), convertedValues.build());
+ return Maps.immutableEntry(
+ keyConverter.convert(key, conversionContext), convertedValues.build());
}
}
@@ -575,6 +580,10 @@
super(new StringConverter(), new StringConverter(), AllowEmptyKeys.YES);
}
+ public Map.Entry<String, List<String>> convert(String input) throws OptionsParsingException {
+ return convert(input, /*conversionContext=*/ null);
+ }
+
@Override
public String getTypeDescription() {
return "a '[name=]value1[,..,valueN]' assignment";
@@ -587,7 +596,8 @@
* be as permissive as possible and value part can be optional (in which case it is considered to
* be null).
*/
- public static class OptionalAssignmentConverter implements Converter<Map.Entry<String, String>> {
+ public static class OptionalAssignmentConverter
+ extends Converter.Contextless<Map.Entry<String, String>> {
@Override
public Map.Entry<String, String> convert(String input) throws OptionsParsingException {
@@ -613,7 +623,8 @@
* A converter for named integers of the form "[name=]value". When no name is specified, an empty
* string is used for the key.
*/
- public static class NamedIntegersConverter implements Converter<Map.Entry<String, Integer>> {
+ public static class NamedIntegersConverter
+ extends Converter.Contextless<Map.Entry<String, Integer>> {
@Override
public Map.Entry<String, Integer> convert(String input) throws OptionsParsingException {
@@ -662,7 +673,7 @@
* A {@link Converter} for {@link com.github.benmanes.caffeine.cache.CaffeineSpec}. The spec may
* be empty, in which case this converter returns null.
*/
- public static final class CaffeineSpecConverter implements Converter<CaffeineSpec> {
+ public static final class CaffeineSpecConverter extends Converter.Contextless<CaffeineSpec> {
@Override
public CaffeineSpec convert(String spec) throws OptionsParsingException {
try {
diff --git a/src/main/java/com/google/devtools/common/options/EnumConverter.java b/src/main/java/com/google/devtools/common/options/EnumConverter.java
index 705957c..73e8d24 100644
--- a/src/main/java/com/google/devtools/common/options/EnumConverter.java
+++ b/src/main/java/com/google/devtools/common/options/EnumConverter.java
@@ -20,15 +20,14 @@
/**
* A converter superclass for converters that parse enums.
*
- * <p>Just subclass this class, creating a zero argument constructor that
- * calls {@link #EnumConverter(Class, String)}.
+ * <p>Just subclass this class, creating a zero argument constructor that calls {@link
+ * #EnumConverter(Class, String)}.
*
- * <p>This class compares the input string to the string returned by the toString()
- * method of each enum member in a case-insensitive way. Usually, this is the
- * name of the symbol, but beware if you override toString()!
+ * <p>This class compares the input string to the string returned by the toString() method of each
+ * enum member in a case-insensitive way. Usually, this is the name of the symbol, but beware if you
+ * override toString()!
*/
-public abstract class EnumConverter<T extends Enum<T>>
- implements Converter<T> {
+public abstract class EnumConverter<T extends Enum<T>> extends Converter.Contextless<T> {
private final Class<T> enumType;
private final String typeName;
@@ -48,9 +47,7 @@
this.typeName = typeName;
}
- /**
- * Implements {@link #convert(String)}.
- */
+ /** Implements {@link Converter#convert(String, Object)}. */
@Override
public T convert(String input) throws OptionsParsingException {
for (T value : enumType.getEnumConstants()) {
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 d17453e..d46daa8 100644
--- a/src/main/java/com/google/devtools/common/options/InvocationPolicyEnforcer.java
+++ b/src/main/java/com/google/devtools/common/options/InvocationPolicyEnforcer.java
@@ -55,6 +55,7 @@
private static final String INVOCATION_POLICY_SOURCE = "Invocation policy";
private final InvocationPolicy invocationPolicy;
private final Level loglevel;
+ @Nullable private final Object conversionContext;
/**
* Creates an InvocationPolicyEnforcer that enforces the given policy.
@@ -63,9 +64,11 @@
* @param loglevel the level at which to log informational statements. Warnings and errors will
* still be logged at the appropriate level.
*/
- public InvocationPolicyEnforcer(InvocationPolicy invocationPolicy, Level loglevel) {
+ public InvocationPolicyEnforcer(
+ InvocationPolicy invocationPolicy, Level loglevel, @Nullable Object conversionContext) {
this.invocationPolicy = Preconditions.checkNotNull(invocationPolicy);
this.loglevel = Preconditions.checkNotNull(loglevel);
+ this.conversionContext = conversionContext;
}
private static final class FlagPolicyWithContext {
@@ -123,18 +126,22 @@
switch (flagPolicy.policy.getOperationCase()) {
case SET_VALUE:
- applySetValueOperation(parser, flagPolicy, valueDescription, loglevel);
+ applySetValueOperation(parser, flagPolicy, valueDescription, loglevel, conversionContext);
break;
case USE_DEFAULT:
applyUseDefaultOperation(
- parser, "UseDefault", flagPolicy.description.getOptionDefinition(), loglevel);
+ parser,
+ "UseDefault",
+ flagPolicy.description.getOptionDefinition(),
+ loglevel,
+ conversionContext);
break;
case ALLOW_VALUES:
AllowValues allowValues = flagPolicy.policy.getAllowValues();
FilterValueOperation.AllowValueOperation allowValueOperation =
- new FilterValueOperation.AllowValueOperation(loglevel);
+ new FilterValueOperation.AllowValueOperation(loglevel, conversionContext);
allowValueOperation.apply(
parser,
flagPolicy.origin,
@@ -148,7 +155,7 @@
case DISALLOW_VALUES:
DisallowValues disallowValues = flagPolicy.policy.getDisallowValues();
FilterValueOperation.DisallowValueOperation disallowValueOperation =
- new FilterValueOperation.DisallowValueOperation(loglevel);
+ new FilterValueOperation.DisallowValueOperation(loglevel, conversionContext);
disallowValueOperation.apply(
parser,
flagPolicy.origin,
@@ -514,7 +521,8 @@
OptionsParser parser,
FlagPolicyWithContext flagPolicy,
OptionValueDescription valueDescription,
- Level loglevel)
+ Level loglevel,
+ Object conversionContext)
throws OptionsParsingException {
SetValue setValue = flagPolicy.policy.getSetValue();
OptionDefinition optionDefinition = flagPolicy.description.getOptionDefinition();
@@ -570,7 +578,7 @@
logger.at(loglevel).log(
"Setting value for %s from invocation policy to '%s', overriding the default value "
+ "'%s'",
- optionDefinition, flagValue, optionDefinition.getDefaultValue());
+ optionDefinition, flagValue, optionDefinition.getDefaultValue(conversionContext));
} else {
logger.at(loglevel).log(
"Setting value for %s from invocation policy to '%s', overriding value '%s' from '%s'",
@@ -580,20 +588,24 @@
valueDescription.getSourceString());
}
- parser.setOptionValueAtSpecificPriorityWithoutExpansion(
- flagPolicy.origin, optionDefinition, flagValue);
+ parser.setOptionValueAtSpecificPriorityWithoutExpansion(
+ flagPolicy.origin, optionDefinition, flagValue);
}
}
private static void applyUseDefaultOperation(
- OptionsParser parser, String policyType, OptionDefinition option, Level loglevel)
+ OptionsParser parser,
+ String policyType,
+ OptionDefinition option,
+ Level loglevel,
+ Object conversionContext)
throws OptionsParsingException {
OptionValueDescription clearedValueDescription = parser.clearValue(option);
if (clearedValueDescription != null) {
// Log the removed value.
String clearedFlagName = clearedValueDescription.getOptionDefinition().getOptionName();
Object clearedFlagDefaultValue =
- clearedValueDescription.getOptionDefinition().getDefaultValue();
+ clearedValueDescription.getOptionDefinition().getDefaultValue(conversionContext);
logger.at(loglevel).log(
"Using default value '%s' for flag '%s' as specified by %s invocation policy, "
+ "overriding original value '%s' from '%s'",
@@ -609,8 +621,8 @@
private abstract static class FilterValueOperation {
private static final class AllowValueOperation extends FilterValueOperation {
- AllowValueOperation(Level loglevel) {
- super("Allow", loglevel);
+ AllowValueOperation(Level loglevel, Object conversionContext) {
+ super("Allow", loglevel, conversionContext);
}
@Override
@@ -620,8 +632,8 @@
}
private static final class DisallowValueOperation extends FilterValueOperation {
- DisallowValueOperation(Level loglevel) {
- super("Disallow", loglevel);
+ DisallowValueOperation(Level loglevel, Object conversionContext) {
+ super("Disallow", loglevel, conversionContext);
}
@Override
@@ -635,10 +647,12 @@
private final String policyType;
private final Level loglevel;
+ private final Object conversionContext;
- FilterValueOperation(String policyType, Level loglevel) {
+ FilterValueOperation(String policyType, Level loglevel, Object conversionContext) {
this.policyType = policyType;
this.loglevel = loglevel;
+ this.conversionContext = conversionContext;
}
/**
@@ -667,7 +681,7 @@
// can be arbitrarily complex.
Set<Object> convertedPolicyValues = new HashSet<>();
for (String value : policyValues) {
- Object convertedValue = optionDefinition.getConverter().convert(value);
+ Object convertedValue = optionDefinition.getConverter().convert(value, conversionContext);
// Some converters return lists, and if the flag is a repeatable flag, the items in the
// list from the converter should be added, and not the list itself. Otherwise the items
// from invocation policy will be compared to lists, which will never work.
@@ -675,7 +689,7 @@
if (optionDefinition.allowsMultiple() && convertedValue instanceof List<?>) {
convertedPolicyValues.addAll((List<?>) convertedValue);
} else {
- convertedPolicyValues.add(optionDefinition.getConverter().convert(value));
+ convertedPolicyValues.add(convertedValue);
}
}
@@ -691,13 +705,16 @@
&& !optionDescription.getOptionDefinition().isSpecialNullDefault()) {
boolean defaultValueAllowed =
isFlagValueAllowed(
- convertedPolicyValues, optionDescription.getOptionDefinition().getDefaultValue());
+ convertedPolicyValues,
+ optionDescription.getOptionDefinition().getDefaultValue(conversionContext));
if (!defaultValueAllowed && useDefault) {
throw new OptionsParsingException(
String.format(
"%sValues policy disallows the default value '%s' for %s but also specifies to "
+ "use the default value",
- policyType, optionDefinition.getDefaultValue(), optionDefinition));
+ policyType,
+ optionDefinition.getDefaultValue(conversionContext),
+ optionDefinition));
}
}
@@ -737,13 +754,14 @@
// the value is being filtered, but the value that is `no value` passes any filter.
// Otherwise, there is no way to "usedefault" on one of these options that has no value by
// default.
- } else if (!isFlagValueAllowed(convertedPolicyValues, optionDefinition.getDefaultValue())) {
+ } else if (!isFlagValueAllowed(
+ convertedPolicyValues, optionDefinition.getDefaultValue(conversionContext))) {
if (newValue != null) {
// Use the default value from the policy, since the original default is not allowed
logger.at(loglevel).log(
"Overriding default value '%s' for %s with value '%s' specified by invocation "
+ "policy. %sed values are: %s",
- optionDefinition.getDefaultValue(),
+ optionDefinition.getDefaultValue(conversionContext),
optionDefinition,
newValue,
policyType,
@@ -757,7 +775,7 @@
String.format(
"Default flag value '%s' for %s is not allowed by invocation policy, but "
+ "the policy does not provide a new value. %sed values are: %s",
- optionDescription.getOptionDefinition().getDefaultValue(),
+ optionDescription.getOptionDefinition().getDefaultValue(conversionContext),
optionDefinition,
policyType,
policyValues));
@@ -783,7 +801,8 @@
for (Object value : optionValues) {
if (!isFlagValueAllowed(convertedPolicyValues, value)) {
if (useDefault) {
- applyUseDefaultOperation(parser, policyType + "Values", option, loglevel);
+ applyUseDefaultOperation(
+ parser, policyType + "Values", option, loglevel, conversionContext);
} else {
throw new OptionsParsingException(
String.format(
@@ -805,7 +824,8 @@
parser.clearValue(option);
parser.setOptionValueAtSpecificPriorityWithoutExpansion(origin, option, newValue);
} else if (useDefault) {
- applyUseDefaultOperation(parser, policyType + "Values", option, loglevel);
+ applyUseDefaultOperation(
+ parser, policyType + "Values", option, loglevel, conversionContext);
} else {
throw new OptionsParsingException(
String.format(
diff --git a/src/main/java/com/google/devtools/common/options/OptionDefinition.java b/src/main/java/com/google/devtools/common/options/OptionDefinition.java
index 3c941d0..422997b7 100644
--- a/src/main/java/com/google/devtools/common/options/OptionDefinition.java
+++ b/src/main/java/com/google/devtools/common/options/OptionDefinition.java
@@ -224,6 +224,7 @@
if (converter != null) {
return converter;
}
+ @SuppressWarnings("rawtypes")
Class<? extends Converter> converterClass = getProvidedConverter();
if (converterClass == Converter.class) {
// No converter provided, use the default one.
@@ -258,7 +259,7 @@
/** Returns the evaluated default value for this option & memoizes the result. */
@Nullable
- public Object getDefaultValue() {
+ public Object getDefaultValue(@Nullable Object conversionContext) {
if (defaultValue != null) {
return defaultValue;
}
@@ -270,7 +271,7 @@
Converter<?> converter = getConverter();
String defaultValueAsString = getUnparsedDefaultValue();
try {
- Object convertedDefaultValue = converter.convert(defaultValueAsString);
+ Object convertedDefaultValue = converter.convert(defaultValueAsString, conversionContext);
defaultValue =
allowsMultiple()
? maybeWrapMultipleDefaultValue(convertedDefaultValue)
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 fec37fa..06db52e 100644
--- a/src/main/java/com/google/devtools/common/options/OptionValueDescription.java
+++ b/src/main/java/com/google/devtools/common/options/OptionValueDescription.java
@@ -37,9 +37,12 @@
public abstract class OptionValueDescription {
protected final OptionDefinition optionDefinition;
+ @Nullable protected final Object conversionContext;
- public OptionValueDescription(OptionDefinition optionDefinition) {
+ public OptionValueDescription(
+ OptionDefinition optionDefinition, @Nullable Object conversionContext) {
this.optionDefinition = optionDefinition;
+ this.conversionContext = conversionContext;
}
public OptionDefinition getOptionDefinition() {
@@ -94,15 +97,15 @@
* OptionProcessor at compile time.
*/
public static OptionValueDescription createOptionValueDescription(
- OptionDefinition option, OptionsData optionsData) {
+ OptionDefinition option, OptionsData optionsData, @Nullable Object conversionContext) {
if (option.isExpansionOption()) {
- return new ExpansionOptionValueDescription(option, optionsData);
+ return new ExpansionOptionValueDescription(option, optionsData, conversionContext);
} else if (option.allowsMultiple()) {
- return new RepeatableOptionValueDescription(option);
+ return new RepeatableOptionValueDescription(option, conversionContext);
} else if (option.hasImplicitRequirements()) {
- return new OptionWithImplicitRequirementsValueDescription(option);
+ return new OptionWithImplicitRequirementsValueDescription(option, conversionContext);
} else {
- return new SingleOptionValueDescription(option);
+ return new SingleOptionValueDescription(option, conversionContext);
}
}
@@ -110,19 +113,21 @@
* For options that have not been set, this will return a correct OptionValueDescription for the
* default value.
*/
- public static OptionValueDescription getDefaultOptionValue(OptionDefinition option) {
- return new DefaultOptionValueDescription(option);
+ public static OptionValueDescription getDefaultOptionValue(
+ OptionDefinition option, @Nullable Object conversionContext) {
+ return new DefaultOptionValueDescription(option, conversionContext);
}
private static class DefaultOptionValueDescription extends OptionValueDescription {
- private DefaultOptionValueDescription(OptionDefinition optionDefinition) {
- super(optionDefinition);
+ private DefaultOptionValueDescription(
+ OptionDefinition optionDefinition, @Nullable Object conversionContext) {
+ super(optionDefinition, conversionContext);
}
@Override
public Object getValue() {
- return optionDefinition.getDefaultValue();
+ return optionDefinition.getDefaultValue(conversionContext);
}
@Override
@@ -151,8 +156,9 @@
private ParsedOptionDescription effectiveOptionInstance;
private Object effectiveValue;
- private SingleOptionValueDescription(OptionDefinition optionDefinition) {
- super(optionDefinition);
+ private SingleOptionValueDescription(
+ OptionDefinition optionDefinition, @Nullable Object conversionContext) {
+ super(optionDefinition, conversionContext);
if (optionDefinition.allowsMultiple()) {
throw new ConstructionException("Can't have a single value for an allowMultiple option.");
}
@@ -268,8 +274,9 @@
ListMultimap<OptionPriority, ParsedOptionDescription> parsedOptions;
ListMultimap<OptionPriority, Object> optionValues;
- private RepeatableOptionValueDescription(OptionDefinition optionDefinition) {
- super(optionDefinition);
+ private RepeatableOptionValueDescription(
+ OptionDefinition optionDefinition, @Nullable Object conversionContext) {
+ super(optionDefinition, conversionContext);
if (!optionDefinition.allowsMultiple()) {
throw new ConstructionException(
"Can't have a repeated value for a non-allowMultiple option.");
@@ -338,8 +345,10 @@
private final List<String> expansion;
private ExpansionOptionValueDescription(
- OptionDefinition optionDefinition, OptionsData optionsData) {
- super(optionDefinition);
+ OptionDefinition optionDefinition,
+ OptionsData optionsData,
+ @Nullable Object conversionContext) {
+ super(optionDefinition, conversionContext);
this.expansion = optionsData.getEvaluatedExpansion(optionDefinition);
if (!optionDefinition.isExpansionOption()) {
throw new ConstructionException(
@@ -388,8 +397,9 @@
private static class OptionWithImplicitRequirementsValueDescription
extends SingleOptionValueDescription {
- private OptionWithImplicitRequirementsValueDescription(OptionDefinition optionDefinition) {
- super(optionDefinition);
+ private OptionWithImplicitRequirementsValueDescription(
+ OptionDefinition optionDefinition, @Nullable Object conversionContext) {
+ super(optionDefinition, conversionContext);
if (!optionDefinition.hasImplicitRequirements()) {
throw new ConstructionException(
"Options without implicit requirements can't be tracked using "
@@ -406,7 +416,9 @@
ExpansionBundle superExpansion = super.addOptionInstance(parsedOption, warnings);
Preconditions.checkArgument(
superExpansion == null, "SingleOptionValueDescription should not expand to anything.");
- if (parsedOption.getConvertedValue().equals(optionDefinition.getDefaultValue())) {
+ if (parsedOption
+ .getConvertedValue()
+ .equals(optionDefinition.getDefaultValue(conversionContext))) {
warnings.add(
String.format(
"%s sets %s to its default value. Since this option has implicit requirements that "
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 0b3df3f..a055cb0 100644
--- a/src/main/java/com/google/devtools/common/options/OptionsParser.java
+++ b/src/main/java/com/google/devtools/common/options/OptionsParser.java
@@ -144,9 +144,13 @@
/** A helper class to create new instances of {@link OptionsParser}. */
public static final class Builder {
- private final OptionsParserImpl.Builder implBuilder = OptionsParserImpl.builder();
+ private final OptionsParserImpl.Builder implBuilder;
private boolean allowResidue = true;
+ private Builder(OptionsParserImpl.Builder implBuilder) {
+ this.implBuilder = implBuilder;
+ }
+
/** Directly sets the {@link OptionsData} used by this parser. */
@CanIgnoreReturnValue
public Builder optionsData(OptionsData optionsData) {
@@ -237,6 +241,11 @@
return this;
}
+ public Builder withConversionContext(Object conversionContext) {
+ this.implBuilder.withConversionContext(conversionContext);
+ return this;
+ }
+
/** Returns a new {@link OptionsParser}. */
public OptionsParser build() {
return new OptionsParser(implBuilder.build(), allowResidue);
@@ -245,7 +254,11 @@
/** Returns a new {@link Builder} to create {@link OptionsParser} instances. */
public static Builder builder() {
- return new Builder();
+ return new Builder(OptionsParserImpl.builder());
+ }
+
+ public Builder toBuilder() {
+ return new Builder(impl.toBuilder()).allowResidue(allowResidue);
}
private final OptionsParserImpl impl;
@@ -260,6 +273,10 @@
this.allowResidue = allowResidue;
}
+ public Object getConversionContext() {
+ return impl.getConversionContext();
+ }
+
@Override
public ImmutableSortedMap<String, Object> getStarlarkOptions() {
return starlarkOptions;
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 8380ec2..41b6a3a 100644
--- a/src/main/java/com/google/devtools/common/options/OptionsParserImpl.java
+++ b/src/main/java/com/google/devtools/common/options/OptionsParserImpl.java
@@ -55,6 +55,7 @@
private final ArrayList<String> skippedPrefixes = new ArrayList<>();
private boolean ignoreInternalOptions = true;
@Nullable private String aliasFlag = null;
+ @Nullable private Object conversionContext = null;
private final Map<String, String> aliases = new HashMap<>();
/** Set the {@link OptionsData} to be used in this instance. */
@@ -97,6 +98,11 @@
return this;
}
+ public Builder withConversionContext(@Nullable Object conversionContext) {
+ this.conversionContext = conversionContext;
+ return this;
+ }
+
/**
* Adds a map of flag aliases where the keys are the flags' alias names and the values are their
* actual names.
@@ -115,6 +121,7 @@
this.skippedPrefixes,
this.ignoreInternalOptions,
this.aliasFlag,
+ this.conversionContext,
this.aliases);
}
}
@@ -168,6 +175,7 @@
private final List<String> skippedPrefixes;
private final boolean ignoreInternalOptions;
@Nullable private final String aliasFlag;
+ @Nullable private final Object conversionContext;
OptionsParserImpl(
OptionsData optionsData,
@@ -175,12 +183,14 @@
List<String> skippedPrefixes,
boolean ignoreInternalOptions,
@Nullable String aliasFlag,
+ @Nullable Object conversionContext,
Map<String, String> aliases) {
this.optionsData = optionsData;
this.argsPreProcessor = argsPreProcessor;
this.skippedPrefixes = skippedPrefixes;
this.ignoreInternalOptions = ignoreInternalOptions;
this.aliasFlag = aliasFlag;
+ this.conversionContext = conversionContext;
this.flagAliasMappings = aliases;
}
@@ -189,9 +199,21 @@
return optionsData;
}
+ @Nullable
+ public Object getConversionContext() {
+ return conversionContext;
+ }
+
/** Returns a {@link Builder} that is configured the same as this parser. */
Builder toBuilder() {
- Builder builder = builder().optionsData(optionsData).argsPreProcessor(argsPreProcessor);
+ Builder builder =
+ builder()
+ .optionsData(optionsData)
+ .argsPreProcessor(argsPreProcessor)
+ .withAliasFlag(aliasFlag)
+ .withAliases(flagAliasMappings)
+ .withConversionContext(conversionContext)
+ .ignoreInternalOptions(ignoreInternalOptions);
for (String skippedPrefix : skippedPrefixes) {
builder.skippedPrefix(skippedPrefix);
}
@@ -241,7 +263,8 @@
OptionDefinition optionDefinition = mapEntry.getValue();
OptionValueDescription optionValue = optionValues.get(optionDefinition);
if (optionValue == null) {
- result.add(OptionValueDescription.getDefaultOptionValue(optionDefinition));
+ result.add(
+ OptionValueDescription.getDefaultOptionValue(optionDefinition, conversionContext));
} else {
result.add(optionValue);
}
@@ -321,7 +344,8 @@
ImmutableList<String> options;
ParsedOptionDescription expansionFlagParsedDummy =
- ParsedOptionDescription.newDummyInstance(expansionFlagDef, originOfExpansionFlag);
+ ParsedOptionDescription.newDummyInstance(
+ expansionFlagDef, originOfExpansionFlag, conversionContext);
if (expansionFlagDef.hasImplicitRequirements()) {
options = ImmutableList.copyOf(expansionFlagDef.getImplicitRequirements());
source =
@@ -482,7 +506,7 @@
/**
* Implementation of {@link
- * OptionsParser#setOptionValueAtSpecificPrioritySkipExpansion(OptionInstanceOrigin,
+ * OptionsParser#setOptionValueAtSpecificPriorityWithoutExpansion(OptionInstanceOrigin,
* OptionDefinition, String)}
*/
void setOptionValueAtSpecificPriorityWithoutExpansion(
@@ -513,7 +537,8 @@
option,
String.format("--%s=%s", option.getOptionName(), unconvertedValue),
unconvertedValue,
- origin));
+ origin,
+ conversionContext));
}
/** Takes care of tracking the parsed option's value in relation to other options. */
@@ -556,7 +581,9 @@
OptionValueDescription entry =
optionValues.computeIfAbsent(
optionDefinition,
- def -> OptionValueDescription.createOptionValueDescription(def, optionsData));
+ def ->
+ OptionValueDescription.createOptionValueDescription(
+ def, optionsData, conversionContext));
ExpansionBundle expansionBundle = entry.addOptionInstance(parsedOption, warnings);
// There are 3 types of flags that expand to other flag values. Expansion flags are the
@@ -667,7 +694,8 @@
commandLineForm.toString(),
unconvertedValue,
new OptionInstanceOrigin(
- priority, sourceFunction.apply(optionDefinition), implicitDependent, expandedFrom));
+ priority, sourceFunction.apply(optionDefinition), implicitDependent, expandedFrom),
+ conversionContext);
}
private boolean shouldIgnoreOption(OptionDefinition optionDefinition) {
@@ -696,7 +724,7 @@
Object value;
OptionValueDescription optionValue = optionValues.get(optionDefinition);
if (optionValue == null) {
- value = optionDefinition.getDefaultValue();
+ value = optionDefinition.getDefaultValue(conversionContext);
} else {
value = optionValue.getValue();
}
diff --git a/src/main/java/com/google/devtools/common/options/ParsedOptionDescription.java b/src/main/java/com/google/devtools/common/options/ParsedOptionDescription.java
index dbf85b3..fbb094c 100644
--- a/src/main/java/com/google/devtools/common/options/ParsedOptionDescription.java
+++ b/src/main/java/com/google/devtools/common/options/ParsedOptionDescription.java
@@ -31,27 +31,35 @@
@Nullable private final String commandLineForm;
@Nullable private final String unconvertedValue;
private final OptionInstanceOrigin origin;
+ @Nullable private final Object conversionContext;
private ParsedOptionDescription(
OptionDefinition optionDefinition,
@Nullable String commandLineForm,
@Nullable String unconvertedValue,
- OptionInstanceOrigin origin) {
+ OptionInstanceOrigin origin,
+ @Nullable Object conversionContext) {
this.optionDefinition = Preconditions.checkNotNull(optionDefinition);
this.commandLineForm = commandLineForm;
this.unconvertedValue = unconvertedValue;
this.origin = Preconditions.checkNotNull(origin);
+ this.conversionContext = conversionContext;
}
static ParsedOptionDescription newParsedOptionDescription(
OptionDefinition optionDefinition,
String commandLineForm,
@Nullable String unconvertedValue,
- OptionInstanceOrigin origin) {
+ OptionInstanceOrigin origin,
+ @Nullable Object conversionContext) {
// An actual ParsedOptionDescription should always have a form in which it was parsed, but some
// options, such as expansion options, legitimately have no value.
return new ParsedOptionDescription(
- optionDefinition, Preconditions.checkNotNull(commandLineForm), unconvertedValue, origin);
+ optionDefinition,
+ Preconditions.checkNotNull(commandLineForm),
+ unconvertedValue,
+ origin,
+ conversionContext);
}
/**
@@ -59,8 +67,10 @@
* not have an original value or form that the option took.
*/
static ParsedOptionDescription newDummyInstance(
- OptionDefinition optionDefinition, OptionInstanceOrigin origin) {
- return new ParsedOptionDescription(optionDefinition, null, null, origin);
+ OptionDefinition optionDefinition,
+ OptionInstanceOrigin origin,
+ @Nullable Object conversionContext) {
+ return new ParsedOptionDescription(optionDefinition, null, null, origin, conversionContext);
}
public OptionDefinition getOptionDefinition() {
@@ -168,7 +178,7 @@
public Object getConvertedValue() throws OptionsParsingException {
Converter<?> converter = optionDefinition.getConverter();
try {
- return converter.convert(unconvertedValue);
+ return converter.convert(unconvertedValue, conversionContext);
} catch (OptionsParsingException e) {
// The converter doesn't know the option name, so we supply it here by re-throwing:
throw new OptionsParsingException(
diff --git a/src/main/java/com/google/devtools/common/options/processor/OptionProcessor.java b/src/main/java/com/google/devtools/common/options/processor/OptionProcessor.java
index 90918a2..fc14801 100644
--- a/src/main/java/com/google/devtools/common/options/processor/OptionProcessor.java
+++ b/src/main/java/com/google/devtools/common/options/processor/OptionProcessor.java
@@ -243,7 +243,7 @@
// For the default converters, it so happens we have access to the convert methods
// at compile time, since we already have the OptionsParser source. Take advantage of
// this to test that the provided defaultValue is valid.
- converterInstance.convert(defaultValue);
+ converterInstance.convert(defaultValue, /*conversionContext=*/ null);
} catch (OptionsParsingException e) {
throw new OptionProcessorException(
optionField,
@@ -286,17 +286,21 @@
.filter(methodElement -> methodElement.getSimpleName().contentEquals("convert"))
.filter(
methodElement ->
- methodElement.getParameters().size() == 1
+ methodElement.getParameters().size() == 2
&& typeUtils.isSameType(
methodElement.getParameters().get(0).asType(),
- elementUtils.getTypeElement(String.class.getCanonicalName()).asType()))
+ elementUtils.getTypeElement(String.class.getCanonicalName()).asType())
+ && typeUtils.isSameType(
+ methodElement.getParameters().get(1).asType(),
+ elementUtils.getTypeElement(Object.class.getCanonicalName()).asType()))
.collect(Collectors.toList());
// Check that there is just the one method
if (methodList.size() != 1) {
throw new OptionProcessorException(
optionField,
- "Converter %s has methods 'convert(String)': %s",
+ "Converter %s has %d methods 'convert(String, Object)', expected 1: %s",
converterElement,
+ methodList.size(),
methodList.stream().map(Object::toString).collect(Collectors.joining(", ")));
}
diff --git a/src/main/java/com/google/devtools/common/options/testing/ConverterTester.java b/src/main/java/com/google/devtools/common/options/testing/ConverterTester.java
index 3f2c4a6..88b0730 100644
--- a/src/main/java/com/google/devtools/common/options/testing/ConverterTester.java
+++ b/src/main/java/com/google/devtools/common/options/testing/ConverterTester.java
@@ -32,14 +32,16 @@
private final Converter<?> converter;
private final Class<? extends Converter<?>> converterClass;
+ private final Object conversionContext;
private final EqualsTester tester = new EqualsTester();
private final LinkedHashSet<String> testedInputs = new LinkedHashSet<>();
private final ArrayList<ImmutableList<String>> inputLists = new ArrayList<>();
/** Creates a new ConverterTester which will test the given Converter class. */
- public ConverterTester(Class<? extends Converter<?>> converterClass) {
+ public ConverterTester(Class<? extends Converter<?>> converterClass, Object conversionContext) {
this.converterClass = converterClass;
this.converter = createConverter();
+ this.conversionContext = conversionContext;
}
private Converter<?> createConverter() {
@@ -96,7 +98,7 @@
for (String input : inputList) {
testedInputs.add(input);
try {
- wrapped.add(new WrappedItem(input, converter.convert(input)));
+ wrapped.add(new WrappedItem(input, converter.convert(input, conversionContext)));
} catch (OptionsParsingException ex) {
throw new AssertionError("Failed to parse input: \"" + input + "\"", ex);
}
@@ -129,9 +131,9 @@
Object convertedAgain;
Object convertedDifferentConverterInstance;
try {
- converted = converter.convert(input);
- convertedAgain = converter.convert(input);
- convertedDifferentConverterInstance = converter2.convert(input);
+ converted = converter.convert(input, conversionContext);
+ convertedAgain = converter.convert(input, conversionContext);
+ convertedDifferentConverterInstance = converter2.convert(input, conversionContext);
} catch (OptionsParsingException ex) {
throw new AssertionError("Failed to parse input: \"" + input + "\"", ex);
}
diff --git a/src/test/java/com/google/devtools/build/android/ConvertersTest.java b/src/test/java/com/google/devtools/build/android/ConvertersTest.java
index f7fc270..49e12e4 100644
--- a/src/test/java/com/google/devtools/build/android/ConvertersTest.java
+++ b/src/test/java/com/google/devtools/build/android/ConvertersTest.java
@@ -95,7 +95,7 @@
StringDictionaryConverter converter = new StringDictionaryConverter();
expected.expect(OptionsParsingException.class);
expected.expectMessage("Dictionary entry [] does not contain both a key and a value.");
- converter.convert("foo:bar,,baz:bar");
+ converter.convert("foo:bar,,baz:bar", /*conversionContext=*/ null);
}
@Test
@@ -105,7 +105,7 @@
expected.expect(OptionsParsingException.class);
expected.expectMessage(String.format(
"Dictionary entry [%s] does not contain both a key and a value.", badEntry));
- converter.convert(badEntry);
+ converter.convert(badEntry, /*conversionContext=*/ null);
}
@Test
@@ -115,7 +115,7 @@
expected.expect(OptionsParsingException.class);
expected.expectMessage(String.format(
"Dictionary entry [%s] contains too many fields.", badEntry));
- converter.convert(badEntry);
+ converter.convert(badEntry, /*conversionContext=*/ null);
}
@Test
@@ -126,13 +126,14 @@
expected.expect(OptionsParsingException.class);
expected.expectMessage(String.format(
"Dictionary already contains the key [%s].", key));
- converter.convert(arg);
+ converter.convert(arg, /*conversionContext=*/ null);
}
@Test
public void testStringDictionaryConverter() throws Exception {
StringDictionaryConverter converter = new StringDictionaryConverter();
- Map<String, String> result = converter.convert("foo:bar,baz:messy\\:stri\\,ng");
+ Map<String, String> result =
+ converter.convert("foo:bar,baz:messy\\:stri\\,ng", /*conversionContext=*/ null);
assertThat(result).containsExactly("foo", "bar", "baz", "messy:stri,ng");
}
@@ -140,10 +141,11 @@
public void testExistingPathStringDictionaryConverter() throws Exception {
Path existingFile = tmp.newFile("existing").toPath();
ExistingPathStringDictionaryConverter converter = new ExistingPathStringDictionaryConverter();
+ // On Windows, the path starts like C:\foo\bar\..., we need to escape the colon.
Map<Path, String> result =
- converter
- // On Windows, the path starts like C:\foo\bar\..., we need to escape the colon.
- .convert(String.format("%s:string", existingFile.toString().replace(":", "\\:")));
+ converter.convert(
+ String.format("%s:string", existingFile.toString().replace(":", "\\:")),
+ /*conversionContext=*/ null);
assertThat(result).containsExactly(existingFile, "string");
}
}
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/config/BuildOptionDetailsTest.java b/src/test/java/com/google/devtools/build/lib/analysis/config/BuildOptionDetailsTest.java
index b1d21d2..fe938e2 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/config/BuildOptionDetailsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/config/BuildOptionDetailsTest.java
@@ -50,7 +50,7 @@
}
/** Example converter for working with options with converters. */
- public static final class Optionalizer implements Converter<Optional<String>> {
+ public static final class Optionalizer extends Converter.Contextless<Optional<String>> {
@Override
public Optional<String> convert(String input) {
if ("".equals(input)) {
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/config/RunUnderConverterTest.java b/src/test/java/com/google/devtools/build/lib/analysis/config/RunUnderConverterTest.java
index 7920082..a9172e3 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/config/RunUnderConverterTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/config/RunUnderConverterTest.java
@@ -43,7 +43,7 @@
private void assertEqualsRunUnder(String input, String label, String command,
List<String> options) throws Exception {
- RunUnder runUnder = new RunUnderConverter().convert(input);
+ RunUnder runUnder = new RunUnderConverter().convert(input, /*conversionContext=*/ null);
assertThat(runUnder.getLabel() == null ? null : runUnder.getLabel().toString())
.isEqualTo(label);
assertThat(runUnder.getCommand()).isEqualTo(command);
@@ -52,7 +52,9 @@
private void assertRunUnderFails(String input, String expectedError) {
OptionsParsingException e =
- assertThrows(OptionsParsingException.class, () -> new RunUnderConverter().convert(input));
+ assertThrows(
+ OptionsParsingException.class,
+ () -> new RunUnderConverter().convert(input, /*conversionContext=*/ null));
assertThat(e).hasMessageThat().isEqualTo(expectedError);
}
}
diff --git a/src/test/java/com/google/devtools/build/lib/buildtool/util/BlazeRuntimeWrapper.java b/src/test/java/com/google/devtools/build/lib/buildtool/util/BlazeRuntimeWrapper.java
index aa5a49e..ca33268 100644
--- a/src/test/java/com/google/devtools/build/lib/buildtool/util/BlazeRuntimeWrapper.java
+++ b/src/test/java/com/google/devtools/build/lib/buildtool/util/BlazeRuntimeWrapper.java
@@ -262,7 +262,8 @@
// Enforce the test invocation policy once the options have been added
InvocationPolicyEnforcer optionsPolicyEnforcer =
- new InvocationPolicyEnforcer(runtime.getModuleInvocationPolicy(), Level.FINE);
+ new InvocationPolicyEnforcer(
+ runtime.getModuleInvocationPolicy(), Level.FINE, /*conversionContext=*/ null);
try {
optionsPolicyEnforcer.enforce(optionsParser, commandAnnotation.name());
} catch (OptionsParsingException e) {
diff --git a/src/test/java/com/google/devtools/common/options/AssignmentConverterTest.java b/src/test/java/com/google/devtools/common/options/AssignmentConverterTest.java
index 3d8ac7b..e71a386 100644
--- a/src/test/java/com/google/devtools/common/options/AssignmentConverterTest.java
+++ b/src/test/java/com/google/devtools/common/options/AssignmentConverterTest.java
@@ -30,7 +30,7 @@
*/
public abstract class AssignmentConverterTest {
- protected Converter<Map.Entry<String, String>> converter = null;
+ protected Converter.Contextless<Map.Entry<String, String>> converter = null;
protected abstract void setConverter();
diff --git a/src/test/java/com/google/devtools/common/options/BUILD b/src/test/java/com/google/devtools/common/options/BUILD
index ab1c422..7d2f51b 100644
--- a/src/test/java/com/google/devtools/common/options/BUILD
+++ b/src/test/java/com/google/devtools/common/options/BUILD
@@ -52,6 +52,7 @@
"//third_party:guava",
"//third_party:guava-testlib",
"//third_party:jimfs",
+ "//third_party:jsr305",
"//third_party:junit4",
"//third_party:mockito",
"//third_party:truth",
diff --git a/src/test/java/com/google/devtools/common/options/CommaSeparatedOptionListConverterTest.java b/src/test/java/com/google/devtools/common/options/CommaSeparatedOptionListConverterTest.java
index 78fe9c0..c17f3da 100644
--- a/src/test/java/com/google/devtools/common/options/CommaSeparatedOptionListConverterTest.java
+++ b/src/test/java/com/google/devtools/common/options/CommaSeparatedOptionListConverterTest.java
@@ -23,7 +23,7 @@
/** A test for {@link Converters.CommaSeparatedOptionListConverter}. */
@RunWith(JUnit4.class)
public class CommaSeparatedOptionListConverterTest {
- private final Converter<ImmutableList<String>> converter =
+ private final Converter.Contextless<ImmutableList<String>> converter =
new Converters.CommaSeparatedOptionListConverter();
@Test
diff --git a/src/test/java/com/google/devtools/common/options/InvocationPolicyEnforcerTestBase.java b/src/test/java/com/google/devtools/common/options/InvocationPolicyEnforcerTestBase.java
index 2cecc91..e7f3c2a 100644
--- a/src/test/java/com/google/devtools/common/options/InvocationPolicyEnforcerTestBase.java
+++ b/src/test/java/com/google/devtools/common/options/InvocationPolicyEnforcerTestBase.java
@@ -29,7 +29,7 @@
public class InvocationPolicyEnforcerTestBase {
/** Test converter that splits a string by commas to produce a list. */
- public static class ToListConverter implements Converter<List<String>> {
+ public static class ToListConverter extends Converter.Contextless<List<String>> {
public ToListConverter() {}
@@ -64,7 +64,8 @@
return new InvocationPolicyEnforcer(
InvocationPolicyParser.parsePolicy(
startupOptionsParser.getOptions(BlazeServerStartupOptions.class).invocationPolicy),
- Level.INFO);
+ Level.INFO,
+ /*conversionContext=*/ null);
}
OptionsParser parser;
diff --git a/src/test/java/com/google/devtools/common/options/OptionDefaultValueConversionTest.java b/src/test/java/com/google/devtools/common/options/OptionDefaultValueConversionTest.java
index b7eabc2..41e397f 100644
--- a/src/test/java/com/google/devtools/common/options/OptionDefaultValueConversionTest.java
+++ b/src/test/java/com/google/devtools/common/options/OptionDefaultValueConversionTest.java
@@ -36,7 +36,7 @@
* {@link Option}-annotated field is considered to be in <i>Prod</i> code if its declaring class and
* all its enclosing classes do not have {@link RunWith} annotation.
*
- * @see OptionDefinition#getDefaultValue()
+ * @see OptionDefinition#getDefaultValue
*/
@RunWith(Parameterized.class)
public class OptionDefaultValueConversionTest {
@@ -53,7 +53,7 @@
thrown = ExpectedException.none();
// act
- optionDefinitionUnderTest.getDefaultValue();
+ optionDefinitionUnderTest.getDefaultValue(/*conversionContext=*/ null);
}
@Parameters
diff --git a/src/test/java/com/google/devtools/common/options/OptionDefinitionTest.java b/src/test/java/com/google/devtools/common/options/OptionDefinitionTest.java
index 221aac3..f1bfc64 100644
--- a/src/test/java/com/google/devtools/common/options/OptionDefinitionTest.java
+++ b/src/test/java/com/google/devtools/common/options/OptionDefinitionTest.java
@@ -57,7 +57,7 @@
assertThrows(
"Incorrect default should have caused getDefaultValue to fail.",
ConstructionException.class,
- () -> optionDef.getDefaultValue());
+ () -> optionDef.getDefaultValue(/*conversionContext=*/ null));
assertThat(e)
.hasMessageThat()
.contains(
@@ -123,14 +123,14 @@
Converter<?> converter = mockOptionDef.getConverter();
assertThat(converter).isInstanceOf(IntegerConverter.class);
- int value = (int) mockOptionDef.getDefaultValue();
+ int value = (int) mockOptionDef.getDefaultValue(/*conversionContext=*/ null);
assertThat(value).isEqualTo(42);
// Expect reference equality, since we didn't recompute the value
Converter<?> secondConverter = mockOptionDef.getConverter();
assertThat(secondConverter).isSameInstanceAs(converter);
- mockOptionDef.getDefaultValue();
+ mockOptionDef.getDefaultValue(/*conversionContext=*/ null);
// Verify that we didn't re-calculate the converter from the provided class object.
verify(mockOptionDef, times(1)).getProvidedConverter();
@@ -159,14 +159,14 @@
Converter<?> converter = mockOptionDef.getConverter();
assertThat(converter).isInstanceOf(StringConverter.class);
- String value = (String) mockOptionDef.getDefaultValue();
+ String value = (String) mockOptionDef.getDefaultValue(/*conversionContext=*/ null);
assertThat(value).isEqualTo("strings");
// Expect reference equality, since we didn't recompute the value
Converter<?> secondConverter = mockOptionDef.getConverter();
assertThat(secondConverter).isSameInstanceAs(converter);
- mockOptionDef.getDefaultValue();
+ mockOptionDef.getDefaultValue(/*conversionContext=*/ null);
// Verify that we didn't re-calculate the converter from the provided class object.
verify(mockOptionDef, times(1)).getProvidedConverter();
@@ -218,7 +218,7 @@
DefaultValueTestOptions.class.getField("nullNonMultipleOption"));
// act
- Object result = optionDef.getDefaultValue();
+ Object result = optionDef.getDefaultValue(/*conversionContext=*/ null);
// assert
assertThat(result).isNull();
@@ -233,7 +233,7 @@
DefaultValueTestOptions.class.getField("nullMultipleOption"));
// act
- List<String> result = (List<String>) optionDef.getDefaultValue();
+ List<String> result = (List<String>) optionDef.getDefaultValue(/*conversionContext=*/ null);
// assert
assertThat(result).isEmpty();
@@ -248,7 +248,7 @@
DefaultValueTestOptions.class.getField("emptyStringMultipleOption"));
// act
- List<String> result = (List<String>) optionDef.getDefaultValue();
+ List<String> result = (List<String>) optionDef.getDefaultValue(/*conversionContext=*/ null);
// assert
assertThat(result).containsExactly("");
@@ -263,7 +263,7 @@
DefaultValueTestOptions.class.getField("nonEmptyStringMultipleOption"));
// act
- List<String> result = (List<String>) optionDef.getDefaultValue();
+ List<String> result = (List<String>) optionDef.getDefaultValue(/*conversionContext=*/ null);
// assert
assertThat(result).containsExactly("text");
diff --git a/src/test/java/com/google/devtools/common/options/OptionsDataTest.java b/src/test/java/com/google/devtools/common/options/OptionsDataTest.java
index 82afa98..ed922c0 100644
--- a/src/test/java/com/google/devtools/common/options/OptionsDataTest.java
+++ b/src/test/java/com/google/devtools/common/options/OptionsDataTest.java
@@ -342,7 +342,7 @@
}
/** Dummy options class. */
- public static class StringConverter implements Converter<String> {
+ public static class StringConverter extends Converter.Contextless<String> {
@Override
public String convert(String input) {
return input;
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 bbf1319..474ff07 100644
--- a/src/test/java/com/google/devtools/common/options/OptionsParserTest.java
+++ b/src/test/java/com/google/devtools/common/options/OptionsParserTest.java
@@ -30,6 +30,7 @@
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Predicate;
+import javax.annotation.Nullable;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -175,7 +176,7 @@
public String privateString;
}
- public static class StringConverter implements Converter<String> {
+ public static class StringConverter extends Converter.Contextless<String> {
@Override
public String convert(String input) {
return input;
@@ -546,6 +547,46 @@
assertThat(options.simple).isNull();
}
+ public static class ConverterWithContextTestOptions extends OptionsBase {
+ @Option(
+ name = "foo",
+ documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
+ converter = ConverterWithContext.class,
+ effectTags = {OptionEffectTag.NO_OP},
+ defaultValue = "bar")
+ public String foo;
+
+ public static class ConverterWithContext implements Converter<String> {
+
+ @Override
+ public String convert(String input, @Nullable Object conversionContext)
+ throws OptionsParsingException {
+ if (conversionContext != null) {
+ return conversionContext + input;
+ }
+ return input;
+ }
+
+ @Override
+ public String getTypeDescription() {
+ return "a funky string";
+ }
+ }
+ }
+
+ @Test
+ public void convertWithContext() throws Exception {
+ OptionsParser parser =
+ OptionsParser.builder()
+ .optionsClasses(ConverterWithContextTestOptions.class)
+ .withConversionContext("bleh ")
+ .build();
+ parser.parse("--foo", "quux");
+ ConverterWithContextTestOptions options =
+ parser.getOptions(ConverterWithContextTestOptions.class);
+ assertThat(options.foo).isEqualTo("bleh quux");
+ }
+
public static class ImplicitDependencyOptions extends OptionsBase {
@Option(
name = "first",
@@ -1898,7 +1939,7 @@
}
/** Converter for Foo. */
- public static class FooConverter implements Converter<Foo> {
+ public static class FooConverter extends Converter.Contextless<Foo> {
@Override
public Foo convert(String input) throws OptionsParsingException {
Foo foo = new Foo();
@@ -2142,7 +2183,8 @@
ParsedOptionDescription.newDummyInstance(
OptionDefinition.extractOptionDefinition(
ImplicitDependencyOptions.class.getField("first")),
- createInvocationPolicyOrigin());
+ createInvocationPolicyOrigin(),
+ /*conversionContext=*/ null);
OptionInstanceOrigin origin =
createInvocationPolicyOrigin(/*implicitDependent=*/ first, /*expandedFrom=*/ null);
@@ -2170,7 +2212,8 @@
ParsedOptionDescription.newDummyInstance(
OptionDefinition.extractOptionDefinition(
ImplicitDependencyOptions.class.getField("first")),
- createInvocationPolicyOrigin());
+ createInvocationPolicyOrigin(),
+ /*conversionContext=*/ null);
OptionInstanceOrigin origin =
createInvocationPolicyOrigin(/*implicitDependent=*/ null, /*expandedFrom=*/ first);
diff --git a/src/test/java/com/google/devtools/common/options/OptionsTest.java b/src/test/java/com/google/devtools/common/options/OptionsTest.java
index 6a0e586..b037507 100644
--- a/src/test/java/com/google/devtools/common/options/OptionsTest.java
+++ b/src/test/java/com/google/devtools/common/options/OptionsTest.java
@@ -375,7 +375,7 @@
" --none\n" + " An expanded option.\n" + " Expands to: --host=www.google.com");
}
- public static class MyURLConverter implements Converter<URL> {
+ public static class MyURLConverter extends Converter.Contextless<URL> {
@Override
public URL convert(String input) throws OptionsParsingException {
diff --git a/src/test/java/com/google/devtools/common/options/RegexPatternConverterTest.java b/src/test/java/com/google/devtools/common/options/RegexPatternConverterTest.java
index 20e7d9d..b18d2d7 100644
--- a/src/test/java/com/google/devtools/common/options/RegexPatternConverterTest.java
+++ b/src/test/java/com/google/devtools/common/options/RegexPatternConverterTest.java
@@ -27,7 +27,7 @@
public class RegexPatternConverterTest {
@Test
public void consistentEqualsAndHashCodeForSamePattern() {
- new ConverterTester(RegexPatternConverter.class)
+ new ConverterTester(RegexPatternConverter.class, /*conversionContext=*/ null)
.addEqualityGroup("")
.addEqualityGroup(".*")
.addEqualityGroup("[^\\s]+")
@@ -39,7 +39,7 @@
String regex = "a";
String semanticallyTheSame = "[a]";
- new ConverterTester(RegexPatternConverter.class)
+ new ConverterTester(RegexPatternConverter.class, /*conversionContext=*/ null)
.addEqualityGroup(regex)
.addEqualityGroup(semanticallyTheSame)
.testConvert();
diff --git a/src/test/java/com/google/devtools/common/options/StringToStringListConverterTest.java b/src/test/java/com/google/devtools/common/options/StringToStringListConverterTest.java
index 1fe8836..ab0af3b 100644
--- a/src/test/java/com/google/devtools/common/options/StringToStringListConverterTest.java
+++ b/src/test/java/com/google/devtools/common/options/StringToStringListConverterTest.java
@@ -18,8 +18,6 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
-import java.util.List;
-import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -28,7 +26,7 @@
@RunWith(JUnit4.class)
public class StringToStringListConverterTest {
- protected Converter<Map.Entry<String, List<String>>> converter =
+ protected Converters.StringToStringListConverter converter =
new Converters.StringToStringListConverter();
@Test
diff --git a/src/test/java/com/google/devtools/common/options/testing/ConverterTesterMapTest.java b/src/test/java/com/google/devtools/common/options/testing/ConverterTesterMapTest.java
index 61a6373..4f3300a 100644
--- a/src/test/java/com/google/devtools/common/options/testing/ConverterTesterMapTest.java
+++ b/src/test/java/com/google/devtools/common/options/testing/ConverterTesterMapTest.java
@@ -29,10 +29,14 @@
@Test
public void add_mapsTestedConverterClassToTester() throws Exception {
- ConverterTester stringTester = new ConverterTester(Converters.StringConverter.class);
- ConverterTester intTester = new ConverterTester(Converters.IntegerConverter.class);
- ConverterTester doubleTester = new ConverterTester(Converters.DoubleConverter.class);
- ConverterTester booleanTester = new ConverterTester(Converters.BooleanConverter.class);
+ ConverterTester stringTester =
+ new ConverterTester(Converters.StringConverter.class, /*conversionContext=*/ null);
+ ConverterTester intTester =
+ new ConverterTester(Converters.IntegerConverter.class, /*conversionContext=*/ null);
+ ConverterTester doubleTester =
+ new ConverterTester(Converters.DoubleConverter.class, /*conversionContext=*/ null);
+ ConverterTester booleanTester =
+ new ConverterTester(Converters.BooleanConverter.class, /*conversionContext=*/ null);
ConverterTesterMap map =
new ConverterTesterMap.Builder()
.add(stringTester)
@@ -54,10 +58,14 @@
@Test
public void addAll_mapsTestedConverterClassesToTester() throws Exception {
- ConverterTester stringTester = new ConverterTester(Converters.StringConverter.class);
- ConverterTester intTester = new ConverterTester(Converters.IntegerConverter.class);
- ConverterTester doubleTester = new ConverterTester(Converters.DoubleConverter.class);
- ConverterTester booleanTester = new ConverterTester(Converters.BooleanConverter.class);
+ ConverterTester stringTester =
+ new ConverterTester(Converters.StringConverter.class, /*conversionContext=*/ null);
+ ConverterTester intTester =
+ new ConverterTester(Converters.IntegerConverter.class, /*conversionContext=*/ null);
+ ConverterTester doubleTester =
+ new ConverterTester(Converters.DoubleConverter.class, /*conversionContext=*/ null);
+ ConverterTester booleanTester =
+ new ConverterTester(Converters.BooleanConverter.class, /*conversionContext=*/ null);
ConverterTesterMap map =
new ConverterTesterMap.Builder()
.addAll(ImmutableList.of(stringTester, intTester, doubleTester, booleanTester))
@@ -76,10 +84,14 @@
@Test
public void addAll_dumpsConverterTesterMapIntoNewMap() throws Exception {
- ConverterTester stringTester = new ConverterTester(Converters.StringConverter.class);
- ConverterTester intTester = new ConverterTester(Converters.IntegerConverter.class);
- ConverterTester doubleTester = new ConverterTester(Converters.DoubleConverter.class);
- ConverterTester booleanTester = new ConverterTester(Converters.BooleanConverter.class);
+ ConverterTester stringTester =
+ new ConverterTester(Converters.StringConverter.class, /*conversionContext=*/ null);
+ ConverterTester intTester =
+ new ConverterTester(Converters.IntegerConverter.class, /*conversionContext=*/ null);
+ ConverterTester doubleTester =
+ new ConverterTester(Converters.DoubleConverter.class, /*conversionContext=*/ null);
+ ConverterTester booleanTester =
+ new ConverterTester(Converters.BooleanConverter.class, /*conversionContext=*/ null);
ConverterTesterMap baseMap =
new ConverterTesterMap.Builder()
.addAll(ImmutableList.of(stringTester, intTester, doubleTester))
@@ -102,11 +114,15 @@
public void build_forbidsDuplicates() throws Exception {
ConverterTesterMap.Builder builder =
new ConverterTesterMap.Builder()
- .add(new ConverterTester(Converters.StringConverter.class))
- .add(new ConverterTester(Converters.IntegerConverter.class))
- .add(new ConverterTester(Converters.DoubleConverter.class))
- .add(new ConverterTester(Converters.BooleanConverter.class))
- .add(new ConverterTester(Converters.BooleanConverter.class));
+ .add(new ConverterTester(Converters.StringConverter.class, /*conversionContext=*/ null))
+ .add(
+ new ConverterTester(Converters.IntegerConverter.class, /*conversionContext=*/ null))
+ .add(new ConverterTester(Converters.DoubleConverter.class, /*conversionContext=*/ null))
+ .add(
+ new ConverterTester(Converters.BooleanConverter.class, /*conversionContext=*/ null))
+ .add(
+ new ConverterTester(
+ Converters.BooleanConverter.class, /*conversionContext=*/ null));
IllegalArgumentException expected =
assertThrows(IllegalArgumentException.class, () -> builder.build());
diff --git a/src/test/java/com/google/devtools/common/options/testing/ConverterTesterTest.java b/src/test/java/com/google/devtools/common/options/testing/ConverterTesterTest.java
index 947791d..36d6bda 100644
--- a/src/test/java/com/google/devtools/common/options/testing/ConverterTesterTest.java
+++ b/src/test/java/com/google/devtools/common/options/testing/ConverterTesterTest.java
@@ -31,7 +31,7 @@
@Test
public void construction_throwsAssertionErrorIfConverterCreationFails() throws Exception {
try {
- new ConverterTester(UnconstructableConverter.class);
+ new ConverterTester(UnconstructableConverter.class, /*conversionContext=*/ null);
} catch (AssertionError expected) {
assertThat(expected) // AssertionError
.hasCauseThat() // InvocationTargetException
@@ -44,7 +44,7 @@
}
/** Test converter for construction_throwsAssertionErrorIfConverterCreationFails. */
- public static final class UnconstructableConverter implements Converter<String> {
+ public static final class UnconstructableConverter extends Converter.Contextless<String> {
public UnconstructableConverter() {
throw new UnsupportedOperationException("YOU CAN'T MAKE ME!");
}
@@ -62,14 +62,15 @@
@Test
public void getConverterClass_returnsConstructorArg() throws Exception {
- ConverterTester tester = new ConverterTester(Converters.BooleanConverter.class);
+ ConverterTester tester =
+ new ConverterTester(Converters.BooleanConverter.class, /*conversionContext=*/ null);
assertThat(tester.getConverterClass()).isEqualTo(Converters.BooleanConverter.class);
}
@Test
public void hasTestForInput_returnsTrueIffInputPassedToAddEqualityGroup() throws Exception {
ConverterTester tester =
- new ConverterTester(Converters.DoubleConverter.class)
+ new ConverterTester(Converters.DoubleConverter.class, /*conversionContext=*/ null)
.addEqualityGroup("1.0", "1", "1.00")
.addEqualityGroup("2");
@@ -86,7 +87,7 @@
@Test
public void addEqualityGroup_throwsIfConversionFails() throws Exception {
ConverterTester tester =
- new ConverterTester(ThrowingConverter.class)
+ new ConverterTester(ThrowingConverter.class, /*conversionContext=*/ null)
.addEqualityGroup("okay")
.addEqualityGroup("also okay", "pretty fine");
try {
@@ -100,7 +101,7 @@
}
/** Test converter for addEqualityGroup_throwsIfConversionFails. */
- public static final class ThrowingConverter implements Converter<String> {
+ public static final class ThrowingConverter extends Converter.Contextless<String> {
@Override
public String convert(String input) throws OptionsParsingException {
if ("wrong".equals(input)) {
@@ -117,18 +118,18 @@
@Test
public void testConvert_passesWhenAllInstancesObeyEqualsAndItemsOnlyEqualToOthersInSameGroup() {
- new ConverterTester(Converters.DoubleConverter.class)
- .addEqualityGroup("1.0", "1", "1.00")
- .addEqualityGroup("2", "2", "2.0000", "2.0", "+2")
- .addEqualityGroup("3")
- .addEqualityGroup("3.1415")
- .testConvert();
+ new ConverterTester(Converters.DoubleConverter.class, /*conversionContext=*/ null)
+ .addEqualityGroup("1.0", "1", "1.00")
+ .addEqualityGroup("2", "2", "2.0000", "2.0", "+2")
+ .addEqualityGroup("3")
+ .addEqualityGroup("3.1415")
+ .testConvert();
}
@Test
public void testConvert_testsHashCodeConsistencyForConvertedInstance() {
ConverterTester tester =
- new ConverterTester(InconsistentHashCodeConverter.class)
+ new ConverterTester(InconsistentHashCodeConverter.class, /*conversionContext=*/ null)
.addEqualityGroup("input doesn't matter");
try {
tester.testConvert();
@@ -159,7 +160,7 @@
/** Test converter for testConvert_testsHashCodeConsistencyForConvertedInstance. */
public static final class InconsistentHashCodeConverter
- implements Converter<InconsistentHashCode> {
+ extends Converter.Contextless<InconsistentHashCode> {
@Override
public InconsistentHashCode convert(String input) throws OptionsParsingException {
return new InconsistentHashCode();
@@ -174,7 +175,7 @@
@Test
public void testConvert_testsHashCodeConsistencyForSameConverter() {
ConverterTester tester =
- new ConverterTester(IncrementingHashCodeConverter.class)
+ new ConverterTester(IncrementingHashCodeConverter.class, /*conversionContext=*/ null)
.addEqualityGroup("meaningless input");
try {
tester.testConvert();
@@ -208,7 +209,7 @@
/** Test converter for testConvert_testsHashCodeConsistencyForSameConverter. */
public static final class IncrementingHashCodeConverter
- implements Converter<SettableHashCode> {
+ extends Converter.Contextless<SettableHashCode> {
private int howManyInstancesHaveIMadeAlready = 0;
@Override
@@ -226,7 +227,7 @@
@Test
public void testConvert_testsHashCodeConsistencyForDifferentConverters() {
ConverterTester tester =
- new ConverterTester(StaticIncrementingHashCodeConverter.class)
+ new ConverterTester(StaticIncrementingHashCodeConverter.class, /*conversionContext=*/ null)
.addEqualityGroup("some kind of input");
try {
tester.testConvert();
@@ -241,7 +242,7 @@
/** Test converter for testConvert_testsHashCodeConsistencyForDifferentConverters. */
public static final class StaticIncrementingHashCodeConverter
- implements Converter<SettableHashCode> {
+ extends Converter.Contextless<SettableHashCode> {
private static int howManyInstancesHaveIMadeAlready = 0;
private final int hashCode;
@@ -266,7 +267,7 @@
@Test
public void testConvert_testsSelfEqualityForConvertedInstance() {
ConverterTester tester =
- new ConverterTester(SelfLoathingConverter.class)
+ new ConverterTester(SelfLoathingConverter.class, /*conversionContext=*/ null)
.addEqualityGroup("self-loathing");
try {
tester.testConvert();
@@ -292,7 +293,8 @@
}
/** Test converter for testConvert_testsSelfEqualityForConvertedInstance. */
- public static final class SelfLoathingConverter implements Converter<SelfLoathingObject> {
+ public static final class SelfLoathingConverter
+ extends Converter.Contextless<SelfLoathingObject> {
@Override
public SelfLoathingObject convert(String input) throws OptionsParsingException {
return new SelfLoathingObject();
@@ -307,7 +309,7 @@
@Test
public void testConvert_testsEqualityForSameConverter() {
ConverterTester tester =
- new ConverterTester(CountingConverter.class)
+ new ConverterTester(CountingConverter.class, /*conversionContext=*/ null)
.addEqualityGroup("countables");
try {
tester.testConvert();
@@ -321,7 +323,7 @@
}
/** Test converter for testConvert_testsEqualityForSameConverter. */
- public static final class CountingConverter implements Converter<Integer> {
+ public static final class CountingConverter extends Converter.Contextless<Integer> {
private int howManyInstancesHaveIMadeAlready = 0;
@Override
@@ -339,7 +341,7 @@
@Test
public void testConvert_testsEqualityForDifferentConverters() {
ConverterTester tester =
- new ConverterTester(StaticCountingConverter.class)
+ new ConverterTester(StaticCountingConverter.class, /*conversionContext=*/ null)
.addEqualityGroup("words I like");
try {
tester.testConvert();
@@ -353,7 +355,7 @@
}
/** Test converter for testConvert_testsEqualityForDifferentConverters. */
- public static final class StaticCountingConverter implements Converter<Integer> {
+ public static final class StaticCountingConverter extends Converter.Contextless<Integer> {
private static int howManyInstancesHaveIMadeAlready = 0;
private final int output;
@@ -377,7 +379,7 @@
@Test
public void testConvert_testsEqualityForItemsInSameGroup() {
ConverterTester tester =
- new ConverterTester(Converters.DoubleConverter.class)
+ new ConverterTester(Converters.DoubleConverter.class, /*conversionContext=*/ null)
.addEqualityGroup("+1.000", "2.30");
try {
tester.testConvert();
@@ -392,7 +394,7 @@
@Test
public void testConvert_testsNonEqualityForItemsInDifferentGroups() {
ConverterTester tester =
- new ConverterTester(Converters.DoubleConverter.class)
+ new ConverterTester(Converters.DoubleConverter.class, /*conversionContext=*/ null)
.addEqualityGroup("+1.000")
.addEqualityGroup("1.0");
try {
diff --git a/src/test/java/com/google/devtools/common/options/testing/OptionsTesterTest.java b/src/test/java/com/google/devtools/common/options/testing/OptionsTesterTest.java
index ebae247..2017570 100644
--- a/src/test/java/com/google/devtools/common/options/testing/OptionsTesterTest.java
+++ b/src/test/java/com/google/devtools/common/options/testing/OptionsTesterTest.java
@@ -170,7 +170,7 @@
}
/** Test converter class for testing testAllDefaultValuesTestedBy. */
- public static final class TestConverter implements Converter<String> {
+ public static final class TestConverter extends Converter.Contextless<String> {
@Override
public String convert(String input) {
return input;
@@ -188,7 +188,7 @@
.testAllDefaultValuesTestedBy(
new ConverterTesterMap.Builder()
.add(
- new ConverterTester(TestConverter.class)
+ new ConverterTester(TestConverter.class, /*conversionContext=*/ null)
.addEqualityGroup("testedDefault", "otherTestedDefault"))
.build());
}
@@ -242,7 +242,9 @@
new OptionsTester(DefaultTestCheckUntestedField.class)
.testAllDefaultValuesTestedBy(
new ConverterTesterMap.Builder()
- .add(new ConverterTester(TestConverter.class).addEqualityGroup("testedDefault"))
+ .add(
+ new ConverterTester(TestConverter.class, /*conversionContext=*/ null)
+ .addEqualityGroup("testedDefault"))
.build());
} catch (AssertionError expected) {
assertThat(expected).hasMessageThat().contains("untestedField");
diff --git a/src/tools/android/java/com/google/devtools/build/android/Converters.java b/src/tools/android/java/com/google/devtools/build/android/Converters.java
index 5e89db2..0c5991e 100644
--- a/src/tools/android/java/com/google/devtools/build/android/Converters.java
+++ b/src/tools/android/java/com/google/devtools/build/android/Converters.java
@@ -38,13 +38,14 @@
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import javax.annotation.Nullable;
/**
* Some convenient converters used by android actions. Note: These are specific to android actions.
*/
public final class Converters {
private static final Converter<String> IDENTITY_CONVERTER =
- new Converter<String>() {
+ new Converter.Contextless<String>() {
@Override
public String convert(String input) {
return input;
@@ -60,7 +61,8 @@
* Converter for {@link UnvalidatedAndroidData}. Relies on {@code
* UnvalidatedAndroidData#valueOf(String)} to perform conversion and validation.
*/
- public static class UnvalidatedAndroidDataConverter implements Converter<UnvalidatedAndroidData> {
+ public static class UnvalidatedAndroidDataConverter
+ extends Converter.Contextless<UnvalidatedAndroidData> {
@Override
public UnvalidatedAndroidData convert(String input) throws OptionsParsingException {
@@ -80,7 +82,7 @@
/** Converter for {@link UnvalidatedAndroidDirectories}. */
public static class UnvalidatedAndroidDirectoriesConverter
- implements Converter<UnvalidatedAndroidDirectories> {
+ extends Converter.Contextless<UnvalidatedAndroidDirectories> {
@Override
public UnvalidatedAndroidDirectories convert(String input) throws OptionsParsingException {
@@ -104,7 +106,7 @@
* DependencyAndroidData#valueOf(String)} to perform conversion and validation.
*/
public static class DependencyAndroidDataListConverter
- implements Converter<List<DependencyAndroidData>> {
+ extends Converter.Contextless<List<DependencyAndroidData>> {
@Override
public List<DependencyAndroidData> convert(String input) throws OptionsParsingException {
@@ -132,7 +134,8 @@
}
/** Converter for a {@link SerializedAndroidData}. */
- public static class SerializedAndroidDataConverter implements Converter<SerializedAndroidData> {
+ public static class SerializedAndroidDataConverter
+ extends Converter.Contextless<SerializedAndroidData> {
@Override
public SerializedAndroidData convert(String input) throws OptionsParsingException {
@@ -152,7 +155,7 @@
/** Converter for a list of {@link SerializedAndroidData}. */
public static class SerializedAndroidDataListConverter
- implements Converter<List<SerializedAndroidData>> {
+ extends Converter.Contextless<List<SerializedAndroidData>> {
@Override
public List<SerializedAndroidData> convert(String input) throws OptionsParsingException {
@@ -181,7 +184,7 @@
/** Converter for a single {@link DependencySymbolFileProvider}. */
public static class DependencySymbolFileProviderConverter
- implements Converter<DependencySymbolFileProvider> {
+ extends Converter.Contextless<DependencySymbolFileProvider> {
@Override
public DependencySymbolFileProvider convert(String input) throws OptionsParsingException {
@@ -206,7 +209,7 @@
* Converter for {@link Revision}. Relies on {@code Revision#parseRevision(String)} to perform
* conversion and validation.
*/
- public static class RevisionConverter implements Converter<Revision> {
+ public static class RevisionConverter extends Converter.Contextless<Revision> {
@Override
public Revision convert(String input) throws OptionsParsingException {
@@ -224,7 +227,7 @@
}
/** Validating converter for Paths. A Path is considered valid if it resolves to a file. */
- public static class PathConverter implements Converter<Path> {
+ public static class PathConverter extends Converter.Contextless<Path> {
private final boolean mustExist;
@@ -284,7 +287,7 @@
* Validating converter for a list of Paths. A Path is considered valid if it resolves to a file.
*/
@Deprecated
- public static class PathListConverter implements Converter<List<Path>> {
+ public static class PathListConverter extends Converter.Contextless<List<Path>> {
private final PathConverter baseConverter;
@@ -336,7 +339,8 @@
}
@Override
- public Map<K, V> convert(String input) throws OptionsParsingException {
+ public Map<K, V> convert(String input, @Nullable Object conversionContext)
+ throws OptionsParsingException {
if (input.isEmpty()) {
return ImmutableMap.of();
}
@@ -354,14 +358,14 @@
}
// Unescape any comma or colon that is not a key or value separator.
String keyString = unescapeInput(entryFields[0]);
- K key = keyConverter.convert(keyString);
+ K key = keyConverter.convert(keyString, conversionContext);
if (map.containsKey(key)) {
throw new OptionsParsingException(
String.format("Dictionary already contains the key [%s].", keyString));
}
// Unescape any comma or colon that is not a key or value separator.
String valueString = unescapeInput(entryFields[1]);
- V value = valueConverter.convert(valueString);
+ V value = valueConverter.convert(valueString, conversionContext);
map.put(key, value);
}
return ImmutableMap.copyOf(map);
@@ -390,8 +394,9 @@
// The way {@link OptionsData} checks for generic types requires convert to have literal type
// parameters and not argument type parameters.
@Override
- public Map<String, String> convert(String input) throws OptionsParsingException {
- return super.convert(input);
+ public Map<String, String> convert(String input, Object conversionContext)
+ throws OptionsParsingException {
+ return super.convert(input, conversionContext);
}
}
@@ -408,14 +413,16 @@
// The way {@link OptionsData} checks for generic types requires convert to have literal type
// parameters and not argument type parameters.
@Override
- public Map<Path, String> convert(String input) throws OptionsParsingException {
- return super.convert(input);
+ public Map<Path, String> convert(String input, Object conversionContext)
+ throws OptionsParsingException {
+ return super.convert(input, conversionContext);
}
}
/** Converts a list of static library strings into paths. */
@Deprecated
- public static class StaticLibraryListConverter implements Converter<List<StaticLibrary>> {
+ public static class StaticLibraryListConverter
+ extends Converter.Contextless<List<StaticLibrary>> {
static final Splitter SPLITTER = Splitter.on(File.pathSeparatorChar);
static final StaticLibraryConverter libraryConverter = new StaticLibraryConverter();
@@ -436,7 +443,7 @@
}
/** Converts a static library string into path. */
- public static class StaticLibraryConverter implements Converter<StaticLibrary> {
+ public static class StaticLibraryConverter extends Converter.Contextless<StaticLibrary> {
static final PathConverter pathConverter = new PathConverter(true);
@@ -452,7 +459,7 @@
}
/** Converts a string of resources and manifest into paths. */
- public static class CompiledResourcesConverter implements Converter<CompiledResources> {
+ public static class CompiledResourcesConverter extends Converter.Contextless<CompiledResources> {
static final PathConverter pathConverter = new PathConverter(true);
static final Pattern COMPILED_RESOURCE_FORMAT = Pattern.compile("(.+):(.+)");
diff --git a/src/tools/android/java/com/google/devtools/build/android/dexer/Dexing.java b/src/tools/android/java/com/google/devtools/build/android/dexer/Dexing.java
index 54b9838..b08339a 100644
--- a/src/tools/android/java/com/google/devtools/build/android/dexer/Dexing.java
+++ b/src/tools/android/java/com/google/devtools/build/android/dexer/Dexing.java
@@ -42,10 +42,8 @@
static final PrintStream nullout = new PrintStream(ByteStreams.nullOutputStream());
- /**
- * Parser for positions options based on the integer field names in {@link PositionList}.
- */
- public static class PositionGranularityConverter implements Converter<Integer> {
+ /** Parser for positions options based on the integer field names in {@link PositionList}. */
+ public static class PositionGranularityConverter extends Converter.Contextless<Integer> {
@Override
public Integer convert(String input) throws OptionsParsingException {
for (Field field : PositionList.class.getFields()) {