|
| 1 | +<meta charset="utf-8" lang="kotlin"> |
| 2 | + |
| 3 | +# Options |
| 4 | + |
| 5 | +## Usage |
| 6 | + |
| 7 | +Users can configure lint using `lint.xml` files, turning on and off |
| 8 | +checks, changing the default severity, ignoring violations based on |
| 9 | +paths or regular expressions matching paths or messages, and so on. |
| 10 | + |
| 11 | +They can also configure “options” on a per issue type basis. Options |
| 12 | +are simply strings, booleans, integers or paths that configure how a |
| 13 | +detector works. |
| 14 | + |
| 15 | +For example, in the following `lint.xml` file, we're configuring the |
| 16 | +`UnknownNullness` detector to turn on its `ignoreDeprecated` option, |
| 17 | +and we're telling the `TooManyViews` detector that the maximum number |
| 18 | +of views in a layout it should allow before generating a warning should |
| 19 | +be set to 20: |
| 20 | + |
| 21 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~xml |
| 22 | +<?xml version="1.0" encoding="UTF-8"?> |
| 23 | +<lint> |
| 24 | + <issue id="UnknownNullness"> |
| 25 | + <option name="ignoreDeprecated" value="true" /> |
| 26 | + </issue> |
| 27 | + <issue id="TooManyViews"> |
| 28 | + <option name="maxCount" value="20" /> |
| 29 | + </issue> |
| 30 | +</lint> |
| 31 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 32 | + |
| 33 | +Note that `lint.xml` files can be located not just in the project |
| 34 | +directory but nested as well, for example for a particular source |
| 35 | +folder. |
| 36 | + |
| 37 | +(See the [lint.xml](../usage/lintxml.md.html) documentation for more.) |
| 38 | + |
| 39 | +## Creating Options |
| 40 | + |
| 41 | +First, create an `Option` and register it with the corresponding |
| 42 | +`Issue`. |
| 43 | + |
| 44 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~kotlin |
| 45 | +val MAX_COUNT = IntOption("maxCount", "Max number of views allowed", 80) |
| 46 | +val MY_ISSUE = Issue.create("MyId", ...) |
| 47 | + .setOptions(listOf(MAX_COUNT)) |
| 48 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 49 | + |
| 50 | +An option has a few pieces of metadata: |
| 51 | + |
| 52 | +* The name, which is a short identifier. Users will configure the |
| 53 | + option by listing this key along with the configured value in their |
| 54 | + `lint.xml` files. By convention this should be using camel case and |
| 55 | + only valid Java identifier characters. |
| 56 | + |
| 57 | +* A description. This should be a short sentence which lists the |
| 58 | + purpose of the option (and should be capitalized, and not end with |
| 59 | + punctuation). |
| 60 | + |
| 61 | +* A default value. This is the value that will be returned from |
| 62 | + `Option.getValue()` if the user has not configured the setting. |
| 63 | + |
| 64 | +* For integer and float options, minimum and maximum allowed values. |
| 65 | + |
| 66 | +* An optional explanation. This is a longer explanation of the option, |
| 67 | + if necessary. |
| 68 | + |
| 69 | +The name and default value are used by lint when options are looked up |
| 70 | +by detectors; the description, explanation and allowed ranges are used |
| 71 | +to include information about available options when lint generates for |
| 72 | +example HTML reports, or text reports including explanations, or |
| 73 | +displaying lint checks in the IDE settings panel, and so on. |
| 74 | + |
| 75 | +There are currently 5 types of options: Strings, booleans, ints, floats |
| 76 | +and paths. There's a separate option class for each one, which makes it |
| 77 | +easier to look up these options since for example for a `StringOption`, |
| 78 | +`getValue` returns a `String`, for an `IntOption` it returns an `Int`, |
| 79 | +and so on. |
| 80 | + |
| 81 | +Option Type | Option Class |
| 82 | +------------------------|----------------------------------- |
| 83 | +`String` | `StringOption` |
| 84 | +`Boolean` | `BooleanOption` |
| 85 | +`Int` | `IntOption` |
| 86 | +`Float` | `FloatOption` |
| 87 | +`File` | `FileOption` |
| 88 | + |
| 89 | +## Reading Options |
| 90 | + |
| 91 | +To look up the configured value for an option, just call `getValue` |
| 92 | +and pass in the `context`: |
| 93 | + |
| 94 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~kotlin |
| 95 | +val maxCount = MAX_COUNT.getValue(context) |
| 96 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 97 | + |
| 98 | +This will return the `Int` value configured for this option by the |
| 99 | +user, or if not set, our original default value, in this case 80. |
| 100 | + |
| 101 | +## Specific Configurations |
| 102 | + |
| 103 | +The above call will look up the option configured for the specific |
| 104 | +source file in the current `context`, which might be an individual |
| 105 | +Kotlin source file. That's generally what you want; users can configure |
| 106 | +`lint.xml` files not just at the root of the project; they can be |
| 107 | +placed throughout the source folders and are interpreted by lint to |
| 108 | +apply to the folders below. Therefore, if we're analyzing a particular |
| 109 | +Kotlin file and we want to check an option, you generally want to check |
| 110 | +what's configured locally for this file. |
| 111 | + |
| 112 | +However, there are cases where you want to look up options up front, |
| 113 | +for example at the project level. |
| 114 | + |
| 115 | +In that case, first look up the particular configuration you want, and |
| 116 | +then pass in that configuration instead of the context to the |
| 117 | +`Option.getValue` call. |
| 118 | + |
| 119 | +For example, the context for the current module is already available in |
| 120 | +the `context`, so you might for example look up the option value like |
| 121 | +this: |
| 122 | + |
| 123 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~kotlin |
| 124 | +val maxCount = MAX_COUNT.getValue(context.configuration) |
| 125 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 126 | + |
| 127 | +If you want to find the most applicable configuration for a given |
| 128 | +source file, use |
| 129 | + |
| 130 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~kotlin |
| 131 | +val configuration = context.findConfiguration(context.file) |
| 132 | +val maxCount = MAX_COUNT.getValue(configuration) |
| 133 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 134 | + |
| 135 | +## Files |
| 136 | + |
| 137 | +Note that there is a special `Option` type for files and paths: |
| 138 | +`FileOption`. Make sure that you use this instead of just a |
| 139 | +`StringOption` if you are planning on configuring files, because in the |
| 140 | +case of paths, users will want to specify paths relative to the |
| 141 | +location of the `lint.xml` file where the path is defined. For |
| 142 | +`FileOption` lint is aware of this and will convert the relative path |
| 143 | +string as necessary. |
| 144 | + |
| 145 | +## Constraints |
| 146 | + |
| 147 | +Note that the integer and float options allow you to specify a valid |
| 148 | +range for the configured value -- a minimum (inclusive) and a maximum |
| 149 | +(exclusive): |
| 150 | + |
| 151 | +This range will be included with the option documentation, such as in |
| 152 | +“**duration** (default is 1.5): Expected duration in seconds. Must be |
| 153 | +at least 0.0 and less than 15.0.” |
| 154 | + |
| 155 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~kotlin |
| 156 | +private val DURATION_OPTION = FloatOption( |
| 157 | + name = "duration", |
| 158 | + description = "Expected duration", |
| 159 | + defaultValue = 1.5f, |
| 160 | + min = 0f, |
| 161 | + max = 15f |
| 162 | +) |
| 163 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 164 | + |
| 165 | +It will also be checked at runtime, and if the configured value is |
| 166 | +outside of the range, lint will report an error and pinpoint the |
| 167 | +location in the invalid `lint.xml` file: |
| 168 | + |
| 169 | +```text |
| 170 | +lint.xml:4: Error: duration: Must be less than 15.0 [LintError] |
| 171 | + <option name="duration" value="100.0" /> |
| 172 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 173 | +1 errors, 0 warnings |
| 174 | +``` |
| 175 | + |
| 176 | +## Testing Options |
| 177 | + |
| 178 | +When writing a lint unit test, you can easily configure specific values |
| 179 | +for your detector options. On the `lint()` test task, you can call |
| 180 | +`configureOption(option, value)`. There are a number of overloads for |
| 181 | +this method, so you can reference the option by its string name, or |
| 182 | +passing in the option instance, and if you do, you can pass in strings, |
| 183 | +integers, booleans, floats and files as values. Here's an example: |
| 184 | + |
| 185 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~kotlin |
| 186 | +lint().files( |
| 187 | + kotlin("fun test() { println("Hello World.") }") |
| 188 | +) |
| 189 | +.configureOption(MAX_COUNT, 150) |
| 190 | +.run() |
| 191 | +.expectClean() |
| 192 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 193 | + |
| 194 | +## Supporting Lint 4.2, 7.0 and 7.1 |
| 195 | + |
| 196 | +The `Option` support is new in 7.2. If your lint check still needs to |
| 197 | +work with older versions of lint, you can bypass the option |
| 198 | +registration, and just read option values directly from the |
| 199 | +configuration. |
| 200 | + |
| 201 | +First, find the configuration as shown above, and then instead of |
| 202 | +calling `Option.getValue`, call `getOption` on the configuration: |
| 203 | + |
| 204 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~kotlin |
| 205 | +val option: String? = configuration.getOption(ISSUE, "maxCount") |
| 206 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 207 | + |
| 208 | +The `getOption` method returns a `String`. For numbers and booleans, |
| 209 | +the coniguration also provides lookups which will convert the value to |
| 210 | +a number or boolean respectively: `getOptionAsInt`, |
| 211 | +`getOptionAsBoolean`, and most importantly, `getOptionAsFile`. If you |
| 212 | +are looking up paths, be sure to use `getOptionAsFile` since it has the |
| 213 | +important attribute that it allows paths to be relative to the |
| 214 | +configuration file where the (possibly inherited) value was defined, |
| 215 | +which is what users expect when editing `lint.xml` files. |
| 216 | + |
| 217 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~kotlin |
| 218 | +val option = configuration.getOptionAsInt(ISSUE, "maxCount", 100) |
| 219 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 220 | + |
| 221 | +<!-- Markdeep: --><style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style><script src="markdeep.min.js" charset="utf-8"></script><script src="https://morgan3d.github.io/markdeep/latest/markdeep.min.js" charset="utf-8"></script><script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script> |
0 commit comments