diff options
Diffstat (limited to 'java/com/google/devtools/common/options/OptionsUsage.java')
-rw-r--r-- | java/com/google/devtools/common/options/OptionsUsage.java | 72 |
1 files changed, 52 insertions, 20 deletions
diff --git a/java/com/google/devtools/common/options/OptionsUsage.java b/java/com/google/devtools/common/options/OptionsUsage.java index b8c19df..aa48cb7 100644 --- a/java/com/google/devtools/common/options/OptionsUsage.java +++ b/java/com/google/devtools/common/options/OptionsUsage.java @@ -13,19 +13,17 @@ // limitations under the License. package com.google.devtools.common.options; -import static com.google.devtools.common.options.OptionsParserImpl.findConverter; - import com.google.common.base.Joiner; import com.google.common.base.Splitter; import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.escape.Escaper; - import java.lang.reflect.Field; import java.text.BreakIterator; import java.util.Collections; import java.util.Comparator; import java.util.List; +import javax.annotation.Nullable; /** * A renderer for usage messages. For now this is very simple. @@ -36,15 +34,17 @@ class OptionsUsage { private static final Joiner COMMA_JOINER = Joiner.on(","); /** - * Given an options class, render the usage string into the usage, - * which is passed in as an argument. + * Given an options class, render the usage string into the usage, which is passed in as an + * argument. This will not include information about expansions for options using expansion + * functions (it would be unsafe to report this as we cannot know what options from other {@link + * OptionsBase} subclasses they depend on until a complete parser is constructed). */ static void getUsage(Class<? extends OptionsBase> optionsClass, StringBuilder usage) { List<Field> optionFields = Lists.newArrayList(OptionsParser.getAllAnnotatedFields(optionsClass)); Collections.sort(optionFields, BY_NAME); for (Field optionField : optionFields) { - getUsage(optionField, usage, OptionsParser.HelpVerbosity.LONG); + getUsage(optionField, usage, OptionsParser.HelpVerbosity.LONG, null); } } @@ -79,10 +79,35 @@ class OptionsUsage { } /** - * Append the usage message for a single option-field message to 'usage'. + * Returns the expansion for an option, to the extent known. Precisely, if an {@link OptionsData} + * object is supplied, the expansion is read from that. Otherwise, the annotation is inspected: If + * the annotation uses {@link Option#expansion} it is returned, and if it uses {@link + * Option#expansionFunction} null is returned, indicating a lack of definite information. In all + * cases, when the option is not an expansion option, an empty array is returned. + */ + private static @Nullable String[] getExpansionIfKnown( + Field optionField, Option annotation, @Nullable OptionsData optionsData) { + if (optionsData != null) { + return optionsData.getEvaluatedExpansion(optionField); + } else { + if (OptionsData.usesExpansionFunction(annotation)) { + return null; + } else { + // Empty array if it's not an expansion option. + return annotation.expansion(); + } + } + } + + /** + * Appends the usage message for a single option-field message to 'usage'. If {@code optionsData} + * is not supplied, options that use expansion functions won't be fully described. */ - static void getUsage(Field optionField, StringBuilder usage, - OptionsParser.HelpVerbosity helpVerbosity) { + static void getUsage( + Field optionField, + StringBuilder usage, + OptionsParser.HelpVerbosity helpVerbosity, + @Nullable OptionsData optionsData) { String flagName = getFlagName(optionField); String typeDescription = getTypeDescription(optionField); Option annotation = optionField.getAnnotation(Option.class); @@ -117,9 +142,12 @@ class OptionsUsage { usage.append(paragraphFill(annotation.help(), 4, 80)); // (indent, width) usage.append('\n'); } - if (annotation.expansion().length > 0) { + String[] expansion = getExpansionIfKnown(optionField, annotation, optionsData); + if (expansion == null) { + usage.append(" Expands to unknown options.\n"); + } else if (expansion.length > 0) { StringBuilder expandsMsg = new StringBuilder("Expands to: "); - for (String exp : annotation.expansion()) { + for (String exp : expansion) { expandsMsg.append(exp).append(" "); } usage.append(paragraphFill(expandsMsg.toString(), 4, 80)); // (indent, width) @@ -128,9 +156,11 @@ class OptionsUsage { } /** - * Append the usage message for a single option-field message to 'usage'. + * Append the usage message for a single option-field message to 'usage'. If {@code optionsData} + * is not supplied, options that use expansion functions won't be fully described. */ - static void getUsageHtml(Field optionField, StringBuilder usage, Escaper escaper) { + static void getUsageHtml( + Field optionField, StringBuilder usage, Escaper escaper, @Nullable OptionsData optionsData) { String plainFlagName = optionField.getAnnotation(Option.class).name(); String flagName = getFlagName(optionField); String valueDescription = optionField.getAnnotation(Option.class).valueHelp(); @@ -138,8 +168,7 @@ class OptionsUsage { Option annotation = optionField.getAnnotation(Option.class); usage.append("<dt><code><a name=\"flag--").append(plainFlagName).append("\"></a>--"); usage.append(flagName); - if (OptionsParserImpl.isBooleanField(optionField) - || OptionsParserImpl.isVoidField(optionField)) { + if (OptionsData.isBooleanField(optionField) || OptionsData.isVoidField(optionField)) { // Nothing for boolean, tristate, boolean_or_enum, or void options. } else if (!valueDescription.isEmpty()) { usage.append("=").append(escaper.escape(valueDescription)); @@ -157,7 +186,7 @@ class OptionsUsage { } else { // Don't call the annotation directly (we must allow overrides to certain defaults). String defaultValueString = OptionsParserImpl.getDefaultOptionString(optionField); - if (OptionsParserImpl.isVoidField(optionField)) { + if (OptionsData.isVoidField(optionField)) { // Void options don't have a default. } else if (OptionsParserImpl.isSpecialNullDefault(defaultValueString, optionField)) { usage.append(" default: see description"); @@ -171,10 +200,13 @@ class OptionsUsage { usage.append(paragraphFill(escaper.escape(annotation.help()), 0, 80)); // (indent, width) usage.append('\n'); } - if (annotation.expansion().length > 0) { + String[] expansion = getExpansionIfKnown(optionField, annotation, optionsData); + if (expansion == null) { + usage.append(" Expands to unknown options.<br>\n"); + } else if (expansion.length > 0) { usage.append("<br/>\n"); StringBuilder expandsMsg = new StringBuilder("Expands to:<br/>\n"); - for (String exp : annotation.expansion()) { + for (String exp : expansion) { // TODO(ulfjack): Can we link to the expanded flags here? expandsMsg .append(" <code>") @@ -259,12 +291,12 @@ class OptionsUsage { }; private static String getTypeDescription(Field optionsField) { - return findConverter(optionsField).getTypeDescription(); + return OptionsData.findConverter(optionsField).getTypeDescription(); } static String getFlagName(Field field) { String name = field.getAnnotation(Option.class).name(); - return OptionsParserImpl.isBooleanField(field) ? "[no]" + name : name; + return OptionsData.isBooleanField(field) ? "[no]" + name : name; } } |