**Recent Changes** This chapter lists recent changes to lint that affect lint check authors: new features, API and behavior changes, and so on. For information about user visible changes to lint, see the User Guide. **8.9** * Lint's testing infrastructure support for testing quickfixes (`expectFixDiffs()`) now also validates that the modified source file is valid Kotlin, Java or XML. You can control this using the `lint().verifyFixedFileSyntax()` option. **8.8** * For the string-replacement quickfix, you can now specify regex flags (such as Pattern.DOT_ALL) to change the pattern matching behavior. **8.7** * The unit testing support now checks to make sure that you don't have duplicate class names across Java and Kotlin (which can lead to subtle and confusing errors.) * The `build.gradle.kts` unit testing support (`TestFiles.kts()`) now performs the same mocking of the builder model that the corresponding Groovy Gradle support (`Testfiles.gradle()`) performs. Among other things, this means that the other source files (`java()`, `kotlin()`, etc) must be located in source sets, e.g. `src/main/res/` and `/src/main/java/` rather than just `res/` and `src/`. This happens automatically if you don't manually specify a target path in the test file declaration. **8.6** * UAST repeats @JvmOverloaded methods in the AST. Lint now looks for and skips these duplications, and a new test mode also looks for potential problems in third party checks. * Added a new chapter to the api-guide on AST analysis, and in particular, using the Kotlin Analysis API. * The `UElementHandler` now supports recently added UAST element types: `UPatternExpression` and `UBinaryExpressionWithPattern`. * There's a new test mode checking for issues related to `@JvmOverloads`. See the [test modes](test-modes.md.html) chapter for more. **8.4** * You can now use `~~` in text messages (error messages, issue explanations, etc) to create strikethrough text. For example, “`Don't do this: ~~super.onCreate()~~`” will render as “Don't do this: ~~super.onCreate()~~”. **8.3** * If you'd like to change your error message reported by your detector, you can now override your `Detector`'s `sameMessage` method: match the details in the previous error message with the new format. This is used by the baseline mechanism such that your message change doesn't suddenly invalidate all existing baseline files for your issue. * The replace-string quickfix descriptor now lets you replace a string repeatedly. Example: ``` fix().replace().text("Foo").with("Bar").repeatedly().build() ``` You can also match an element optionally. Example: ``` fix().composite( fix().replace().text("").with("").build(), fix().replace().text("").with("").optional().build() ) ``` * The quickfix machinery was improved significantly. It now does a better job inserting imports (in alphabetical order instead of always prepending to the import list), inserting new XML attributes in the right canonical Android order, cleaning up whitespace after edits, etc. This may result in some diffs in any quickfix-related unit tests (e.g. `lint().run().expectFixDiffs(...)`) * The `getFileNameWithParent` utility method now always uses / as a file separator instead of the platform-specific one (e.g. \ on Windows). This ensures that baselines don't vary their error messages (where this utility method is typically used) based on which OS they were generated on. **8.2** * For unit tests, you can now specify the language level to be used for Kotlin and Java. For example, if your unit test is using Java records, add `.javaLanguageLevel("17")` to your `lint()` test configuration. **8.1** * The [data flow analyzer](dataflow-analyzer.md.html) has been improved; in addition to fixing a few bugs, there are a couple of new convenience sub classes which makes common tasks easier to accomplish; see the documentation for `TargetMethodDataFlowAnalyzer` for example. * The new `mavenLibrary` (and `binaryStub`) test files make it simple to create binary stub files in your tests, without having to perform compilation and check in base64 and gzip encoded test files. When your detector resolves references, the PSI elements you get back differ whether you're calling into source or into binary (jar/.class file) elements, so testing both (which the new test files automate using test modes) is helpful. More information about this is available in [](unit-testing.md.html). * Lint now supports analyzing TOML files. There is a new Scope.TOML_FILE detectors can register an interest in, a new TomlScanner interface to implement for visitTomlDocument callbacks, etc. From a GradleScanner, you can directly resolve version catalog libraries via lookup methods on the GradleContext. * Lint's “diff” output for unit test verification has been improved; it's now smarter about combining nearby chunks. (This should not break existing tests; the test infrastructure will try the older format as a fallback if the diffs aren't matching for the new format.) * Lint contains JVM 17 bytecode. You will now need to use JDK 17+ when compiling custom Lint checks. You should also configure the Kotlin compiler to target JVM 17, otherwise you may see errors when calling inline functions declared in Lint, UAST, or PSI. * Lint's testing infrastructure now looks not just for test/ but also androidTest/ and testFixtures/ to set the corresponding source set type on each test context. **8.0** * A new testmode which makes sure lint checks are all suppressible. It analyzes the reported error locations from the expected test output, and inserts suppress annotations in XML, Kotlin and Java files and makes sure that the corresponding warnings disappear. **7.4** * Annotation detectors can now specify just an annotation name instead of its fully qualified name in order to match *all* annotations of that name. For example, `override fun applicableAnnotations() = listOf("Nullable")` will match both `androidx.annotation.Nullable` and `org.jetbrains.annotations.Nullable`. This is used by for example the built-in CheckResultDetector to match many new variants of the `CheckReturnValue` annotations, such as the ones in mockito and in protobuf. * The new AnnotationUsageTypes IMPLICIT_CONSTRUCTOR and IMPLICIT_CONSTRUCTOR_CALL let detectors analyzing annotations get callbacks when an annotated no-args constructor is invoked explicitly from a subclass which has an implicit constructor, or from an implicit super call in an explicit sub constructor. These are not included by default, so override isApplicableAnnotationUsage to opt in. **7.3** * The new AnnotationUsageType.DEFINTION now lets detectors easily check occurrences of an annotation in the source code. Previously, `visitAnnotationUsage` would only check annotated elements, not the annotations themselves, and to check an annotation you'd need to create an `UElementHandler`. See the docs for the new enum constant for more details, and for an example of a detector that was converted from a handler to using this, see `IgnoreWithoutReasonDetector`. * Lint unit tests can now include `package-info.java` files with annotations in source form (until now, this only worked if the files were provided as binary class files) * String replacement quickfixes can now be configured with a list of imports to be performed when the fix is applied. This can be used to for example import Kotlin extension functions needed by the replacement string. (You should not use this for normal imports; instead, the replacement string should use fully qualified names everywhere along with the `shortenNames` property on the fix, and then lint will rewrite and import all symbols that can be done without conflicts.) **7.2** * There is now a way to register “options” for detectors. These are simple key/value pairs of type string, integer, boolean or file, and users can configure values in `lint.xml` files. This has all been possible since 4.2, but in 7.2 there is now a way to register the names, descriptions and default values of these options, and these will show up in issue explanations, HTML reports, and so on. (In the future we can use this to create an Options UI in the IDE, allow configuration via Gradle DSL, and so on.) For more, see the [options chapter](options.md.html). * A new test mode, `TestMode.CDATA`, checks that tests correctly handle XML CDATA sections in `` declarations. **7.1** * Lint now bundles IntelliJ version 2021.1 and Kotlin compiler version 1.5.30. You may see minor API changes in these dependencies. For example, the Kotlin UAST class `KotlinUMethod` changed packages from `org.jetbrains.uast.kotlin.declarations` to `org.jetbrains.uast.kotlin`. * The default behaviour of ResourceXmlDetector will change. It will skip res/raw folder and you have to override appliesTo method if you want your Lint checks to run there. * The computation of checksums for binary test files (e.g. `compiled` and `bytecode`) unfortunately had to change; the old mechamism was not stable. This means that after updating some of the test files will show as having wrong checksums (e.g. “The checksum does not match for test.kt; expected 0x26e3997d but was 0xb76b5946”). In these cases, just drop in the new checksum. * Source-modifying test modes. Lint's testing library now runs your unit tests through a number of additional paces: it will try inserting unnecessary parentheses, it will try replacing all imported symbols with fully qualified names, it will try adding argument names and reordering arguments to Kotlin calls, etc, and making sure the same results are reported. More information about this is available in [](test-modes.md.html). * The support for Kotlin's overloaded operators is significantly improved. While these are method calls, in the AST they do not show up as `UCallExpressions` (instead, you'll find them as `UBinaryExpression`, `UPrefixExpression`, `UArrayAccessExpression` and so on), which meant various call-specific checks ignored them. Now, in addition to the built-in checks all applying to these implicit calls as well, lint can present these expressions as call expressions. This means that the `getApplicableMethodNames` machinery for call callbacks will now also work for overloaded functions, and code which is iterating through calls can use the new `UastCallVisitor` (or directly construct `UImplicitCallExpression` wrappers) to simplify processing of all these types of calls. Finally, lint now provides a way to resolve operators for array access expressions (which is missing in UAST) via the UArrayAccessExpression.resolveOperator extension method, which is also used by the above machinery. * The annotation support (where a detector callback is invoked when elements are combined with annotated elements) has been significantly reworked (and the detector API changed). It now supports visiting the following additional scenarios: * Fields in annotated classes and packages * Fields and methods in annotated outerclasses * Class and object literals * Overridden methods * File level annotations (from Kotlin) It also offers better control for handling scopes -- providing all relevant annotations in the hierarchy at the same time such that a lint check for example can easily determine whether an outer annotation like `@Immutable` is canceled by a closer `@Mutable` annotation. There are some new annotation usage type enum constants which let your lint checks treat these differently. For example, the lint check which makes sure that calls to methods annotated with `@CheckResult` started flagging overrides of these methods. The fix was to add the following override to the `CheckResultDetector`: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~kotlin override fun isApplicableAnnotationUsage(type: AnnotationUsageType): Boolean { return type != AnnotationUsageType.METHOD_OVERRIDE && super.isApplicableAnnotationUsage(type) } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (Using this new API constant will make your lint check only work with the new version of lint. An alternative fix is to check that the `usage` parameter is not a `UMethod`.) For more, see the [new documentation](annotations.md.html) for how to handle annotations from detectors. * The lint testing library now contains a new test file type, `rClass`, which lets you easily construct Android `R` classes with resource declarations (which are needed in tests that reference the R fields to ensure that symbol resolution works.) * When you call `context.getLocation(UMethod)`, lint will now default this method to be equivalent to `context.getNameLocation(UMethod)` instead, which will highlight the method name. This might surface itself as unit test failures where the location range moves from a single `^` into a `~~~~~` range. This is because the location printer uses `^` to just indicate the start offset when a range is multi-line. **7.0** * The API level has bumped to 10. * Partial analysis. Lint's architecture has changed to support better scalability across large projects, where module results can be cached, etc. See the api-guide's dedicated chapter for more details. It is enabled by default starting in AGP 7.0.0-alpha13. * Issue registration now takes an optional `Vendor` property, where you can specify information about which company or team provided this lint check, which library it's associated with, contact information, and so on. This will make it easier for users to figure out where to send feedback or requests for 3rd party lint checks. * Bytecode verification: Instead of warning about 3rd party lint checks being obsolete because they were not compiled against the latest Lint API, lint now run its own bytecode verification against the lint jar and will silently accept older (and newer!) lint checks if they do not reference APIs that are not available. * Android Lint checks can now always access the resource repository for random access to resources, instead of having to gather them in batch mode. (Previously this was only available when lint checks were running in the IDE.) * The lint unit testing library now provides a `TestMode` concept. You can define setup and teardown methods, and lint will run unit tests repeatedly for each test mode. There are a number of built-in test modes already enabled; for example, all lint tests will run both in global analysis mode and in partial analysis mode, and the results compared to ensure they are the same. * Lint unit tests now include source contents for secondary locations too. If the test fails, lint will retry without secondary source locations and not report an error; this preserves backwards compatibility. * There's a new `Incident` class which is used to hold information to be reported to the user. Previously, there were a number of overloaded methods to report issues, taking locations, error messages, quick fixes, and so on. Each time we added another one we'd have to add another overload. Now, you instead just report incidents. This is critical to the new partial analysis architecture but is also required if you for example want to override severities per incident as described above. * Lint checks can now vary the severity on a per incident basis by calling overrideSeverity on the incidents. This means that there is no longer a need to create separate issues for flavors of the same underlying problem with slightly different expectations around warnings or errors. * There are additional modifier lookup methods for Kotlin modifiers on `JavaEvaluator`, like `isReified()`, `isCompanion()`, `isTailRec()`, and so on. * API documentation is now available. * UAST for Kotlin is now based on Kotlin 1.5. * Certain Kotlin PSI elements have new implementations known as _ultra light classes_. Ultra light classes improve performance by answering PSI queries “directly from source” rather than delegating to the Kotlin compiler backend. You may see ultra light classes when accessing the `UElement.javaPsi` property of a Kotlin UAST element. They can also appear when resolving references. For example, resolving a Kotlin field reference to its declaration may result in an instance of `KtUltraLightFieldForSourceDeclaration`. As a reminder, Kotlin light classes represent the “Java view” of an underlying Kotlin PSI element. To access the underlying Kotlin PSI element you should use `UElement.sourcePsi` (preferred) or otherwise the extension property `PsiElement.unwrapped` (declared in `org.jetbrains.kotlin.asJava`). * There is a new bug where calling `getNameIdentifier()` on Kotlin fields may return `null` ([KT-45629](https://youtrack.jetbrains.com/issue/KT-45629)). As a workaround you can use `JavaContext.findNameElement()` instead. * Kotlin references to Java methods now trigger both the `visitMethodCall()` callback _and_ the `visitReference()` callback. Previously only `visitMethodCall()` was triggered. * Quickfixes can now create and delete new files; see `LintFix#newFile` and `LintFix#deleteFile`. * For quickfixes, the `independent` property had inverted logic; this has now been reversed to follow the meaning of the name. * The location range returned when looking up the location for a call will now include arguments outside of the call range itself. This is important when the code is using Kotlin's assignment syntax for calling methods as if they are properties. * Lint's unit testing framework now checks all `import` statements in test files to make sure that they resolve. This will help catch common bugs and misunderstandings where tests reference frameworks that aren't available to lint in the unit test, and where you need to either add the library or more commonly just add some simple stubs. If the import statements do not matter to the test, you can just mark the test as allowing compilation errors, using `.allowCompilationErrors()` on the `lint()` task. * The [data flow analyzer](dataflow-analyzer.md.html) has been significantly improved, particularly around Kotlin scoping functions.