1*8975f5c5SAndroid Build Coastguard Worker# Lint 2*8975f5c5SAndroid Build Coastguard Worker 3*8975f5c5SAndroid Build Coastguard Worker[Android Lint] is [one of the static analysis tools] that Chromium uses to catch 4*8975f5c5SAndroid Build Coastguard Workerpossible issues in Java code. 5*8975f5c5SAndroid Build Coastguard Worker 6*8975f5c5SAndroid Build Coastguard WorkerThis is a [list of checks] that you might encounter. 7*8975f5c5SAndroid Build Coastguard Worker 8*8975f5c5SAndroid Build Coastguard Worker[Android Lint]: https://googlesamples.github.io/android-custom-lint-rules/book.md.html 9*8975f5c5SAndroid Build Coastguard Worker[one of the static analysis tools]: static_analysis.md 10*8975f5c5SAndroid Build Coastguard Worker[list of checks]: https://googlesamples.github.io/android-custom-lint-rules/checks/index.md.html 11*8975f5c5SAndroid Build Coastguard Worker 12*8975f5c5SAndroid Build Coastguard Worker[TOC] 13*8975f5c5SAndroid Build Coastguard Worker 14*8975f5c5SAndroid Build Coastguard Worker## How Chromium uses lint 15*8975f5c5SAndroid Build Coastguard Worker 16*8975f5c5SAndroid Build Coastguard WorkerChromium only runs lint on apk or bundle targets that explicitly set 17*8975f5c5SAndroid Build Coastguard Worker`enable_lint = true`. You can run lint by compiling the apk or bundle target 18*8975f5c5SAndroid Build Coastguard Workerwith ninja; once the code finishes compiling, ninja will automatically run lint 19*8975f5c5SAndroid Build Coastguard Workeron the code. 20*8975f5c5SAndroid Build Coastguard Worker 21*8975f5c5SAndroid Build Coastguard WorkerSome example targets that have lint enabled are: 22*8975f5c5SAndroid Build Coastguard Worker 23*8975f5c5SAndroid Build Coastguard Worker - `//chrome/android:monochrome_public_bundle` 24*8975f5c5SAndroid Build Coastguard Worker - `//android_webview/support_library/boundary_interfaces:boundary_interface_example_apk` 25*8975f5c5SAndroid Build Coastguard Worker - Other targets with `enable_lint` enabled: https://source.chromium.org/search?q=lang:gn%20enable_lint%5C%20%3D%5C%20true&ss=chromium 26*8975f5c5SAndroid Build Coastguard Worker 27*8975f5c5SAndroid Build Coastguard WorkerIf you think lint is not running and already verified your GN 28*8975f5c5SAndroid Build Coastguard Workertarget has `enable_lint = true`, then you can double check that 29*8975f5c5SAndroid Build Coastguard Worker`android_static_analysis` is set to `"on"` (this is the default value): 30*8975f5c5SAndroid Build Coastguard Worker 31*8975f5c5SAndroid Build Coastguard Worker```shell 32*8975f5c5SAndroid Build Coastguard Worker$ gn args out/Default --list=android_static_analysis 33*8975f5c5SAndroid Build Coastguard Workerandroid_static_analysis 34*8975f5c5SAndroid Build Coastguard Worker Current value (from the default) = "on" 35*8975f5c5SAndroid Build Coastguard Worker From //build/config/android/config.gni:85 36*8975f5c5SAndroid Build Coastguard Worker``` 37*8975f5c5SAndroid Build Coastguard Worker 38*8975f5c5SAndroid Build Coastguard Worker## My code has a lint error 39*8975f5c5SAndroid Build Coastguard Worker 40*8975f5c5SAndroid Build Coastguard WorkerIf lint reports an issue in your code, there are several possible remedies. 41*8975f5c5SAndroid Build Coastguard WorkerIn descending order of preference: 42*8975f5c5SAndroid Build Coastguard Worker 43*8975f5c5SAndroid Build Coastguard Worker### Fix it 44*8975f5c5SAndroid Build Coastguard Worker 45*8975f5c5SAndroid Build Coastguard WorkerWhile this isn't always the right response, fixing the lint error or warning 46*8975f5c5SAndroid Build Coastguard Workershould be the default. 47*8975f5c5SAndroid Build Coastguard Worker 48*8975f5c5SAndroid Build Coastguard Worker### Suppress it locally 49*8975f5c5SAndroid Build Coastguard Worker 50*8975f5c5SAndroid Build Coastguard WorkerJava provides an annotation, 51*8975f5c5SAndroid Build Coastguard Worker[`@SuppressWarnings`](https://developer.android.com/reference/java/lang/SuppressWarnings), 52*8975f5c5SAndroid Build Coastguard Workerthat tells lint to ignore the annotated element. It can be used on classes, 53*8975f5c5SAndroid Build Coastguard Workerconstructors, methods, parameters, fields, or local variables, though usage in 54*8975f5c5SAndroid Build Coastguard WorkerChromium is typically limited to the first three. You do not need to import it 55*8975f5c5SAndroid Build Coastguard Workersince it is in the `java.lang` package. 56*8975f5c5SAndroid Build Coastguard Worker 57*8975f5c5SAndroid Build Coastguard WorkerLike many suppression annotations, `@SuppressWarnings` takes a value that tells 58*8975f5c5SAndroid Build Coastguard Worker**lint** what to ignore. It can be a single `String`: 59*8975f5c5SAndroid Build Coastguard Worker 60*8975f5c5SAndroid Build Coastguard Worker```java 61*8975f5c5SAndroid Build Coastguard Worker@SuppressWarnings("NewApi") 62*8975f5c5SAndroid Build Coastguard Workerpublic void foo() { 63*8975f5c5SAndroid Build Coastguard Worker a.methodThatRequiresHighSdkLevel(); 64*8975f5c5SAndroid Build Coastguard Worker} 65*8975f5c5SAndroid Build Coastguard Worker``` 66*8975f5c5SAndroid Build Coastguard Worker 67*8975f5c5SAndroid Build Coastguard WorkerIt can also be a list of `String`s: 68*8975f5c5SAndroid Build Coastguard Worker 69*8975f5c5SAndroid Build Coastguard Worker```java 70*8975f5c5SAndroid Build Coastguard Worker@SuppressWarnings({ 71*8975f5c5SAndroid Build Coastguard Worker "NewApi", 72*8975f5c5SAndroid Build Coastguard Worker "UseSparseArrays" 73*8975f5c5SAndroid Build Coastguard Worker }) 74*8975f5c5SAndroid Build Coastguard Workerpublic Map<Integer, FakeObject> bar() { 75*8975f5c5SAndroid Build Coastguard Worker Map<Integer, FakeObject> shouldBeASparseArray = new HashMap<Integer, FakeObject>(); 76*8975f5c5SAndroid Build Coastguard Worker another.methodThatRequiresHighSdkLevel(shouldBeASparseArray); 77*8975f5c5SAndroid Build Coastguard Worker return shouldBeASparseArray; 78*8975f5c5SAndroid Build Coastguard Worker} 79*8975f5c5SAndroid Build Coastguard Worker``` 80*8975f5c5SAndroid Build Coastguard Worker 81*8975f5c5SAndroid Build Coastguard WorkerFor resource xml files you can use `tools:ignore`: 82*8975f5c5SAndroid Build Coastguard Worker 83*8975f5c5SAndroid Build Coastguard Worker```xml 84*8975f5c5SAndroid Build Coastguard Worker<?xml version="1.0" encoding="utf-8"?> 85*8975f5c5SAndroid Build Coastguard Worker<resources xmlns:tools="http://schemas.android.com/tools"> 86*8975f5c5SAndroid Build Coastguard Worker <!-- TODO(crbug/###): remove tools:ignore once these colors are used --> 87*8975f5c5SAndroid Build Coastguard Worker <color name="hi" tools:ignore="NewApi,UnusedResources">@color/unused</color> 88*8975f5c5SAndroid Build Coastguard Worker</resources> 89*8975f5c5SAndroid Build Coastguard Worker``` 90*8975f5c5SAndroid Build Coastguard Worker 91*8975f5c5SAndroid Build Coastguard WorkerThe examples above are the recommended ways of suppressing lint warnings. 92*8975f5c5SAndroid Build Coastguard Worker 93*8975f5c5SAndroid Build Coastguard Worker### Suppress it in a `lint-suppressions.xml` file 94*8975f5c5SAndroid Build Coastguard Worker 95*8975f5c5SAndroid Build Coastguard Worker**lint** can be given a per-target XML configuration file containing warnings or 96*8975f5c5SAndroid Build Coastguard Workererrors that should be ignored. Each target defines its own configuration file 97*8975f5c5SAndroid Build Coastguard Workervia the `lint_suppressions_file` gn variable. It is usually defined near its 98*8975f5c5SAndroid Build Coastguard Worker`enable_lint` gn variable. 99*8975f5c5SAndroid Build Coastguard Worker 100*8975f5c5SAndroid Build Coastguard WorkerThese suppressions files should only be used for temporarily ignoring warnings 101*8975f5c5SAndroid Build Coastguard Workerthat are too hard (or not possible) to suppress locally, and permanently 102*8975f5c5SAndroid Build Coastguard Workerignoring warnings only for this target. To permanently ignore a warning for all 103*8975f5c5SAndroid Build Coastguard Workertargets, add the warning to the `_DISABLED_ALWAYS` list in 104*8975f5c5SAndroid Build Coastguard Worker[build/android/gyp/lint.py](https://source.chromium.org/chromium/chromium/src/+/main:build/android/gyp/lint.py). 105*8975f5c5SAndroid Build Coastguard WorkerDisabling globally makes lint a bit faster. 106*8975f5c5SAndroid Build Coastguard Worker 107*8975f5c5SAndroid Build Coastguard WorkerThe exception to the above rule is for warnings that affect multiple languages. 108*8975f5c5SAndroid Build Coastguard WorkerFeel free to suppress those in lint-suppressions.xml files since it is not 109*8975f5c5SAndroid Build Coastguard Workerpractical to suppress them in each language file and it is a lot of extra bloat 110*8975f5c5SAndroid Build Coastguard Workerto list out every language for every violation in lint-baseline.xml files. 111*8975f5c5SAndroid Build Coastguard Worker 112*8975f5c5SAndroid Build Coastguard WorkerHere is an example of how to structure a suppressions XML file: 113*8975f5c5SAndroid Build Coastguard Worker 114*8975f5c5SAndroid Build Coastguard Worker```xml 115*8975f5c5SAndroid Build Coastguard Worker<?xml version="1.0" encoding="utf-8" ?> 116*8975f5c5SAndroid Build Coastguard Worker<lint> 117*8975f5c5SAndroid Build Coastguard Worker <!-- Chrome is a system app. --> 118*8975f5c5SAndroid Build Coastguard Worker <issue id="ProtectedPermissions" severity="ignore"/> 119*8975f5c5SAndroid Build Coastguard Worker <issue id="UnusedResources"> 120*8975f5c5SAndroid Build Coastguard Worker <!-- 1 raw resources are accessed by URL in various places. --> 121*8975f5c5SAndroid Build Coastguard Worker <ignore regexp="gen/remoting/android/.*/res/raw/credits.*"/> 122*8975f5c5SAndroid Build Coastguard Worker <!-- TODO(crbug.com/###): Remove the following line. --> 123*8975f5c5SAndroid Build Coastguard Worker <ignore regexp="The resource `R.string.soon_to_be_used` appears to be unused"/> 124*8975f5c5SAndroid Build Coastguard Worker </issue> 125*8975f5c5SAndroid Build Coastguard Worker</lint> 126*8975f5c5SAndroid Build Coastguard Worker``` 127*8975f5c5SAndroid Build Coastguard Worker 128*8975f5c5SAndroid Build Coastguard Worker## What are `lint-baseline.xml` files for? 129*8975f5c5SAndroid Build Coastguard Worker 130*8975f5c5SAndroid Build Coastguard WorkerBaseline files are to help us introduce new lint warnings and errors without 131*8975f5c5SAndroid Build Coastguard Workerblocking on fixing all our existing code that violate these new errors. Since 132*8975f5c5SAndroid Build Coastguard Workerthey are generated files, they should **not** be used to suppress lint warnings. 133*8975f5c5SAndroid Build Coastguard WorkerOne of the approaches above should be used instead. Eventually all the errors in 134*8975f5c5SAndroid Build Coastguard Workerbaseline files should be either fixed or ignored permanently. 135*8975f5c5SAndroid Build Coastguard Worker 136*8975f5c5SAndroid Build Coastguard WorkerMost devs do not need to update baseline files and should not need the script 137*8975f5c5SAndroid Build Coastguard Workerbelow. Occasionally when making large build configuration changes it may be 138*8975f5c5SAndroid Build Coastguard Workernecessary to update baseline files (e.g. increasing the min_sdk_version). 139*8975f5c5SAndroid Build Coastguard Worker 140*8975f5c5SAndroid Build Coastguard WorkerBaseline files are defined via the `lint_baseline_file` gn variable. It is 141*8975f5c5SAndroid Build Coastguard Workerusually defined near a target's `enable_lint` gn variable. To regenerate all 142*8975f5c5SAndroid Build Coastguard Workerbaseline files, run: 143*8975f5c5SAndroid Build Coastguard Worker 144*8975f5c5SAndroid Build Coastguard Worker``` 145*8975f5c5SAndroid Build Coastguard Worker$ third_party/android_build_tools/lint/rebuild_baselines.py 146*8975f5c5SAndroid Build Coastguard Worker``` 147*8975f5c5SAndroid Build Coastguard Worker 148*8975f5c5SAndroid Build Coastguard WorkerThis script will also update baseline files in downstream //clank if needed. 149*8975f5c5SAndroid Build Coastguard WorkerSince downstream and upstream use separate lint binaries, it is usually safe 150*8975f5c5SAndroid Build Coastguard Workerto simply land the update CLs in any order. 151