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