diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/HelpCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/HelpCommand.java index 0fa2167fdb4798..edbe662bd1d9db 100644 --- a/src/main/java/com/google/devtools/build/lib/runtime/commands/HelpCommand.java +++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/HelpCommand.java @@ -273,6 +273,7 @@ private static BazelFlagsProto.FlagInfo.Builder createFlagInfo(OptionDefinition flagBuilder.setHasNegativeFlag(option.hasNegativeOption()); flagBuilder.setDocumentation(option.getHelpText()); flagBuilder.setAllowsMultiple(option.allowsMultiple()); + flagBuilder.setRequiresValue(option.requiresValue()); List optionEffectTags = Arrays.stream(option.getOptionEffectTags()) 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 3388ee08a52ed3..2d3d112248e2b6 100644 --- a/src/main/java/com/google/devtools/common/options/OptionDefinition.java +++ b/src/main/java/com/google/devtools/common/options/OptionDefinition.java @@ -270,6 +270,14 @@ public boolean usesBooleanValueSyntax() { || getConverter() instanceof BoolOrEnumConverter; } + /** + * Returns whether an option requires a value when instantiated, or instead can be present without + * an explicit value. + */ + public boolean requiresValue() { + return !isVoidField() && !usesBooleanValueSyntax(); + } + /** Returns the evaluated default value for this option & memoizes the result. */ @Nullable public Object getDefaultValue(@Nullable Object conversionContext) { diff --git a/src/main/java/com/google/devtools/common/options/OptionsUsage.java b/src/main/java/com/google/devtools/common/options/OptionsUsage.java index 2c0b8910dd3638..afd168e530a857 100644 --- a/src/main/java/com/google/devtools/common/options/OptionsUsage.java +++ b/src/main/java/com/google/devtools/common/options/OptionsUsage.java @@ -221,7 +221,7 @@ static void getUsageHtml( .append(flagName) .append(""); - if (optionDefinition.usesBooleanValueSyntax() || optionDefinition.isVoidField()) { + if (!optionDefinition.requiresValue()) { // Nothing for boolean, tristate, boolean_or_enum, or void options. } else if (!valueDescription.isEmpty()) { usage.append("=").append(escaper.escape(valueDescription)); diff --git a/src/main/protobuf/bazel_flags.proto b/src/main/protobuf/bazel_flags.proto index 04e58ab915fb64..1ed9969b331720 100644 --- a/src/main/protobuf/bazel_flags.proto +++ b/src/main/protobuf/bazel_flags.proto @@ -41,6 +41,11 @@ message FlagInfo { repeated string metadata_tags = 8; // The documentation category assigned to this flag optional string documentation_category = 9; + // Whether the flag requires a value. + // If false, value-less invocations are acceptable, e.g. --subcommands, + // but if true a value must be present for all instantiations of the flag, + // e.g. --jobs=100. + optional bool requires_value = 10; } message FlagCollection {