**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.