# Options ## Usage Users can configure lint using `lint.xml` files, turning on and off checks, changing the default severity, ignoring violations based on paths or regular expressions matching paths or messages, and so on. They can also configure “options” on a per issue type basis. Options are simply strings, booleans, integers or paths that configure how a detector works. For example, in the following `lint.xml` file, we're configuring the `UnknownNullness` detector to turn on its `ignoreDeprecated` option, and we're telling the `TooManyViews` detector that the maximum number of views in a layout it should allow before generating a warning should be set to 20: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~xml <?xml version="1.0" encoding="UTF-8"?> <lint> <issue id="UnknownNullness"> <option name="ignoreDeprecated" value="true" /> </issue> <issue id="TooManyViews"> <option name="maxCount" value="20" /> </issue> </lint> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Note that `lint.xml` files can be located not just in the project directory but nested as well, for example for a particular source folder. (See the [lint.xml](../usage/lintxml.md.html) documentation for more.) ## Creating Options First, create an `Option` and register it with the corresponding `Issue`. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~kotlin val MAX_COUNT = IntOption("maxCount", "Max number of views allowed", 80) val MY_ISSUE = Issue.create("MyId", ...) .setOptions(listOf(MAX_COUNT)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ An option has a few pieces of metadata: * The name, which is a short identifier. Users will configure the option by listing this key along with the configured value in their `lint.xml` files. By convention this should be using camel case and only valid Java identifier characters. * A description. This should be a short sentence which lists the purpose of the option (and should be capitalized, and not end with punctuation). * A default value. This is the value that will be returned from `Option.getValue()` if the user has not configured the setting. * For integer and float options, minimum and maximum allowed values. * An optional explanation. This is a longer explanation of the option, if necessary. The name and default value are used by lint when options are looked up by detectors; the description, explanation and allowed ranges are used to include information about available options when lint generates for example HTML reports, or text reports including explanations, or displaying lint checks in the IDE settings panel, and so on. There are currently 5 types of options: Strings, booleans, ints, floats and paths. There's a separate option class for each one, which makes it easier to look up these options since for example for a `StringOption`, `getValue` returns a `String`, for an `IntOption` it returns an `Int`, and so on. Option Type | Option Class ------------------------|----------------------------------- `String` | `StringOption` `Boolean` | `BooleanOption` `Int` | `IntOption` `Float` | `FloatOption` `File` | `FileOption` ## Reading Options To look up the configured value for an option, just call `getValue` and pass in the `context`: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~kotlin val maxCount = MAX_COUNT.getValue(context) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This will return the `Int` value configured for this option by the user, or if not set, our original default value, in this case 80. ## Specific Configurations The above call will look up the option configured for the specific source file in the current `context`, which might be an individual Kotlin source file. That's generally what you want; users can configure `lint.xml` files not just at the root of the project; they can be placed throughout the source folders and are interpreted by lint to apply to the folders below. Therefore, if we're analyzing a particular Kotlin file and we want to check an option, you generally want to check what's configured locally for this file. However, there are cases where you want to look up options up front, for example at the project level. In that case, first look up the particular configuration you want, and then pass in that configuration instead of the context to the `Option.getValue` call. For example, the context for the current module is already available in the `context`, so you might for example look up the option value like this: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~kotlin val maxCount = MAX_COUNT.getValue(context.configuration) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If you want to find the most applicable configuration for a given source file, use ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~kotlin val configuration = context.findConfiguration(context.file) val maxCount = MAX_COUNT.getValue(configuration) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## Files Note that there is a special `Option` type for files and paths: `FileOption`. Make sure that you use this instead of just a `StringOption` if you are planning on configuring files, because in the case of paths, users will want to specify paths relative to the location of the `lint.xml` file where the path is defined. For `FileOption` lint is aware of this and will convert the relative path string as necessary. ## Constraints Note that the integer and float options allow you to specify a valid range for the configured value -- a minimum (inclusive) and a maximum (exclusive): This range will be included with the option documentation, such as in “**duration** (default is 1.5): Expected duration in seconds. Must be at least 0.0 and less than 15.0.” ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~kotlin private val DURATION_OPTION = FloatOption( name = "duration", description = "Expected duration", defaultValue = 1.5f, min = 0f, max = 15f ) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ It will also be checked at runtime, and if the configured value is outside of the range, lint will report an error and pinpoint the location in the invalid `lint.xml` file: ```text lint.xml:4: Error: duration: Must be less than 15.0 [LintError] ---------------------------------------- 1 errors, 0 warnings ``` ## Testing Options When writing a lint unit test, you can easily configure specific values for your detector options. On the `lint()` test task, you can call `configureOption(option, value)`. There are a number of overloads for this method, so you can reference the option by its string name, or passing in the option instance, and if you do, you can pass in strings, integers, booleans, floats and files as values. Here's an example: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~kotlin lint().files( kotlin("fun test() { println("Hello World.") }") ) .configureOption(MAX_COUNT, 150) .run() .expectClean() ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## Supporting Lint 4.2, 7.0 and 7.1 The `Option` support is new in 7.2. If your lint check still needs to work with older versions of lint, you can bypass the option registration, and just read option values directly from the configuration. First, find the configuration as shown above, and then instead of calling `Option.getValue`, call `getOption` on the configuration: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~kotlin val option: String? = configuration.getOption(ISSUE, "maxCount") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The `getOption` method returns a `String`. For numbers and booleans, the coniguration also provides lookups which will convert the value to a number or boolean respectively: `getOptionAsInt`, `getOptionAsBoolean`, and most importantly, `getOptionAsFile`. If you are looking up paths, be sure to use `getOptionAsFile` since it has the important attribute that it allows paths to be relative to the configuration file where the (possibly inherited) value was defined, which is what users expect when editing `lint.xml` files. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~kotlin val option = configuration.getOptionAsInt(ISSUE, "maxCount", 100) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~