summaryrefslogtreecommitdiff
path: root/java/com/google/devtools/common/options/OptionsUsage.java
diff options
context:
space:
mode:
authorJon Brandvein <brandjon@google.com>2017-03-21 23:15:28 +0000
committerColin Cross <ccross@android.com>2017-03-22 09:56:48 -0700
commit172122c125f4b4b3eb402b0d5606a7862a28fd47 (patch)
tree1e4e9dbef87e3e263f3cadd09a590520e23a8e81 /java/com/google/devtools/common/options/OptionsUsage.java
parent95395ef8bc57dab3c5b356b5fd91c3d175c33d0f (diff)
downloaddesugar-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.java60
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("&nbsp;&nbsp;<code>")