Disallow default values for multiple options.
Only the following multiple options from now on are allowed to have default values:
- several options declared in tests - because this is required in tests
- `runs_per_test`, `flaky_test_attempts` and `worker_max_instances` - because they historically had a default value and getting rid of it is not backward-compatible.
The long-term goal is to prohibit default values for all multiple options.
RELNOTES: None.
PiperOrigin-RevId: 310891066
diff --git a/src/main/java/com/google/devtools/common/options/Option.java b/src/main/java/com/google/devtools/common/options/Option.java
index ec65473..5d27e47 100644
--- a/src/main/java/com/google/devtools/common/options/Option.java
+++ b/src/main/java/com/google/devtools/common/options/Option.java
@@ -24,8 +24,8 @@
* <p>The fields of this annotation have matching getters in {@link OptionDefinition}. Please do not
* access these fields directly, but instead go through that class.
*
- * <p>A number of checks are run on an Option's fields' values at compile time. See
- * {@link com.google.devtools.common.options.processor.OptionProcessor} for details.
+ * <p>A number of checks are run on an Option's fields' values at compile time. See {@link
+ * com.google.devtools.common.options.processor.OptionProcessor} for details.
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@@ -57,13 +57,18 @@
* were dual to each other. The second reason is more mundane but also more restrictive:
* annotation values must be compile-time constants.
*
- * <p>If an option's defaultValue() is the string "null", the option's converter will not be
- * invoked to interpret it; an empty {@link java.util.List} (for {@code allowMultiple = true}
- * options) or a null reference (for others) will be used instead. (It would be nice if
- * defaultValue could simply return null, but bizarrely, the Java Language Specification does not
- * consider null to be a compile-time constant.) This special interpretation of the string "null"
- * is only applicable when computing the default value; if specified on the command-line, this
- * string will have its usual literal meaning.
+ * <p>If an option's defaultValue() is the string "null" (see {@link
+ * OptionDefinition#SPECIAL_NULL_DEFAULT_VALUE}), the option's converter will not be invoked to
+ * interpret it; an empty {@link java.util.List} (for {@code allowMultiple = true} options) or a
+ * null reference (for others) will be used instead. (It would be nice if defaultValue could
+ * simply return null, but bizarrely, the Java Language Specification does not consider null to be
+ * a compile-time constant.) This special interpretation of the string "null" is only applicable
+ * when computing the default value; if specified on the command-line, this string will have its
+ * usual literal meaning.
+ *
+ * <p>Multiple options (e.g. with {@code allowMultiple = true}) are not allowed to have default
+ * values (with only a small numner of exceptions - see {@link OptionsProcessor}), thus should
+ * always use {@link OptionDefinition#SPECIAL_NULL_DEFAULT_VALUE}.
*/
String defaultValue();
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 29e3e29..fec0832 100644
--- a/src/main/java/com/google/devtools/common/options/OptionDefinition.java
+++ b/src/main/java/com/google/devtools/common/options/OptionDefinition.java
@@ -31,6 +31,13 @@
*/
public class OptionDefinition implements Comparable<OptionDefinition> {
+ /**
+ * A special value used to specify an absence of default value.
+ *
+ * @see Option#defaultValue
+ */
+ public static final String SPECIAL_NULL_DEFAULT_VALUE = "null";
+
// TODO(b/65049598) make ConstructionException checked, which will make this checked as well.
static class NotAnOptionException extends ConstructionException {
NotAnOptionException(Field field) {
@@ -172,7 +179,7 @@
}
public boolean isSpecialNullDefault() {
- return getUnparsedDefaultValue().equals("null") && !getType().isPrimitive();
+ return SPECIAL_NULL_DEFAULT_VALUE.equals(getUnparsedDefaultValue()) && !getType().isPrimitive();
}
/** Returns whether the arg is an expansion option. */
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 485efcd..74626f9 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
@@ -19,6 +19,7 @@
import com.google.devtools.common.options.Converters;
import com.google.devtools.common.options.ExpansionFunction;
import com.google.devtools.common.options.Option;
+import com.google.devtools.common.options.OptionDefinition;
import com.google.devtools.common.options.OptionDocumentationCategory;
import com.google.devtools.common.options.OptionEffectTag;
import com.google.devtools.common.options.OptionMetadataTag;
@@ -56,17 +57,20 @@
* Annotation processor for {@link Option}.
*
* <p>Checks the following invariants about {@link Option}-annotated fields ("options"):
+ *
* <ul>
- * <li>The {@link OptionsParser} only accepts options in {@link OptionsBase}-inheriting classes
- * <li>All options must be declared publicly and be neither static nor final.
- * <li>All options that must be used on the command line must have sensible names without
+ * <li>The {@link OptionsParser} only accepts options in {@link OptionsBase}-inheriting classes
+ * <li>All options must be declared publicly and be neither static nor final.
+ * <li>All options that must be used on the command line must have sensible names without
* whitespace or other confusing characters, such as equal signs.
- * <li>The type of the option must match the converter that will convert the unparsed string value
+ * <li>The type of the option must match the converter that will convert the unparsed string value
* into the option type. For options that do not specify a converter, check that there is a
* valid match in the {@link Converters#DEFAULT_CONVERTERS} list.
- * <li>Options must list valid combinations of tags and documentation categories.
- * <li>Expansion options and options with implicit requirements cannot expand in more than one way,
- * how multiple expansions would interact is not defined and should not be necessary.
+ * <li>Options must list valid combinations of tags and documentation categories.
+ * <li>Expansion options and options with implicit requirements cannot expand in more than one
+ * way, how multiple expansions would interact is not defined and should not be necessary.
+ * <li>Multiple options must not declare default value (see {@link
+ * #MULTIPLE_OPTIONS_DEFAULT_VALUE_EXCEPTIONS} for exceptions).
* </ul>
*
* <p>These properties can be relied upon at runtime without additional checks.
@@ -278,9 +282,7 @@
// instead check that T of Converter<T> matches the option's type, but this is all we can
// do.
List<ExecutableElement> methodList =
- elementUtils
- .getAllMembers(converterElement)
- .stream()
+ elementUtils.getAllMembers(converterElement).stream()
.filter(element -> element.getKind() == ElementKind.METHOD)
.map(methodElement -> (ExecutableElement) methodElement)
.filter(methodElement -> methodElement.getSimpleName().contentEquals("convert"))
@@ -487,6 +489,46 @@
}
}
+ private boolean hasSpecialNullDefaultValue(Option annotation) {
+ return OptionDefinition.SPECIAL_NULL_DEFAULT_VALUE.equals(annotation.defaultValue());
+ }
+
+ /**
+ * Options that are allowed to have default values.
+ *
+ * <p>DO NOT ADD new (especially production) options here - the long-term goal is to prohibit
+ * multiple options to have default values.
+ */
+ private static final ImmutableList<String> MULTIPLE_OPTIONS_DEFAULT_VALUE_EXCEPTIONS =
+ ImmutableList.of(
+ // Multiple options used in OptionDefinitionTest
+ "non_empty_string_multiple_option",
+ "empty_string_multiple_option",
+ // Production multiple options that still have default value.
+ // Mostly due to backward compatibility reasons.
+ "runs_per_test",
+ "flaky_test_attempts",
+ "worker_max_instances");
+
+ private boolean isMultipleOptionDefaultValueException(Option annotation) {
+ return MULTIPLE_OPTIONS_DEFAULT_VALUE_EXCEPTIONS.contains(annotation.name());
+ }
+
+ private void checkNoDefaultValueForMultipleOption(VariableElement optionField)
+ throws OptionProcessorException {
+ Option annotation = optionField.getAnnotation(Option.class);
+
+ if (annotation.allowMultiple()
+ && !hasSpecialNullDefaultValue(annotation)
+ && !isMultipleOptionDefaultValueException(annotation)) {
+ String message =
+ String.format(
+ "Default values for multiple options are not allowed - use \"%s\" special value",
+ "null");
+ throw new OptionProcessorException(optionField, message);
+ }
+ }
+
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(Option.class)) {
@@ -503,6 +545,7 @@
checkConverter(optionField);
checkEffectTagRationality(optionField);
checkMetadataTagAndCategoryRationality(optionField);
+ checkNoDefaultValueForMultipleOption(optionField);
} catch (OptionProcessorException e) {
error(e.getElementInError(), e.getMessage());
}
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 584bb1d..b7eabc2 100644
--- a/src/test/java/com/google/devtools/common/options/OptionDefaultValueConversionTest.java
+++ b/src/test/java/com/google/devtools/common/options/OptionDefaultValueConversionTest.java
@@ -14,9 +14,7 @@
package com.google.devtools.common.options;
-import static com.google.common.truth.Truth.assertWithMessage;
import static java.util.stream.Collectors.toList;
-import static org.junit.Assume.assumeTrue;
import com.google.common.flogger.GoogleLogger;
import com.google.devtools.build.lib.util.Classpath;
@@ -49,29 +47,6 @@
@Parameter public OptionDefinition optionDefinitionUnderTest;
- /**
- * Regression test for {@code allowMultiple = true} {@link Option#defaultValue()} switch from
- * {@code ""} to {@code "null"} as a part of enabling default values for {@code allowMultiple =
- * true} {@link Option}s.
- */
- @Test
- public void allowMultipleOptionsShouldNotHaveEmptyStringDefault() {
- // apply the test only to allowMultiple = true Options
- assumeTrue(optionDefinitionUnderTest.allowsMultiple());
-
- // arrange
- String assertionMessage =
- String.format(
- "\"%s\" option default value is an empty string - use a special \"null\" value for"
- + " empty multiple options",
- optionDefinitionUnderTest.getOptionName());
-
- // assert
- assertWithMessage(assertionMessage)
- .that(optionDefinitionUnderTest.getUnparsedDefaultValue())
- .isNotEmpty();
- }
-
@Test
public void shouldConvertDefaultValue() {
// assert
diff --git a/src/test/java/com/google/devtools/common/options/processor/OptionProcessorTest.java b/src/test/java/com/google/devtools/common/options/processor/OptionProcessorTest.java
index fc44f83..aac02be 100644
--- a/src/test/java/com/google/devtools/common/options/processor/OptionProcessorTest.java
+++ b/src/test/java/com/google/devtools/common/options/processor/OptionProcessorTest.java
@@ -203,14 +203,6 @@
}
@Test
- public void defaultConvertersForAllowMultipleOptionsAreFound() {
- assertAbout(javaSource())
- .that(getFile("AllDefaultConvertersWithAllowMultiple.java"))
- .processedWith(new OptionProcessor())
- .compilesWithoutError();
- }
-
- @Test
public void converterReturnsListForAllowMultipleIsAllowed() {
assertAbout(javaSource())
.that(getFile("MultipleOptionWithListTypeConverter.java"))
@@ -260,6 +252,16 @@
}
@Test
+ public void allowMultipleOptionsWithDefaultValuesAreRejected() {
+ assertAbout(javaSource())
+ .that(getFile("AllowMultipleOptionWithDefaultValue.java"))
+ .processedWith(new OptionProcessor())
+ .failsToCompile()
+ .withErrorContaining(
+ "Default values for multiple options are not allowed - use \"null\" special value");
+ }
+
+ @Test
public void optionWithIncorrectConverterIsRejected() {
assertAbout(javaSource())
.that(getFile("IncorrectConverterType.java"))
diff --git a/src/test/java/com/google/devtools/common/options/processor/optiontestsources/AllDefaultConvertersWithAllowMultiple.java b/src/test/java/com/google/devtools/common/options/processor/optiontestsources/AllDefaultConvertersWithAllowMultiple.java
deleted file mode 100644
index 8f26ade..0000000
--- a/src/test/java/com/google/devtools/common/options/processor/optiontestsources/AllDefaultConvertersWithAllowMultiple.java
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2017 The Bazel Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package com.google.devtools.common.options.processor.optiontestsources;
-
-import com.google.devtools.common.options.Option;
-import com.google.devtools.common.options.OptionDocumentationCategory;
-import com.google.devtools.common.options.OptionEffectTag;
-import com.google.devtools.common.options.OptionsBase;
-import com.google.devtools.common.options.TriState;
-import java.time.Duration;
-import java.util.List;
-
-/**
- * This class should contain allowMultiple examples for all of the types with DEFAULT_CONVERTERS,
- * and each converter should be found without generating compilation errors.
- */
-public class AllDefaultConvertersWithAllowMultiple extends OptionsBase {
- @Option(
- name = "boolean_option",
- defaultValue = "true",
- documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
- effectTags = {OptionEffectTag.NO_OP},
- allowMultiple = true
- )
- public List<Boolean> booleanOption;
-
- @Option(
- name = "double_option",
- defaultValue = "42.73",
- documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
- effectTags = {OptionEffectTag.NO_OP},
- allowMultiple = true
- )
- public List<Double> doubleOption;
-
- @Option(
- name = "int_option",
- defaultValue = "42",
- documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
- effectTags = {OptionEffectTag.NO_OP},
- allowMultiple = true
- )
- public List<Integer> intOption;
-
- @Option(
- name = "long_option",
- defaultValue = "-5000000000000",
- documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
- effectTags = {OptionEffectTag.NO_OP},
- allowMultiple = true
- )
- public List<Long> longOption;
-
- @Option(
- name = "string_option",
- defaultValue = "strings are strings are strings are strings",
- documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
- effectTags = {OptionEffectTag.NO_OP},
- allowMultiple = true
- )
- public List<String> stringOption;
-
- @Option(
- name = "tri_state_option",
- defaultValue = "auto",
- documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
- effectTags = {OptionEffectTag.NO_OP},
- allowMultiple = true
- )
- public List<TriState> triStateOption;
-
- @Option(
- name = "duration_option",
- defaultValue = "3600s",
- documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
- effectTags = {OptionEffectTag.NO_OP},
- allowMultiple = true
- )
- public List<Duration> durationOption;
-
- @Option(
- name = "void_option",
- defaultValue = "null",
- documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
- effectTags = {OptionEffectTag.NO_OP},
- allowMultiple = true
- )
- public List<Void> voidOption; // what does this even mean?
-}
diff --git a/src/test/java/com/google/devtools/common/options/processor/optiontestsources/AllowMultipleOptionWithDefaultValue.java b/src/test/java/com/google/devtools/common/options/processor/optiontestsources/AllowMultipleOptionWithDefaultValue.java
new file mode 100644
index 0000000..16eecf4
--- /dev/null
+++ b/src/test/java/com/google/devtools/common/options/processor/optiontestsources/AllowMultipleOptionWithDefaultValue.java
@@ -0,0 +1,31 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package com.google.devtools.common.options.processor.optiontestsources;
+
+import com.google.devtools.common.options.Option;
+import com.google.devtools.common.options.OptionDocumentationCategory;
+import com.google.devtools.common.options.OptionEffectTag;
+import com.google.devtools.common.options.OptionsBase;
+import java.util.List;
+
+/** This example options class should fail to compile. */
+public class AllowMultipleOptionWithDefaultValue extends OptionsBase {
+ @Option(
+ name = "bad_option",
+ defaultValue = "true",
+ documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
+ effectTags = {OptionEffectTag.NO_OP},
+ allowMultiple = true)
+ public List<String> badOption;
+}
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 626d087..4d32b1d 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
@@ -40,11 +40,10 @@
/** Test options class for optionAnnotationCheck_PassesWhenAllFieldsAnnotated. */
public static class BaseAllFieldsAnnotated extends OptionsBase {
@Option(
- name = "public_inherited_field_with_annotation",
- documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
- effectTags = {OptionEffectTag.NO_OP},
- defaultValue = "defaultFoo"
- )
+ name = "public_inherited_field_with_annotation",
+ documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
+ effectTags = {OptionEffectTag.NO_OP},
+ defaultValue = "defaultFoo")
public String inheritedField;
}
@@ -54,16 +53,14 @@
name = "public_declared_field_with_annotation",
documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
effectTags = {OptionEffectTag.NO_OP},
- defaultValue = "defaultFoo"
- )
+ defaultValue = "defaultFoo")
public String publicField;
@Option(
name = "other_public_declared_field_with_annotation",
documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
effectTags = {OptionEffectTag.NO_OP},
- defaultValue = "defaultFoo"
- )
+ defaultValue = "defaultFoo")
public String publicField2;
}
@@ -139,11 +136,10 @@
/** Test options class for optionAccessCheck_PassesWhenAllFieldsPublicNotStaticNotFinal. */
public static class BaseAllFieldsPublicNotStaticNotFinal extends OptionsBase {
@Option(
- name = "public_inherited_field_with_annotation",
- documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
- effectTags = {OptionEffectTag.NO_OP},
- defaultValue = "defaultFoo"
- )
+ name = "public_inherited_field_with_annotation",
+ documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
+ effectTags = {OptionEffectTag.NO_OP},
+ defaultValue = "defaultFoo")
public String inheritedField;
}
@@ -151,11 +147,10 @@
public static final class OptionAccessCheckAllFieldsPublicNotStaticNotFinal
extends BaseAllFieldsPublicNotStaticNotFinal {
@Option(
- name = "public_declared_field_with_annotation",
- documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
- effectTags = {OptionEffectTag.NO_OP},
- defaultValue = "defaultFoo"
- )
+ name = "public_declared_field_with_annotation",
+ documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
+ effectTags = {OptionEffectTag.NO_OP},
+ defaultValue = "defaultFoo")
public String annotatedField;
}
@@ -201,48 +196,43 @@
/** Test options class for defaultTestCheck_PassesIfAllDefaultsTested. */
public static final class DefaultTestCheck extends OptionsBase {
@Option(
- name = "tested_field",
- documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
- effectTags = {OptionEffectTag.NO_OP},
- converter = TestConverter.class,
- defaultValue = "testedDefault"
- )
+ name = "tested_field",
+ documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
+ effectTags = {OptionEffectTag.NO_OP},
+ converter = TestConverter.class,
+ defaultValue = "testedDefault")
public String testedField;
@Option(
- name = "field_implicitly_using_default_converter",
- documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
- effectTags = {OptionEffectTag.NO_OP},
- defaultValue = "implicitConverterDefault"
- )
+ name = "field_implicitly_using_default_converter",
+ documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
+ effectTags = {OptionEffectTag.NO_OP},
+ defaultValue = "implicitConverterDefault")
public String implicitConverterField;
@Option(
- name = "other_tested_field",
- documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
- effectTags = {OptionEffectTag.NO_OP},
- converter = TestConverter.class,
- defaultValue = "otherTestedDefault"
- )
+ name = "other_tested_field",
+ documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
+ effectTags = {OptionEffectTag.NO_OP},
+ converter = TestConverter.class,
+ defaultValue = "otherTestedDefault")
public String otherTestedField;
@Option(
- name = "field_with_null_default",
- documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
- effectTags = {OptionEffectTag.NO_OP},
- converter = TestConverter.class,
- defaultValue = "null"
- )
+ name = "field_with_null_default",
+ documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
+ effectTags = {OptionEffectTag.NO_OP},
+ converter = TestConverter.class,
+ defaultValue = "null")
public String nullDefaultField;
@Option(
- name = "allowMultiple_field",
- documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
- effectTags = {OptionEffectTag.NO_OP},
- converter = TestConverter.class,
- defaultValue = "allowMultipleDefault",
- allowMultiple = true
- )
+ name = "allowMultiple_field",
+ documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
+ effectTags = {OptionEffectTag.NO_OP},
+ converter = TestConverter.class,
+ defaultValue = "null",
+ allowMultiple = true)
public List<String> allowMultipleField;
}
@@ -280,12 +270,11 @@
*/
public static final class DefaultTestCheckUntestedField extends OptionsBase {
@Option(
- name = "untested_field",
- documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
- effectTags = {OptionEffectTag.NO_OP},
- converter = TestConverter.class,
- defaultValue = "untestedDefault"
- )
+ name = "untested_field",
+ documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
+ effectTags = {OptionEffectTag.NO_OP},
+ converter = TestConverter.class,
+ defaultValue = "untestedDefault")
public String untestedField;
}
@@ -304,12 +293,11 @@
/** Test options class for defaultTestCheck_FailsIfTesterIsAbsentEvenForNullDefault. */
public static final class DefaultTestCheckUntestedNullField extends OptionsBase {
@Option(
- name = "untested_field",
- documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
- effectTags = {OptionEffectTag.NO_OP},
- converter = TestConverter.class,
- defaultValue = "null"
- )
+ name = "untested_field",
+ documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
+ effectTags = {OptionEffectTag.NO_OP},
+ converter = TestConverter.class,
+ defaultValue = "null")
public String untestedNullField;
}
@@ -328,13 +316,12 @@
/** Test options class for defaultTestCheck_FailsIfTesterIsAbsentEvenForAllowMultiple. */
public static final class DefaultTestCheckUntestedMultipleField extends OptionsBase {
@Option(
- name = "untested_field",
- documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
- effectTags = {OptionEffectTag.NO_OP},
- converter = TestConverter.class,
- defaultValue = "untestedDefault",
- allowMultiple = true
- )
+ name = "untested_field",
+ documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
+ effectTags = {OptionEffectTag.NO_OP},
+ converter = TestConverter.class,
+ defaultValue = "null",
+ allowMultiple = true)
public List<String> untestedMultipleField;
}
}