xref: /aosp_15_r20/tools/metalava/README.md (revision 115816f9299ab6ddd6b9673b81f34e707f6bacab)
1*115816f9SAndroid Build Coastguard Worker# Metalava
2*115816f9SAndroid Build Coastguard Worker
3*115816f9SAndroid Build Coastguard WorkerMetalava is a metadata generator intended for JVM type projects. The main
4*115816f9SAndroid Build Coastguard Workerusers of this tool are Android Platform and AndroidX libraries, however this
5*115816f9SAndroid Build Coastguard Workertool also works on non-Android libraries.
6*115816f9SAndroid Build Coastguard Worker
7*115816f9SAndroid Build Coastguard WorkerMetalava has many features related to API management. Some examples of the most
8*115816f9SAndroid Build Coastguard Workercommonly used ones are:
9*115816f9SAndroid Build Coastguard Worker
10*115816f9SAndroid Build Coastguard Worker* Allows extracting the API (into signature text files, into stub API files
11*115816f9SAndroid Build Coastguard Worker  which in turn get compiled into android.jar, the Android SDK library) and
12*115816f9SAndroid Build Coastguard Worker  more importantly to hide code intended to be implementation only, driven by
13*115816f9SAndroid Build Coastguard Worker  javadoc comments like @hide, @doconly, @removed, etc, as well as various
14*115816f9SAndroid Build Coastguard Worker  annotations.
15*115816f9SAndroid Build Coastguard Worker
16*115816f9SAndroid Build Coastguard Worker* Extracting source level annotations into external annotations file (such as
17*115816f9SAndroid Build Coastguard Worker  the typedef annotations, which cannot be stored in the SDK as .class level
18*115816f9SAndroid Build Coastguard Worker  annotations) to ship alongside the Android SDK and used by Android Lint.
19*115816f9SAndroid Build Coastguard Worker
20*115816f9SAndroid Build Coastguard Worker* Diffing versions of the API and determining whether a newer version is
21*115816f9SAndroid Build Coastguard Worker  compatible with the older version. (See [COMPATIBILITY.md](COMPATIBILITY.md))
22*115816f9SAndroid Build Coastguard Worker
23*115816f9SAndroid Build Coastguard Worker## Building and running
24*115816f9SAndroid Build Coastguard Worker
25*115816f9SAndroid Build Coastguard WorkerTo download the code and any dependencies required for building, see [DOWNLOADING.md](DOWNLOADING.md)
26*115816f9SAndroid Build Coastguard Worker
27*115816f9SAndroid Build Coastguard WorkerTo build:
28*115816f9SAndroid Build Coastguard Worker
29*115816f9SAndroid Build Coastguard Worker    $ cd tools/metalava
30*115816f9SAndroid Build Coastguard Worker    $ ./gradlew
31*115816f9SAndroid Build Coastguard Worker
32*115816f9SAndroid Build Coastguard WorkerIt puts build artifacts in `../../out/metalava/`.
33*115816f9SAndroid Build Coastguard Worker
34*115816f9SAndroid Build Coastguard WorkerTo run the metalava executable:
35*115816f9SAndroid Build Coastguard Worker
36*115816f9SAndroid Build Coastguard Worker### Through Gradle
37*115816f9SAndroid Build Coastguard Worker
38*115816f9SAndroid Build Coastguard WorkerTo list all the options:
39*115816f9SAndroid Build Coastguard Worker
40*115816f9SAndroid Build Coastguard Worker    $ ./gradlew run
41*115816f9SAndroid Build Coastguard Worker
42*115816f9SAndroid Build Coastguard WorkerTo run it with specific arguments:
43*115816f9SAndroid Build Coastguard Worker
44*115816f9SAndroid Build Coastguard Worker    $ ./gradlew run --args="--api path/to/api.txt"
45*115816f9SAndroid Build Coastguard Worker
46*115816f9SAndroid Build Coastguard Worker### Through distribution artifact
47*115816f9SAndroid Build Coastguard Worker
48*115816f9SAndroid Build Coastguard WorkerFirst build it with:
49*115816f9SAndroid Build Coastguard Worker
50*115816f9SAndroid Build Coastguard Worker    $ ./gradlew installDist
51*115816f9SAndroid Build Coastguard Worker
52*115816f9SAndroid Build Coastguard WorkerThen run it with:
53*115816f9SAndroid Build Coastguard Worker
54*115816f9SAndroid Build Coastguard Worker    $ ../../out/metalava/metalava/build/install/metalava/bin/metalava
55*115816f9SAndroid Build Coastguard Worker                    _        _
56*115816f9SAndroid Build Coastguard Worker     _ __ ___   ___| |_ __ _| | __ ___   ____ _
57*115816f9SAndroid Build Coastguard Worker    | '_ ` _ \ / _ \ __/ _` | |/ _` \ \ / / _` |
58*115816f9SAndroid Build Coastguard Worker    | | | | | |  __/ || (_| | | (_| |\ V / (_| |
59*115816f9SAndroid Build Coastguard Worker    |_| |_| |_|\___|\__\__,_|_|\__,_| \_/ \__,_|
60*115816f9SAndroid Build Coastguard Worker
61*115816f9SAndroid Build Coastguard Worker    metalava extracts metadata from source code to generate artifacts such as the
62*115816f9SAndroid Build Coastguard Worker    signature files, the SDK stub files, external annotations etc.
63*115816f9SAndroid Build Coastguard Worker
64*115816f9SAndroid Build Coastguard Worker    Usage: metalava <flags>
65*115816f9SAndroid Build Coastguard Worker
66*115816f9SAndroid Build Coastguard Worker    Flags:
67*115816f9SAndroid Build Coastguard Worker
68*115816f9SAndroid Build Coastguard Worker    --help                                This message.
69*115816f9SAndroid Build Coastguard Worker    --quiet                               Only include vital output
70*115816f9SAndroid Build Coastguard Worker    --verbose                             Include extra diagnostic output
71*115816f9SAndroid Build Coastguard Worker
72*115816f9SAndroid Build Coastguard Worker    ...
73*115816f9SAndroid Build Coastguard Worker
74*115816f9SAndroid Build Coastguard Worker(*output truncated*)
75*115816f9SAndroid Build Coastguard Worker
76*115816f9SAndroid Build Coastguard Worker### Maven artifacts
77*115816f9SAndroid Build Coastguard Worker
78*115816f9SAndroid Build Coastguard WorkerTo build Metalava's Maven artifacts including `.pom` and `.module` metadata, run:
79*115816f9SAndroid Build Coastguard Worker
80*115816f9SAndroid Build Coastguard Worker    $ ./gradlew createArchive
81*115816f9SAndroid Build Coastguard Worker
82*115816f9SAndroid Build Coastguard WorkerThen locate the artifacts under `../../out/dist/repo/m2repository`.
83*115816f9SAndroid Build Coastguard Worker
84*115816f9SAndroid Build Coastguard Worker### Integration testing
85*115816f9SAndroid Build Coastguard Worker
86*115816f9SAndroid Build Coastguard WorkerTo build and run Metalava against a pinned version of an AndroidX library you can
87*115816f9SAndroid Build Coastguard Workerrun the following:
88*115816f9SAndroid Build Coastguard Worker
89*115816f9SAndroid Build Coastguard Worker    $ INTEGRATION=true ./gradlew integration:run
90*115816f9SAndroid Build Coastguard Worker
91*115816f9SAndroid Build Coastguard WorkerDetails on what runs are in `integration/build.gradle.kts`.
92*115816f9SAndroid Build Coastguard Worker
93*115816f9SAndroid Build Coastguard WorkerIt can also be run for repeated measurement using [gradle-profiler](https://github.com/gradle/gradle-profiler) with
94*115816f9SAndroid Build Coastguard Worker
95*115816f9SAndroid Build Coastguard Worker    $ INTEGRATION=true /path/to/gradle-profiler --benchmark --project-dir . --scenario-file integration/integration.scenarios
96*115816f9SAndroid Build Coastguard Worker
97*115816f9SAndroid Build Coastguard Worker## Features
98*115816f9SAndroid Build Coastguard Worker
99*115816f9SAndroid Build Coastguard Worker* Ability to read in an existing android.jar file instead of from source, which
100*115816f9SAndroid Build Coastguard Worker  means we can regenerate signature files etc for older versions according to
101*115816f9SAndroid Build Coastguard Worker  new formats (e.g. to fix past errors in doclava, such as annotation instance
102*115816f9SAndroid Build Coastguard Worker  methods which were accidentally not included.)
103*115816f9SAndroid Build Coastguard Worker
104*115816f9SAndroid Build Coastguard Worker* Ability to merge in data (annotations etc) from external sources, such as
105*115816f9SAndroid Build Coastguard Worker  IntelliJ external annotations data as well as signature files containing
106*115816f9SAndroid Build Coastguard Worker  annotations. This isn't just merged at export time, it's merged at codebase
107*115816f9SAndroid Build Coastguard Worker  load time such that it can be part of the API analysis.
108*115816f9SAndroid Build Coastguard Worker
109*115816f9SAndroid Build Coastguard Worker* Support for an updated signature file format (which is described in [FORMAT.md](FORMAT.md))
110*115816f9SAndroid Build Coastguard Worker
111*115816f9SAndroid Build Coastguard Worker  * Address errors in the doclava1 format which for example was missing
112*115816f9SAndroid Build Coastguard Worker    annotation class instance methods
113*115816f9SAndroid Build Coastguard Worker
114*115816f9SAndroid Build Coastguard Worker  * Improve the signature format such that it for example labels enums "enum"
115*115816f9SAndroid Build Coastguard Worker    instead of "abstract class extends java.lang.Enum", annotations as
116*115816f9SAndroid Build Coastguard Worker    "@interface" instead of "abstract class extends java.lang.Annotation", sorts
117*115816f9SAndroid Build Coastguard Worker    modifiers in the canonical modifier order, using "extends" instead of
118*115816f9SAndroid Build Coastguard Worker    "implements" for the superclass of an interface, and many other similar
119*115816f9SAndroid Build Coastguard Worker    tweaks outlined in the `Compatibility` class. (Metalava also allows (and
120*115816f9SAndroid Build Coastguard Worker    ignores) block comments in the signature files.)
121*115816f9SAndroid Build Coastguard Worker
122*115816f9SAndroid Build Coastguard Worker  * Add support for writing (and reading) annotations into the signature
123*115816f9SAndroid Build Coastguard Worker    files. This is vital now that some of these annotations become part of the
124*115816f9SAndroid Build Coastguard Worker    API contract (in particular nullness contracts, as well as parameter names
125*115816f9SAndroid Build Coastguard Worker    and default values.)
126*115816f9SAndroid Build Coastguard Worker
127*115816f9SAndroid Build Coastguard Worker  * Support for a "compact" nullness format -- one based on Kotlin's
128*115816f9SAndroid Build Coastguard Worker    syntax. Since the goal is to have **all** API elements explicitly state
129*115816f9SAndroid Build Coastguard Worker    their nullness contract, the signature files would very quickly become
130*115816f9SAndroid Build Coastguard Worker    bloated with @NonNull and @Nullable annotations everywhere. So instead, the
131*115816f9SAndroid Build Coastguard Worker    signature format now uses a suffix of `?` for nullable, `!` for not yet
132*115816f9SAndroid Build Coastguard Worker    annotated, and nothing for non-null.
133*115816f9SAndroid Build Coastguard Worker
134*115816f9SAndroid Build Coastguard Worker    Instead of
135*115816f9SAndroid Build Coastguard Worker
136*115816f9SAndroid Build Coastguard Worker        method public java.lang.Double convert0(java.lang.Float);
137*115816f9SAndroid Build Coastguard Worker        method @Nullable public java.lang.Double convert1(@NonNull java.lang.Float);
138*115816f9SAndroid Build Coastguard Worker
139*115816f9SAndroid Build Coastguard Worker    we have
140*115816f9SAndroid Build Coastguard Worker
141*115816f9SAndroid Build Coastguard Worker        method public java.lang.Double! convert0(java.lang.Float!);
142*115816f9SAndroid Build Coastguard Worker        method public java.lang.Double? convert1(java.lang.Float);
143*115816f9SAndroid Build Coastguard Worker
144*115816f9SAndroid Build Coastguard Worker  * Other compactness improvements: Skip packages in some cases both for export
145*115816f9SAndroid Build Coastguard Worker    and reinsert during import. Specifically, drop "java.lang."  from package
146*115816f9SAndroid Build Coastguard Worker    names such that you have
147*115816f9SAndroid Build Coastguard Worker
148*115816f9SAndroid Build Coastguard Worker        method public void onUpdate(int, String);
149*115816f9SAndroid Build Coastguard Worker
150*115816f9SAndroid Build Coastguard Worker    instead of
151*115816f9SAndroid Build Coastguard Worker
152*115816f9SAndroid Build Coastguard Worker        method public void onUpdate(int, java.lang.String);
153*115816f9SAndroid Build Coastguard Worker
154*115816f9SAndroid Build Coastguard Worker    Similarly, annotations (the ones considered part of the API; unknown
155*115816f9SAndroid Build Coastguard Worker    annotations are not included in signature files) use just the simple name
156*115816f9SAndroid Build Coastguard Worker    instead of the full package name, e.g. `@UiThread` instead of
157*115816f9SAndroid Build Coastguard Worker    `@android.annotation.UiThread`.
158*115816f9SAndroid Build Coastguard Worker
159*115816f9SAndroid Build Coastguard Worker  * Misc documentation handling; for example, it attempts to fix sentences that
160*115816f9SAndroid Build Coastguard Worker    javadoc will mistreat, such as sentences that "end" with "e.g. ".  It also
161*115816f9SAndroid Build Coastguard Worker    looks for various common typos and fixes those; here's a sample error
162*115816f9SAndroid Build Coastguard Worker    message running metalava on master: Enhancing docs:
163*115816f9SAndroid Build Coastguard Worker
164*115816f9SAndroid Build Coastguard Worker        frameworks/base/core/java/android/content/res/AssetManager.java:166: error: Replaced Kitkat with KitKat in documentation for Method android.content.res.AssetManager.getLocales() [Typo]
165*115816f9SAndroid Build Coastguard Worker        frameworks/base/core/java/android/print/PrinterCapabilitiesInfo.java:122: error: Replaced Kitkat with KitKat in documentation for Method android.print.PrinterCapabilitiesInfo.Builder.setColorModes(int, int) [Typo]
166*115816f9SAndroid Build Coastguard Worker
167*115816f9SAndroid Build Coastguard Worker* Built-in support for injecting new annotations for use by the Kotlin compiler,
168*115816f9SAndroid Build Coastguard Worker  not just nullness annotations found in the source code and annotations merged
169*115816f9SAndroid Build Coastguard Worker  in from external sources, but also inferring whether nullness annotations have
170*115816f9SAndroid Build Coastguard Worker  recently changed and if so marking them as @Migrate (which lets the Kotlin
171*115816f9SAndroid Build Coastguard Worker  compiler treat errors in the user code as warnings instead of errors.)
172*115816f9SAndroid Build Coastguard Worker
173*115816f9SAndroid Build Coastguard Worker* Support for generating documentation into the stubs files (so we can run
174*115816f9SAndroid Build Coastguard Worker  javadoc or [Dokka](https://github.com/Kotlin/dokka) on the stubs files instead
175*115816f9SAndroid Build Coastguard Worker  of the source code). This means that the documentation tool itself does not
176*115816f9SAndroid Build Coastguard Worker  need to be able to figure out which parts of the source code is included in
177*115816f9SAndroid Build Coastguard Worker  the API and which one is implementation; it is simply handed the filtered API
178*115816f9SAndroid Build Coastguard Worker  stub sources that include documentation.
179*115816f9SAndroid Build Coastguard Worker
180*115816f9SAndroid Build Coastguard Worker* Support for parsing Kotlin files. API files can now be implemented in Kotlin
181*115816f9SAndroid Build Coastguard Worker  as well and metalava will parse and extract API information from them just as
182*115816f9SAndroid Build Coastguard Worker  is done for Java files.
183*115816f9SAndroid Build Coastguard Worker
184*115816f9SAndroid Build Coastguard Worker* Like doclava1, metalava can diff two APIs and warn about API compatibility
185*115816f9SAndroid Build Coastguard Worker  problems such as removing API elements. Metalava adds new warnings around
186*115816f9SAndroid Build Coastguard Worker  nullness, such as attempting to change a nullness contract incompatibly
187*115816f9SAndroid Build Coastguard Worker  (e.g. you can change a parameter from non null to nullable for final classes,
188*115816f9SAndroid Build Coastguard Worker  but not versa).  It also lets you diff directly on a source tree; it does not
189*115816f9SAndroid Build Coastguard Worker  require you to create two signature files to diff.
190*115816f9SAndroid Build Coastguard Worker
191*115816f9SAndroid Build Coastguard Worker* Consistent stubs: In doclava1, the code which iterated over the API and
192*115816f9SAndroid Build Coastguard Worker  generated the signature files and generated the stubs had diverged, so there
193*115816f9SAndroid Build Coastguard Worker  was some inconsistency. In metalava the stub files contain **exactly** the
194*115816f9SAndroid Build Coastguard Worker  same signatures as in the signature files.
195*115816f9SAndroid Build Coastguard Worker
196*115816f9SAndroid Build Coastguard Worker  (This turned out to be incredibly important; this revealed for example that
197*115816f9SAndroid Build Coastguard Worker  StringBuilder.setLength(int) was missing from the API signatures since it is a
198*115816f9SAndroid Build Coastguard Worker  public method inherited from a package protected super class, which the API
199*115816f9SAndroid Build Coastguard Worker  extraction code in doclava1 missed, but accidentally included in the SDK
200*115816f9SAndroid Build Coastguard Worker  anyway since it packages package private classes. Metalava strictly applies
201*115816f9SAndroid Build Coastguard Worker  the exact same API as is listed in the signature files, and once this was
202*115816f9SAndroid Build Coastguard Worker  hooked up to the build it immediately became apparent that it was missing
203*115816f9SAndroid Build Coastguard Worker  important methods that should really be part of the API.)
204*115816f9SAndroid Build Coastguard Worker
205*115816f9SAndroid Build Coastguard Worker* API Lint: Metalava can optionally (with --api-lint) run a series of additional
206*115816f9SAndroid Build Coastguard Worker  checks on the public API in the codebase and flag issues that are discouraged
207*115816f9SAndroid Build Coastguard Worker  or forbidden by the Android API Council; there are currently around 80 checks.
208*115816f9SAndroid Build Coastguard Worker  Some of these take advantage of looking at the source code which wasn't
209*115816f9SAndroid Build Coastguard Worker  possible with the signature-file based Python version; for example, it looks
210*115816f9SAndroid Build Coastguard Worker  inside method bodies to see if you're synchronizing on this or the current
211*115816f9SAndroid Build Coastguard Worker  class, which is forbidden.
212*115816f9SAndroid Build Coastguard Worker
213*115816f9SAndroid Build Coastguard Worker* Baselines: Metalava can report all of its issues into a "baseline" file, which
214*115816f9SAndroid Build Coastguard Worker  records the current set of issues. From that point forward, when metalava
215*115816f9SAndroid Build Coastguard Worker  finds a problem, it will only be reported if it is not already in the
216*115816f9SAndroid Build Coastguard Worker  baseline.  This lets you enforce new issues going forward without having to
217*115816f9SAndroid Build Coastguard Worker  fix all existing violations. Periodically, as older issues are fixed, you can
218*115816f9SAndroid Build Coastguard Worker  regenerate the baseline. For issues with some false positives, such as API
219*115816f9SAndroid Build Coastguard Worker  Lint, being able to check in the set of accepted or verified false positives
220*115816f9SAndroid Build Coastguard Worker  is quite important.
221*115816f9SAndroid Build Coastguard Worker
222*115816f9SAndroid Build Coastguard Worker* Metalava can generate reports about nullness annotation coverage (which helps
223*115816f9SAndroid Build Coastguard Worker  target efforts since we plan to annotate the entire API). First, it can
224*115816f9SAndroid Build Coastguard Worker  generate a raw count:
225*115816f9SAndroid Build Coastguard Worker
226*115816f9SAndroid Build Coastguard Worker        Nullness Annotation Coverage Statistics:
227*115816f9SAndroid Build Coastguard Worker        1279 out of 46900 methods were annotated (2%)
228*115816f9SAndroid Build Coastguard Worker        2 out of 21683 fields were annotated (0%)
229*115816f9SAndroid Build Coastguard Worker        2770 out of 47492 parameters were annotated (5%)
230*115816f9SAndroid Build Coastguard Worker
231*115816f9SAndroid Build Coastguard Worker  More importantly, you can also point it to some existing compiled applications
232*115816f9SAndroid Build Coastguard Worker  (.class or .jar files) and it will then measure the annotation coverage of the
233*115816f9SAndroid Build Coastguard Worker  APIs used by those applications. This lets us target the most important APIs
234*115816f9SAndroid Build Coastguard Worker  that are currently used by a corpus of apps and target our annotation efforts
235*115816f9SAndroid Build Coastguard Worker  in a targeted way. For example, running the analysis on the current version of
236*115816f9SAndroid Build Coastguard Worker  framework, and pointing it to the
237*115816f9SAndroid Build Coastguard Worker  [Plaid](https://github.com/nickbutcher/plaid) app's compiled output with
238*115816f9SAndroid Build Coastguard Worker
239*115816f9SAndroid Build Coastguard Worker      ... --annotation-coverage-of ~/plaid/app/build/intermediates/classes/debug
240*115816f9SAndroid Build Coastguard Worker
241*115816f9SAndroid Build Coastguard Worker  This produces the following output:
242*115816f9SAndroid Build Coastguard Worker
243*115816f9SAndroid Build Coastguard Worker    324 methods and fields were missing nullness annotations out of 650 total
244*115816f9SAndroid Build Coastguard Worker    API references.  API nullness coverage is 50%
245*115816f9SAndroid Build Coastguard Worker
246*115816f9SAndroid Build Coastguard Worker    ```
247*115816f9SAndroid Build Coastguard Worker    | Qualified Class Name                                         |      Usage Count |
248*115816f9SAndroid Build Coastguard Worker    |--------------------------------------------------------------|-----------------:|
249*115816f9SAndroid Build Coastguard Worker    | android.os.Parcel                                            |              146 |
250*115816f9SAndroid Build Coastguard Worker    | android.view.View                                            |              119 |
251*115816f9SAndroid Build Coastguard Worker    | android.view.ViewPropertyAnimator                            |              114 |
252*115816f9SAndroid Build Coastguard Worker    | android.content.Intent                                       |              104 |
253*115816f9SAndroid Build Coastguard Worker    | android.graphics.Rect                                        |               79 |
254*115816f9SAndroid Build Coastguard Worker    | android.content.Context                                      |               61 |
255*115816f9SAndroid Build Coastguard Worker    | android.widget.TextView                                      |               53 |
256*115816f9SAndroid Build Coastguard Worker    | android.transition.TransitionValues                          |               49 |
257*115816f9SAndroid Build Coastguard Worker    | android.animation.Animator                                   |               34 |
258*115816f9SAndroid Build Coastguard Worker    | android.app.ActivityOptions                                  |               34 |
259*115816f9SAndroid Build Coastguard Worker    | android.view.LayoutInflater                                  |               31 |
260*115816f9SAndroid Build Coastguard Worker    | android.app.Activity                                         |               28 |
261*115816f9SAndroid Build Coastguard Worker    | android.content.SharedPreferences                            |               26 |
262*115816f9SAndroid Build Coastguard Worker    | android.content.SharedPreferences.Editor                     |               26 |
263*115816f9SAndroid Build Coastguard Worker    | android.text.SpannableStringBuilder                          |               23 |
264*115816f9SAndroid Build Coastguard Worker    | android.view.ViewGroup.MarginLayoutParams                    |               21 |
265*115816f9SAndroid Build Coastguard Worker    | ... (99 more items                                           |                  |
266*115816f9SAndroid Build Coastguard Worker    ```
267*115816f9SAndroid Build Coastguard Worker
268*115816f9SAndroid Build Coastguard WorkerTop referenced un-annotated members:
269*115816f9SAndroid Build Coastguard Worker
270*115816f9SAndroid Build Coastguard Worker    ```
271*115816f9SAndroid Build Coastguard Worker    | Member                                                       |      Usage Count |
272*115816f9SAndroid Build Coastguard Worker    |--------------------------------------------------------------|-----------------:|
273*115816f9SAndroid Build Coastguard Worker    | Parcel.readString()                                          |               62 |
274*115816f9SAndroid Build Coastguard Worker    | Parcel.writeString(String)                                   |               62 |
275*115816f9SAndroid Build Coastguard Worker    | TextView.setText(CharSequence)                               |               34 |
276*115816f9SAndroid Build Coastguard Worker    | TransitionValues.values                                      |               28 |
277*115816f9SAndroid Build Coastguard Worker    | View.getContext()                                            |               28 |
278*115816f9SAndroid Build Coastguard Worker    | ViewPropertyAnimator.setDuration(long)                       |               26 |
279*115816f9SAndroid Build Coastguard Worker    | ViewPropertyAnimator.setInterpolator(android.animation.Ti... |               26 |
280*115816f9SAndroid Build Coastguard Worker    | LayoutInflater.inflate(int, android.view.ViewGroup, boole... |               23 |
281*115816f9SAndroid Build Coastguard Worker    | Rect.left                                                    |               22 |
282*115816f9SAndroid Build Coastguard Worker    | Rect.top                                                     |               22 |
283*115816f9SAndroid Build Coastguard Worker    | Intent.Intent(android.content.Context, Class<?>)             |               21 |
284*115816f9SAndroid Build Coastguard Worker    | Rect.bottom                                                  |               21 |
285*115816f9SAndroid Build Coastguard Worker    | TransitionValues.view                                        |               21 |
286*115816f9SAndroid Build Coastguard Worker    | VERSION.SDK_INT                                              |               18 |
287*115816f9SAndroid Build Coastguard Worker    | Context.getResources()                                       |               18 |
288*115816f9SAndroid Build Coastguard Worker    | EditText.getText()                                           |               18 |
289*115816f9SAndroid Build Coastguard Worker    | ... (309 more items                                          |                  |
290*115816f9SAndroid Build Coastguard Worker    ```
291*115816f9SAndroid Build Coastguard Worker
292*115816f9SAndroid Build Coastguard Worker  From this it's clear that it would be useful to start annotating
293*115816f9SAndroid Build Coastguard Worker  android.os.Parcel and android.view.View for example where there are
294*115816f9SAndroid Build Coastguard Worker  unannotated APIs that are frequently used, at least by this app.
295*115816f9SAndroid Build Coastguard Worker
296*115816f9SAndroid Build Coastguard Worker* Built on top of a full, type-resolved AST. Doclava1 was integrated with
297*115816f9SAndroid Build Coastguard Worker  javadoc, which meant that most of the source tree was opaque. Therefore, as
298*115816f9SAndroid Build Coastguard Worker  just one example, the code which generated documentation for typedef constants
299*115816f9SAndroid Build Coastguard Worker  had to require the constants to all share a single prefix it could look
300*115816f9SAndroid Build Coastguard Worker  for. However, in metalava, annotation references are available at the AST
301*115816f9SAndroid Build Coastguard Worker  level, so it can resolve references and map them back to the original field
302*115816f9SAndroid Build Coastguard Worker  references and include those directly.
303*115816f9SAndroid Build Coastguard Worker
304*115816f9SAndroid Build Coastguard Worker* Support for extracting annotations. Metalava can also generate the external
305*115816f9SAndroid Build Coastguard Worker  annotation files needed by Studio and lint in Gradle, which captures the
306*115816f9SAndroid Build Coastguard Worker  typedefs (@IntDef and @StringDef classes) in the source code. Prior to this
307*115816f9SAndroid Build Coastguard Worker  this was generated manually via the development/tools/extract code. This also
308*115816f9SAndroid Build Coastguard Worker  merges in manually curated data; some of this is in the manual/ folder in this
309*115816f9SAndroid Build Coastguard Worker  project.
310*115816f9SAndroid Build Coastguard Worker
311*115816f9SAndroid Build Coastguard Worker* Support for extracting API levels (api-versions.xml). This was generated by
312*115816f9SAndroid Build Coastguard Worker  separate code (tools/base/misc/api-generator), invoked during the build. This
313*115816f9SAndroid Build Coastguard Worker  functionality is now rolled into metalava, which has one very important
314*115816f9SAndroid Build Coastguard Worker  attribute: metalava will use this information when recording API levels for
315*115816f9SAndroid Build Coastguard Worker  API usage. (Prior to this, this was based on signature file parsing in
316*115816f9SAndroid Build Coastguard Worker  doclava, which sometimes generated incorrect results. Metalava uses the
317*115816f9SAndroid Build Coastguard Worker  android.jar files themselves to ensure that it computes the exact available
318*115816f9SAndroid Build Coastguard Worker  SDK data for each API level.)
319*115816f9SAndroid Build Coastguard Worker
320*115816f9SAndroid Build Coastguard Worker* Misc other features. For example, if you use the @VisibleForTesting annotation
321*115816f9SAndroid Build Coastguard Worker  from the support library, where you can express the intended visibility if the
322*115816f9SAndroid Build Coastguard Worker  method had not required visibility for testing, then metalava will treat that
323*115816f9SAndroid Build Coastguard Worker  method using the intended visibility instead when generating signature files
324*115816f9SAndroid Build Coastguard Worker  and stubs.
325*115816f9SAndroid Build Coastguard Worker
326*115816f9SAndroid Build Coastguard Worker## Architecture & Implementation
327*115816f9SAndroid Build Coastguard Worker
328*115816f9SAndroid Build Coastguard WorkerMetalava is implemented on top of IntelliJ parsing APIs (PSI and UAST). However,
329*115816f9SAndroid Build Coastguard Workerthese are hidden behind a "model": an abstraction layer which only exposes high
330*115816f9SAndroid Build Coastguard Workerlevel concepts like packages, classes and inner classes, methods, fields, and
331*115816f9SAndroid Build Coastguard Workermodifier lists (including annotations).
332*115816f9SAndroid Build Coastguard Worker
333*115816f9SAndroid Build Coastguard WorkerThis is done for multiple reasons:
334*115816f9SAndroid Build Coastguard Worker
335*115816f9SAndroid Build Coastguard Worker(1) It allows us to have multiple "back-ends": for example, metalava can read in
336*115816f9SAndroid Build Coastguard Worker    a model not just from parsing source code, but from reading older SDK
337*115816f9SAndroid Build Coastguard Worker    android.jar files (e.g. backed by bytecode) or reading previous signature
338*115816f9SAndroid Build Coastguard Worker    files.  Reading in multiple versions of an API lets doclava perform
339*115816f9SAndroid Build Coastguard Worker    "diffing", such as warning if an API is changing in an incompatible way. It
340*115816f9SAndroid Build Coastguard Worker    can also generate signature files in the new format (including data that was
341*115816f9SAndroid Build Coastguard Worker    missing in older signature files, such as annotation methods) without having
342*115816f9SAndroid Build Coastguard Worker    to parse older source code which may no longer be easy to parse.
343*115816f9SAndroid Build Coastguard Worker
344*115816f9SAndroid Build Coastguard Worker(2) There's a lot of logic for deciding whether code found in the source tree
345*115816f9SAndroid Build Coastguard Worker    should be included in the API. With the model approach we can build up an
346*115816f9SAndroid Build Coastguard Worker    API and for example mark a subset of its methods as included. By having a
347*115816f9SAndroid Build Coastguard Worker    separate hierarchy we can easily perform this work once and pass around our
348*115816f9SAndroid Build Coastguard Worker    filtered model instead of passing around PsiClass and PsiMethod instances
349*115816f9SAndroid Build Coastguard Worker    and having to keep the filtered data separately and remembering to always
350*115816f9SAndroid Build Coastguard Worker    consult the filter, not the PSI elements directly.
351*115816f9SAndroid Build Coastguard Worker
352*115816f9SAndroid Build Coastguard WorkerThe basic API element class is "Item". (In doclava1 this was called a
353*115816f9SAndroid Build Coastguard Worker"DocInfo".)  There are several sub interfaces of Item: PackageItem, ClassItem,
354*115816f9SAndroid Build Coastguard WorkerMemberItem, MethodItem, FieldItem, ParameterItem, etc. And then there are
355*115816f9SAndroid Build Coastguard Workerseveral implementation hierarchies: One is PSI based, where you point metalava
356*115816f9SAndroid Build Coastguard Workerto a source tree or a .jar file, and it constructs Items built on top of PSI:
357*115816f9SAndroid Build Coastguard WorkerPsiPackageItem, PsiClassItem, PsiMethodItem, etc. Another is textual, based on
358*115816f9SAndroid Build Coastguard Workersignature files: TextPackageItem, TextClassItem, and so on.
359*115816f9SAndroid Build Coastguard Worker
360*115816f9SAndroid Build Coastguard WorkerThe "Codebase" class captures a complete API snapshot (including classes that
361*115816f9SAndroid Build Coastguard Workerare hidden, which is why it's called a "Codebase" rather than an "API").
362*115816f9SAndroid Build Coastguard Worker
363*115816f9SAndroid Build Coastguard WorkerThere are methods to load codebases - from source folders, from a .jar file,
364*115816f9SAndroid Build Coastguard Workerfrom a signature file. That's how API diffing is performed: you load two
365*115816f9SAndroid Build Coastguard Workercodebases (from whatever source you want, typically a previous API signature
366*115816f9SAndroid Build Coastguard Workerfile and the current set of source folders), and then you "diff" the two.
367*115816f9SAndroid Build Coastguard Worker
368*115816f9SAndroid Build Coastguard WorkerThere are several key helpers that help with the implementation, detailed next.
369*115816f9SAndroid Build Coastguard Worker
370*115816f9SAndroid Build Coastguard Worker### Visiting Items
371*115816f9SAndroid Build Coastguard Worker
372*115816f9SAndroid Build Coastguard WorkerFirst, metalava provides an ItemVisitor. This lets you visit the API easily.
373*115816f9SAndroid Build Coastguard WorkerFor example, here's how you can visit every class:
374*115816f9SAndroid Build Coastguard Worker
375*115816f9SAndroid Build Coastguard Worker    codebase.accept(object : ItemVisitor() {
376*115816f9SAndroid Build Coastguard Worker        override fun visitClass(cls: ClassItem) {
377*115816f9SAndroid Build Coastguard Worker            // code operating on the class here
378*115816f9SAndroid Build Coastguard Worker        }
379*115816f9SAndroid Build Coastguard Worker    })
380*115816f9SAndroid Build Coastguard Worker
381*115816f9SAndroid Build Coastguard WorkerSimilarly you can visit all items (regardless of type) by overriding
382*115816f9SAndroid Build Coastguard Worker`visitItem`, or to specifically visit methods, fields and so on overriding
383*115816f9SAndroid Build Coastguard Worker`visitPackage`, `visitClass`, `visitMethod`, etc.
384*115816f9SAndroid Build Coastguard Worker
385*115816f9SAndroid Build Coastguard WorkerThere is also an `ApiVisitor`. This is a subclass of the `ItemVisitor`, but
386*115816f9SAndroid Build Coastguard Workerwhich limits itself to visiting code elements that are part of the API.
387*115816f9SAndroid Build Coastguard Worker
388*115816f9SAndroid Build Coastguard WorkerThis is how for example the SignatureWriter and the StubWriter are both
389*115816f9SAndroid Build Coastguard Workerimplemented: they simply extend `ApiVisitor`, which means they'll only export
390*115816f9SAndroid Build Coastguard Workerthe API items in the codebase, and then in each relevant method they emit the
391*115816f9SAndroid Build Coastguard Workersignature or stub data:
392*115816f9SAndroid Build Coastguard Worker
393*115816f9SAndroid Build Coastguard Worker    class SignatureWriter(
394*115816f9SAndroid Build Coastguard Worker            private val writer: PrintWriter,
395*115816f9SAndroid Build Coastguard Worker            private val generateDefaultConstructors: Boolean,
396*115816f9SAndroid Build Coastguard Worker            private val filter: (Item) -> Boolean) : ApiVisitor() {
397*115816f9SAndroid Build Coastguard Worker
398*115816f9SAndroid Build Coastguard Worker    ....
399*115816f9SAndroid Build Coastguard Worker
400*115816f9SAndroid Build Coastguard Worker    override fun visitConstructor(constructor: ConstructorItem) {
401*115816f9SAndroid Build Coastguard Worker        writer.print("    ctor ")
402*115816f9SAndroid Build Coastguard Worker        writeModifiers(constructor)
403*115816f9SAndroid Build Coastguard Worker        writer.print(constructor.containingClass().fullName())
404*115816f9SAndroid Build Coastguard Worker        writeParameterList(constructor)
405*115816f9SAndroid Build Coastguard Worker        writeThrowsList(constructor)
406*115816f9SAndroid Build Coastguard Worker        writer.print(";\n")
407*115816f9SAndroid Build Coastguard Worker    }
408*115816f9SAndroid Build Coastguard Worker
409*115816f9SAndroid Build Coastguard Worker    ....
410*115816f9SAndroid Build Coastguard Worker
411*115816f9SAndroid Build Coastguard Worker### Visiting Types
412*115816f9SAndroid Build Coastguard Worker
413*115816f9SAndroid Build Coastguard WorkerThere is a `TypeVisitor` similar to `ItemVisitor` which you can use to visit all
414*115816f9SAndroid Build Coastguard Workertypes in the codebase.
415*115816f9SAndroid Build Coastguard Worker
416*115816f9SAndroid Build Coastguard WorkerWhen computing the API, all types that are included in the API should be
417*115816f9SAndroid Build Coastguard Workerincluded (e.g. if `List<Foo>` is part of the API then `Foo` must be too).  This
418*115816f9SAndroid Build Coastguard Workeris easy to do with the `TypeVisitor`.
419*115816f9SAndroid Build Coastguard Worker
420*115816f9SAndroid Build Coastguard Worker### Diffing Codebases
421*115816f9SAndroid Build Coastguard Worker
422*115816f9SAndroid Build Coastguard WorkerAnother visitor which helps with implementation is the ComparisonVisitor:
423*115816f9SAndroid Build Coastguard Worker
424*115816f9SAndroid Build Coastguard Worker    open class ComparisonVisitor {
425*115816f9SAndroid Build Coastguard Worker        open fun compare(old: Item, new: Item) {}
426*115816f9SAndroid Build Coastguard Worker        open fun added(item: Item) {}
427*115816f9SAndroid Build Coastguard Worker        open fun removed(item: Item) {}
428*115816f9SAndroid Build Coastguard Worker
429*115816f9SAndroid Build Coastguard Worker        open fun compare(old: PackageItem, new: PackageItem) { }
430*115816f9SAndroid Build Coastguard Worker        open fun compare(old: ClassItem, new: ClassItem) { }
431*115816f9SAndroid Build Coastguard Worker        open fun compare(old: MethodItem, new: MethodItem) { }
432*115816f9SAndroid Build Coastguard Worker        open fun compare(old: FieldItem, new: FieldItem) { }
433*115816f9SAndroid Build Coastguard Worker        open fun compare(old: ParameterItem, new: ParameterItem) { }
434*115816f9SAndroid Build Coastguard Worker
435*115816f9SAndroid Build Coastguard Worker        open fun added(item: PackageItem) { }
436*115816f9SAndroid Build Coastguard Worker        open fun added(item: ClassItem) { }
437*115816f9SAndroid Build Coastguard Worker        open fun added(item: MethodItem) { }
438*115816f9SAndroid Build Coastguard Worker        open fun added(item: FieldItem) { }
439*115816f9SAndroid Build Coastguard Worker        open fun added(item: ParameterItem) { }
440*115816f9SAndroid Build Coastguard Worker
441*115816f9SAndroid Build Coastguard Worker        open fun removed(item: PackageItem) { }
442*115816f9SAndroid Build Coastguard Worker        open fun removed(item: ClassItem) { }
443*115816f9SAndroid Build Coastguard Worker        open fun removed(item: MethodItem) { }
444*115816f9SAndroid Build Coastguard Worker        open fun removed(item: FieldItem) { }
445*115816f9SAndroid Build Coastguard Worker        open fun removed(item: ParameterItem) { }
446*115816f9SAndroid Build Coastguard Worker    }
447*115816f9SAndroid Build Coastguard Worker
448*115816f9SAndroid Build Coastguard WorkerThis makes it easy to perform API comparison operations.
449*115816f9SAndroid Build Coastguard Worker
450*115816f9SAndroid Build Coastguard WorkerFor example, metalava has a feature to mark "newly annotated" nullness
451*115816f9SAndroid Build Coastguard Workerannotations as migrated. To do this, it just extends `ComparisonVisitor`,
452*115816f9SAndroid Build Coastguard Workeroverrides the `compare(old: Item, new: Item)` method, and checks whether the old
453*115816f9SAndroid Build Coastguard Workeritem has no nullness annotations and the new one does, and if so, also marks the
454*115816f9SAndroid Build Coastguard Workernew annotations as @Migrate.
455*115816f9SAndroid Build Coastguard Worker
456*115816f9SAndroid Build Coastguard WorkerSimilarly, the API Check can simply override
457*115816f9SAndroid Build Coastguard Worker
458*115816f9SAndroid Build Coastguard Worker    open fun removed(item: Item) {
459*115816f9SAndroid Build Coastguard Worker        reporter.report(error, item, "Removing ${Item.describe(item)} is not allowed")
460*115816f9SAndroid Build Coastguard Worker    }
461*115816f9SAndroid Build Coastguard Worker
462*115816f9SAndroid Build Coastguard Workerto flag all API elements that have been removed as invalid (since you cannot
463*115816f9SAndroid Build Coastguard Workerremove API. (The real check is slightly more complicated; it looks into the
464*115816f9SAndroid Build Coastguard Workerhierarchy to see if there still is an inherited method with the same signature,
465*115816f9SAndroid Build Coastguard Workerin which case the deletion is allowed.))
466*115816f9SAndroid Build Coastguard Worker
467*115816f9SAndroid Build Coastguard Worker### Documentation Generation
468*115816f9SAndroid Build Coastguard Worker
469*115816f9SAndroid Build Coastguard WorkerAs mentioned above, metalava generates documentation directly into the stubs
470*115816f9SAndroid Build Coastguard Workerfiles, which can then be processed by Dokka and Javadoc to generate the same
471*115816f9SAndroid Build Coastguard Workerdocs as before.
472*115816f9SAndroid Build Coastguard Worker
473*115816f9SAndroid Build Coastguard WorkerDoclava1 was integrated with javadoc directly, so the way it generated metadata
474*115816f9SAndroid Build Coastguard Workerdocs (such as documenting permissions, ranges and typedefs from annotations) was
475*115816f9SAndroid Build Coastguard Workerto insert auxiliary tags (`@range`, `@permission`, etc) and then this would get
476*115816f9SAndroid Build Coastguard Workerconverted into English docs later via `macros_override.cs`.
477*115816f9SAndroid Build Coastguard Worker
478*115816f9SAndroid Build Coastguard WorkerThis it not how metalava does it; it generates the English documentation
479*115816f9SAndroid Build Coastguard Workerdirectly. This was not just convenient for the implementation (since metalava
480*115816f9SAndroid Build Coastguard Workerdoes not use javadoc data structures to pass maps like the arguments for the
481*115816f9SAndroid Build Coastguard Workertypedef macro), but should also help Dokka -- and arguably the Kotlin code which
482*115816f9SAndroid Build Coastguard Workergenerates the documentation is easier to reason about and to update when it's
483*115816f9SAndroid Build Coastguard Workerhandling loop conditionals. (As a result I for example improved some of the
484*115816f9SAndroid Build Coastguard Workergrammar, e.g. when it's listing a number of possible constants the conjunction
485*115816f9SAndroid Build Coastguard Workeris usually "or", but if it's a flag, the sentence begins with "a combination of
486*115816f9SAndroid Build Coastguard Worker" and then the conjunction at the end should be "and").
487