diff options
author | Jon Brandvein <brandjon@google.com> | 2017-03-21 23:15:28 +0000 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2017-03-22 09:56:48 -0700 |
commit | 172122c125f4b4b3eb402b0d5606a7862a28fd47 (patch) | |
tree | 1e4e9dbef87e3e263f3cadd09a590520e23a8e81 /java/com/google/devtools/common/options/OptionsUsage.java | |
parent | 95395ef8bc57dab3c5b356b5fd91c3d175c33d0f (diff) | |
download | desugar-172122c125f4b4b3eb402b0d5606a7862a28fd47.tar.gz |
Add expansion functions to options parser
This provides a way to programmatically define expansions of options based on what other options are defined for the parser. In particular, it will be used for the --incompatible_* changes mechanism, to turn on all incompatible change flags.
Expansion functions are specified in the @Option annotation, similar to converters. They are computed when an OptionsParser is constructed, and inspect a preliminary version of its OptionsData to determine the expansion result. This is then cached in the final OptionsData used by the parser.
Expansion information for usage strings is available, but only when the usage strings are obtained via the parser.
--
PiperOrigin-RevId: 150817553
MOS_MIGRATED_REVID=150817553
GitOrigin-RevId: 22d261c21748fba31797f0de8bd98fb2ff2fd2f5
Change-Id: Iec0d628fbf873b2b3d7fb7f4c86ad809f9955dbb
Diffstat (limited to 'java/com/google/devtools/common/options/OptionsUsage.java')
-rw-r--r-- | java/com/google/devtools/common/options/OptionsUsage.java | 60 |
1 files changed, 48 insertions, 12 deletions
diff --git a/java/com/google/devtools/common/options/OptionsUsage.java b/java/com/google/devtools/common/options/OptionsUsage.java index f3ee4d3..aa48cb7 100644 --- a/java/com/google/devtools/common/options/OptionsUsage.java +++ b/java/com/google/devtools/common/options/OptionsUsage.java @@ -23,6 +23,7 @@ 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. @@ -33,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); } } @@ -76,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. */ - static void getUsage(Field optionField, StringBuilder usage, - OptionsParser.HelpVerbosity helpVerbosity) { + 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, + @Nullable OptionsData optionsData) { String flagName = getFlagName(optionField); String typeDescription = getTypeDescription(optionField); Option annotation = optionField.getAnnotation(Option.class); @@ -114,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) @@ -125,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(); @@ -167,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>") |