aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/common/options/Option.java
blob: a62558c4e74bcaec85d45e53328d3ba5adb02325 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Copyright 2014 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;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * An interface for annotating fields in classes (derived from OptionsBase)
 * that are options.
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Option {

  /**
   * The name of the option ("--name").
   */
  String name();

  /**
   * The single-character abbreviation of the option ("-abbrev").
   */
  char abbrev() default '\0';

  /**
   * A help string for the usage information.
   */
  String help() default "";

  /**
   * The default value for the option. This method should only be invoked
   * directly by the parser implementation. Any access to default values
   * should go via the parser to allow for application specific defaults.
   *
   * <p>There are two reasons this is a string.  Firstly, it ensures that
   * explicitly specifying this option at its default value (as printed in the
   * usage message) has the same behavior as not specifying the option at all;
   * this would be very hard to achieve if the default value was an instance of
   * type T, since we'd need to ensure that {@link #toString()} and {@link
   * #converter} 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; a null reference 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>The default value for flags that set allowMultiple to true is always
   * the empty list and the value in the annotation is ignored. 
   */
  String defaultValue();

  /**
   * A string describing the category of options that this belongs to. {@link
   * OptionsParser#describeOptions} prints options of the same category grouped
   * together.
   */
  String category() default "misc";

  /**
   * The converter that we'll use to convert this option into an object or
   * a simple type. The default is to use the builtin converters.
   * Custom converters must implement the {@link Converter} interface.
   */
  @SuppressWarnings({"unchecked", "rawtypes"})
  // Can't figure out how to coerce Converter.class into Class<? extends Converter<?>>
  Class<? extends Converter> converter() default Converter.class;

  /**
   * A flag indicating whether the option type should be allowed to occur
   * multiple times in a single option list.
   *
   * <p>If the command can occur multiple times, then the attribute value
   * <em>must</em> be a list type {@code List<T>}, and the result type of the
   * converter for this option must either match the parameter {@code T} or
   * {@code List<T>}. In the latter case the individual lists are concatenated
   * to form the full options value.
   *
   * <p>The {@link #defaultValue()} field of the annotation is ignored for repeatable
   * flags and the default value will be the empty list.
   */
  boolean allowMultiple() default false;

  /**
   * If the option is actually an abbreviation for other options, this field will
   * contain the strings to expand this option into. The original option is dropped
   * and the replacement used in its stead. It is recommended that such an option be
   * of type {@link Void}.
   *
   * An expanded option overrides previously specified options of the same name,
   * even if it is explicitly specified. This is the original behavior and can
   * be surprising if the user is not aware of it, which has led to several
   * requests to change this behavior. This was discussed in the blaze team and
   * it was decided that it is not a strong enough case to change the behavior.
   */
  String[] expansion() default {};

  /**
   * If the option requires that additional options be implicitly appended, this field
   * will contain the additional options. Implicit dependencies are parsed at the end
   * of each {@link OptionsParser#parse} invocation, and override options specified in
   * the same call. However, they can be overridden by options specified in a later
   * call or by options with a higher priority.
   *
   * @see OptionPriority
   */
  String[] implicitRequirements() default {};

  /**
   * If this field is a non-empty string, the option is deprecated, and a
   * deprecation warning is added to the list of warnings when such an option
   * is used.
   */
  String deprecationWarning() default "";

  /**
   * The old name for this option. If an option has a name "foo" and an old name "bar",
   * --foo=baz and --bar=baz will be equivalent. If the old name is used, a warning will be printed
   * indicating that the old name is deprecated and the new name should be used.
   */
  String oldName() default "";

  /**
   * Indicates that this option is a wrapper for other options, and will be unwrapped
   * when parsed. For example, if foo is a wrapper option, then "--foo=--bar=baz"
   * will be parsed as the flag "--bar=baz" (rather than --foo taking the value
   * "--bar=baz"). A wrapper option should have the type {@link Void} (if it is something other
   * than Void, the parser will not assign a value to it). The 
   * {@link Option#implicitRequirements()}, {@link Option#expansion()}, {@link Option#converter()}
   * attributes will not be processed. Wrapper options are implicitly repeatable (i.e., as though
   * {@link Option#allowMultiple()} is true regardless of its value in the annotation).
   */
  boolean wrapperOption() default false;
}