Snap for 8426163 from 12aeb49f0601662baa0e6a140c1759267f50592e to mainline-tzdata2-release

Change-Id: Ic9e876e3286b589eea569005ddb1b16cdb4fb704
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
index e34606c..a5f05cd 100644
--- a/.idea/jarRepositories.xml
+++ b/.idea/jarRepositories.xml
@@ -21,10 +21,5 @@
       <option name="name" value="Google" />
       <option name="url" value="https://dl.google.com/dl/android/maven2/" />
     </remote-repository>
-    <remote-repository>
-      <option name="id" value="MavenRepo" />
-      <option name="name" value="MavenRepo" />
-      <option name="url" value="https://repo.maven.apache.org/maven2/" />
-    </remote-repository>
   </component>
 </project>
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 921deaf..7e90b4c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -12,10 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package {
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
 java_binary_host {
     name: "metalava",
     srcs: [
diff --git a/androidx-studio-integration.sh b/androidx-studio-integration.sh
index 6a982c6..964503e 100755
--- a/androidx-studio-integration.sh
+++ b/androidx-studio-integration.sh
@@ -14,9 +14,10 @@
 export OUT_DIR=out
 export DIST_DIR="$DIST_DIR"
 
-JAVA_HOME="$(pwd)/prebuilts/studio/jdk/jdk11/linux" tools/gradlew -p tools/ publishLocal --stacktrace
+JAVA_HOME="$(pwd)/prebuilts/studio/jdk/linux" tools/gradlew -p tools/ publishLocal --stacktrace
 
 export LINT_VERSION=`grep -oP "(?<=baseVersion = ).*" tools/buildSrc/base/version.properties`
 export LINT_REPO="$(pwd)/out/repo"
 
-tools/gradlew -p tools/metalava --no-daemon --stacktrace -PlintRepo=$LINT_REPO -PlintVersion=$LINT_VERSION
+# Disable building metalava because lint upgraded to kotlin 1.4 and we are not compatible with it.
+# tools/gradlew -p tools/metalava --no-daemon --stacktrace -PlintRepo=$LINT_REPO -PlintVersion=$LINT_VERSION
diff --git a/build.gradle.kts b/build.gradle.kts
index 3cfadfa..2d18ae2 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -8,6 +8,10 @@
 import java.io.FileNotFoundException
 import java.util.Properties
 
+if (JavaVersion.current() != JavaVersion.VERSION_1_8) {
+    throw GradleException("You are using Java ${JavaVersion.current()}, but this build only supports Java 8. Please set your JAVA_HOME to JDK 8")
+}
+
 buildDir = getBuildDirectory()
 
 defaultTasks = mutableListOf(
@@ -20,7 +24,7 @@
 
 repositories {
     google()
-    mavenCentral()
+    jcenter()
     val lintRepo = project.findProperty("lintRepo") as String?
     if (lintRepo != null) {
         logger.warn("Building using custom $lintRepo maven repository")
@@ -31,7 +35,7 @@
 }
 
 plugins {
-    kotlin("jvm") version "1.5.0"
+    kotlin("jvm") version "1.3.72"
     id("application")
     id("java")
     id("maven-publish")
@@ -41,7 +45,7 @@
 version = getMetalavaVersion()
 
 application {
-    mainClass.set("com.android.tools.metalava.Driver")
+    mainClassName = "com.android.tools.metalava.Driver"
     applicationDefaultJvmArgs = listOf("-ea", "-Xms2g", "-Xmx4g")
 }
 
@@ -56,8 +60,8 @@
 
     kotlinOptions {
         jvmTarget = "1.8"
-        apiVersion = "1.4"
-        languageVersion = "1.4"
+        apiVersion = "1.3"
+        languageVersion = "1.3"
         allWarningsAsErrors = true
     }
 }
@@ -67,41 +71,24 @@
     logger.warn("Building using custom $customLintVersion version of Android Lint")
     customLintVersion
 } else {
-    "30.0.0-alpha14"
+    "27.2.0-alpha07"
 }
-val kotlinVersion: String = "1.5.0"
+val kotlinVersion: String = "1.3.72"
 
 dependencies {
     implementation("com.android.tools.external.org-jetbrains:uast:$studioVersion")
-    implementation("com.android.tools.external.com-intellij:kotlin-compiler:$studioVersion")
     implementation("com.android.tools.external.com-intellij:intellij-core:$studioVersion")
     implementation("com.android.tools.lint:lint-api:$studioVersion")
     implementation("com.android.tools.lint:lint-checks:$studioVersion")
     implementation("com.android.tools.lint:lint-gradle:$studioVersion")
     implementation("com.android.tools.lint:lint:$studioVersion")
-    implementation("com.android.tools:common:$studioVersion")
-    implementation("com.android.tools:sdk-common:$studioVersion")
-    implementation("com.android.tools:sdklib:$studioVersion")
     implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion")
     implementation("org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion")
-    implementation("org.ow2.asm:asm:8.0")
-    implementation("org.ow2.asm:asm-tree:8.0")
     testImplementation("com.android.tools.lint:lint-tests:$studioVersion")
     testImplementation("junit:junit:4.11")
-    testImplementation("com.google.truth:truth:1.0")
-    testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion")
 }
 
-val zipTask: TaskProvider<Zip> = project.tasks.register(
-    "zipResultsOf${name.capitalize()}",
-    Zip::class.java
-) {
-    destinationDirectory.set(File(getDistributionDirectory(), "host-test-reports"))
-    archiveFileName.set("metalava-tests.zip")
-}
-
-val testTask = tasks.named("test", Test::class.java)
-testTask.configure {
+tasks.withType(Test::class.java) {
     testLogging.events = hashSetOf(
         TestLogEvent.FAILED,
         TestLogEvent.PASSED,
@@ -109,11 +96,17 @@
         TestLogEvent.STANDARD_OUT,
         TestLogEvent.STANDARD_ERROR
     )
+    val zipTask = project.tasks.register("zipResultsOf${name.capitalize()}", Zip::class.java) {
+        destinationDirectory.set(File(getDistributionDirectory(), "host-test-reports"))
+        archiveFileName.set("metalava-tests.zip")
+    }
     if (isBuildingOnServer()) ignoreFailures = true
     finalizedBy(zipTask)
-}
-zipTask.configure {
-    from(testTask.map { it.reports.junitXml.outputLocation.get() })
+    doFirst {
+        zipTask.configure {
+            from(reports.junitXml.destination)
+        }
+    }
 }
 
 fun getMetalavaVersion(): Any {
@@ -230,16 +223,13 @@
 
 // Workaround for https://github.com/gradle/gradle/issues/11717
 tasks.withType(GenerateModuleMetadata::class.java).configureEach {
-    val outDirProvider = project.providers.environmentVariable("DIST_DIR")
-    inputs.property("buildOutputDirectory", outDirProvider).optional(true)
     doLast {
         val metadata = outputFile.asFile.get()
-        val text = metadata.readText()
-        val buildId = outDirProvider.orNull?.let { File(it).name } ?: "0"
+        var text = metadata.readText()
         metadata.writeText(
             text.replace(
                 "\"buildId\": .*".toRegex(),
-                "\"buildId:\": \"${buildId}\"")
+                "\"buildId:\": \"${getBuildId()}\"")
         )
     }
 }
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index 4c35c32..5f94ee6 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -15,11 +15,11 @@
  */
 
 plugins {
-    kotlin("jvm") version "1.5.0"
+    kotlin("jvm") version "1.3.72"
 }
 
 repositories {
-    mavenCentral()
+    jcenter()
 }
 
 dependencies {
diff --git a/gradle.properties b/gradle.properties
index 04cb68f..e1841e4 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,8 +1,4 @@
 # suppress inspection "UnusedProperty" for whole file
 org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=1024m
 org.gradle.daemon=true
-org.gradle.caching=true
-org.gradle.parallel=true
-org.gradle.vfs.watch=true
-kotlin.incremental=true
 kotlin.incremental.usePreciseJavaTracking=true
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 20e4994..28aa708 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -4,4 +4,4 @@
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip
diff --git a/src/main/java/com/android/tools/metalava/AndroidApiChecks.kt b/src/main/java/com/android/tools/metalava/AndroidApiChecks.kt
index f907b59..ef49b01 100644
--- a/src/main/java/com/android/tools/metalava/AndroidApiChecks.kt
+++ b/src/main/java/com/android/tools/metalava/AndroidApiChecks.kt
@@ -17,6 +17,7 @@
 package com.android.tools.metalava
 
 import com.android.SdkConstants
+import com.android.tools.metalava.doclava1.Issues
 import com.android.tools.metalava.model.AnnotationAttributeValue
 import com.android.tools.metalava.model.ClassItem
 import com.android.tools.metalava.model.Codebase
diff --git a/src/main/java/com/android/tools/metalava/AnnotationStatistics.kt b/src/main/java/com/android/tools/metalava/AnnotationStatistics.kt
index acc6d3f..b9614a8 100644
--- a/src/main/java/com/android/tools/metalava/AnnotationStatistics.kt
+++ b/src/main/java/com/android/tools/metalava/AnnotationStatistics.kt
@@ -17,6 +17,7 @@
 package com.android.tools.metalava
 
 import com.android.SdkConstants
+import com.android.tools.metalava.doclava1.ApiPredicate
 import com.android.tools.metalava.model.ClassItem
 import com.android.tools.metalava.model.Codebase
 import com.android.tools.metalava.model.FieldItem
diff --git a/src/main/java/com/android/tools/metalava/AnnotationsDiffer.kt b/src/main/java/com/android/tools/metalava/AnnotationsDiffer.kt
index f5bba25..6bb1434 100644
--- a/src/main/java/com/android/tools/metalava/AnnotationsDiffer.kt
+++ b/src/main/java/com/android/tools/metalava/AnnotationsDiffer.kt
@@ -16,6 +16,9 @@
 
 package com.android.tools.metalava
 
+import com.android.tools.metalava.doclava1.ApiPredicate
+import com.android.tools.metalava.doclava1.Issues
+import com.android.tools.metalava.doclava1.FilterPredicate
 import com.android.tools.metalava.model.Codebase
 import com.android.tools.metalava.model.Item
 import java.io.File
diff --git a/src/main/java/com/android/tools/metalava/AnnotationsMerger.kt b/src/main/java/com/android/tools/metalava/AnnotationsMerger.kt
index 2879bac..cf91fa3 100644
--- a/src/main/java/com/android/tools/metalava/AnnotationsMerger.kt
+++ b/src/main/java/com/android/tools/metalava/AnnotationsMerger.kt
@@ -120,12 +120,12 @@
             // resolve types in the stubs
             val roots = mutableListOf<File>()
             extractRoots(options.sources, roots)
+            roots.addAll(options.classpath)
             roots.addAll(options.sourcePath)
             val javaStubsCodebase = parseSources(
                 javaStubFiles,
                 "Codebase loaded from stubs",
-                sourcePath = roots,
-                classpath = options.classpath)
+                sourcePath = roots)
             mergeJavaStubsCodebase(javaStubsCodebase)
         }
     }
@@ -257,10 +257,6 @@
                 }
             }
 
-            override fun removed(old: Item, from: Item?) {
-                reporter.report(Issues.UNMATCHED_MERGE_ANNOTATION, old, "qualifier annotations were given for $old but no matching item was found")
-            }
-
             private fun mergeAnnotation(
                 annotation: AnnotationItem,
                 newModifiers: ModifierList,
diff --git a/src/main/java/com/android/tools/metalava/ApiAnalyzer.kt b/src/main/java/com/android/tools/metalava/ApiAnalyzer.kt
index ad84363..d3a6821 100644
--- a/src/main/java/com/android/tools/metalava/ApiAnalyzer.kt
+++ b/src/main/java/com/android/tools/metalava/ApiAnalyzer.kt
@@ -16,6 +16,8 @@
 
 package com.android.tools.metalava
 
+import com.android.tools.metalava.doclava1.ApiPredicate
+import com.android.tools.metalava.doclava1.Issues
 import com.android.tools.metalava.model.AnnotationAttributeValue
 import com.android.tools.metalava.model.ClassItem
 import com.android.tools.metalava.model.Codebase
@@ -890,10 +892,20 @@
                 // but iterating through the type argument classes below will find and
                 // check the component class
                 if (cls != null && !filterReference.test(cls) && !cls.isFromClassPath()) {
-                    reporter.report(
-                        Issues.HIDDEN_TYPE_PARAMETER, item,
-                        "${item.toString().capitalize()} references hidden type $type."
-                    )
+                    if (cls.modifiers.isCompanion() &&
+                        cls.isPrivate &&
+                        cls.containingClass()?.isInterface() == true
+                    ) {
+                        reporter.report(
+                            Issues.PRIVATE_COMPANION, cls, "Do not use private companion " +
+                                "objects inside interfaces as these become public if targeting " +
+                                "Java 8 or older.")
+                    } else {
+                        reporter.report(
+                            Issues.HIDDEN_TYPE_PARAMETER, item,
+                            "${item.toString().capitalize()} references hidden type $type."
+                        )
+                    }
                 }
 
                 type.typeArgumentClasses()
@@ -943,21 +955,8 @@
         // be written, e.g. hidden things
         for (cl in notStrippable) {
             if (!cl.isHiddenOrRemoved()) {
-                val publiclyConstructable =
-                    cl.constructors().any { it.checkLevel() }
                 for (m in cl.methods()) {
                     if (!m.checkLevel()) {
-                        // TODO: enable this check for options.showSingleAnnotations
-                        if (options.showSingleAnnotations.isEmpty() &&
-                            publiclyConstructable && m.modifiers.isAbstract()
-                        ) {
-                            reporter.report(
-                                Issues.HIDDEN_ABSTRACT_METHOD, m,
-                                "${m.name()} cannot be hidden and abstract when " +
-                                    "${cl.simpleName()} has a visible constructor, in case a " +
-                                    "third-party attempts to subclass it."
-                            )
-                        }
                         continue
                     }
                     if (m.isHiddenOrRemoved()) {
diff --git a/src/main/java/com/android/tools/metalava/ApiLint.kt b/src/main/java/com/android/tools/metalava/ApiLint.kt
index e60bada..c6fc9ed 100644
--- a/src/main/java/com/android/tools/metalava/ApiLint.kt
+++ b/src/main/java/com/android/tools/metalava/ApiLint.kt
@@ -46,98 +46,97 @@
 import com.android.resources.ResourceType.TRANSITION
 import com.android.resources.ResourceType.XML
 import com.android.sdklib.SdkVersionInfo
-import com.android.tools.metalava.Issues.ABSTRACT_INNER
-import com.android.tools.metalava.Issues.ACRONYM_NAME
-import com.android.tools.metalava.Issues.ACTION_VALUE
-import com.android.tools.metalava.Issues.ALL_UPPER
-import com.android.tools.metalava.Issues.ANDROID_URI
-import com.android.tools.metalava.Issues.ARRAY_RETURN
-import com.android.tools.metalava.Issues.AUTO_BOXING
-import com.android.tools.metalava.Issues.BAD_FUTURE
-import com.android.tools.metalava.Issues.BANNED_THROW
-import com.android.tools.metalava.Issues.BUILDER_SET_STYLE
-import com.android.tools.metalava.Issues.CALLBACK_INTERFACE
-import com.android.tools.metalava.Issues.CALLBACK_METHOD_NAME
-import com.android.tools.metalava.Issues.CALLBACK_NAME
-import com.android.tools.metalava.Issues.COMMON_ARGS_FIRST
-import com.android.tools.metalava.Issues.COMPILE_TIME_CONSTANT
-import com.android.tools.metalava.Issues.CONCRETE_COLLECTION
-import com.android.tools.metalava.Issues.CONFIG_FIELD_NAME
-import com.android.tools.metalava.Issues.CONSISTENT_ARGUMENT_ORDER
-import com.android.tools.metalava.Issues.CONTEXT_FIRST
-import com.android.tools.metalava.Issues.CONTEXT_NAME_SUFFIX
-import com.android.tools.metalava.Issues.ENDS_WITH_IMPL
-import com.android.tools.metalava.Issues.ENUM
-import com.android.tools.metalava.Issues.EQUALS_AND_HASH_CODE
-import com.android.tools.metalava.Issues.EXCEPTION_NAME
-import com.android.tools.metalava.Issues.EXECUTOR_REGISTRATION
-import com.android.tools.metalava.Issues.EXTENDS_ERROR
-import com.android.tools.metalava.Issues.FORBIDDEN_SUPER_CLASS
-import com.android.tools.metalava.Issues.FRACTION_FLOAT
-import com.android.tools.metalava.Issues.GENERIC_EXCEPTION
-import com.android.tools.metalava.Issues.GETTER_ON_BUILDER
-import com.android.tools.metalava.Issues.GETTER_SETTER_NAMES
-import com.android.tools.metalava.Issues.HEAVY_BIT_SET
-import com.android.tools.metalava.Issues.ILLEGAL_STATE_EXCEPTION
-import com.android.tools.metalava.Issues.INTENT_BUILDER_NAME
-import com.android.tools.metalava.Issues.INTENT_NAME
-import com.android.tools.metalava.Issues.INTERFACE_CONSTANT
-import com.android.tools.metalava.Issues.INTERNAL_CLASSES
-import com.android.tools.metalava.Issues.INTERNAL_FIELD
-import com.android.tools.metalava.Issues.Issue
-import com.android.tools.metalava.Issues.KOTLIN_OPERATOR
-import com.android.tools.metalava.Issues.LISTENER_INTERFACE
-import com.android.tools.metalava.Issues.LISTENER_LAST
-import com.android.tools.metalava.Issues.MANAGER_CONSTRUCTOR
-import com.android.tools.metalava.Issues.MANAGER_LOOKUP
-import com.android.tools.metalava.Issues.MENTIONS_GOOGLE
-import com.android.tools.metalava.Issues.METHOD_NAME_TENSE
-import com.android.tools.metalava.Issues.METHOD_NAME_UNITS
-import com.android.tools.metalava.Issues.MIN_MAX_CONSTANT
-import com.android.tools.metalava.Issues.MISSING_BUILD_METHOD
-import com.android.tools.metalava.Issues.MISSING_GETTER_MATCHING_BUILDER
-import com.android.tools.metalava.Issues.MISSING_NULLABILITY
-import com.android.tools.metalava.Issues.MUTABLE_BARE_FIELD
-import com.android.tools.metalava.Issues.NOT_CLOSEABLE
-import com.android.tools.metalava.Issues.NO_BYTE_OR_SHORT
-import com.android.tools.metalava.Issues.NO_CLONE
-import com.android.tools.metalava.Issues.NO_SETTINGS_PROVIDER
-import com.android.tools.metalava.Issues.NULLABLE_COLLECTION
-import com.android.tools.metalava.Issues.ON_NAME_EXPECTED
-import com.android.tools.metalava.Issues.OPTIONAL_BUILDER_CONSTRUCTOR_ARGUMENT
-import com.android.tools.metalava.Issues.OVERLAPPING_CONSTANTS
-import com.android.tools.metalava.Issues.PACKAGE_LAYERING
-import com.android.tools.metalava.Issues.PAIRED_REGISTRATION
-import com.android.tools.metalava.Issues.PARCELABLE_LIST
-import com.android.tools.metalava.Issues.PARCEL_CONSTRUCTOR
-import com.android.tools.metalava.Issues.PARCEL_CREATOR
-import com.android.tools.metalava.Issues.PARCEL_NOT_FINAL
-import com.android.tools.metalava.Issues.PERCENTAGE_INT
-import com.android.tools.metalava.Issues.PROTECTED_MEMBER
-import com.android.tools.metalava.Issues.PUBLIC_TYPEDEF
-import com.android.tools.metalava.Issues.RAW_AIDL
-import com.android.tools.metalava.Issues.REGISTRATION_NAME
-import com.android.tools.metalava.Issues.RESOURCE_FIELD_NAME
-import com.android.tools.metalava.Issues.RESOURCE_STYLE_FIELD_NAME
-import com.android.tools.metalava.Issues.RESOURCE_VALUE_FIELD_NAME
-import com.android.tools.metalava.Issues.RETHROW_REMOTE_EXCEPTION
-import com.android.tools.metalava.Issues.SERVICE_NAME
-import com.android.tools.metalava.Issues.SETTER_RETURNS_THIS
-import com.android.tools.metalava.Issues.SINGLETON_CONSTRUCTOR
-import com.android.tools.metalava.Issues.SINGLE_METHOD_INTERFACE
-import com.android.tools.metalava.Issues.SINGULAR_CALLBACK
-import com.android.tools.metalava.Issues.START_WITH_LOWER
-import com.android.tools.metalava.Issues.START_WITH_UPPER
-import com.android.tools.metalava.Issues.STATIC_FINAL_BUILDER
-import com.android.tools.metalava.Issues.STATIC_UTILS
-import com.android.tools.metalava.Issues.STREAM_FILES
-import com.android.tools.metalava.Issues.TOP_LEVEL_BUILDER
-import com.android.tools.metalava.Issues.UNIQUE_KOTLIN_OPERATOR
-import com.android.tools.metalava.Issues.USER_HANDLE
-import com.android.tools.metalava.Issues.USER_HANDLE_NAME
-import com.android.tools.metalava.Issues.USE_ICU
-import com.android.tools.metalava.Issues.USE_PARCEL_FILE_DESCRIPTOR
-import com.android.tools.metalava.Issues.VISIBLY_SYNCHRONIZED
+import com.android.tools.metalava.doclava1.Issues.ABSTRACT_INNER
+import com.android.tools.metalava.doclava1.Issues.ACRONYM_NAME
+import com.android.tools.metalava.doclava1.Issues.ACTION_VALUE
+import com.android.tools.metalava.doclava1.Issues.ALL_UPPER
+import com.android.tools.metalava.doclava1.Issues.ANDROID_URI
+import com.android.tools.metalava.doclava1.Issues.ARRAY_RETURN
+import com.android.tools.metalava.doclava1.Issues.AUTO_BOXING
+import com.android.tools.metalava.doclava1.Issues.BAD_FUTURE
+import com.android.tools.metalava.doclava1.Issues.BANNED_THROW
+import com.android.tools.metalava.doclava1.Issues.BUILDER_SET_STYLE
+import com.android.tools.metalava.doclava1.Issues.CALLBACK_INTERFACE
+import com.android.tools.metalava.doclava1.Issues.CALLBACK_METHOD_NAME
+import com.android.tools.metalava.doclava1.Issues.CALLBACK_NAME
+import com.android.tools.metalava.doclava1.Issues.COMMON_ARGS_FIRST
+import com.android.tools.metalava.doclava1.Issues.COMPILE_TIME_CONSTANT
+import com.android.tools.metalava.doclava1.Issues.CONCRETE_COLLECTION
+import com.android.tools.metalava.doclava1.Issues.CONFIG_FIELD_NAME
+import com.android.tools.metalava.doclava1.Issues.CONSISTENT_ARGUMENT_ORDER
+import com.android.tools.metalava.doclava1.Issues.CONTEXT_FIRST
+import com.android.tools.metalava.doclava1.Issues.CONTEXT_NAME_SUFFIX
+import com.android.tools.metalava.doclava1.Issues.ENDS_WITH_IMPL
+import com.android.tools.metalava.doclava1.Issues.ENUM
+import com.android.tools.metalava.doclava1.Issues.EQUALS_AND_HASH_CODE
+import com.android.tools.metalava.doclava1.Issues.EXCEPTION_NAME
+import com.android.tools.metalava.doclava1.Issues.EXECUTOR_REGISTRATION
+import com.android.tools.metalava.doclava1.Issues.EXTENDS_ERROR
+import com.android.tools.metalava.doclava1.Issues.FORBIDDEN_SUPER_CLASS
+import com.android.tools.metalava.doclava1.Issues.FRACTION_FLOAT
+import com.android.tools.metalava.doclava1.Issues.GENERIC_EXCEPTION
+import com.android.tools.metalava.doclava1.Issues.GETTER_ON_BUILDER
+import com.android.tools.metalava.doclava1.Issues.GETTER_SETTER_NAMES
+import com.android.tools.metalava.doclava1.Issues.HEAVY_BIT_SET
+import com.android.tools.metalava.doclava1.Issues.ILLEGAL_STATE_EXCEPTION
+import com.android.tools.metalava.doclava1.Issues.INTENT_BUILDER_NAME
+import com.android.tools.metalava.doclava1.Issues.INTENT_NAME
+import com.android.tools.metalava.doclava1.Issues.INTERFACE_CONSTANT
+import com.android.tools.metalava.doclava1.Issues.INTERNAL_CLASSES
+import com.android.tools.metalava.doclava1.Issues.INTERNAL_FIELD
+import com.android.tools.metalava.doclava1.Issues.Issue
+import com.android.tools.metalava.doclava1.Issues.KOTLIN_OPERATOR
+import com.android.tools.metalava.doclava1.Issues.LISTENER_INTERFACE
+import com.android.tools.metalava.doclava1.Issues.LISTENER_LAST
+import com.android.tools.metalava.doclava1.Issues.MANAGER_CONSTRUCTOR
+import com.android.tools.metalava.doclava1.Issues.MANAGER_LOOKUP
+import com.android.tools.metalava.doclava1.Issues.MENTIONS_GOOGLE
+import com.android.tools.metalava.doclava1.Issues.METHOD_NAME_TENSE
+import com.android.tools.metalava.doclava1.Issues.METHOD_NAME_UNITS
+import com.android.tools.metalava.doclava1.Issues.MIN_MAX_CONSTANT
+import com.android.tools.metalava.doclava1.Issues.MISSING_BUILD_METHOD
+import com.android.tools.metalava.doclava1.Issues.MISSING_GETTER_MATCHING_BUILDER
+import com.android.tools.metalava.doclava1.Issues.MISSING_NULLABILITY
+import com.android.tools.metalava.doclava1.Issues.MUTABLE_BARE_FIELD
+import com.android.tools.metalava.doclava1.Issues.NOT_CLOSEABLE
+import com.android.tools.metalava.doclava1.Issues.NO_BYTE_OR_SHORT
+import com.android.tools.metalava.doclava1.Issues.NO_CLONE
+import com.android.tools.metalava.doclava1.Issues.NO_SETTINGS_PROVIDER
+import com.android.tools.metalava.doclava1.Issues.ON_NAME_EXPECTED
+import com.android.tools.metalava.doclava1.Issues.OPTIONAL_BUILDER_CONSTRUCTOR_ARGUMENT
+import com.android.tools.metalava.doclava1.Issues.OVERLAPPING_CONSTANTS
+import com.android.tools.metalava.doclava1.Issues.PACKAGE_LAYERING
+import com.android.tools.metalava.doclava1.Issues.PAIRED_REGISTRATION
+import com.android.tools.metalava.doclava1.Issues.PARCELABLE_LIST
+import com.android.tools.metalava.doclava1.Issues.PARCEL_CONSTRUCTOR
+import com.android.tools.metalava.doclava1.Issues.PARCEL_CREATOR
+import com.android.tools.metalava.doclava1.Issues.PARCEL_NOT_FINAL
+import com.android.tools.metalava.doclava1.Issues.PERCENTAGE_INT
+import com.android.tools.metalava.doclava1.Issues.PROTECTED_MEMBER
+import com.android.tools.metalava.doclava1.Issues.PUBLIC_TYPEDEF
+import com.android.tools.metalava.doclava1.Issues.RAW_AIDL
+import com.android.tools.metalava.doclava1.Issues.REGISTRATION_NAME
+import com.android.tools.metalava.doclava1.Issues.RESOURCE_FIELD_NAME
+import com.android.tools.metalava.doclava1.Issues.RESOURCE_STYLE_FIELD_NAME
+import com.android.tools.metalava.doclava1.Issues.RESOURCE_VALUE_FIELD_NAME
+import com.android.tools.metalava.doclava1.Issues.RETHROW_REMOTE_EXCEPTION
+import com.android.tools.metalava.doclava1.Issues.SERVICE_NAME
+import com.android.tools.metalava.doclava1.Issues.SETTER_RETURNS_THIS
+import com.android.tools.metalava.doclava1.Issues.SINGLETON_CONSTRUCTOR
+import com.android.tools.metalava.doclava1.Issues.SINGLE_METHOD_INTERFACE
+import com.android.tools.metalava.doclava1.Issues.SINGULAR_CALLBACK
+import com.android.tools.metalava.doclava1.Issues.START_WITH_LOWER
+import com.android.tools.metalava.doclava1.Issues.START_WITH_UPPER
+import com.android.tools.metalava.doclava1.Issues.STATIC_FINAL_BUILDER
+import com.android.tools.metalava.doclava1.Issues.STATIC_UTILS
+import com.android.tools.metalava.doclava1.Issues.STREAM_FILES
+import com.android.tools.metalava.doclava1.Issues.TOP_LEVEL_BUILDER
+import com.android.tools.metalava.doclava1.Issues.UNIQUE_KOTLIN_OPERATOR
+import com.android.tools.metalava.doclava1.Issues.USER_HANDLE
+import com.android.tools.metalava.doclava1.Issues.USER_HANDLE_NAME
+import com.android.tools.metalava.doclava1.Issues.USE_ICU
+import com.android.tools.metalava.doclava1.Issues.USE_PARCEL_FILE_DESCRIPTOR
+import com.android.tools.metalava.doclava1.Issues.VISIBLY_SYNCHRONIZED
 import com.android.tools.metalava.model.AnnotationItem
 import com.android.tools.metalava.model.AnnotationItem.Companion.getImplicitNullness
 import com.android.tools.metalava.model.ClassItem
@@ -186,10 +185,6 @@
             return
         }
 
-        if (item is ParameterItem && item.containingMethod().deprecated) {
-            return
-        }
-
         // With show annotations we might be flagging API that is filtered out: hide these here
         val testItem = if (item is ParameterItem) item.containingMethod() else item
         if (!filterEmit.test(testItem)) {
@@ -200,6 +195,8 @@
     }
 
     private fun check() {
+        val prevCount = reporter.totalCount
+
         if (oldCodebase != null) {
             // Only check the new APIs
             CodebaseComparator().compare(object : ComparisonVisitor() {
@@ -211,6 +208,36 @@
             // No previous codebase to compare with: visit the whole thing
             codebase.accept(this)
         }
+
+        val apiLintIssues = reporter.totalCount - prevCount
+        if (apiLintIssues > 0) {
+            // We've reported API lint violations; emit some verbiage to explain
+            // how to suppress the error rules.
+            options.stdout.println("\n$apiLintIssues new API lint issues were found.")
+            val baseline = options.baseline
+            if (baseline?.updateFile != null && baseline.file != null && !baseline.silentUpdate) {
+                options.stdout.println("""
+                ************************************************************
+                Your API changes are triggering API Lint warnings or errors.
+                To make these errors go away, fix the code according to the
+                error and/or warning messages above.
+
+                If it's not possible to do so, there are two workarounds:
+
+                1. You can suppress the errors with @SuppressLint("<id>")
+                2. You can update the baseline by executing the following
+                   command:
+                       cp \
+                       ${baseline.updateFile} \
+                       ${baseline.file}
+                   To submit the revised baseline.txt to the main Android
+                   repository, you will need approval.
+                ************************************************************
+                """.trimIndent())
+            } else {
+                options.stdout.println("See tools/metalava/API-LINT.md for how to handle these.")
+            }
+        }
     }
 
     override fun skip(item: Item): Boolean {
@@ -240,7 +267,6 @@
         val returnType = method.returnType()
         if (returnType != null) {
             checkType(returnType, method)
-            checkNullableCollections(returnType, method)
         }
         for (parameter in method.parameters()) {
             checkType(parameter.type(), parameter)
@@ -327,7 +353,6 @@
         checkServices(field)
         checkFieldName(field)
         checkSettingKeys(field)
-        checkNullableCollections(field.type(), field)
     }
 
     private fun checkMethod(
@@ -480,12 +505,6 @@
                         if f.typ in req and f.value is None:
                             error(clazz, f, None, "All constants must be defined at compile time")
          */
-
-        // Skip this check on Kotlin
-        if (field.isKotlin()) {
-            return
-        }
-
         // Existing violations
         val qualified = field.containingClass().qualifiedName()
         if (qualified.startsWith("android.os.Build") ||
@@ -592,18 +611,12 @@
             else -> return
         }
         val methodName = method.name()
-
         if (!onCallbackNamePattern.matches(methodName)) {
             report(
                 CALLBACK_METHOD_NAME, method,
                 "$kind method names must follow the on<Something> style: $methodName"
             )
         }
-
-        for (parameter in method.parameters()) {
-            // We require nonnull collections as parameters to callback methods
-            checkNullableCollections(parameter.type(), parameter)
-        }
     }
 
     private fun checkListeners(cls: ClassItem, methods: Sequence<MethodItem>) {
@@ -697,10 +710,6 @@
         if (!(name.contains("_ACTION") || name.contains("ACTION_") || value.contains(".action."))) {
             return
         }
-        val className = field.containingClass().qualifiedName()
-        when (className) {
-            "android.Manifest.permission" -> return
-        }
         if (!name.startsWith("ACTION_")) {
             report(
                 INTENT_NAME, field,
@@ -708,7 +717,7 @@
             )
             return
         }
-        val prefix = when (className) {
+        val prefix = when (field.containingClass().qualifiedName()) {
             "android.content.Intent" -> "android.intent.action"
             "android.provider.Settings" -> "android.settings"
             "android.app.admin.DevicePolicyManager", "android.app.admin.DeviceAdminReceiver" -> "android.app.action"
@@ -995,7 +1004,7 @@
             report(INTERNAL_FIELD, field,
                     "Internal field ${field.name()} must not be exposed")
         }
-        if (constantNamePattern.matches(field.name()) && field.isJava()) {
+        if (constantNamePattern.matches(field.name())) {
             if (!modifiers.isStatic() || !modifiers.isFinal()) {
                 report(ALL_UPPER, field,
                         "Constant ${field.name()} must be marked static final")
@@ -1369,8 +1378,7 @@
                 }
             }
         }
-        // Maps each setter to a list of potential getters that would satisfy it.
-        val expectedGetters = mutableListOf<Pair<Item, Set<String>>>()
+        val expectedGetters = mutableListOf<Pair<Item, String>>()
         var builtType: TypeItem? = null
         val clsType = cls.toType().toTypeString()
 
@@ -1402,41 +1410,23 @@
                         "Builder setter must be @NonNull: ${method.describe()}"
                     )
                 }
-                val isBool = when (method.parameters().firstOrNull()?.type()?.toTypeString()) {
-                    "boolean", "java.lang.Boolean" -> true
-                    else -> false
+                when {
+                    name.startsWith("set") -> name.removePrefix("set")
+                    name.startsWith("add") -> "${name.removePrefix("add")}s"
+                    else -> null
+                }?.let { getterSuffix ->
+                    val isBool = when (method.parameters().firstOrNull()?.type()?.toTypeString()) {
+                        "boolean", "java.lang.Boolean" -> true
+                        else -> false
+                    }
+                    val expectedGetter = if (isBool && name.startsWith("set")) {
+                        val pattern = goodBooleanGetterSetterPrefixes.match(name, GetterSetterPattern::setter)!!
+                        "${pattern.getter}${name.removePrefix(pattern.setter)}"
+                    } else {
+                        "get$getterSuffix"
+                    }
+                    expectedGetters.add(method to expectedGetter)
                 }
-                val allowedGetters: Set<String>? = if (isBool && name.startsWith("set")) {
-                    val pattern = goodBooleanGetterSetterPrefixes.match(
-                            name, GetterSetterPattern::setter)!!
-                    setOf("${pattern.getter}${name.removePrefix(pattern.setter)}")
-                } else {
-                    when {
-                        name.startsWith("set") -> listOf(name.removePrefix("set"))
-                        name.startsWith("add") -> {
-                            val nameWithoutPrefix = name.removePrefix("add")
-                            when {
-                                name.endsWith("s") -> {
-                                    // If the name ends with s, it may already be a plural. If the
-                                    // add method accepts a single value, it is called addFoo() and
-                                    // getFoos() is right. If an add method accepts a collection, it
-                                    // is called addFoos() and getFoos() is right. So we allow both.
-                                    listOf(nameWithoutPrefix, "${nameWithoutPrefix}es")
-                                }
-                                name.endsWith("sh") || name.endsWith("ch") || name.endsWith("x") ||
-                                        name.endsWith("z") -> listOf("${nameWithoutPrefix}es")
-                                name.endsWith("y") &&
-                                        name[name.length - 2] !in listOf('a', 'e', 'i', 'o', 'u')
-                                -> {
-                                    listOf("${nameWithoutPrefix.removeSuffix("y")}ies")
-                                }
-                                else -> listOf("${nameWithoutPrefix}s")
-                            }
-                        }
-                        else -> null
-                    }?.map { "get$it" }?.toSet()
-                }
-                allowedGetters?.let { expectedGetters.add(method to it) }
             } else {
                 report(
                     BUILDER_SET_STYLE, method,
@@ -1451,21 +1441,13 @@
             )
         }
         builtType?.asClass()?.let { builtClass ->
-            val builtMethods = builtClass.filteredMethods(filterReference, includeSuperClassMethods = true).map { it.name() }.toSet()
-            for ((setter, expectedGetterNames) in expectedGetters) {
-                if (builtMethods.intersect(expectedGetterNames).isEmpty()) {
-                    val expectedGetterCalls = expectedGetterNames.map { "$it()" }
-                    val errorString = if (expectedGetterCalls.size == 1) {
-                        "${builtClass.qualifiedName()} does not declare a " +
-                                "`${expectedGetterCalls.first()}` method matching " +
-                                "${setter.describe()}"
-                    } else {
-                        "${builtClass.qualifiedName()} does not declare a getter method " +
-                                "matching ${setter.describe()} (expected one of: " +
-                                "$expectedGetterCalls)"
-                    }
-                    report(MISSING_GETTER_MATCHING_BUILDER, setter, errorString)
-                }
+            val builtMethods = builtClass.filteredMethods(filterReference).map { it.name() }.toSet()
+            for ((setter, expectedGetterName) in expectedGetters) {
+                if (!builtMethods.contains(expectedGetterName))
+                report(
+                    MISSING_GETTER_MATCHING_BUILDER, setter,
+                    "${builtClass.qualifiedName()} does not declare a `$expectedGetterName()` method matching ${setter.describe()}"
+                )
             }
         }
     }
@@ -1777,42 +1759,6 @@
         }
     }
 
-    private fun checkNullableCollections(type: TypeItem, item: Item) {
-        if (type.primitive) return
-        if (!item.modifiers.isNullable()) return
-        val typeAsClass = type.asClass() ?: return
-
-        val superItem: Item? = when (item) {
-            is MethodItem -> item.findPredicateSuperMethod(filterReference)
-            is ParameterItem -> item.containingMethod().findPredicateSuperMethod(filterReference)
-                    ?.parameters()?.find { it.parameterIndex == item.parameterIndex }
-            else -> null
-        }
-
-        if (superItem?.modifiers?.isNullable() == true) {
-            return
-        }
-
-        if (type.isArray() ||
-                typeAsClass.extendsOrImplements("java.util.Collection") ||
-                typeAsClass.extendsOrImplements("kotlin.collections.Collection") ||
-                typeAsClass.extendsOrImplements("java.util.Map") ||
-                typeAsClass.extendsOrImplements("kotlin.collections.Map") ||
-                typeAsClass.qualifiedName() == "android.os.Bundle" ||
-                typeAsClass.qualifiedName() == "android.os.PersistableBundle") {
-            val where = when (item) {
-                is MethodItem -> "Return type of ${item.describe()}"
-                else -> "Type of ${item.describe()}"
-            }
-
-            val erased = type.toErasedTypeString(item)
-            report(
-                    NULLABLE_COLLECTION, item,
-                    "$where is a nullable collection (`$erased`); must be non-null"
-            )
-        }
-    }
-
     private fun checkFlags(fields: Sequence<FieldItem>) {
         /*
             def verify_flags(clazz):
@@ -2020,9 +1966,6 @@
                 // for Foo<Bar>, Bar does.
                 return // Do not enforce nullability for generics
             }
-            if (item is MethodItem && item.isKotlinProperty()) {
-                return // kotlinc doesn't add nullability https://youtrack.jetbrains.com/issue/KT-45771
-            }
             val where = when (item) {
                 is ParameterItem -> "parameter `${item.name()}` in method `${item.parent()?.name()}`"
                 is FieldItem -> {
@@ -2087,8 +2030,7 @@
                 "java.lang.Float",
                 "java.lang.Integer",
                 "java.lang.Long",
-                "java.lang.Short",
-                "java.lang.Boolean" ->
+                "java.lang.Short" ->
                     true
                 else ->
                     false
@@ -2879,6 +2821,43 @@
     }
 
     private fun checkUnits(method: MethodItem) {
+        /*
+            def verify_units(clazz):
+                """Verifies that we use consistent naming for units."""
+
+                # If we find K, recommend replacing with V
+                bad = {
+                    "Ns": "Nanos",
+                    "Ms": "Millis or Micros",
+                    "Sec": "Seconds", "Secs": "Seconds",
+                    "Hr": "Hours", "Hrs": "Hours",
+                    "Mo": "Months", "Mos": "Months",
+                    "Yr": "Years", "Yrs": "Years",
+                    "Byte": "Bytes", "Space": "Bytes",
+                }
+
+                for m in clazz.methods:
+                    if m.typ not in ["short","int","long"]: continue
+                    for k, v in bad.iteritems():
+                        if m.name.endswith(k):
+                            error(clazz, m, None, "Expected method name units to be " + v)
+                    if m.name.endswith("Nanos") or m.name.endswith("Micros"):
+                        warn(clazz, m, None, "Returned time values are strongly encouraged to be in milliseconds unless you need the extra precision")
+                    if m.name.endswith("Seconds"):
+                        error(clazz, m, None, "Returned time values must be in milliseconds")
+
+                for m in clazz.methods:
+                    typ = m.typ
+                    if typ == "void":
+                        if len(m.args) != 1: continue
+                        typ = m.args[0]
+
+                    if m.name.endswith("Fraction") and typ != "float":
+                        error(clazz, m, None, "Fractions must use floats")
+                    if m.name.endswith("Percentage") and typ != "int":
+                        error(clazz, m, None, "Percentage must use ints")
+
+        */
         val returnType = method.returnType() ?: return
         var type = returnType.toTypeString()
         val name = method.name()
@@ -2890,6 +2869,16 @@
                     METHOD_NAME_UNITS, method,
                     "Expected method name units to be `$value`, was `$badUnit` in `$name`"
                 )
+            } else if (name.endsWith("Nanos") || name.endsWith("Micros")) {
+                report(
+                    METHOD_NAME_UNITS, method,
+                    "Returned time values are strongly encouraged to be in milliseconds unless you need the extra precision, was `$name`"
+                )
+            } else if (name.endsWith("Seconds")) {
+                report(
+                    METHOD_NAME_UNITS, method,
+                    "Returned time values must be in milliseconds, was `$name`"
+                )
             }
         } else if (type == "void") {
             if (method.parameters().size != 1) {
@@ -2897,12 +2886,12 @@
             }
             type = method.parameters()[0].type().toTypeString()
         }
-        if (name.endsWith("Fraction") && (type == "int" || type == "long" || type == "short")) {
+        if (name.endsWith("Fraction") && type != "float") {
             report(
                 FRACTION_FLOAT, method,
                 "Fractions must use floats, was `$type` in `$name`"
             )
-        } else if (name.endsWith("Percentage") && (type == "float" || type == "double")) {
+        } else if (name.endsWith("Percentage") && type != "int") {
             report(
                 PERCENTAGE_INT, method,
                 "Percentage must use ints, was `$type` in `$name`"
@@ -3110,7 +3099,7 @@
 
          */
 
-        if (!type.isArray() || (item is ParameterItem && item.isVarArgs())) {
+        if (!type.isArray() || typeString.endsWith("...")) {
             return
         }
 
@@ -3698,13 +3687,13 @@
         private val constantNamePattern = Regex("[A-Z0-9_]+")
         private val internalNamePattern = Regex("[ms][A-Z0-9].*")
         private val fieldNamePattern = Regex("[a-z].*")
-        private val onCallbackNamePattern = Regex("on[A-Z][a-z0-9][a-zA-Z0-9]*")
-        private val configFieldPattern = Regex("config_[a-z][a-zA-Z0-9]*")
-        private val layoutFieldPattern = Regex("layout_[a-z][a-zA-Z0-9]*")
+        private val onCallbackNamePattern = Regex("on[A-Z][a-z][a-zA-Z1-9]*")
+        private val configFieldPattern = Regex("config_[a-z][a-zA-Z1-9]*")
+        private val layoutFieldPattern = Regex("layout_[a-z][a-zA-Z1-9]*")
         private val stateFieldPattern = Regex("state_[a-z_]+")
-        private val resourceFileFieldPattern = Regex("[a-z0-9_]+")
-        private val resourceValueFieldPattern = Regex("[a-z][a-zA-Z0-9]*")
-        private val styleFieldPattern = Regex("[A-Z][A-Za-z0-9]+(_[A-Z][A-Za-z0-9]+?)*")
+        private val resourceFileFieldPattern = Regex("[a-z1-9_]+")
+        private val resourceValueFieldPattern = Regex("[a-z][a-zA-Z1-9]*")
+        private val styleFieldPattern = Regex("[A-Z][A-Za-z1-9]+(_[A-Z][A-Za-z1-9]+?)*")
 
         private val acronymPattern2 = Regex("([A-Z]){2,}")
         private val acronymPattern3 = Regex("([A-Z]){3,}")
@@ -3779,16 +3768,3 @@
         }
     }
 }
-
-internal const val DefaultLintErrorMessage = """
-************************************************************
-Your API changes are triggering API Lint warnings or errors.
-To make these errors go away, fix the code according to the
-error and/or warning messages above.
-
-If it's not possible to do so, there are two workarounds:
-
-1. Suppress the issues with @Suppress("<id>") / @SuppressWarnings("<id>")
-2. Update the baseline passed into metalava
-************************************************************
-"""
\ No newline at end of file
diff --git a/src/main/java/com/android/tools/metalava/ApiType.kt b/src/main/java/com/android/tools/metalava/ApiType.kt
index 228796c..c9372c2 100644
--- a/src/main/java/com/android/tools/metalava/ApiType.kt
+++ b/src/main/java/com/android/tools/metalava/ApiType.kt
@@ -17,6 +17,9 @@
 package com.android.tools.metalava
 
 import com.android.SdkConstants.DOT_TXT
+import com.android.tools.metalava.doclava1.ApiPredicate
+import com.android.tools.metalava.doclava1.ElidingPredicate
+import com.android.tools.metalava.doclava1.FilterPredicate
 import com.android.tools.metalava.model.Codebase
 import com.android.tools.metalava.model.Item
 import java.io.File
diff --git a/src/main/java/com/android/tools/metalava/ArtifactTagger.kt b/src/main/java/com/android/tools/metalava/ArtifactTagger.kt
index 916ace5..3dfb49c 100644
--- a/src/main/java/com/android/tools/metalava/ArtifactTagger.kt
+++ b/src/main/java/com/android/tools/metalava/ArtifactTagger.kt
@@ -18,6 +18,7 @@
 
 import com.android.tools.metalava.model.text.ApiFile
 import com.android.tools.metalava.model.text.ApiParseException
+import com.android.tools.metalava.doclava1.Issues
 import com.android.tools.metalava.model.text.TextCodebase
 import com.android.tools.metalava.model.ClassItem
 import com.android.tools.metalava.model.Codebase
diff --git a/src/main/java/com/android/tools/metalava/Baseline.kt b/src/main/java/com/android/tools/metalava/Baseline.kt
index 6921442..6328976 100644
--- a/src/main/java/com/android/tools/metalava/Baseline.kt
+++ b/src/main/java/com/android/tools/metalava/Baseline.kt
@@ -16,6 +16,7 @@
 
 package com.android.tools.metalava
 
+import com.android.tools.metalava.doclava1.Issues
 import com.android.tools.metalava.model.ClassItem
 import com.android.tools.metalava.model.FieldItem
 import com.android.tools.metalava.model.Item
@@ -46,7 +47,6 @@
     val description: String,
     val file: File?,
     var updateFile: File?,
-    // TODO(roosa): unless file == updateFile, existing baselines will be merged into the updateFile regardless of this value
     var merge: Boolean = false,
     private var headerComment: String = "",
     /**
@@ -215,7 +215,9 @@
             val issueId = line.substring(0, idEnd).trim()
             val elementId = line.substring(idEnd + 2, elementEnd).trim()
 
-            val message = lines[i + 1].trim()
+            // Unless merging, we don't need the actual messages since we're only matching by
+            // issue id and API location, so don't bother computing.
+            val message = if (merge) lines[i + 1].trim() else ""
 
             val issue = Issues.findIssueById(issueId)
             if (issue == null) {
diff --git a/src/main/java/com/android/tools/metalava/ComparisonVisitor.kt b/src/main/java/com/android/tools/metalava/ComparisonVisitor.kt
index d131508..f6198e7 100644
--- a/src/main/java/com/android/tools/metalava/ComparisonVisitor.kt
+++ b/src/main/java/com/android/tools/metalava/ComparisonVisitor.kt
@@ -23,7 +23,6 @@
 import com.android.tools.metalava.model.FieldItem
 import com.android.tools.metalava.model.Item
 import com.android.tools.metalava.model.MethodItem
-import com.android.tools.metalava.model.MergedCodebase
 import com.android.tools.metalava.model.PackageItem
 import com.android.tools.metalava.model.ParameterItem
 import com.android.tools.metalava.model.PropertyItem
@@ -98,21 +97,7 @@
         println("New:\n${ItemTree.prettyPrint(newTree)}")
         */
 
-        compare(visitor, oldTree, newTree, null, null, filter)
-    }
-
-    fun compare(visitor: ComparisonVisitor, old: MergedCodebase, new: MergedCodebase, filter: Predicate<Item>? = null) {
-        // Algorithm: build up two trees (by nesting level); then visit the
-        // two trees
-        val oldTree = createTree(old, filter)
-        val newTree = createTree(new, filter)
-
-        /* Debugging:
-        println("Old:\n${ItemTree.prettyPrint(oldTree)}")
-        println("New:\n${ItemTree.prettyPrint(newTree)}")
-        */
-
-        compare(visitor, oldTree, newTree, null, null, filter)
+        compare(visitor, oldTree, newTree, null, null)
     }
 
     private fun compare(
@@ -120,8 +105,7 @@
         oldList: List<ItemTree>,
         newList: List<ItemTree>,
         newParent: Item?,
-        oldParent: Item?,
-        filter: Predicate<Item>?
+        oldParent: Item?
     ) {
         // Debugging tip: You can print out a tree like this: ItemTree.prettyPrint(list)
         var index1 = 0
@@ -143,13 +127,13 @@
                         compare > 0 -> {
                             index2++
                             if (new.emit) {
-                                visitAdded(new, oldParent, visitor, newTree, filter)
+                                visitAdded(new, oldParent, visitor, newTree)
                             }
                         }
                         compare < 0 -> {
                             index1++
                             if (old.emit) {
-                                visitRemoved(old, oldTree, visitor, newParent, filter)
+                                visitRemoved(visitor, old, newParent)
                             }
                         }
                         else -> {
@@ -157,16 +141,16 @@
                                 if (old.emit) {
                                     visitCompare(visitor, old, new)
                                 } else {
-                                    visitAdded(new, oldParent, visitor, newTree, filter)
+                                    visitAdded(new, oldParent, visitor, newTree)
                                 }
                             } else {
                                 if (old.emit) {
-                                    visitRemoved(old, oldTree, visitor, newParent, filter)
+                                    visitRemoved(visitor, old, newParent)
                                 }
                             }
 
                             // Compare the children (recurse)
-                            compare(visitor, oldTree.children, newTree.children, newTree.item(), oldTree.item(), filter)
+                            compare(visitor, oldTree.children, newTree.children, newTree.item(), oldTree.item())
 
                             index1++
                             index2++
@@ -175,9 +159,7 @@
                 } else {
                     // All the remaining items in oldList have been deleted
                     while (index1 < length1) {
-                        val oldTree = oldList[index1++]
-                        val old = oldTree.item()
-                        visitRemoved(old, oldTree, visitor, newParent, filter)
+                        visitRemoved(visitor, oldList[index1++].item(), newParent)
                     }
                 }
             } else if (index2 < length2) {
@@ -186,7 +168,7 @@
                     val newTree = newList[index2++]
                     val new = newTree.item()
 
-                    visitAdded(new, oldParent, visitor, newTree, filter)
+                    visitAdded(new, oldParent, visitor, newTree)
                 }
             } else {
                 break
@@ -198,8 +180,7 @@
         new: Item,
         oldParent: Item?,
         visitor: ComparisonVisitor,
-        newTree: ItemTree,
-        filter: Predicate<Item>?
+        newTree: ItemTree
     ) {
         // If it's a method, we may not have added a new method,
         // we may simply have inherited it previously and overriding
@@ -221,7 +202,7 @@
             // Compare the children (recurse)
             if (inherited.parameters().isNotEmpty()) {
                 val parameters = inherited.parameters().map { ItemTree(it) }.toList()
-                compare(visitor, parameters, newTree.children, newTree.item(), inherited, filter)
+                compare(visitor, parameters, newTree.children, newTree.item(), inherited)
             }
         } else {
             visitAdded(visitor, new)
@@ -264,66 +245,6 @@
         }
     }
 
-    private fun visitRemoved(
-        old: Item,
-        oldTree: ItemTree,
-        visitor: ComparisonVisitor,
-        newParent: Item?,
-        filter: Predicate<Item>?
-    ) {
-
-        // If it's a method, we may not have removed the method, we may have simply
-        // removed an override and are now inheriting the method from a superclass.
-        // Alternatively, it may have always truly been an inherited method, but if the base
-        // class was hidden then the signature file may have listed the method as being
-        // declared on the subclass
-        val inheritedMethod =
-            if (old is MethodItem && !old.isConstructor() && newParent is ClassItem) {
-                val superMethod = newParent.findPredicateMethodWithSuper(old, filter)
-
-                if (superMethod != null && (filter == null || filter.test(superMethod))) {
-                    superMethod.duplicate(newParent)
-                } else {
-                    null
-                }
-            } else {
-                null
-            }
-
-        if (inheritedMethod != null) {
-            visitCompare(visitor, old, inheritedMethod)
-            // Compare the children (recurse)
-            if (inheritedMethod.parameters().isNotEmpty()) {
-                val parameters = inheritedMethod.parameters().map { ItemTree(it) }.toList()
-                compare(visitor, oldTree.children, parameters, oldTree.item(), inheritedMethod, filter)
-            }
-            return
-        }
-
-        // fields may also be moved to superclasses like methods may
-        val inheritedField =
-            if (old is FieldItem && newParent is ClassItem) {
-                val superField = newParent.findField(
-                    fieldName = old.name(),
-                    includeSuperClasses = true,
-                    includeInterfaces = true)
-
-                if (superField != null && (filter == null || filter.test(superField))) {
-                    superField.duplicate(newParent)
-                } else {
-                    null
-                }
-            } else {
-                null
-            }
-
-        if (inheritedField != null) {
-            visitCompare(visitor, old, inheritedField)
-            return
-        }
-        visitRemoved(visitor, old, newParent)
-    }
-
     @Suppress("USELESS_CAST") // Overloaded visitor methods: be explicit about which one is being invoked
     private fun visitRemoved(visitor: ComparisonVisitor, item: Item, from: Item?) {
         visitor.removed(item, from)
@@ -468,6 +389,13 @@
         }
     }
 
+    private fun ensureSorted(items: MutableList<ItemTree>) {
+        items.sortWith(treeComparator)
+        for (item in items) {
+            ensureSorted(item)
+        }
+    }
+
     private fun ensureSorted(item: ItemTree) {
         item.children.sortWith(treeComparator)
         for (child in item.children) {
@@ -475,92 +403,38 @@
         }
     }
 
-    /**
-     * Sorts and removes duplicate items.
-     * The kept item will be an unhidden item if possible.
-     * Ties are broken in favor of keeping children having lower indices
-     */
-    private fun removeDuplicates(item: ItemTree) {
-        item.children.sortWith(treeComparator)
-        val children = item.children
-        var i = children.count() - 2
-        while (i >= 0) {
-            val child = children[i]
-            val prev = children[i + 1]
-            if (comparator.compare(child.item, prev.item) == 0) {
-                if (prev.item!!.emit && !child.item!!.emit) {
-                    // merge child into prev because prev is emitted
-                    prev.children += child.children
-                    children.removeAt(i)
-                } else {
-                    // merge prev into child because child was specified first
-                    child.children += prev.children
-                    children.removeAt(i + 1)
-                }
-            }
-            i--
-        }
-        for (child in children) {
-            removeDuplicates(child)
-        }
-    }
-
-    private fun createTree(codebase: MergedCodebase, filter: Predicate<Item>? = null): List<ItemTree> {
-        return createTree(codebase.children, filter)
-    }
-
     private fun createTree(codebase: Codebase, filter: Predicate<Item>? = null): List<ItemTree> {
-        return createTree(listOf(codebase), filter)
-    }
-
-    private fun createTree(codebases: List<Codebase>, filter: Predicate<Item>? = null): List<ItemTree> {
         val stack = Stack<ItemTree>()
         val root = ItemTree(null)
         stack.push(root)
 
-        for (codebase in codebases) {
-            val acceptAll = codebase.preFiltered || filter == null
-            val predicate = if (acceptAll) Predicate { true } else filter!!
-            codebase.accept(object : ApiVisitor(
-                nestInnerClasses = true,
-                inlineInheritedFields = true,
-                filterEmit = predicate,
-                filterReference = predicate,
-                // Whenever a caller passes arguments of "--show-annotation 'SomeAnnotation' --check-compatibility:api:released $oldApi",
-                // really what they mean is:
-                // 1. Definitions:
-                //  1.1 Define the SomeAnnotation API as the set of APIs that are either public or are annotated with @SomeAnnotation
-                //  1.2 $oldApi was previously the difference between the SomeAnnotation api and the public api
-                // 2. The caller would like Metalava to verify that all APIs that are known to have previously been part of the SomeAnnotation api remain part of the SomeAnnotation api
-                // So, when doing compatibility checking we want to consider public APIs even if the caller didn't explicitly pass --show-unannotated
-                showUnannotated = true
-            ) {
-                override fun visitItem(item: Item) {
-                    val node = ItemTree(item)
-                    val parent = stack.peek()
-                    parent.children += node
+        val acceptAll = codebase.preFiltered || filter == null
+        val predicate = if (acceptAll) Predicate { true } else filter!!
+        codebase.accept(object : ApiVisitor(
+            nestInnerClasses = true,
+            inlineInheritedFields = true,
+            filterEmit = predicate,
+            filterReference = predicate
+        ) {
+            override fun visitItem(item: Item) {
+                val node = ItemTree(item)
+                val parent = stack.peek()
+                parent.children += node
 
-                    stack.push(node)
-                }
+                stack.push(node)
+            }
 
-                override fun include(cls: ClassItem): Boolean = if (acceptAll) true else super.include(cls)
+            override fun include(cls: ClassItem): Boolean = if (acceptAll) true else super.include(cls)
 
-                /** Include all classes in the tree, even implicitly defined classes (such as containing classes) */
-                override fun shouldEmitClass(vc: VisitCandidate): Boolean = true
+            /** Include all classes in the tree, even implicitly defined classes (such as containing classes) */
+            override fun shouldEmitClass(vc: VisitCandidate): Boolean = true
 
-                override fun afterVisitItem(item: Item) {
-                    stack.pop()
-                }
-            })
-        }
+            override fun afterVisitItem(item: Item) {
+                stack.pop()
+            }
+        })
 
-        if (codebases.count() >= 2) {
-            removeDuplicates(root)
-            // removeDuplicates will also sort the items
-        } else {
-            ensureSorted(root)
-        }
-
+        ensureSorted(root.children)
         return root.children
     }
 
diff --git a/src/main/java/com/android/tools/metalava/Compatibility.kt b/src/main/java/com/android/tools/metalava/Compatibility.kt
index e7000bd..32f5a1e 100644
--- a/src/main/java/com/android/tools/metalava/Compatibility.kt
+++ b/src/main/java/com/android/tools/metalava/Compatibility.kt
@@ -107,6 +107,12 @@
     /** Whether signature files and stubs should contain annotations */
     var annotationsInSignatures: Boolean = !compat
 
+    /** Emit errors in the old API diff format */
+    var oldErrorOutputFormat: Boolean = false
+
+    /** Whether to include the exit <b>code</b> in the error output next to the id */
+    var includeExitCode = oldErrorOutputFormat
+
     /**
      * When a public class implementing a public interface inherits the implementation
      * of a method in that interface from a hidden super class, the method must be
diff --git a/src/main/java/com/android/tools/metalava/CompatibilityCheck.kt b/src/main/java/com/android/tools/metalava/CompatibilityCheck.kt
index 3f8ba9e..db2c4e9 100644
--- a/src/main/java/com/android/tools/metalava/CompatibilityCheck.kt
+++ b/src/main/java/com/android/tools/metalava/CompatibilityCheck.kt
@@ -18,7 +18,9 @@
 
 import com.android.tools.metalava.NullnessMigration.Companion.findNullnessAnnotation
 import com.android.tools.metalava.NullnessMigration.Companion.isNullable
-import com.android.tools.metalava.Issues.Issue
+import com.android.tools.metalava.doclava1.ApiPredicate
+import com.android.tools.metalava.doclava1.Issues
+import com.android.tools.metalava.doclava1.Issues.Issue
 import com.android.tools.metalava.model.text.TextCodebase
 import com.android.tools.metalava.model.AnnotationItem
 import com.android.tools.metalava.model.ClassItem
@@ -26,7 +28,6 @@
 import com.android.tools.metalava.model.FieldItem
 import com.android.tools.metalava.model.Item
 import com.android.tools.metalava.model.Item.Companion.describe
-import com.android.tools.metalava.model.MergedCodebase
 import com.android.tools.metalava.model.MethodItem
 import com.android.tools.metalava.model.PackageItem
 import com.android.tools.metalava.model.ParameterItem
@@ -81,29 +82,25 @@
 
     var foundProblems = false
 
-    private fun containingMethod(item: Item): MethodItem? {
-        if (item is MethodItem) {
-            return item
+    override fun compare(old: Item, new: Item) {
+        val oldModifiers = old.modifiers
+        val newModifiers = new.modifiers
+        if (oldModifiers.isOperator() && !newModifiers.isOperator()) {
+            report(
+                Issues.OPERATOR_REMOVAL,
+                new,
+                "Cannot remove `operator` modifier from ${describe(new)}: Incompatible change"
+            )
         }
-        if (item is ParameterItem) {
-            return item.containingMethod()
-        }
-        return null
-    }
 
-    private fun compareNullability(old: Item, new: Item) {
-        val oldMethod = containingMethod(old)
-        val newMethod = containingMethod(new)
-
-        if (oldMethod != null && newMethod != null) {
-            if (oldMethod.containingClass().qualifiedName() != newMethod.containingClass().qualifiedName() || ((oldMethod.inheritedFrom != null) != (newMethod.inheritedFrom != null))) {
-                // If the old method and new method are defined on different classes, then it's possible
-                // that the old method was previously overridden and we omitted it.
-                // So, if the old method and new methods are defined on different classes, then we skip
-                // nullability checks
-                return
-            }
+        if (oldModifiers.isInfix() && !newModifiers.isInfix()) {
+            report(
+                Issues.INFIX_REMOVAL,
+                new,
+                "Cannot remove `infix` modifier from ${describe(new)}: Incompatible change"
+            )
         }
+
         // Should not remove nullness information
         // Can't change information incompatibly
         val oldNullnessAnnotation = findNullnessAnnotation(old)
@@ -153,28 +150,6 @@
         }
     }
 
-    override fun compare(old: Item, new: Item) {
-        val oldModifiers = old.modifiers
-        val newModifiers = new.modifiers
-        if (oldModifiers.isOperator() && !newModifiers.isOperator()) {
-            report(
-                Issues.OPERATOR_REMOVAL,
-                new,
-                "Cannot remove `operator` modifier from ${describe(new)}: Incompatible change"
-            )
-        }
-
-        if (oldModifiers.isInfix() && !newModifiers.isInfix()) {
-            report(
-                Issues.INFIX_REMOVAL,
-                new,
-                "Cannot remove `infix` modifier from ${describe(new)}: Incompatible change"
-            )
-        }
-
-        compareNullability(old, new)
-    }
-
     override fun compare(old: ParameterItem, new: ParameterItem) {
         val prevName = old.publicName() ?: return
         val newName = new.publicName()
@@ -255,14 +230,6 @@
             )
         }
 
-        if (oldModifiers.isFunctional() && !newModifiers.isFunctional()) {
-            report(
-                Issues.FUN_REMOVAL,
-                new,
-                "Cannot remove 'fun' modifier from ${describe(new)}: source incompatible change"
-            )
-        }
-
         // Check for changes in final & static, but not in enums (since PSI and signature files differ
         // a bit in whether they include these for enums
         if (!new.isEnum()) {
@@ -435,14 +402,7 @@
                     new,
                     capitalize = true
                 )} has changed value from $prevString to $newString"
-
-                // Adding a default value to an annotation method is safe
-                val annotationMethodAddingDefaultValue =
-                    new.containingClass().isAnnotationType() && old.defaultValue().isEmpty()
-
-                if (!annotationMethodAddingDefaultValue) {
-                    report(Issues.CHANGED_VALUE, new, message)
-                }
+                report(Issues.CHANGED_VALUE, new, message)
             }
         }
 
@@ -697,11 +657,6 @@
             return
         }
 
-        if (!filterReference.test(item)) {
-            // This item is something we weren't asked to verify
-            return
-        }
-
         var message = "Added ${describe(item)}"
 
         // Clarify error message for removed API to make it less ambiguous
@@ -735,6 +690,23 @@
             return
         }
 
+        if (base != null) {
+            // We're diffing "overlay" APIs, such as system or test API files,
+            // where the signature files only list a delta from the full, "base" API.
+            // In that case, if an API is promoted from @SystemApi or @TestApi to be
+            // a full part of the API, it will look like a removal; it appeared in the
+            // previous file and not in the new file, but it's not removed, it's just
+            // not a delta anymore.
+            //
+            // For that reason, we also pass in the "base" API in these cases, and when
+            // an item is removed, we also check the full API to see if it's present
+            // there, and if so, this item is not actually deleted.
+            val baseItem = findBaseItem(item)
+            if (baseItem != null && ApiPredicate(ignoreShown = true).test(baseItem)) {
+                return
+            }
+        }
+
         report(issue, item, "Removed ${if (item.deprecated) "deprecated " else ""}${describe(item)}")
     }
 
@@ -895,23 +867,15 @@
             previous: Codebase,
             releaseType: ReleaseType,
             apiType: ApiType,
-            oldBase: Codebase? = null,
-            newBase: Codebase? = null
+            base: Codebase? = null
         ) {
-            val filter = apiType.getReferenceFilter()
-                .or(apiType.getEmitFilter())
-                .or(ApiType.PUBLIC_API.getReferenceFilter())
-                .or(ApiType.PUBLIC_API.getEmitFilter())
-            val checker = CompatibilityCheck(filter, previous, apiType, newBase, getReporterForReleaseType(releaseType))
+            val filter = apiType.getEmitFilter()
+            val checker = CompatibilityCheck(filter, previous, apiType, base, getReporterForReleaseType(releaseType))
             val issueConfiguration = releaseType.getIssueConfiguration()
             val previousConfiguration = configuration
-            // newBase is considered part of the current codebase
-            val currentFullCodebase = MergedCodebase(listOf(newBase, codebase).filterNotNull())
-            // oldBase is considered part of the previous codebase
-            val previousFullCodebase = MergedCodebase(listOf(oldBase, previous).filterNotNull())
             try {
                 configuration = issueConfiguration
-                CodebaseComparator().compare(checker, previousFullCodebase, currentFullCodebase, filter)
+                CodebaseComparator().compare(checker, previous, codebase, filter)
             } finally {
                 configuration = previousConfiguration
             }
diff --git a/src/main/java/com/android/tools/metalava/DocAnalyzer.kt b/src/main/java/com/android/tools/metalava/DocAnalyzer.kt
index a92e5f4..fd7fb6d 100644
--- a/src/main/java/com/android/tools/metalava/DocAnalyzer.kt
+++ b/src/main/java/com/android/tools/metalava/DocAnalyzer.kt
@@ -2,10 +2,12 @@
 
 import com.android.SdkConstants.ATTR_VALUE
 import com.android.sdklib.SdkVersionInfo
+import com.android.sdklib.repository.AndroidSdkHandler
 import com.android.tools.lint.LintCliClient
 import com.android.tools.lint.checks.ApiLookup
 import com.android.tools.lint.detector.api.editDistance
 import com.android.tools.lint.helpers.DefaultJavaEvaluator
+import com.android.tools.metalava.doclava1.Issues
 import com.android.tools.metalava.model.AnnotationAttributeValue
 import com.android.tools.metalava.model.AnnotationItem
 import com.android.tools.metalava.model.ClassItem
@@ -180,8 +182,7 @@
             private fun handleAnnotation(
                 annotation: AnnotationItem,
                 item: Item,
-                depth: Int,
-                visitedClasses: MutableSet<String> = mutableSetOf()
+                depth: Int
             ) {
                 val name = annotation.qualifiedName()
                 if (name == null || name.startsWith(JAVA_LANG_PREFIX)) {
@@ -213,7 +214,6 @@
                     "kotlin.Deprecated" -> handleKotlinDeprecation(annotation, item)
                 }
 
-                visitedClasses.add(name)
                 // Thread annotations are ignored here because they're handled as a group afterwards
 
                 // TODO: Resource type annotations
@@ -225,8 +225,8 @@
                             "Unbounded recursion, processing annotation " +
                                 "${annotation.toSource()} in $item in ${item.compilationUnit()} "
                         )
-                    } else if (nested.qualifiedName() !in visitedClasses) {
-                        handleAnnotation(nested, item, depth + 1, visitedClasses)
+                    } else if (nested.qualifiedName() != annotation.qualifiedName()) {
+                        handleAnnotation(nested, item, depth + 1)
                     }
                 }
             }
@@ -580,7 +580,7 @@
                 if (original != qualified) {
                     qualified.substring(if (qualified[3] == ' ') 4 else 3, qualified.length - 2)
                 } else {
-                    insert
+                    original
                 }
             } else {
                 insert
@@ -683,6 +683,10 @@
                 return super.findResource(relativePath)
             }
 
+            override fun getSdk(): AndroidSdkHandler? {
+                return null
+            }
+
             override fun getCacheDir(name: String?, create: Boolean): File? {
                 if (create && isUnderTest()) {
                     // Pick unique directory during unit tests
diff --git a/src/main/java/com/android/tools/metalava/Driver.kt b/src/main/java/com/android/tools/metalava/Driver.kt
index 20e8756..20f21ee 100644
--- a/src/main/java/com/android/tools/metalava/Driver.kt
+++ b/src/main/java/com/android/tools/metalava/Driver.kt
@@ -32,6 +32,9 @@
 import com.android.tools.lint.detector.api.assertionsEnabled
 import com.android.tools.metalava.CompatibilityCheck.CheckRequest
 import com.android.tools.metalava.apilevels.ApiGenerator
+import com.android.tools.metalava.doclava1.ApiPredicate
+import com.android.tools.metalava.doclava1.FilterPredicate
+import com.android.tools.metalava.doclava1.Issues
 import com.android.tools.metalava.model.ClassItem
 import com.android.tools.metalava.model.Codebase
 import com.android.tools.metalava.model.Item
@@ -67,8 +70,6 @@
 const val PROGRAM_NAME = "metalava"
 const val HELP_PROLOGUE = "$PROGRAM_NAME extracts metadata from source code to generate artifacts such as the " +
     "signature files, the SDK stub files, external annotations etc."
-const val PACKAGE_HTML = "package.html"
-const val OVERVIEW_HTML = "overview.html"
 
 @Suppress("PropertyName") // Can't mark const because trimIndent() :-(
 val BANNER: String = """
@@ -276,13 +277,11 @@
         ApiGenerator.generate(apiLevelJars, androidApiLevelXml, codebase)
     }
 
-    if (options.docStubsDir != null || options.enhanceDocumentation) {
-        if (!codebase.supportsDocumentation()) {
-            error("Codebase does not support documentation, so it cannot be enhanced.")
-        }
+    if (options.docStubsDir != null && codebase.supportsDocumentation()) {
         progress("Enhancing docs: ")
         val docAnalyzer = DocAnalyzer(codebase)
         docAnalyzer.enhance()
+
         val applyApiLevelsXml = options.applyApiLevelsXml
         if (applyApiLevelsXml != null) {
             progress("Applying API levels")
@@ -356,14 +355,6 @@
         ) { printWriter -> DexApiWriter(printWriter, removedDexEmit, removedReference) }
     }
 
-    options.proguard?.let { proguard ->
-        val apiEmit = FilterPredicate(ApiPredicate())
-        val apiReference = ApiPredicate(ignoreShown = true)
-        createReportFile(
-            codebase, proguard, "Proguard file"
-        ) { printWriter -> ProguardWriter(printWriter, apiEmit, apiReference) }
-    }
-
     options.sdkValueDir?.let { dir ->
         dir.mkdirs()
         SdkFileWriter(codebase, dir).generate()
@@ -587,8 +578,7 @@
         throw DriverException("Cannot perform compatibility check of signature file $signatureFile in format ${current.format} without analyzing current codebase with $ARG_FORMAT=${current.format}")
     }
 
-    var newBase: Codebase? = null
-    var oldBase: Codebase? = null
+    var base: Codebase? = null
     val releaseType = check.releaseType
     val apiType = check.apiType
 
@@ -607,17 +597,19 @@
                 kotlinStyleNulls = options.inputKotlinStyleNulls
             )
         } else if (!options.showUnannotated || apiType != ApiType.PUBLIC_API) {
-            if (options.baseApiForCompatCheck != null) {
-                // This option does not make sense with showAnnotation, as the "base" in that case
-                // is the non-annotated APIs.
-                throw DriverException(ARG_CHECK_COMPATIBILITY_BASE_API +
-                    " is not compatible with --showAnnotation.")
+            val apiFile = apiType.getSignatureFile(codebase, "compat-check-signatures-$apiType")
+
+            // Fast path: if the signature files are identical, we're already good!
+            if (apiFile.readText(UTF_8) == signatureFile.readText(UTF_8)) {
+                return
             }
 
-            newBase = codebase
-            oldBase = newBase
+            base = codebase
 
-            codebase
+            SignatureFileLoader.load(
+                file = apiFile,
+                kotlinStyleNulls = options.inputKotlinStyleNulls
+            )
         } else {
             // Fast path: if we've already generated a signature file and it's identical, we're good!
             val apiFile = options.apiFile
@@ -625,21 +617,12 @@
                 return
             }
 
-            val baseApiFile = options.baseApiForCompatCheck
-            if (baseApiFile != null) {
-                oldBase = SignatureFileLoader.load(
-                    file = baseApiFile,
-                    kotlinStyleNulls = options.inputKotlinStyleNulls
-                )
-                newBase = oldBase
-            }
-
             codebase
         }
 
     // If configured, compares the new API with the previous API and reports
     // any incompatibilities.
-    CompatibilityCheck.checkCompatibility(new, current, releaseType, apiType, oldBase, newBase)
+    CompatibilityCheck.checkCompatibility(new, current, releaseType, apiType, base)
 
     // Make sure the text files are identical too? (only applies for *current.txt;
     // last-released is expected to differ)
@@ -908,7 +891,7 @@
     val rootDir = sourceRoots.firstOrNull() ?: sourcePath.firstOrNull() ?: File("").canonicalFile
 
     val units = Extractor.createUnitsForFiles(environment.ideaProject, sources)
-    val packageDocs = gatherPackageJavadoc(sources, sourceRoots)
+    val packageDocs = gatherHiddenPackagesFromJavaDocs(sourcePath)
 
     val codebase = PsiBasedCodebase(rootDir, description)
     codebase.initialize(environment, units, packageDocs)
@@ -1122,12 +1105,9 @@
                 addSourceFiles(list, child)
             }
         }
-    } else if (file.isFile) {
-        when {
-            file.name.endsWith(DOT_JAVA) ||
-            file.name.endsWith(DOT_KT) ||
-            file.name.equals(PACKAGE_HTML) ||
-            file.name.equals(OVERVIEW_HTML) -> list.add(file)
+    } else {
+        if (file.isFile && (file.path.endsWith(DOT_JAVA) || file.path.endsWith(DOT_KT))) {
+            list.add(file)
         }
     }
 }
@@ -1144,44 +1124,94 @@
     return sources.sortedWith(compareBy { it.name })
 }
 
-private fun gatherPackageJavadoc(sources: List<File>, sourceRoots: List<File>): PackageDocs {
-    val packageComments = HashMap<String, String>(100)
-    val overviewHtml = HashMap<String, String>(10)
-    val hiddenPackages = HashSet<String>(100)
-    val sortedSourceRoots = sourceRoots.sortedBy { -it.name.length }
-    for (file in sources) {
+private fun addHiddenPackages(
+    packageToDoc: MutableMap<String, String>,
+    packageToOverview: MutableMap<String, String>,
+    hiddenPackages: MutableSet<String>,
+    file: File,
+    pkg: String
+) {
+    if (FileReadSandbox.isDirectory(file)) {
+        if (skippableDirectory(file)) {
+            return
+        }
+        // Ignore symbolic links during traversal
+        if (java.nio.file.Files.isSymbolicLink(file.toPath())) {
+            reporter.report(
+                Issues.IGNORING_SYMLINK, file,
+                "Ignoring symlink during package.html discovery directory traversal"
+            )
+            return
+        }
+        val files = file.listFiles()
+        if (files != null) {
+            for (child in files) {
+                var subPkg =
+                    if (FileReadSandbox.isDirectory(child))
+                        if (pkg.isEmpty())
+                            child.name
+                        else pkg + "." + child.name
+                    else pkg
+
+                if (subPkg.endsWith("src.main.java")) {
+                    // It looks like the source path was incorrectly configured; make corrections here
+                    // to ensure that we map the package.html files to the real packages.
+                    subPkg = ""
+                }
+
+                addHiddenPackages(packageToDoc, packageToOverview, hiddenPackages, child, subPkg)
+            }
+        }
+    } else if (FileReadSandbox.isFile(file)) {
         var javadoc = false
         val map = when (file.name) {
-            PACKAGE_HTML -> {
-                javadoc = true; packageComments
+            "package.html" -> {
+                javadoc = true; packageToDoc
             }
-            OVERVIEW_HTML -> {
-                overviewHtml
+            "overview.html" -> {
+                packageToOverview
             }
-            else -> continue
+            else -> return
         }
         var contents = Files.asCharSource(file, UTF_8).read()
         if (javadoc) {
             contents = packageHtmlToJavadoc(contents)
         }
 
-        // Figure out the package: if there is a java file in the same directory, get the package
-        // name from the java file. Otherwise, guess from the directory path + source roots.
-        // NOTE: This causes metalava to read files other than the ones explicitly passed to it.
-        var pkg = file.parentFile?.listFiles()
-            ?.filter { it.name.endsWith(DOT_JAVA) }
-            ?.asSequence()?.mapNotNull { findPackage(it) }
-            ?.firstOrNull()
-        if (pkg == null) {
-            // Strip the longest prefix source root.
-            val prefix = sortedSourceRoots.firstOrNull { file.startsWith(it) }?.path ?: ""
-            pkg = file.parentFile.path.substring(prefix.length).trim('/').replace("/", ".")
+        var realPkg = pkg
+        // Sanity check the package; it's computed from the directory name
+        // relative to the source path, but if the real source path isn't
+        // passed in (and is instead some directory containing the source path)
+        // then we compute the wrong package here. Instead, look for an adjacent
+        // java class and pick the package from it
+        for (sibling in file.parentFile?.listFiles() ?: emptyArray()) {
+            if (sibling.path.endsWith(DOT_JAVA)) {
+                val javaPkg = ClassName(sibling.readText()).packageName
+                if (javaPkg != null) {
+                    realPkg = javaPkg
+                    break
+                }
+            }
         }
-        map[pkg] = contents
+
+        map[realPkg] = contents
         if (contents.contains("@hide")) {
-            hiddenPackages.add(pkg)
+            hiddenPackages.add(realPkg)
         }
     }
+}
+
+private fun gatherHiddenPackagesFromJavaDocs(sourcePath: List<File>): PackageDocs {
+    val packageComments = HashMap<String, String>(100)
+    val overviewHtml = HashMap<String, String>(10)
+    val hiddenPackages = HashSet<String>(100)
+    for (file in sourcePath) {
+        if (file.path.isBlank()) {
+            // Ignoring empty paths, which means "no source path search". Use "." for current directory.
+            continue
+        }
+        addHiddenPackages(packageComments, overviewHtml, hiddenPackages, file, "")
+    }
 
     return PackageDocs(packageComments, overviewHtml, hiddenPackages)
 }
diff --git a/src/main/java/com/android/tools/metalava/ElidingPredicate.kt b/src/main/java/com/android/tools/metalava/ElidingPredicate.kt
deleted file mode 100644
index 1dba9b5..0000000
--- a/src/main/java/com/android/tools/metalava/ElidingPredicate.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.metalava
-
-import com.android.tools.metalava.model.Item
-import com.android.tools.metalava.model.MethodItem
-
-import java.util.function.Predicate
-
-/**
- * Filter that will elide exact duplicate methods that are already included
- * in another superclass/interfaces.
- */
-class ElidingPredicate(private val wrapped: Predicate<Item>) : Predicate<Item> {
-
-    override fun test(method: Item): Boolean {
-        // This method should be included, but if it's an exact duplicate
-        // override then we can elide it.
-        return if (method is MethodItem && !method.isConstructor()) {
-            val differentSuper = method.findPredicateSuperMethod(Predicate { test ->
-                // We're looking for included and perfect signature
-                wrapped.test(test) &&
-                    test is MethodItem &&
-                    MethodItem.sameSignature(method, test, false)
-            })
-            differentSuper == null
-        } else {
-            true
-        }
-    }
-}
diff --git a/src/main/java/com/android/tools/metalava/ExtractAnnotations.kt b/src/main/java/com/android/tools/metalava/ExtractAnnotations.kt
index 205c4e4..4acb65f 100644
--- a/src/main/java/com/android/tools/metalava/ExtractAnnotations.kt
+++ b/src/main/java/com/android/tools/metalava/ExtractAnnotations.kt
@@ -19,6 +19,7 @@
 import com.android.SdkConstants
 import com.android.tools.lint.annotations.Extractor
 import com.android.tools.lint.client.api.AnnotationLookup
+import com.android.tools.metalava.doclava1.Issues
 import com.android.tools.metalava.model.AnnotationItem
 import com.android.tools.metalava.model.AnnotationTarget
 import com.android.tools.metalava.model.ClassItem
diff --git a/src/main/java/com/android/tools/metalava/FileFormat.kt b/src/main/java/com/android/tools/metalava/FileFormat.kt
index c38b8df..ed0c4c5 100644
--- a/src/main/java/com/android/tools/metalava/FileFormat.kt
+++ b/src/main/java/com/android/tools/metalava/FileFormat.kt
@@ -29,8 +29,7 @@
     // signature formats should be last to make comparisons work (for example in [configureOptions])
     V1("Doclava signature file", "1.0"),
     V2("Metalava signature file", "2.0"),
-    V3("Metalava signature file", "3.0"),
-    V4("Metalava signature file", "4.0");
+    V3("Metalava signature file", "3.0");
 
     /** Configures the option object such that the output format will be the given format */
     fun configureOptions(options: Options, compatibility: Compatibility) {
@@ -41,7 +40,6 @@
         options.compatOutput = this == V1
         options.outputKotlinStyleNulls = this >= V3
         options.outputDefaultValues = this >= V2
-        options.outputConciseDefaultValues = this >= V4
         compatibility.omitCommonPackages = this >= V2
         options.includeSignatureFormatVersion = this >= V2
     }
@@ -55,7 +53,6 @@
             V1 -> 1
             V2 -> 2
             V3 -> 3
-            V4 -> 4
 
             BASELINE,
             JDIFF,
@@ -76,8 +73,7 @@
         return when (this) {
             V1,
             V2,
-            V3,
-            V4 -> DOT_TXT
+            V3 -> DOT_TXT
 
             BASELINE -> DOT_TXT
 
@@ -95,7 +91,7 @@
     private fun headerPrefix(): String? {
         return when (this) {
             V1 -> null
-            V2, V3, V4 -> "// Signature format: "
+            V2, V3 -> "// Signature format: "
             BASELINE -> "// Baseline format: "
             JDIFF, SINCE_XML -> "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
             UNKNOWN -> null
@@ -103,7 +99,7 @@
     }
 
     fun isSignatureFormat(): Boolean {
-        return this == V1 || this == V2 || this == V3 || this == V4
+        return this == V1 || this == V2 || this == V3
     }
 
     companion object {
diff --git a/src/main/java/com/android/tools/metalava/Issues.kt b/src/main/java/com/android/tools/metalava/Issues.kt
deleted file mode 100644
index 13b7d2c..0000000
--- a/src/main/java/com/android/tools/metalava/Issues.kt
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.tools.metalava
-
-import com.android.sdklib.SdkVersionInfo
-import java.util.ArrayList
-import java.util.HashMap
-import java.util.Locale
-import kotlin.reflect.full.declaredMemberProperties
-
-object Issues {
-    private val allIssues: MutableList<Issue> = ArrayList(300)
-    private val nameToIssue: MutableMap<String, Issue> = HashMap(300)
-
-    val PARSE_ERROR = Issue(Severity.ERROR)
-    // Compatibility issues
-    val ADDED_PACKAGE = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val ADDED_CLASS = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val ADDED_METHOD = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val ADDED_FIELD = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val ADDED_INTERFACE = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val REMOVED_PACKAGE = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val REMOVED_CLASS = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val REMOVED_METHOD = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val REMOVED_FIELD = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val REMOVED_INTERFACE = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val CHANGED_STATIC = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val ADDED_FINAL = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val CHANGED_TRANSIENT = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val CHANGED_VOLATILE = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val CHANGED_TYPE = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val CHANGED_VALUE = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val CHANGED_SUPERCLASS = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val CHANGED_SCOPE = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val CHANGED_ABSTRACT = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val CHANGED_THROWS = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val CHANGED_NATIVE = Issue(Severity.HIDDEN, Category.COMPATIBILITY)
-    val CHANGED_CLASS = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val CHANGED_DEPRECATED = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val CHANGED_SYNCHRONIZED = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val ADDED_FINAL_UNINSTANTIABLE = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val REMOVED_FINAL = Issue(Severity.WARNING, Category.COMPATIBILITY)
-    val REMOVED_DEPRECATED_CLASS = Issue(REMOVED_CLASS, Category.COMPATIBILITY)
-    val REMOVED_DEPRECATED_METHOD = Issue(REMOVED_METHOD, Category.COMPATIBILITY)
-    val REMOVED_DEPRECATED_FIELD = Issue(REMOVED_FIELD, Category.COMPATIBILITY)
-    val ADDED_ABSTRACT_METHOD = Issue(ADDED_METHOD, Category.COMPATIBILITY)
-    val ADDED_REIFIED = Issue(Severity.WARNING, Category.COMPATIBILITY)
-
-    // Issues in javadoc generation
-    val UNRESOLVED_LINK = Issue(Severity.LINT, Category.DOCUMENTATION)
-    val BAD_INCLUDE_TAG = Issue(Severity.LINT, Category.DOCUMENTATION)
-    val UNKNOWN_TAG = Issue(Severity.LINT, Category.DOCUMENTATION)
-    val UNKNOWN_PARAM_TAG_NAME = Issue(Severity.LINT, Category.DOCUMENTATION)
-    val UNDOCUMENTED_PARAMETER = Issue(Severity.HIDDEN, Category.DOCUMENTATION)
-    val BAD_ATTR_TAG = Issue(Severity.LINT, Category.DOCUMENTATION)
-    val BAD_INHERITDOC = Issue(Severity.HIDDEN, Category.DOCUMENTATION)
-    val HIDDEN_LINK = Issue(Severity.LINT, Category.DOCUMENTATION)
-    val HIDDEN_CONSTRUCTOR = Issue(Severity.WARNING, Category.DOCUMENTATION)
-    val UNAVAILABLE_SYMBOL = Issue(Severity.WARNING, Category.DOCUMENTATION)
-    val HIDDEN_SUPERCLASS = Issue(Severity.WARNING, Category.DOCUMENTATION)
-    val DEPRECATED = Issue(Severity.HIDDEN, Category.DOCUMENTATION)
-    val DEPRECATION_MISMATCH = Issue(Severity.ERROR, Category.DOCUMENTATION)
-    val MISSING_COMMENT = Issue(Severity.LINT, Category.DOCUMENTATION)
-    val IO_ERROR = Issue(Severity.ERROR)
-    val NO_SINCE_DATA = Issue(Severity.HIDDEN, Category.DOCUMENTATION)
-    val NO_FEDERATION_DATA = Issue(Severity.WARNING, Category.DOCUMENTATION)
-    val BROKEN_SINCE_FILE = Issue(Severity.ERROR, Category.DOCUMENTATION)
-    val INVALID_CONTENT_TYPE = Issue(Severity.ERROR, Category.DOCUMENTATION)
-    val INVALID_SAMPLE_INDEX = Issue(Severity.ERROR, Category.DOCUMENTATION)
-    val HIDDEN_TYPE_PARAMETER = Issue(Severity.WARNING, Category.DOCUMENTATION)
-    val PRIVATE_SUPERCLASS = Issue(Severity.WARNING, Category.DOCUMENTATION)
-    val NULLABLE = Issue(Severity.HIDDEN, Category.DOCUMENTATION)
-    val INT_DEF = Issue(Severity.HIDDEN, Category.DOCUMENTATION)
-    val REQUIRES_PERMISSION = Issue(Severity.LINT, Category.DOCUMENTATION)
-    val BROADCAST_BEHAVIOR = Issue(Severity.LINT, Category.DOCUMENTATION)
-    val SDK_CONSTANT = Issue(Severity.LINT, Category.DOCUMENTATION)
-    val TODO = Issue(Severity.LINT, Category.DOCUMENTATION)
-    val NO_ARTIFACT_DATA = Issue(Severity.HIDDEN, Category.DOCUMENTATION)
-    val BROKEN_ARTIFACT_FILE = Issue(Severity.ERROR, Category.DOCUMENTATION)
-
-    // Metalava warnings (not from doclava)
-
-    val TYPO = Issue(Severity.WARNING, Category.DOCUMENTATION)
-    val MISSING_PERMISSION = Issue(Severity.LINT, Category.DOCUMENTATION)
-    val MULTIPLE_THREAD_ANNOTATIONS = Issue(Severity.LINT, Category.DOCUMENTATION)
-    val UNRESOLVED_CLASS = Issue(Severity.LINT, Category.DOCUMENTATION)
-    val INVALID_NULL_CONVERSION = Issue(Severity.ERROR, Category.COMPATIBILITY)
-    val PARAMETER_NAME_CHANGE = Issue(Severity.ERROR, Category.COMPATIBILITY)
-    val OPERATOR_REMOVAL = Issue(Severity.ERROR, Category.COMPATIBILITY)
-    val INFIX_REMOVAL = Issue(Severity.ERROR, Category.COMPATIBILITY)
-    val VARARG_REMOVAL = Issue(Severity.ERROR, Category.COMPATIBILITY)
-    val ADD_SEALED = Issue(Severity.ERROR, Category.COMPATIBILITY)
-    val FUN_REMOVAL = Issue(Severity.ERROR, Category.COMPATIBILITY)
-    val ANNOTATION_EXTRACTION = Issue(Severity.ERROR)
-    val SUPERFLUOUS_PREFIX = Issue(Severity.WARNING)
-    val HIDDEN_TYPEDEF_CONSTANT = Issue(Severity.ERROR)
-    val EXPECTED_PLATFORM_TYPE = Issue(Severity.HIDDEN)
-    val INTERNAL_ERROR = Issue(Severity.ERROR)
-    val RETURNING_UNEXPECTED_CONSTANT = Issue(Severity.WARNING)
-    val DEPRECATED_OPTION = Issue(Severity.WARNING)
-    val BOTH_PACKAGE_INFO_AND_HTML = Issue(Severity.WARNING, Category.DOCUMENTATION)
-    val UNMATCHED_MERGE_ANNOTATION = Issue(Severity.WARNING)
-    // The plan is for this to be set as an error once (1) existing code is marked as @deprecated
-    // and (2) the principle is adopted by the API council
-    val REFERENCES_DEPRECATED = Issue(Severity.HIDDEN)
-    val UNHIDDEN_SYSTEM_API = Issue(Severity.ERROR)
-    val SHOWING_MEMBER_IN_HIDDEN_CLASS = Issue(Severity.ERROR)
-    val INVALID_NULLABILITY_ANNOTATION = Issue(Severity.ERROR)
-    val REFERENCES_HIDDEN = Issue(Severity.ERROR)
-    val IGNORING_SYMLINK = Issue(Severity.INFO)
-    val INVALID_NULLABILITY_ANNOTATION_WARNING = Issue(Severity.WARNING)
-    // The plan is for this to be set as an error once (1) existing code is marked as @deprecated
-    // and (2) the principle is adopted by the API council
-    val EXTENDS_DEPRECATED = Issue(Severity.HIDDEN)
-    val FORBIDDEN_TAG = Issue(Severity.ERROR)
-    val MISSING_COLUMN = Issue(Severity.WARNING, Category.DOCUMENTATION)
-    val INVALID_SYNTAX = Issue(Severity.ERROR)
-    val UNRESOLVED_IMPORT = Issue(Severity.INFO)
-    val HIDDEN_ABSTRACT_METHOD = Issue(Severity.ERROR)
-
-    // API lint
-    val START_WITH_LOWER = Issue(Severity.ERROR, Category.API_LINT, "style-conventions")
-    val START_WITH_UPPER = Issue(Severity.ERROR, Category.API_LINT, "style-conventions")
-    val ALL_UPPER = Issue(Severity.ERROR, Category.API_LINT, "constant-naming")
-    val ACRONYM_NAME = Issue(Severity.WARNING, Category.API_LINT, "acronyms-in-method-name")
-    val ENUM = Issue(Severity.ERROR, Category.API_LINT, "avoid-enum")
-    val ENDS_WITH_IMPL = Issue(Severity.ERROR, Category.API_LINT, "dont-end-with-impl")
-    val MIN_MAX_CONSTANT = Issue(Severity.WARNING, Category.API_LINT, "min-max-constants")
-    val COMPILE_TIME_CONSTANT = Issue(Severity.ERROR, Category.API_LINT)
-    val SINGULAR_CALLBACK = Issue(Severity.ERROR, Category.API_LINT, "callback-class-singular")
-    val CALLBACK_NAME = Issue(Severity.WARNING, Category.API_LINT, "observer-should-be-callback")
-    val CALLBACK_INTERFACE =
-        Issue(Severity.ERROR, Category.API_LINT, "callback-abstract-instead-of-interface")
-    val CALLBACK_METHOD_NAME = Issue(Severity.ERROR, Category.API_LINT, "callback-method-naming")
-    val LISTENER_INTERFACE = Issue(Severity.ERROR, Category.API_LINT, "callbacks-listener")
-    val SINGLE_METHOD_INTERFACE = Issue(Severity.ERROR, Category.API_LINT, "callbacks-listener")
-    val INTENT_NAME =
-        Issue(Severity.ERROR, Category.API_LINT, "use-standard-prefixes-for-constants")
-    val ACTION_VALUE = Issue(Severity.ERROR, Category.API_LINT)
-    val EQUALS_AND_HASH_CODE = Issue(Severity.ERROR, Category.API_LINT, "equals-and-hashcode")
-    val PARCEL_CREATOR = Issue(Severity.ERROR, Category.API_LINT, "parcelable-creator")
-    val PARCEL_NOT_FINAL = Issue(Severity.ERROR, Category.API_LINT, "parcelable-final")
-    val PARCEL_CONSTRUCTOR = Issue(Severity.ERROR, Category.API_LINT, "parcelable-creator")
-    val PROTECTED_MEMBER = Issue(Severity.ERROR, Category.API_LINT, "avoid-protected")
-    val PAIRED_REGISTRATION = Issue(Severity.ERROR, Category.API_LINT, "callbacks-symmetry")
-    val REGISTRATION_NAME = Issue(Severity.ERROR, Category.API_LINT, "callbacks-accessors")
-    val VISIBLY_SYNCHRONIZED = Issue(Severity.ERROR, Category.API_LINT, "avoid-synchronized")
-    val INTENT_BUILDER_NAME =
-        Issue(Severity.WARNING, Category.API_LINT, "intent-builder-createintent")
-    val CONTEXT_NAME_SUFFIX = Issue(Severity.ERROR, Category.API_LINT, "classes-subclass-naming")
-    val INTERFACE_CONSTANT = Issue(Severity.ERROR, Category.API_LINT, "services-intents")
-    val ON_NAME_EXPECTED = Issue(Severity.WARNING, Category.API_LINT, "callback-method-naming")
-    val TOP_LEVEL_BUILDER = Issue(Severity.WARNING, Category.API_LINT, "builders-static-inner")
-    val MISSING_BUILD_METHOD =
-        Issue(Severity.WARNING, Category.API_LINT, "builder-must-declare-build")
-    val BUILDER_SET_STYLE = Issue(Severity.WARNING, Category.API_LINT, "builder-method-naming")
-    val SETTER_RETURNS_THIS = Issue(Severity.WARNING, Category.API_LINT)
-    val RAW_AIDL = Issue(Severity.ERROR, Category.API_LINT, "no-public-binder")
-    val INTERNAL_CLASSES = Issue(Severity.ERROR, Category.API_LINT)
-    val PACKAGE_LAYERING = Issue(Severity.WARNING, Category.API_LINT)
-    val GETTER_SETTER_NAMES = Issue(Severity.ERROR, Category.API_LINT)
-    val CONCRETE_COLLECTION = Issue(Severity.ERROR, Category.API_LINT, "classes-collections")
-    val OVERLAPPING_CONSTANTS = Issue(Severity.WARNING, Category.API_LINT, "overlapping-constants")
-    val GENERIC_EXCEPTION = Issue(Severity.ERROR, Category.API_LINT, "appropriate-exception")
-    val ILLEGAL_STATE_EXCEPTION =
-        Issue(Severity.WARNING, Category.API_LINT, "appropriate-exception")
-    val RETHROW_REMOTE_EXCEPTION = Issue(Severity.ERROR, Category.API_LINT, "appropriate-exception")
-    val MENTIONS_GOOGLE = Issue(Severity.ERROR, Category.API_LINT, "mentions-google")
-    val HEAVY_BIT_SET = Issue(Severity.ERROR, Category.API_LINT, "avoid-bitset")
-    val MANAGER_CONSTRUCTOR = Issue(Severity.ERROR, Category.API_LINT)
-    val MANAGER_LOOKUP = Issue(Severity.ERROR, Category.API_LINT)
-    val AUTO_BOXING = Issue(Severity.ERROR, Category.API_LINT, "auto-boxing")
-    val STATIC_UTILS = Issue(Severity.ERROR, Category.API_LINT)
-    val CONTEXT_FIRST = Issue(Severity.ERROR, Category.API_LINT)
-    val LISTENER_LAST = Issue(Severity.WARNING, Category.API_LINT, "placement-of-sam-parameters")
-    val EXECUTOR_REGISTRATION = Issue(Severity.WARNING, Category.API_LINT, "callbacks-listener")
-    val CONFIG_FIELD_NAME = Issue(Severity.ERROR, Category.API_LINT)
-    val RESOURCE_FIELD_NAME = Issue(Severity.ERROR, Category.API_LINT)
-    val RESOURCE_VALUE_FIELD_NAME = Issue(Severity.ERROR, Category.API_LINT)
-    val RESOURCE_STYLE_FIELD_NAME = Issue(Severity.ERROR, Category.API_LINT)
-    val STREAM_FILES = Issue(Severity.WARNING, Category.API_LINT)
-    val PARCELABLE_LIST = Issue(Severity.WARNING, Category.API_LINT)
-    val ABSTRACT_INNER = Issue(Severity.WARNING, Category.API_LINT)
-    val BANNED_THROW = Issue(Severity.ERROR, Category.API_LINT)
-    val EXTENDS_ERROR = Issue(Severity.ERROR, Category.API_LINT)
-    val EXCEPTION_NAME = Issue(Severity.ERROR, Category.API_LINT)
-    val METHOD_NAME_UNITS = Issue(Severity.ERROR, Category.API_LINT, "unit-names")
-    val FRACTION_FLOAT = Issue(Severity.ERROR, Category.API_LINT)
-    val PERCENTAGE_INT = Issue(Severity.ERROR, Category.API_LINT)
-    val NOT_CLOSEABLE = Issue(Severity.WARNING, Category.API_LINT)
-    val KOTLIN_OPERATOR = Issue(Severity.INFO, Category.API_LINT)
-    val ARRAY_RETURN =
-        Issue(Severity.WARNING, Category.API_LINT, "methods-prefer-collection-over-array")
-    val USER_HANDLE = Issue(Severity.WARNING, Category.API_LINT)
-    val USER_HANDLE_NAME = Issue(Severity.WARNING, Category.API_LINT)
-    val SERVICE_NAME = Issue(Severity.ERROR, Category.API_LINT)
-    val METHOD_NAME_TENSE = Issue(Severity.WARNING, Category.API_LINT)
-    val NO_CLONE = Issue(Severity.ERROR, Category.API_LINT, "avoid-clone")
-    val USE_ICU = Issue(Severity.WARNING, Category.API_LINT)
-    val USE_PARCEL_FILE_DESCRIPTOR =
-        Issue(Severity.ERROR, Category.API_LINT, "prefer-parcelfiledescriptor")
-    val NO_BYTE_OR_SHORT = Issue(Severity.WARNING, Category.API_LINT, "avoid-short-byte")
-    val SINGLETON_CONSTRUCTOR = Issue(Severity.ERROR, Category.API_LINT, "singleton-class")
-    val COMMON_ARGS_FIRST = Issue(Severity.WARNING, Category.API_LINT, "optional-params-last")
-    val CONSISTENT_ARGUMENT_ORDER = Issue(Severity.ERROR, Category.API_LINT, "optional-params-last")
-    val KOTLIN_KEYWORD = Issue(Severity.ERROR, Category.API_LINT)
-    val UNIQUE_KOTLIN_OPERATOR = Issue(Severity.ERROR, Category.API_LINT)
-    val SAM_SHOULD_BE_LAST =
-        Issue(Severity.WARNING, Category.API_LINT, "placement-of-sam-parameters")
-    val MISSING_JVMSTATIC = Issue(Severity.WARNING, Category.API_LINT)
-    val DEFAULT_VALUE_CHANGE = Issue(Severity.ERROR, Category.API_LINT, "default-value-removal")
-    val DOCUMENT_EXCEPTIONS = Issue(Severity.ERROR, Category.API_LINT, "docs-throws")
-    val FORBIDDEN_SUPER_CLASS = Issue(Severity.ERROR, Category.API_LINT)
-    val MISSING_NULLABILITY = Issue(Severity.ERROR, Category.API_LINT, "annotations")
-    val MUTABLE_BARE_FIELD = Issue(Severity.ERROR, Category.API_LINT, "mutable-bare-field")
-    val INTERNAL_FIELD = Issue(Severity.ERROR, Category.API_LINT, "internal-fields")
-    val PUBLIC_TYPEDEF = Issue(Severity.ERROR, Category.API_LINT, "no-public-typedefs")
-    val ANDROID_URI = Issue(Severity.ERROR, Category.API_LINT, "android-uri")
-    val BAD_FUTURE = Issue(Severity.ERROR, Category.API_LINT, "bad-future")
-    val STATIC_FINAL_BUILDER = Issue(Severity.WARNING, Category.API_LINT, "builders-static-inner")
-    val GETTER_ON_BUILDER = Issue(Severity.WARNING, Category.API_LINT, "getter-on-builder")
-    val MISSING_GETTER_MATCHING_BUILDER =
-        Issue(Severity.WARNING, Category.API_LINT, "builders-symmetric-setters")
-    val OPTIONAL_BUILDER_CONSTRUCTOR_ARGUMENT =
-        Issue(Severity.WARNING, Category.API_LINT, "builders-nonnull-constructors")
-    val NO_SETTINGS_PROVIDER = Issue(Severity.HIDDEN, Category.API_LINT, "no-settings-provider")
-    val NULLABLE_COLLECTION = Issue(Severity.WARNING, Category.API_LINT, "methods-prefer-non-null-collections")
-
-    fun findIssueById(id: String?): Issue? {
-        return nameToIssue[id]
-    }
-
-    fun findIssueByIdIgnoringCase(id: String): Issue? {
-        for (e in allIssues) {
-            if (id.equals(e.name, ignoreCase = true)) {
-                return e
-            }
-        }
-        return null
-    }
-
-    class Issue private constructor(
-        val defaultLevel: Severity,
-        /**
-         * When `level` is set to [Severity.INHERIT], this is the parent from
-         * which the issue will inherit its level.
-         */
-        val parent: Issue?,
-        /** Applicable category  */
-        val category: Category,
-        /** Related rule, if any  */
-        val rule: String?
-    ) {
-        /**
-         * The name of this issue
-         */
-        lateinit var name: String
-            internal set
-
-        internal constructor(
-            defaultLevel: Severity,
-            category: Category = Category.UNKNOWN
-        ) : this(defaultLevel, null, category, null)
-
-        internal constructor(
-            defaultLevel: Severity,
-            category: Category,
-            rule: String
-        ) : this(defaultLevel, null, category, rule)
-
-        internal constructor(
-            parent: Issue,
-            category: Category
-        ) : this(Severity.INHERIT, parent, category, null)
-
-        override fun toString(): String {
-            return "Issue $name"
-        }
-
-        init {
-            allIssues.add(this)
-        }
-    }
-
-    enum class Category(val description: String, val ruleLink: String?) {
-        COMPATIBILITY("Compatibility", null),
-        DOCUMENTATION("Documentation", null),
-        API_LINT("API Lint", "https://s.android.com/api-guidelines#"),
-        UNKNOWN("Default", null)
-    }
-
-    init { // Initialize issue names based on the field names
-        for (property in Issues::class.declaredMemberProperties) {
-            if (property.returnType.classifier != Issue::class) continue
-            val issue = property.getter.call(Issues) as Issue
-
-            issue.name = SdkVersionInfo.underlinesToCamelCase(property.name.toLowerCase(Locale.US))
-            nameToIssue[issue.name] = issue
-        }
-        for (issue in allIssues) {
-            check(issue.name != "")
-        }
-    }
-}
diff --git a/src/main/java/com/android/tools/metalava/KotlinInteropChecks.kt b/src/main/java/com/android/tools/metalava/KotlinInteropChecks.kt
index 97dc8d2..04f644e 100644
--- a/src/main/java/com/android/tools/metalava/KotlinInteropChecks.kt
+++ b/src/main/java/com/android/tools/metalava/KotlinInteropChecks.kt
@@ -16,6 +16,7 @@
 
 package com.android.tools.metalava
 
+import com.android.tools.metalava.doclava1.Issues
 import com.android.tools.metalava.model.ClassItem
 import com.android.tools.metalava.model.Codebase
 import com.android.tools.metalava.model.FieldItem
@@ -278,10 +279,13 @@
         }
 
         var haveDefault = false
-        for (parameter in parameters) {
-            if (parameter.hasDefaultValue()) {
-                haveDefault = true
-                break
+        if (parameters.isNotEmpty() && method.isJava()) {
+            // Public java parameter names should also not use Kotlin keywords as names
+            for (parameter in parameters) {
+                if (parameter.hasDefaultValue()) {
+                    haveDefault = true
+                    break
+                }
             }
         }
 
diff --git a/src/main/java/com/android/tools/metalava/MarkPackagesAsRecent.kt b/src/main/java/com/android/tools/metalava/MarkPackagesAsRecent.kt
index 2117177..84353be 100644
--- a/src/main/java/com/android/tools/metalava/MarkPackagesAsRecent.kt
+++ b/src/main/java/com/android/tools/metalava/MarkPackagesAsRecent.kt
@@ -16,6 +16,7 @@
 
 package com.android.tools.metalava
 
+import com.android.tools.metalava.doclava1.ApiPredicate
 import com.android.tools.metalava.model.ClassItem
 import com.android.tools.metalava.model.Item
 import com.android.tools.metalava.model.visitors.ApiVisitor
diff --git a/src/main/java/com/android/tools/metalava/NullabilityAnnotationsValidator.kt b/src/main/java/com/android/tools/metalava/NullabilityAnnotationsValidator.kt
index ee650a7..6ac6491 100644
--- a/src/main/java/com/android/tools/metalava/NullabilityAnnotationsValidator.kt
+++ b/src/main/java/com/android/tools/metalava/NullabilityAnnotationsValidator.kt
@@ -16,6 +16,7 @@
 
 package com.android.tools.metalava
 
+import com.android.tools.metalava.doclava1.Issues
 import com.android.tools.metalava.model.AnnotationItem
 import com.android.tools.metalava.model.Codebase
 import com.android.tools.metalava.model.Item
diff --git a/src/main/java/com/android/tools/metalava/Options.kt b/src/main/java/com/android/tools/metalava/Options.kt
index 7a87d67..a376086 100644
--- a/src/main/java/com/android/tools/metalava/Options.kt
+++ b/src/main/java/com/android/tools/metalava/Options.kt
@@ -21,6 +21,7 @@
 import com.android.sdklib.SdkVersionInfo
 import com.android.tools.lint.detector.api.isJdkFolder
 import com.android.tools.metalava.CompatibilityCheck.CheckRequest
+import com.android.tools.metalava.doclava1.Issues
 import com.android.tools.metalava.model.defaultConfiguration
 import com.android.utils.SdkUtils.wrap
 import com.google.common.base.CharMatcher
@@ -81,11 +82,9 @@
 const val ARG_KOTLIN_STUBS = "--kotlin-stubs"
 const val ARG_STUBS_SOURCE_LIST = "--write-stubs-source-list"
 const val ARG_DOC_STUBS_SOURCE_LIST = "--write-doc-stubs-source-list"
-const val ARG_PROGUARD = "--proguard"
 const val ARG_EXTRACT_ANNOTATIONS = "--extract-annotations"
-const val ARG_EXCLUDE_ALL_ANNOTATIONS = "--exclude-all-annotations"
+const val ARG_EXCLUDE_ANNOTATIONS = "--exclude-annotations"
 const val ARG_EXCLUDE_DOCUMENTATION_FROM_STUBS = "--exclude-documentation-from-stubs"
-const val ARG_ENHANCE_DOCUMENTATION = "--enhance-documentation"
 const val ARG_HIDE_PACKAGE = "--hide-package"
 const val ARG_MANIFEST = "--manifest"
 const val ARG_MIGRATE_NULLNESS = "--migrate-nullness"
@@ -94,7 +93,6 @@
 const val ARG_CHECK_COMPATIBILITY_API_RELEASED = "--check-compatibility:api:released"
 const val ARG_CHECK_COMPATIBILITY_REMOVED_CURRENT = "--check-compatibility:removed:current"
 const val ARG_CHECK_COMPATIBILITY_REMOVED_RELEASED = "--check-compatibility:removed:released"
-const val ARG_CHECK_COMPATIBILITY_BASE_API = "--check-compatibility:base"
 const val ARG_ALLOW_COMPATIBLE_DIFFERENCES = "--allow-compatible-differences"
 const val ARG_NO_NATIVE_DIFF = "--no-native-diff"
 const val ARG_INPUT_KOTLIN_NULLS = "--input-kotlin-nulls"
@@ -148,7 +146,6 @@
 const val ARG_REWRITE_ANNOTATIONS = "--rewrite-annotations"
 const val ARG_INCLUDE_SOURCE_RETENTION = "--include-source-retention"
 const val ARG_PASS_THROUGH_ANNOTATION = "--pass-through-annotation"
-const val ARG_EXCLUDE_ANNOTATION = "--exclude-annotation"
 const val ARG_INCLUDE_SIG_VERSION = "--include-signature-version"
 const val ARG_UPDATE_API = "--only-update-api"
 const val ARG_CHECK_API = "--only-check-api"
@@ -220,8 +217,7 @@
     private val mutableConvertToXmlFiles: MutableList<ConvertFile> = mutableListOf()
     /** Internal list backing [passThroughAnnotations] */
     private val mutablePassThroughAnnotations: MutableSet<String> = mutableSetOf()
-    /** Internal list backing [excludeAnnotations] */
-    private val mutableExcludeAnnotations: MutableSet<String> = mutableSetOf()
+
     /** Ignored flags we've already warned about - store here such that we don't keep reporting them */
     private val alreadyWarned: MutableSet<String> = mutableSetOf()
 
@@ -276,12 +272,6 @@
     var includeDocumentationInStubs = true
 
     /**
-     * Enhance documentation in various ways, for example auto-generating documentation based on
-     * source annotations present in the code. This is implied by --doc-stubs.
-     */
-    var enhanceDocumentation = false
-
-    /**
      * Whether metalava is invoked as part of updating the API files. When this is true, metalava
      * should *cancel* various other flags that are also being passed in, such as --check-compatibility.
      * This is there to ease integration in the build system: for a given target, the build system will
@@ -320,12 +310,6 @@
     /** Whether default values should be included in signature files */
     var outputDefaultValues = !compatOutput
 
-    /**
-     *  Whether only the presence of default values should be included in signature files, and not
-     *  the full body of the default value.
-     */
-    var outputConciseDefaultValues = false // requires V4
-
     /** The output format version being used */
     var outputFormat: FileFormat = if (compatOutput) FileFormat.V1 else FileFormat.V2
 
@@ -438,9 +422,6 @@
     /** Whether code compiled from Kotlin should be emitted as .kt stubs instead of .java stubs */
     var kotlinStubs = false
 
-    /** Proguard Keep list file to write */
-    var proguard: File? = null
-
     /** If set, a file to write an API file to. Corresponds to the --api/-api flag. */
     var apiFile: File? = null
 
@@ -499,9 +480,6 @@
     /** The set of annotation classes that should be passed through unchanged */
     var passThroughAnnotations = mutablePassThroughAnnotations
 
-    /** The set of annotation classes that should be removed from all outputs */
-    var excludeAnnotations = mutableExcludeAnnotations
-
     /**
      * A signature file to migrate nullness data from
      */
@@ -513,9 +491,6 @@
     /** The list of compatibility checks to run */
     val compatibilityChecks: List<CheckRequest> = mutableCompatibilityChecks
 
-    /** The API to use a base for the otherwise checked API during compat checks. */
-    var baseApiForCompatCheck: File? = null
-
     /**
      * When checking signature files, whether compatible differences in signature
      * files are allowed. This is normally not allowed (since it means the next
@@ -596,7 +571,7 @@
     var allBaselines: List<Baseline>
 
     /** If set, metalava will show this error message when "API lint" (i.e. [ARG_API_LINT]) fails. */
-    var errorMessageApiLint: String = DefaultLintErrorMessage
+    var errorMessageApiLint: String? = null
 
     /**
      * If set, metalava will show this error message when "check-compatibility:*:released" fails.
@@ -928,10 +903,9 @@
                 ARG_STUBS_SOURCE_LIST -> stubsSourceList = stringToNewFile(getValue(args, ++index))
                 ARG_DOC_STUBS_SOURCE_LIST -> docStubsSourceList = stringToNewFile(getValue(args, ++index))
 
-                ARG_EXCLUDE_ALL_ANNOTATIONS -> generateAnnotations = false
+                ARG_EXCLUDE_ANNOTATIONS -> generateAnnotations = false
 
                 ARG_EXCLUDE_DOCUMENTATION_FROM_STUBS -> includeDocumentationInStubs = false
-                ARG_ENHANCE_DOCUMENTATION -> enhanceDocumentation = true
 
                 // Note that this only affects stub generation, not signature files.
                 // For signature files, clear the compatibility mode
@@ -945,19 +919,10 @@
                     }
                 }
 
-                ARG_EXCLUDE_ANNOTATION -> {
-                    val annotations = getValue(args, ++index)
-                    annotations.split(",").forEach { path ->
-                        mutableExcludeAnnotations.add(path)
-                    }
-                }
-
                 // Flag used by test suite to avoid including locations in
                 // the output when diffing against golden files
                 "--omit-locations" -> omitLocations = true
 
-                ARG_PROGUARD, "-proguard" -> proguard = stringToNewFile(getValue(args, ++index))
-
                 ARG_HIDE_PACKAGE, "-hidePackage" -> mutableHidePackages.add(getValue(args, ++index))
 
                 ARG_STUB_PACKAGES, "-stubpackages" -> {
@@ -1124,11 +1089,6 @@
                     mutableCompatibilityChecks.add(CheckRequest(file, ApiType.REMOVED, ReleaseType.RELEASED))
                 }
 
-                ARG_CHECK_COMPATIBILITY_BASE_API -> {
-                    val file = stringToExistingFile(getValue(args, ++index))
-                    baseApiForCompatCheck = file
-                }
-
                 ARG_ALLOW_COMPATIBLE_DIFFERENCES -> allowCompatibleDifferences = true
                 ARG_NO_NATIVE_DIFF -> noNativeDiff = true
 
@@ -1594,13 +1554,10 @@
                             "$ARG_FORMAT=v2", "$ARG_FORMAT=recommended" -> {
                                 FileFormat.V2
                             }
-                            "$ARG_FORMAT=v3" -> {
+                            "$ARG_FORMAT=v3", "$ARG_FORMAT=latest" -> {
                                 FileFormat.V3
                             }
-                            "$ARG_FORMAT=v4", "$ARG_FORMAT=latest" -> {
-                                FileFormat.V4
-                            }
-                            else -> throw DriverException(stderr = "Unexpected signature format; expected v1, v2, v3 or v4")
+                            else -> throw DriverException(stderr = "Unexpected signature format; expected v1, v2 or v3")
                         }
                         outputFormat.configureOptions(this, compatibility)
                     } else if (arg.startsWith("-")) {
@@ -1674,11 +1631,9 @@
             apiLevelJars = findAndroidJars(patterns, currentApiLevel, currentCodeName, currentJar)
         }
 
-        // outputKotlinStyleNulls implies at least format=v3
+        // outputKotlinStyleNulls implies format=v3
         if (outputKotlinStyleNulls) {
-            if (outputFormat < FileFormat.V3) {
-                outputFormat = FileFormat.V3
-            }
+            outputFormat = FileFormat.V3
             outputFormat.configureOptions(this, compatibility)
         }
 
@@ -1711,7 +1666,6 @@
             docStubsSourceList = null
             sdkValueDir = null
             externalAnnotations = null
-            proguard = null
             noDocs = true
             invokeDocumentationToolArguments = emptyArray()
             mutableCompatibilityChecks.clear()
@@ -1737,7 +1691,6 @@
             docStubsSourceList = null
             sdkValueDir = null
             externalAnnotations = null
-            proguard = null
             noDocs = true
             invokeDocumentationToolArguments = emptyArray()
             mutableAnnotationCoverageOf.clear()
@@ -2373,7 +2326,6 @@
             "$ARG_INCLUDE_SIG_VERSION[=yes|no]", "Whether the signature files should include a comment listing " +
                 "the format version of the signature file.",
 
-            "$ARG_PROGUARD <file>", "Write a ProGuard keep file for the API",
             "$ARG_SDK_VALUES <dir>", "Write SDK values files to the given directory",
 
             "", "\nGenerating Stubs:",
@@ -2387,14 +2339,9 @@
             ARG_KOTLIN_STUBS, "[CURRENTLY EXPERIMENTAL] If specified, stubs generated from Kotlin source code will " +
                 "be written in Kotlin rather than the Java programming language.",
             ARG_INCLUDE_ANNOTATIONS, "Include annotations such as @Nullable in the stub files.",
-            ARG_EXCLUDE_ALL_ANNOTATIONS, "Exclude annotations such as @Nullable from the stub files; the default.",
+            ARG_EXCLUDE_ANNOTATIONS, "Exclude annotations such as @Nullable from the stub files; the default.",
             "$ARG_PASS_THROUGH_ANNOTATION <annotation classes>", "A comma separated list of fully qualified names of " +
                 "annotation classes that must be passed through unchanged.",
-            "$ARG_EXCLUDE_ANNOTATION <annotation classes>", "A comma separated list of fully qualified names of " +
-                "annotation classes that must be stripped from metalava's outputs.",
-            ARG_ENHANCE_DOCUMENTATION,
-            "Enhance documentation in various ways, for example auto-generating documentation based on source " +
-                "annotations present in the code. This is implied by --doc-stubs.",
             ARG_EXCLUDE_DOCUMENTATION_FROM_STUBS, "Exclude element documentation (javadoc and kdoc) " +
                 "from the generated stubs. (Copyright notices are not affected by this, they are always included. " +
                 "Documentation stubs (--doc-stubs) are not affected.)",
@@ -2418,11 +2365,6 @@
                 "released API, respectively. Different compatibility checks apply in the two scenarios. " +
                 "For example, to check the code base against the current public API, use " +
                 "$ARG_CHECK_COMPATIBILITY:api:current.",
-            "$ARG_CHECK_COMPATIBILITY_BASE_API <file>", "When performing a compat check, use the provided signature " +
-                "file as a base api, which is treated as part of the API being checked. This allows us to compute the " +
-                "full API surface from a partial API surface (e.g. the current @SystemApi txt file), which allows us to " +
-                "recognize when an API is moved from the partial API to the base API and avoid incorrectly flagging this " +
-                "as an API removal.",
             "$ARG_API_LINT [api file]", "Check API for Android API best practices. If a signature file is " +
                 "provided, only the APIs that are new since the API will be checked.",
             "$ARG_API_LINT_IGNORE_PREFIX [prefix]", "A list of package prefixes to ignore API issues in " +
@@ -2616,8 +2558,21 @@
                 }
                 return
             }
+
+            val numericId = try {
+                id.toInt()
+            } catch (e: NumberFormatException) {
+                -1
+            }
+
             val issue = Issues.findIssueById(id)
-                ?: Issues.findIssueByIdIgnoringCase(id)?.also {
+                ?: Issues.findIssueById(numericId)?.also {
+                    reporter.report(
+                        Issues.DEPRECATED_OPTION, null as File?,
+                        "Issue lookup by numeric id is deprecated, use " +
+                            "$arg ${it.name} instead of $arg $id"
+                    )
+                } ?: Issues.findIssueByIdIgnoringCase(id)?.also {
                     reporter.report(
                         Issues.DEPRECATED_OPTION, null as File?,
                         "Case-insensitive issue matching is deprecated, use " +
diff --git a/src/main/java/com/android/tools/metalava/ProguardWriter.kt b/src/main/java/com/android/tools/metalava/ProguardWriter.kt
deleted file mode 100644
index cb8a2be..0000000
--- a/src/main/java/com/android/tools/metalava/ProguardWriter.kt
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.metalava
-
-import com.android.tools.metalava.model.ClassItem
-import com.android.tools.metalava.model.ConstructorItem
-import com.android.tools.metalava.model.FieldItem
-import com.android.tools.metalava.model.Item
-import com.android.tools.metalava.model.MethodItem
-import com.android.tools.metalava.model.ParameterItem
-import com.android.tools.metalava.model.TypeItem
-import com.android.tools.metalava.model.VisibilityLevel
-import com.android.tools.metalava.model.visitors.ApiVisitor
-import java.io.PrintWriter
-import java.util.function.Predicate
-
-class ProguardWriter(
-    private val writer: PrintWriter,
-    filterEmit: Predicate<Item>,
-    filterReference: Predicate<Item>
-) : ApiVisitor(
-    visitConstructorsAsMethods = false,
-    nestInnerClasses = false,
-    inlineInheritedFields = true,
-    filterEmit = filterEmit,
-    filterReference = filterReference
-) {
-
-    override fun visitClass(cls: ClassItem) {
-        writer.print("-keep class ")
-        writer.print(cls.qualifiedNameWithDollarInnerClasses())
-        writer.print(" {\n")
-    }
-
-    override fun afterVisitClass(cls: ClassItem) {
-        writer.print("}\n")
-    }
-
-    override fun visitConstructor(constructor: ConstructorItem) {
-        writer.print("    ")
-        writer.print("<init>")
-
-        writeParametersKeepList(constructor.parameters())
-        writer.print(";\n")
-    }
-
-    override fun visitMethod(method: MethodItem) {
-        writer.print("    ")
-        val modifiers = method.modifiers
-        val visibilityLevel = modifiers.getVisibilityLevel()
-        if (visibilityLevel != VisibilityLevel.PACKAGE_PRIVATE) {
-            writer.write(visibilityLevel.javaSourceCodeModifier + " ")
-        }
-
-        if (modifiers.isStatic()) {
-            writer.print("static ")
-        }
-        if (modifiers.isAbstract()) {
-            writer.print("abstract ")
-        }
-        if (modifiers.isSynchronized()) {
-            writer.print("synchronized ")
-        }
-
-        writer.print(getCleanTypeName(method.returnType()))
-        writer.print(" ")
-        writer.print(method.name())
-
-        writeParametersKeepList(method.parameters())
-
-        writer.print(";\n")
-    }
-
-    private fun writeParametersKeepList(params: List<ParameterItem>) {
-        writer.print("(")
-
-        for (pi in params) {
-            if (pi !== params[0]) {
-                writer.print(", ")
-            }
-            writer.print(getCleanTypeName(pi.type()))
-        }
-
-        writer.print(")")
-    }
-
-    override fun visitField(field: FieldItem) {
-        writer.print("    ")
-
-        val modifiers = field.modifiers
-        val visibilityLevel = modifiers.getVisibilityLevel()
-        if (visibilityLevel != VisibilityLevel.PACKAGE_PRIVATE) {
-            writer.write(visibilityLevel.javaSourceCodeModifier + " ")
-        }
-
-        if (modifiers.isStatic()) {
-            writer.print("static ")
-        }
-        if (modifiers.isTransient()) {
-            writer.print("transient ")
-        }
-        if (modifiers.isVolatile()) {
-            writer.print("volatile ")
-        }
-
-        writer.print(getCleanTypeName(field.type()))
-
-        writer.print(" ")
-        writer.print(field.name())
-
-        writer.print(";\n")
-    }
-
-    private fun getCleanTypeName(t: TypeItem?): String {
-        t ?: return ""
-        val cls = t.asClass() ?: return t.toCanonicalType()
-        var qualifiedName = cls.qualifiedNameWithDollarInnerClasses()
-
-        for (i in 0 until t.arrayDimensions()) {
-            qualifiedName += "[]"
-        }
-        return qualifiedName
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/com/android/tools/metalava/ReleaseType.kt b/src/main/java/com/android/tools/metalava/ReleaseType.kt
index d37cbcf..814cc77 100644
--- a/src/main/java/com/android/tools/metalava/ReleaseType.kt
+++ b/src/main/java/com/android/tools/metalava/ReleaseType.kt
@@ -16,6 +16,7 @@
 
 package com.android.tools.metalava
 
+import com.android.tools.metalava.doclava1.Issues
 import com.android.tools.metalava.model.IssueConfiguration
 
 enum class ReleaseType(val flagName: String, private val displayName: String = flagName) {
diff --git a/src/main/java/com/android/tools/metalava/Reporter.kt b/src/main/java/com/android/tools/metalava/Reporter.kt
index 2d9afc7..9bf115e 100644
--- a/src/main/java/com/android/tools/metalava/Reporter.kt
+++ b/src/main/java/com/android/tools/metalava/Reporter.kt
@@ -22,6 +22,7 @@
 import com.android.tools.metalava.Severity.INHERIT
 import com.android.tools.metalava.Severity.LINT
 import com.android.tools.metalava.Severity.WARNING
+import com.android.tools.metalava.doclava1.Issues
 import com.android.tools.metalava.model.AnnotationArrayAttributeValue
 import com.android.tools.metalava.model.Item
 import com.android.tools.metalava.model.configuration
@@ -34,7 +35,6 @@
 import com.intellij.psi.PsiElement
 import com.intellij.psi.PsiModifierListOwner
 import com.intellij.psi.impl.light.LightElement
-import org.jetbrains.uast.kotlin.KotlinUClass
 import java.io.File
 import java.io.PrintWriter
 
@@ -184,27 +184,33 @@
 
         item ?: return false
 
-        for (annotation in item.modifiers.annotations()) {
-            val annotationName = annotation.qualifiedName()
-            if (annotationName != null && annotationName in SUPPRESS_ANNOTATIONS) {
-                for (attribute in annotation.attributes()) {
-                    // Assumption that all annotations in SUPPRESS_ANNOTATIONS only have
-                    // one attribute such as value/names that is varargs of String
-                    val value = attribute.value
-                    if (value is AnnotationArrayAttributeValue) {
-                        // Example: @SuppressLint({"RequiresFeature", "AllUpper"})
-                        for (innerValue in value.values) {
-                            val string = innerValue.value()?.toString() ?: continue
-                            if (suppressMatches(string, id.name, message)) {
+        if (severity == LINT || severity == WARNING || severity == ERROR) {
+            for (annotation in item.modifiers.annotations()) {
+                val annotationName = annotation.qualifiedName()
+                if (annotationName != null && annotationName in SUPPRESS_ANNOTATIONS) {
+                    for (attribute in annotation.attributes()) {
+                        val id1 = "Doclava${id.code}"
+                        val id2 = id.name
+                        // Assumption that all annotations in SUPPRESS_ANNOTATIONS only have
+                        // one attribute such as value/names that is varargs of String
+                        val value = attribute.value
+                        if (value is AnnotationArrayAttributeValue) {
+                            // Example: @SuppressLint({"DocLava1", "DocLava2"})
+                            for (innerValue in value.values) {
+                                val string = innerValue.value()?.toString() ?: continue
+                                if (suppressMatches(string, id1, message) || suppressMatches(string, id2, message)) {
+                                    return true
+                                }
+                            }
+                        } else {
+                            // Example: @SuppressLint("DocLava1")
+                            val string = value.value()?.toString()
+                            if (string != null && (
+                                    suppressMatches(string, id1, message) || suppressMatches(string, id2, message))
+                            ) {
                                 return true
                             }
                         }
-                    } else {
-                        // Example: @SuppressLint("RequiresFeature")
-                        val string = value.value()?.toString()
-                        if (string != null && (suppressMatches(string, id.name, message))) {
-                            return true
-                        }
                     }
                 }
             }
@@ -232,9 +238,7 @@
     private fun getTextRange(element: PsiElement): TextRange? {
         var range: TextRange? = null
 
-        if (element is KotlinUClass) {
-            range = element.sourcePsi?.textRange
-        } else if (element is PsiCompiledElement) {
+        if (element is PsiCompiledElement) {
             if (element is LightElement) {
                 range = (element as PsiElement).textRange
             }
@@ -355,23 +359,44 @@
             if (!omitLocations) {
                 location?.let { sb.append(it).append(": ") }
             }
-            when (severity) {
-                LINT -> sb.append("lint: ")
-                INFO -> sb.append("info: ")
-                WARNING -> sb.append("warning: ")
-                ERROR -> sb.append("error: ")
-                INHERIT, HIDDEN -> {
+            if (compatibility.oldErrorOutputFormat) {
+                // according to doclava1 there are some people or tools parsing old format
+                when (severity) {
+                    LINT -> sb.append("lint ")
+                    INFO -> sb.append("info ")
+                    WARNING -> sb.append("warning ")
+                    ERROR -> sb.append("error ")
+                    INHERIT, HIDDEN -> {
+                    }
                 }
-            }
-            sb.append(message)
-            id?.let {
-                sb.append(" [")
-                sb.append(it.name)
-                sb.append("]")
-                val link = it.category.ruleLink
-                if (it.rule != null && link != null) {
-                    sb.append(" [See ").append(link).append(it.rule)
+                id?.let { sb.append(it.name).append(": ") }
+                sb.append(message)
+            } else {
+                when (severity) {
+                    LINT -> sb.append("lint: ")
+                    INFO -> sb.append("info: ")
+                    WARNING -> sb.append("warning: ")
+                    ERROR -> sb.append("error: ")
+                    INHERIT, HIDDEN -> {
+                    }
+                }
+                sb.append(message)
+                id?.let {
+                    sb.append(" [")
+                    sb.append(it.name)
+                    if (compatibility.includeExitCode) {
+                        sb.append(":")
+                        sb.append(it.code)
+                    }
                     sb.append("]")
+                    if (it.rule != null) {
+                        sb.append(" [Rule ").append(it.rule)
+                        val link = it.category.ruleLink
+                        if (link != null) {
+                            sb.append(" in ").append(link)
+                        }
+                        sb.append("]")
+                    }
                 }
             }
         }
diff --git a/src/main/java/com/android/tools/metalava/SignatureWriter.kt b/src/main/java/com/android/tools/metalava/SignatureWriter.kt
index f51803c..bc78eda 100644
--- a/src/main/java/com/android/tools/metalava/SignatureWriter.kt
+++ b/src/main/java/com/android/tools/metalava/SignatureWriter.kt
@@ -278,13 +278,6 @@
             if (i > 0) {
                 writer.print(", ")
             }
-            if (parameter.hasDefaultValue() &&
-                options.outputDefaultValues &&
-                options.outputConciseDefaultValues
-            ) {
-                // Concise representation of a parameter with a default
-                writer.print("optional ")
-            }
             writeModifiers(parameter)
             writeType(parameter, parameter.type())
             if (emitParameterNames) {
@@ -294,10 +287,7 @@
                     writer.print(name)
                 }
             }
-            if (parameter.isDefaultValueKnown() &&
-                options.outputDefaultValues &&
-                !options.outputConciseDefaultValues
-            ) {
+            if (options.outputDefaultValues && parameter.hasDefaultValue()) {
                 writer.print(" = ")
                 val defaultValue = parameter.defaultValue()
                 if (defaultValue != null) {
diff --git a/src/main/java/com/android/tools/metalava/ApiPredicate.kt b/src/main/java/com/android/tools/metalava/doclava1/ApiPredicate.kt
similarity index 89%
rename from src/main/java/com/android/tools/metalava/ApiPredicate.kt
rename to src/main/java/com/android/tools/metalava/doclava1/ApiPredicate.kt
index 1178900..bac6155 100644
--- a/src/main/java/com/android/tools/metalava/ApiPredicate.kt
+++ b/src/main/java/com/android/tools/metalava/doclava1/ApiPredicate.kt
@@ -1,27 +1,15 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+package com.android.tools.metalava.doclava1
 
-package com.android.tools.metalava
-
+import com.android.tools.metalava.Options
 import com.android.tools.metalava.model.ClassItem
 import com.android.tools.metalava.model.Item
 import com.android.tools.metalava.model.MemberItem
 import com.android.tools.metalava.model.PackageItem
+import com.android.tools.metalava.options
 import java.util.function.Predicate
 
+// Ported from doclava1
+
 /**
  * Predicate that decides if the given member should be considered part of an
  * API surface area. To make the most accurate decision, it searches for
diff --git a/src/main/java/com/android/tools/metalava/doclava1/ElidingPredicate.kt b/src/main/java/com/android/tools/metalava/doclava1/ElidingPredicate.kt
new file mode 100644
index 0000000..6d091e2
--- /dev/null
+++ b/src/main/java/com/android/tools/metalava/doclava1/ElidingPredicate.kt
@@ -0,0 +1,31 @@
+package com.android.tools.metalava.doclava1
+
+import com.android.tools.metalava.model.Item
+import com.android.tools.metalava.model.MethodItem
+
+import java.util.function.Predicate
+
+// Ported from doclava1
+
+/**
+ * Filter that will elide exact duplicate methods that are already included
+ * in another superclass/interfaces.
+ */
+class ElidingPredicate(private val wrapped: Predicate<Item>) : Predicate<Item> {
+
+    override fun test(method: Item): Boolean {
+        // This method should be included, but if it's an exact duplicate
+        // override then we can elide it.
+        return if (method is MethodItem && !method.isConstructor()) {
+            val differentSuper = method.findPredicateSuperMethod(Predicate { test ->
+                // We're looking for included and perfect signature
+                wrapped.test(test) &&
+                    test is MethodItem &&
+                    MethodItem.sameSignature(method, test, false)
+            })
+            differentSuper == null
+        } else {
+            true
+        }
+    }
+}
diff --git a/src/main/java/com/android/tools/metalava/FilterPredicate.kt b/src/main/java/com/android/tools/metalava/doclava1/FilterPredicate.kt
similarity index 89%
rename from src/main/java/com/android/tools/metalava/FilterPredicate.kt
rename to src/main/java/com/android/tools/metalava/doclava1/FilterPredicate.kt
index 842647b..084c655 100644
--- a/src/main/java/com/android/tools/metalava/FilterPredicate.kt
+++ b/src/main/java/com/android/tools/metalava/doclava1/FilterPredicate.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.tools.metalava
+package com.android.tools.metalava.doclava1
 
 import com.android.tools.metalava.model.Item
 import com.android.tools.metalava.model.MethodItem
 import java.util.function.Predicate
 
+// Ported from doclava1
+
 class FilterPredicate(private val wrapped: Predicate<Item>) : Predicate<Item> {
 
     override fun test(method: Item): Boolean {
diff --git a/src/main/java/com/android/tools/metalava/doclava1/Issues.kt b/src/main/java/com/android/tools/metalava/doclava1/Issues.kt
new file mode 100644
index 0000000..aabfcc0
--- /dev/null
+++ b/src/main/java/com/android/tools/metalava/doclava1/Issues.kt
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tools.metalava.doclava1
+
+import com.android.sdklib.SdkVersionInfo
+import com.android.tools.metalava.Severity
+import java.util.ArrayList
+import java.util.HashMap
+import java.util.Locale
+import kotlin.reflect.full.declaredMemberProperties
+
+// Copied from doclava1 (and a bunch of stuff left alone preserving to have same error id's)
+object Issues {
+    private val allIssues: MutableList<Issue> = ArrayList(200)
+    private val nameToIssue: MutableMap<String, Issue> = HashMap(200)
+    private val idToIssue: MutableMap<Int, Issue> = HashMap(200)
+
+    val PARSE_ERROR = Issue(1, Severity.ERROR)
+    val ADDED_PACKAGE = Issue(2, Severity.WARNING, Category.COMPATIBILITY)
+    val ADDED_CLASS = Issue(3, Severity.WARNING, Category.COMPATIBILITY)
+    val ADDED_METHOD = Issue(4, Severity.WARNING, Category.COMPATIBILITY)
+    val ADDED_FIELD = Issue(5, Severity.WARNING, Category.COMPATIBILITY)
+    val ADDED_INTERFACE = Issue(6, Severity.WARNING, Category.COMPATIBILITY)
+    val REMOVED_PACKAGE = Issue(7, Severity.WARNING, Category.COMPATIBILITY)
+    val REMOVED_CLASS = Issue(8, Severity.WARNING, Category.COMPATIBILITY)
+    val REMOVED_METHOD = Issue(9, Severity.WARNING, Category.COMPATIBILITY)
+    val REMOVED_FIELD = Issue(10, Severity.WARNING, Category.COMPATIBILITY)
+    val REMOVED_INTERFACE = Issue(11, Severity.WARNING, Category.COMPATIBILITY)
+    val CHANGED_STATIC = Issue(12, Severity.WARNING, Category.COMPATIBILITY)
+    val ADDED_FINAL = Issue(13, Severity.WARNING, Category.COMPATIBILITY)
+    val CHANGED_TRANSIENT = Issue(14, Severity.WARNING, Category.COMPATIBILITY)
+    val CHANGED_VOLATILE = Issue(15, Severity.WARNING, Category.COMPATIBILITY)
+    val CHANGED_TYPE = Issue(16, Severity.WARNING, Category.COMPATIBILITY)
+    val CHANGED_VALUE = Issue(17, Severity.WARNING, Category.COMPATIBILITY)
+    val CHANGED_SUPERCLASS = Issue(18, Severity.WARNING, Category.COMPATIBILITY)
+    val CHANGED_SCOPE = Issue(19, Severity.WARNING, Category.COMPATIBILITY)
+    val CHANGED_ABSTRACT = Issue(20, Severity.WARNING, Category.COMPATIBILITY)
+    val CHANGED_THROWS = Issue(21, Severity.WARNING, Category.COMPATIBILITY)
+    val CHANGED_NATIVE = Issue(22, Severity.HIDDEN, Category.COMPATIBILITY)
+    val CHANGED_CLASS = Issue(23, Severity.WARNING, Category.COMPATIBILITY)
+    val CHANGED_DEPRECATED = Issue(24, Severity.WARNING, Category.COMPATIBILITY)
+    val CHANGED_SYNCHRONIZED = Issue(25, Severity.WARNING, Category.COMPATIBILITY)
+    val ADDED_FINAL_UNINSTANTIABLE = Issue(26, Severity.WARNING, Category.COMPATIBILITY)
+    val REMOVED_FINAL = Issue(27, Severity.WARNING, Category.COMPATIBILITY)
+    val REMOVED_DEPRECATED_CLASS = Issue(28, REMOVED_CLASS, Category.COMPATIBILITY)
+    val REMOVED_DEPRECATED_METHOD = Issue(29, REMOVED_METHOD, Category.COMPATIBILITY)
+    val REMOVED_DEPRECATED_FIELD = Issue(30, REMOVED_FIELD, Category.COMPATIBILITY)
+    val ADDED_ABSTRACT_METHOD = Issue(31, ADDED_METHOD, Category.COMPATIBILITY)
+    val ADDED_REIFIED = Issue(32, Severity.WARNING, Category.COMPATIBILITY)
+
+    // Issues in javadoc generation
+    val UNRESOLVED_LINK = Issue(101, Severity.LINT, Category.DOCUMENTATION)
+    val BAD_INCLUDE_TAG = Issue(102, Severity.LINT, Category.DOCUMENTATION)
+    val UNKNOWN_TAG = Issue(103, Severity.LINT, Category.DOCUMENTATION)
+    val UNKNOWN_PARAM_TAG_NAME = Issue(104, Severity.LINT, Category.DOCUMENTATION)
+    val UNDOCUMENTED_PARAMETER = Issue(105, Severity.HIDDEN, Category.DOCUMENTATION)
+    val BAD_ATTR_TAG = Issue(106, Severity.LINT, Category.DOCUMENTATION)
+    val BAD_INHERITDOC = Issue(107, Severity.HIDDEN, Category.DOCUMENTATION)
+    val HIDDEN_LINK = Issue(108, Severity.LINT, Category.DOCUMENTATION)
+    val HIDDEN_CONSTRUCTOR = Issue(109, Severity.WARNING, Category.DOCUMENTATION)
+    val UNAVAILABLE_SYMBOL = Issue(110, Severity.WARNING, Category.DOCUMENTATION)
+    val HIDDEN_SUPERCLASS = Issue(111, Severity.WARNING, Category.DOCUMENTATION)
+    val DEPRECATED = Issue(112, Severity.HIDDEN, Category.DOCUMENTATION)
+    val DEPRECATION_MISMATCH = Issue(113, Severity.ERROR, Category.DOCUMENTATION)
+    val MISSING_COMMENT = Issue(114, Severity.LINT, Category.DOCUMENTATION)
+    val IO_ERROR = Issue(115, Severity.ERROR)
+    val NO_SINCE_DATA = Issue(116, Severity.HIDDEN, Category.DOCUMENTATION)
+    val NO_FEDERATION_DATA = Issue(117, Severity.WARNING, Category.DOCUMENTATION)
+    val BROKEN_SINCE_FILE = Issue(118, Severity.ERROR, Category.DOCUMENTATION)
+    val INVALID_CONTENT_TYPE = Issue(119, Severity.ERROR, Category.DOCUMENTATION)
+    val INVALID_SAMPLE_INDEX = Issue(120, Severity.ERROR, Category.DOCUMENTATION)
+    val HIDDEN_TYPE_PARAMETER = Issue(121, Severity.WARNING, Category.DOCUMENTATION)
+    val PRIVATE_SUPERCLASS = Issue(122, Severity.WARNING, Category.DOCUMENTATION)
+    val NULLABLE = Issue(123, Severity.HIDDEN, Category.DOCUMENTATION)
+    val INT_DEF = Issue(124, Severity.HIDDEN, Category.DOCUMENTATION)
+    val REQUIRES_PERMISSION = Issue(125, Severity.LINT, Category.DOCUMENTATION)
+    val BROADCAST_BEHAVIOR = Issue(126, Severity.LINT, Category.DOCUMENTATION)
+    val SDK_CONSTANT = Issue(127, Severity.LINT, Category.DOCUMENTATION)
+    val TODO = Issue(128, Severity.LINT, Category.DOCUMENTATION)
+    val NO_ARTIFACT_DATA = Issue(129, Severity.HIDDEN, Category.DOCUMENTATION)
+    val BROKEN_ARTIFACT_FILE = Issue(130, Severity.ERROR, Category.DOCUMENTATION)
+
+    // Metalava warnings (not from doclava)
+
+    val TYPO = Issue(131, Severity.WARNING, Category.DOCUMENTATION)
+    val MISSING_PERMISSION = Issue(132, Severity.LINT, Category.DOCUMENTATION)
+    val MULTIPLE_THREAD_ANNOTATIONS = Issue(133, Severity.LINT, Category.DOCUMENTATION)
+    val UNRESOLVED_CLASS = Issue(134, Severity.LINT, Category.DOCUMENTATION)
+    val INVALID_NULL_CONVERSION = Issue(135, Severity.ERROR, Category.COMPATIBILITY)
+    val PARAMETER_NAME_CHANGE = Issue(136, Severity.ERROR, Category.COMPATIBILITY)
+    val OPERATOR_REMOVAL = Issue(137, Severity.ERROR, Category.COMPATIBILITY)
+    val INFIX_REMOVAL = Issue(138, Severity.ERROR, Category.COMPATIBILITY)
+    val VARARG_REMOVAL = Issue(139, Severity.ERROR, Category.COMPATIBILITY)
+    val ADD_SEALED = Issue(140, Severity.ERROR, Category.COMPATIBILITY)
+    val ANNOTATION_EXTRACTION = Issue(146, Severity.ERROR)
+    val SUPERFLUOUS_PREFIX = Issue(147, Severity.WARNING)
+    val HIDDEN_TYPEDEF_CONSTANT = Issue(148, Severity.ERROR)
+    val EXPECTED_PLATFORM_TYPE = Issue(149, Severity.HIDDEN)
+    val INTERNAL_ERROR = Issue(150, Severity.ERROR)
+    val RETURNING_UNEXPECTED_CONSTANT = Issue(151, Severity.WARNING)
+    val DEPRECATED_OPTION = Issue(152, Severity.WARNING)
+    val BOTH_PACKAGE_INFO_AND_HTML = Issue(153, Severity.WARNING, Category.DOCUMENTATION)
+    // The plan is for this to be set as an error once (1) existing code is marked as @deprecated
+    // and (2) the principle is adopted by the API council
+    val REFERENCES_DEPRECATED = Issue(154, Severity.HIDDEN)
+    val UNHIDDEN_SYSTEM_API = Issue(155, Severity.ERROR)
+    val SHOWING_MEMBER_IN_HIDDEN_CLASS = Issue(156, Severity.ERROR)
+    val INVALID_NULLABILITY_ANNOTATION = Issue(157, Severity.ERROR)
+    val REFERENCES_HIDDEN = Issue(158, Severity.ERROR)
+    val IGNORING_SYMLINK = Issue(159, Severity.INFO)
+    val INVALID_NULLABILITY_ANNOTATION_WARNING = Issue(160, Severity.WARNING)
+    // The plan is for this to be set as an error once (1) existing code is marked as @deprecated
+    // and (2) the principle is adopted by the API council
+    val EXTENDS_DEPRECATED = Issue(161, Severity.HIDDEN)
+    val FORBIDDEN_TAG = Issue(162, Severity.ERROR)
+    val MISSING_COLUMN = Issue(163, Severity.WARNING, Category.DOCUMENTATION)
+    val INVALID_SYNTAX = Issue(164, Severity.ERROR)
+    val UNRESOLVED_IMPORT = Issue(165, Severity.INFO)
+
+    // API lint
+    val START_WITH_LOWER = Issue(300, Severity.ERROR, Category.API_LINT, "S1")
+    val START_WITH_UPPER = Issue(301, Severity.ERROR, Category.API_LINT, "S1")
+    val ALL_UPPER = Issue(302, Severity.ERROR, Category.API_LINT, "C2")
+    val ACRONYM_NAME = Issue(303, Severity.WARNING, Category.API_LINT, "S1")
+    val ENUM = Issue(304, Severity.ERROR, Category.API_LINT, "F5")
+    val ENDS_WITH_IMPL = Issue(305, Severity.ERROR, Category.API_LINT)
+    val MIN_MAX_CONSTANT = Issue(306, Severity.WARNING, Category.API_LINT, "C8")
+    val COMPILE_TIME_CONSTANT = Issue(307, Severity.ERROR, Category.API_LINT)
+    val SINGULAR_CALLBACK = Issue(308, Severity.ERROR, Category.API_LINT, "L1")
+    val CALLBACK_NAME = Issue(309, Severity.WARNING, Category.API_LINT, "L1")
+    val CALLBACK_INTERFACE = Issue(310, Severity.ERROR, Category.API_LINT, "CL3")
+    val CALLBACK_METHOD_NAME = Issue(311, Severity.ERROR, Category.API_LINT, "L1")
+    val LISTENER_INTERFACE = Issue(312, Severity.ERROR, Category.API_LINT, "L1")
+    val SINGLE_METHOD_INTERFACE = Issue(313, Severity.ERROR, Category.API_LINT, "L1")
+    val INTENT_NAME = Issue(314, Severity.ERROR, Category.API_LINT, "C3")
+    val ACTION_VALUE = Issue(315, Severity.ERROR, Category.API_LINT, "C4")
+    val EQUALS_AND_HASH_CODE = Issue(316, Severity.ERROR, Category.API_LINT, "M8")
+    val PARCEL_CREATOR = Issue(317, Severity.ERROR, Category.API_LINT, "FW3")
+    val PARCEL_NOT_FINAL = Issue(318, Severity.ERROR, Category.API_LINT, "FW8")
+    val PARCEL_CONSTRUCTOR = Issue(319, Severity.ERROR, Category.API_LINT, "FW3")
+    val PROTECTED_MEMBER = Issue(320, Severity.ERROR, Category.API_LINT, "M7")
+    val PAIRED_REGISTRATION = Issue(321, Severity.ERROR, Category.API_LINT, "L2")
+    val REGISTRATION_NAME = Issue(322, Severity.ERROR, Category.API_LINT, "L3")
+    val VISIBLY_SYNCHRONIZED = Issue(323, Severity.ERROR, Category.API_LINT, "M5")
+    val INTENT_BUILDER_NAME = Issue(324, Severity.WARNING, Category.API_LINT, "FW1")
+    val CONTEXT_NAME_SUFFIX = Issue(325, Severity.ERROR, Category.API_LINT, "C4")
+    val INTERFACE_CONSTANT = Issue(326, Severity.ERROR, Category.API_LINT, "C4")
+    val ON_NAME_EXPECTED = Issue(327, Severity.WARNING, Category.API_LINT)
+    val TOP_LEVEL_BUILDER = Issue(328, Severity.WARNING, Category.API_LINT)
+    val MISSING_BUILD_METHOD = Issue(329, Severity.WARNING, Category.API_LINT)
+    val BUILDER_SET_STYLE = Issue(330, Severity.WARNING, Category.API_LINT)
+    val SETTER_RETURNS_THIS = Issue(331, Severity.WARNING, Category.API_LINT, "M4")
+    val RAW_AIDL = Issue(332, Severity.ERROR, Category.API_LINT)
+    val INTERNAL_CLASSES = Issue(333, Severity.ERROR, Category.API_LINT)
+    val PACKAGE_LAYERING = Issue(334, Severity.WARNING, Category.API_LINT, "FW6")
+    val GETTER_SETTER_NAMES = Issue(335, Severity.ERROR, Category.API_LINT, "M6")
+    val CONCRETE_COLLECTION = Issue(336, Severity.ERROR, Category.API_LINT, "CL2")
+    val OVERLAPPING_CONSTANTS = Issue(337, Severity.WARNING, Category.API_LINT, "C1")
+    val GENERIC_EXCEPTION = Issue(338, Severity.ERROR, Category.API_LINT, "S1")
+    val ILLEGAL_STATE_EXCEPTION = Issue(339, Severity.WARNING, Category.API_LINT, "S1")
+    val RETHROW_REMOTE_EXCEPTION = Issue(340, Severity.ERROR, Category.API_LINT, "FW9")
+    val MENTIONS_GOOGLE = Issue(341, Severity.ERROR, Category.API_LINT)
+    val HEAVY_BIT_SET = Issue(342, Severity.ERROR, Category.API_LINT)
+    val MANAGER_CONSTRUCTOR = Issue(343, Severity.ERROR, Category.API_LINT)
+    val MANAGER_LOOKUP = Issue(344, Severity.ERROR, Category.API_LINT)
+    val AUTO_BOXING = Issue(345, Severity.ERROR, Category.API_LINT, "M11")
+    val STATIC_UTILS = Issue(346, Severity.ERROR, Category.API_LINT)
+    val CONTEXT_FIRST = Issue(347, Severity.ERROR, Category.API_LINT, "M3")
+    val LISTENER_LAST = Issue(348, Severity.WARNING, Category.API_LINT, "M3")
+    val EXECUTOR_REGISTRATION = Issue(349, Severity.WARNING, Category.API_LINT, "L1")
+    val CONFIG_FIELD_NAME = Issue(350, Severity.ERROR, Category.API_LINT)
+    val RESOURCE_FIELD_NAME = Issue(351, Severity.ERROR, Category.API_LINT)
+    val RESOURCE_VALUE_FIELD_NAME = Issue(352, Severity.ERROR, Category.API_LINT, "C7")
+    val RESOURCE_STYLE_FIELD_NAME = Issue(353, Severity.ERROR, Category.API_LINT, "C7")
+    val STREAM_FILES = Issue(354, Severity.WARNING, Category.API_LINT, "M10")
+    val PARCELABLE_LIST = Issue(355, Severity.WARNING, Category.API_LINT)
+    val ABSTRACT_INNER = Issue(356, Severity.WARNING, Category.API_LINT)
+    val BANNED_THROW = Issue(358, Severity.ERROR, Category.API_LINT)
+    val EXTENDS_ERROR = Issue(359, Severity.ERROR, Category.API_LINT)
+    val EXCEPTION_NAME = Issue(360, Severity.ERROR, Category.API_LINT)
+    val METHOD_NAME_UNITS = Issue(361, Severity.ERROR, Category.API_LINT)
+    val FRACTION_FLOAT = Issue(362, Severity.ERROR, Category.API_LINT)
+    val PERCENTAGE_INT = Issue(363, Severity.ERROR, Category.API_LINT)
+    val NOT_CLOSEABLE = Issue(364, Severity.WARNING, Category.API_LINT)
+    val KOTLIN_OPERATOR = Issue(365, Severity.INFO, Category.API_LINT)
+    val ARRAY_RETURN = Issue(366, Severity.WARNING, Category.API_LINT)
+    val USER_HANDLE = Issue(367, Severity.WARNING, Category.API_LINT)
+    val USER_HANDLE_NAME = Issue(368, Severity.WARNING, Category.API_LINT)
+    val SERVICE_NAME = Issue(369, Severity.ERROR, Category.API_LINT, "C4")
+    val METHOD_NAME_TENSE = Issue(370, Severity.WARNING, Category.API_LINT)
+    val NO_CLONE = Issue(371, Severity.ERROR, Category.API_LINT)
+    val USE_ICU = Issue(372, Severity.WARNING, Category.API_LINT)
+    val USE_PARCEL_FILE_DESCRIPTOR = Issue(373, Severity.ERROR, Category.API_LINT, "FW11")
+    val NO_BYTE_OR_SHORT = Issue(374, Severity.WARNING, Category.API_LINT, "FW12")
+    val SINGLETON_CONSTRUCTOR = Issue(375, Severity.ERROR, Category.API_LINT)
+    val COMMON_ARGS_FIRST = Issue(376, Severity.WARNING, Category.API_LINT, "M2")
+    val CONSISTENT_ARGUMENT_ORDER = Issue(377, Severity.ERROR, Category.API_LINT, "M2")
+    val KOTLIN_KEYWORD = Issue(378, Severity.ERROR, Category.API_LINT) // Formerly 141
+    val UNIQUE_KOTLIN_OPERATOR = Issue(379, Severity.ERROR, Category.API_LINT)
+    val SAM_SHOULD_BE_LAST = Issue(380, Severity.WARNING, Category.API_LINT) // Formerly 142
+    val MISSING_JVMSTATIC = Issue(381, Severity.WARNING, Category.API_LINT) // Formerly 143
+    val DEFAULT_VALUE_CHANGE = Issue(382, Severity.ERROR, Category.API_LINT) // Formerly 144
+    val DOCUMENT_EXCEPTIONS = Issue(383, Severity.ERROR, Category.API_LINT) // Formerly 145
+    val FORBIDDEN_SUPER_CLASS = Issue(384, Severity.ERROR, Category.API_LINT)
+    val MISSING_NULLABILITY = Issue(385, Severity.ERROR, Category.API_LINT)
+    val MUTABLE_BARE_FIELD = Issue(386, Severity.ERROR, Category.API_LINT, "F2")
+    val INTERNAL_FIELD = Issue(387, Severity.ERROR, Category.API_LINT, "F2")
+    val PUBLIC_TYPEDEF = Issue(388, Severity.ERROR, Category.API_LINT, "FW15")
+    val ANDROID_URI = Issue(389, Severity.ERROR, Category.API_LINT, "FW14")
+    val BAD_FUTURE = Issue(390, Severity.ERROR, Category.API_LINT)
+    val STATIC_FINAL_BUILDER = Issue(391, Severity.WARNING, Category.API_LINT)
+    val GETTER_ON_BUILDER = Issue(392, Severity.WARNING, Category.API_LINT)
+    val MISSING_GETTER_MATCHING_BUILDER = Issue(393, Severity.WARNING, Category.API_LINT)
+    val OPTIONAL_BUILDER_CONSTRUCTOR_ARGUMENT = Issue(394, Severity.WARNING, Category.API_LINT)
+    val NO_SETTINGS_PROVIDER = Issue(395, Severity.HIDDEN, Category.API_LINT)
+    val PRIVATE_COMPANION = Issue(396, Severity.ERROR, Category.API_LINT)
+
+    fun findIssueById(id: Int): Issue? {
+        return idToIssue[id]
+    }
+
+    fun findIssueById(id: String?): Issue? {
+        return nameToIssue[id]
+    }
+
+    fun findIssueByIdIgnoringCase(id: String): Issue? {
+        for (e in allIssues) {
+            if (id.equals(e.name, ignoreCase = true)) {
+                return e
+            }
+        }
+        return null
+    }
+
+    class Issue private constructor(
+        val code: Int,
+        val defaultLevel: Severity,
+        /**
+         * When `level` is set to [Severity.INHERIT], this is the parent from
+         * which the issue will inherit its level.
+         */
+        val parent: Issue?,
+        /** Applicable category  */
+        val category: Category,
+        /** Related rule, if any  */
+        val rule: String?,
+        /** Related explanation, if any  */
+        val explanation: String?
+    ) {
+        /**
+         * The name of this issue
+         */
+        lateinit var name: String
+            internal set
+
+        internal constructor(
+            code: Int,
+            defaultLevel: Severity,
+            category: Category = Category.UNKNOWN
+        ) : this(code, defaultLevel, null, category, null, null)
+
+        internal constructor(
+            code: Int,
+            defaultLevel: Severity,
+            category: Category,
+            rule: String
+        ) : this(code, defaultLevel, null, category, rule, null)
+
+        internal constructor(
+            code: Int,
+            parent: Issue,
+            category: Category
+        ) : this(code, Severity.INHERIT, parent, category, null, null)
+
+        override fun toString(): String {
+            return "Issue #$code ($name)"
+        }
+
+        init {
+            allIssues.add(this)
+        }
+    }
+
+    enum class Category(val description: String, val ruleLink: String?) {
+        COMPATIBILITY("Compatibility", null),
+        DOCUMENTATION("Documentation", null),
+        API_LINT("API Lint", "go/android-api-guidelines"),
+        UNKNOWN("Default", null)
+    }
+
+    init { // Initialize issue names based on the field names
+        for (property in Issues::class.declaredMemberProperties) {
+            if (property.returnType.classifier != Issue::class) continue
+            val issue = property.getter.call(Issues) as Issue
+
+            issue.name = SdkVersionInfo.underlinesToCamelCase(property.name.toLowerCase(Locale.US))
+            nameToIssue[issue.name] = issue
+            idToIssue[issue.code] = issue
+        }
+        for (issue in allIssues) {
+            check(issue.name != "")
+        }
+    }
+}
diff --git a/src/main/java/com/android/tools/metalava/model/AnnotationItem.kt b/src/main/java/com/android/tools/metalava/model/AnnotationItem.kt
index 67cc713..37802ad 100644
--- a/src/main/java/com/android/tools/metalava/model/AnnotationItem.kt
+++ b/src/main/java/com/android/tools/metalava/model/AnnotationItem.kt
@@ -35,7 +35,7 @@
 import com.android.tools.metalava.Options
 import com.android.tools.metalava.RECENTLY_NONNULL
 import com.android.tools.metalava.RECENTLY_NULLABLE
-import com.android.tools.metalava.ApiPredicate
+import com.android.tools.metalava.doclava1.ApiPredicate
 import com.android.tools.metalava.model.psi.PsiBasedCodebase
 import com.android.tools.metalava.options
 import com.intellij.psi.PsiCallExpression
@@ -176,9 +176,6 @@
             if (options.passThroughAnnotations.contains(qualifiedName)) {
                 return qualifiedName
             }
-            if (options.excludeAnnotations.contains(qualifiedName)) {
-                return null
-            }
             when (qualifiedName) {
                 // Resource annotations
                 "android.support.annotation.AnimRes",
@@ -285,11 +282,6 @@
                 "android.support.annotation.LongDef",
                 "android.annotation.LongDef" -> return "androidx.annotation.LongDef"
 
-                // Context Types
-                "android.annotation.UiContext" -> return "androidx.annotation.UiContext"
-                "android.annotation.DisplayContext" -> return "androidx.annotation.DisplayContext"
-                "android.annotation.NonUiContext" -> return "androidx.annotation.NonUiContext"
-
                 // Misc
                 "android.support.annotation.CallSuper",
                 "android.annotation.CallSuper" -> return "androidx.annotation.CallSuper"
@@ -402,13 +394,6 @@
         private fun nonNullAnnotationName(target: AnnotationTarget) =
             if (target == AnnotationTarget.SDK_STUBS_FILE) ANDROID_NONNULL else ANDROIDX_NONNULL
 
-        private val TYPEDEF_ANNOTATION_TARGETS =
-            if (options.typedefMode == Options.TypedefMode.INLINE ||
-                options.typedefMode == Options.TypedefMode.NONE) // just here for compatibility purposes
-                ANNOTATION_EXTERNAL
-            else
-                ANNOTATION_EXTERNAL_ONLY
-
         /** The applicable targets for this annotation */
         fun computeTargets(
             annotation: AnnotationItem,
@@ -431,7 +416,7 @@
                 "androidx.annotation.StringDef",
                 "android.support.annotation.LongDef",
                 "android.annotation.LongDef",
-                "androidx.annotation.LongDef" -> return TYPEDEF_ANNOTATION_TARGETS
+                "androidx.annotation.LongDef" -> return ANNOTATION_EXTERNAL_ONLY
 
                 // Not directly API relevant
                 "android.view.ViewDebug.ExportedProperty",
@@ -439,13 +424,11 @@
 
                 // Skip known annotations that we (a) never want in external annotations and (b) we are
                 // specially overwriting anyway in the stubs (and which are (c) not API significant)
-                "com.android.modules.annotation.MinSdk",
                 "java.lang.annotation.Native",
                 "java.lang.SuppressWarnings",
                 "java.lang.Override",
                 "kotlin.Suppress",
                 "androidx.annotation.experimental.UseExperimental",
-                "androidx.annotation.OptIn",
                 "kotlin.UseExperimental",
                 "kotlin.OptIn" -> return NO_ANNOTATION_TARGETS
 
diff --git a/src/main/java/com/android/tools/metalava/model/AnnotationTarget.kt b/src/main/java/com/android/tools/metalava/model/AnnotationTarget.kt
index c124819..37865b4 100644
--- a/src/main/java/com/android/tools/metalava/model/AnnotationTarget.kt
+++ b/src/main/java/com/android/tools/metalava/model/AnnotationTarget.kt
@@ -16,6 +16,9 @@
 
 package com.android.tools.metalava.model
 
+import com.android.tools.metalava.Options
+import com.android.tools.metalava.options
+
 /** Various places where a given annotation can be written */
 enum class AnnotationTarget {
     /** Write the annotation into the signature file */
@@ -26,8 +29,8 @@
     DOC_STUBS_FILE,
     /** Write the annotation into external annotation files */
     EXTERNAL_ANNOTATIONS_FILE,
-    /** Write the annotation for internal purposes (e.g. cloning a method) */
-    INTERNAL;
+    /** Don't write the annotation anywhere */
+    NONE;
 
     /** Is this target a stubs file? */
     fun isStubsFile(): Boolean {
@@ -36,7 +39,7 @@
 }
 
 /** Don't write this annotation anywhere; it is not API significant. */
-val NO_ANNOTATION_TARGETS = setOf(AnnotationTarget.INTERNAL)
+val NO_ANNOTATION_TARGETS = setOf(AnnotationTarget.NONE)
 
 /**
  * Annotation is API significant: write it into the signature file and stub source code.
@@ -55,19 +58,14 @@
 val ANNOTATION_IN_ALL_STUBS = setOf(
     AnnotationTarget.SIGNATURE_FILE,
     AnnotationTarget.SDK_STUBS_FILE,
-    AnnotationTarget.DOC_STUBS_FILE,
-    AnnotationTarget.INTERNAL
+    AnnotationTarget.DOC_STUBS_FILE
 )
 
 /**
  * Like [ANNOTATION_IN_ALL_STUBS], but limited to SDK stubs, not included in documentation stubs.
  * Example: RecentlyNonNull.
  */
-val ANNOTATION_IN_SDK_STUBS = setOf(
-    AnnotationTarget.SIGNATURE_FILE,
-    AnnotationTarget.SDK_STUBS_FILE,
-    AnnotationTarget.INTERNAL
-)
+val ANNOTATION_IN_SDK_STUBS = setOf(AnnotationTarget.SIGNATURE_FILE, AnnotationTarget.SDK_STUBS_FILE)
 
 /**
  * Like [ANNOTATION_IN_ALL_STUBS], but limited to documentation stubs, not included in SDK stubs.
@@ -78,32 +76,21 @@
 val ANNOTATION_IN_DOC_STUBS_AND_EXTERNAL = setOf(
     AnnotationTarget.SIGNATURE_FILE,
     AnnotationTarget.DOC_STUBS_FILE,
-    AnnotationTarget.EXTERNAL_ANNOTATIONS_FILE,
-    AnnotationTarget.INTERNAL
+    AnnotationTarget.EXTERNAL_ANNOTATIONS_FILE
 )
 
 /** Annotation is API significant: write it into the signature file and into external annotations file. */
-val ANNOTATION_EXTERNAL = setOf(
-    AnnotationTarget.SIGNATURE_FILE,
-    AnnotationTarget.EXTERNAL_ANNOTATIONS_FILE,
-    AnnotationTarget.INTERNAL
-)
+val ANNOTATION_EXTERNAL = setOf(AnnotationTarget.SIGNATURE_FILE, AnnotationTarget.EXTERNAL_ANNOTATIONS_FILE)
 
 /** Write it only into the external annotations file, not the signature file */
-val ANNOTATION_EXTERNAL_ONLY = setOf(
-    AnnotationTarget.EXTERNAL_ANNOTATIONS_FILE,
-    AnnotationTarget.INTERNAL
-)
+val ANNOTATION_EXTERNAL_ONLY = if (options.typedefMode == Options.TypedefMode.INLINE ||
+    options.typedefMode == Options.TypedefMode.NONE) // just here for compatibility purposes
+    setOf(AnnotationTarget.SIGNATURE_FILE, AnnotationTarget.EXTERNAL_ANNOTATIONS_FILE)
+else
+    setOf(AnnotationTarget.EXTERNAL_ANNOTATIONS_FILE)
 
-/** Write it only into the signature file */
-val ANNOTATION_SIGNATURE_ONLY = setOf(
-    AnnotationTarget.SIGNATURE_FILE,
-    AnnotationTarget.INTERNAL
-)
+/** Write it only into the he signature file */
+val ANNOTATION_SIGNATURE_ONLY = setOf(AnnotationTarget.SIGNATURE_FILE)
 
 /** Write it only into the stubs, but don't track it in the signature files. */
-val ANNOTATION_STUBS_ONLY = setOf(
-    AnnotationTarget.SDK_STUBS_FILE,
-    AnnotationTarget.DOC_STUBS_FILE,
-    AnnotationTarget.INTERNAL
-)
+val ANNOTATION_STUBS_ONLY = setOf(AnnotationTarget.SDK_STUBS_FILE, AnnotationTarget.DOC_STUBS_FILE)
diff --git a/src/main/java/com/android/tools/metalava/model/ClassItem.kt b/src/main/java/com/android/tools/metalava/model/ClassItem.kt
index a0d1c42..0cee0cc 100644
--- a/src/main/java/com/android/tools/metalava/model/ClassItem.kt
+++ b/src/main/java/com/android/tools/metalava/model/ClassItem.kt
@@ -417,21 +417,6 @@
         return null
     }
 
-    /**
-     * Finds a method matching the given method that satisfies the given predicate,
-     * considering all methods defined on this class and its super classes
-     */
-    fun findPredicateMethodWithSuper(template: MethodItem, filter: Predicate<Item>?): MethodItem? {
-        val method = findMethod(template, true, true)
-        if (method == null) {
-            return null
-        }
-        if (filter == null || filter.test(method)) {
-            return method
-        }
-        return method.findPredicateSuperMethod(filter)
-    }
-
     /** Finds a given method in this class matching the VM name signature */
     fun findMethodByDesc(
         name: String,
@@ -577,10 +562,7 @@
      * Return methods matching the given predicate. Forcibly includes local
      * methods that override a matching method in an ancestor class.
      */
-    fun filteredMethods(
-        predicate: Predicate<Item>,
-        includeSuperClassMethods: Boolean = false
-    ): Collection<MethodItem> {
+    fun filteredMethods(predicate: Predicate<Item>): Collection<MethodItem> {
         val methods = LinkedHashSet<MethodItem>()
         for (method in methods()) {
             if (predicate.test(method) || method.findPredicateSuperMethod(predicate) != null) {
@@ -590,9 +572,6 @@
                 methods.add(method)
             }
         }
-        if (includeSuperClassMethods) {
-            superClass()?.filteredMethods(predicate, includeSuperClassMethods)?.let { methods += it }
-        }
         return methods
     }
 
diff --git a/src/main/java/com/android/tools/metalava/model/Codebase.kt b/src/main/java/com/android/tools/metalava/model/Codebase.kt
index e8a9a58..cf3036a 100644
--- a/src/main/java/com/android/tools/metalava/model/Codebase.kt
+++ b/src/main/java/com/android/tools/metalava/model/Codebase.kt
@@ -23,7 +23,7 @@
 import com.android.SdkConstants.TAG_USES_SDK
 import com.android.tools.metalava.CodebaseComparator
 import com.android.tools.metalava.ComparisonVisitor
-import com.android.tools.metalava.Issues
+import com.android.tools.metalava.doclava1.Issues
 import com.android.tools.metalava.model.psi.CodePrinter
 import com.android.tools.metalava.model.text.TextBackedAnnotationItem
 import com.android.tools.metalava.model.visitors.ItemVisitor
diff --git a/src/main/java/com/android/tools/metalava/model/DefaultModifierList.kt b/src/main/java/com/android/tools/metalava/model/DefaultModifierList.kt
index 4a9e8e3..0bfd158 100644
--- a/src/main/java/com/android/tools/metalava/model/DefaultModifierList.kt
+++ b/src/main/java/com/android/tools/metalava/model/DefaultModifierList.kt
@@ -119,10 +119,6 @@
         return isSet(SEALED)
     }
 
-    override fun isFunctional(): Boolean {
-        return isSet(FUN)
-    }
-
     override fun isInfix(): Boolean {
         return isSet(INFIX)
     }
@@ -191,10 +187,6 @@
         set(SEALED, sealed)
     }
 
-    override fun setFunctional(functional: Boolean) {
-        set(FUN, functional)
-    }
-
     override fun setInfix(infix: Boolean) {
         set(INFIX, infix)
     }
@@ -316,7 +308,7 @@
         const val DEPRECATED = 1 shl 12
         const val VARARG = 1 shl 13
         const val SEALED = 1 shl 14
-        const val FUN = 1 shl 15
+        // 15 currently unused
         const val INFIX = 1 shl 16
         const val OPERATOR = 1 shl 17
         const val INLINE = 1 shl 18
@@ -330,7 +322,7 @@
          */
         private const val EQUIVALENCE_MASK = VISIBILITY_MASK or STATIC or ABSTRACT or
             FINAL or TRANSIENT or VOLATILE or DEPRECATED or VARARG or
-            SEALED or FUN or INFIX or OPERATOR or SUSPEND or COMPANION
+            SEALED or INFIX or OPERATOR or SUSPEND or COMPANION
 
         private const val COMPAT_EQUIVALENCE_MASK = EQUIVALENCE_MASK or SYNCHRONIZED
     }
diff --git a/src/main/java/com/android/tools/metalava/model/FieldItem.kt b/src/main/java/com/android/tools/metalava/model/FieldItem.kt
index 3cb25cd..e65bda9 100644
--- a/src/main/java/com/android/tools/metalava/model/FieldItem.kt
+++ b/src/main/java/com/android/tools/metalava/model/FieldItem.kt
@@ -198,10 +198,10 @@
                 }
                 is Float -> {
                     writer.print(" = ")
-                    when {
-                        value == Float.POSITIVE_INFINITY -> writer.print("(1.0f/0.0f);")
-                        value == Float.NEGATIVE_INFINITY -> writer.print("(-1.0f/0.0f);")
-                        java.lang.Float.isNaN(value) -> writer.print("(0.0f/0.0f);")
+                    when (value) {
+                        Float.POSITIVE_INFINITY -> writer.print("(1.0f/0.0f);")
+                        Float.NEGATIVE_INFINITY -> writer.print("(-1.0f/0.0f);")
+                        Float.NaN -> writer.print("(0.0f/0.0f);")
                         else -> {
                             writer.print(canonicalizeFloatingPointString(value.toString()))
                             writer.print("f;")
@@ -210,10 +210,10 @@
                 }
                 is Double -> {
                     writer.print(" = ")
-                    when {
-                        value == Double.POSITIVE_INFINITY -> writer.print("(1.0/0.0);")
-                        value == Double.NEGATIVE_INFINITY -> writer.print("(-1.0/0.0);")
-                        java.lang.Double.isNaN(value) -> writer.print("(0.0/0.0);")
+                    when (value) {
+                        Double.POSITIVE_INFINITY -> writer.print("(1.0/0.0);")
+                        Double.NEGATIVE_INFINITY -> writer.print("(-1.0/0.0);")
+                        Double.NaN -> writer.print("(0.0/0.0);")
                         else -> {
                             writer.print(canonicalizeFloatingPointString(value.toString()))
                             writer.print(";")
diff --git a/src/main/java/com/android/tools/metalava/model/IssueConfiguration.kt b/src/main/java/com/android/tools/metalava/model/IssueConfiguration.kt
index 8e9a27e..6b34b13 100644
--- a/src/main/java/com/android/tools/metalava/model/IssueConfiguration.kt
+++ b/src/main/java/com/android/tools/metalava/model/IssueConfiguration.kt
@@ -18,7 +18,7 @@
 
 import com.android.tools.metalava.Options
 import com.android.tools.metalava.Severity
-import com.android.tools.metalava.Issues
+import com.android.tools.metalava.doclava1.Issues
 
 /** An issue configuration is a set of overrides for severities for various [Issues.Issue] */
 class IssueConfiguration {
diff --git a/src/main/java/com/android/tools/metalava/model/MergedCodebase.kt b/src/main/java/com/android/tools/metalava/model/MergedCodebase.kt
deleted file mode 100644
index cdc1d08..0000000
--- a/src/main/java/com/android/tools/metalava/model/MergedCodebase.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.metalava.model
-
-class MergedCodebase(val children: List<Codebase>)
diff --git a/src/main/java/com/android/tools/metalava/model/ModifierList.kt b/src/main/java/com/android/tools/metalava/model/ModifierList.kt
index b0649cb..c3afff6 100644
--- a/src/main/java/com/android/tools/metalava/model/ModifierList.kt
+++ b/src/main/java/com/android/tools/metalava/model/ModifierList.kt
@@ -51,7 +51,6 @@
 
     // Kotlin
     fun isSealed(): Boolean = false
-    fun isFunctional(): Boolean = false
     fun isCompanion(): Boolean = false
     fun isInfix(): Boolean = false
     fun isConst(): Boolean = false
@@ -464,10 +463,6 @@
                 if (list.isNative() && target.isStubsFile()) {
                     writer.write("native ")
                 }
-
-                if (list.isFunctional()) {
-                    writer.write("fun ")
-                }
             }
         }
 
diff --git a/src/main/java/com/android/tools/metalava/model/MutableModifierList.kt b/src/main/java/com/android/tools/metalava/model/MutableModifierList.kt
index 0158013..e71f699 100644
--- a/src/main/java/com/android/tools/metalava/model/MutableModifierList.kt
+++ b/src/main/java/com/android/tools/metalava/model/MutableModifierList.kt
@@ -28,7 +28,6 @@
     fun setVolatile(volatile: Boolean)
     fun setDefault(default: Boolean)
     fun setSealed(sealed: Boolean)
-    fun setFunctional(functional: Boolean)
     fun setInfix(infix: Boolean)
     fun setOperator(operator: Boolean)
     fun setInline(inline: Boolean)
diff --git a/src/main/java/com/android/tools/metalava/model/ParameterItem.kt b/src/main/java/com/android/tools/metalava/model/ParameterItem.kt
index 27e1748..a7194e6 100644
--- a/src/main/java/com/android/tools/metalava/model/ParameterItem.kt
+++ b/src/main/java/com/android/tools/metalava/model/ParameterItem.kt
@@ -41,29 +41,16 @@
     fun publicName(): String?
 
     /**
-     * Returns whether this parameter has a default value. In Kotlin, this is supported directly;
-     * in Java, it's supported via a special annotation, {@literal @DefaultValue("source"). This
-     * does not necessarily imply that the default value is accessible, and we know the body of the
-     * default value.
-     *
-     * @see isDefaultValueKnown
+     * Returns whether this parameter has a default value. In Kotlin, this is supported
+     * directly; in Java, it's supported via a special annotation,
+     * {@literal @DefaultValue("source").
      */
     fun hasDefaultValue(): Boolean
 
     /**
-     * Returns whether this parameter has an accessible default value that we plan to keep. This is
-     * a superset of [hasDefaultValue] - if we are not writing the default values to the signature
-     * file, then the default value might not be available, even though the parameter does have a
-     * default.
-     *
-     * @see hasDefaultValue
-     */
-    fun isDefaultValueKnown(): Boolean
-
-    /**
      * Returns the default value.
      *
-     * **This method should only be called if [isDefaultValueKnown] returned true!** (This
+     * **This method should only be called if [hasDefaultValue] returned true!** (This
      * is necessary since the null return value is a valid default value separate from
      * no default value specified.)
      *
diff --git a/src/main/java/com/android/tools/metalava/model/TypeItem.kt b/src/main/java/com/android/tools/metalava/model/TypeItem.kt
index f4bc0ba..1687d07 100644
--- a/src/main/java/com/android/tools/metalava/model/TypeItem.kt
+++ b/src/main/java/com/android/tools/metalava/model/TypeItem.kt
@@ -112,8 +112,7 @@
     fun convertType(replacementMap: Map<String, String>?, owner: Item? = null): TypeItem
 
     fun convertTypeString(replacementMap: Map<String, String>?): String {
-        val typeString =
-            toTypeString(outerAnnotations = true, innerAnnotations = true, kotlinStyleNulls = false)
+        val typeString = toTypeString(outerAnnotations = true, innerAnnotations = true, kotlinStyleNulls = false)
         return convertTypeString(typeString, replacementMap)
     }
 
@@ -268,8 +267,7 @@
                         // If I do the replacements one letter at a time I end up with C,C,C; if I do the substitutions
                         // simultaneously I get B,C,C. Therefore, we insert "___" as a magical prefix to prevent
                         // scenarios like this, and then we'll drop them afterwards.
-                        string =
-                            string.replace(Regex(pattern = """\b$from\b"""), replacement = "___$to")
+                        string = string.replace(Regex(pattern = """\b$from\b"""), replacement = "___$to")
                     }
                 }
                 string = string.replace("___", "")
@@ -279,92 +277,6 @@
             }
         }
 
-        /**
-         * Convert a type string containing to its lambda representation or return the original.
-         *
-         * E.g.: `"kotlin.jvm.functions.Function1<Integer, String>"` to `"(Integer) -> String"`.
-         */
-        fun toLambdaFormat(typeName: String): String {
-            // Bail if this isn't a Kotlin function type
-            if (!typeName.startsWith(KOTLIN_FUNCTION_PREFIX)) {
-                return typeName
-            }
-
-            // Find the first character after the first opening angle bracket. This will either be
-            // the first character of the paramTypes of the lambda if it has parameters.
-            val paramTypesStart =
-                typeName.indexOf('<', startIndex = KOTLIN_FUNCTION_PREFIX.length) + 1
-
-            // The last type param is always the return type. We find and set these boundaries with
-            // the push down loop below.
-            var paramTypesEnd = -1
-            var returnTypeStart = -1
-
-            // Get the exclusive end of the return type parameter by finding the last closing
-            // angle bracket.
-            val returnTypeEnd = typeName.lastIndexOf('>')
-
-            // Bail if an an unexpected format broke the indexOf's above.
-            if (paramTypesStart <= 0 || paramTypesStart >= returnTypeEnd) {
-                return typeName
-            }
-
-            // This loop looks for the last comma that is not inside the type parameters of a type
-            // parameter. It's a simple push down state machine that stores its depth as a counter
-            // instead of a stack. It runs backwards from the last character of the type parameters
-            // just before the last closing angle bracket to the beginning just before the first
-            // opening angle bracket.
-            var depth = 0
-            for (i in returnTypeEnd - 1 downTo paramTypesStart) {
-                val c = typeName[i]
-
-                // Increase or decrease stack depth on angle brackets
-                when (c) {
-                    '>' -> depth++
-                    '<' -> depth--
-                }
-
-                when {
-                    depth == 0 -> when { // At the top level
-                        c == ',' -> {
-                            // When top level comma is found, mark it as the exclusive end of the
-                            // parameter types and end the loop
-                            paramTypesEnd = i
-                            break
-                        }
-                        !c.isWhitespace() -> {
-                            // Keep moving the start of the return type back until whitespace
-                            returnTypeStart = i
-                        }
-                    }
-                    depth < 0 -> return typeName // Bail, unbalanced nesting
-                }
-            }
-
-            // Bail if some sort of unbalanced nesting occurred or the indices around the comma
-            // appear grossly incorrect.
-            if (depth > 0 || returnTypeStart < 0 || returnTypeStart <= paramTypesEnd) {
-                return typeName
-            }
-
-            return buildString(typeName.length) {
-                append("(")
-
-                // Slice param types, if any, and append them between the parenthesis
-                if (paramTypesEnd > 0) {
-                    append(typeName, paramTypesStart, paramTypesEnd)
-                }
-
-                append(") -> ")
-
-                // Slice out the return type param and append it after the arrow
-                append(typeName, returnTypeStart, returnTypeEnd)
-            }
-        }
-
-        /** Prefix of Kotlin JVM function types, used for lambdas. */
-        private const val KOTLIN_FUNCTION_PREFIX = "kotlin.jvm.functions.Function"
-
         // Copied from doclava1
         fun toSlashFormat(typeName: String): String {
             var name = typeName
diff --git a/src/main/java/com/android/tools/metalava/model/psi/CodePrinter.kt b/src/main/java/com/android/tools/metalava/model/psi/CodePrinter.kt
index 44323b2..97bfad7 100644
--- a/src/main/java/com/android/tools/metalava/model/psi/CodePrinter.kt
+++ b/src/main/java/com/android/tools/metalava/model/psi/CodePrinter.kt
@@ -18,7 +18,7 @@
 
 import com.android.SdkConstants.DOT_CLASS
 import com.android.tools.lint.detector.api.ConstantEvaluator
-import com.android.tools.metalava.Issues
+import com.android.tools.metalava.doclava1.Issues
 import com.android.tools.metalava.model.Codebase
 import com.android.tools.metalava.model.Item
 import com.android.tools.metalava.model.canonicalizeFloatingPointString
@@ -414,20 +414,20 @@
                     return value.toString()
                 }
                 is Float -> {
-                    return when {
-                        value == Float.POSITIVE_INFINITY -> "(1.0f/0.0f)"
-                        value == Float.NEGATIVE_INFINITY -> "(-1.0f/0.0f)"
-                        java.lang.Float.isNaN(value) -> "(0.0f/0.0f)"
+                    return when (value) {
+                        Float.POSITIVE_INFINITY -> "(1.0f/0.0f)"
+                        Float.NEGATIVE_INFINITY -> "(-1.0f/0.0f)"
+                        Float.NaN -> "(0.0f/0.0f)"
                         else -> {
                             canonicalizeFloatingPointString(value.toString()) + "f"
                         }
                     }
                 }
                 is Double -> {
-                    return when {
-                        value == Double.POSITIVE_INFINITY -> "(1.0/0.0)"
-                        value == Double.NEGATIVE_INFINITY -> "(-1.0/0.0)"
-                        java.lang.Double.isNaN(value) -> "(0.0/0.0)"
+                    return when (value) {
+                        Double.POSITIVE_INFINITY -> "(1.0/0.0)"
+                        Double.NEGATIVE_INFINITY -> "(-1.0/0.0)"
+                        Double.NaN -> "(0.0/0.0)"
                         else -> {
                             canonicalizeFloatingPointString(value.toString())
                         }
@@ -457,20 +457,20 @@
                 is Byte -> Integer.toHexString(constant.toInt())
                 is Short -> Integer.toHexString(constant.toInt())
                 is Float -> {
-                    when {
-                        constant == Float.POSITIVE_INFINITY -> "Float.POSITIVE_INFINITY"
-                        constant == Float.NEGATIVE_INFINITY -> "Float.NEGATIVE_INFINITY"
-                        java.lang.Float.isNaN(constant) -> "Float.NaN"
+                    when (constant) {
+                        Float.POSITIVE_INFINITY -> "Float.POSITIVE_INFINITY"
+                        Float.NEGATIVE_INFINITY -> "Float.NEGATIVE_INFINITY"
+                        Float.NaN -> "Float.NaN"
                         else -> {
                             "${canonicalizeFloatingPointString(constant.toString())}F"
                         }
                     }
                 }
                 is Double -> {
-                    when {
-                        constant == Double.POSITIVE_INFINITY -> "Double.POSITIVE_INFINITY"
-                        constant == Double.NEGATIVE_INFINITY -> "Double.NEGATIVE_INFINITY"
-                        java.lang.Double.isNaN(constant) -> "Double.NaN"
+                    when (constant) {
+                        Double.POSITIVE_INFINITY -> "Double.POSITIVE_INFINITY"
+                        Double.NEGATIVE_INFINITY -> "Double.NEGATIVE_INFINITY"
+                        Double.NaN -> "Double.NaN"
                         else -> {
                             canonicalizeFloatingPointString(constant.toString())
                         }
@@ -504,15 +504,15 @@
                     return true
                 }
                 is Float -> {
-                    return when {
-                        v == Float.POSITIVE_INFINITY -> {
+                    return when (v) {
+                        Float.POSITIVE_INFINITY -> {
                             // This convention (displaying fractions) is inherited from doclava
                             sb.append("(1.0f/0.0f)"); true
                         }
-                        v == Float.NEGATIVE_INFINITY -> {
+                        Float.NEGATIVE_INFINITY -> {
                             sb.append("(-1.0f/0.0f)"); true
                         }
-                        java.lang.Float.isNaN(v) -> {
+                        Float.NaN -> {
                             sb.append("(0.0f/0.0f)"); true
                         }
                         else -> {
@@ -522,15 +522,15 @@
                     }
                 }
                 is Double -> {
-                    return when {
-                        v == Double.POSITIVE_INFINITY -> {
+                    return when (v) {
+                        Double.POSITIVE_INFINITY -> {
                             // This convention (displaying fractions) is inherited from doclava
                             sb.append("(1.0/0.0)"); true
                         }
-                        v == Double.NEGATIVE_INFINITY -> {
+                        Double.NEGATIVE_INFINITY -> {
                             sb.append("(-1.0/0.0)"); true
                         }
-                        java.lang.Double.isNaN(v) -> {
+                        Double.NaN -> {
                             sb.append("(0.0/0.0)"); true
                         }
                         else -> {
diff --git a/src/main/java/com/android/tools/metalava/model/psi/Javadoc.kt b/src/main/java/com/android/tools/metalava/model/psi/Javadoc.kt
index 96801c2..e96fae5 100644
--- a/src/main/java/com/android/tools/metalava/model/psi/Javadoc.kt
+++ b/src/main/java/com/android/tools/metalava/model/psi/Javadoc.kt
@@ -16,7 +16,7 @@
 
 package com.android.tools.metalava.model.psi
 
-import com.android.tools.metalava.Issues
+import com.android.tools.metalava.doclava1.Issues
 import com.android.tools.metalava.model.ClassItem
 import com.android.tools.metalava.model.Item
 import com.android.tools.metalava.model.PackageItem
@@ -191,11 +191,11 @@
 }
 
 fun findFirstTag(docComment: PsiDocComment): PsiDocTag? {
-    return docComment.tags.asSequence().minByOrNull { it.textRange.startOffset }
+    return docComment.tags.asSequence().minBy { it.textRange.startOffset }
 }
 
 fun findLastTag(docComment: PsiDocComment): PsiDocTag? {
-    return docComment.tags.asSequence().maxByOrNull { it.textRange.startOffset }
+    return docComment.tags.asSequence().maxBy { it.textRange.startOffset }
 }
 
 fun findTagEnd(tag: PsiDocTag): Int {
@@ -732,8 +732,6 @@
 
     val reference = extractReference(element)
     val referenceText = reference?.element?.text ?: element.text
-    val customLinkText = extractCustomLinkText(element)
-    val displayText = customLinkText?.text ?: referenceText
     if (!PREPEND_LOCAL_CLASS && referenceText.startsWith("#")) {
         val suffix = element.text
         if (suffix.contains("(") && suffix.contains(")")) {
@@ -775,7 +773,7 @@
                             sb.append(suffix)
                         }
                         sb.append(' ')
-                        sb.append(displayText)
+                        sb.append(referenceText)
                         sb.append("}")
                         return true
                     }
@@ -833,8 +831,8 @@
                         val suffix = text.substring(text.indexOf(referenceText) + referenceText.length)
                         "@see $qualifiedName$suffix"
                     }
-                    text.startsWith("{") -> "{@$name $qualifiedName $displayText}"
-                    else -> "@$name $qualifiedName $displayText"
+                    text.startsWith("{") -> "{@$name $qualifiedName $referenceText}"
+                    else -> "@$name $qualifiedName $referenceText"
                 }
                 sb.append(append)
                 return true
@@ -908,7 +906,7 @@
                         close++
                     }
                     val memberPart = text.substring(nameEnd, close)
-                    val append = "${text.substring(0, start)}$qualifiedName$memberPart $displayText}"
+                    val append = "${text.substring(0, start)}$qualifiedName$memberPart $referenceText}"
                     sb.append(append)
                     return true
                 }
@@ -1031,13 +1029,3 @@
     val child = salientElement.firstChild
     return if (child !is PsiReference) null else child
 }
-
-private fun extractCustomLinkText(tag: PsiDocTag): PsiDocToken? {
-    val dataElements = tag.dataElements
-    if (dataElements.isEmpty()) {
-        return null
-    }
-    val salientElement: PsiElement =
-        dataElements.lastOrNull { it !is PsiWhiteSpace && it !is PsiDocMethodOrFieldRef } ?: return null
-    return if (salientElement !is PsiDocToken) null else salientElement
-}
diff --git a/src/main/java/com/android/tools/metalava/model/psi/PsiAnnotationItem.kt b/src/main/java/com/android/tools/metalava/model/psi/PsiAnnotationItem.kt
index c9665b2..6561881 100644
--- a/src/main/java/com/android/tools/metalava/model/psi/PsiAnnotationItem.kt
+++ b/src/main/java/com/android/tools/metalava/model/psi/PsiAnnotationItem.kt
@@ -65,7 +65,7 @@
     }
 
     override fun resolve(): ClassItem? {
-        return codebase.findOrCreateClass(originalName ?: return null)
+        return codebase.findClass(originalName ?: return null)
     }
 
     override fun isNonNull(): Boolean {
@@ -217,8 +217,7 @@
                                 val initializer = resolved.initializer
                                 if (initializer != null) {
                                     val fieldItem = cls.findField(resolved.name)
-                                    if (fieldItem == null || fieldItem.isHiddenOrRemoved() ||
-                                            !fieldItem.isPublic) {
+                                    if (fieldItem == null || fieldItem.isHiddenOrRemoved()) {
                                         // Use the literal value instead
                                         val source = getConstantSource(initializer)
                                         if (source != null) {
diff --git a/src/main/java/com/android/tools/metalava/model/psi/PsiBasedCodebase.kt b/src/main/java/com/android/tools/metalava/model/psi/PsiBasedCodebase.kt
index 16579f5..ca97060 100644
--- a/src/main/java/com/android/tools/metalava/model/psi/PsiBasedCodebase.kt
+++ b/src/main/java/com/android/tools/metalava/model/psi/PsiBasedCodebase.kt
@@ -20,7 +20,7 @@
 import com.android.tools.lint.UastEnvironment
 import com.android.tools.metalava.ANDROIDX_NONNULL
 import com.android.tools.metalava.ANDROIDX_NULLABLE
-import com.android.tools.metalava.Issues
+import com.android.tools.metalava.doclava1.Issues
 import com.android.tools.metalava.model.ClassItem
 import com.android.tools.metalava.model.DefaultCodebase
 import com.android.tools.metalava.model.Item
diff --git a/src/main/java/com/android/tools/metalava/model/psi/PsiClassItem.kt b/src/main/java/com/android/tools/metalava/model/psi/PsiClassItem.kt
index 84f3798..4de63e1 100644
--- a/src/main/java/com/android/tools/metalava/model/psi/PsiClassItem.kt
+++ b/src/main/java/com/android/tools/metalava/model/psi/PsiClassItem.kt
@@ -39,10 +39,8 @@
 import com.intellij.psi.SyntheticElement
 import com.intellij.psi.impl.source.PsiClassReferenceType
 import com.intellij.psi.util.PsiUtil
-import org.jetbrains.kotlin.psi.KtParameter
 import org.jetbrains.kotlin.psi.KtProperty
 import org.jetbrains.kotlin.psi.KtPropertyAccessor
-import org.jetbrains.kotlin.psi.psiUtil.isPropertyParameter
 import org.jetbrains.uast.UClass
 import org.jetbrains.uast.UFile
 import org.jetbrains.uast.UMethod
@@ -343,7 +341,7 @@
         if (replacementMap.isEmpty()) {
             newMethod = PsiMethodItem.create(codebase, this, method)
         } else {
-            val stub = method.toStubForCloning(replacementMap)
+            val stub = method.toStub(replacementMap)
             val psiMethod = codebase.createPsiMethod(stub, psiClass)
             newMethod = PsiMethodItem.create(codebase, this, psiMethod)
             newMethod.inheritedMethod = method.inheritedMethod
@@ -465,26 +463,11 @@
                 )
             }
 
-            // create methods
             val constructors: MutableList<PsiConstructorItem> = ArrayList(5)
-            var hasConstructorWithOnlyOptionalArgs = false
-            var noArgConstructor: PsiConstructorItem? = null
             for (psiMethod in psiMethods) {
                 if (psiMethod.isConstructor) {
                     val constructor = PsiConstructorItem.create(codebase, item, psiMethod)
-                    if (constructor.areAllParametersOptional()) {
-                        if (constructor.parameters().count() > 0) {
-                            constructors.add(constructor)
-                            // uast reported a constructor having only optional arguments, so if we
-                            // later find an explicit no-arg constructor, we can skip it because
-                            // its existence is implied
-                            hasConstructorWithOnlyOptionalArgs = true
-                        } else {
-                            noArgConstructor = constructor
-                        }
-                    } else {
-                        constructors.add(constructor)
-                    }
+                    constructors.add(constructor)
                 } else if (classType == ClassType.ENUM &&
                     !compatibility.defaultEnumMethods &&
                     psiMethod is SyntheticElement
@@ -495,9 +478,6 @@
                     methods.add(method)
                 }
             }
-            if (noArgConstructor != null && !hasConstructorWithOnlyOptionalArgs) {
-                constructors.add(noArgConstructor)
-            }
 
             if (hasImplicitDefaultConstructor) {
                 assert(constructors.isEmpty())
@@ -543,24 +523,14 @@
                             continue
                         }
                         val sourcePsi = method.sourcePsi
-                        if (sourcePsi is KtProperty ||
-                            sourcePsi is KtPropertyAccessor ||
-                            sourcePsi is KtParameter
-                        ) {
-                            if (method.name.startsWith("set") ||
-                                method.name.startsWith("component")
-                            ) {
+                        if (sourcePsi is KtProperty || sourcePsi is KtPropertyAccessor) {
+                            if (method.name.startsWith("set")) {
                                 continue
                             }
                             val name =
                                 when (sourcePsi) {
                                     is KtProperty -> sourcePsi.name
                                     is KtPropertyAccessor -> sourcePsi.property.name
-                                    is KtParameter -> {
-                                        if (sourcePsi.isPropertyParameter()) {
-                                            sourcePsi.name
-                                        } else null
-                                    }
                                     else -> null
                                 } ?: continue
                             val psiType = method.returnType ?: continue
@@ -752,4 +722,4 @@
     val modifiers = modifierList ?: return false
     return !(modifiers.hasModifierProperty(PsiModifier.PUBLIC) ||
         modifiers.hasModifierProperty(PsiModifier.PROTECTED))
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/android/tools/metalava/model/psi/PsiItem.kt b/src/main/java/com/android/tools/metalava/model/psi/PsiItem.kt
index 18b6b9d..125cc05 100644
--- a/src/main/java/com/android/tools/metalava/model/psi/PsiItem.kt
+++ b/src/main/java/com/android/tools/metalava/model/psi/PsiItem.kt
@@ -225,10 +225,6 @@
         modifiers.setOwner(this)
     }
 
-    override fun isJava(): Boolean {
-        return !isKotlin()
-    }
-
     override fun isKotlin(): Boolean {
         return isKotlin(element)
     }
diff --git a/src/main/java/com/android/tools/metalava/model/psi/PsiMethodItem.kt b/src/main/java/com/android/tools/metalava/model/psi/PsiMethodItem.kt
index 8320709..264dda1 100644
--- a/src/main/java/com/android/tools/metalava/model/psi/PsiMethodItem.kt
+++ b/src/main/java/com/android/tools/metalava/model/psi/PsiMethodItem.kt
@@ -32,7 +32,6 @@
 import com.intellij.psi.util.TypeConversionUtil
 import org.intellij.lang.annotations.Language
 import org.jetbrains.kotlin.psi.KtNamedFunction
-import org.jetbrains.kotlin.psi.KtParameter
 import org.jetbrains.kotlin.psi.KtProperty
 import org.jetbrains.kotlin.psi.KtPropertyAccessor
 import org.jetbrains.uast.UClass
@@ -172,8 +171,7 @@
     override fun isKotlinProperty(): Boolean {
         return psiMethod is KotlinUMethod && (
             psiMethod.sourcePsi is KtProperty ||
-            psiMethod.sourcePsi is KtPropertyAccessor ||
-            psiMethod.sourcePsi is KtParameter && (psiMethod.sourcePsi as KtParameter).hasValOrVar())
+            psiMethod.sourcePsi is KtPropertyAccessor)
     }
 
     override fun findThrownExceptions(): Set<ClassItem> {
@@ -220,15 +218,6 @@
         return exceptions
     }
 
-    fun areAllParametersOptional(): Boolean {
-        for (param in parameters) {
-            if (!param.hasDefaultValue()) {
-                return false
-            }
-        }
-        return true
-    }
-
     override fun defaultValue(): String {
         if (psiMethod is PsiAnnotationMethod) {
             val value = psiMethod.defaultValue
@@ -288,16 +277,8 @@
     }
     */
 
-    /**
-     * Converts the method to a stub that can be converted back to a PsiMethod.
-     *
-     * Note: This must not be used for emitting stub jars. For that, see
-     * [com.android.tools.metalava.stub.StubWriter].
-     *
-     * @param replacementMap a map that specifies replacement types for formal type parameters.
-     */
     @Language("JAVA")
-    fun toStubForCloning(replacementMap: Map<String, String> = emptyMap()): String {
+    fun toStub(replacementMap: Map<String, String> = emptyMap()): String {
         val method = this
         // There are type variables; we have to recreate the method signature
         val sb = StringBuilder(100)
@@ -305,7 +286,7 @@
         val modifierString = StringWriter()
         ModifierList.write(
             modifierString, method.modifiers, method,
-            target = AnnotationTarget.INTERNAL,
+            target = AnnotationTarget.SDK_STUBS_FILE,
             removeAbstract = false,
             removeFinal = false,
             addPublic = true
@@ -333,7 +314,7 @@
             val parameterModifierString = StringWriter()
             ModifierList.write(
                 parameterModifierString, parameter.modifiers, parameter,
-                target = AnnotationTarget.INTERNAL
+                target = AnnotationTarget.SDK_STUBS_FILE
             )
             sb.append(parameterModifierString.toString())
             sb.append(parameter.type().convertTypeString(replacementMap))
@@ -478,4 +459,4 @@
 
     override fun toString(): String = "${if (isConstructor()) "constructor" else "method"} ${
     containingClass.qualifiedName()}.${name()}(${parameters().joinToString { it.type().toSimpleType() }})"
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/android/tools/metalava/model/psi/PsiModifierItem.kt b/src/main/java/com/android/tools/metalava/model/psi/PsiModifierItem.kt
index 26545f1..faa7292 100644
--- a/src/main/java/com/android/tools/metalava/model/psi/PsiModifierItem.kt
+++ b/src/main/java/com/android/tools/metalava/model/psi/PsiModifierItem.kt
@@ -19,6 +19,7 @@
 import com.android.tools.metalava.ANDROIDX_VISIBLE_FOR_TESTING
 import com.android.tools.metalava.ANDROID_SUPPORT_VISIBLE_FOR_TESTING
 import com.android.tools.metalava.ATTR_OTHERWISE
+import com.android.tools.metalava.METALAVA_SYNTHETIC_SUFFIX
 import com.android.tools.metalava.model.AnnotationItem
 import com.android.tools.metalava.model.Codebase
 import com.android.tools.metalava.model.DefaultModifierList
@@ -35,10 +36,8 @@
 import org.jetbrains.kotlin.asJava.elements.KtLightNullabilityAnnotation
 import org.jetbrains.kotlin.lexer.KtTokens
 import org.jetbrains.kotlin.psi.KtModifierList
-import org.jetbrains.kotlin.psi.KtModifierListOwner
 import org.jetbrains.kotlin.psi.KtNamedFunction
 import org.jetbrains.kotlin.psi.KtPropertyAccessor
-import org.jetbrains.kotlin.psi.psiUtil.hasFunModifier
 import org.jetbrains.uast.UAnnotated
 import org.jetbrains.uast.UMethod
 import org.jetbrains.uast.UVariable
@@ -153,19 +152,17 @@
                 if (ktModifierList.hasModifier(KtTokens.COMPANION_KEYWORD)) {
                     flags = flags or COMPANION
                 }
-                if (ktModifierList.hasFunModifier()) {
-                    flags = flags or FUN
-                }
-            }
-            // Methods that are property accessors inherit visibility from the source element
-            if (element is UMethod && (element.sourceElement is KtPropertyAccessor)) {
-                val sourceElement = element.sourceElement
-                if (sourceElement is KtModifierListOwner) {
-                    val sourceModifierList = sourceElement.modifierList
-                    if (sourceModifierList != null) {
-                        if (sourceModifierList.hasModifier(KtTokens.INTERNAL_KEYWORD)) {
-                            visibilityFlags = INTERNAL
-                        }
+            } else {
+                // UAST returns a null modifierList.kotlinOrigin for get/set methods for
+                // properties
+                if (element is UMethod &&
+                    (
+                        element.sourceElement is KtPropertyAccessor
+                    )
+                ) {
+                    // If the name contains the marker of an internal method, mark it internal
+                    if (element.name.endsWith("\$$METALAVA_SYNTHETIC_SUFFIX")) {
+                        visibilityFlags = INTERNAL
                     }
                 }
             }
@@ -280,15 +277,7 @@
         fun create(codebase: PsiBasedCodebase, original: PsiModifierItem): PsiModifierItem {
             val originalAnnotations = original.annotations ?: return PsiModifierItem(codebase, original.flags)
             val copy: MutableList<AnnotationItem> = ArrayList(originalAnnotations.size)
-            originalAnnotations.mapTo(copy) { item ->
-                when (item) {
-                    is PsiAnnotationItem -> PsiAnnotationItem.create(codebase, item)
-                    is UAnnotationItem -> UAnnotationItem.create(codebase, item)
-                    else -> {
-                        throw Exception("Unexpected annotation type ${item::class.qualifiedName}")
-                    }
-                }
-            }
+            originalAnnotations.mapTo(copy) { PsiAnnotationItem.create(codebase, it as PsiAnnotationItem) }
             return PsiModifierItem(codebase, original.flags, copy)
         }
     }
diff --git a/src/main/java/com/android/tools/metalava/model/psi/PsiParameterItem.kt b/src/main/java/com/android/tools/metalava/model/psi/PsiParameterItem.kt
index 2587fc9..de137d8 100644
--- a/src/main/java/com/android/tools/metalava/model/psi/PsiParameterItem.kt
+++ b/src/main/java/com/android/tools/metalava/model/psi/PsiParameterItem.kt
@@ -19,11 +19,10 @@
 import com.android.tools.metalava.model.MethodItem
 import com.android.tools.metalava.model.ParameterItem
 import com.android.tools.metalava.model.TypeItem
-import com.android.tools.metalava.model.VisibilityLevel
 import com.android.tools.metalava.model.psi.CodePrinter.Companion.constantToSource
 import com.intellij.psi.PsiParameter
 import org.jetbrains.kotlin.psi.KtConstantExpression
-import org.jetbrains.kotlin.psi.KtFunction
+import org.jetbrains.kotlin.psi.KtNamedFunction
 import org.jetbrains.kotlin.psi.KtParameter
 import org.jetbrains.uast.UExpression
 import org.jetbrains.uast.UastFacade
@@ -53,13 +52,6 @@
             if (isReceiver()) {
                 return null
             }
-            // Hardcode parameter name for the generated suspend function continuation parameter
-            if (containingMethod.modifiers.isSuspend() &&
-                    "kotlin.coroutines.Continuation" == type.asClass()?.qualifiedName() &&
-                    containingMethod.parameters().size - 1 == parameterIndex
-            ) {
-                return "p"
-            }
             return name
         } else {
             // Java: Look for @ParameterName annotation
@@ -72,9 +64,7 @@
         return null
     }
 
-    override fun hasDefaultValue(): Boolean = isDefaultValueKnown()
-
-    override fun isDefaultValueKnown(): Boolean {
+    override fun hasDefaultValue(): Boolean {
         return if (isKotlin(psiParameter)) {
             getKtParameter()?.hasDefaultValue() ?: false && defaultValue() != INVALID_VALUE
         } else {
@@ -88,7 +78,7 @@
 
     private fun getKtParameter(): KtParameter? {
         val ktParameters =
-            ((containingMethod.psiMethod as? KotlinUMethod)?.sourcePsi as? KtFunction)?.valueParameters
+            ((containingMethod.psiMethod as? KotlinUMethod)?.sourcePsi as? KtNamedFunction)?.valueParameters
                 ?: return null
 
         // Perform matching based on parameter names, because indices won't work in the
@@ -198,7 +188,7 @@
         ): PsiParameterItem {
             val name = psiParameter.name
             val commentText = "" // no javadocs on individual parameters
-            val modifiers = createParameterModifiers(codebase, psiParameter, commentText)
+            val modifiers = modifiers(codebase, psiParameter, commentText)
             val type = codebase.getType(psiParameter.type)
             val parameter = PsiParameterItem(
                 codebase = codebase,
@@ -237,28 +227,10 @@
             return original.map { create(codebase, it as PsiParameterItem) }
         }
 
-        fun createParameterModifiers(
-            codebase: PsiBasedCodebase,
-            psiParameter: PsiParameter,
-            commentText: String
-        ): PsiModifierItem {
-            val modifiers = modifiers(codebase, psiParameter, commentText)
-            // Method parameters don't have a visibility level; they are visible to anyone that can
-            // call their method. However, Kotlin constructors sometimes appear to specify the
-            // visibility of a constructor parameter by putting visibility inside the constructor
-            // signature. This is really to indicate that the matching property should have the
-            // mentioned visibility.
-            // If the method parameter seems to specify a visibility level, we correct it back to
-            // the default, here, to ensure we don't attempt to incorrectly emit this information
-            // into a signature file.
-            modifiers.setVisibilityLevel(VisibilityLevel.PACKAGE_PRIVATE)
-            return modifiers
-        }
-
         /**
          * Private marker return value from [#computeDefaultValue] signifying that the parameter
          * has a default value but we were unable to compute a suitable static string representation for it
          */
         private const val INVALID_VALUE = "__invalid_value__"
     }
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/android/tools/metalava/model/psi/UAnnotationItem.kt b/src/main/java/com/android/tools/metalava/model/psi/UAnnotationItem.kt
index d5d3056..a2c6f00 100644
--- a/src/main/java/com/android/tools/metalava/model/psi/UAnnotationItem.kt
+++ b/src/main/java/com/android/tools/metalava/model/psi/UAnnotationItem.kt
@@ -64,7 +64,7 @@
     }
 
     override fun resolve(): ClassItem? {
-        return codebase.findOrCreateClass(originalName ?: return null)
+        return codebase.findClass(originalName ?: return null)
     }
 
     override fun isNonNull(): Boolean {
diff --git a/src/main/java/com/android/tools/metalava/model/text/ApiFile.java b/src/main/java/com/android/tools/metalava/model/text/ApiFile.java
index a3e9146..c89a9c7 100644
--- a/src/main/java/com/android/tools/metalava/model/text/ApiFile.java
+++ b/src/main/java/com/android/tools/metalava/model/text/ApiFile.java
@@ -684,10 +684,6 @@
                     modifiers.setVarArg(true);
                     token = tokenizer.requireToken();
                     break;
-                case "fun":
-                    modifiers.setFunctional(true);
-                    token = tokenizer.requireToken();
-                    break;
                 default:
                     break processModifiers;
             }
@@ -824,12 +820,7 @@
             }
 
             // Each item can be
-            // optional annotations optional-modifiers type-with-use-annotations-and-generics optional-name optional-equals-default-value
-
-            // Used to represent the presence of a default value, instead of showing the entire
-            // default value
-            boolean hasDefaultValue = token.equals("optional");
-            if (hasDefaultValue) { token = tokenizer.requireToken(); }
+            // annotations optional-modifiers type-with-use-annotations-and-generics optional-name optional-equals-default-value
 
             // Metalava: including annotations in file now
             List<String> annotations = getAnnotations(tokenizer, token);
@@ -874,7 +865,7 @@
                 publicName = null;
             }
 
-            String defaultValue = TextParameterItemKt.UNKNOWN_DEFAULT_VALUE;
+            String defaultValue = TextParameterItemKt.NO_DEFAULT_VALUE;
             if ("=".equals(token)) {
                 defaultValue = tokenizer.requireToken(true);
                 StringBuilder sb = new StringBuilder(defaultValue);
@@ -915,10 +906,6 @@
                 defaultValue = sb.toString();
             }
 
-            if (!defaultValue.equals(TextParameterItemKt.UNKNOWN_DEFAULT_VALUE)) {
-                hasDefaultValue = true;
-            }
-
             if (",".equals(token)) {
                 token = tokenizer.requireToken();
             } else if (")".equals(token)) {
@@ -926,7 +913,7 @@
                 throw new ApiParseException("expected , or ), found " + token, tokenizer);
             }
 
-            method.addParameter(new TextParameterItem(api, method, name, publicName, hasDefaultValue, defaultValue, index,
+            method.addParameter(new TextParameterItem(api, method, name, publicName, defaultValue, index,
                 typeInfo, modifiers, tokenizer.pos()));
             if (modifiers.isVarArg()) {
                 method.setVarargs(true);
diff --git a/src/main/java/com/android/tools/metalava/model/text/TextClassItem.kt b/src/main/java/com/android/tools/metalava/model/text/TextClassItem.kt
index b13b09a..28d1e59 100644
--- a/src/main/java/com/android/tools/metalava/model/text/TextClassItem.kt
+++ b/src/main/java/com/android/tools/metalava/model/text/TextClassItem.kt
@@ -252,7 +252,7 @@
         assert(emit == (position != SourcePositionInfo.UNKNOWN))
         return emit
     }
-    override fun toString(): String = "class ${qualifiedName()}"
+    override fun toString(): String = qualifiedName()
 
     override fun mapTypeVariables(target: ClassItem): Map<String, String> {
         return emptyMap()
diff --git a/src/main/java/com/android/tools/metalava/model/text/TextParameterItem.kt b/src/main/java/com/android/tools/metalava/model/text/TextParameterItem.kt
index 5802e44..690db47 100644
--- a/src/main/java/com/android/tools/metalava/model/text/TextParameterItem.kt
+++ b/src/main/java/com/android/tools/metalava/model/text/TextParameterItem.kt
@@ -19,15 +19,14 @@
 import com.android.tools.metalava.model.MethodItem
 import com.android.tools.metalava.model.ParameterItem
 
-const val UNKNOWN_DEFAULT_VALUE = "__unknown_default_value__"
+const val NO_DEFAULT_VALUE = "__no_default_value__"
 
 class TextParameterItem(
     codebase: TextCodebase,
     private val containingMethod: TextMethodItem,
     private var name: String,
     private var publicName: String?,
-    private val hasDefaultValue: Boolean,
-    private var defaultValueBody: String? = UNKNOWN_DEFAULT_VALUE,
+    private var defaultValue: String? = NO_DEFAULT_VALUE,
     override val parameterIndex: Int,
     private var type: TextTypeItem,
     modifiers: TextModifiers,
@@ -48,9 +47,8 @@
     override fun type(): TextTypeItem = type
     override fun name(): String = name
     override fun publicName(): String? = publicName
-    override fun hasDefaultValue(): Boolean = hasDefaultValue
-    override fun isDefaultValueKnown(): Boolean = defaultValueBody != UNKNOWN_DEFAULT_VALUE
-    override fun defaultValue(): String? = defaultValueBody
+    override fun hasDefaultValue(): Boolean = defaultValue != NO_DEFAULT_VALUE
+    override fun defaultValue(): String? = defaultValue
     override fun containingMethod(): MethodItem = containingMethod
 
     override fun equals(other: Any?): Boolean {
diff --git a/src/main/java/com/android/tools/metalava/model/visitors/ApiVisitor.kt b/src/main/java/com/android/tools/metalava/model/visitors/ApiVisitor.kt
index 64aca53..8186e08 100644
--- a/src/main/java/com/android/tools/metalava/model/visitors/ApiVisitor.kt
+++ b/src/main/java/com/android/tools/metalava/model/visitors/ApiVisitor.kt
@@ -17,7 +17,7 @@
 package com.android.tools.metalava.model.visitors
 
 import com.android.tools.metalava.Options
-import com.android.tools.metalava.ApiPredicate
+import com.android.tools.metalava.doclava1.ApiPredicate
 import com.android.tools.metalava.model.ClassItem
 import com.android.tools.metalava.model.FieldItem
 import com.android.tools.metalava.model.Item
diff --git a/src/main/java/com/android/tools/metalava/stub/StubWriter.kt b/src/main/java/com/android/tools/metalava/stub/StubWriter.kt
index 2418379..fd148fc 100644
--- a/src/main/java/com/android/tools/metalava/stub/StubWriter.kt
+++ b/src/main/java/com/android/tools/metalava/stub/StubWriter.kt
@@ -16,9 +16,9 @@
 
 package com.android.tools.metalava.stub
 
-import com.android.tools.metalava.ApiPredicate
-import com.android.tools.metalava.FilterPredicate
-import com.android.tools.metalava.Issues
+import com.android.tools.metalava.doclava1.ApiPredicate
+import com.android.tools.metalava.doclava1.FilterPredicate
+import com.android.tools.metalava.doclava1.Issues
 import com.android.tools.metalava.model.AnnotationTarget
 import com.android.tools.metalava.model.ClassItem
 import com.android.tools.metalava.model.Codebase
@@ -161,13 +161,8 @@
 
     private fun getClassFile(classItem: ClassItem): File {
         assert(classItem.containingClass() == null) { "Should only be called on top level classes" }
-        val packageDir = getPackageDir(classItem.containingPackage())
-
-        return if (classItem.isKotlin() && options.kotlinStubs) {
-            File(packageDir, "${classItem.simpleName()}.kt")
-        } else {
-            File(packageDir, "${classItem.simpleName()}.java")
-        }
+        // TODO: Look up compilation unit language
+        return File(getPackageDir(classItem.containingPackage()), "${classItem.simpleName()}.java")
     }
 
     /**
@@ -249,7 +244,11 @@
     docStubs: Boolean
 ) {
     if (options.includeDocumentationInStubs || docStubs) {
-        val documentation = item.fullyQualifiedDocumentation()
+        val documentation = if (docStubs) {
+            item.fullyQualifiedDocumentation()
+        } else {
+            item.documentation
+        }
         if (documentation.isNotBlank()) {
             val trimmed = trimDocIndent(documentation)
             writer.println(trimmed)
diff --git a/src/main/resources/version.properties b/src/main/resources/version.properties
index 87cce1a..62a299c 100644
--- a/src/main/resources/version.properties
+++ b/src/main/resources/version.properties
@@ -2,4 +2,4 @@
 # Version definition
 # This file is read by gradle build scripts, but also packaged with metalava
 # as a resource for the Version classes to read.
-metalavaVersion=1.0.0-alpha03
+metalavaVersion=1.0.0-alpha01
diff --git a/src/test/java/com/android/tools/metalava/AnnotationsMergerTest.kt b/src/test/java/com/android/tools/metalava/AnnotationsMergerTest.kt
index 8193640..751588e 100644
--- a/src/test/java/com/android/tools/metalava/AnnotationsMergerTest.kt
+++ b/src/test/java/com/android/tools/metalava/AnnotationsMergerTest.kt
@@ -169,12 +169,7 @@
                     method @androidx.annotation.NonNull public test.pkg.Appendable append(@androidx.annotation.Nullable java.lang.CharSequence);
                   }
                 }
-                """,
-            expectedIssues = """
-                TESTROOT/merged-annotations.txt:4: warning: qualifier annotations were given for method test.pkg.Appendable.append2(CharSequence) but no matching item was found [UnmatchedMergeAnnotation]
-                TESTROOT/merged-annotations.txt:5: warning: qualifier annotations were given for method test.pkg.Appendable.reverse(String) but no matching item was found [UnmatchedMergeAnnotation]
-                TESTROOT/merged-annotations.txt:7: warning: qualifier annotations were given for class test.pkg.RandomClass but no matching item was found [UnmatchedMergeAnnotation]
-            """
+                """
         )
     }
 
@@ -261,27 +256,23 @@
                     @NonNull Appendable append(@Nullable java.lang.CharSequence csq);
                 }
                 """,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public interface Appendable {
-                    @android.annotation.NonNull
-                    public test.pkg.Appendable append(@android.annotation.Nullable java.lang.CharSequence csq);
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    /** @hide */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public interface ForTesting {
-                    public void foo();
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public interface Appendable {
+                @android.annotation.NonNull
+                public test.pkg.Appendable append(@android.annotation.Nullable java.lang.CharSequence csq);
+                }
+                """,
+                """
+                package test.pkg;
+                /** @hide */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public interface ForTesting {
+                public void foo();
+                }
+                """
             ),
             api = """
                 package test.pkg {
@@ -485,145 +476,4 @@
                 """
         )
     }
-
-    @Test
-    fun `Merge inclusion annotations on api in java namespace`() {
-        check(
-            sourceFiles = arrayOf(
-                java(
-                    "src/java/net/Example.java",
-                    """
-                    package java.net;
-
-                    public class Example {
-                        public void aNotAnnotated() { }
-                        public void bShown() { }
-                    }
-                    """
-                )
-            ),
-            compatibilityMode = false,
-            outputKotlinStyleNulls = false,
-            omitCommonPackages = false,
-            extraArguments = arrayOf(
-                ARG_SHOW_SINGLE_ANNOTATION, "test.annotation.Show"
-            ),
-            mergeInclusionAnnotations = """
-                package java.net;
-
-                public class Example {
-                    void aNotAnnotated();
-                    @test.annotation.Show void bShown();
-                }
-                """,
-            api = """
-                package java.net {
-                  public class Example {
-                    method public void bShown();
-                  }
-                }
-                """
-        )
-    }
-
-    @Test
-    fun `Redefining java lang object plus using some internal classes`() {
-        check(
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package java.util;
-                    public class HashMap {
-                        static class Node {
-                        }
-                        static class TreeNode extends LinkedHashMap.LinkedHashMapEntry {
-                        }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package java.util;
-
-                    public class LinkedHashMap<K,V>
-                        extends HashMap<K,V>
-                        implements Map<K,V>
-                    {
-                        static class LinkedHashMapEntry<K,V> extends HashMap.Node<K,V> {
-                        }
-                    }
-
-                    """
-                ),
-                java(
-                    """
-                    package java.lang;
-
-                    public class Object {
-                        protected void finalize() throws Throwable { }
-                    }
-                    """
-                )
-            ),
-            compatibilityMode = false,
-            extraArguments = arrayOf(
-                ARG_SHOW_SINGLE_ANNOTATION, "libcore.api.CorePlatformApi"
-            ),
-            mergeInclusionAnnotations = """
-                package java.util;
-
-                public class LinkedHashMap extends java.util.HashMap {
-                }
-                """,
-            api = "" // This test is checking that it doesn't crash
-        )
-    }
-
-    @Test
-    fun `Merge nullability into child`() {
-        // This is a contrived test that verifies that even if Child no longer directly declares
-        // method1, the inherited method1 is still found
-        check(
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    public class Child extends Parent {
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-
-                    public class Parent {
-                        public void method1(String arg) {
-                        }
-                    }
-                    """
-                )
-            ),
-            compatibilityMode = false,
-            mergeJavaStubAnnotations = """
-                package test.pkg;
-
-                public class Child {
-                    public void method1(@Nullable String arg) {
-                    }
-                }
-                """,
-            api = """
-                package test.pkg {
-                  public class Child extends test.pkg.Parent {
-                    ctor public Child();
-                  }
-                  public class Parent {
-                    ctor public Parent();
-                    method public void method1(String);
-                  }
-                }
-                """,
-            expectedIssues = "" // should not report that Child.method1 is undefined
-        )
-    }
 }
diff --git a/src/test/java/com/android/tools/metalava/ApiAnalyzerTest.kt b/src/test/java/com/android/tools/metalava/ApiAnalyzerTest.kt
index db32742..49c454a 100644
--- a/src/test/java/com/android/tools/metalava/ApiAnalyzerTest.kt
+++ b/src/test/java/com/android/tools/metalava/ApiAnalyzerTest.kt
@@ -20,97 +20,22 @@
 
 class ApiAnalyzerTest : DriverTest() {
     @Test
-    fun `Hidden abstract method with show @SystemApi`() {
+    fun `private companion object inside an interface`() {
         check(
-            showAnnotations = arrayOf("android.annotation.SystemApi"),
+            compatibilityMode = false,
             expectedIssues = """
-                src/test/pkg/SystemApiClass.java:6: error: badAbstractHiddenMethod cannot be hidden and abstract when SystemApiClass has a visible constructor, in case a third-party attempts to subclass it. [HiddenAbstractMethod]
-                src/test/pkg/PublicClass.java:4: error: badAbstractHiddenMethod cannot be hidden and abstract when PublicClass has a visible constructor, in case a third-party attempts to subclass it. [HiddenAbstractMethod]
-                src/test/pkg/PublicClass.java:6: error: badPackagePrivateMethod cannot be hidden and abstract when PublicClass has a visible constructor, in case a third-party attempts to subclass it. [HiddenAbstractMethod]
+                src/test/pkg/MyInterface.kt:4: error: Do not use private companion objects inside interfaces as these become public if targeting Java 8 or older. [PrivateCompanion]
             """,
             sourceFiles = arrayOf(
-                java("""
-                    package test.pkg;
-                    import android.annotation.SystemApi;
-                    public abstract class PublicClass {
-                        /** @hide */
-                        public abstract boolean badAbstractHiddenMethod() { return true; }
-                        abstract void badPackagePrivateMethod() { }
-                        /**
-                         * This method does not fail because it is visible due to showAnnotations,
-                         * instead it will fail when running analysis on public API. See test below.
-                         * @hide
-                         */
-                        @SystemApi
-                        public abstract boolean goodAbstractSystemHiddenMethod() { return true; }
-                    }
-                """
-                ),
-                java("""
-                    package test.pkg;
-                    import android.annotation.SystemApi;
-                    public abstract class PublicClassWithHiddenConstructor {
-                        private PublicClassWithHiddenConstructor() { }
-                        /** @hide */
-                        public abstract boolean goodAbstractHiddenMethod() { return true; }
-                    }
-                """
-                ),
-                java("""
-                   package test.pkg;
-                   import android.annotation.SystemApi;
-                   /** @hide */
-                   @SystemApi
-                   public abstract class SystemApiClass {
-                        /** @hide */
-                        public abstract boolean badAbstractHiddenMethod() { return true; }
-                        /**
-                         * This method is OK, because it matches visibility of the class
-                         * @hide
-                         */
-                        @SystemApi
-                        public abstract boolean goodAbstractSystemHiddenMethod() { return true; }
-                        public abstract boolean goodAbstractPublicMethod() { return true; }
-                   }
-               """
-                ),
-                java("""
-                    package test.pkg;
-                    import android.annotation.SystemApi;
-                    /** This class is OK because it is all hidden @hide */
-                    public abstract class HiddenClass {
-                        public abstract boolean goodAbstractHiddenMethod() { return true; }
-                    }
-                """
-                ),
-                systemApiSource
-            )
-        )
-    }
+                kotlin(
+                    """
+                        package test.pkg
 
-    @Test
-    fun `Hidden abstract method for public API`() {
-        check(
-            expectedIssues = """
-                src/test/pkg/PublicClass.java:4: error: badAbstractHiddenMethod cannot be hidden and abstract when PublicClass has a visible constructor, in case a third-party attempts to subclass it. [HiddenAbstractMethod]
-                src/test/pkg/PublicClass.java:6: error: badPackagePrivateMethod cannot be hidden and abstract when PublicClass has a visible constructor, in case a third-party attempts to subclass it. [HiddenAbstractMethod]
-                src/test/pkg/PublicClass.java:7: error: badAbstractSystemHiddenMethod cannot be hidden and abstract when PublicClass has a visible constructor, in case a third-party attempts to subclass it. [HiddenAbstractMethod]
-            """,
-            sourceFiles = arrayOf(
-                java("""
-                    package test.pkg;
-                    import android.annotation.SystemApi;
-                    public abstract class PublicClass {
-                        /** @hide */
-                        public abstract boolean badAbstractHiddenMethod() { return true; }
-                        abstract void badPackagePrivateMethod() { }
-                        /** @hide */
-                        @SystemApi
-                        public abstract boolean badAbstractSystemHiddenMethod() { return true; }
-                    }
-                """
-                ),
-                systemApiSource
+                        interface MyInterface {
+                            private companion object
+                        }
+                    """
+                )
             )
         )
     }
diff --git a/src/test/java/com/android/tools/metalava/ApiFileTest.kt b/src/test/java/com/android/tools/metalava/ApiFileTest.kt
index 05d72ae..cedc38d 100644
--- a/src/test/java/com/android/tools/metalava/ApiFileTest.kt
+++ b/src/test/java/com/android/tools/metalava/ApiFileTest.kt
@@ -162,22 +162,22 @@
                     import android.view.View
 
                     class Foo {
-                        fun method1(myInt: Int = 42,
-                            myInt2: Int? = null,
-                            myByte: Int = 2 * 21,
+                        fun method1(int: Int = 42,
+                            int2: Int? = null,
+                            byte: Int = 2 * 21,
                             str: String = "hello " + "world",
                             vararg args: String) { }
 
-                        fun method2(myInt: Int, myInt2: Int = (2*int) * SIZE) { }
+                        fun method2(int: Int, int2: Int = (2*int) * SIZE) { }
 
-                        fun method3(str: String, myInt: Int, myInt2: Int = double(int) + str.length) { }
+                        fun method3(str: String, int: Int, int2: Int = double(int) + str.length) { }
 
                         fun emptyLambda(sizeOf: () -> Unit = {  }) {}
 
                         fun View.drawToBitmap(config: Bitmap.Config = Bitmap.Config.ARGB_8888): Bitmap? = null
 
                         companion object {
-                            fun double(myInt: Int) = 2 * myInt
+                            fun double(int: Int) = 2 * int
                             fun print(foo: Foo = Foo()) { println(foo) }
                         }
                     }
@@ -201,13 +201,13 @@
                     ctor public Foo();
                     method public android.graphics.Bitmap? drawToBitmap(android.view.View, android.graphics.Bitmap.Config config = android.graphics.Bitmap.Config.ARGB_8888);
                     method public void emptyLambda(kotlin.jvm.functions.Function0<kotlin.Unit> sizeOf = {});
-                    method public void method1(int myInt = 42, Integer? myInt2 = null, int myByte = 42, String str = "hello world", java.lang.String... args);
-                    method public void method2(int myInt, int myInt2 = (2 * int) * some.other.pkg.Constants.Misc.SIZE);
-                    method public void method3(String str, int myInt, int myInt2 = double(int) + str.length);
+                    method public void method1(int p = 42, Integer? int2 = null, int p1 = 42, String str = "hello world", java.lang.String... args);
+                    method public void method2(int p, int int2 = (2 * int) * some.other.pkg.Constants.Misc.SIZE);
+                    method public void method3(String str, int p, int int2 = double(int) + str.length);
                     field public static final test.pkg.Foo.Companion Companion;
                   }
                   public static final class Foo.Companion {
-                    method public int double(int myInt);
+                    method public int double(int p);
                     method public void print(test.pkg.Foo foo = test.pkg.Foo());
                   }
                 }
@@ -282,7 +282,7 @@
                 // Signature format: 3.0
                 package androidx.core.util {
                   public final class TestKt {
-                    method public static inline <K, V> android.util.LruCache<K,V> lruCache(int maxSize, kotlin.jvm.functions.Function2<? super K,? super V,java.lang.Integer> sizeOf = { _, _ -> return 1 }, kotlin.jvm.functions.Function1<? super K,? extends V> create = { it -> return null as V }, kotlin.jvm.functions.Function4<? super java.lang.Boolean,? super K,? super V,? super V,kotlin.Unit> onEntryRemoved = { _, _, _, _ ->  });
+                    method public static inline <K, V> android.util.LruCache<K,V> lruCache(int maxSize, kotlin.jvm.functions.Function2<? super K,? super V,java.lang.Integer> sizeOf = { _, _ -> return 1 }, kotlin.jvm.functions.Function1<? super K,? extends V> create = { return null as V }, kotlin.jvm.functions.Function4<? super java.lang.Boolean,? super K,? super V,? super V,kotlin.Unit> onEntryRemoved = { _, _, _, _ ->  });
                   }
                 }
                 """,
@@ -340,8 +340,7 @@
                     method public java.lang.String getProperty1();
                     method public java.lang.String getProperty2();
                     method public void otherMethod(boolean ok, int times);
-                    method public void setProperty2(java.lang.String property2);
-                    property public final java.lang.String property1;
+                    method public void setProperty2(java.lang.String p);
                     property public final java.lang.String property2;
                     field public static final test.pkg.Kotlin.Companion Companion;
                     field public static final int MY_CONST = 42; // 0x2a
@@ -446,8 +445,7 @@
                 kotlin(
                     """
                     package test.pkg
-                    suspend inline fun hello(foo: Int) { }
-                    suspend fun helloTwoContinuations(myContinuation: kotlin.coroutines.Continuation<Any>) { }
+                    suspend inline fun hello() { }
                     internal suspend fun internalHello() { }
                     private suspend fun privateHello() { }
                     """
@@ -456,8 +454,7 @@
             api = """
                 package test.pkg {
                   public final class TestKt {
-                    method @Nullable public static suspend inline Object hello(int foo, @NonNull kotlin.coroutines.Continuation<? super kotlin.Unit> p);
-                    method @Nullable public static suspend Object helloTwoContinuations(@NonNull kotlin.coroutines.Continuation<java.lang.Object> myContinuation, @NonNull kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+                    method @Nullable public static suspend inline Object hello(@NonNull kotlin.coroutines.Continuation<? super kotlin.Unit> p);
                   }
                 }
                 """
@@ -476,9 +473,6 @@
                         // This property should have no public setter
                         var readOnlyVar = false
                             internal set
-                        // This property should have no public setter
-                        public var readOnlyVarWithPublicModifer = false
-                            internal set
                     }
                     """
                 )
@@ -489,9 +483,7 @@
                   public final class MyClass {
                     ctor public MyClass();
                     method public boolean getReadOnlyVar();
-                    method public boolean getReadOnlyVarWithPublicModifer();
                     property public final boolean readOnlyVar;
-                    property public final boolean readOnlyVarWithPublicModifer;
                   }
                 }
                 """
@@ -792,8 +784,6 @@
                     ctor public NonNullableKotlinPair(F first, S second);
                     method public F getFirst();
                     method public S getSecond();
-                    property public final F first;
-                    property public final S second;
                   }
                   public class NullableJavaPair<F, S> {
                     ctor public NullableJavaPair(F?, S?);
@@ -804,8 +794,6 @@
                     ctor public NullableKotlinPair(F? first, S? second);
                     method public F? getFirst();
                     method public S? getSecond();
-                    property public final F? first;
-                    property public final S? second;
                   }
                   public class PlatformJavaPair<F, S> {
                     ctor public PlatformJavaPair(F!, S!);
@@ -956,6 +944,8 @@
                     method public test.pkg.Issue create(String id, String briefDescription, String explanation);
                   }
                   public enum Language {
+                    method public static test.pkg.Language valueOf(String name) throws java.lang.IllegalArgumentException;
+                    method public static test.pkg.Language[] values();
                     enum_constant public static final test.pkg.Language JAVA;
                     enum_constant public static final test.pkg.Language KOTLIN;
                   }
@@ -1087,7 +1077,7 @@
                   public final class SimpleClass {
                     ctor public SimpleClass();
                     method public int getNonJvmField();
-                    method public void setNonJvmField(int nonJvmField);
+                    method public void setNonJvmField(int p);
                     property public final int nonJvmField;
                     field public int jvmField;
                   }
@@ -1121,8 +1111,8 @@
                     ctor public SimpleClass();
                     method public int getAnotherProperty();
                     method public int myPropertyJvmGetter();
-                    method public void setAnotherProperty(int anotherProperty);
-                    method public void setMyProperty(int myProperty);
+                    method public void setAnotherProperty(int p);
+                    method public void setMyProperty(int p);
                     property public final int anotherProperty;
                     property public final int myProperty;
                   }
@@ -1160,7 +1150,7 @@
             api = """
                 // Signature format: 3.0
                 package test.pkg {
-                  @kotlin.RequiresOptIn @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget, kotlin.annotation.AnnotationTarget}) public @interface ExperimentalBar {
+                  @kotlin.RequiresOptIn @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION}) public @interface ExperimentalBar {
                   }
                   @test.pkg.ExperimentalBar public final class FancyBar {
                     ctor public FancyBar();
@@ -1237,9 +1227,8 @@
             api = """
                 // Signature format: 3.0
                 package androidx.annotation.experimental {
-                  @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget, kotlin.annotation.AnnotationTarget, kotlin.annotation.AnnotationTarget, kotlin.annotation.AnnotationTarget, kotlin.annotation.AnnotationTarget, kotlin.annotation.AnnotationTarget, kotlin.annotation.AnnotationTarget, kotlin.annotation.AnnotationTarget, kotlin.annotation.AnnotationTarget, kotlin.annotation.AnnotationTarget}) public @interface UseExperimental {
-                    method public abstract kotlin.reflect.KClass<? extends java.lang.annotation.Annotation>[] markerClass();
-                    property public abstract kotlin.reflect.KClass<? extends java.lang.annotation.Annotation>![] markerClass;
+                  @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.LOCAL_VARIABLE, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER, AnnotationTarget.FILE, AnnotationTarget.TYPEALIAS}) public @interface UseExperimental {
+                    method public abstract Class<? extends java.lang.annotation.Annotation>[] markerClass();
                   }
                 }
                 package test.pkg {
@@ -1247,7 +1236,7 @@
                     ctor public AnotherSimpleClass();
                     method public void methodUsingFancyBar();
                   }
-                  @kotlin.Experimental @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget, kotlin.annotation.AnnotationTarget}) public @interface ExperimentalBar {
+                  @kotlin.Experimental @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION}) public @interface ExperimentalBar {
                   }
                   @test.pkg.ExperimentalBar public final class FancyBar {
                     ctor public FancyBar();
@@ -1605,9 +1594,6 @@
         // Real life example: StringBuilder.setLength
         // This is just like the above test, but with compat mode disabled.
         check(
-            expectedIssues = """
-                src/test/pkg/PublicSuper.java:3: error: isContiguous cannot be hidden and abstract when PublicSuper has a visible constructor, in case a third-party attempts to subclass it. [HiddenAbstractMethod]
-            """,
             compatibilityMode = false,
             sourceFiles = arrayOf(
                 java(
@@ -1708,7 +1694,7 @@
         // part of the source tree, ensure that we compute the right retention (runtime, meaning
         // it should show up in the stubs file.).
         check(
-            extraArguments = arrayOf(ARG_EXCLUDE_ALL_ANNOTATIONS),
+            extraArguments = arrayOf(ARG_EXCLUDE_ANNOTATIONS),
             sourceFiles = arrayOf(
                 java(
                     """
@@ -1753,7 +1739,7 @@
               }
             }
             package test.pkg {
-              @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention) public @interface ExplicitRuntimeRetention {
+              @kotlin.annotation.Retention(AnnotationRetention.RUNTIME) public @interface ExplicitRuntimeRetention {
               }
               @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface Foo {
                 method public abstract String value();
@@ -1763,31 +1749,27 @@
             }
             """.trimIndent(),
             compatibilityMode = true,
-            stubFiles = arrayOf(
+            stubs = arrayOf(
                 // For annotations where the java.lang.annotation classes themselves are not
                 // part of the source tree, ensure that we compute the right retention (runtime, meaning
                 // it should show up in the stubs file.).
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS)
-                    public @interface Foo {
-                    public java.lang.String value();
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package android.annotation;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS)
-                    @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.LOCAL_VARIABLE})
-                    public @interface SuppressLint {
-                    public java.lang.String[] value();
-                    }
-                    """
-                )
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS)
+                public @interface Foo {
+                public java.lang.String value();
+                }
+                """,
+                """
+                package android.annotation;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS)
+                @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.LOCAL_VARIABLE})
+                public @interface SuppressLint {
+                public java.lang.String[] value();
+                }
+                """
             )
         )
     }
@@ -4192,79 +4174,6 @@
     }
 
     @Test
-    fun `Test for experimental annotations from classpath`() {
-        check(
-            format = FileFormat.V3,
-            classpath = arrayOf(
-                /* The following source file, compiled, and root folder jar'ed and stored as base64 gzip
-                   Encoded using openssl base64 < test.jar | tr -d '\n'
-
-                    package test.pkg
-                    @RequiresOptIn
-                    annotation class ExternalExperimentalAnnotation
-                 */
-                base64gzip(
-                    "test.jar", "" +
-                        "UEsDBAoAAAgIADt2U1IAAAAAAgAAAAAAAAAJAAAATUVUQS1JTkYvAwBQSwMECgAACAgAFXZ" +
-                        "TUrJ/Au4bAAAAGQAAABQAAABNRVRBLUlORi9NQU5JRkVTVC5NRvNNzMtMSy0u0Q1LLSrOzM" +
-                        "+zUjDUM+Dl4uUCAFBLAwQKAAAICAA7dlNSDWpm1BUAAAAYAAAAGwAAAE1FVEEtSU5GL3Rlc" +
-                        "3Qua290bGluX21vZHVsZWNgYGBmYGBgBGIWIGYCYgYlBi0GAFBLAwQKAAAICAA7dlNSAAAA" +
-                        "AAIAAAAAAAAABQAAAHRlc3QvAwBQSwMECgAACAgAO3ZTUgAAAAACAAAAAAAAAAkAAAB0ZXN" +
-                        "0L3BrZy8DAFBLAwQKAAAICAA7dlNSPYCyXGwBAABkAgAALQAAAHRlc3QvcGtnL0V4dGVybm" +
-                        "FsRXhwZXJpbWVudGFsQW5ub3RhdGlvbi5jbGFzc41Qy04CQRCsWZ6uL/CBICp6wXhxlasnT" +
-                        "TBuAmLwceE0wIQsLLPIzhK87c1f8Rs8GMLRjzL2qoiJRr309HRVdXf188vjE4ACcgy7SrjK" +
-                        "6HVaRnGoRF9yuzjsib7VFVJx+1hKR3FlOTIGxpBo8wE3bC5bRqXeFg0VQ4ghN63yT77xVRp" +
-                        "hSJU6jrItaVTFrWf1hVvpKVMeMWyXfpRXhaINKCNKZMBtTzDk/6BeOLbVuCNBrHp9fmWWiw" +
-                        "zJydiyULzJFSdU6w5CZJ8FIRwEjWr1txqCQJZYh0rNQ9pu5Ou6ltZ0LZHVR358fK+lR35BO" +
-                        "2AnI3/8EA2kzQLDXumfd6T5YAgHbIad37n7HeLol47Xb4hTy6YLZKoeOe2KG8u16raYUl2G" +
-                        "7AdmysE3NE9rIkyDo3h3uRHYRhab9J5RFidsRkDHLOYQwXwNIRMLJhZNJJCc/JZMLGOFUqz" +
-                        "WwFyksEaQi7SLjIt1bFG3KHWKAa9QSwECFAMKAAAICAA7dlNSAAAAAAIAAAAAAAAACQAAAA" +
-                        "AAAAAAABAA7UEAAAAATUVUQS1JTkYvUEsBAhQDCgAACAgAFXZTUrJ/Au4bAAAAGQAAABQAA" +
-                        "AAAAAAAAAAAAKSBKQAAAE1FVEEtSU5GL01BTklGRVNULk1GUEsBAhQDCgAACAgAO3ZTUg1q" +
-                        "ZtQVAAAAGAAAABsAAAAAAAAAAAAAAKCBdgAAAE1FVEEtSU5GL3Rlc3Qua290bGluX21vZHV" +
-                        "sZVBLAQIUAwoAAAgIADt2U1IAAAAAAgAAAAAAAAAFAAAAAAAAAAAAEADoQcQAAAB0ZXN0L1" +
-                        "BLAQIUAwoAAAgIADt2U1IAAAAAAgAAAAAAAAAJAAAAAAAAAAAAEADoQekAAAB0ZXN0L3BrZ" +
-                        "y9QSwECFAMKAAAICAA7dlNSPYCyXGwBAABkAgAALQAAAAAAAAAAAAAAoIESAQAAdGVzdC9w" +
-                        "a2cvRXh0ZXJuYWxFeHBlcmltZW50YWxBbm5vdGF0aW9uLmNsYXNzUEsFBgAAAAAGAAYAhwE" +
-                        "AAMkCAAAAAA=="
-                )
-            ),
-            sourceFiles = arrayOf(
-                kotlin(
-                    """
-                    package test.pkg
-
-                    @ExternalExperimentalAnnotation
-                    class ClassUsingExternalExperimentalApi
-
-                    @InLibraryExperimentalAnnotation
-                    class ClassUsingInLibraryExperimentalApi
-                """
-                ),
-                kotlin(
-                    """
-                        package test.pkg
-                        @RequiresOptIn
-                        annotation class InLibraryExperimentalAnnotation
-                    """
-                )
-            ),
-            expectedIssues = "",
-            api =
-            """
-                // Signature format: 3.0
-                package test.pkg {
-                  @kotlin.RequiresOptIn public @interface InLibraryExperimentalAnnotation {
-                  }
-                }
-            """,
-            extraArguments = arrayOf(
-                ARG_HIDE_META_ANNOTATION, "kotlin.RequiresOptIn"
-            )
-        )
-    }
-
-    @Test
     fun `@IntRange value in kotlin`() {
         check(
             format = FileFormat.V3,
@@ -4291,39 +4200,6 @@
                     ctor public KotlinClass(@IntRange(from=2) int differentParam);
                     method public int getParam();
                     method public void myMethod(@IntRange(from=3) int methodParam);
-                    property public final int param;
-                  }
-                }
-            """
-        )
-    }
-
-    @Test
-    fun `Annotation value visibility`() {
-        check(
-            format = FileFormat.V2,
-            sourceFiles = arrayOf(
-                java("""
-                    package test.pkg
-
-                    import androidx.annotation.IntRange
-
-                    public final class ApiClass {
-                        private int hiddenConstant = 1;
-                        public ApiClass(@IntRange(from=1) int x) {}
-                        public void method(@IntRange(from = hiddenConstant) int x) {}
-                    }
-                """
-                ),
-                androidxIntRangeSource
-            ),
-            extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation"),
-            api = """
-                // Signature format: 2.0
-                package test.pkg {
-                  public final class ApiClass {
-                    ctor public ApiClass(@IntRange(from=1) int);
-                    method public void method(@IntRange(from=0x1) int);
                   }
                 }
             """
@@ -4365,231 +4241,6 @@
     }
 
     @Test
-    fun `Constructor property tracking`() {
-        check(
-            format = FileFormat.V3,
-            sourceFiles = arrayOf(
-                kotlin("""
-                    package test.pkg
-                    sealed class MyClass(
-                        val firstConstructorProperty: Int,
-                        val secondConstructorProperty: Boolean
-                    ) {
-                        val nonConstructorProperty: String = "PROP"
-                    }
-                    """
-                ),
-                kotlin("""
-                    package test.pkg
-                    data class MyDataClass(
-                        val constructorProperty: String,
-                        internal val internalConstructorProperty: String
-                    )
-                """)
-            ),
-            api = """
-                // Signature format: 3.0
-                package test.pkg {
-                  public abstract sealed class MyClass {
-                    method public final int getFirstConstructorProperty();
-                    method public final String getNonConstructorProperty();
-                    method public final boolean getSecondConstructorProperty();
-                    property public final int firstConstructorProperty;
-                    property public final String nonConstructorProperty;
-                    property public final boolean secondConstructorProperty;
-                  }
-                  public final class MyDataClass {
-                    ctor public MyDataClass(String constructorProperty, String internalConstructorProperty);
-                    method public String component1();
-                    method public test.pkg.MyDataClass copy(String constructorProperty, String internalConstructorProperty);
-                    method public String getConstructorProperty();
-                    property public final String constructorProperty;
-                  }
-                }
-            """
-        )
-    }
-
-    @Test
-    fun `Concise default Values Names in Java`() {
-        // Java code which explicitly specifies parameter names
-        check(
-            format = FileFormat.V4,
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    import androidx.annotation.DefaultValue;
-
-                    public class Foo {
-                        public void foo(
-                            @DefaultValue("null") String prefix,
-                            @DefaultValue("\"Hello World\"") String greeting,
-                            @DefaultValue("42") int meaning) {
-                        }
-                    }
-                    """
-                ),
-                supportDefaultValue
-            ),
-            api = """
-                // Signature format: 4.0
-                package test.pkg {
-                  public class Foo {
-                    ctor public Foo();
-                    method public void foo(optional String!, optional String!, optional int);
-                  }
-                }
-                 """,
-            extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation")
-        )
-    }
-
-    @Test
-    fun `Concise default Values and Names in Kotlin`() {
-        // Kotlin code which explicitly specifies parameter names
-        check(
-            format = FileFormat.V4,
-            compatibilityMode = false,
-            sourceFiles = arrayOf(
-                kotlin(
-                    """
-                    package test.pkg
-                    import some.other.pkg.Constants.Misc.SIZE
-                    import android.graphics.Bitmap
-                    import android.view.View
-
-                    class Foo(a: String = "1", b: String = "2") {
-                        fun method1(myInt: Int = 42,
-                            myInt2: Int? = null,
-                            myByte: Int = 2 * 21,
-                            str: String = "hello " + "world",
-                            vararg args: String) { }
-
-                        fun method2(myInt: Int, myInt2: Int = (2*int) * SIZE) { }
-
-                        fun method3(str: String, myInt: Int, myInt2: Int = double(int) + str.length) { }
-
-                        fun emptyLambda(sizeOf: () -> Unit = {  }) {}
-
-                        fun View.drawToBitmap(config: Bitmap.Config = Bitmap.Config.ARGB_8888): Bitmap? = null
-
-                        companion object {
-                            fun double(myInt: Int) = 2 * myInt
-                            fun print(foo: Foo = Foo()) { println(foo) }
-                        }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package some.other.pkg;
-                    public class Constants {
-                        public static class Misc {
-                            public static final int SIZE = 5;
-                        }
-                    }
-                    """
-                )
-            ),
-            api = """
-                // Signature format: 4.0
-                package test.pkg {
-                  public final class Foo {
-                    ctor public Foo(optional String a, optional String b);
-                    method public android.graphics.Bitmap? drawToBitmap(android.view.View, optional android.graphics.Bitmap.Config config);
-                    method public void emptyLambda(optional kotlin.jvm.functions.Function0<kotlin.Unit> sizeOf);
-                    method public void method1(optional int myInt, optional Integer? myInt2, optional int myByte, optional String str, java.lang.String... args);
-                    method public void method2(int myInt, optional int myInt2);
-                    method public void method3(String str, int myInt, optional int myInt2);
-                    field public static final test.pkg.Foo.Companion Companion;
-                  }
-                  public static final class Foo.Companion {
-                    method public int double(int myInt);
-                    method public void print(optional test.pkg.Foo foo);
-                  }
-                }
-                """,
-            extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation", ARG_HIDE_PACKAGE, "some.other.pkg"),
-            includeSignatureVersion = true
-        )
-    }
-
-    @Test
-    fun `Concise default Values in Kotlin for expressions`() {
-        // Testing trickier default values; regression test for problem
-        // observed in androidx.core.util with LruCache
-        check(
-            format = FileFormat.V4,
-            sourceFiles = arrayOf(
-                kotlin(
-                    """
-                    package androidx.core.util
-
-                    import android.util.LruCache
-
-                    inline fun <K : Any, V : Any> lruCache(
-                        maxSize: Int,
-                        crossinline sizeOf: (key: K, value: V) -> Int = { _, _ -> 1 },
-                        @Suppress("USELESS_CAST") // https://youtrack.jetbrains.com/issue/KT-21946
-                        crossinline create: (key: K) -> V? = { null as V? },
-                        crossinline onEntryRemoved: (evicted: Boolean, key: K, oldValue: V, newValue: V?) -> Unit =
-                            { _, _, _, _ -> }
-                    ): LruCache<K, V> {
-                        return object : LruCache<K, V>(maxSize) {
-                            override fun sizeOf(key: K, value: V) = sizeOf(key, value)
-                            override fun create(key: K) = create(key)
-                            override fun entryRemoved(evicted: Boolean, key: K, oldValue: V, newValue: V?) {
-                                onEntryRemoved(evicted, key, oldValue, newValue)
-                            }
-                        }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package androidx.collection;
-
-                    import androidx.annotation.NonNull;
-                    import androidx.annotation.Nullable;
-
-                    import java.util.LinkedHashMap;
-                    import java.util.Locale;
-                    import java.util.Map;
-
-                    public class LruCache<K, V> {
-                        @Nullable
-                        protected V create(@NonNull K key) {
-                            return null;
-                        }
-
-                        protected int sizeOf(@NonNull K key, @NonNull V value) {
-                            return 1;
-                        }
-
-                        protected void entryRemoved(boolean evicted, @NonNull K key, @NonNull V oldValue,
-                                @Nullable V newValue) {
-                        }
-                    }
-                    """
-                ),
-                androidxNullableSource,
-                androidxNonNullSource
-            ),
-            api = """
-                // Signature format: 4.0
-                package androidx.core.util {
-                  public final class TestKt {
-                    method public static inline <K, V> android.util.LruCache<K,V> lruCache(int maxSize, optional kotlin.jvm.functions.Function2<? super K,? super V,java.lang.Integer> sizeOf, optional kotlin.jvm.functions.Function1<? super K,? extends V> create, optional kotlin.jvm.functions.Function4<? super java.lang.Boolean,? super K,? super V,? super V,kotlin.Unit> onEntryRemoved);
-                  }
-                }
-                """,
-            extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation", ARG_HIDE_PACKAGE, "androidx.collection"),
-            includeSignatureVersion = true
-        )
-    }
-
-    @Test
     fun `Test type erasure and dexApi from signature`() {
         check(
             signatureSources = arrayOf("""
@@ -4609,34 +4260,4 @@
             """
         )
     }
-
-    @Test
-    fun `Functional interface in signature`() {
-        check(
-            format = FileFormat.V4,
-            sourceFiles = arrayOf(
-                kotlin("""
-                    package test.pkg
-
-                    fun interface FunctionalInterface {
-                        fun methodOne(number: Int): Boolean
-                    }
-
-                    fun userOfFunctionalInterface(parameter: FunctionalInterface) { }
-                """
-                )
-            ),
-            api = """
-                // Signature format: 4.0
-                package test.pkg {
-                  public fun interface FunctionalInterface {
-                    method public boolean methodOne(int number);
-                  }
-                  public final class FunctionalInterfaceKt {
-                    method public static void userOfFunctionalInterface(test.pkg.FunctionalInterface parameter);
-                  }
-                }
-            """
-        )
-    }
 }
diff --git a/src/test/java/com/android/tools/metalava/ApiLintBaselineTest.kt b/src/test/java/com/android/tools/metalava/ApiLintBaselineTest.kt
index 8cf7c0d..7c8273e 100644
--- a/src/test/java/com/android/tools/metalava/ApiLintBaselineTest.kt
+++ b/src/test/java/com/android/tools/metalava/ApiLintBaselineTest.kt
@@ -107,9 +107,12 @@
                     Enums are discouraged in Android APIs
             """,
             expectedIssues = """
-                src/android/pkg/MyEnum.java:3: error: Enums are discouraged in Android APIs [Enum] [See https://s.android.com/api-guidelines#avoid-enum]
+                src/android/pkg/MyEnum.java:3: error: Enums are discouraged in Android APIs [Enum] [Rule F5 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                1 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -132,7 +135,7 @@
             baselineApiLint = "",
             errorMessageApiLint = "*** api-lint failed ***",
             expectedIssues = """
-                src/android/pkg/MyClassImpl.java:3: error: Don't expose your implementation details: `MyClassImpl` ends with `Impl` [EndsWithImpl] [See https://s.android.com/api-guidelines#dont-end-with-impl]
+                src/android/pkg/MyClassImpl.java:3: error: Don't expose your implementation details: `MyClassImpl` ends with `Impl` [EndsWithImpl]
                 """,
             sourceFiles = arrayOf(
                 java(
@@ -145,9 +148,13 @@
                 )
             ),
             expectedFail = """
+                1 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
                 *** api-lint failed ***
             """,
             expectedOutput = """
+                1 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
                 *** api-lint failed ***
                 """
         )
@@ -160,7 +167,7 @@
             compatibilityMode = false,
             baselineApiLint = "",
             expectedIssues = """
-                src/android/pkg/MyClassImpl.java:3: error: Don't expose your implementation details: `MyClassImpl` ends with `Impl` [EndsWithImpl] [See https://s.android.com/api-guidelines#dont-end-with-impl]
+                src/android/pkg/MyClassImpl.java:3: error: Don't expose your implementation details: `MyClassImpl` ends with `Impl` [EndsWithImpl]
                 """,
             sourceFiles = arrayOf(
                 java(
@@ -172,8 +179,14 @@
                     """
                 )
             ),
-            expectedFail = DefaultLintErrorMessage,
-            expectedOutput = DefaultLintErrorMessage
+            expectedFail = """
+                1 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
+            expectedOutput = """
+                1 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+                """
         )
     }
 }
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/metalava/ApiLintTest.kt b/src/test/java/com/android/tools/metalava/ApiLintTest.kt
index 712da27..800214c 100644
--- a/src/test/java/com/android/tools/metalava/ApiLintTest.kt
+++ b/src/test/java/com/android/tools/metalava/ApiLintTest.kt
@@ -34,18 +34,21 @@
             ),
             compatibilityMode = false,
             expectedIssues = """
-                src/Dp.kt:3: warning: Acronyms should not be capitalized in method names: was `badCALL`, should this be `badCall`? [AcronymName] [See https://s.android.com/api-guidelines#acronyms-in-method-name]
-                src/android/pkg/ALL_CAPS.java:3: warning: Acronyms should not be capitalized in class names: was `ALL_CAPS`, should this be `AllCaps`? [AcronymName] [See https://s.android.com/api-guidelines#acronyms-in-method-name]
-                src/android/pkg/HTMLWriter.java:3: warning: Acronyms should not be capitalized in class names: was `HTMLWriter`, should this be `HtmlWriter`? [AcronymName] [See https://s.android.com/api-guidelines#acronyms-in-method-name]
-                src/android/pkg/MyStringImpl.java:3: error: Don't expose your implementation details: `MyStringImpl` ends with `Impl` [EndsWithImpl] [See https://s.android.com/api-guidelines#dont-end-with-impl]
-                src/android/pkg/badlyNamedClass.java:5: error: Class must start with uppercase char: badlyNamedClass [StartWithUpper] [See https://s.android.com/api-guidelines#style-conventions]
-                src/android/pkg/badlyNamedClass.java:7: error: Method name must start with lowercase char: BadlyNamedMethod1 [StartWithLower] [See https://s.android.com/api-guidelines#style-conventions]
-                src/android/pkg/badlyNamedClass.java:9: warning: Acronyms should not be capitalized in method names: was `fromHTMLToHTML`, should this be `fromHtmlToHtml`? [AcronymName] [See https://s.android.com/api-guidelines#acronyms-in-method-name]
-                src/android/pkg/badlyNamedClass.java:10: warning: Acronyms should not be capitalized in method names: was `toXML`, should this be `toXml`? [AcronymName] [See https://s.android.com/api-guidelines#acronyms-in-method-name]
-                src/android/pkg/badlyNamedClass.java:11: warning: Acronyms should not be capitalized in method names: was `getID`, should this be `getId`? [AcronymName] [See https://s.android.com/api-guidelines#acronyms-in-method-name]
-                src/android/pkg/badlyNamedClass.java:6: error: Constant field names must be named with only upper case characters: `android.pkg.badlyNamedClass#BadlyNamedField`, should be `BADLY_NAMED_FIELD`? [AllUpper] [See https://s.android.com/api-guidelines#constant-naming]
+                src/Dp.kt:3: warning: Acronyms should not be capitalized in method names: was `badCALL`, should this be `badCall`? [AcronymName] [Rule S1 in go/android-api-guidelines]
+                src/android/pkg/ALL_CAPS.java:3: warning: Acronyms should not be capitalized in class names: was `ALL_CAPS`, should this be `AllCaps`? [AcronymName] [Rule S1 in go/android-api-guidelines]
+                src/android/pkg/HTMLWriter.java:3: warning: Acronyms should not be capitalized in class names: was `HTMLWriter`, should this be `HtmlWriter`? [AcronymName] [Rule S1 in go/android-api-guidelines]
+                src/android/pkg/MyStringImpl.java:3: error: Don't expose your implementation details: `MyStringImpl` ends with `Impl` [EndsWithImpl]
+                src/android/pkg/badlyNamedClass.java:5: error: Class must start with uppercase char: badlyNamedClass [StartWithUpper] [Rule S1 in go/android-api-guidelines]
+                src/android/pkg/badlyNamedClass.java:7: error: Method name must start with lowercase char: BadlyNamedMethod1 [StartWithLower] [Rule S1 in go/android-api-guidelines]
+                src/android/pkg/badlyNamedClass.java:9: warning: Acronyms should not be capitalized in method names: was `fromHTMLToHTML`, should this be `fromHtmlToHtml`? [AcronymName] [Rule S1 in go/android-api-guidelines]
+                src/android/pkg/badlyNamedClass.java:10: warning: Acronyms should not be capitalized in method names: was `toXML`, should this be `toXml`? [AcronymName] [Rule S1 in go/android-api-guidelines]
+                src/android/pkg/badlyNamedClass.java:11: warning: Acronyms should not be capitalized in method names: was `getID`, should this be `getId`? [AcronymName] [Rule S1 in go/android-api-guidelines]
+                src/android/pkg/badlyNamedClass.java:6: error: Constant field names must be named with only upper case characters: `android.pkg.badlyNamedClass#BadlyNamedField`, should be `BADLY_NAMED_FIELD`? [AllUpper] [Rule C2 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                10 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -179,9 +182,9 @@
             """.trimIndent(),
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/badlyNamedClass.java:8: warning: Acronyms should not be capitalized in method names: was `toXML2`, should this be `toXmL2`? [AcronymName] [See https://s.android.com/api-guidelines#acronyms-in-method-name]
-                src/android/pkg2/HTMLWriter.java:3: warning: Acronyms should not be capitalized in class names: was `HTMLWriter`, should this be `HtmlWriter`? [AcronymName] [See https://s.android.com/api-guidelines#acronyms-in-method-name]
-                src/android/pkg2/HTMLWriter.java:4: warning: Acronyms should not be capitalized in method names: was `fromHTMLToHTML`, should this be `fromHtmlToHtml`? [AcronymName] [See https://s.android.com/api-guidelines#acronyms-in-method-name]
+                src/android/pkg/badlyNamedClass.java:8: warning: Acronyms should not be capitalized in method names: was `toXML2`, should this be `toXmL2`? [AcronymName] [Rule S1 in go/android-api-guidelines]
+                src/android/pkg2/HTMLWriter.java:3: warning: Acronyms should not be capitalized in class names: was `HTMLWriter`, should this be `HtmlWriter`? [AcronymName] [Rule S1 in go/android-api-guidelines]
+                src/android/pkg2/HTMLWriter.java:4: warning: Acronyms should not be capitalized in method names: was `fromHTMLToHTML`, should this be `fromHtmlToHtml`? [AcronymName] [Rule S1 in go/android-api-guidelines]
                 """,
             sourceFiles = arrayOf(
                 java(
@@ -218,12 +221,15 @@
             compatibilityMode = false,
             expectedIssues = """
                 src/android/pkg/Constants.java:13: error: All constants must be defined at compile time: android.pkg.Constants#FOO [CompileTimeConstant]
-                src/android/pkg/Constants.java:12: warning: If min/max could change in future, make them dynamic methods: android.pkg.Constants#MAX_FOO [MinMaxConstant] [See https://s.android.com/api-guidelines#min-max-constants]
-                src/android/pkg/Constants.java:11: warning: If min/max could change in future, make them dynamic methods: android.pkg.Constants#MIN_FOO [MinMaxConstant] [See https://s.android.com/api-guidelines#min-max-constants]
-                src/android/pkg/Constants.java:9: error: Constant field names must be named with only upper case characters: `android.pkg.Constants#myStrings`, should be `MY_STRINGS`? [AllUpper] [See https://s.android.com/api-guidelines#constant-naming]
-                src/android/pkg/Constants.java:7: error: Constant field names must be named with only upper case characters: `android.pkg.Constants#strings`, should be `STRINGS`? [AllUpper] [See https://s.android.com/api-guidelines#constant-naming]
+                src/android/pkg/Constants.java:12: warning: If min/max could change in future, make them dynamic methods: android.pkg.Constants#MAX_FOO [MinMaxConstant] [Rule C8 in go/android-api-guidelines]
+                src/android/pkg/Constants.java:11: warning: If min/max could change in future, make them dynamic methods: android.pkg.Constants#MIN_FOO [MinMaxConstant] [Rule C8 in go/android-api-guidelines]
+                src/android/pkg/Constants.java:9: error: Constant field names must be named with only upper case characters: `android.pkg.Constants#myStrings`, should be `MY_STRINGS`? [AllUpper] [Rule C2 in go/android-api-guidelines]
+                src/android/pkg/Constants.java:7: error: Constant field names must be named with only upper case characters: `android.pkg.Constants#strings`, should be `STRINGS`? [AllUpper] [Rule C2 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                5 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -256,9 +262,12 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/MyEnum.java:3: error: Enums are discouraged in Android APIs [Enum] [See https://s.android.com/api-guidelines#avoid-enum]
+                src/android/pkg/MyEnum.java:3: error: Enums are discouraged in Android APIs [Enum] [Rule F5 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                1 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -279,12 +288,15 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/MyCallback.java:9: error: Callback method names must follow the on<Something> style: bar [CallbackMethodName] [See https://s.android.com/api-guidelines#callback-method-naming]
-                src/android/pkg/MyCallbacks.java:3: error: Callback class names should be singular: MyCallbacks [SingularCallback] [See https://s.android.com/api-guidelines#callback-class-singular]
-                src/android/pkg/MyInterfaceCallback.java:3: error: Callbacks must be abstract class instead of interface to enable extension in future API levels: MyInterfaceCallback [CallbackInterface] [See https://s.android.com/api-guidelines#callback-abstract-instead-of-interface]
-                src/android/pkg/MyObserver.java:3: warning: Class should be named MyCallback [CallbackName] [See https://s.android.com/api-guidelines#observer-should-be-callback]
+                src/android/pkg/MyCallback.java:8: error: Callback method names must follow the on<Something> style: bar [CallbackMethodName] [Rule L1 in go/android-api-guidelines]
+                src/android/pkg/MyCallbacks.java:3: error: Callback class names should be singular: MyCallbacks [SingularCallback] [Rule L1 in go/android-api-guidelines]
+                src/android/pkg/MyInterfaceCallback.java:3: error: Callbacks must be abstract class instead of interface to enable extension in future API levels: MyInterfaceCallback [CallbackInterface] [Rule CL3 in go/android-api-guidelines]
+                src/android/pkg/MyObserver.java:3: warning: Class should be named MyCallback [CallbackName] [Rule L1 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                4 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -328,7 +340,6 @@
                         }
                         public void onAnimationStart() {
                         }
-                        public void onN1GoodMethod() { }
                         public void bar() {
                         }
                         public static void staticMethod() {
@@ -348,10 +359,13 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/MyClassListener.java:3: error: Listeners should be an interface, or otherwise renamed Callback: MyClassListener [ListenerInterface] [See https://s.android.com/api-guidelines#callbacks-listener]
-                src/android/pkg/MyListener.java:6: error: Listener method names must follow the on<Something> style: bar [CallbackMethodName] [See https://s.android.com/api-guidelines#callback-method-naming]
+                src/android/pkg/MyClassListener.java:3: error: Listeners should be an interface, or otherwise renamed Callback: MyClassListener [ListenerInterface] [Rule L1 in go/android-api-guidelines]
+                src/android/pkg/MyListener.java:6: error: Listener method names must follow the on<Something> style: bar [CallbackMethodName] [Rule L1 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                2 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -413,11 +427,14 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/accounts/Actions.java:7: error: Intent action constant name must be ACTION_FOO: ACCOUNT_ADDED [IntentName] [See https://s.android.com/api-guidelines#use-standard-prefixes-for-constants]
-                src/android/accounts/Actions.java:6: error: Inconsistent action value; expected `android.accounts.action.ACCOUNT_OPENED`, was `android.accounts.ACCOUNT_OPENED` [ActionValue]
-                src/android/accounts/Actions.java:8: error: Intent action constant name must be ACTION_FOO: SOMETHING [IntentName] [See https://s.android.com/api-guidelines#use-standard-prefixes-for-constants]
+                src/android/accounts/Actions.java:7: error: Intent action constant name must be ACTION_FOO: ACCOUNT_ADDED [IntentName] [Rule C3 in go/android-api-guidelines]
+                src/android/accounts/Actions.java:6: error: Inconsistent action value; expected `android.accounts.action.ACCOUNT_OPENED`, was `android.accounts.ACCOUNT_OPENED` [ActionValue] [Rule C4 in go/android-api-guidelines]
+                src/android/accounts/Actions.java:8: error: Intent action constant name must be ACTION_FOO: SOMETHING [IntentName] [Rule C3 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                3 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -442,11 +459,14 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/accounts/Extras.java:5: error: Inconsistent extra value; expected `android.accounts.extra.AUTOMATIC_RULE_ID`, was `android.app.extra.AUTOMATIC_RULE_ID` [ActionValue]
-                src/android/accounts/Extras.java:7: error: Intent extra constant name must be EXTRA_FOO: RULE_ID [IntentName] [See https://s.android.com/api-guidelines#use-standard-prefixes-for-constants]
-                src/android/accounts/Extras.java:6: error: Intent extra constant name must be EXTRA_FOO: SOMETHING_EXTRA [IntentName] [See https://s.android.com/api-guidelines#use-standard-prefixes-for-constants]
+                src/android/accounts/Extras.java:5: error: Inconsistent extra value; expected `android.accounts.extra.AUTOMATIC_RULE_ID`, was `android.app.extra.AUTOMATIC_RULE_ID` [ActionValue] [Rule C4 in go/android-api-guidelines]
+                src/android/accounts/Extras.java:7: error: Intent extra constant name must be EXTRA_FOO: RULE_ID [IntentName] [Rule C3 in go/android-api-guidelines]
+                src/android/accounts/Extras.java:6: error: Intent extra constant name must be EXTRA_FOO: SOMETHING_EXTRA [IntentName] [Rule C3 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                3 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -470,10 +490,13 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/MissingEquals.java:4: error: Must override both equals and hashCode; missing one in android.pkg.MissingEquals [EqualsAndHashCode] [See https://s.android.com/api-guidelines#equals-and-hashcode]
-                src/android/pkg/MissingHashCode.java:7: error: Must override both equals and hashCode; missing one in android.pkg.MissingHashCode [EqualsAndHashCode] [See https://s.android.com/api-guidelines#equals-and-hashcode]
+                src/android/pkg/MissingEquals.java:4: error: Must override both equals and hashCode; missing one in android.pkg.MissingEquals [EqualsAndHashCode] [Rule M8 in go/android-api-guidelines]
+                src/android/pkg/MissingHashCode.java:7: error: Must override both equals and hashCode; missing one in android.pkg.MissingHashCode [EqualsAndHashCode] [Rule M8 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                2 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -534,13 +557,16 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/MissingCreator.java:5: error: Parcelable requires a `CREATOR` field; missing in android.pkg.MissingCreator [ParcelCreator] [See https://s.android.com/api-guidelines#parcelable-creator]
-                src/android/pkg/MissingDescribeContents.java:5: error: Parcelable requires `public int describeContents()`; missing in android.pkg.MissingDescribeContents [ParcelCreator] [See https://s.android.com/api-guidelines#parcelable-creator]
-                src/android/pkg/MissingWriteToParcel.java:5: error: Parcelable requires `void writeToParcel(Parcel, int)`; missing in android.pkg.MissingWriteToParcel [ParcelCreator] [See https://s.android.com/api-guidelines#parcelable-creator]
-                src/android/pkg/NonFinalParcelable.java:5: error: Parcelable classes must be final: android.pkg.NonFinalParcelable is not final [ParcelNotFinal] [See https://s.android.com/api-guidelines#parcelable-final]
-                src/android/pkg/ParcelableConstructor.java:6: error: Parcelable inflation is exposed through CREATOR, not raw constructors, in android.pkg.ParcelableConstructor [ParcelConstructor] [See https://s.android.com/api-guidelines#parcelable-creator]
+                src/android/pkg/MissingCreator.java:5: error: Parcelable requires a `CREATOR` field; missing in android.pkg.MissingCreator [ParcelCreator] [Rule FW3 in go/android-api-guidelines]
+                src/android/pkg/MissingDescribeContents.java:5: error: Parcelable requires `public int describeContents()`; missing in android.pkg.MissingDescribeContents [ParcelCreator] [Rule FW3 in go/android-api-guidelines]
+                src/android/pkg/MissingWriteToParcel.java:5: error: Parcelable requires `void writeToParcel(Parcel, int)`; missing in android.pkg.MissingWriteToParcel [ParcelCreator] [Rule FW3 in go/android-api-guidelines]
+                src/android/pkg/NonFinalParcelable.java:5: error: Parcelable classes must be final: android.pkg.NonFinalParcelable is not final [ParcelNotFinal] [Rule FW8 in go/android-api-guidelines]
+                src/android/pkg/ParcelableConstructor.java:6: error: Parcelable inflation is exposed through CREATOR, not raw constructors, in android.pkg.ParcelableConstructor [ParcelConstructor] [Rule FW3 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                5 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -624,10 +650,13 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/MyClass.java:6: error: Protected methods not allowed; must be public: method android.pkg.MyClass.wrong()} [ProtectedMember] [See https://s.android.com/api-guidelines#avoid-protected]
-                src/android/pkg/MyClass.java:8: error: Protected fields not allowed; must be public: field android.pkg.MyClass.wrong} [ProtectedMember] [See https://s.android.com/api-guidelines#avoid-protected]
+                src/android/pkg/MyClass.java:6: error: Protected methods not allowed; must be public: method android.pkg.MyClass.wrong()} [ProtectedMember] [Rule M7 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:8: error: Protected fields not allowed; must be public: field android.pkg.MyClass.wrong} [ProtectedMember] [Rule M7 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                2 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -653,19 +682,22 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/MyClass.java:11: error: Non-static field ALSO_BAD_CONSTANT must be named using fooBar style [StartWithLower] [See https://s.android.com/api-guidelines#style-conventions]
-                src/android/pkg/MyClass.java:11: error: Constant ALSO_BAD_CONSTANT must be marked static final [AllUpper] [See https://s.android.com/api-guidelines#constant-naming]
-                src/android/pkg/MyClass.java:7: error: Non-static field AlsoBadName must be named using fooBar style [StartWithLower] [See https://s.android.com/api-guidelines#style-conventions]
-                src/android/pkg/MyClass.java:10: error: Bare field BAD_CONSTANT must be marked final, or moved behind accessors if mutable [MutableBareField] [See https://s.android.com/api-guidelines#mutable-bare-field]
-                src/android/pkg/MyClass.java:10: error: Constant BAD_CONSTANT must be marked static final [AllUpper] [See https://s.android.com/api-guidelines#constant-naming]
-                src/android/pkg/MyClass.java:5: error: Bare field badMutable must be marked final, or moved behind accessors if mutable [MutableBareField] [See https://s.android.com/api-guidelines#mutable-bare-field]
-                src/android/pkg/MyClass.java:9: error: Bare field badStaticMutable must be marked final, or moved behind accessors if mutable [MutableBareField] [See https://s.android.com/api-guidelines#mutable-bare-field]
-                src/android/pkg/MyClass.java:6: error: Internal field mBadName must not be exposed [InternalField] [See https://s.android.com/api-guidelines#internal-fields]
-                src/android/pkg/MyClass.java:8: error: Constant field names must be named with only upper case characters: `android.pkg.MyClass#sBadStaticName`, should be `S_BAD_STATIC_NAME`? [AllUpper] [See https://s.android.com/api-guidelines#constant-naming]
-                src/android/pkg/MyClass.java:8: error: Internal field sBadStaticName must not be exposed [InternalField] [See https://s.android.com/api-guidelines#internal-fields]
-                src/android/pkg/MyClass.java:15: error: Internal field mBad must not be exposed [InternalField] [See https://s.android.com/api-guidelines#internal-fields]
+                src/android/pkg/MyClass.java:11: error: Non-static field ALSO_BAD_CONSTANT must be named using fooBar style [StartWithLower] [Rule S1 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:11: error: Constant ALSO_BAD_CONSTANT must be marked static final [AllUpper] [Rule C2 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:7: error: Non-static field AlsoBadName must be named using fooBar style [StartWithLower] [Rule S1 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:10: error: Bare field BAD_CONSTANT must be marked final, or moved behind accessors if mutable [MutableBareField] [Rule F2 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:10: error: Constant BAD_CONSTANT must be marked static final [AllUpper] [Rule C2 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:5: error: Bare field badMutable must be marked final, or moved behind accessors if mutable [MutableBareField] [Rule F2 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:9: error: Bare field badStaticMutable must be marked final, or moved behind accessors if mutable [MutableBareField] [Rule F2 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:6: error: Internal field mBadName must not be exposed [InternalField] [Rule F2 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:8: error: Constant field names must be named with only upper case characters: `android.pkg.MyClass#sBadStaticName`, should be `S_BAD_STATIC_NAME`? [AllUpper] [Rule C2 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:8: error: Internal field sBadStaticName must not be exposed [InternalField] [Rule F2 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:15: error: Internal field mBad must not be exposed [InternalField] [Rule F2 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                11 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -687,24 +719,6 @@
                         }
                     }
                     """
-                ),
-                kotlin(
-                    """
-                    package android.pkg
-
-                    class KotlinClass(val ok: Int) {
-                        companion object {
-                            const val OkConstant = 1
-                            const val OK_CONSTANT = 2
-                            @JvmField
-                            val OkSingleton = KotlinClass(3)
-                            @JvmField
-                            val OK_SINGLETON = KotlinClass(4)
-                        }
-
-                        object OkObject
-                    }
-                    """
                 )
             )
         )
@@ -716,27 +730,30 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/MyClass.java:7: error: Use android.net.Uri instead of java.net.URL (method android.pkg.MyClass.bad1()) [AndroidUri] [See https://s.android.com/api-guidelines#android-uri]
-                src/android/pkg/MyClass.java:8: error: Use android.net.Uri instead of java.net.URI (parameter param in android.pkg.MyClass.bad2(java.util.List<java.net.URI> param)) [AndroidUri] [See https://s.android.com/api-guidelines#android-uri]
-                src/android/pkg/MyClass.java:9: error: Use android.net.Uri instead of android.net.URL (parameter param in android.pkg.MyClass.bad3(android.net.URL param)) [AndroidUri] [See https://s.android.com/api-guidelines#android-uri]
+                src/android/pkg/MyClass.java:7: error: Use android.net.Uri instead of java.net.URL (method android.pkg.MyClass.bad1()) [AndroidUri] [Rule FW14 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:8: error: Use android.net.Uri instead of java.net.URI (parameter param in android.pkg.MyClass.bad2(java.util.List<java.net.URI> param)) [AndroidUri] [Rule FW14 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:9: error: Use android.net.Uri instead of android.net.URL (parameter param in android.pkg.MyClass.bad3(android.net.URL param)) [AndroidUri] [Rule FW14 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                3 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
                     package android.pkg;
 
                     import java.util.List;import java.util.concurrent.CompletableFuture;import java.util.concurrent.Future;
-                    import androidx.annotation.NonNull;
+                    import androidx.annotation.Nullable;
 
                     public final class MyClass {
-                        public @NonNull java.net.URL bad1() { throw new RuntimeException(); }
-                        public void bad2(@NonNull List<java.net.URI> param) { }
-                        public void bad3(@NonNull android.net.URL param) { }
+                        public @Nullable java.net.URL bad1() { return null; }
+                        public void bad2(@Nullable List<java.net.URI> param) { }
+                        public void bad3(@Nullable android.net.URL param) { }
                     }
                     """
                 ),
-                androidxNonNullSource
+                androidxNullableSource
             )
         )
     }
@@ -747,15 +764,18 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/MyClass.java:9: error: Use ListenableFuture (library), or a combination of Consumer<T>, Executor, and CancellationSignal (platform) instead of java.util.concurrent.CompletableFuture (method android.pkg.MyClass.bad1()) [BadFuture] [See https://s.android.com/api-guidelines#bad-future]
-                src/android/pkg/MyClass.java:10: error: Use ListenableFuture (library), or a combination of Consumer<T>, Executor, and CancellationSignal (platform) instead of java.util.concurrent.CompletableFuture (parameter param in android.pkg.MyClass.bad2(java.util.concurrent.CompletableFuture<java.lang.String> param)) [BadFuture] [See https://s.android.com/api-guidelines#bad-future]
-                src/android/pkg/MyClass.java:11: error: Use ListenableFuture (library), or a combination of Consumer<T>, Executor, and CancellationSignal (platform) instead of java.util.concurrent.Future (method android.pkg.MyClass.bad3()) [BadFuture] [See https://s.android.com/api-guidelines#bad-future]
-                src/android/pkg/MyClass.java:12: error: Use ListenableFuture (library), or a combination of Consumer<T>, Executor, and CancellationSignal (platform) instead of java.util.concurrent.Future (parameter param in android.pkg.MyClass.bad4(java.util.concurrent.Future<java.lang.String> param)) [BadFuture] [See https://s.android.com/api-guidelines#bad-future]
-                src/android/pkg/MyClass.java:21: error: BadCompletableFuture should not extend `java.util.concurrent.CompletableFuture`. In AndroidX, use (but do not extend) ListenableFuture. In platform, use a combination of Consumer<T>, Executor, and CancellationSignal`. [BadFuture] [See https://s.android.com/api-guidelines#bad-future]
-                src/android/pkg/MyClass.java:17: error: BadFuture should not extend `java.util.concurrent.Future`. In AndroidX, use (but do not extend) ListenableFuture. In platform, use a combination of Consumer<T>, Executor, and CancellationSignal`. [BadFuture] [See https://s.android.com/api-guidelines#bad-future]
-                src/android/pkg/MyClass.java:19: error: BadFutureClass should not implement `java.util.concurrent.Future`. In AndroidX, use (but do not extend) ListenableFuture. In platform, use a combination of Consumer<T>, Executor, and CancellationSignal`. [BadFuture] [See https://s.android.com/api-guidelines#bad-future]
+                src/android/pkg/MyClass.java:9: error: Use ListenableFuture (library), or a combination of Consumer<T>, Executor, and CancellationSignal (platform) instead of java.util.concurrent.CompletableFuture (method android.pkg.MyClass.bad1()) [BadFuture]
+                src/android/pkg/MyClass.java:10: error: Use ListenableFuture (library), or a combination of Consumer<T>, Executor, and CancellationSignal (platform) instead of java.util.concurrent.CompletableFuture (parameter param in android.pkg.MyClass.bad2(java.util.concurrent.CompletableFuture<java.lang.String> param)) [BadFuture]
+                src/android/pkg/MyClass.java:11: error: Use ListenableFuture (library), or a combination of Consumer<T>, Executor, and CancellationSignal (platform) instead of java.util.concurrent.Future (method android.pkg.MyClass.bad3()) [BadFuture]
+                src/android/pkg/MyClass.java:12: error: Use ListenableFuture (library), or a combination of Consumer<T>, Executor, and CancellationSignal (platform) instead of java.util.concurrent.Future (parameter param in android.pkg.MyClass.bad4(java.util.concurrent.Future<java.lang.String> param)) [BadFuture]
+                src/android/pkg/MyClass.java:21: error: BadCompletableFuture should not extend `java.util.concurrent.CompletableFuture`. In AndroidX, use (but do not extend) ListenableFuture. In platform, use a combination of Consumer<T>, Executor, and CancellationSignal`. [BadFuture]
+                src/android/pkg/MyClass.java:17: error: BadFuture should not extend `java.util.concurrent.Future`. In AndroidX, use (but do not extend) ListenableFuture. In platform, use a combination of Consumer<T>, Executor, and CancellationSignal`. [BadFuture]
+                src/android/pkg/MyClass.java:19: error: BadFutureClass should not implement `java.util.concurrent.Future`. In AndroidX, use (but do not extend) ListenableFuture. In platform, use a combination of Consumer<T>, Executor, and CancellationSignal`. [BadFuture]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                7 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -802,11 +822,14 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/MyClass.java:15: error: Don't expose @IntDef: SomeInt must be hidden. [PublicTypedef] [See https://s.android.com/api-guidelines#no-public-typedefs]
-                src/android/pkg/MyClass.java:20: error: Don't expose @LongDef: SomeLong must be hidden. [PublicTypedef] [See https://s.android.com/api-guidelines#no-public-typedefs]
-                src/android/pkg/MyClass.java:10: error: Don't expose @StringDef: SomeString must be hidden. [PublicTypedef] [See https://s.android.com/api-guidelines#no-public-typedefs]
+                src/android/pkg/MyClass.java:15: error: Don't expose @IntDef: SomeInt must be hidden. [PublicTypedef] [Rule FW15 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:20: error: Don't expose @LongDef: SomeLong must be hidden. [PublicTypedef] [Rule FW15 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:10: error: Don't expose @StringDef: SomeString must be hidden. [PublicTypedef] [Rule FW15 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                3 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -847,15 +870,18 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/RegistrationInterface.java:6: error: Found registerOverriddenUnpairedCallback but not unregisterOverriddenUnpairedCallback in android.pkg.RegistrationInterface [PairedRegistration] [See https://s.android.com/api-guidelines#callbacks-symmetry]
-                src/android/pkg/RegistrationMethods.java:8: error: Found registerUnpairedCallback but not unregisterUnpairedCallback in android.pkg.RegistrationMethods [PairedRegistration] [See https://s.android.com/api-guidelines#callbacks-symmetry]
-                src/android/pkg/RegistrationMethods.java:12: error: Found unregisterMismatchedCallback but not registerMismatchedCallback in android.pkg.RegistrationMethods [PairedRegistration] [See https://s.android.com/api-guidelines#callbacks-symmetry]
-                src/android/pkg/RegistrationMethods.java:13: error: Callback methods should be named register/unregister; was addCallback [RegistrationName] [See https://s.android.com/api-guidelines#callbacks-accessors]
-                src/android/pkg/RegistrationMethods.java:18: error: Found addUnpairedListener but not removeUnpairedListener in android.pkg.RegistrationMethods [PairedRegistration] [See https://s.android.com/api-guidelines#callbacks-symmetry]
-                src/android/pkg/RegistrationMethods.java:19: error: Found removeMismatchedListener but not addMismatchedListener in android.pkg.RegistrationMethods [PairedRegistration] [See https://s.android.com/api-guidelines#callbacks-symmetry]
-                src/android/pkg/RegistrationMethods.java:20: error: Listener methods should be named add/remove; was registerWrongListener [RegistrationName] [See https://s.android.com/api-guidelines#callbacks-accessors]
+                src/android/pkg/RegistrationInterface.java:6: error: Found registerOverriddenUnpairedCallback but not unregisterOverriddenUnpairedCallback in android.pkg.RegistrationInterface [PairedRegistration] [Rule L2 in go/android-api-guidelines]
+                src/android/pkg/RegistrationMethods.java:8: error: Found registerUnpairedCallback but not unregisterUnpairedCallback in android.pkg.RegistrationMethods [PairedRegistration] [Rule L2 in go/android-api-guidelines]
+                src/android/pkg/RegistrationMethods.java:12: error: Found unregisterMismatchedCallback but not registerMismatchedCallback in android.pkg.RegistrationMethods [PairedRegistration] [Rule L2 in go/android-api-guidelines]
+                src/android/pkg/RegistrationMethods.java:13: error: Callback methods should be named register/unregister; was addCallback [RegistrationName] [Rule L3 in go/android-api-guidelines]
+                src/android/pkg/RegistrationMethods.java:18: error: Found addUnpairedListener but not removeUnpairedListener in android.pkg.RegistrationMethods [PairedRegistration] [Rule L2 in go/android-api-guidelines]
+                src/android/pkg/RegistrationMethods.java:19: error: Found removeMismatchedListener but not addMismatchedListener in android.pkg.RegistrationMethods [PairedRegistration] [Rule L2 in go/android-api-guidelines]
+                src/android/pkg/RegistrationMethods.java:20: error: Listener methods should be named add/remove; was registerWrongListener [RegistrationName] [Rule L3 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                7 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -869,7 +895,7 @@
                         public void registerUnpairedCallback(@Nullable Runnable r) { }
                         // OK here because it is override
                         @Override
-                        public void registerOverriddenUnpairedCallback(@Nullable Runnable r) { }
+                        public void registerOverriddenUnpairedCallback(@Nullable Runnable r) { } 
                         public void unregisterMismatchedCallback(@Nullable Runnable r) { }
                         public void addCallback(@Nullable Runnable r) { }
 
@@ -904,17 +930,20 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/CheckSynchronization.java:12: error: Internal locks must not be exposed: method android.pkg.CheckSynchronization.errorMethod1(Runnable) [VisiblySynchronized] [See https://s.android.com/api-guidelines#avoid-synchronized]
-                src/android/pkg/CheckSynchronization.java:14: error: Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.pkg.CheckSynchronization.errorMethod2() [VisiblySynchronized] [See https://s.android.com/api-guidelines#avoid-synchronized]
-                src/android/pkg/CheckSynchronization.java:18: error: Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.pkg.CheckSynchronization.errorMethod2() [VisiblySynchronized] [See https://s.android.com/api-guidelines#avoid-synchronized]
-                src/android/pkg/CheckSynchronization.java:23: error: Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.pkg.CheckSynchronization.errorMethod3() [VisiblySynchronized] [See https://s.android.com/api-guidelines#avoid-synchronized]
-                src/android/pkg/CheckSynchronization2.kt:5: error: Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.pkg.CheckSynchronization2.errorMethod1() [VisiblySynchronized] [See https://s.android.com/api-guidelines#avoid-synchronized]
-                src/android/pkg/CheckSynchronization2.kt:8: error: Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.pkg.CheckSynchronization2.errorMethod2() [VisiblySynchronized] [See https://s.android.com/api-guidelines#avoid-synchronized]
-                src/android/pkg/CheckSynchronization2.kt:13: error: Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.pkg.CheckSynchronization2.errorMethod3() [VisiblySynchronized] [See https://s.android.com/api-guidelines#avoid-synchronized]
-                src/android/pkg/CheckSynchronization2.kt:16: error: Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.pkg.CheckSynchronization2.errorMethod4() [VisiblySynchronized] [See https://s.android.com/api-guidelines#avoid-synchronized]
-                src/android/pkg/CheckSynchronization2.kt:18: error: Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.pkg.CheckSynchronization2.errorMethod5() [VisiblySynchronized] [See https://s.android.com/api-guidelines#avoid-synchronized]
+                src/android/pkg/CheckSynchronization.java:12: error: Internal locks must not be exposed: method android.pkg.CheckSynchronization.errorMethod1(Runnable) [VisiblySynchronized] [Rule M5 in go/android-api-guidelines]
+                src/android/pkg/CheckSynchronization.java:14: error: Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.pkg.CheckSynchronization.errorMethod2() [VisiblySynchronized] [Rule M5 in go/android-api-guidelines]
+                src/android/pkg/CheckSynchronization.java:18: error: Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.pkg.CheckSynchronization.errorMethod2() [VisiblySynchronized] [Rule M5 in go/android-api-guidelines]
+                src/android/pkg/CheckSynchronization.java:23: error: Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.pkg.CheckSynchronization.errorMethod3() [VisiblySynchronized] [Rule M5 in go/android-api-guidelines]
+                src/android/pkg/CheckSynchronization2.kt:5: error: Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.pkg.CheckSynchronization2.errorMethod1() [VisiblySynchronized] [Rule M5 in go/android-api-guidelines]
+                src/android/pkg/CheckSynchronization2.kt:8: error: Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.pkg.CheckSynchronization2.errorMethod2() [VisiblySynchronized] [Rule M5 in go/android-api-guidelines]
+                src/android/pkg/CheckSynchronization2.kt:13: error: Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.pkg.CheckSynchronization2.errorMethod3() [VisiblySynchronized] [Rule M5 in go/android-api-guidelines]
+                src/android/pkg/CheckSynchronization2.kt:16: error: Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.pkg.CheckSynchronization2.errorMethod4() [VisiblySynchronized] [Rule M5 in go/android-api-guidelines]
+                src/android/pkg/CheckSynchronization2.kt:18: error: Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.pkg.CheckSynchronization2.errorMethod5() [VisiblySynchronized] [Rule M5 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                9 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -987,8 +1016,8 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/IntentBuilderNames.java:8: warning: Methods creating an Intent should be named `create<Foo>Intent()`, was `makeMyIntent` [IntentBuilderName] [See https://s.android.com/api-guidelines#intent-builder-createintent]
-                src/android/pkg/IntentBuilderNames.java:10: warning: Methods creating an Intent should be named `create<Foo>Intent()`, was `createIntentNow` [IntentBuilderName] [See https://s.android.com/api-guidelines#intent-builder-createintent]
+                src/android/pkg/IntentBuilderNames.java:8: warning: Methods creating an Intent should be named `create<Foo>Intent()`, was `makeMyIntent` [IntentBuilderName] [Rule FW1 in go/android-api-guidelines]
+                src/android/pkg/IntentBuilderNames.java:10: warning: Methods creating an Intent should be named `create<Foo>Intent()`, was `createIntentNow` [IntentBuilderName] [Rule FW1 in go/android-api-guidelines]
                 """,
             sourceFiles = arrayOf(
                 java(
@@ -1018,16 +1047,19 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/MyClass1.java:3: error: Inconsistent class name; should be `<Foo>Activity`, was `MyClass1` [ContextNameSuffix] [See https://s.android.com/api-guidelines#classes-subclass-naming]
-                src/android/pkg/MyClass1.java:6: warning: Methods implemented by developers should follow the on<Something> style, was `badlyNamedAbstractMethod` [OnNameExpected] [See https://s.android.com/api-guidelines#callback-method-naming]
-                src/android/pkg/MyClass1.java:7: warning: If implemented by developer, should follow the on<Something> style; otherwise consider marking final [OnNameExpected] [See https://s.android.com/api-guidelines#callback-method-naming]
+                src/android/pkg/MyClass1.java:3: error: Inconsistent class name; should be `<Foo>Activity`, was `MyClass1` [ContextNameSuffix] [Rule C4 in go/android-api-guidelines]
+                src/android/pkg/MyClass1.java:6: warning: Methods implemented by developers should follow the on<Something> style, was `badlyNamedAbstractMethod` [OnNameExpected]
+                src/android/pkg/MyClass1.java:7: warning: If implemented by developer, should follow the on<Something> style; otherwise consider marking final [OnNameExpected]
                 src/android/pkg/MyClass1.java:3: error: MyClass1 should not extend `Activity`. Activity subclasses are impossible to compose. Expose a composable API instead. [ForbiddenSuperClass]
-                src/android/pkg/MyClass2.java:3: error: Inconsistent class name; should be `<Foo>Provider`, was `MyClass2` [ContextNameSuffix] [See https://s.android.com/api-guidelines#classes-subclass-naming]
-                src/android/pkg/MyClass3.java:3: error: Inconsistent class name; should be `<Foo>Service`, was `MyClass3` [ContextNameSuffix] [See https://s.android.com/api-guidelines#classes-subclass-naming]
-                src/android/pkg/MyClass4.java:3: error: Inconsistent class name; should be `<Foo>Receiver`, was `MyClass4` [ContextNameSuffix] [See https://s.android.com/api-guidelines#classes-subclass-naming]
+                src/android/pkg/MyClass2.java:3: error: Inconsistent class name; should be `<Foo>Provider`, was `MyClass2` [ContextNameSuffix] [Rule C4 in go/android-api-guidelines]
+                src/android/pkg/MyClass3.java:3: error: Inconsistent class name; should be `<Foo>Service`, was `MyClass3` [ContextNameSuffix] [Rule C4 in go/android-api-guidelines]
+                src/android/pkg/MyClass4.java:3: error: Inconsistent class name; should be `<Foo>Receiver`, was `MyClass4` [ContextNameSuffix] [Rule C4 in go/android-api-guidelines]
                 src/android/pkg/MyOkActivity.java:3: error: MyOkActivity should not extend `Activity`. Activity subclasses are impossible to compose. Expose a composable API instead. [ForbiddenSuperClass]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                8 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -1088,22 +1120,20 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/Bad.java:12: warning: Builder must be final: android.pkg.Bad.BadBuilder [StaticFinalBuilder] [See https://s.android.com/api-guidelines#builders-static-inner]
-                src/android/pkg/Bad.java:12: warning: Builder must be static: android.pkg.Bad.BadBuilder [StaticFinalBuilder] [See https://s.android.com/api-guidelines#builders-static-inner]
-                src/android/pkg/Bad.java:13: warning: Builder constructor arguments must be mandatory (i.e. not @Nullable): parameter badParameter in android.pkg.Bad.BadBuilder(String badParameter) [OptionalBuilderConstructorArgument] [See https://s.android.com/api-guidelines#builders-nonnull-constructors]
-                src/android/pkg/Bad.java:36: warning: Builder methods names should use setFoo() / addFoo() / clearFoo() style: method android.pkg.Bad.BadBuilder.withBadSetterStyle(boolean) [BuilderSetStyle] [See https://s.android.com/api-guidelines#builder-method-naming]
-                src/android/pkg/Bad.java:39: warning: Builder setter must be @NonNull: method android.pkg.Bad.BadBuilder.setReturnsNullable(boolean) [SetterReturnsThis]
-                src/android/pkg/Bad.java:42: warning: Getter should be on the built object, not the builder: method android.pkg.Bad.BadBuilder.getOnBuilder() [GetterOnBuilder] [See https://s.android.com/api-guidelines#getter-on-builder]
-                src/android/pkg/Bad.java:44: warning: Methods must return the builder object (return type android.pkg.Bad.BadBuilder instead of void): method android.pkg.Bad.BadBuilder.setNotReturningBuilder(boolean) [SetterReturnsThis]
-                src/android/pkg/Bad.java:18: warning: android.pkg.Bad does not declare a `getWithoutMatchingGetters()` method matching method android.pkg.Bad.BadBuilder.addWithoutMatchingGetter(String) [MissingGetterMatchingBuilder] [See https://s.android.com/api-guidelines#builders-symmetric-setters]
-                src/android/pkg/Bad.java:21: warning: android.pkg.Bad does not declare a `isWithoutMatchingGetter()` method matching method android.pkg.Bad.BadBuilder.setWithoutMatchingGetter(boolean) [MissingGetterMatchingBuilder] [See https://s.android.com/api-guidelines#builders-symmetric-setters]
-                src/android/pkg/Bad.java:24: warning: android.pkg.Bad does not declare a `getPluralWithoutMatchingGetters()` method matching method android.pkg.Bad.BadBuilder.addPluralWithoutMatchingGetter(Collection<String>) [MissingGetterMatchingBuilder] [See https://s.android.com/api-guidelines#builders-symmetric-setters]
-                src/android/pkg/Bad.java:30: warning: android.pkg.Bad does not declare a getter method matching method android.pkg.Bad.BadBuilder.addPluralWithoutMatchingGetters(Collection<String>) (expected one of: [getPluralWithoutMatchingGetters(), getPluralWithoutMatchingGetterses()]) [MissingGetterMatchingBuilder] [See https://s.android.com/api-guidelines#builders-symmetric-setters]
-                src/android/pkg/Bad.java:44: warning: android.pkg.Bad does not declare a `isNotReturningBuilder()` method matching method android.pkg.Bad.BadBuilder.setNotReturningBuilder(boolean) [MissingGetterMatchingBuilder] [See https://s.android.com/api-guidelines#builders-symmetric-setters]
-                src/android/pkg/Bad.java:55: warning: Methods must return the builder object (return type android.pkg.Bad.BadGenericBuilder<T> instead of T): method android.pkg.Bad.BadGenericBuilder.setBoolean(boolean) [SetterReturnsThis]
-                src/android/pkg/Bad.java:50: warning: android.pkg.Bad.NoBuildMethodBuilder does not declare a `build()` method, but builder classes are expected to [MissingBuildMethod] [See https://s.android.com/api-guidelines#builder-must-declare-build]
-                src/android/pkg/TopLevelBuilder.java:3: warning: Builder should be defined as inner class: android.pkg.TopLevelBuilder [TopLevelBuilder] [See https://s.android.com/api-guidelines#builders-static-inner]
-                src/android/pkg/TopLevelBuilder.java:3: warning: android.pkg.TopLevelBuilder does not declare a `build()` method, but builder classes are expected to [MissingBuildMethod] [See https://s.android.com/api-guidelines#builder-must-declare-build]
+                src/android/pkg/Bad.java:12: warning: Builder must be final: android.pkg.Bad.BadBuilder [StaticFinalBuilder]
+                src/android/pkg/Bad.java:12: warning: Builder must be static: android.pkg.Bad.BadBuilder [StaticFinalBuilder]
+                src/android/pkg/Bad.java:13: warning: Builder constructor arguments must be mandatory (i.e. not @Nullable): parameter badParameter in android.pkg.Bad.BadBuilder(String badParameter) [OptionalBuilderConstructorArgument]
+                src/android/pkg/Bad.java:24: warning: Builder methods names should use setFoo() / addFoo() / clearFoo() style: method android.pkg.Bad.BadBuilder.withBadSetterStyle(boolean) [BuilderSetStyle]
+                src/android/pkg/Bad.java:27: warning: Builder setter must be @NonNull: method android.pkg.Bad.BadBuilder.setReturnsNullable(boolean) [SetterReturnsThis] [Rule M4 in go/android-api-guidelines]
+                src/android/pkg/Bad.java:30: warning: Getter should be on the built object, not the builder: method android.pkg.Bad.BadBuilder.getOnBuilder() [GetterOnBuilder]
+                src/android/pkg/Bad.java:32: warning: Methods must return the builder object (return type android.pkg.Bad.BadBuilder instead of void): method android.pkg.Bad.BadBuilder.setNotReturningBuilder(boolean) [SetterReturnsThis] [Rule M4 in go/android-api-guidelines]
+                src/android/pkg/Bad.java:18: warning: android.pkg.Bad does not declare a `getWithoutMatchingGetters()` method matching method android.pkg.Bad.BadBuilder.addWithoutMatchingGetter(String) [MissingGetterMatchingBuilder]
+                src/android/pkg/Bad.java:21: warning: android.pkg.Bad does not declare a `isWithoutMatchingGetter()` method matching method android.pkg.Bad.BadBuilder.setWithoutMatchingGetter(boolean) [MissingGetterMatchingBuilder]
+                src/android/pkg/Bad.java:32: warning: android.pkg.Bad does not declare a `isNotReturningBuilder()` method matching method android.pkg.Bad.BadBuilder.setNotReturningBuilder(boolean) [MissingGetterMatchingBuilder]
+                src/android/pkg/Bad.java:43: warning: Methods must return the builder object (return type android.pkg.Bad.BadGenericBuilder<T> instead of T): method android.pkg.Bad.BadGenericBuilder.setBoolean(boolean) [SetterReturnsThis] [Rule M4 in go/android-api-guidelines]
+                src/android/pkg/Bad.java:38: warning: android.pkg.Bad.NoBuildMethodBuilder does not declare a `build()` method, but builder classes are expected to [MissingBuildMethod]
+                src/android/pkg/TopLevelBuilder.java:3: warning: Builder should be defined as inner class: android.pkg.TopLevelBuilder [TopLevelBuilder]
+                src/android/pkg/TopLevelBuilder.java:3: warning: android.pkg.TopLevelBuilder does not declare a `build()` method, but builder classes are expected to [MissingBuildMethod]
                 """,
             sourceFiles = arrayOf(
                 java(
@@ -1126,16 +1156,6 @@
                         public int getInt();
                         @NonNull
                         public List<String> getStrings();
-                        @NonNull
-                        public List<String> getProperties();
-                        @NonNull
-                        public List<String> getRays();
-                        @NonNull
-                        public List<String> getBuses();
-                        @NonNull
-                        public List<String> getTaxes();
-                        @NonNull
-                        public List<String> getMessages();
                         public boolean isBoolean();
                         public boolean hasBoolean2();
                         public boolean shouldBoolean3();
@@ -1153,23 +1173,6 @@
                             public OkBuilder addString(@NonNull String value) { return this; }
 
                             @NonNull
-                            public OkBuilder addProperty(@NonNull String value) { return this; }
-
-                            @NonNull
-                            public OkBuilder addRay(@NonNull String value) { return this; }
-
-                            @NonNull
-                            public OkBuilder addBus(@NonNull String value) { return this; }
-
-                            @NonNull
-                            public OkBuilder addTax(@NonNull String value) { return this; }
-
-                            @NonNull
-                            public OkBuilder addMessages(@NonNull Collection<String> value) {
-                                return this;
-                            }
-
-                            @NonNull
                             public OkBuilder clearStrings() { return this; }
 
                             @NonNull
@@ -1202,24 +1205,6 @@
                     """
                     package android.pkg;
 
-                    public class SubOk extends Ok {
-
-                        public static final class Builder {
-                            public Builder() {}
-
-                            @NonNull
-                            public SubOk build() { return null; }
-
-                            @NonNull
-                            public Builder setInt(int value) { return this; }
-                        }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package android.pkg;
-
                     import androidx.annotation.NonNull;
                     import androidx.annotation.Nullable;
 
@@ -1242,18 +1227,6 @@
                             public BadBuilder setWithoutMatchingGetter(boolean v) { return this; }
 
                             @NonNull
-                            public BadBuilder addPluralWithoutMatchingGetter(
-                                @NonNull Collection<String> value) {
-                                return this;
-                            }
-
-                            @NonNull
-                            public BadBuilder addPluralWithoutMatchingGetters(
-                                @NonNull Collection<String> value) {
-                                return this;
-                            }
-
-                            @NonNull
                             public BadBuilder withBadSetterStyle(boolean v) { return this; }
 
                             @Nullable
@@ -1288,49 +1261,18 @@
     }
 
     @Test
-    fun `Check suppress works on inherited methods`() {
-        check(
-            apiLint = "", // enabled
-            compatibilityMode = false,
-            expectedIssues = """
-                warning: Should avoid odd sized primitives; use `int` instead of `short` in method android.pkg.Ok.Public.shouldFail(PublicT) [NoByteOrShort] [See https://s.android.com/api-guidelines#avoid-short-byte]
-                """,
-            sourceFiles = arrayOf(
-                java(
-                """
-                package android.pkg;
-
-                import androidx.annotation.NonNull;
-
-                public class Ok {
-
-                    static final class Hidden<HiddenT> {
-                        @SuppressWarnings("NoByteOrShort")
-                        public short suppressed(HiddenT t) { return null; }
-
-                        public short shouldFail(HiddenT t) { return null; }
-                    }
-
-                    public static final class Public<PublicT> extends Hidden<PublicT> {
-                    }
-                }
-                """
-                ),
-                androidxNonNullSource
-            )
-        )
-    }
-
-    @Test
     fun `Raw AIDL`() {
         check(
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/MyClass1.java:3: error: Raw AIDL interfaces must not be exposed: MyClass1 extends Binder [RawAidl] [See https://s.android.com/api-guidelines#no-public-binder]
-                src/android/pkg/MyClass2.java:3: error: Raw AIDL interfaces must not be exposed: MyClass2 implements IInterface [RawAidl] [See https://s.android.com/api-guidelines#no-public-binder]
+                src/android/pkg/MyClass1.java:3: error: Raw AIDL interfaces must not be exposed: MyClass1 extends Binder [RawAidl]
+                src/android/pkg/MyClass2.java:3: error: Raw AIDL interfaces must not be exposed: MyClass2 implements IInterface [RawAidl]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                2 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -1368,7 +1310,10 @@
             expectedIssues = """
                 src/com/android/pkg/MyClass.java:3: error: Internal classes must not be exposed [InternalClasses]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                1 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -1388,10 +1333,10 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/content/MyClass1.java:8: warning: Field type `android.view.View` violates package layering: nothing in `package android.content` should depend on `package android.view` [PackageLayering]
-                src/android/content/MyClass1.java:8: warning: Method return type `android.view.View` violates package layering: nothing in `package android.content` should depend on `package android.view` [PackageLayering]
-                src/android/content/MyClass1.java:8: warning: Method parameter type `android.view.View` violates package layering: nothing in `package android.content` should depend on `package android.view` [PackageLayering]
-                src/android/content/MyClass1.java:8: warning: Method parameter type `android.view.View` violates package layering: nothing in `package android.content` should depend on `package android.view` [PackageLayering]
+                src/android/content/MyClass1.java:8: warning: Field type `android.view.View` violates package layering: nothing in `package android.content` should depend on `package android.view` [PackageLayering] [Rule FW6 in go/android-api-guidelines]
+                src/android/content/MyClass1.java:8: warning: Method return type `android.view.View` violates package layering: nothing in `package android.content` should depend on `package android.view` [PackageLayering] [Rule FW6 in go/android-api-guidelines]
+                src/android/content/MyClass1.java:8: warning: Method parameter type `android.view.View` violates package layering: nothing in `package android.content` should depend on `package android.view` [PackageLayering] [Rule FW6 in go/android-api-guidelines]
+                src/android/content/MyClass1.java:8: warning: Method parameter type `android.view.View` violates package layering: nothing in `package android.content` should depend on `package android.view` [PackageLayering] [Rule FW6 in go/android-api-guidelines]
                 """,
             sourceFiles = arrayOf(
                 java(
@@ -1428,15 +1373,18 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                    src/android/pkg/MyClass.java:20: error: Symmetric method for `isVisibleBad` must be named `setVisibleBad`; was `setIsVisibleBad` [GetterSetterNames]
-                    src/android/pkg/MyClass.java:24: error: Symmetric method for `hasTransientStateBad` must be named `setHasTransientStateBad`; was `setTransientStateBad` [GetterSetterNames]
-                    src/android/pkg/MyClass.java:28: error: Symmetric method for `setHasTransientStateAlsoBad` must be named `hasTransientStateAlsoBad`; was `isHasTransientStateAlsoBad` [GetterSetterNames]
-                    src/android/pkg/MyClass.java:31: error: Symmetric method for `setCanRecordBad` must be named `canRecordBad`; was `isCanRecordBad` [GetterSetterNames]
-                    src/android/pkg/MyClass.java:34: error: Symmetric method for `setShouldFitWidthBad` must be named `shouldFitWidthBad`; was `isShouldFitWidthBad` [GetterSetterNames]
-                    src/android/pkg/MyClass.java:37: error: Symmetric method for `setWiFiRoamingSettingEnabledBad` must be named `isWiFiRoamingSettingEnabledBad`; was `getWiFiRoamingSettingEnabledBad` [GetterSetterNames]
-                    src/android/pkg/MyClass.java:40: error: Symmetric method for `setEnabledBad` must be named `isEnabledBad`; was `getEnabledBad` [GetterSetterNames]
+                    src/android/pkg/MyClass.java:20: error: Symmetric method for `isVisibleBad` must be named `setVisibleBad`; was `setIsVisibleBad` [GetterSetterNames] [Rule M6 in go/android-api-guidelines]
+                    src/android/pkg/MyClass.java:24: error: Symmetric method for `hasTransientStateBad` must be named `setHasTransientStateBad`; was `setTransientStateBad` [GetterSetterNames] [Rule M6 in go/android-api-guidelines]
+                    src/android/pkg/MyClass.java:28: error: Symmetric method for `setHasTransientStateAlsoBad` must be named `hasTransientStateAlsoBad`; was `isHasTransientStateAlsoBad` [GetterSetterNames] [Rule M6 in go/android-api-guidelines]
+                    src/android/pkg/MyClass.java:31: error: Symmetric method for `setCanRecordBad` must be named `canRecordBad`; was `isCanRecordBad` [GetterSetterNames] [Rule M6 in go/android-api-guidelines]
+                    src/android/pkg/MyClass.java:34: error: Symmetric method for `setShouldFitWidthBad` must be named `shouldFitWidthBad`; was `isShouldFitWidthBad` [GetterSetterNames] [Rule M6 in go/android-api-guidelines]
+                    src/android/pkg/MyClass.java:37: error: Symmetric method for `setWiFiRoamingSettingEnabledBad` must be named `isWiFiRoamingSettingEnabledBad`; was `getWiFiRoamingSettingEnabledBad` [GetterSetterNames] [Rule M6 in go/android-api-guidelines]
+                    src/android/pkg/MyClass.java:40: error: Symmetric method for `setEnabledBad` must be named `isEnabledBad`; was `getEnabledBad` [GetterSetterNames] [Rule M6 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                7 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -1493,45 +1441,14 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/MyClass.java:6: error: Parameter type is concrete collection (`java.util.HashMap`); must be higher-level interface [ConcreteCollection] [See https://s.android.com/api-guidelines#classes-collections]
-                src/android/pkg/MyClass.java:9: error: Return type is concrete collection (`java.util.Vector`); must be higher-level interface [ConcreteCollection] [See https://s.android.com/api-guidelines#classes-collections]
-                src/android/pkg/MyClass.java:10: error: Parameter type is concrete collection (`java.util.LinkedList`); must be higher-level interface [ConcreteCollection] [See https://s.android.com/api-guidelines#classes-collections]
+                src/android/pkg/MyClass.java:6: error: Parameter type is concrete collection (`java.util.HashMap`); must be higher-level interface [ConcreteCollection] [Rule CL2 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:9: error: Return type is concrete collection (`java.util.Vector`); must be higher-level interface [ConcreteCollection] [Rule CL2 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:10: error: Parameter type is concrete collection (`java.util.LinkedList`); must be higher-level interface [ConcreteCollection] [Rule CL2 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package android.pkg;
-
-                    import androidx.annotation.NonNull;
-
-                    public class MyClass {
-                        public MyClass(@NonNull java.util.HashMap<String,String> map1,
-                                @NonNull java.util.Map<String,String> map2) {
-                        }
-                        @NonNull
-                        public java.util.Vector<String> getList(@NonNull java.util.LinkedList<String> list) {
-                            throw new RuntimeException();
-                        }
-                    }
-                    """
-                ),
-                androidxNonNullSource
-            )
-        )
-    }
-
-    @Test
-    fun `Check nullable collections`() {
-        check(
-            apiLint = "", // enabled
-            compatibilityMode = false,
-            expectedIssues = """
-                src/android/pkg/MyCallback.java:4: warning: Type of parameter list in android.pkg.MyCallback.onFoo(java.util.List<java.lang.String> list) is a nullable collection (`java.util.List`); must be non-null [NullableCollection] [See https://s.android.com/api-guidelines#methods-prefer-non-null-collections]
-                src/android/pkg/MyClass.java:8: warning: Return type of method android.pkg.MyClass.getList(java.util.List<java.lang.String>) is a nullable collection (`java.util.List`); must be non-null [NullableCollection] [See https://s.android.com/api-guidelines#methods-prefer-non-null-collections]
-                src/android/pkg/MyClass.java:12: warning: Type of field android.pkg.MyClass.STRINGS is a nullable collection (`java.lang.String[]`); must be non-null [NullableCollection] [See https://s.android.com/api-guidelines#methods-prefer-non-null-collections]
-                src/android/pkg/MySubClass.java:12: warning: Return type of method android.pkg.MySubClass.getOtherList(java.util.List<java.lang.String>) is a nullable collection (`java.util.List`); must be non-null [NullableCollection] [See https://s.android.com/api-guidelines#methods-prefer-non-null-collections]
-                """,
+            expectedFail = """
+                3 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -1540,69 +1457,13 @@
                     import androidx.annotation.Nullable;
 
                     public class MyClass {
-                        public MyClass() { }
-
+                        public MyClass(@Nullable java.util.HashMap<String,String> map1,
+                                @Nullable java.util.Map<String,String> map2) {
+                        }
                         @Nullable
-                        public java.util.List<String> getList(@Nullable java.util.List<String> list) {
+                        public java.util.Vector<String> getList(@Nullable  java.util.LinkedList<String> list) {
                             return null;
                         }
-                        @Nullable
-                        public static final String[] STRINGS = null;
-
-                        /** @deprecated don't use this. */
-                        @Deprecated
-                        @Nullable
-                        public String[] ignoredBecauseDeprecated(@Nullable String[] ignored) {
-                            return null;
-                        }
-
-                        protected MyClass() {
-                        }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package android.pkg;
-
-                    import androidx.annotation.Nullable;
-
-                    /** @hide */
-                    public interface MyHiddenInterface {
-                        @Nullable
-                        java.util.List<String> getOtherList(@Nullable java.util.List<String> list);
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package android.pkg;
-
-                    import androidx.annotation.Nullable;
-
-                    public class MySubClass extends MyClass implements MyHiddenInterface {
-                        @Nullable
-                        public java.util.List<String> getList(@Nullable java.util.List<String> list) {
-                            // Ignored because it has the same nullability as its super method
-                            return null;
-                        }
-
-                        @Override
-                        @Nullable
-                        public java.util.List<String> getOtherList(@Nullable java.util.List<String> list) {
-                            // Reported because the super method is hidden.
-                            return null;
-                        }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package android.pkg;
-
-                    public class MyCallback {
-                        public void onFoo(@Nullable java.util.List<String> list) {
-                        }
                     }
                     """
                 ),
@@ -1617,7 +1478,7 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/accounts/OverlappingFlags.java:19: warning: Found overlapping flag constant values: `TEST1_FLAG_SECOND` with value 3 (0x3) and overlapping flag value 1 (0x1) from `TEST1_FLAG_FIRST` [OverlappingConstants] [See https://s.android.com/api-guidelines#overlapping-constants]
+                src/android/accounts/OverlappingFlags.java:19: warning: Found overlapping flag constant values: `TEST1_FLAG_SECOND` with value 3 (0x3) and overlapping flag value 1 (0x1) from `TEST1_FLAG_FIRST` [OverlappingConstants] [Rule C1 in go/android-api-guidelines]
                 """,
             sourceFiles = arrayOf(
                 java(
@@ -1659,14 +1520,17 @@
             ),
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/MyClass.java:6: error: Methods must not throw generic exceptions (`java.lang.Exception`) [GenericException] [See https://s.android.com/api-guidelines#appropriate-exception]
-                src/android/pkg/MyClass.java:7: error: Methods must not throw generic exceptions (`java.lang.Throwable`) [GenericException] [See https://s.android.com/api-guidelines#appropriate-exception]
-                src/android/pkg/MyClass.java:8: error: Methods must not throw generic exceptions (`java.lang.Error`) [GenericException] [See https://s.android.com/api-guidelines#appropriate-exception]
-                src/android/pkg/MyClass.java:9: warning: Methods taking no arguments should throw `IllegalStateException` instead of `java.lang.IllegalArgumentException` [IllegalStateException] [See https://s.android.com/api-guidelines#appropriate-exception]
-                src/android/pkg/MyClass.java:10: warning: Methods taking no arguments should throw `IllegalStateException` instead of `java.lang.NullPointerException` [IllegalStateException] [See https://s.android.com/api-guidelines#appropriate-exception]
-                src/android/pkg/MyClass.java:11: error: Methods calling system APIs should rethrow `RemoteException` as `RuntimeException` (but do not list it in the throws clause) [RethrowRemoteException] [See https://s.android.com/api-guidelines#appropriate-exception]
+                src/android/pkg/MyClass.java:6: error: Methods must not throw generic exceptions (`java.lang.Exception`) [GenericException] [Rule S1 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:7: error: Methods must not throw generic exceptions (`java.lang.Throwable`) [GenericException] [Rule S1 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:8: error: Methods must not throw generic exceptions (`java.lang.Error`) [GenericException] [Rule S1 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:9: warning: Methods taking no arguments should throw `IllegalStateException` instead of `java.lang.IllegalArgumentException` [IllegalStateException] [Rule S1 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:10: warning: Methods taking no arguments should throw `IllegalStateException` instead of `java.lang.NullPointerException` [IllegalStateException] [Rule S1 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:11: error: Methods calling system APIs should rethrow `RemoteException` as `RuntimeException` (but do not list it in the throws clause) [RethrowRemoteException] [Rule FW9 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                6 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -1695,10 +1559,13 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/MyClass.java:4: error: Must never reference Google (`MyGoogleService`) [MentionsGoogle] [See https://s.android.com/api-guidelines#mentions-google]
-                src/android/pkg/MyClass.java:5: error: Must never reference Google (`callGoogle`) [MentionsGoogle] [See https://s.android.com/api-guidelines#mentions-google]
+                src/android/pkg/MyClass.java:4: error: Must never reference Google (`MyGoogleService`) [MentionsGoogle]
+                src/android/pkg/MyClass.java:5: error: Must never reference Google (`callGoogle`) [MentionsGoogle]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                2 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -1721,11 +1588,14 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/MyClass.java:8: error: Type must not be heavy BitSet (method android.pkg.MyClass.reverse(java.util.BitSet)) [HeavyBitSet] [See https://s.android.com/api-guidelines#avoid-bitset]
-                src/android/pkg/MyClass.java:9: error: Type must not be heavy BitSet (parameter bitset in android.pkg.MyClass.reverse(java.util.BitSet bitset)) [HeavyBitSet] [See https://s.android.com/api-guidelines#avoid-bitset]
-                src/android/pkg/MyClass.java:6: error: Type must not be heavy BitSet (field android.pkg.MyClass.bitset) [HeavyBitSet] [See https://s.android.com/api-guidelines#avoid-bitset]
+                src/android/pkg/MyClass.java:8: error: Type must not be heavy BitSet (method android.pkg.MyClass.reverse(java.util.BitSet)) [HeavyBitSet]
+                src/android/pkg/MyClass.java:9: error: Type must not be heavy BitSet (parameter bitset in android.pkg.MyClass.reverse(java.util.BitSet bitset)) [HeavyBitSet]
+                src/android/pkg/MyClass.java:6: error: Type must not be heavy BitSet (field android.pkg.MyClass.bitset) [HeavyBitSet]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                3 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -1755,7 +1625,10 @@
                 src/android/pkg/MyFirstManager.java:6: error: Managers must always be obtained from Context; no direct constructors [ManagerConstructor]
                 src/android/pkg/MyFirstManager.java:8: error: Managers must always be obtained from Context (`get`) [ManagerLookup]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                2 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -1794,19 +1667,19 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/test/pkg/KotlinClass.kt:4: error: Must avoid boxed primitives (`java.lang.Double`) [AutoBoxing] [See https://s.android.com/api-guidelines#auto-boxing]
-                src/test/pkg/KotlinClass.kt:6: error: Must avoid boxed primitives (`java.lang.Boolean`) [AutoBoxing] [See https://s.android.com/api-guidelines#auto-boxing]
-                src/test/pkg/MyClass.java:9: error: Must avoid boxed primitives (`java.lang.Long`) [AutoBoxing] [See https://s.android.com/api-guidelines#auto-boxing]
-                src/test/pkg/MyClass.java:11: error: Must avoid boxed primitives (`java.lang.Short`) [AutoBoxing] [See https://s.android.com/api-guidelines#auto-boxing]
-                src/test/pkg/MyClass.java:12: error: Must avoid boxed primitives (`java.lang.Double`) [AutoBoxing] [See https://s.android.com/api-guidelines#auto-boxing]
-                src/test/pkg/MyClass.java:13: error: Must avoid boxed primitives (`java.lang.Boolean`) [AutoBoxing] [See https://s.android.com/api-guidelines#auto-boxing]
-                src/test/pkg/MyClass.java:6: error: Must avoid boxed primitives (`java.lang.Integer`) [AutoBoxing] [See https://s.android.com/api-guidelines#auto-boxing]
+                src/android/pkg/MyClass.java:9: error: Must avoid boxed primitives (`java.lang.Long`) [AutoBoxing] [Rule M11 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:11: error: Must avoid boxed primitives (`java.lang.Short`) [AutoBoxing] [Rule M11 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:12: error: Must avoid boxed primitives (`java.lang.Double`) [AutoBoxing] [Rule M11 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:6: error: Must avoid boxed primitives (`java.lang.Integer`) [AutoBoxing] [Rule M11 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                4 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
-                    package test.pkg;
+                    package android.pkg;
 
                     import androidx.annotation.Nullable;
 
@@ -1818,20 +1691,9 @@
                         }
                         @Nullable
                         public Short getDouble(@Nullable Double l) { return null; }
-                        @Nullable
-                        public Boolean getBoolean() { return null; }
                     }
                     """
                 ),
-                kotlin("""
-                    package test.pkg
-                    class KotlinClass {
-                        fun getIntegerOk(): Double { TODO() }
-                        fun getIntegerBad(): Double? { TODO() }
-                        fun getBooleanOk(): Boolean { TODO() }
-                        fun getBooleanBad(): Boolean? { TODO() }
-                    }
-                """),
                 androidxNullableSource
             )
         )
@@ -1846,7 +1708,10 @@
                 src/android/pkg/MyUtils1.java:3: error: Fully-static utility classes must not have constructor [StaticUtils]
                 src/android/pkg/MyUtils2.java:3: error: Fully-static utility classes must not have constructor [StaticUtils]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                2 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -1909,10 +1774,13 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/MyClass.java:11: error: Context is distinct, so it must be the first argument (method `wrong`) [ContextFirst]
-                src/android/pkg/MyClass.java:12: error: ContentResolver is distinct, so it must be the first argument (method `wrong`) [ContextFirst]
+                src/android/pkg/MyClass.java:11: error: Context is distinct, so it must be the first argument (method `wrong`) [ContextFirst] [Rule M3 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:12: error: ContentResolver is distinct, so it must be the first argument (method `wrong`) [ContextFirst] [Rule M3 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                2 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -1942,8 +1810,8 @@
             extraArguments = arrayOf(ARG_API_LINT, ARG_HIDE, "ExecutorRegistration"),
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/MyClass.java:7: warning: Listeners should always be at end of argument list (method `MyClass`) [ListenerLast] [See https://s.android.com/api-guidelines#placement-of-sam-parameters]
-                src/android/pkg/MyClass.java:10: warning: Listeners should always be at end of argument list (method `wrong`) [ListenerLast] [See https://s.android.com/api-guidelines#placement-of-sam-parameters]
+                src/android/pkg/MyClass.java:7: warning: Listeners should always be at end of argument list (method `MyClass`) [ListenerLast] [Rule M3 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:10: warning: Listeners should always be at end of argument list (method `wrong`) [ListenerLast] [Rule M3 in go/android-api-guidelines]
                 """,
             sourceFiles = arrayOf(
                 java(
@@ -2024,8 +1892,8 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/MyClass.java:16: warning: Registration methods should have overload that accepts delivery Executor: `registerWrongCallback` [ExecutorRegistration] [See https://s.android.com/api-guidelines#callbacks-listener]
-                src/android/pkg/MyClass.java:6: warning: Registration methods should have overload that accepts delivery Executor: `MyClass` [ExecutorRegistration] [See https://s.android.com/api-guidelines#callbacks-listener]
+                src/android/pkg/MyClass.java:16: warning: Registration methods should have overload that accepts delivery Executor: `registerWrongCallback` [ExecutorRegistration] [Rule L1 in go/android-api-guidelines]
+                src/android/pkg/MyClass.java:6: warning: Registration methods should have overload that accepts delivery Executor: `MyClass` [ExecutorRegistration] [Rule L1 in go/android-api-guidelines]
                 """,
             sourceFiles = arrayOf(
                 java(
@@ -2083,12 +1951,15 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/R.java:11: error: Expected resource name in `android.R.id` to be in the `fooBarBaz` style, was `wrong_style` [ResourceValueFieldName]
+                src/android/R.java:11: error: Expected resource name in `android.R.id` to be in the `fooBarBaz` style, was `wrong_style` [ResourceValueFieldName] [Rule C7 in go/android-api-guidelines]
                 src/android/R.java:17: error: Expected config name to be in the `config_fooBarBaz` style, was `config_wrong_config_style` [ConfigFieldName]
                 src/android/R.java:20: error: Expected resource name in `android.R.layout` to be in the `foo_bar_baz` style, was `wrongNameStyle` [ResourceFieldName]
-                src/android/R.java:31: error: Expected resource name in `android.R.style` to be in the `FooBar_Baz` style, was `wrong_style_name` [ResourceStyleFieldName]
+                src/android/R.java:31: error: Expected resource name in `android.R.style` to be in the `FooBar_Baz` style, was `wrong_style_name` [ResourceStyleFieldName] [Rule C7 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                4 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -2137,8 +2008,8 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/CheckFiles.java:13: warning: Methods accepting `File` should also accept `FileDescriptor` or streams: method android.pkg.CheckFiles.error(int,java.io.File) [StreamFiles]
-                src/android/pkg/CheckFiles.java:9: warning: Methods accepting `File` should also accept `FileDescriptor` or streams: constructor android.pkg.CheckFiles(android.content.Context,java.io.File) [StreamFiles]
+                src/android/pkg/CheckFiles.java:13: warning: Methods accepting `File` should also accept `FileDescriptor` or streams: method android.pkg.CheckFiles.error(int,java.io.File) [StreamFiles] [Rule M10 in go/android-api-guidelines]
+                src/android/pkg/CheckFiles.java:9: warning: Methods accepting `File` should also accept `FileDescriptor` or streams: constructor android.pkg.CheckFiles(android.content.Context,java.io.File) [StreamFiles] [Rule M10 in go/android-api-guidelines]
                 """,
             sourceFiles = arrayOf(
                 java(
@@ -2170,8 +2041,8 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/CheckFiles.java:13: warning: Methods accepting `File` should also accept `FileDescriptor` or streams: method android.pkg.CheckFiles.error(int,java.io.File) [StreamFiles]
-                src/android/pkg/CheckFiles.java:9: warning: Methods accepting `File` should also accept `FileDescriptor` or streams: constructor android.pkg.CheckFiles(android.content.Context,java.io.File) [StreamFiles]
+                src/android/pkg/CheckFiles.java:13: warning: Methods accepting `File` should also accept `FileDescriptor` or streams: method android.pkg.CheckFiles.error(int,java.io.File) [StreamFiles] [Rule M10 in go/android-api-guidelines]
+                src/android/pkg/CheckFiles.java:9: warning: Methods accepting `File` should also accept `FileDescriptor` or streams: constructor android.pkg.CheckFiles(android.content.Context,java.io.File) [StreamFiles] [Rule M10 in go/android-api-guidelines]
                 """,
             sourceFiles = arrayOf(
                 java(
@@ -2238,7 +2109,10 @@
                 src/android/pkg/MyClass.java:7: error: Methods must not mention RuntimeException subclasses in throws clauses (was `java.lang.SecurityException`) [BannedThrow]
                 src/android/pkg/MyClass.java:6: error: Methods must not mention RuntimeException subclasses in throws clauses (was `java.lang.ClassCastException`) [BannedThrow]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                2 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -2265,7 +2139,10 @@
                 src/android/pkg/MyClass.java:3: error: Trouble must be reported through an `Exception`, not an `Error` (`MyClass` extends `Error`) [ExtendsError]
                 src/android/pkg/MySomething.java:3: error: Exceptions must be named `FooException`, was `MySomething` [ExceptionName]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                2 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -2293,29 +2170,36 @@
             extraArguments = arrayOf(ARG_API_LINT, ARG_HIDE, "NoByteOrShort"),
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/UnitNameTest.java:7: error: Expected method name units to be `Hours`, was `Hr` in `getErrorHr` [MethodNameUnits] [See https://s.android.com/api-guidelines#unit-names]
-                src/android/pkg/UnitNameTest.java:8: error: Expected method name units to be `Nanos`, was `Ns` in `getErrorNs` [MethodNameUnits] [See https://s.android.com/api-guidelines#unit-names]
-                src/android/pkg/UnitNameTest.java:9: error: Expected method name units to be `Bytes`, was `Byte` in `getErrorByte` [MethodNameUnits] [See https://s.android.com/api-guidelines#unit-names]
-                src/android/pkg/UnitNameTest.java:14: error: Fractions must use floats, was `int` in `getErrorFraction` [FractionFloat]
-                src/android/pkg/UnitNameTest.java:15: error: Fractions must use floats, was `int` in `setErrorFraction` [FractionFloat]
-                src/android/pkg/UnitNameTest.java:19: error: Percentage must use ints, was `float` in `getErrorPercentage` [PercentageInt]
-                src/android/pkg/UnitNameTest.java:20: error: Percentage must use ints, was `float` in `setErrorPercentage` [PercentageInt]
-                src/android/pkg/UnitNameTest.java:22: error: Expected method name units to be `Bytes`, was `Byte` in `readSingleByte` [MethodNameUnits] [See https://s.android.com/api-guidelines#unit-names]
+                src/android/pkg/UnitNameTest.java:5: error: Expected method name units to be `Hours`, was `Hr` in `getErrorHr` [MethodNameUnits]
+                src/android/pkg/UnitNameTest.java:6: error: Expected method name units to be `Nanos`, was `Ns` in `getErrorNs` [MethodNameUnits]
+                src/android/pkg/UnitNameTest.java:7: error: Expected method name units to be `Bytes`, was `Byte` in `getErrorByte` [MethodNameUnits]
+                src/android/pkg/UnitNameTest.java:8: error: Returned time values are strongly encouraged to be in milliseconds unless you need the extra precision, was `getErrorNanos` [MethodNameUnits]
+                src/android/pkg/UnitNameTest.java:9: error: Returned time values are strongly encouraged to be in milliseconds unless you need the extra precision, was `getErrorMicros` [MethodNameUnits]
+                src/android/pkg/UnitNameTest.java:10: error: Returned time values must be in milliseconds, was `getErrorSeconds` [MethodNameUnits]
+                src/android/pkg/UnitNameTest.java:16: error: Fractions must use floats, was `int` in `getErrorFraction` [FractionFloat]
+                src/android/pkg/UnitNameTest.java:17: error: Fractions must use floats, was `int` in `setErrorFraction` [FractionFloat]
+                src/android/pkg/UnitNameTest.java:21: error: Percentage must use ints, was `float` in `getErrorPercentage` [PercentageInt]
+                src/android/pkg/UnitNameTest.java:22: error: Percentage must use ints, was `float` in `setErrorPercentage` [PercentageInt]
+                src/android/pkg/UnitNameTest.java:24: error: Expected method name units to be `Bytes`, was `Byte` in `readSingleByte` [MethodNameUnits]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                11 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
-                androidxNonNullSource,
                 java(
                     """
                     package android.pkg;
 
-                    import androidx.annotation.NonNull;
-
                     public class UnitNameTest {
                         public int okay() { return 0; }
                         public int getErrorHr() { return 0; }
                         public int getErrorNs() { return 0; }
                         public short getErrorByte() { return (short)0; }
+                        public int getErrorNanos() { return 0; }
+                        public long getErrorMicros() { return 0L; }
+                        public long getErrorSeconds() { return 0L; }
+                        public float getErrorSeconds() { return 0; }
 
                         public float getOkFraction() { return 0f; }
                         public void setOkFraction(float f) { }
@@ -2330,18 +2214,6 @@
 
                         public int readSingleByte() { return 0; }
 
-                        public static final class UnitNameTestBuilder {
-                            public UnitNameTestBuilder() {}
-
-                            @NonNull
-                            public UnitNameTest build() { return null; }
-
-                            @NonNull
-                            public UnitNameTestBuilder setOkFraction(float f) { return this; }
-
-                            @NonNull
-                            public UnitNameTestBuilder setOkPercentage(int i) { return this; }
-                        }
                     }
                     """
                 )
@@ -2558,7 +2430,10 @@
                 src/android/pkg/KotlinKeywordTest.java:7: error: Avoid method names that are Kotlin hard keywords ("fun"); see https://android.github.io/kotlin-guides/interop.html#no-hard-keywords [KotlinKeyword]
                 src/android/pkg/KotlinKeywordTest.java:8: error: Avoid field names that are Kotlin hard keywords ("as"); see https://android.github.io/kotlin-guides/interop.html#no-hard-keywords [KotlinKeyword]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                2 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -2592,7 +2467,10 @@
                 src/android/pkg/KotlinOperatorTest.java:9: error: Only one of `plus` and `plusAssign` methods should be present for Kotlin [UniqueKotlinOperator]
                 src/android/pkg/KotlinOperatorTest.java:10: info: Method can be invoked as a compound assignment operator from Kotlin: `plusAssign` (this is usually desirable; just make sure it makes sense for this type of object) [KotlinOperator]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                1 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -2620,34 +2498,30 @@
             extraArguments = arrayOf(ARG_API_LINT, ARG_HIDE, "AutoBoxing"),
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/ArrayTest.java:11: warning: Method should return Collection<Object> (or subclass) instead of raw array; was `java.lang.Object[]` [ArrayReturn] [See https://s.android.com/api-guidelines#methods-prefer-collection-over-array]
-                src/android/pkg/ArrayTest.java:13: warning: Method parameter should be Collection<Number> (or subclass) instead of raw array; was `java.lang.Number[]` [ArrayReturn] [See https://s.android.com/api-guidelines#methods-prefer-collection-over-array]
+                src/android/pkg/ArrayTest.java:11: warning: Method should return Collection<Object> (or subclass) instead of raw array; was `java.lang.Object[]` [ArrayReturn]
+                src/android/pkg/ArrayTest.java:13: warning: Method parameter should be Collection<Number> (or subclass) instead of raw array; was `java.lang.Number[]` [ArrayReturn]
                 """,
             sourceFiles = arrayOf(
                 java(
                     """
                     package android.pkg;
 
-                    import androidx.annotation.NonNull;
+                    import androidx.annotation.Nullable;
 
                     public class ArrayTest {
-                        @NonNull
-                        public int[] ok1() { throw new RuntimeException(); }
-                        @NonNull
-                        public String[] ok2() { throw new RuntimeException(); }
+                        @Nullable
+                        public int[] ok1() { return null; }
+                        @Nullable
+                        public String[] ok2() { return null; }
                         public void ok3(@Nullable int[] i) { }
-                        @NonNull
-                        public Object[] error1() { throw new RuntimeException(); }
-                        public void error2(@NonNull Number[] i) { }
-                        public void ok(@NonNull Number... args) { }
+                        @Nullable
+                        public Object[] error1() { return null; }
+                        public void error2(@Nullable Number[] i) { }
+                        public void ok(@Nullable Number... args) { }
                     }
                     """
                 ),
-                kotlin("""
-                    package test.pkg
-                    fun okMethod(vararg values: Integer, foo: Float, bar: Float)
-                    """),
-                androidxNonNullSource
+                androidxNullableSource
             )
         )
     }
@@ -2727,11 +2601,14 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/content/Context.java:11: error: Inconsistent service constant name; expected `SOMETHING_SERVICE`, was `OTHER_MANAGER` [ServiceName]
-                src/android/content/Context.java:12: error: Inconsistent service constant name; expected `OTHER_SERVICE`, was `OTHER_MANAGER_SERVICE` [ServiceName]
-                src/android/content/Context.java:9: error: Inconsistent service value; expected `other`, was `something` (Note: Do not change the name of already released services, which will break tools using `adb shell dumpsys`. Instead add `@SuppressLint("ServiceName"))` [ServiceName]
+                src/android/content/Context.java:11: error: Inconsistent service constant name; expected `SOMETHING_SERVICE`, was `OTHER_MANAGER` [ServiceName] [Rule C4 in go/android-api-guidelines]
+                src/android/content/Context.java:12: error: Inconsistent service constant name; expected `OTHER_SERVICE`, was `OTHER_MANAGER_SERVICE` [ServiceName] [Rule C4 in go/android-api-guidelines]
+                src/android/content/Context.java:9: error: Inconsistent service value; expected `other`, was `something` (Note: Do not change the name of already released services, which will break tools using `adb shell dumpsys`. Instead add `@SuppressLint("ServiceName"))` [ServiceName] [Rule C4 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                3 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -2801,9 +2678,12 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/CloneTest.java:7: error: Provide an explicit copy constructor instead of implementing `clone()` [NoClone] [See https://s.android.com/api-guidelines#avoid-clone]
+                src/android/pkg/CloneTest.java:7: error: Provide an explicit copy constructor instead of implementing `clone()` [NoClone]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                1 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -2858,10 +2738,13 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/PdfTest.java:6: error: Must use ParcelFileDescriptor instead of FileDescriptor in parameter fd in android.pkg.PdfTest.error1(java.io.FileDescriptor fd) [UseParcelFileDescriptor] [See https://s.android.com/api-guidelines#prefer-parcelfiledescriptor]
-                src/android/pkg/PdfTest.java:7: error: Must use ParcelFileDescriptor instead of FileDescriptor in method android.pkg.PdfTest.getFileDescriptor() [UseParcelFileDescriptor] [See https://s.android.com/api-guidelines#prefer-parcelfiledescriptor]
+                src/android/pkg/PdfTest.java:6: error: Must use ParcelFileDescriptor instead of FileDescriptor in parameter fd in android.pkg.PdfTest.error1(java.io.FileDescriptor fd) [UseParcelFileDescriptor] [Rule FW11 in go/android-api-guidelines]
+                src/android/pkg/PdfTest.java:7: error: Must use ParcelFileDescriptor instead of FileDescriptor in method android.pkg.PdfTest.getFileDescriptor() [UseParcelFileDescriptor] [Rule FW11 in go/android-api-guidelines]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                2 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -2911,8 +2794,8 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/ByteTest.java:4: warning: Should avoid odd sized primitives; use `int` instead of `byte` in parameter b in android.pkg.ByteTest.error1(byte b) [NoByteOrShort] [See https://s.android.com/api-guidelines#avoid-short-byte]
-                src/android/pkg/ByteTest.java:5: warning: Should avoid odd sized primitives; use `int` instead of `short` in parameter s in android.pkg.ByteTest.error2(short s) [NoByteOrShort] [See https://s.android.com/api-guidelines#avoid-short-byte]
+                src/android/pkg/ByteTest.java:4: warning: Should avoid odd sized primitives; use `int` instead of `byte` in parameter b in android.pkg.ByteTest.error1(byte b) [NoByteOrShort] [Rule FW12 in go/android-api-guidelines]
+                src/android/pkg/ByteTest.java:5: warning: Should avoid odd sized primitives; use `int` instead of `short` in parameter s in android.pkg.ByteTest.error2(short s) [NoByteOrShort] [Rule FW12 in go/android-api-guidelines]
                 """,
             sourceFiles = arrayOf(
                 java(
@@ -2935,9 +2818,12 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/MySingleton.java:8: error: Singleton classes should use `getInstance()` methods: `MySingleton` [SingletonConstructor] [See https://s.android.com/api-guidelines#singleton-class]
+                src/android/pkg/MySingleton.java:8: error: Singleton classes should use `getInstance()` methods: `MySingleton` [SingletonConstructor]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                1 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -2982,7 +2868,10 @@
                 src/android/pkg/IndirectActivity.java:2: error: IndirectActivity should not extend `Activity`. Activity subclasses are impossible to compose. Expose a composable API instead. [ForbiddenSuperClass]
                 src/android/pkg/MyTask.java:2: error: MyTask should not extend `AsyncTask`. AsyncTask is an implementation detail. Expose a listener or, in androidx, a `ListenableFuture` API instead [ForbiddenSuperClass]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                3 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -3017,9 +2906,12 @@
         check(
             apiLint = "", // enabled
             compatibilityMode = false,
+            // Note, src/android/pkg/FontFamily.kt:1 warning should not be there, it is a bug in PSI
+            // https://youtrack.jetbrains.com/issue/KT-32556
             expectedIssues = """
                 src/android/pkg/A.kt:3: info: Note that adding the `operator` keyword would allow calling this method using operator syntax [KotlinOperator]
                 src/android/pkg/Bar.kt:4: info: Note that adding the `operator` keyword would allow calling this method using operator syntax [KotlinOperator]
+                src/android/pkg/FontFamily.kt:1: info: Note that adding the `operator` keyword would allow calling this method using operator syntax [KotlinOperator]
                 src/android/pkg/Foo.java:7: info: Method can be invoked as a binary operator from Kotlin: `div` (this is usually desirable; just make sure it makes sense for this type of object) [KotlinOperator]
                 """,
             sourceFiles = arrayOf(
@@ -3083,13 +2975,16 @@
             extraArguments = arrayOf(ARG_API_LINT, ARG_HIDE, "AllUpper,StaticUtils,Enum"),
             compatibilityMode = false,
             expectedIssues = """
-                src/android/pkg/Foo.java:11: error: Missing nullability on parameter `name` in method `Foo` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-                src/android/pkg/Foo.java:12: error: Missing nullability on parameter `value` in method `setBadValue` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-                src/android/pkg/Foo.java:13: error: Missing nullability on method `getBadValue` return [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-                src/android/pkg/Foo.java:20: error: Missing nullability on parameter `duration` in method `methodMissingParamAnnotations` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-                src/android/pkg/Foo.java:7: error: Missing nullability on field `badField` in class `class android.pkg.Foo` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
+                src/android/pkg/Foo.java:11: error: Missing nullability on parameter `name` in method `Foo` [MissingNullability]
+                src/android/pkg/Foo.java:12: error: Missing nullability on parameter `value` in method `setBadValue` [MissingNullability]
+                src/android/pkg/Foo.java:13: error: Missing nullability on method `getBadValue` return [MissingNullability]
+                src/android/pkg/Foo.java:20: error: Missing nullability on parameter `duration` in method `methodMissingParamAnnotations` [MissingNullability]
+                src/android/pkg/Foo.java:7: error: Missing nullability on field `badField` in class `class android.pkg.Foo` [MissingNullability]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                5 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -3208,10 +3103,13 @@
             apiLint = "", // enabled
             compatibilityMode = false,
             expectedIssues = """
-                src/test/pkg/MyClass.java:13: error: Missing nullability on method `method4` return [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-                src/test/pkg/MyClass.java:14: error: Missing nullability on parameter `input` in method `method4` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
+                src/test/pkg/MyClass.java:13: error: Missing nullability on method `method4` return [MissingNullability]
+                src/test/pkg/MyClass.java:14: error: Missing nullability on parameter `input` in method `method4` [MissingNullability]
             """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                2 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -3259,12 +3157,15 @@
                 "NoSettingsProvider"
             ),
             expectedIssues = """
-                src/android/provider/Settings.java:9: error: New setting keys are not allowed (Field: BAD1); use getters/setters in relevant manager class [NoSettingsProvider] [See https://s.android.com/api-guidelines#no-settings-provider]
-                src/android/provider/Settings.java:11: error: Bare field okay2 must be marked final, or moved behind accessors if mutable [MutableBareField] [See https://s.android.com/api-guidelines#mutable-bare-field]
-                src/android/provider/Settings.java:17: error: New setting keys are not allowed (Field: BAD1); use getters/setters in relevant manager class [NoSettingsProvider] [See https://s.android.com/api-guidelines#no-settings-provider]
-                src/android/provider/Settings.java:21: error: New setting keys are not allowed (Field: BAD1); use getters/setters in relevant manager class [NoSettingsProvider] [See https://s.android.com/api-guidelines#no-settings-provider]
+                src/android/provider/Settings.java:9: error: New setting keys are not allowed (Field: BAD1); use getters/setters in relevant manager class [NoSettingsProvider]
+                src/android/provider/Settings.java:11: error: Bare field okay2 must be marked final, or moved behind accessors if mutable [MutableBareField] [Rule F2 in go/android-api-guidelines]
+                src/android/provider/Settings.java:17: error: New setting keys are not allowed (Field: BAD1); use getters/setters in relevant manager class [NoSettingsProvider]
+                src/android/provider/Settings.java:21: error: New setting keys are not allowed (Field: BAD1); use getters/setters in relevant manager class [NoSettingsProvider]
             """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                4 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -3355,127 +3256,4 @@
             )
         )
     }
-
-    @Test
-    fun `Inherited interface constants`() {
-        check(
-            compatibilityMode = false,
-            expectedIssues = "",
-            expectedFail = "",
-            apiLint = """
-                package javax.microedition.khronos.egl {
-                    public interface EGL {
-                    }
-                    public interface EGL10 extends javax.microedition.khronos.egl.EGL {
-                        field public static final int EGL_SUCCESS = 0;
-                    }
-                    public interface EGL11 extends javax.microedition.khronos.egl.EGL10 {
-                        field public static final int EGL_CONTEXT_LOST = 1;
-                    }
-                    public interface EGLDisplay {
-                    }
-                }
-                """,
-            sourceFiles = arrayOf(
-                java(
-                    """
-                        package javax.microedition.khronos.egl;
-
-                        public interface EGL {
-                        }
-                    """
-                ),
-                java(
-                    """
-                        package javax.microedition.khronos.egl;
-
-                        public interface EGL10 extends EGL {
-                            EGLDisplay EGL_SUCCESS = new EGLImpl();
-                        }
-                    """
-                ),
-                java(
-                    """
-                        package javax.microedition.khronos.egl;
-
-                        public interface EGL11 extends EGL10 {
-                            int EGL_CONTEXT_LOST = 1;
-                        }
-                    """
-                ),
-                java(
-                    """
-                        package javax.microedition.khronos.egl;
-
-                        public abstract class EGLDisplay {
-                        }
-                    """
-                )
-            )
-        )
-    }
-
-    @Test
-    fun `Inherited interface constants inherited through parents into children`() {
-        check(
-            compatibilityMode = false,
-            expectedIssues = "",
-            expectedFail = "",
-            apiLint = """
-                package android.provider {
-                  public static final class Settings.Global extends android.provider.Settings.NameValueTable {
-                  }
-                  public static class Settings.NameValueTable implements android.provider.BaseColumns {
-                  }
-                  public interface BaseColumns {
-                      field public static final String _ID = "_id";
-                  }
-                }
-                """,
-            sourceFiles = arrayOf(
-                java(
-                    """
-                        package android.provider;
-
-                        public class Settings {
-                            private Settings() { }
-                            public static final class Global extends NameValueTable {
-                            }
-                            public static final class NameValueTable implements BaseColumns {
-                            }
-                        }
-                    """
-                ),
-                java(
-                    """
-                        package android.provider;
-
-                        public interface BaseColumns {
-                            public static final String _ID = "_id";
-                        }
-                    """
-                )
-            ),
-            extraArguments = arrayOf("--error", "NoSettingsProvider")
-        )
-    }
-
-    @Test
-    fun `No warnings about nullability on private constructor getters`() {
-        check(
-            compatibilityMode = false,
-            expectedIssues = "",
-            apiLint = "",
-            sourceFiles = arrayOf(
-                kotlin(
-                    """
-                        package test.pkg
-                        class MyClass private constructor(
-                            val myParameter: Set<Int>
-                        )
-                    """
-                )
-            )
-        )
-    }
 }
diff --git a/src/test/java/com/android/tools/metalava/ArtifactTaggerTest.kt b/src/test/java/com/android/tools/metalava/ArtifactTaggerTest.kt
index c684645..46120eb 100644
--- a/src/test/java/com/android/tools/metalava/ArtifactTaggerTest.kt
+++ b/src/test/java/com/android/tools/metalava/ArtifactTaggerTest.kt
@@ -86,27 +86,25 @@
                 src/test/pkg/baz/Missing.java:2: error: No registered artifact signature file referenced class test.pkg.baz.Missing [NoArtifactData]
             """,
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg.foo;
-                    /**
-                     * My Foo class documentation.
-                     * @artifactId my.library.group:foo:1.0.0
-                     */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Foo {
-                    public Foo() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * @artifactId my.library.group:foo:1.0.0
-                     */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Inner {
-                    public Inner() { throw new RuntimeException("Stub!"); }
-                    }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg.foo;
+                /**
+                 * My Foo class documentation.
+                 * @artifactId my.library.group:foo:1.0.0
+                 */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Foo {
+                public Foo() { throw new RuntimeException("Stub!"); }
+                /**
+                 * @artifactId my.library.group:foo:1.0.0
+                 */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Inner {
+                public Inner() { throw new RuntimeException("Stub!"); }
+                }
+                }
+                """
             )
 
         )
diff --git a/src/test/java/com/android/tools/metalava/CompatibilityCheckTest.kt b/src/test/java/com/android/tools/metalava/CompatibilityCheckTest.kt
index f00d8a0..bde00a9 100644
--- a/src/test/java/com/android/tools/metalava/CompatibilityCheckTest.kt
+++ b/src/test/java/com/android/tools/metalava/CompatibilityCheckTest.kt
@@ -608,6 +608,7 @@
                             private AbstractMap() { }
                             public V put(K k, V v) { return null; }
                             public java.util.Set<K> keySet() { return null; }
+                            public V put(K k, V v) { return null; }
                             public void putAll(java.util.Map<? extends K, ? extends V> x) { }
                         }
                         """
@@ -711,16 +712,14 @@
     fun `Remove default parameter`() {
         check(
             expectedIssues = """
-                src/test/pkg/Foo.kt:3: error: Attempted to remove default value from parameter s1 in test.pkg.Foo in constructor test.pkg.Foo [DefaultValueChange] [See https://s.android.com/api-guidelines#default-value-removal]
-                src/test/pkg/Foo.kt:7: error: Attempted to remove default value from parameter s1 in test.pkg.Foo.method4 in method test.pkg.Foo.method4 [DefaultValueChange] [See https://s.android.com/api-guidelines#default-value-removal]
-
+                src/test/pkg/Foo.kt:7: error: Attempted to remove default value from parameter s1 in test.pkg.Foo.method4 in method test.pkg.Foo.method4 [DefaultValueChange]
                 """,
             compatibilityMode = false,
             inputKotlinStyleNulls = true,
             checkCompatibilityApi = """
                 package test.pkg {
                   public final class Foo {
-                    ctor public Foo(String? s1 = null);
+                    ctor public Foo();
                     method public final void method1(boolean b, String? s1);
                     method public final void method2(boolean b, String? s1);
                     method public final void method3(boolean b, String? s1 = "null");
@@ -733,45 +732,7 @@
                     """
                     package test.pkg
 
-                    class Foo(s1: String?) {
-                        fun method1(b: Boolean, s1: String?) { }         // No change
-                        fun method2(b: Boolean, s1: String? = null) { }  // Adding: OK
-                        fun method3(b: Boolean, s1: String? = null) { }  // No change
-                        fun method4(b: Boolean, s1: String?) { }         // Removed
-                    }
-                    """
-                )
-            )
-        )
-    }
-
-    @Test
-    fun `Remove optional parameter`() {
-        check(
-            expectedIssues = """
-                src/test/pkg/Foo.kt:3: error: Attempted to remove default value from parameter s1 in test.pkg.Foo in constructor test.pkg.Foo [DefaultValueChange] [See https://s.android.com/api-guidelines#default-value-removal]
-                src/test/pkg/Foo.kt:7: error: Attempted to remove default value from parameter s1 in test.pkg.Foo.method4 in method test.pkg.Foo.method4 [DefaultValueChange] [See https://s.android.com/api-guidelines#default-value-removal]
-                """,
-            compatibilityMode = false,
-            inputKotlinStyleNulls = true,
-            format = FileFormat.V4,
-            checkCompatibilityApi = """
-                package test.pkg {
-                  public final class Foo {
-                    ctor public Foo(optional String? s1);
-                    method public final void method1(boolean b, String? s1);
-                    method public final void method2(boolean b, String? s1);
-                    method public final void method3(boolean b, optional String? s1);
-                    method public final void method4(boolean b, optional String? s1);
-                  }
-                }
-                """,
-            sourceFiles = arrayOf(
-                kotlin(
-                    """
-                    package test.pkg
-
-                    class Foo(s1: String?) {                             // Removed
+                    class Foo {
                         fun method1(b: Boolean, s1: String?) { }         // No change
                         fun method2(b: Boolean, s1: String? = null) { }  // Adding: OK
                         fun method3(b: Boolean, s1: String? = null) { }  // No change
@@ -905,6 +866,7 @@
             expectedIssues = """
                 src/test/pkg/ExportedProperty.java:15: error: Method test.pkg.ExportedProperty.category has changed value from "" to nothing [ChangedValue]
                 src/test/pkg/ExportedProperty.java:14: error: Method test.pkg.ExportedProperty.floating has changed value from 1.0f to 1.1f [ChangedValue]
+                src/test/pkg/ExportedProperty.java:16: error: Method test.pkg.ExportedProperty.formatToHexString has changed value from nothing to false [ChangedValue]
                 src/test/pkg/ExportedProperty.java:13: error: Method test.pkg.ExportedProperty.prefix has changed value from "" to "hello" [ChangedValue]
                 """,
             checkCompatibilityApi = """
@@ -1772,11 +1734,12 @@
     @Test
     fun `Partial text file which references inner classes not listed elsewhere`() {
         // This happens in system and test files where we only include APIs that differ
-        // from the base API. When parsing these code bases we need to gracefully handle
+        // from the base IDE. When parsing these code bases we need to gracefully handle
         // references to inner classes.
         check(
             includeSystemApiAnnotations = true,
             expectedIssues = """
+                src/test/pkg/Bar.java:17: error: Added method test.pkg.Bar.Inner1.Inner2.addedMethod() to the system API [AddedMethod]
                 TESTROOT/current-api.txt:4: error: Removed method test.pkg.Bar.Inner1.Inner2.removedMethod() [RemovedMethod]
                 """,
             sourceFiles = arrayOf(
@@ -1823,7 +1786,7 @@
             ),
 
             extraArguments = arrayOf(
-                ARG_SHOW_ANNOTATION, "android.annotation.SystemApi",
+                ARG_SHOW_ANNOTATION, "android.annotation.TestApi",
                 ARG_HIDE_PACKAGE, "android.annotation",
                 ARG_HIDE_PACKAGE, "android.support.annotation"
             ),
@@ -1849,6 +1812,7 @@
             includeSystemApiAnnotations = true,
             expectedIssues = """
                 TESTROOT/current-api.txt:4: error: Removed method android.rolecontrollerservice.RoleControllerService.onClearRoleHolders() [RemovedMethod]
+                src/android/rolecontrollerservice/RoleControllerService.java:7: error: Added method android.rolecontrollerservice.RoleControllerService.onGrantDefaultRoles() to the system API [AddedAbstractMethod]
                 """,
             sourceFiles = arrayOf(
                 java(
@@ -1968,14 +1932,13 @@
     fun `Test verifying simple removed API`() {
         check(
             expectedIssues = """
-                TESTROOT/removed-current-api.txt:5: error: Removed method test.pkg.Bar.removedMethod2() [RemovedMethod]
+                src/test/pkg/Bar.java:8: error: Added method test.pkg.Bar.newlyRemoved() to the removed API [AddedMethod]
                 """,
             checkCompatibilityRemovedApiCurrent = """
                 package test.pkg {
                   public class Bar {
                     ctor public Bar();
                     method public void removedMethod();
-                    method public void removedMethod2();
                   }
                   public class Bar.Inner {
                     ctor public Bar.Inner();
@@ -1988,16 +1951,16 @@
                     package test.pkg;
                     @SuppressWarnings("JavaDoc")
                     public class Bar {
-                        /** @removed */ // still part of the removed api
+                        /** @removed */
                         public Bar() { }
-                        // no longer part of the removed api
+                        // No longer removed: /** @removed */
                         public void removedMethod() { }
                         /** @removed */
                         public void newlyRemoved() { }
 
                         public void newlyAdded() { }
 
-                        /** @removed */ // still part of the removed api
+                        /** @removed */
                         public class Inner { }
                     }
                     """
@@ -2256,77 +2219,6 @@
     }
 
     @Test
-    fun `Test check release with base api`() {
-        check(
-            expectedIssues = "",
-            checkCompatibilityApiReleased = """
-                package test.pkg {
-                  public class SomeClass {
-                      method public static void publicMethodA();
-                      method public static void publicMethodB();
-                  }
-                }
-                """,
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-
-                    public class SomeClass {
-                      public static void publicMethodA();
-                    }
-                    """
-                )
-            ),
-            checkCompatibilityBaseApi = """
-                package test.pkg {
-                  public class SomeClass {
-                      method public static void publicMethodB();
-                  }
-                }
-            """
-        )
-    }
-
-    @Test
-    fun `Test check a class moving from the released api to the base api`() {
-        check(
-            compatibilityMode = false,
-            checkCompatibilityApiReleased = """
-                package test.pkg {
-                  public class SomeClass1 {
-                    method public void method1();
-                  }
-                  public class SomeClass2 {
-                    method public void oldMethod();
-                  }
-                }
-                """,
-            checkCompatibilityBaseApi = """
-                package test.pkg {
-                  public class SomeClass2 {
-                    method public void newMethod();
-                  }
-                }
-            """,
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-
-                    public class SomeClass1 {
-                        public void method1();
-                    }
-                    """
-                )
-            ),
-            expectedIssues = """
-            TESTROOT/released-api.txt:6: error: Removed method test.pkg.SomeClass2.oldMethod() [RemovedMethod]
-            """.trimIndent()
-        )
-    }
-
-    @Test
     fun `Implicit nullness`() {
         check(
             compatibilityMode = false,
@@ -2619,593 +2511,6 @@
         )
     }
 
-    @Test
-    fun `Empty prev api with @hide and --show-annotation`() {
-        check(
-            compatibilityMode = false,
-            checkCompatibilityApiReleased = """
-                """,
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package android.media;
-
-                    /**
-                     * @hide
-                     */
-                    public class SubtitleController {
-                        public interface Listener {
-                            void onSubtitleTrackSelected() { }
-                        }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package android.media;
-                    import android.annotation.SystemApi;
-
-                    /**
-                     * @hide
-                     */
-                    @android.annotation.SystemApi
-                    public class MediaPlayer implements SubtitleController.Listener {
-                    }
-                    """
-                ),
-                systemApiSource
-            ),
-            extraArguments = arrayOf(
-                ARG_SHOW_ANNOTATION, "android.annotation.SystemApi",
-                ARG_HIDE_PACKAGE, "android.annotation",
-                ARG_HIDE_PACKAGE, "android.support.annotation"
-            ),
-            expectedIssues = ""
-
-        )
-    }
-
-    @Test
-    fun `Inherited systemApi method in an inner class`() {
-        check(
-            compatibilityMode = false,
-            checkCompatibilityApiReleased = """
-                package android.telephony {
-                  public class MmTelFeature.Capabilities {
-                    method public boolean isCapable(int);
-                  }
-                }
-                """,
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package android.telephony;
-
-                    /**
-                     * @hide
-                     */
-                    @android.annotation.SystemApi
-                    public class MmTelFeature {
-                        public static class Capabilities extends ParentCapabilities {
-                            @Override
-                            boolean isCapable(int argument) { return true; }
-                        }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package android.telephony;
-
-                    /**
-                     * @hide
-                     */
-                    @android.annotation.SystemApi
-                    public class Parent {
-                        public static class ParentCapabilities {
-                            public boolean isCapable(int argument) { return false; }
-                        }
-                    }
-                    """
-                ),
-                systemApiSource
-            ),
-            extraArguments = arrayOf(
-                ARG_SHOW_ANNOTATION, "android.annotation.SystemApi",
-                ARG_HIDE_PACKAGE, "android.annotation",
-                ARG_HIDE_PACKAGE, "android.support.annotation"
-            ),
-            expectedIssues = ""
-        )
-    }
-
-    @Test
-    fun `Moving removed api back to public api`() {
-        check(
-            compatibilityMode = false,
-            checkCompatibilityRemovedApiReleased = """
-                package android.content {
-                  public class ContextWrapper {
-                    method public void createContextForSplit();
-                  }
-                }
-                """,
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package android.content;
-
-                    public class ContextWrapper extends Parent {
-                        /** @removed */
-                        @Override
-                        public void getSharedPreferences() { }
-
-                        /** @hide */
-                        @Override
-                        public void createContextForSplit() { }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package android.content;
-
-                    public abstract class Parent {
-                        /** @hide */
-                        @Override
-                        public void getSharedPreferences() { }
-
-                        public abstract void createContextForSplit() { }
-                    }
-                    """
-                )
-            ),
-            expectedIssues = ""
-        )
-    }
-
-    @Test
-    fun `Inherited nullability annotations`() {
-        check(
-            compatibilityMode = false,
-            checkCompatibilityApiReleased = """
-                package test.pkg {
-                  public final class SAXException extends test.pkg.Parent {
-                  }
-                  public final class Parent extends test.pkg.Grandparent {
-                  }
-                  public final class Grandparent {
-                    method @Nullable public String getMessage();
-                  }
-                }
-                """,
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-
-                    public final class SAXException extends Parent {
-                        @Override public String getMessage() {
-                            return "sample";
-                        }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-
-                    public final class Parent extends Grandparent {
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-
-                    public final class Grandparent {
-                        public String getMessage() {
-                            return "sample";
-                        }
-                    }
-                    """
-                )
-            ),
-            mergeJavaStubAnnotations = """
-                package test.pkg;
-
-                public class Grandparent implements java.io.Serializable {
-                    @libcore.util.Nullable public test.pkg.String getMessage() { throw new RuntimeException("Stub!"); }
-                }
-            """,
-            expectedIssues = """
-                """
-        )
-    }
-
-    @Test
-    fun `Inherited @removed fields`() {
-        check(
-            compatibilityMode = false,
-            checkCompatibilityRemovedApiReleased = """
-                package android.provider {
-
-                  public static final class StreamItems implements android.provider.BaseColumns {
-                    field public static final String _COUNT = "_count";
-                    field public static final String _ID = "_id";
-                  }
-                }
-                """,
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package android.provider;
-
-                    /**
-                     * @removed
-                     */
-                    public static final class StreamItems implements BaseColumns {
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package android.provider;
-
-                    public interface BaseColumns {
-                        public static final String _ID = "_id";
-                        public static final String _COUNT = "_count";
-                    }
-                    """
-                )
-            ),
-            expectedIssues = """
-                """
-        )
-    }
-
-    @Test
-    fun `Inherited deprecated protected @removed method`() {
-        check(
-            compatibilityMode = false,
-            checkCompatibilityApiReleased = """
-                package android.icu.util {
-                  public class SpecificCalendar {
-                    method @Deprecated protected void validateField();
-                  }
-                }
-                """,
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package android.icu.util;
-                    import java.text.Format;
-
-                    public class SpecificCalendar extends Calendar {
-                        /**
-                         * @deprecated for this test
-                         * @hide
-                         */
-                        @Override
-                        @Deprecated
-                        protected void validateField() {
-                        }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package android.icu.util;
-
-                    public class Calendar {
-                        protected void validateField() {
-                        }
-                    }
-                    """
-                )
-            ),
-            expectedIssues = """
-                """
-        )
-    }
-
-    @Test
-    fun `Move class from SystemApi to public and then remove a method`() {
-        check(
-            compatibilityMode = false,
-            checkCompatibilityApiReleased = """
-                package android.hardware.lights {
-                  public static final class LightsRequest.Builder {
-                    ctor public LightsRequest.Builder();
-                    method public void clearLight();
-                    method public void setLight();
-                  }
-
-                  public final class LightsManager {
-                  }
-                }
-                """,
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package android.hardware.lights;
-
-                    import android.annotation.SystemApi;
-
-                    public class LightsRequest {
-                        public static class Builder {
-                            void clearLight() { }
-                        }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package android.hardware.lights;
-
-                    import android.annotation.SystemApi;
-
-                    /**
-                     * @hide
-                     */
-                    @SystemApi
-                    public class LightsManager {
-                    }
-                    """
-                ),
-                systemApiSource
-            ),
-            extraArguments = arrayOf(
-                ARG_SHOW_ANNOTATION, "android.annotation.SystemApi",
-                ARG_HIDE_PACKAGE, "android.annotation",
-                ARG_HIDE_PACKAGE, "android.support.annotation"
-            ),
-
-            expectedIssues = """
-                TESTROOT/released-api.txt:5: error: Removed method android.hardware.lights.LightsRequest.Builder.setLight() [RemovedMethod]
-                """
-        )
-    }
-
-    @Test
-    fun `Moving a field from SystemApi to public`() {
-        check(
-            compatibilityMode = false,
-            checkCompatibilityApiReleased = """
-                package android.content {
-                  public class Context {
-                    field public static final String BUGREPORT_SERVICE = "bugreport";
-                    method public File getPreloadsFileCache();
-                  }
-                }
-                """,
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package android.content;
-
-                    import android.annotation.SystemApi;
-
-                    public class Context {
-                        public static final String BUGREPORT_SERVICE = "bugreport";
-
-                        /**
-                         * @hide
-                         */
-                        @SystemApi
-                        public File getPreloadsFileCache() { return null; }
-                    }
-                    """
-                ),
-                systemApiSource
-            ),
-            extraArguments = arrayOf(
-                ARG_SHOW_ANNOTATION, "android.annotation.SystemApi",
-                ARG_HIDE_PACKAGE, "android.annotation",
-                ARG_HIDE_PACKAGE, "android.support.annotation"
-            ),
-
-            expectedIssues = """
-                """
-        )
-    }
-
-    @Test
-    fun `Compare interfaces when Object is redefined`() {
-        check(
-            compatibilityMode = false,
-            checkCompatibilityApiReleased = """
-                package java.lang {
-                  public class Object {
-                    method public final void wait();
-                  }
-                }
-                package test.pkg {
-                  public interface SomeInterface {
-                  }
-                }
-                """,
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-
-                    public interface SomeInterface {
-                    }
-                    """
-                )
-            ),
-            // it's not quite right to say that java.lang was removed, but it's better than also
-            // saying that SomeInterface no longer implements wait()
-            expectedIssues = """
-                TESTROOT/released-api.txt:1: error: Removed package java.lang [RemovedPackage]
-                """
-        )
-    }
-
-    @Test
-    fun `Overriding method without redeclaring nullability`() {
-        check(
-            compatibilityMode = false,
-            checkCompatibilityApiReleased = """
-                package test.pkg {
-                  public class Child extends test.pkg.Parent {
-                  }
-                  public class Parent {
-                    method public void sample(@Nullable String);
-                  }
-                }
-                """,
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-
-                    public class Child extends Parent {
-                        public void sample(String arg) {
-                        }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-
-                    public class Parent {
-                        public void sample(@Nullable String arg) {
-                        }
-                    }
-                    """
-                )
-            ),
-            // The correct behavior would be for this test to fail, because of the removal of
-            // nullability annotations on the child class. However, when we generate signature files,
-            // we omit methods having the same signature as super methods, so if we were to generate
-            // a signature file for this source, we would generate the given signature file. So,
-            // we temporarily allow (and expect) this to pass without errors
-            // expectedIssues = "src/test/pkg/Child.java:4: error: Attempted to remove @Nullable annotation from parameter arg in test.pkg.Child.sample(String arg) [InvalidNullConversion]"
-            expectedIssues = ""
-        )
-    }
-
-    @Test
-    fun `Final class inherits a method`() {
-        check(
-            compatibilityMode = false,
-            checkCompatibilityApiReleased = """
-                package java.security {
-                  public abstract class BasicPermission extends java.security.Permission {
-                    method public boolean implies(java.security.Permission);
-                  }
-                  public abstract class Permission {
-                    method public abstract boolean implies(java.security.Permission);
-                  }
-                }
-                package javax.security.auth {
-                  public final class AuthPermission extends java.security.BasicPermission {
-                  }
-                }
-                """,
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package javax.security.auth;
-
-                    public final class AuthPermission extends java.security.BasicPermission {
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package java.security;
-
-                    public abstract class BasicPermission extends Permission {
-                        public boolean implies(Permission p) {
-                            return true;
-                        }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package java.security;
-                    public abstract class Permission {
-                        public abstract boolean implies(Permission permission);
-                        }
-                    }
-                    """
-                )
-            ),
-            expectedIssues = ""
-        )
-    }
-
-    @Test
-    fun `Implementing undefined interface`() {
-        check(
-            compatibilityMode = false,
-            checkCompatibilityApiReleased = """
-                package org.apache.http.conn.scheme {
-                  @Deprecated public final class PlainSocketFactory implements org.apache.http.conn.scheme.SocketFactory {
-                  }
-                }
-                """,
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package org.apache.http.conn.scheme;
-
-                    /** @deprecated */
-                    @Deprecated
-                    public final class PlainSocketFactory implements SocketFactory {
-                    }
-                    """
-                )
-            ),
-            expectedIssues = ""
-        )
-    }
-
-    @Test
-    fun `Inherited abstract method`() {
-        check(
-            compatibilityMode = false,
-            checkCompatibilityApiReleased = """
-                package test.pkg {
-                  public class MeasureFormat {
-                      method public test.pkg.MeasureFormat parse();
-                  }
-                }
-                """,
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-
-                    public class MeasureFormat extends UFormat {
-                        private MeasureFormat() { }
-                        /** @hide */
-                        public MeasureFormat parse();
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    import android.annotation.SystemApi;
-
-                    public abstract class UFormat {
-                        public abstract UFormat parse() {
-                        }
-                    }
-                    """
-                ),
-                systemApiSource
-            ),
-            expectedIssues = ""
-        )
-    }
-
     @Ignore("Not currently working: we're getting the wrong PSI results; I suspect caching across the two codebases")
     @Test
     fun `Test All Android API levels`() {
@@ -3764,85 +3069,6 @@
         )
     }
 
-    @Test
-    fun `Remove fun modifier from interface`() {
-        check(
-            expectedIssues = """
-                src/test/pkg/FunctionalInterface.kt:3: error: Cannot remove 'fun' modifier from class test.pkg.FunctionalInterface: source incompatible change [FunRemoval]
-                """,
-            format = FileFormat.V4,
-            checkCompatibilityApi = """
-                // Signature format: 4.0
-                package test.pkg {
-                  public fun interface FunctionalInterface {
-                    method public boolean methodOne(int number);
-                  }
-                }
-                """,
-            sourceFiles = arrayOf(
-                kotlin(
-                    """
-                    package test.pkg
-
-                    interface FunctionalInterface {
-                        fun methodOne(number: Int): Boolean
-                    }
-                    """
-                )
-            )
-        )
-    }
-
-    @Test
-    fun `Remove fun modifier from interface signature files`() {
-        check(
-            expectedIssues = """
-                TESTROOT/load-api.txt:3: error: Cannot remove 'fun' modifier from class test.pkg.FunctionalInterface: source incompatible change [FunRemoval]
-                """,
-            format = FileFormat.V4,
-            checkCompatibilityApi = """
-                // Signature format: 4.0
-                package test.pkg {
-                  public fun interface FunctionalInterface {
-                    method public boolean methodOne(int number);
-                  }
-                }
-                """,
-            signatureSource = """
-                // Signature format: 4.0
-                package test.pkg {
-                  public interface FunctionalInterface {
-                    method public boolean methodOne(int number);
-                  }
-                }
-            """.trimIndent()
-        )
-    }
-
-    @Test
-    fun `Adding default value to annotation parameter`() {
-        check(
-            expectedIssues = "",
-            format = FileFormat.V4,
-            checkCompatibilityApi = """
-                // Signature format: 4.0
-                package androidx.annotation.experimental {
-                  public @interface UseExperimental {
-                    method public abstract Class<?> markerClass();
-                  }
-                }
-                """,
-            sourceFiles = arrayOf(
-                java("""
-                    package androidx.annotation.experimental;
-                    public @interface UseExperimental {
-                        Class<?> markerClass() default void.class;
-                    }
-                """)
-            )
-        )
-    }
-
     // TODO: Check method signatures changing incompatibly (look especially out for adding new overloaded
     // methods and comparator getting confused!)
     //   ..equals on the method items should actually be very useful!
diff --git a/src/test/java/com/android/tools/metalava/CoreApiTest.kt b/src/test/java/com/android/tools/metalava/CoreApiTest.kt
index 5ed3021..aca9590 100644
--- a/src/test/java/com/android/tools/metalava/CoreApiTest.kt
+++ b/src/test/java/com/android/tools/metalava/CoreApiTest.kt
@@ -87,29 +87,28 @@
                   }
                 }
                 """,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    /**
-                     * Hide everything in this package:
-                     */
-                    package test.pkg;
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    /**
-                     * Included because it is annotated with a --show-single-annotation
-                     */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Exposed {
-                    Exposed() { throw new RuntimeException("Stub!"); }
-                    public void exposed() { throw new RuntimeException("Stub!"); }
-                    public java.lang.String exposed;
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                /**
+                 * Hide everything in this package:
+                 */
+                package test.pkg;
+                """,
+                // Specify target with [] since NotExposed is not included in the stubs, so
+                // matching up stub expected files here with source inputs doesn't match
+                """
+                [test/pkg/Exposed.java]
+                package test.pkg;
+                /**
+                 * Included because it is annotated with a --show-single-annotation
+                 */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Exposed {
+                Exposed() { throw new RuntimeException("Stub!"); }
+                public void exposed() { throw new RuntimeException("Stub!"); }
+                public java.lang.String exposed;
+                }
+                """
             ),
             extraArguments = arrayOf(
                 ARG_SHOW_SINGLE_ANNOTATION, "libcore.api.IntraCoreApi",
@@ -179,30 +178,29 @@
                   }
                 }
                 """,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    /**
-                     * Hide everything in this package:
-                     * @hide
-                     */
-                    package test.pkg;
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    /**
-                     * Included because it is annotated with a --show-single-annotation
-                     * @hide
-                     */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Exposed {
-                    Exposed() { throw new RuntimeException("Stub!"); }
-                    public void exposed() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                /**
+                 * Hide everything in this package:
+                 * @hide
+                 */
+                package test.pkg;
+                """,
+                // Specify target with [] since NotExposed is not included in the stubs, so
+                // matching up stub expected files here with source inputs doesn't match
+                """
+                [test/pkg/Exposed.java]
+                package test.pkg;
+                /**
+                 * Included because it is annotated with a --show-single-annotation
+                 * @hide
+                 */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Exposed {
+                Exposed() { throw new RuntimeException("Stub!"); }
+                public void exposed() { throw new RuntimeException("Stub!"); }
+                }
+                """
             ),
             extraArguments = arrayOf(
                 ARG_SHOW_SINGLE_ANNOTATION, "libcore.api.IntraCoreApi",
@@ -340,18 +338,19 @@
                   }
                 }
                 """,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class ExposedClass {
-                    public ExposedClass() { throw new RuntimeException("Stub!"); }
-                    public void exposedMethod() { throw new RuntimeException("Stub!"); }
-                    public java.lang.String exposedField;
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                NO_STUB,
+                NO_STUB,
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class ExposedClass {
+                public ExposedClass() { throw new RuntimeException("Stub!"); }
+                public void exposedMethod() { throw new RuntimeException("Stub!"); }
+                public java.lang.String exposedField;
+                }
+                """,
+                NO_STUB
             ),
             extraArguments = arrayOf(
                 ARG_HIDE_META_ANNOTATION, "libcore.api.LibCoreMetaHidden"
diff --git a/src/test/java/com/android/tools/metalava/DocAnalyzerTest.kt b/src/test/java/com/android/tools/metalava/DocAnalyzerTest.kt
index 0d7de79..cda9dfe 100644
--- a/src/test/java/com/android/tools/metalava/DocAnalyzerTest.kt
+++ b/src/test/java/com/android/tools/metalava/DocAnalyzerTest.kt
@@ -2,11 +2,11 @@
 
 import com.android.tools.lint.checks.infrastructure.TestFiles.source
 import com.android.tools.metalava.model.psi.trimDocIndent
+import com.google.common.io.Files
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertTrue
 import org.junit.Test
 import java.io.File
-import java.nio.file.Files
 import kotlin.text.Charsets.UTF_8
 
 /** Tests for the [DocAnalyzer] which enhances the docs */
@@ -37,38 +37,36 @@
             ),
             checkCompilation = false, // needs androidx.annotations in classpath
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Foo {
-                    public Foo() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * These are the docs for method1.
-                     * @param factor1 This value must never be {@code null}.
-                     * @param factor2 This value must never be {@code null}.
-                     * @return This value may be {@code null}.
-                     */
-                    @androidx.annotation.Nullable
-                    public java.lang.Double method1(@androidx.annotation.NonNull java.lang.Double factor1, @androidx.annotation.NonNull java.lang.Double factor2) { throw new RuntimeException("Stub!"); }
-                    /**
-                     * These are the docs for method2. It can sometimes return null.
-                     * @param factor1 This value must never be {@code null}.
-                     * @param factor2 This value must never be {@code null}.
-                     */
-                    @androidx.annotation.Nullable
-                    public java.lang.Double method2(@androidx.annotation.NonNull java.lang.Double factor1, @androidx.annotation.NonNull java.lang.Double factor2) { throw new RuntimeException("Stub!"); }
-                    /**
-                     * @param factor1 This value must never be {@code null}.
-                     * @param factor2 This value must never be {@code null}.
-                     * @return This value may be {@code null}.
-                     */
-                    @androidx.annotation.Nullable
-                    public java.lang.Double method3(@androidx.annotation.NonNull java.lang.Double factor1, @androidx.annotation.NonNull java.lang.Double factor2) { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Foo {
+                public Foo() { throw new RuntimeException("Stub!"); }
+                /**
+                 * These are the docs for method1.
+                 * @param factor1 This value must never be {@code null}.
+                 * @param factor2 This value must never be {@code null}.
+                 * @return This value may be {@code null}.
+                 */
+                @androidx.annotation.Nullable
+                public java.lang.Double method1(@androidx.annotation.NonNull java.lang.Double factor1, @androidx.annotation.NonNull java.lang.Double factor2) { throw new RuntimeException("Stub!"); }
+                /**
+                 * These are the docs for method2. It can sometimes return null.
+                 * @param factor1 This value must never be {@code null}.
+                 * @param factor2 This value must never be {@code null}.
+                 */
+                @androidx.annotation.Nullable
+                public java.lang.Double method2(@androidx.annotation.NonNull java.lang.Double factor1, @androidx.annotation.NonNull java.lang.Double factor2) { throw new RuntimeException("Stub!"); }
+                /**
+                 * @param factor1 This value must never be {@code null}.
+                 * @param factor2 This value must never be {@code null}.
+                 * @return This value may be {@code null}.
+                 */
+                @androidx.annotation.Nullable
+                public java.lang.Double method3(@androidx.annotation.NonNull java.lang.Double factor1, @androidx.annotation.NonNull java.lang.Double factor2) { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -99,22 +97,20 @@
             ),
             checkCompilation = true,
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package android.annotation;
-                    /**
-                     * Denotes that an integer parameter, field or method return value is expected
-                     * to be a String resource reference (e.g.&nbsp;{@code android.R.string.ok}).
-                     */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    @java.lang.annotation.Documented
-                    @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS)
-                    @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.LOCAL_VARIABLE})
-                    public @interface StringRes {
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package android.annotation;
+                /**
+                 * Denotes that an integer parameter, field or method return value is expected
+                 * to be a String resource reference (e.g.&nbsp;{@code android.R.string.ok}).
+                 */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                @java.lang.annotation.Documented
+                @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS)
+                @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.LOCAL_VARIABLE})
+                public @interface StringRes {
+                }
+                """
             ),
             extraArguments = arrayOf(ARG_HIDE, "Typo") // "e.g. " correction should still run with Typo fixing is off.
         )
@@ -139,18 +135,16 @@
             checkCompilation = true,
             docStubs = true,
             expectedIssues = "src/test/pkg/Foo.java:2: warning: Replaced Andriod with Android in the documentation for class test.pkg.Foo [Typo]",
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    /** This is an API for Android. Replace all occurrences: Android. */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Foo {
-                    /** Ignore matches within words: xAndriodx */
-                    public Foo() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                /** This is an API for Android. Replace all occurrences: Android. */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Foo {
+                /** Ignore matches within words: xAndriodx */
+                public Foo() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -217,49 +211,47 @@
             ),
             checkCompilation = false, // needs androidx.annotations in classpath
             expectedIssues = "src/test/pkg/PermissionTest.java:31: lint: Unrecognized permission `carier priviliges`; did you mean `carrier privileges`? [MissingPermission]",
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    import android.Manifest;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class PermissionTest {
-                    public PermissionTest() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * Requires {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
-                     */
-                    @androidx.annotation.RequiresPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION)
-                    public void test1() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * Requires {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
-                     */
-                    @androidx.annotation.RequiresPermission(allOf=android.Manifest.permission.ACCESS_COARSE_LOCATION)
-                    public void test2() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * Requires {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} or {@link android.Manifest.permission#ACCESS_FINE_LOCATION}
-                     */
-                    @androidx.annotation.RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION})
-                    public void test3() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * Requires {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} and {@link android.Manifest.permission#ACCOUNT_MANAGER}
-                     */
-                    @androidx.annotation.RequiresPermission(allOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCOUNT_MANAGER})
-                    public void test4() { throw new RuntimeException("Stub!"); }
-                    @androidx.annotation.RequiresPermission(value=android.Manifest.permission.WATCH_APPOPS, conditional=true)
-                    public void test5() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * Requires {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} or {@link android.telephony.TelephonyManager#hasCarrierPrivileges carrier privileges}
-                     */
-                    @androidx.annotation.RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, "carrier privileges"})
-                    public void test6() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * Requires {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} or "carier priviliges"
-                     */
-                    @androidx.annotation.RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, "carier priviliges"})
-                    public void test6() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                import android.Manifest;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class PermissionTest {
+                public PermissionTest() { throw new RuntimeException("Stub!"); }
+                /**
+                 * Requires {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
+                 */
+                @androidx.annotation.RequiresPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION)
+                public void test1() { throw new RuntimeException("Stub!"); }
+                /**
+                 * Requires {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
+                 */
+                @androidx.annotation.RequiresPermission(allOf=android.Manifest.permission.ACCESS_COARSE_LOCATION)
+                public void test2() { throw new RuntimeException("Stub!"); }
+                /**
+                 * Requires {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} or {@link android.Manifest.permission#ACCESS_FINE_LOCATION}
+                 */
+                @androidx.annotation.RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION})
+                public void test3() { throw new RuntimeException("Stub!"); }
+                /**
+                 * Requires {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} and {@link android.Manifest.permission#ACCOUNT_MANAGER}
+                 */
+                @androidx.annotation.RequiresPermission(allOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCOUNT_MANAGER})
+                public void test4() { throw new RuntimeException("Stub!"); }
+                @androidx.annotation.RequiresPermission(value=android.Manifest.permission.WATCH_APPOPS, conditional=true)
+                public void test5() { throw new RuntimeException("Stub!"); }
+                /**
+                 * Requires {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} or {@link android.telephony.TelephonyManager#hasCarrierPrivileges carrier privileges}
+                 */
+                @androidx.annotation.RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, "carrier privileges"})
+                public void test6() { throw new RuntimeException("Stub!"); }
+                /**
+                 * Requires {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} or "carier priviliges"
+                 */
+                @androidx.annotation.RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, "carier priviliges"})
+                public void test6() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -297,18 +289,16 @@
                 requiresPermissionSource
             ),
             checkCompilation = false, // needs androidx.annotations in classpath
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class PermissionTest {
-                    public PermissionTest() { throw new RuntimeException("Stub!"); }
-                    @androidx.annotation.RequiresPermission(value=android.Manifest.permission.WATCH_APPOPS, conditional=true)
-                    public void test1() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class PermissionTest {
+                public PermissionTest() { throw new RuntimeException("Stub!"); }
+                @androidx.annotation.RequiresPermission(value=android.Manifest.permission.WATCH_APPOPS, conditional=true)
+                public void test1() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -339,32 +329,30 @@
             ),
             docStubs = true,
             checkCompilation = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class RangeTest {
-                    public RangeTest() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * @param range2 Value is 20 or greater
-                     * @return Value is 10 or greater
-                     */
-                    @androidx.annotation.IntRange(from=10)
-                    public int test1(@androidx.annotation.IntRange(from=20) int range2) { throw new RuntimeException("Stub!"); }
-                    /**
-                     * @return Value is between 10 and 20 inclusive
-                     */
-                    @androidx.annotation.IntRange(from=10, to=20)
-                    public int test2() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * @return Value is 100 or less
-                     */
-                    @androidx.annotation.IntRange(to=100)
-                    public int test3() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class RangeTest {
+                public RangeTest() { throw new RuntimeException("Stub!"); }
+                /**
+                 * @param range2 Value is 20 or greater
+                 * @return Value is 10 or greater
+                 */
+                @androidx.annotation.IntRange(from=10)
+                public int test1(@androidx.annotation.IntRange(from=20) int range2) { throw new RuntimeException("Stub!"); }
+                /**
+                 * @return Value is between 10 and 20 inclusive
+                 */
+                @androidx.annotation.IntRange(from=10, to=20)
+                public int test2() { throw new RuntimeException("Stub!"); }
+                /**
+                 * @return Value is 100 or less
+                 */
+                @androidx.annotation.IntRange(to=100)
+                public int test3() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -390,28 +378,26 @@
             ),
             checkCompilation = true,
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    /**
-                     * Methods in this class must be called on the thread that originally created
-                     * this UI element, unless otherwise noted. This is typically the
-                     * main thread of your app. *
-                     */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    @androidx.annotation.UiThread
-                    public class RangeTest {
-                    public RangeTest() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * This method may take several seconds to complete, so it should
-                     * only be called from a worker thread.
-                     */
-                    @androidx.annotation.WorkerThread
-                    public int test1() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                /**
+                 * Methods in this class must be called on the thread that originally created
+                 * this UI element, unless otherwise noted. This is typically the
+                 * main thread of your app. *
+                 */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                @androidx.annotation.UiThread
+                public class RangeTest {
+                public RangeTest() { throw new RuntimeException("Stub!"); }
+                /**
+                 * This method may take several seconds to complete, so it should
+                 * only be called from a worker thread.
+                 */
+                @androidx.annotation.WorkerThread
+                public int test1() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -437,26 +423,24 @@
             checkCompilation = true,
             expectedIssues = "src/test/pkg/RangeTest.java:5: lint: Found more than one threading annotation on method test.pkg.RangeTest.test1(); the auto-doc feature does not handle this correctly [MultipleThreadAnnotations]",
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class RangeTest {
-                    public RangeTest() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * This method must be called on the thread that originally created
-                     * this UI element. This is typically the main thread of your app.
-                     * <br>
-                     * This method may take several seconds to complete, so it should
-                     * only be called from a worker thread.
-                     */
-                    @androidx.annotation.UiThread
-                    @androidx.annotation.WorkerThread
-                    public int test1() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class RangeTest {
+                public RangeTest() { throw new RuntimeException("Stub!"); }
+                /**
+                 * This method must be called on the thread that originally created
+                 * this UI element. This is typically the main thread of your app.
+                 * <br>
+                 * This method may take several seconds to complete, so it should
+                 * only be called from a worker thread.
+                 */
+                @androidx.annotation.UiThread
+                @androidx.annotation.WorkerThread
+                public int test1() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -509,35 +493,33 @@
                         </class>
                     </api>
                     """,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package android.widget;
-                    /** @apiSince 21 */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Toolbar2 {
-                    public Toolbar2() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * Existing documentation for {@linkplain #getCurrentContentInsetEnd()} here.
-                     * <br>
-                     * This method must be called on the thread that originally created
-                     * this UI element. This is typically the main thread of your app.
-                     * @return blah blah blah
-                     * @apiSince 24
-                     */
-                    @androidx.annotation.UiThread
-                    public int getCurrentContentInsetEnd() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * <br>
-                     * This method must be called on the thread that originally created
-                     * this UI element. This is typically the main thread of your app.
-                     * @apiSince 15
-                     */
-                    @androidx.annotation.UiThread
-                    public int getCurrentContentInsetRight() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package android.widget;
+                /** @apiSince 21 */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Toolbar2 {
+                public Toolbar2() { throw new RuntimeException("Stub!"); }
+                /**
+                 * Existing documentation for {@linkplain #getCurrentContentInsetEnd()} here.
+                 * <br>
+                 * This method must be called on the thread that originally created
+                 * this UI element. This is typically the main thread of your app.
+                 * @return blah blah blah
+                 * @apiSince 24
+                 */
+                @androidx.annotation.UiThread
+                public int getCurrentContentInsetEnd() { throw new RuntimeException("Stub!"); }
+                /**
+                 * <br>
+                 * This method must be called on the thread that originally created
+                 * this UI element. This is typically the main thread of your app.
+                 * @apiSince 15
+                 */
+                @androidx.annotation.UiThread
+                public int getCurrentContentInsetRight() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -586,29 +568,27 @@
             ),
             checkCompilation = true,
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class TypedefTest {
-                    public TypedefTest() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * @param style Value is {@link test.pkg.TypedefTest#STYLE_NORMAL}, {@link test.pkg.TypedefTest#STYLE_NO_TITLE}, {@link test.pkg.TypedefTest#STYLE_NO_FRAME}, or {@link test.pkg.TypedefTest#STYLE_NO_INPUT}
-                     */
-                    public void setStyle(int style, int theme) { throw new RuntimeException("Stub!"); }
-                    /**
-                     * @param flags Value is either <code>0</code> or a combination of {@link test.pkg.TypedefTest#STYLE_NORMAL}, {@link test.pkg.TypedefTest#STYLE_NO_TITLE}, {@link test.pkg.TypedefTest#STYLE_NO_FRAME}, {@link test.pkg.TypedefTest#STYLE_NO_INPUT}, 2, and 3 + 1
-                     */
-                    public void setFlags(java.lang.Object first, int flags) { throw new RuntimeException("Stub!"); }
-                    public static final int STYLE_NORMAL = 0; // 0x0
-                    public static final int STYLE_NO_FRAME = 2; // 0x2
-                    public static final int STYLE_NO_INPUT = 3; // 0x3
-                    public static final int STYLE_NO_TITLE = 1; // 0x1
-                    public static final int STYLE_UNRELATED = 3; // 0x3
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class TypedefTest {
+                public TypedefTest() { throw new RuntimeException("Stub!"); }
+                /**
+                 * @param style Value is {@link test.pkg.TypedefTest#STYLE_NORMAL}, {@link test.pkg.TypedefTest#STYLE_NO_TITLE}, {@link test.pkg.TypedefTest#STYLE_NO_FRAME}, or {@link test.pkg.TypedefTest#STYLE_NO_INPUT}
+                 */
+                public void setStyle(int style, int theme) { throw new RuntimeException("Stub!"); }
+                /**
+                 * @param flags Value is either <code>0</code> or a combination of {@link test.pkg.TypedefTest#STYLE_NORMAL}, {@link test.pkg.TypedefTest#STYLE_NO_TITLE}, {@link test.pkg.TypedefTest#STYLE_NO_FRAME}, {@link test.pkg.TypedefTest#STYLE_NO_INPUT}, 2, and 3 + 1
+                 */
+                public void setFlags(java.lang.Object first, int flags) { throw new RuntimeException("Stub!"); }
+                public static final int STYLE_NORMAL = 0; // 0x0
+                public static final int STYLE_NO_FRAME = 2; // 0x2
+                public static final int STYLE_NO_INPUT = 3; // 0x3
+                public static final int STYLE_NO_TITLE = 1; // 0x1
+                public static final int STYLE_UNRELATED = 3; // 0x3
+                }
+                """
             )
         )
     }
@@ -648,24 +628,22 @@
             ),
             docStubs = true,
             checkCompilation = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class TypedefTest {
-                    public TypedefTest() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * @param style Value is {@link test.pkg.TypedefTest#STYLE_NORMAL}, {@link test.pkg.TypedefTest#STYLE_NO_TITLE}, {@link test.pkg.TypedefTest#STYLE_NO_FRAME}, or STYLE_NO_INPUT
-                     * Value is 20 or greater
-                     */
-                    public void setStyle(int style, int theme) { throw new RuntimeException("Stub!"); }
-                    public static final int STYLE_NORMAL = 0; // 0x0
-                    public static final int STYLE_NO_FRAME = 2; // 0x2
-                    public static final int STYLE_NO_TITLE = 1; // 0x1
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class TypedefTest {
+                public TypedefTest() { throw new RuntimeException("Stub!"); }
+                /**
+                 * @param style Value is {@link test.pkg.TypedefTest#STYLE_NORMAL}, {@link test.pkg.TypedefTest#STYLE_NO_TITLE}, {@link test.pkg.TypedefTest#STYLE_NO_FRAME}, or STYLE_NO_INPUT
+                 * Value is 20 or greater
+                 */
+                public void setStyle(int style, int theme) { throw new RuntimeException("Stub!"); }
+                public static final int STYLE_NORMAL = 0; // 0x0
+                public static final int STYLE_NO_FRAME = 2; // 0x2
+                public static final int STYLE_NO_TITLE = 1; // 0x1
+                }
+                """
             )
         )
     }
@@ -691,22 +669,20 @@
             ),
             checkCompilation = true,
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class RangeTest {
-                    public RangeTest() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * Requires {@link test.pkg.RangeTest#ACCESS_COARSE_LOCATION}
-                     */
-                    @androidx.annotation.RequiresPermission(test.pkg.RangeTest.ACCESS_COARSE_LOCATION)
-                    public void test1() { throw new RuntimeException("Stub!"); }
-                    public static final java.lang.String ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION";
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class RangeTest {
+                public RangeTest() { throw new RuntimeException("Stub!"); }
+                /**
+                 * Requires {@link test.pkg.RangeTest#ACCESS_COARSE_LOCATION}
+                 */
+                @androidx.annotation.RequiresPermission(test.pkg.RangeTest.ACCESS_COARSE_LOCATION)
+                public void test1() { throw new RuntimeException("Stub!"); }
+                public static final java.lang.String ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION";
+                }
+                """
             )
         )
     }
@@ -731,21 +707,19 @@
             checkCompilation = true,
             docStubs = true,
             expectedIssues = "src/test/pkg/RangeTest.java:4: lint: Cannot find permission field for \"MyPermission\" required by method test.pkg.RangeTest.test1() (may be hidden or removed) [MissingPermission]",
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class RangeTest {
-                    public RangeTest() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * Requires "MyPermission"
-                     */
-                    @androidx.annotation.RequiresPermission("MyPermission")
-                    public void test1() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class RangeTest {
+                public RangeTest() { throw new RuntimeException("Stub!"); }
+                /**
+                 * Requires "MyPermission"
+                 */
+                @androidx.annotation.RequiresPermission("MyPermission")
+                public void test1() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -771,24 +745,22 @@
             ),
             checkCompilation = true,
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class RangeTest {
-                    public RangeTest() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * This is the existing documentation.
-                     * <br>
-                     * Requires {@link test.pkg.RangeTest#ACCESS_COARSE_LOCATION}
-                     */
-                    @androidx.annotation.RequiresPermission(test.pkg.RangeTest.ACCESS_COARSE_LOCATION)
-                    public int test1() { throw new RuntimeException("Stub!"); }
-                    public static final java.lang.String ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION";
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class RangeTest {
+                public RangeTest() { throw new RuntimeException("Stub!"); }
+                /**
+                 * This is the existing documentation.
+                 * <br>
+                 * Requires {@link test.pkg.RangeTest#ACCESS_COARSE_LOCATION}
+                 */
+                @androidx.annotation.RequiresPermission(test.pkg.RangeTest.ACCESS_COARSE_LOCATION)
+                public int test1() { throw new RuntimeException("Stub!"); }
+                public static final java.lang.String ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION";
+                }
+                """
             )
         )
     }
@@ -817,25 +789,23 @@
             ),
             checkCompilation = true,
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class RangeTest {
-                    public RangeTest() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * This is the existing documentation.
-                     * Multiple lines of it.
-                     * <br>
-                     * Requires {@link test.pkg.RangeTest#ACCESS_COARSE_LOCATION}
-                     */
-                    @androidx.annotation.RequiresPermission(test.pkg.RangeTest.ACCESS_COARSE_LOCATION)
-                    public int test1() { throw new RuntimeException("Stub!"); }
-                    public static final java.lang.String ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION";
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class RangeTest {
+                public RangeTest() { throw new RuntimeException("Stub!"); }
+                /**
+                 * This is the existing documentation.
+                 * Multiple lines of it.
+                 * <br>
+                 * Requires {@link test.pkg.RangeTest#ACCESS_COARSE_LOCATION}
+                 */
+                @androidx.annotation.RequiresPermission(test.pkg.RangeTest.ACCESS_COARSE_LOCATION)
+                public int test1() { throw new RuntimeException("Stub!"); }
+                public static final java.lang.String ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION";
+                }
+                """
             )
         )
     }
@@ -857,20 +827,18 @@
             ),
             checkCompilation = true,
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class RangeTest {
-                    public RangeTest() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * @param parameter2 Value is 10 or greater
-                     */
-                    public int test1(int parameter1, @androidx.annotation.IntRange(from=10) int parameter2, int parameter3) { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class RangeTest {
+                public RangeTest() { throw new RuntimeException("Stub!"); }
+                /**
+                 * @param parameter2 Value is 10 or greater
+                 */
+                public int test1(int parameter1, @androidx.annotation.IntRange(from=10) int parameter2, int parameter3) { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -902,28 +870,26 @@
             ),
             docStubs = true,
             checkCompilation = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class RangeTest {
-                    public RangeTest() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * This is the existing documentation.
-                     * <br>
-                     * Requires {@link test.pkg.RangeTest#ACCESS_COARSE_LOCATION}
-                     * @param parameter1 docs for parameter1
-                     * @param parameter2 docs for parameter2
-                     * @param parameter3 docs for parameter2
-                     * @return return value documented here
-                     */
-                    @androidx.annotation.RequiresPermission(test.pkg.RangeTest.ACCESS_COARSE_LOCATION)
-                    public int test1(int parameter1, int parameter2, int parameter3) { throw new RuntimeException("Stub!"); }
-                    public static final java.lang.String ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION";
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class RangeTest {
+                public RangeTest() { throw new RuntimeException("Stub!"); }
+                /**
+                 * This is the existing documentation.
+                 * <br>
+                 * Requires {@link test.pkg.RangeTest#ACCESS_COARSE_LOCATION}
+                 * @param parameter1 docs for parameter1
+                 * @param parameter2 docs for parameter2
+                 * @param parameter3 docs for parameter2
+                 * @return return value documented here
+                 */
+                @androidx.annotation.RequiresPermission(test.pkg.RangeTest.ACCESS_COARSE_LOCATION)
+                public int test1(int parameter1, int parameter2, int parameter3) { throw new RuntimeException("Stub!"); }
+                public static final java.lang.String ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION";
+                }
+                """
             )
         )
     }
@@ -949,22 +915,20 @@
             ),
             checkCompilation = true,
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class RangeTest {
-                    public RangeTest() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * This is the existing documentation.
-                     * @param parameter2 Value is 10 or greater
-                     * @return return value documented here
-                     */
-                    public int test1(int parameter1, @androidx.annotation.IntRange(from=10) int parameter2, int parameter3) { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class RangeTest {
+                public RangeTest() { throw new RuntimeException("Stub!"); }
+                /**
+                 * This is the existing documentation.
+                 * @param parameter2 Value is 10 or greater
+                 * @return return value documented here
+                 */
+                public int test1(int parameter1, @androidx.annotation.IntRange(from=10) int parameter2, int parameter3) { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -992,24 +956,22 @@
             ),
             checkCompilation = true,
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class RangeTest {
-                    public RangeTest() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * This is the existing documentation.
-                     * @param parameter1 docs for parameter1
-                     * @param parameter3 docs for parameter2
-                     * @param parameter2 Value is 10 or greater
-                     * @return return value documented here
-                     */
-                    public int test1(int parameter1, @androidx.annotation.IntRange(from=10) int parameter2, int parameter3) { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class RangeTest {
+                public RangeTest() { throw new RuntimeException("Stub!"); }
+                /**
+                 * This is the existing documentation.
+                 * @param parameter1 docs for parameter1
+                 * @param parameter3 docs for parameter2
+                 * @param parameter2 Value is 10 or greater
+                 * @return return value documented here
+                 */
+                public int test1(int parameter1, @androidx.annotation.IntRange(from=10) int parameter2, int parameter3) { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -1038,25 +1000,23 @@
             ),
             checkCompilation = true,
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class RangeTest {
-                    public RangeTest() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * This is the existing documentation.
-                     * @param parameter1 docs for parameter1
-                     * @param parameter2 docs for parameter2
-                     * Value is 10 or greater
-                     * @param parameter3 docs for parameter2
-                     * @return return value documented here
-                     */
-                    public int test1(int parameter1, @androidx.annotation.IntRange(from=10) int parameter2, int parameter3) { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class RangeTest {
+                public RangeTest() { throw new RuntimeException("Stub!"); }
+                /**
+                 * This is the existing documentation.
+                 * @param parameter1 docs for parameter1
+                 * @param parameter2 docs for parameter2
+                 * Value is 10 or greater
+                 * @param parameter3 docs for parameter2
+                 * @return return value documented here
+                 */
+                public int test1(int parameter1, @androidx.annotation.IntRange(from=10) int parameter2, int parameter3) { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -1079,21 +1039,19 @@
             ),
             checkCompilation = true,
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class RangeTest {
-                    public RangeTest() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * @return Value is 10 or greater
-                     */
-                    @androidx.annotation.IntRange(from=10)
-                    public int test1(int parameter1, int parameter2, int parameter3) { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class RangeTest {
+                public RangeTest() { throw new RuntimeException("Stub!"); }
+                /**
+                 * @return Value is 10 or greater
+                 */
+                @androidx.annotation.IntRange(from=10)
+                public int test1(int parameter1, int parameter2, int parameter3) { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -1120,23 +1078,21 @@
             ),
             checkCompilation = true,
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class RangeTest {
-                    public RangeTest() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * This is the existing documentation.
-                     * @return return value documented here
-                     * Value is 10 or greater
-                     */
-                    @androidx.annotation.IntRange(from=10)
-                    public int test1(int parameter1, int parameter2, int parameter3) { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class RangeTest {
+                public RangeTest() { throw new RuntimeException("Stub!"); }
+                /**
+                 * This is the existing documentation.
+                 * @return return value documented here
+                 * Value is 10 or greater
+                 */
+                @androidx.annotation.IntRange(from=10)
+                public int test1(int parameter1, int parameter2, int parameter3) { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -1192,23 +1148,21 @@
                         </class>
                     </api>
                     """,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package android.widget;
-                    /** @apiSince 21 */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Toolbar {
-                    public Toolbar() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * Existing documentation for {@linkplain #getCurrentContentInsetEnd()} here.
-                     * @return blah blah blah
-                     * @apiSince 24
-                     */
-                    public int getCurrentContentInsetEnd() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package android.widget;
+                /** @apiSince 21 */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Toolbar {
+                public Toolbar() { throw new RuntimeException("Stub!"); }
+                /**
+                 * Existing documentation for {@linkplain #getCurrentContentInsetEnd()} here.
+                 * @return blah blah blah
+                 * @apiSince 24
+                 */
+                public int getCurrentContentInsetEnd() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -1247,31 +1201,29 @@
                     """,
             checkCompilation = true,
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package android.hardware;
-                    /**
-                     * The Camera class is used to set image capture settings, start/stop preview.
-                     *
-                     * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
-                     *             applications.*
-                     * @apiSince 1
-                     * @deprecatedSince 21
-                     */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    @Deprecated
-                    public class Camera {
-                    public Camera() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * @deprecated Use something else.
-                     * @apiSince 14
-                     * @deprecatedSince 19
-                     */
-                    @Deprecated public static final java.lang.String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO";
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package android.hardware;
+                /**
+                 * The Camera class is used to set image capture settings, start/stop preview.
+                 *
+                 * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+                 *             applications.*
+                 * @apiSince 1
+                 * @deprecatedSince 21
+                 */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                @Deprecated
+                public class Camera {
+                public Camera() { throw new RuntimeException("Stub!"); }
+                /**
+                 * @deprecated Use something else.
+                 * @apiSince 14
+                 * @deprecatedSince 19
+                 */
+                @Deprecated public static final java.lang.String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO";
+                }
+                """
             )
         )
     }
@@ -1314,23 +1266,21 @@
                     """,
             checkCompilation = true,
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package android.pkg;
-                    /** @apiSince 1 */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Test {
-                    public Test() { throw new RuntimeException("Stub!"); }
-                    /** @apiSince 35 */
-                    public static final java.lang.String UNIT_TEST_1 = "unit.test.1";
-                    /**
-                     * @hide
-                     */
-                    public static final java.lang.String UNIT_TEST_2 = "unit.test.2";
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package android.pkg;
+                /** @apiSince 1 */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Test {
+                public Test() { throw new RuntimeException("Stub!"); }
+                /** @apiSince 35 */
+                public static final java.lang.String UNIT_TEST_1 = "unit.test.1";
+                /**
+                 * @hide
+                 */
+                public static final java.lang.String UNIT_TEST_2 = "unit.test.2";
+                }
+                """
             )
         )
     }
@@ -1370,22 +1320,20 @@
                     """,
             checkCompilation = true,
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package android.pkg;
-                    /** @apiSince 1 */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Test {
-                    /** @apiSince 1 */
-                    public Test(int i) { throw new RuntimeException("Stub!"); }
-                    /** @apiSince 35 */
-                    public static final java.lang.String UNIT_TEST_1 = "unit.test.1";
-                    /** @apiSince Z */
-                    public static final java.lang.String UNIT_TEST_2 = "unit.test.2";
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package android.pkg;
+                /** @apiSince 1 */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Test {
+                /** @apiSince 1 */
+                public Test(int i) { throw new RuntimeException("Stub!"); }
+                /** @apiSince 35 */
+                public static final java.lang.String UNIT_TEST_1 = "unit.test.1";
+                /** @apiSince Z */
+                public static final java.lang.String UNIT_TEST_2 = "unit.test.2";
+                }
+                """
             )
         )
     }
@@ -1458,39 +1406,34 @@
                     """,
             checkCompilation = true,
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package android.pkg1;
-                    /** @apiSince 15 */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Test1 {
-                    public Test1() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    /** @apiSince 15 */
-                    package android.pkg1;
-                    """
-                ),
-                java(
-                    """
-                    /**
-                     * Some existing doc here.
-                     * @deprecated
-                     * <!-- comment -->
-                     */
-                    package android.pkg2;
-                    """
-                ),
-                java(
-                    """
-                    /** @apiSince 20 */
-                    package android.pkg3;
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package android.pkg1;
+                /** @apiSince 15 */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Test1 {
+                public Test1() { throw new RuntimeException("Stub!"); }
+                }
+                """,
+                """
+                [android/pkg1/package-info.java]
+                /** @apiSince 15 */
+                package android.pkg1;
+                """,
+                """
+                [android/pkg2/package-info.java]
+                /**
+                 * Some existing doc here.
+                 * @deprecated
+                 * <!-- comment -->
+                 */
+                package android.pkg2;
+                """,
+                """
+                [android/pkg3/package-info.java]
+                /** @apiSince 20 */
+                package android.pkg3;
+                """
             ),
             docStubsSourceList = """
                 TESTROOT/stubs/android/pkg1/package-info.java
@@ -1597,29 +1540,29 @@
             // Make sure the stubs are generated correctly; in particular, that we've
             // pulled docs from overview.html into javadoc on package-info.java instead
             // (removing all the content surrounding <body>, etc)
-            stubFiles = arrayOf(
-                source("overview.html", "<html>My overview docs</html>"),
-                java(
-                    """
-                    /**
-                     * My package docs<br>
-                     * <!-- comment -->
-                     * Sample code: /** code here &#42;/
-                     * Another line.<br>
-                     */
-                    package test.visible;
-                    """
-                ),
-                java(
-                    """
-                    package test.visible;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class MyClass {
-                    public MyClass() { throw new RuntimeException("Stub!"); }
-                    public void test() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                <html>My overview docs</html>
+                """,
+                """
+                [test/visible/package-info.java]
+                /**
+                 * My package docs<br>
+                 * <!-- comment -->
+                 * Sample code: /** code here &#42;/
+                 * Another line.<br>
+                 */
+                package test.visible;
+                """,
+                """
+                [test/visible/MyClass.java]
+                package test.visible;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class MyClass {
+                public MyClass() { throw new RuntimeException("Stub!"); }
+                public void test() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -1653,20 +1596,18 @@
             ),
             checkCompilation = true,
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    import android.content.pm.PackageManager;
-                    /**
-                     * Requires the {@link android.content.pm.PackageManager#FEATURE_LOCATION PackageManager#FEATURE_LOCATION} feature which can be detected using {@link android.content.pm.PackageManager#hasSystemFeature(String) PackageManager.hasSystemFeature(String)}.
-                     */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class LocationManager {
-                    public LocationManager() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                import android.content.pm.PackageManager;
+                /**
+                 * Requires the {@link android.content.pm.PackageManager#FEATURE_LOCATION PackageManager#FEATURE_LOCATION} feature which can be detected using {@link android.content.pm.PackageManager#hasSystemFeature(String) PackageManager.hasSystemFeature(String)}.
+                 */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class LocationManager {
+                public LocationManager() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -1689,18 +1630,16 @@
             ),
             docStubs = true,
             checkCompilation = false, // duplicate class: androidx.annotation.RequiresApi
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    /** @apiSince 21 */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    @androidx.annotation.RequiresApi(21)
-                    public class MyClass1 {
-                    public MyClass1() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                /** @apiSince 21 */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                @androidx.annotation.RequiresApi(21)
+                public class MyClass1 {
+                public MyClass1() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -1734,36 +1673,33 @@
             ),
             checkCompilation = true,
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    /**
-                     * @deprecated Use Jetpack preference library
-                     */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    @Deprecated
-                    public final class Foo {
-                    @Deprecated
-                    public Foo() { throw new RuntimeException("Stub!"); }
-                    public void foo() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * {@inheritDoc}
-                     * @deprecated Blah blah blah 1
-                     */
-                    @Deprecated
-                    @androidx.annotation.NonNull
-                    public java.lang.String toString() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * My description
-                     * @deprecated Existing deprecation message.
-                     * Blah blah blah 2
-                     */
-                    @Deprecated
-                    public int hashCode() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                /**
+                 * @deprecated Use Jetpack preference library
+                 */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                @Deprecated
+                public final class Foo {
+                public Foo() { throw new RuntimeException("Stub!"); }
+                public void foo() { throw new RuntimeException("Stub!"); }
+                /**
+                 * {@inheritDoc}
+                 * @deprecated Blah blah blah 1
+                 */
+                @Deprecated
+                @androidx.annotation.NonNull
+                public java.lang.String toString() { throw new RuntimeException("Stub!"); }
+                /**
+                 * My description
+                 * @deprecated Existing deprecation message.
+                 * Blah blah blah 2
+                 */
+                @Deprecated
+                public int hashCode() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -1802,31 +1738,27 @@
                 )
             ),
             checkCompilation = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    /**
-                     * Documentation here
-                     */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
-                    public @interface MyAnnotation {
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    /**
-                     * Other documentation here
-                     */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class OtherClass {
-                    public OtherClass() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                /**
+                 * Documentation here
+                 */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
+                public @interface MyAnnotation {
+                }
+                """,
+                """
+                package test.pkg;
+                /**
+                 * Other documentation here
+                 */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class OtherClass {
+                public OtherClass() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -1875,8 +1807,7 @@
             checkCompilation = true,
             expectedIssues = null, // be unopinionated about whether there should be warnings
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
+            stubs = arrayOf(
                     """
                     package javax.security;
                     /**
@@ -1900,9 +1831,7 @@
                     public class Example {
                     public Example() { throw new RuntimeException("Stub!"); }
                     }
-                    """
-                ),
-                java(
+                    """,
                     """
                     package not.part.of.ojluni;
                     /**
@@ -1915,7 +1844,6 @@
                     public TestCollection() { throw new RuntimeException("Stub!"); }
                     }
                     """
-                )
             ),
             extraArguments = arrayOf(
                 ARG_REPLACE_DOCUMENTATION,
@@ -1958,31 +1886,27 @@
                 )
             ),
             checkCompilation = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    /**
-                     * Documentation 1 here
-                     */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    @test.pkg.MyAnnotation2
-                    public @interface MyAnnotation1 {
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    /**
-                     * Documentation 2 here
-                     */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    @test.pkg.MyAnnotation1
-                    public @interface MyAnnotation2 {
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                /**
+                 * Documentation 1 here
+                 */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                @test.pkg.MyAnnotation2
+                public @interface MyAnnotation1 {
+                }
+                """,
+                """
+                package test.pkg;
+                /**
+                 * Documentation 2 here
+                 */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                @test.pkg.MyAnnotation1
+                public @interface MyAnnotation2 {
+                }
+                """
             )
         )
     }
@@ -2012,7 +1936,7 @@
             return
         }
 
-        val dir = Files.createTempDirectory(null).toFile()
+        val dir = Files.createTempDir()
         val html = "$dir/javadoc"
         val sourceList = "$dir/sources.txt"
 
@@ -2059,20 +1983,18 @@
             ),
             checkCompilation = true,
 
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    import android.content.pm.PackageManager;
-                    /**
-                     * Requires the {@link android.content.pm.PackageManager#FEATURE_LOCATION PackageManager#FEATURE_LOCATION} feature which can be detected using {@link android.content.pm.PackageManager#hasSystemFeature(String) PackageManager.hasSystemFeature(String)}.
-                     */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class LocationManager {
-                    public LocationManager() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                import android.content.pm.PackageManager;
+                /**
+                 * Requires the {@link android.content.pm.PackageManager#FEATURE_LOCATION PackageManager#FEATURE_LOCATION} feature which can be detected using {@link android.content.pm.PackageManager#hasSystemFeature(String) PackageManager.hasSystemFeature(String)}.
+                 */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class LocationManager {
+                public LocationManager() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
 
@@ -2137,33 +2059,31 @@
                 src/test/pkg/ColumnTest.java:12: warning: Cannot find feature field for Cursor.NONEXISTENT required by field ColumnTest.BOGUS (may be hidden or removed) [MissingColumn]
                 """,
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    import android.database.Cursor;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class ColumnTest {
-                    public ColumnTest() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * This constant represents a column name that can be used with a {@link android.content.ContentProvider} through a {@link android.content.ContentValues} or {@link android.database.Cursor} object. The values stored in this column are {@link Cursor.NONEXISTENT}, and are read-only and cannot be mutated.
-                     */
-                    @android.provider.Column(value=Cursor.NONEXISTENT, readOnly=true) public static final java.lang.String BOGUS = "bogus";
-                    /**
-                     * This constant represents a column name that can be used with a {@link android.content.ContentProvider} through a {@link android.content.ContentValues} or {@link android.database.Cursor} object. The values stored in this column are {@link android.database.Cursor#FIELD_TYPE_STRING Cursor#FIELD_TYPE_STRING} .
-                     */
-                    @android.provider.Column(android.database.Cursor.FIELD_TYPE_STRING) public static final java.lang.String DATA = "_data";
-                    /**
-                     * This constant represents a column name that can be used with a {@link android.content.ContentProvider} through a {@link android.content.ContentValues} or {@link android.database.Cursor} object. The values stored in this column are {@link android.database.Cursor#FIELD_TYPE_BLOB Cursor#FIELD_TYPE_BLOB} , and are read-only and cannot be mutated.
-                     */
-                    @android.provider.Column(value=android.database.Cursor.FIELD_TYPE_BLOB, readOnly=true) public static final java.lang.String HASH = "_hash";
-                    /**
-                     * This constant represents a column name that can be used with a {@link android.content.ContentProvider} through a {@link android.content.ContentValues} or {@link android.database.Cursor} object. The values stored in this column are {@link android.database.Cursor#FIELD_TYPE_STRING Cursor#FIELD_TYPE_STRING} , and are read-only and cannot be mutated.
-                     */
-                    @android.provider.Column(value=android.database.Cursor.FIELD_TYPE_STRING, readOnly=true) public static final java.lang.String TITLE = "title";
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                import android.database.Cursor;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class ColumnTest {
+                public ColumnTest() { throw new RuntimeException("Stub!"); }
+                /**
+                 * This constant represents a column name that can be used with a {@link android.content.ContentProvider} through a {@link android.content.ContentValues} or {@link android.database.Cursor} object. The values stored in this column are {@link Cursor.NONEXISTENT}, and are read-only and cannot be mutated.
+                 */
+                @android.provider.Column(value=Cursor.NONEXISTENT, readOnly=true) public static final java.lang.String BOGUS = "bogus";
+                /**
+                 * This constant represents a column name that can be used with a {@link android.content.ContentProvider} through a {@link android.content.ContentValues} or {@link android.database.Cursor} object. The values stored in this column are {@link android.database.Cursor#FIELD_TYPE_STRING Cursor#FIELD_TYPE_STRING} .
+                 */
+                @android.provider.Column(android.database.Cursor.FIELD_TYPE_STRING) public static final java.lang.String DATA = "_data";
+                /**
+                 * This constant represents a column name that can be used with a {@link android.content.ContentProvider} through a {@link android.content.ContentValues} or {@link android.database.Cursor} object. The values stored in this column are {@link android.database.Cursor#FIELD_TYPE_BLOB Cursor#FIELD_TYPE_BLOB} , and are read-only and cannot be mutated.
+                 */
+                @android.provider.Column(value=android.database.Cursor.FIELD_TYPE_BLOB, readOnly=true) public static final java.lang.String HASH = "_hash";
+                /**
+                 * This constant represents a column name that can be used with a {@link android.content.ContentProvider} through a {@link android.content.ContentValues} or {@link android.database.Cursor} object. The values stored in this column are {@link android.database.Cursor#FIELD_TYPE_STRING Cursor#FIELD_TYPE_STRING} , and are read-only and cannot be mutated.
+                 */
+                @android.provider.Column(value=android.database.Cursor.FIELD_TYPE_STRING, readOnly=true) public static final java.lang.String TITLE = "title";
+                }
+                """
             )
         )
     }
@@ -2197,78 +2117,20 @@
                         </class>
                     </api>
                     """,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package android.widget;
-                    /** @apiSince 21 */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Toolbar {
-                    public Toolbar() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * Existing documentation for {@linkplain #getCurrentContentInsetEnd()} here.
-                     * @apiSince 24
-                     */
-                    public int getCurrentContentInsetEnd() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
-            )
-        )
-    }
-
-    @Test
-    fun `memberDoc crash`() {
-        check(
-            sourceFiles = arrayOf(
-                java("""
-                    package test.pkg;
-                    import java.lang.annotation.ElementType;
-                    import java.lang.annotation.Retention;
-                    import java.lang.annotation.RetentionPolicy;
-                    import java.lang.annotation.Target;
-                    /**
-                     * More text here
-                     * @memberDoc Important {@link another.pkg.Bar#BAR}
-                     * and here
-                     */
-                    @Target({ ElementType.FIELD })
-                    @Retention(RetentionPolicy.SOURCE)
-                    public @interface Foo { }
-                """),
-                java("""
-                    package another.pkg;
-                    public class Bar {
-                        public String BAR = "BAAAAR";
-                    }
-                """),
-                java("""
-                    package yetonemore.pkg;
-                    public class Fun {
-                        /**
-                         * Separate comment
-                         */
-                        @test.pkg.Foo
-                        public static final String FUN = "FUN";
-                    }
-                """)
-            ),
-            docStubs = true,
-            stubFiles = arrayOf(
-                java("""
-                    package yetonemore.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Fun {
-                    public Fun() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * Separate comment
-                     * <br>
-                     * Important {@link another.pkg.Bar#BAR}
-                     * and here
-                     */
-                    public static final java.lang.String FUN = "FUN";
-                    }
-                """)
+            stubs = arrayOf(
+                """
+                package android.widget;
+                /** @apiSince 21 */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Toolbar {
+                public Toolbar() { throw new RuntimeException("Stub!"); }
+                /**
+                 * Existing documentation for {@linkplain #getCurrentContentInsetEnd()} here.
+                 * @apiSince 24
+                 */
+                public int getCurrentContentInsetEnd() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
diff --git a/src/test/java/com/android/tools/metalava/DriverTest.kt b/src/test/java/com/android/tools/metalava/DriverTest.kt
index 9f45870..5879445 100644
--- a/src/test/java/com/android/tools/metalava/DriverTest.kt
+++ b/src/test/java/com/android/tools/metalava/DriverTest.kt
@@ -17,6 +17,7 @@
 package com.android.tools.metalava
 
 import com.android.SdkConstants
+import com.android.SdkConstants.DOT_JAVA
 import com.android.SdkConstants.DOT_KT
 import com.android.ide.common.process.DefaultProcessExecutor
 import com.android.ide.common.process.LoggedProcessOutputHandler
@@ -26,16 +27,17 @@
 import com.android.tools.lint.UastEnvironment
 import com.android.tools.lint.checks.ApiLookup
 import com.android.tools.lint.checks.infrastructure.ClassName
+import com.android.tools.lint.checks.infrastructure.LintDetectorTest
 import com.android.tools.lint.checks.infrastructure.TestFile
 import com.android.tools.lint.checks.infrastructure.TestFiles
 import com.android.tools.lint.checks.infrastructure.TestFiles.java
 import com.android.tools.lint.checks.infrastructure.TestFiles.kotlin
 import com.android.tools.lint.checks.infrastructure.stripComments
 import com.android.tools.lint.client.api.LintClient
+import com.android.tools.metalava.model.text.ApiFile
 import com.android.tools.metalava.model.SUPPORT_TYPE_USE_ANNOTATIONS
 import com.android.tools.metalava.model.defaultConfiguration
 import com.android.tools.metalava.model.parseDocument
-import com.android.tools.metalava.model.text.ApiFile
 import com.android.utils.FileUtils
 import com.android.utils.SdkUtils
 import com.android.utils.StdLogger
@@ -63,6 +65,12 @@
 
 const val CHECK_JDIFF = false
 
+/**
+ * Marker class for stubs argument to [DriverTest.check] indicating that no
+ * stubs should be generated for a particular source file.
+ */
+const val NO_STUB = ""
+
 abstract class DriverTest {
     @get:Rule
     var temporaryFolder = TemporaryFolder()
@@ -118,26 +126,15 @@
                 if (cleanupString(expectedFail, null).replace(".", "").trim() !=
                     actualFail.replace(".", "").trim()
                 ) {
-                    val reportedCompatError = actualFail.startsWith("Aborting: Found compatibility problems checking the ")
                     if (expectedFail == "Aborting: Found compatibility problems with --check-compatibility" &&
-                        reportedCompatError
+                        actualFail.startsWith("Aborting: Found compatibility problems checking the ")
                     ) {
                         // Special case for compat checks; we don't want to force each one of them
                         // to pass in the right string (which may vary based on whether writing out
                         // the signature was passed at the same time
                         // ignore
                     } else {
-                        if (reportedCompatError) {
-                            // if a compatibility error was unexpectedly reported, then mark that as
-                            // an error but keep going so we can see the actual compatibility error
-                            if (expectedFail.trimIndent() != actualFail) {
-                                addError("ComparisonFailure: expected failure $expectedFail, actual $actualFail")
-                            }
-                        } else {
-                            // no compatibility error; check for other errors now, and
-                            // if one is found, fail right away
-                            assertEquals(expectedFail.trimIndent(), actualFail)
-                        }
+                        assertEquals(expectedFail.trimIndent(), actualFail)
                     }
                 }
             }
@@ -242,10 +239,10 @@
         /** Any jars to add to the class path */
         classpath: Array<TestFile>? = null,
         /** The API signature content (corresponds to --api) */
-        @Language("TEXT")
+        // @Language("TEXT") https://youtrack.jetbrains.com/issue/KT-35859
         api: String? = null,
         /** The API signature content (corresponds to --api-xml) */
-        @Language("XML")
+        // @Language("XML") https://youtrack.jetbrains.com/issue/KT-35859
         apiXml: String? = null,
         /** The DEX API (corresponds to --dex-api) */
         dexApi: String? = null,
@@ -254,10 +251,12 @@
         /** The removed dex API (corresponds to --removed-dex-api) */
         removedDexApi: String? = null,
         /** The subtract api signature content (corresponds to --subtract-api) */
-        @Language("TEXT")
+        // @Language("TEXT") https://youtrack.jetbrains.com/issue/KT-35859
         subtractApi: String? = null,
-        /** Expected stubs (corresponds to --stubs) */
-        stubFiles: Array<TestFile> = emptyArray(),
+        /** Expected stubs (corresponds to --stubs) in order corresponding to [sourceFiles]. Use
+         * [NO_STUB] as a marker for source files that are not expected to generate stubs */
+        // @Language("JAVA") https://youtrack.jetbrains.com/issue/KT-35859
+        stubs: Array<String> = emptyArray(),
         /** Stub source file list generated */
         stubsSourceList: String? = null,
         /** Doc Stub source file list generated */
@@ -279,50 +278,44 @@
         errorSeverityExpectedIssues: String? = null,
         checkCompilation: Boolean = false,
         /** Annotations to merge in (in .xml format) */
-        @Language("XML")
+        // @Language("XML") https://youtrack.jetbrains.com/issue/KT-35859
         mergeXmlAnnotations: String? = null,
         /** Annotations to merge in (in .txt/.signature format) */
-        @Language("TEXT")
+        // @Language("TEXT") https://youtrack.jetbrains.com/issue/KT-35859
         mergeSignatureAnnotations: String? = null,
         /** Qualifier annotations to merge in (in Java stub format) */
-        @Language("JAVA")
+        // @Language("JAVA") https://youtrack.jetbrains.com/issue/KT-35859
         mergeJavaStubAnnotations: String? = null,
         /** Inclusion annotations to merge in (in Java stub format) */
-        @Language("JAVA")
+        // @Language("JAVA") https://youtrack.jetbrains.com/issue/KT-35859
         mergeInclusionAnnotations: String? = null,
         /** Optional API signature files content to load **instead** of Java/Kotlin source files */
-        @Language("TEXT")
+        // @Language("TEXT") https://youtrack.jetbrains.com/issue/KT-35859
         signatureSources: Array<String> = emptyArray(),
         /**
          * An optional API signature file content to load **instead** of Java/Kotlin source files.
          * This is added to [signatureSources]. This argument exists for backward compatibility.
          */
-        @Language("TEXT")
+        // @Language("TEXT") https://youtrack.jetbrains.com/issue/KT-35859
         signatureSource: String? = null,
         /** An optional API jar file content to load **instead** of Java/Kotlin source files */
         apiJar: File? = null,
         /** An optional API signature to check the current API's compatibility with */
-        @Language("TEXT")
+        // @Language("TEXT") https://youtrack.jetbrains.com/issue/KT-35859
         checkCompatibilityApi: String? = null,
         /** An optional API signature to check the last released API's compatibility with */
-        @Language("TEXT")
+        // @Language("TEXT") https://youtrack.jetbrains.com/issue/KT-35859
         checkCompatibilityApiReleased: String? = null,
         /** An optional API signature to check the current removed API's compatibility with */
-        @Language("TEXT")
+        // @Language("TEXT") https://youtrack.jetbrains.com/issue/KT-35859
         checkCompatibilityRemovedApiCurrent: String? = null,
         /** An optional API signature to check the last released removed API's compatibility with */
-        @Language("TEXT")
+        // @Language("TEXT")
         checkCompatibilityRemovedApiReleased: String? = null,
-        /** An optional API signature to use as the base API codebase during compat checks */
-        @Language("TEXT")
-        checkCompatibilityBaseApi: String? = null,
         /** An optional API signature to compute nullness migration status from */
         allowCompatibleDifferences: Boolean = true,
-        @Language("TEXT")
+        // @Language("TEXT") https://youtrack.jetbrains.com/issue/KT-35859
         migrateNullsApi: String? = null,
-        /** An optional Proguard keep file to generate */
-        @Language("Proguard")
-        proguard: String? = null,
         /** Show annotations (--show-annotation arguments) */
         showAnnotations: Array<String> = emptyArray(),
         /** "Show for stub purposes" API annotation ([ARG_SHOW_FOR_STUB_PURPOSES_ANNOTATION]) */
@@ -348,7 +341,7 @@
         /** List of extra jar files to record annotation coverage from */
         coverageJars: Array<TestFile>? = null,
         /** Optional manifest to load and associate with the codebase */
-        @Language("XML")
+        // @Language("XML") https://youtrack.jetbrains.com/issue/KT-35859
         manifest: String? = null,
         /** Packages to pre-import (these will therefore NOT be included in emitted stubs, signature files etc */
         importedPackages: List<String> = emptyList(),
@@ -431,7 +424,7 @@
          * If non null, enable API lint. If non-blank, a codebase where only new APIs not in the codebase
          * are linted.
          */
-        @Language("TEXT")
+        // @Language("TEXT") https://youtrack.jetbrains.com/issue/KT-35859
         apiLint: String? = null,
         /** The source files to pass to the analyzer */
         sourceFiles: Array<TestFile> = emptyArray(),
@@ -663,19 +656,6 @@
             null
         }
 
-        val checkCompatibilityBaseApiFile = if (checkCompatibilityBaseApi != null) {
-            val maybeFile = File(checkCompatibilityBaseApi)
-            if (maybeFile.isFile) {
-                maybeFile
-            } else {
-                val file = File(project, "compatibility-base-api.txt")
-                file.writeText(checkCompatibilityBaseApi.trimIndent())
-                file
-            }
-        } else {
-            null
-        }
-
         val migrateNullsApiFile = if (migrateNullsApi != null) {
             val jar = File(migrateNullsApi)
             if (jar.isFile) {
@@ -720,12 +700,6 @@
             emptyArray()
         }
 
-        val checkCompatibilityBaseApiArguments = if (checkCompatibilityBaseApiFile != null) {
-            arrayOf(ARG_CHECK_COMPATIBILITY_BASE_API, checkCompatibilityBaseApiFile.path)
-        } else {
-            emptyArray()
-        }
-
         val checkCompatibilityRemovedCurrentArguments = if (checkCompatibilityRemovedApiCurrentFile != null) {
             val extra: Array<String> = if (allowCompatibleDifferences) {
                 arrayOf(ARG_ALLOW_COMPATIBLE_DIFFERENCES)
@@ -766,14 +740,6 @@
             emptyArray()
         }
 
-        var proguardFile: File? = null
-        val proguardKeepArguments = if (proguard != null) {
-            proguardFile = File(project, "proguard.cfg")
-            arrayOf(ARG_PROGUARD, proguardFile.path)
-        } else {
-            emptyArray()
-        }
-
         val showAnnotationArguments = if (showAnnotations.isNotEmpty() || includeSystemApiAnnotations) {
             val args = mutableListOf<String>()
             for (annotation in showAnnotations) {
@@ -938,7 +904,7 @@
         }
 
         var stubsDir: File? = null
-        val stubsArgs = if (stubFiles.isNotEmpty()) {
+        val stubsArgs = if (stubs.isNotEmpty()) {
             stubsDir = temporaryFolder.newFolder("stubs")
             if (docStubs) {
                 arrayOf(ARG_DOC_STUBS, stubsDir.path)
@@ -1170,10 +1136,8 @@
             *migrateNullsArguments,
             *checkCompatibilityArguments,
             *checkCompatibilityApiReleasedArguments,
-            *checkCompatibilityBaseApiArguments,
             *checkCompatibilityRemovedCurrentArguments,
             *checkCompatibilityRemovedReleasedArguments,
-            *proguardKeepArguments,
             *manifestFileArgs,
             *convertArgs,
             *applyApiLevelsXmlArgs,
@@ -1204,9 +1168,9 @@
             expectedFail = expectedFail
         )
 
-        if (expectedIssues != null || allReportedIssues.toString() != "") {
+        if (expectedIssues != null) {
             assertEquals(
-                expectedIssues?.trimIndent()?.trim() ?: "",
+                expectedIssues.trimIndent().trim(),
                 cleanupString(allReportedIssues.toString(), project)
             )
         }
@@ -1314,15 +1278,6 @@
             assertEquals(stripComments(removedDexApi, stripLineComments = false).trimIndent(), actualText)
         }
 
-        if (proguard != null && proguardFile != null) {
-            val expectedProguard = readFile(proguardFile)
-            assertTrue(
-                "${proguardFile.path} does not exist even though --proguard was used",
-                proguardFile.exists()
-            )
-            assertEquals(stripComments(proguard, stripLineComments = false).trimIndent(), expectedProguard.trim())
-        }
-
         if (sdk_broadcast_actions != null) {
             val actual = readFile(File(sdkFilesDir, "broadcast_actions.txt"), stripBlankLines, trim)
             assertEquals(sdk_broadcast_actions.trimIndent().trim(), actual.trim())
@@ -1373,16 +1328,56 @@
             assertEquals(validateNullability, actualReport)
         }
 
-        if (stubFiles.isNotEmpty()) {
-            for (expected in stubFiles) {
-                val actual = File(stubsDir!!, expected.targetRelativePath)
-                if (actual.exists()) {
-                    val actualContents = readFile(actual, stripBlankLines, trim)
-                    assertEquals(expected.contents, actualContents)
+        if (stubs.isNotEmpty() && stubsDir != null) {
+            for (i in stubs.indices) {
+                var stub = stubs[i].trimIndent()
+
+                var targetPath: String
+                var stubFile: File
+                if (stub.startsWith("[") && stub.contains("]")) {
+                    val pathEnd = stub.indexOf("]\n")
+                    targetPath = stub.substring(1, pathEnd)
+                    stubFile = File(stubsDir, targetPath)
+                    if (stubFile.isFile) {
+                        stub = stub.substring(pathEnd + 2)
+                    }
                 } else {
-                    val existing = stubsDir.walkTopDown().filter { it.isFile }.map { it.path }.joinToString("\n  ")
+                    val sourceFile = sourceFiles[i]
+                    targetPath = if (sourceFile.targetPath.endsWith(DOT_KT)) {
+                        // Kotlin source stubs are rewritten as .java files for now
+                        sourceFile.targetPath.substring(0, sourceFile.targetPath.length - 3) + DOT_JAVA
+                    } else {
+                        sourceFile.targetPath
+                    }
+                    stubFile = File(stubsDir, targetPath.substring("src/".length))
+                }
+                if (!stubFile.isFile) {
+                    if (stub.startsWith("[") && stub.contains("]")) {
+                        val pathEnd = stub.indexOf("]\n")
+                        val path = stub.substring(1, pathEnd)
+                        stubFile = File(stubsDir, path)
+                        if (stubFile.isFile) {
+                            stub = stub.substring(pathEnd + 2)
+                        }
+                    }
+                }
+                if (stubFile.exists()) {
+                    val actualText = readFile(stubFile, stripBlankLines, trim)
+                    assertEquals(stub, actualText)
+                } else if (stub != NO_STUB) {
+                    /* Example:
+                        stubs = arrayOf(
+                            """
+                            [test/visible/package-info.java]
+                            <html>My package docs</html>
+                            package test.visible;
+                            """,
+                            ...
+                       Here the stub will be read from $stubsDir/test/visible/package-info.java.
+                     */
                     throw FileNotFoundException(
-                        "Could not find a generated stub for ${expected.targetRelativePath}. Found these files: \n  $existing"
+                        "Could not find generated stub for $targetPath; consider " +
+                            "setting target relative path in stub header as prefix surrounded by []"
                     )
                 }
             }
@@ -1541,19 +1536,19 @@
             }
         }
 
-        fun java(to: String, @Language("JAVA") source: String): TestFile {
+        fun java(to: String, @Language("JAVA") source: String): LintDetectorTest.TestFile {
             return TestFiles.java(to, source.trimIndent())
         }
 
-        fun java(@Language("JAVA") source: String): TestFile {
+        fun java(@Language("JAVA") source: String): LintDetectorTest.TestFile {
             return TestFiles.java(source.trimIndent())
         }
 
-        fun kotlin(@Language("kotlin") source: String): TestFile {
+        fun kotlin(@Language("kotlin") source: String): LintDetectorTest.TestFile {
             return TestFiles.kotlin(source.trimIndent())
         }
 
-        fun kotlin(to: String, @Language("kotlin") source: String): TestFile {
+        fun kotlin(to: String, @Language("kotlin") source: String): LintDetectorTest.TestFile {
             return TestFiles.kotlin(to, source.trimIndent())
         }
 
diff --git a/src/test/java/com/android/tools/metalava/ExtractAnnotationsTest.kt b/src/test/java/com/android/tools/metalava/ExtractAnnotationsTest.kt
index a22911d..2ae6a89 100644
--- a/src/test/java/com/android/tools/metalava/ExtractAnnotationsTest.kt
+++ b/src/test/java/com/android/tools/metalava/ExtractAnnotationsTest.kt
@@ -162,8 +162,8 @@
                     <root>
                       <item name="test.pkg.LongDefTest void setFlags(java.lang.Object, int) 1">
                         <annotation name="androidx.annotation.LongDef">
-                          <val name="value" val="{test.pkg.LongDefTestKt.STYLE_NORMAL, test.pkg.LongDefTestKt.STYLE_NO_TITLE, test.pkg.LongDefTestKt.STYLE_NO_FRAME, test.pkg.LongDefTestKt.STYLE_NO_INPUT, 3, 4L}" />
                           <val name="flag" val="true" />
+                          <val name="value" val="{test.pkg.LongDefTestKt.STYLE_NORMAL, test.pkg.LongDefTestKt.STYLE_NO_TITLE, test.pkg.LongDefTestKt.STYLE_NO_FRAME, test.pkg.LongDefTestKt.STYLE_NO_INPUT, 3, 4L}" />
                         </annotation>
                       </item>
                       <item name="test.pkg.LongDefTest void setStyle(int, int) 0">
@@ -173,8 +173,8 @@
                       </item>
                       <item name="test.pkg.LongDefTest.Inner void setInner(int) 0">
                         <annotation name="androidx.annotation.LongDef">
-                          <val name="value" val="{test.pkg.LongDefTestKt.STYLE_NORMAL, test.pkg.LongDefTestKt.STYLE_NO_TITLE, test.pkg.LongDefTestKt.STYLE_NO_FRAME, test.pkg.LongDefTestKt.STYLE_NO_INPUT, 3, 4L}" />
                           <val name="flag" val="true" />
+                          <val name="value" val="{test.pkg.LongDefTestKt.STYLE_NORMAL, test.pkg.LongDefTestKt.STYLE_NO_TITLE, test.pkg.LongDefTestKt.STYLE_NO_FRAME, test.pkg.LongDefTestKt.STYLE_NO_INPUT, 3, 4L}" />
                         </annotation>
                       </item>
                     </root>
@@ -240,8 +240,8 @@
                     <root>
                       <item name="test.pkg.LongDefTest void setFlags(java.lang.Object, int) 1">
                         <annotation name="androidx.annotation.LongDef">
-                          <val name="value" val="{test.pkg.LongDefTestKt.STYLE_NORMAL, test.pkg.LongDefTestKt.STYLE_NO_TITLE, test.pkg.LongDefTestKt.STYLE_NO_FRAME, test.pkg.LongDefTestKt.STYLE_NO_INPUT, 3, 4L}" />
                           <val name="flag" val="true" />
+                          <val name="value" val="{test.pkg.LongDefTestKt.STYLE_NORMAL, test.pkg.LongDefTestKt.STYLE_NO_TITLE, test.pkg.LongDefTestKt.STYLE_NO_FRAME, test.pkg.LongDefTestKt.STYLE_NO_INPUT, 3, 4L}" />
                         </annotation>
                       </item>
                       <item name="test.pkg.LongDefTest void setStyle(int, int) 0">
@@ -251,8 +251,8 @@
                       </item>
                       <item name="test.pkg.LongDefTest.Inner void setInner(int) 0">
                         <annotation name="androidx.annotation.LongDef">
-                          <val name="value" val="{test.pkg.LongDefTestKt.STYLE_NORMAL, test.pkg.LongDefTestKt.STYLE_NO_TITLE, test.pkg.LongDefTestKt.STYLE_NO_FRAME, test.pkg.LongDefTestKt.STYLE_NO_INPUT, 3, 4L}" />
                           <val name="flag" val="true" />
+                          <val name="value" val="{test.pkg.LongDefTestKt.STYLE_NORMAL, test.pkg.LongDefTestKt.STYLE_NO_TITLE, test.pkg.LongDefTestKt.STYLE_NO_FRAME, test.pkg.LongDefTestKt.STYLE_NO_INPUT, 3, 4L}" />
                         </annotation>
                       </item>
                     </root>
@@ -407,18 +407,16 @@
                 intRangeAnnotationSource,
                 recentlyNullableSource
             ),
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Test {
-                    public Test() { throw new RuntimeException("Stub!"); }
-                    @androidx.annotation.RecentlyNullable
-                    public static java.lang.String sayHello(int value) { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Test {
+                public Test() { throw new RuntimeException("Stub!"); }
+                @androidx.annotation.RecentlyNullable
+                public static java.lang.String sayHello(int value) { throw new RuntimeException("Stub!"); }
+                }
+                """
             ),
             extractAnnotations = mapOf(
                 "test.pkg" to """
diff --git a/src/test/java/com/android/tools/metalava/HideAnnotationTest.kt b/src/test/java/com/android/tools/metalava/HideAnnotationTest.kt
deleted file mode 100644
index fc16af5..0000000
--- a/src/test/java/com/android/tools/metalava/HideAnnotationTest.kt
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.metalava
-
-import org.junit.Test
-
-class HideAnnotationTest : DriverTest() {
-    // Regression test for b/133364476 crash
-    @Test
-    fun `Using hide annotation with Kotlin source`() {
-        check(
-            expectedIssues = """
-                src/test/pkg/).kt:2: warning: Public class test.pkg.ExtendingMyHiddenClass stripped of unavailable superclass test.pkg.MyHiddenClass [HiddenSuperclass]
-            """,
-            sourceFiles = arrayOf(
-                kotlin(
-                    """
-                    package test.pkg
-                    @Retention(AnnotationRetention.BINARY)
-                    @Target(AnnotationTarget.ANNOTATION_CLASS)
-                    annotation class MetaHide
-                """
-                ),
-                kotlin(
-                    """
-                    package test.pkg
-                    @MetaHide
-                    annotation class RegularHide
-                """
-                ),
-                kotlin(
-                    """
-                    package test.pkg
-                    @RegularHide
-                    open class MyHiddenClass<T> {
-                        @RegularHide
-                        fun myHiddenFun(target: T, name: String) {}
-                    }
-                """
-                ),
-                kotlin(
-                    """
-                    package test.pkg
-                    @OptIn(MyHiddenClass::class)
-                    open class ExtendingMyHiddenClass<Float> : MyHiddenClass<Float>() {
-                    }
-                """
-                )
-            ),
-            hideAnnotations = arrayOf(
-                "test.pkg.MetaHide"
-            ),
-            hideMetaAnnotations = arrayOf(
-                "test.pkg.MetaHide"
-            ),
-            compatibilityMode = false,
-            api = """
-                package test.pkg {
-                  public class ExtendingMyHiddenClass<Float> {
-                    ctor public ExtendingMyHiddenClass();
-                  }
-                  @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention) @kotlin.annotation.Target(allowedTargets=kotlin.annotation.AnnotationTarget) public @interface MetaHide {
-                  }
-                }
-                """
-        )
-    }
-}
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/metalava/Java9LanguageFeaturesTest.kt b/src/test/java/com/android/tools/metalava/Java9LanguageFeaturesTest.kt
index 286517a..6e51e9e 100644
--- a/src/test/java/com/android/tools/metalava/Java9LanguageFeaturesTest.kt
+++ b/src/test/java/com/android/tools/metalava/Java9LanguageFeaturesTest.kt
@@ -18,7 +18,6 @@
 
 package com.android.tools.metalava
 
-import org.junit.Ignore
 import org.junit.Test
 
 class Java9LanguageFeaturesTest : DriverTest() {
@@ -63,7 +62,7 @@
                     interface Foo {
                         companion object {
                             @JvmField
-                            const val answer: Int = 42
+                            val answer: Int = 42
                             @JvmStatic
                             fun sayHello() {
                                 println("Hello, world!")
@@ -186,7 +185,6 @@
         )
     }
 
-    @Ignore("TODO: unable to load JDK11 libraries from java.home")
     @Test
     fun `Using JDK APIs`() {
         // Non-Android example
diff --git a/src/test/java/com/android/tools/metalava/KeepFileTest.kt b/src/test/java/com/android/tools/metalava/KeepFileTest.kt
deleted file mode 100644
index 178b653..0000000
--- a/src/test/java/com/android/tools/metalava/KeepFileTest.kt
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.metalava
-
-import org.junit.Test
-
-class KeepFileTest : DriverTest() {
-    @Test
-    fun `Generate Keep file`() {
-        check(
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings("ALL")
-                    public interface MyInterface<T extends Object>
-                            extends MyBaseInterface {
-                    }
-                    """
-                ), java(
-                    """
-                    package a.b.c;
-                    @SuppressWarnings("ALL")
-                    public interface MyStream<T, S extends MyStream<T, S>> extends java.lang.AutoCloseable {
-                    }
-                    """
-                ), java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings("ALL")
-                    public interface MyInterface2<T extends Number>
-                            extends MyBaseInterface {
-                        class TtsSpan<C extends MyInterface<?>> { }
-                        abstract class Range<T extends Comparable<? super T>> {
-                            protected String myString;
-                        }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    public interface MyBaseInterface {
-                        void fun(int a, String b);
-                    }
-                    """
-                )
-            ),
-            proguard = """
-                -keep class a.b.c.MyStream {
-                }
-                -keep class test.pkg.MyBaseInterface {
-                    public abstract void fun(int, java.lang.String);
-                }
-                -keep class test.pkg.MyInterface {
-                }
-                -keep class test.pkg.MyInterface2 {
-                }
-                -keep class test.pkg.MyInterface2${"$"}Range {
-                    <init>();
-                    protected java.lang.String myString;
-                }
-                -keep class test.pkg.MyInterface2${"$"}TtsSpan {
-                    <init>();
-                }
-                """,
-            extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword")
-        )
-    }
-
-    @Test
-    fun `Primitive types`() {
-        check(
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    public class MyClass {
-                        public int testMethodA(int a) {}
-                        public boolean testMethodB(boolean a) {}
-                        public float testMethodC(float a) {}
-                        public double testMethodD(double a) {}
-                        public byte testMethodE(byte a) {}
-                    }
-                    """
-                )
-            ),
-            proguard = """
-                -keep class test.pkg.MyClass {
-                    <init>();
-                    public int testMethodA(int);
-                    public boolean testMethodB(boolean);
-                    public float testMethodC(float);
-                    public double testMethodD(double);
-                    public byte testMethodE(byte);
-                }
-                """,
-            extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword")
-        )
-    }
-
-    @Test
-    fun `Primitive array types`() {
-        check(
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    public class MyClass {
-                        public int[] testMethodA(int[] a) {}
-                        public float[][] testMethodB(float[][] a) {}
-                        public double[][][] testMethodC(double[][][] a) {}
-                        public byte testMethodD(byte... a) {}
-                    }
-                    """
-                )
-            ),
-            proguard = """
-                -keep class test.pkg.MyClass {
-                    <init>();
-                    public int[] testMethodA(int[]);
-                    public float[][] testMethodB(float[][]);
-                    public double[][][] testMethodC(double[][][]);
-                    public byte testMethodD(byte[]);
-                }
-                """,
-            extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword")
-        )
-    }
-
-    @Test
-    fun `Object Array parameters`() {
-        check(
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    public class MyClass {
-                        public void testMethodA(String a) {}
-                        public void testMethodB(Boolean[] a) {}
-                        public void testMethodC(Integer... a) {}
-                    }
-                    """
-                )
-            ),
-            proguard = """
-                -keep class test.pkg.MyClass {
-                    <init>();
-                    public void testMethodA(java.lang.String);
-                    public void testMethodB(java.lang.Boolean[]);
-                    public void testMethodC(java.lang.Integer[]);
-                }
-                """,
-            extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword")
-        )
-    }
-
-    @Test
-    fun `Arrays with Inner class`() {
-        check(
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    public class MyClass {
-                        public void testMethodA(InnerClass a) {}
-                        public void testMethodB(InnerClass[] a) {}
-                        public void testMethodC(InnerClass... a) {}
-                        public class InnerClass {}
-                    }
-                    """
-                )
-            ),
-            proguard = """
-                -keep class test.pkg.MyClass {
-                    <init>();
-                    public void testMethodA(test.pkg.MyClass${"$"}InnerClass);
-                    public void testMethodB(test.pkg.MyClass${"$"}InnerClass[]);
-                    public void testMethodC(test.pkg.MyClass${"$"}InnerClass[]);
-                }
-                -keep class test.pkg.MyClass${"$"}InnerClass {
-                    <init>();
-                }
-                """,
-            extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword")
-        )
-    }
-
-    @Test
-    fun `Conflicting Class Names in parameters`() {
-        check(
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    public class String {}
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    public class MyClass {
-                        public void testMethodA(String a, String b) {}
-                        public void testMethodB(String a, test.pkg.String b) {}
-                        public void testMethodC(String a, java.lang.String b) {}
-                        public void testMethodD(java.lang.String a, test.pkg.String b) {}
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    public class MyClassArrays {
-                        public void testMethodA(String[] a, String[] b) {}
-                        public void testMethodB(String[] a, test.pkg.String[] b) {}
-                        public void testMethodC(String[] a, java.lang.String[] b) {}
-                        public void testMethodD(java.lang.String... a, test.pkg.String... b) {}
-                    }
-                    """
-                )
-            ),
-            proguard = """
-                -keep class test.pkg.MyClass {
-                    <init>();
-                    public void testMethodA(test.pkg.String, test.pkg.String);
-                    public void testMethodB(test.pkg.String, test.pkg.String);
-                    public void testMethodC(test.pkg.String, java.lang.String);
-                    public void testMethodD(java.lang.String, test.pkg.String);
-                }
-                -keep class test.pkg.MyClassArrays {
-                    <init>();
-                    public void testMethodA(test.pkg.String[], test.pkg.String[]);
-                    public void testMethodB(test.pkg.String[], test.pkg.String[]);
-                    public void testMethodC(test.pkg.String[], java.lang.String[]);
-                    public void testMethodD(java.lang.String[], test.pkg.String[]);
-                }
-                -keep class test.pkg.String {
-                    <init>();
-                }
-                """,
-            extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword")
-        )
-    }
-
-    @Test
-    fun `Multi dimensional arrays`() {
-        check(
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    public class String {}
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    public class MyClassArrays {
-                        public void testMethodA(String[][] a, String[][] b) {}
-                        public void testMethodB(String[][][] a, test.pkg.String[][][] b) {}
-                        public void testMethodC(String[][] a, java.lang.String[][] b) {}
-                        public class InnerClass {}
-                        public void testMethodD(InnerClass[][] a) {}
-                    }
-                    """
-                )
-            ),
-            proguard = """
-                -keep class test.pkg.MyClassArrays {
-                    <init>();
-                    public void testMethodA(test.pkg.String[][], test.pkg.String[][]);
-                    public void testMethodB(test.pkg.String[][][], test.pkg.String[][][]);
-                    public void testMethodC(test.pkg.String[][], java.lang.String[][]);
-                    public void testMethodD(test.pkg.MyClassArrays${"$"}InnerClass[][]);
-                }
-                -keep class test.pkg.MyClassArrays${"$"}InnerClass {
-                    <init>();
-                }
-                -keep class test.pkg.String {
-                    <init>();
-                }
-                """,
-            extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword")
-        )
-    }
-
-    @Test
-    fun `Methods with arrays as the return type`() {
-        check(
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    public class MyClass {
-                        public String[] testMethodA() {}
-                        public String[][] testMethodB() {}
-                        public String[][][] testMethodC() {}
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    public class MyOtherClass {
-                        public java.lang.String[] testMethodA() {}
-                        public String[][] testMethodB() {}
-                        public test.pkg.String[][][] testMethodC() {}
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    public class String {}
-                    """
-                )
-            ),
-            proguard = """
-                -keep class test.pkg.MyClass {
-                    <init>();
-                    public test.pkg.String[] testMethodA();
-                    public test.pkg.String[][] testMethodB();
-                    public test.pkg.String[][][] testMethodC();
-                }
-                -keep class test.pkg.MyOtherClass {
-                    <init>();
-                    public java.lang.String[] testMethodA();
-                    public test.pkg.String[][] testMethodB();
-                    public test.pkg.String[][][] testMethodC();
-                }
-                -keep class test.pkg.String {
-                    <init>();
-                }
-                """,
-            extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword")
-        )
-    }
-}
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/metalava/KotlinInteropChecksTest.kt b/src/test/java/com/android/tools/metalava/KotlinInteropChecksTest.kt
index bdd97c1..6131fa5 100644
--- a/src/test/java/com/android/tools/metalava/KotlinInteropChecksTest.kt
+++ b/src/test/java/com/android/tools/metalava/KotlinInteropChecksTest.kt
@@ -28,7 +28,10 @@
                 src/test/pkg/Test.java:8: error: Avoid parameter names that are Kotlin hard keywords ("typealias"); see https://android.github.io/kotlin-guides/interop.html#no-hard-keywords [KotlinKeyword]
                 src/test/pkg/Test.java:9: error: Avoid field names that are Kotlin hard keywords ("object"); see https://android.github.io/kotlin-guides/interop.html#no-hard-keywords [KotlinKeyword]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                3 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -56,9 +59,9 @@
         check(
             apiLint = "",
             expectedIssues = """
-                src/test/pkg/Test.java:20: warning: SAM-compatible parameters (such as parameter 1, "run", in test.pkg.Test.error1) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions [SamShouldBeLast] [See https://s.android.com/api-guidelines#placement-of-sam-parameters]
-                src/test/pkg/Test.java:21: warning: SAM-compatible parameters (such as parameter 2, "callback", in test.pkg.Test.error2) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions [SamShouldBeLast] [See https://s.android.com/api-guidelines#placement-of-sam-parameters]
-                src/test/pkg/test.kt:7: warning: lambda parameters (such as parameter 1, "bar", in test.pkg.TestKt.error) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions [SamShouldBeLast] [See https://s.android.com/api-guidelines#placement-of-sam-parameters]
+                src/test/pkg/Test.java:20: warning: SAM-compatible parameters (such as parameter 1, "run", in test.pkg.Test.error1) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions [SamShouldBeLast]
+                src/test/pkg/Test.java:21: warning: SAM-compatible parameters (such as parameter 2, "callback", in test.pkg.Test.error2) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions [SamShouldBeLast]
+                src/test/pkg/test.kt:7: warning: lambda parameters (such as parameter 1, "bar", in test.pkg.TestKt.error) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions [SamShouldBeLast]
                 """,
             sourceFiles = arrayOf(
                 java(
@@ -78,7 +81,7 @@
                         public void ok3(@Nullable Runnable run) { }
                         public void ok4(int x, @Nullable Runnable run) { }
                         public void ok5(@Nullable Runnable run1, @Nullable Runnable run2) { }
-                        public void ok6(@NonNull java.util.List<String> list, boolean b) { }
+                        public void ok6(@Nullable java.util.List list, boolean b) { }
                         // Consumer declares exactly one non-default method (accept), other methods are default.
                         public void ok7(@NonNull String packageName, @NonNull Executor executor,
                             @NonNull Consumer<Boolean> callback) {}
@@ -114,11 +117,7 @@
     fun `Companion object methods should be marked with JvmStatic`() {
         check(
             apiLint = "",
-            extraArguments = arrayOf(
-                ARG_HIDE, "AllUpper",
-                ARG_HIDE, "AcronymName",
-                ARG_HIDE, "CompileTimeConstant"
-            ),
+            extraArguments = arrayOf(ARG_HIDE, "AllUpper", ARG_HIDE, "AcronymName"),
             expectedIssues = """
                 src/test/pkg/Foo.kt:8: warning: Companion object constants like BIG_INTEGER_ONE should be marked @JvmField for Java interoperability; see https://developer.android.com/kotlin/interop#companion_constants [MissingJvmstatic]
                 src/test/pkg/Foo.kt:11: warning: Companion object constants like WRONG should be using @JvmField, not @JvmStatic; see https://developer.android.com/kotlin/interop#companion_constants [MissingJvmstatic]
@@ -191,12 +190,15 @@
             apiLint = "",
             extraArguments = arrayOf(ARG_HIDE, "BannedThrow", ARG_HIDE, "GenericException"),
             expectedIssues = """
-                src/test/pkg/Foo.kt:6: error: Method Foo.error_throws_multiple_times appears to be throwing java.io.FileNotFoundException; this should be recorded with a @Throws annotation; see https://android.github.io/kotlin-guides/interop.html#document-exceptions [DocumentExceptions] [See https://s.android.com/api-guidelines#docs-throws]
-                src/test/pkg/Foo.kt:16: error: Method Foo.error_throwsCheckedExceptionWithWrongExceptionClassInThrows appears to be throwing java.io.FileNotFoundException; this should be recorded with a @Throws annotation; see https://android.github.io/kotlin-guides/interop.html#document-exceptions [DocumentExceptions] [See https://s.android.com/api-guidelines#docs-throws]
-                src/test/pkg/Foo.kt:37: error: Method Foo.error_throwsRuntimeExceptionDocsMissing appears to be throwing java.lang.UnsupportedOperationException; this should be listed in the documentation; see https://android.github.io/kotlin-guides/interop.html#document-exceptions [DocumentExceptions] [See https://s.android.com/api-guidelines#docs-throws]
-                src/test/pkg/Foo.kt:43: error: Method Foo.error_missingSpecificAnnotation appears to be throwing java.lang.UnsupportedOperationException; this should be listed in the documentation; see https://android.github.io/kotlin-guides/interop.html#document-exceptions [DocumentExceptions] [See https://s.android.com/api-guidelines#docs-throws]
+                src/test/pkg/Foo.kt:6: error: Method Foo.error_throws_multiple_times appears to be throwing java.io.FileNotFoundException; this should be recorded with a @Throws annotation; see https://android.github.io/kotlin-guides/interop.html#document-exceptions [DocumentExceptions]
+                src/test/pkg/Foo.kt:16: error: Method Foo.error_throwsCheckedExceptionWithWrongExceptionClassInThrows appears to be throwing java.io.FileNotFoundException; this should be recorded with a @Throws annotation; see https://android.github.io/kotlin-guides/interop.html#document-exceptions [DocumentExceptions]
+                src/test/pkg/Foo.kt:37: error: Method Foo.error_throwsRuntimeExceptionDocsMissing appears to be throwing java.lang.UnsupportedOperationException; this should be listed in the documentation; see https://android.github.io/kotlin-guides/interop.html#document-exceptions [DocumentExceptions]
+                src/test/pkg/Foo.kt:43: error: Method Foo.error_missingSpecificAnnotation appears to be throwing java.lang.UnsupportedOperationException; this should be listed in the documentation; see https://android.github.io/kotlin-guides/interop.html#document-exceptions [DocumentExceptions]
                 """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                4 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """.trimIndent(),
             sourceFiles = arrayOf(
                 kotlin(
                     """
diff --git a/src/test/java/com/android/tools/metalava/MarkPackagesAsRecentTest.kt b/src/test/java/com/android/tools/metalava/MarkPackagesAsRecentTest.kt
index 601873b..352264a 100644
--- a/src/test/java/com/android/tools/metalava/MarkPackagesAsRecentTest.kt
+++ b/src/test/java/com/android/tools/metalava/MarkPackagesAsRecentTest.kt
@@ -29,18 +29,16 @@
                 ARG_FORCE_CONVERT_TO_WARNING_NULLABILITY_ANNOTATIONS, "*"
             ),
 
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Foo {
-                    public Foo() { throw new RuntimeException("Stub!"); }
-                    @androidx.annotation.RecentlyNullable
-                    public void method() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Foo {
+                public Foo() { throw new RuntimeException("Stub!"); }
+                @androidx.annotation.RecentlyNullable
+                public void method() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -67,18 +65,16 @@
                 ARG_SHOW_ANNOTATION, "androidx.annotation.RestrictTo"
             ),
 
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Foo {
-                    public Foo() { throw new RuntimeException("Stub!"); }
-                    @androidx.annotation.RecentlyNullable
-                    public void method() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Foo {
+                public Foo() { throw new RuntimeException("Stub!"); }
+                @androidx.annotation.RecentlyNullable
+                public void method() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
diff --git a/src/test/java/com/android/tools/metalava/NullnessMigrationTest.kt b/src/test/java/com/android/tools/metalava/NullnessMigrationTest.kt
index 874056f..d7d054b 100644
--- a/src/test/java/com/android/tools/metalava/NullnessMigrationTest.kt
+++ b/src/test/java/com/android/tools/metalava/NullnessMigrationTest.kt
@@ -92,18 +92,16 @@
                   }
                 }
                 """,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public abstract class MyTest {
-                    private MyTest() { throw new RuntimeException("Stub!"); }
-                    @androidx.annotation.RecentlyNullable
-                    public java.lang.Double convert1(java.lang.Float f) { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public abstract class MyTest {
+                private MyTest() { throw new RuntimeException("Stub!"); }
+                @androidx.annotation.RecentlyNullable
+                public java.lang.Double convert1(java.lang.Float f) { throw new RuntimeException("Stub!"); }
+                }
+                """
             ),
             extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation")
         )
@@ -142,17 +140,15 @@
                   }
                 }
                 """,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public abstract class MyTest {
-                    private MyTest() { throw new RuntimeException("Stub!"); }
-                    public java.lang.Double convert1(@androidx.annotation.RecentlyNonNull java.lang.Float f) { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public abstract class MyTest {
+                private MyTest() { throw new RuntimeException("Stub!"); }
+                public java.lang.Double convert1(@androidx.annotation.RecentlyNonNull java.lang.Float f) { throw new RuntimeException("Stub!"); }
+                }
+                """
             ),
             extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation")
         )
@@ -205,25 +201,23 @@
                   }
                 }
                 """,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class MyTest {
-                    public MyTest() { throw new RuntimeException("Stub!"); }
-                    public java.lang.Double convert0(java.lang.Float f) { throw new RuntimeException("Stub!"); }
-                    @androidx.annotation.RecentlyNullable
-                    public java.lang.Double convert1(@androidx.annotation.RecentlyNonNull java.lang.Float f) { throw new RuntimeException("Stub!"); }
-                    @android.annotation.Nullable
-                    public java.lang.Double convert2(@android.annotation.NonNull java.lang.Float f) { throw new RuntimeException("Stub!"); }
-                    @android.annotation.Nullable
-                    public java.lang.Double convert3(@android.annotation.NonNull java.lang.Float f) { throw new RuntimeException("Stub!"); }
-                    @android.annotation.Nullable
-                    public java.lang.Double convert4(@android.annotation.NonNull java.lang.Float f) { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class MyTest {
+                public MyTest() { throw new RuntimeException("Stub!"); }
+                public java.lang.Double convert0(java.lang.Float f) { throw new RuntimeException("Stub!"); }
+                @androidx.annotation.RecentlyNullable
+                public java.lang.Double convert1(@androidx.annotation.RecentlyNonNull java.lang.Float f) { throw new RuntimeException("Stub!"); }
+                @android.annotation.Nullable
+                public java.lang.Double convert2(@android.annotation.NonNull java.lang.Float f) { throw new RuntimeException("Stub!"); }
+                @android.annotation.Nullable
+                public java.lang.Double convert3(@android.annotation.NonNull java.lang.Float f) { throw new RuntimeException("Stub!"); }
+                @android.annotation.Nullable
+                public java.lang.Double convert4(@android.annotation.NonNull java.lang.Float f) { throw new RuntimeException("Stub!"); }
+                }
+                """
             ),
             extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation")
         )
@@ -474,39 +468,35 @@
                   }
                 }
                 """,
-            stubFiles = if (SUPPORT_TYPE_USE_ANNOTATIONS) {
+            stubs = if (SUPPORT_TYPE_USE_ANNOTATIONS) {
                 arrayOf(
-                    java(
-                        """
-                        package test.pkg;
-                        @SuppressWarnings({"unchecked", "deprecation", "all"})
-                        public class Foo {
-                        public Foo() { throw new RuntimeException("Stub!"); }
-                        public static char @androidx.annotation.RecentlyNonNull [] toChars(int codePoint) { throw new RuntimeException("Stub!"); }
-                        public static int codePointAt(char @androidx.annotation.RecentlyNonNull [] a, int index) { throw new RuntimeException("Stub!"); }
-                        public <T> T @android.annotation.RecentlyNonNull [] toArray(T @androidx.annotation.RecentlyNonNull [] a) { throw new RuntimeException("Stub!"); }
-                        @androidx.annotation.NonNull
-                        public static java.lang.String newMethod(@android.annotation.Nullable java.lang.String argument) { throw new RuntimeException("Stub!"); }
-                        }
                     """
-                    )
+                    package test.pkg;
+                    @SuppressWarnings({"unchecked", "deprecation", "all"})
+                    public class Foo {
+                    public Foo() { throw new RuntimeException("Stub!"); }
+                    public static char @androidx.annotation.RecentlyNonNull [] toChars(int codePoint) { throw new RuntimeException("Stub!"); }
+                    public static int codePointAt(char @androidx.annotation.RecentlyNonNull [] a, int index) { throw new RuntimeException("Stub!"); }
+                    public <T> T @android.annotation.RecentlyNonNull [] toArray(T @androidx.annotation.RecentlyNonNull [] a) { throw new RuntimeException("Stub!"); }
+                    @androidx.annotation.NonNull
+                    public static java.lang.String newMethod(@android.annotation.Nullable java.lang.String argument) { throw new RuntimeException("Stub!"); }
+                    }
+                """
                 )
             } else {
                 arrayOf(
-                    java(
-                        """
-                        package test.pkg;
-                        @SuppressWarnings({"unchecked", "deprecation", "all"})
-                        public class Foo {
-                        public Foo() { throw new RuntimeException("Stub!"); }
-                        public static char[] toChars(int codePoint) { throw new RuntimeException("Stub!"); }
-                        public static int codePointAt(char[] a, int index) { throw new RuntimeException("Stub!"); }
-                        public <T> T[] toArray(T[] a) { throw new RuntimeException("Stub!"); }
-                        @android.annotation.NonNull
-                        public static java.lang.String newMethod(@android.annotation.Nullable java.lang.String argument) { throw new RuntimeException("Stub!"); }
-                        }
-                        """
-                    )
+                    """
+                    package test.pkg;
+                    @SuppressWarnings({"unchecked", "deprecation", "all"})
+                    public class Foo {
+                    public Foo() { throw new RuntimeException("Stub!"); }
+                    public static char[] toChars(int codePoint) { throw new RuntimeException("Stub!"); }
+                    public static int codePointAt(char[] a, int index) { throw new RuntimeException("Stub!"); }
+                    public <T> T[] toArray(T[] a) { throw new RuntimeException("Stub!"); }
+                    @android.annotation.NonNull
+                    public static java.lang.String newMethod(@android.annotation.Nullable java.lang.String argument) { throw new RuntimeException("Stub!"); }
+                    }
+                    """
                 )
             }
         )
@@ -546,35 +536,31 @@
                   }
                 }
                 """,
-            stubFiles = if (SUPPORT_TYPE_USE_ANNOTATIONS) {
+            stubs = if (SUPPORT_TYPE_USE_ANNOTATIONS) {
                 arrayOf(
-                    java(
-                        """
-                        package test.pkg;
-                        @SuppressWarnings({"unchecked", "deprecation", "all"})
-                        public class Foo {
-                        public Foo() { throw new RuntimeException("Stub!"); }
-                        public static char @androidx.annotation.RecentlyNonNull [] toChars(int codePoint) { throw new RuntimeException("Stub!"); }
-                        public static int codePointAt(char @androidx.annotation.RecentlyNonNull [] a, int index) { throw new RuntimeException("Stub!"); }
-                        public <T> T @androidx.annotation.RecentlyNonNull [] toArray(T @androidx.annotation.RecentlyNonNull [] a) { throw new RuntimeException("Stub!"); }
-                        }
-                        """
-                    )
+                    """
+                    package test.pkg;
+                    @SuppressWarnings({"unchecked", "deprecation", "all"})
+                    public class Foo {
+                    public Foo() { throw new RuntimeException("Stub!"); }
+                    public static char @androidx.annotation.RecentlyNonNull [] toChars(int codePoint) { throw new RuntimeException("Stub!"); }
+                    public static int codePointAt(char @androidx.annotation.RecentlyNonNull [] a, int index) { throw new RuntimeException("Stub!"); }
+                    public <T> T @androidx.annotation.RecentlyNonNull [] toArray(T @androidx.annotation.RecentlyNonNull [] a) { throw new RuntimeException("Stub!"); }
+                    }
+                    """
                 )
             } else {
                 arrayOf(
-                    java(
-                        """
-                        package test.pkg;
-                        @SuppressWarnings({"unchecked", "deprecation", "all"})
-                        public class Foo {
-                        public Foo() { throw new RuntimeException("Stub!"); }
-                        public static char[] toChars(int codePoint) { throw new RuntimeException("Stub!"); }
-                        public static int codePointAt(char[] a, int index) { throw new RuntimeException("Stub!"); }
-                        public <T> T[] toArray(T[] a) { throw new RuntimeException("Stub!"); }
-                        }
-                        """
-                    )
+                    """
+                    package test.pkg;
+                    @SuppressWarnings({"unchecked", "deprecation", "all"})
+                    public class Foo {
+                    public Foo() { throw new RuntimeException("Stub!"); }
+                    public static char[] toChars(int codePoint) { throw new RuntimeException("Stub!"); }
+                    public static int codePointAt(char[] a, int index) { throw new RuntimeException("Stub!"); }
+                    public <T> T[] toArray(T[] a) { throw new RuntimeException("Stub!"); }
+                    }
+                    """
                 )
             }
         )
@@ -616,37 +602,33 @@
                 }
             """,
             extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation"),
-            stubFiles = if (SUPPORT_TYPE_USE_ANNOTATIONS) {
+            stubs = if (SUPPORT_TYPE_USE_ANNOTATIONS) {
                 arrayOf(
-                    java(
-                        """
-                        package test.pkg;
-                        @SuppressWarnings({"unchecked", "deprecation", "all"})
-                        public class Foo {
-                        public Foo() { throw new RuntimeException("Stub!"); }
-                        @androidx.annotation.RecentlyNonNull
-                        public java.lang.reflect.Constructor<?> @androidx.annotation.RecentlyNonNull [] getConstructors() { throw new RuntimeException("Stub!"); }
-                        @androidx.annotation.RecentlyNonNull
-                        public synchronized java.lang.reflect.TypeVariable<java.lang.@androidx.annotation.RecentlyNonNull Class<T>> @androidx.annotation.RecentlyNonNull [] getTypeParameters() { throw new RuntimeException("Stub!"); }
-                        }
-                        """
-                    )
+                    """
+                    package test.pkg;
+                    @SuppressWarnings({"unchecked", "deprecation", "all"})
+                    public class Foo {
+                    public Foo() { throw new RuntimeException("Stub!"); }
+                    @androidx.annotation.RecentlyNonNull
+                    public java.lang.reflect.Constructor<?> @androidx.annotation.RecentlyNonNull [] getConstructors() { throw new RuntimeException("Stub!"); }
+                    @androidx.annotation.RecentlyNonNull
+                    public synchronized java.lang.reflect.TypeVariable<java.lang.@androidx.annotation.RecentlyNonNull Class<T>> @androidx.annotation.RecentlyNonNull [] getTypeParameters() { throw new RuntimeException("Stub!"); }
+                    }
+                    """
                 )
             } else {
                 arrayOf(
-                    java(
-                        """
-                        package test.pkg;
-                        @SuppressWarnings({"unchecked", "deprecation", "all"})
-                        public class Foo {
-                        public Foo() { throw new RuntimeException("Stub!"); }
-                        @androidx.annotation.RecentlyNonNull
-                        public java.lang.reflect.Constructor<?>[] getConstructors() { throw new RuntimeException("Stub!"); }
-                        @androidx.annotation.RecentlyNonNull
-                        public synchronized java.lang.reflect.TypeVariable<java.lang.Class<T>>[] getTypeParameters() { throw new RuntimeException("Stub!"); }
-                        }
-                        """
-                    )
+                    """
+                    package test.pkg;
+                    @SuppressWarnings({"unchecked", "deprecation", "all"})
+                    public class Foo {
+                    public Foo() { throw new RuntimeException("Stub!"); }
+                    @androidx.annotation.RecentlyNonNull
+                    public java.lang.reflect.Constructor<?>[] getConstructors() { throw new RuntimeException("Stub!"); }
+                    @androidx.annotation.RecentlyNonNull
+                    public synchronized java.lang.reflect.TypeVariable<java.lang.Class<T>>[] getTypeParameters() { throw new RuntimeException("Stub!"); }
+                    }
+                    """
                 )
             }
         )
@@ -698,28 +680,24 @@
                   }
                 }
             """,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public interface Appendable {
-                    @androidx.annotation.RecentlyNonNull
-                    public test.pkg.Appendable append(@androidx.annotation.RecentlyNullable java.lang.CharSequence csq);
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    /** @hide */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public interface ForSystemUse {
-                    @androidx.annotation.RecentlyNonNull
-                    public java.lang.Object foo(@androidx.annotation.RecentlyNullable java.lang.String foo);
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public interface Appendable {
+                @androidx.annotation.RecentlyNonNull
+                public test.pkg.Appendable append(@androidx.annotation.RecentlyNullable java.lang.CharSequence csq);
+                }
+                """,
+                """
+                package test.pkg;
+                /** @hide */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public interface ForSystemUse {
+                @androidx.annotation.RecentlyNonNull
+                public java.lang.Object foo(@androidx.annotation.RecentlyNullable java.lang.String foo);
+                }
+                """
             ),
             api = """
                 package test.pkg {
@@ -813,31 +791,27 @@
                 androidxNonNullSource,
                 androidxNullableSource
             ),
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Child1 extends test.pkg.Parent {
-                    private Child1() { throw new RuntimeException("Stub!"); }
-                    public void method1(@androidx.annotation.RecentlyNonNull java.lang.String first, int second) { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Child2 extends test.pkg.Parent {
-                    private Child2() { throw new RuntimeException("Stub!"); }
-                    public void method0(java.lang.String first, int second) { throw new RuntimeException("Stub!"); }
-                    public void method1(java.lang.String first, int second) { throw new RuntimeException("Stub!"); }
-                    public void method2(@androidx.annotation.RecentlyNonNull java.lang.String first, int second) { throw new RuntimeException("Stub!"); }
-                    public void method3(java.lang.String first, int second) { throw new RuntimeException("Stub!"); }
-                    public void method4(java.lang.String first, int second) { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Child1 extends test.pkg.Parent {
+                private Child1() { throw new RuntimeException("Stub!"); }
+                public void method1(@androidx.annotation.RecentlyNonNull java.lang.String first, int second) { throw new RuntimeException("Stub!"); }
+                }
+                """,
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Child2 extends test.pkg.Parent {
+                private Child2() { throw new RuntimeException("Stub!"); }
+                public void method0(java.lang.String first, int second) { throw new RuntimeException("Stub!"); }
+                public void method1(java.lang.String first, int second) { throw new RuntimeException("Stub!"); }
+                public void method2(@androidx.annotation.RecentlyNonNull java.lang.String first, int second) { throw new RuntimeException("Stub!"); }
+                public void method3(java.lang.String first, int second) { throw new RuntimeException("Stub!"); }
+                public void method4(java.lang.String first, int second) { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
diff --git a/src/test/java/com/android/tools/metalava/OptionsTest.kt b/src/test/java/com/android/tools/metalava/OptionsTest.kt
index 6c22a59..ab47e43 100644
--- a/src/test/java/com/android/tools/metalava/OptionsTest.kt
+++ b/src/test/java/com/android/tools/metalava/OptionsTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.tools.metalava
 
+import com.android.tools.metalava.doclava1.Issues
 import com.android.tools.metalava.model.defaultConfiguration
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
@@ -136,7 +137,7 @@
 --java-source <level>
                                              Sets the source level for Java source files; default is 1.8.
 --kotlin-source <level>
-                                             Sets the source level for Kotlin source files; default is 1.4.
+                                             Sets the source level for Kotlin source files; default is 1.3.
 --sdk-home <dir>
                                              If set, locate the `android.jar` file from the given Android SDK
 --compile-sdk-version <api>
@@ -205,8 +206,6 @@
 --include-signature-version[=yes|no]
                                              Whether the signature files should include a comment listing the format
                                              version of the signature file.
---proguard <file>
-                                             Write a ProGuard keep file for the API
 --sdk-values <dir>
                                              Write SDK values files to the given directory
 
@@ -227,18 +226,11 @@
                                              code will be written in Kotlin rather than the Java programming language.
 --include-annotations
                                              Include annotations such as @Nullable in the stub files.
---exclude-all-annotations
+--exclude-annotations
                                              Exclude annotations such as @Nullable from the stub files; the default.
 --pass-through-annotation <annotation classes>
                                              A comma separated list of fully qualified names of annotation classes that
                                              must be passed through unchanged.
---exclude-annotation <annotation classes>
-                                             A comma separated list of fully qualified names of annotation classes that
-                                             must be stripped from metalava's outputs.
---enhance-documentation
-                                             Enhance documentation in various ways, for example auto-generating
-                                             documentation based on source annotations present in the code. This is
-                                             implied by --doc-stubs.
 --exclude-documentation-from-stubs
                                              Exclude element documentation (javadoc and kdoc) from the generated stubs.
                                              (Copyright notices are not affected by this, they are always included.
@@ -269,13 +261,6 @@
                                              publicly released API, respectively. Different compatibility checks apply
                                              in the two scenarios. For example, to check the code base against the
                                              current public API, use --check-compatibility:api:current.
---check-compatibility:base <file>
-                                             When performing a compat check, use the provided signature file as a base
-                                             api, which is treated as part of the API being checked. This allows us to
-                                             compute the full API surface from a partial API surface (e.g. the current
-                                             @SystemApi txt file), which allows us to recognize when an API is moved
-                                             from the partial API to the base API and avoid incorrectly flagging this as
-                                             an API removal.
 --api-lint [api file]
                                              Check API for Android API best practices. If a signature file is provided,
                                              only the APIs that are new since the API will be checked.
@@ -548,6 +533,15 @@
     }
 
     @Test
+    fun `Test issue severity options by numeric id`() {
+        check(
+            extraArguments = arrayOf("--hide", "366"),
+            expectedIssues = "warning: Issue lookup by numeric id is deprecated, use --hide ArrayReturn instead of --hide 366 [DeprecatedOption]"
+        )
+        assertEquals(Severity.HIDDEN, defaultConfiguration.getSeverity(Issues.ARRAY_RETURN))
+    }
+
+    @Test
     fun `Test issue severity options with case insensitive names`() {
         check(
             extraArguments = arrayOf("--hide", "arrayreturn"),
diff --git a/src/test/java/com/android/tools/metalava/ReporterTest.kt b/src/test/java/com/android/tools/metalava/ReporterTest.kt
index ffde69f..f324349 100644
--- a/src/test/java/com/android/tools/metalava/ReporterTest.kt
+++ b/src/test/java/com/android/tools/metalava/ReporterTest.kt
@@ -24,13 +24,16 @@
         check(
             apiLint = "",
             expectedIssues = """
-                src/test/pkg/foo.java:2: error: Class must start with uppercase char: foo [StartWithUpper] [See https://s.android.com/api-guidelines#style-conventions]
-                src/test/pkg/foo.java:4: warning: If min/max could change in future, make them dynamic methods: test.pkg.foo#MAX_BAR [MinMaxConstant] [See https://s.android.com/api-guidelines#min-max-constants]
+                src/test/pkg/foo.java:2: error: Class must start with uppercase char: foo [StartWithUpper] [Rule S1 in go/android-api-guidelines]
+                src/test/pkg/foo.java:4: warning: If min/max could change in future, make them dynamic methods: test.pkg.foo#MAX_BAR [MinMaxConstant] [Rule C8 in go/android-api-guidelines]
             """,
             errorSeverityExpectedIssues = """
-                src/test/pkg/foo.java:2: error: Class must start with uppercase char: foo [StartWithUpper] [See https://s.android.com/api-guidelines#style-conventions]
+                src/test/pkg/foo.java:2: error: Class must start with uppercase char: foo [StartWithUpper] [Rule S1 in go/android-api-guidelines]
             """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                2 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java(
                     """
@@ -50,10 +53,13 @@
         check(
             apiLint = "",
             expectedIssues = """
-                src/test/pkg/Bar.kt:10: error: Method name must start with lowercase char: Unsuppressed [StartWithLower] [See https://s.android.com/api-guidelines#style-conventions]
-                src/test/pkg/Foo.java:10: error: Method name must start with lowercase char: Unsuppressed [StartWithLower] [See https://s.android.com/api-guidelines#style-conventions]
+                src/test/pkg/Bar.kt:10: error: Method name must start with lowercase char: Unsuppressed [StartWithLower] [Rule S1 in go/android-api-guidelines]
+                src/test/pkg/Foo.java:10: error: Method name must start with lowercase char: Unsuppressed [StartWithLower] [Rule S1 in go/android-api-guidelines]
             """,
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                2 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+            """,
             sourceFiles = arrayOf(
                 java("""
                     package test.pkg;
@@ -87,37 +93,18 @@
     }
 
     @Test
-    fun `Test suppressing infos`() {
-        check(
-            apiLint = "",
-            expectedIssues = "",
-            sourceFiles = arrayOf(
-                java("""
-                    package test.pkg;
-                    import android.annotation.SuppressLint;
-
-                    public class Foo {
-                        @SuppressLint("KotlinOperator")
-                        public int get(int i) { return i + 1; }
-                    }
-                """),
-                suppressLintSource
-            )
-        )
-    }
-
-    @Test
     fun `Test repeat errors with 1 error`() {
         check(
             apiLint = "",
             expectedIssues = """
-                src/test/pkg/Foo.java:4: error: Missing nullability on parameter `a` in method `foo1` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
+                src/test/pkg/Foo.java:4: error: Missing nullability on parameter `a` in method `foo1` [MissingNullability]
             """,
             expectedFail = """
+                1 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
                 Error: metalava detected the following problems:
-                src/test/pkg/Foo.java:4: error: Missing nullability on parameter `a` in method `foo1` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-
-            """.trimIndent() + DefaultLintErrorMessage,
+                src/test/pkg/Foo.java:4: error: Missing nullability on parameter `a` in method `foo1` [MissingNullability]
+            """,
             repeatErrorsMax = 5,
             sourceFiles = arrayOf(
                 java("""
@@ -137,21 +124,22 @@
         check(
             apiLint = "",
             expectedIssues = """
-                src/test/pkg/Foo.java:4: error: Missing nullability on parameter `a` in method `foo1` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-                src/test/pkg/Foo.java:5: error: Missing nullability on parameter `a` in method `foo2` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-                src/test/pkg/Foo.java:6: error: Missing nullability on parameter `a` in method `foo3` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-                src/test/pkg/Foo.java:7: error: Missing nullability on parameter `a` in method `foo4` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-                src/test/pkg/Foo.java:8: error: Missing nullability on parameter `a` in method `foo5` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
+                src/test/pkg/Foo.java:4: error: Missing nullability on parameter `a` in method `foo1` [MissingNullability]
+                src/test/pkg/Foo.java:5: error: Missing nullability on parameter `a` in method `foo2` [MissingNullability]
+                src/test/pkg/Foo.java:6: error: Missing nullability on parameter `a` in method `foo3` [MissingNullability]
+                src/test/pkg/Foo.java:7: error: Missing nullability on parameter `a` in method `foo4` [MissingNullability]
+                src/test/pkg/Foo.java:8: error: Missing nullability on parameter `a` in method `foo5` [MissingNullability]
             """,
             expectedFail = """
+                5 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
                 Error: metalava detected the following problems:
-                src/test/pkg/Foo.java:4: error: Missing nullability on parameter `a` in method `foo1` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-                src/test/pkg/Foo.java:5: error: Missing nullability on parameter `a` in method `foo2` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-                src/test/pkg/Foo.java:6: error: Missing nullability on parameter `a` in method `foo3` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-                src/test/pkg/Foo.java:7: error: Missing nullability on parameter `a` in method `foo4` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-                src/test/pkg/Foo.java:8: error: Missing nullability on parameter `a` in method `foo5` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-
-            """.trimIndent() + DefaultLintErrorMessage,
+                src/test/pkg/Foo.java:4: error: Missing nullability on parameter `a` in method `foo1` [MissingNullability]
+                src/test/pkg/Foo.java:5: error: Missing nullability on parameter `a` in method `foo2` [MissingNullability]
+                src/test/pkg/Foo.java:6: error: Missing nullability on parameter `a` in method `foo3` [MissingNullability]
+                src/test/pkg/Foo.java:7: error: Missing nullability on parameter `a` in method `foo4` [MissingNullability]
+                src/test/pkg/Foo.java:8: error: Missing nullability on parameter `a` in method `foo5` [MissingNullability]
+            """,
             repeatErrorsMax = 5,
             sourceFiles = arrayOf(
                 java("""
@@ -175,23 +163,24 @@
         check(
             apiLint = "",
             expectedIssues = """
-                src/test/pkg/Foo.java:4: error: Missing nullability on parameter `a` in method `foo1` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-                src/test/pkg/Foo.java:5: error: Missing nullability on parameter `a` in method `foo2` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-                src/test/pkg/Foo.java:6: error: Missing nullability on parameter `a` in method `foo3` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-                src/test/pkg/Foo.java:7: error: Missing nullability on parameter `a` in method `foo4` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-                src/test/pkg/Foo.java:8: error: Missing nullability on parameter `a` in method `foo5` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-                src/test/pkg/Foo.java:9: error: Missing nullability on parameter `a` in method `foo6` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
+                src/test/pkg/Foo.java:4: error: Missing nullability on parameter `a` in method `foo1` [MissingNullability]
+                src/test/pkg/Foo.java:5: error: Missing nullability on parameter `a` in method `foo2` [MissingNullability]
+                src/test/pkg/Foo.java:6: error: Missing nullability on parameter `a` in method `foo3` [MissingNullability]
+                src/test/pkg/Foo.java:7: error: Missing nullability on parameter `a` in method `foo4` [MissingNullability]
+                src/test/pkg/Foo.java:8: error: Missing nullability on parameter `a` in method `foo5` [MissingNullability]
+                src/test/pkg/Foo.java:9: error: Missing nullability on parameter `a` in method `foo6` [MissingNullability]
             """,
             expectedFail = """
+                6 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
                 Error: metalava detected the following problems:
-                src/test/pkg/Foo.java:4: error: Missing nullability on parameter `a` in method `foo1` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-                src/test/pkg/Foo.java:5: error: Missing nullability on parameter `a` in method `foo2` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-                src/test/pkg/Foo.java:6: error: Missing nullability on parameter `a` in method `foo3` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-                src/test/pkg/Foo.java:7: error: Missing nullability on parameter `a` in method `foo4` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
-                src/test/pkg/Foo.java:8: error: Missing nullability on parameter `a` in method `foo5` [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
+                src/test/pkg/Foo.java:4: error: Missing nullability on parameter `a` in method `foo1` [MissingNullability]
+                src/test/pkg/Foo.java:5: error: Missing nullability on parameter `a` in method `foo2` [MissingNullability]
+                src/test/pkg/Foo.java:6: error: Missing nullability on parameter `a` in method `foo3` [MissingNullability]
+                src/test/pkg/Foo.java:7: error: Missing nullability on parameter `a` in method `foo4` [MissingNullability]
+                src/test/pkg/Foo.java:8: error: Missing nullability on parameter `a` in method `foo5` [MissingNullability]
                 1 more error(s) omitted. Search the log for 'error:' to find all of them.
-
-            """.trimIndent() + DefaultLintErrorMessage,
+            """,
             repeatErrorsMax = 5,
             sourceFiles = arrayOf(
                 java("""
diff --git a/src/test/java/com/android/tools/metalava/ShowAnnotationTest.kt b/src/test/java/com/android/tools/metalava/ShowAnnotationTest.kt
index 91fb515..70e9436 100644
--- a/src/test/java/com/android/tools/metalava/ShowAnnotationTest.kt
+++ b/src/test/java/com/android/tools/metalava/ShowAnnotationTest.kt
@@ -217,31 +217,27 @@
                     """
                 )
             ),
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg2;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class MyChild extends test.pkg1.MyParent {
-                    public MyChild() { throw new RuntimeException("Stub!"); }
-                    public static final long CONSTANT1 = 12345L; // 0x3039L
-                    public static final long CONSTANT2 = 67890L; // 0x10932L
-                    public static final long CONSTANT3 = 42L; // 0x2aL
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg1;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class MyParent implements java.io.Closeable {
-                    public MyParent() { throw new RuntimeException("Stub!"); }
-                    public static final long CONSTANT1 = 12345L; // 0x3039L
-                    public static final long CONSTANT2 = 67890L; // 0x10932L
-                    public static final long CONSTANT3 = 42L; // 0x2aL
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg2;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class MyChild extends test.pkg1.MyParent {
+                public MyChild() { throw new RuntimeException("Stub!"); }
+                public static final long CONSTANT1 = 12345L; // 0x3039L
+                public static final long CONSTANT2 = 67890L; // 0x10932L
+                public static final long CONSTANT3 = 42L; // 0x2aL
+                }
+            """.trimIndent(),
+                """
+                package test.pkg1;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class MyParent implements java.io.Closeable {
+                public MyParent() { throw new RuntimeException("Stub!"); }
+                public static final long CONSTANT1 = 12345L; // 0x3039L
+                public static final long CONSTANT2 = 67890L; // 0x10932L
+                public static final long CONSTANT3 = 42L; // 0x2aL
+                }
+                """.trimIndent()
             ),
             // Empty API: showUnannotated=false
             api = """
@@ -754,33 +750,28 @@
                   }
                 }
                 """,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    /** @hide */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Class1 {
-                    public Class1() { throw new RuntimeException("Stub!"); }
-                    /** @hide */
-                    public void member() { throw new RuntimeException("Stub!"); }
-                    /** @hide */
-                    public static final java.lang.String FIELD = "Class1.FIELD";
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    /** @hide */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Class2 extends test.pkg.Class1 {
-                    public Class2() { throw new RuntimeException("Stub!"); }
-                    /** @hide */
-                    public void member() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf("""
+                package test.pkg;
+                /** @hide */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Class1 {
+                public Class1() { throw new RuntimeException("Stub!"); }
+                /** @hide */
+                public void member() { throw new RuntimeException("Stub!"); }
+                /** @hide */
+                public static final java.lang.String FIELD = "Class1.FIELD";
+                }
+                """,
+                """
+                package test.pkg;
+                /** @hide */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Class2 extends test.pkg.Class1 {
+                public Class2() { throw new RuntimeException("Stub!"); }
+                /** @hide */
+                public void member() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
diff --git a/src/test/java/com/android/tools/metalava/ShowForStubPurposesAnnotationTest.kt b/src/test/java/com/android/tools/metalava/ShowForStubPurposesAnnotationTest.kt
index 00e57da..ebb364e 100644
--- a/src/test/java/com/android/tools/metalava/ShowForStubPurposesAnnotationTest.kt
+++ b/src/test/java/com/android/tools/metalava/ShowForStubPurposesAnnotationTest.kt
@@ -17,6 +17,7 @@
 package com.android.tools.metalava
 
 import com.android.tools.lint.checks.infrastructure.TestFile
+import com.android.tools.metalava.doclava1.Issues
 import org.junit.Test
 
 class ShowForStubPurposesAnnotationTest : DriverTest() {
@@ -356,79 +357,70 @@
                   }
                 }
                 """,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class SystemClass {
-                    public SystemClass() { throw new RuntimeException("Stub!"); }
-                    public void noAnnotation() { throw new RuntimeException("Stub!"); }
-                    public void system() { throw new RuntimeException("Stub!"); }
-                    public void module() { throw new RuntimeException("Stub!"); }
-                    public void moduleAndSystem() { throw new RuntimeException("Stub!"); }
-                    public void referFromModuleToSystem(test.pkg.SystemClass2 arg) { throw new RuntimeException("Stub!"); }
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public static class NestedDefault {
-                    public NestedDefault() { throw new RuntimeException("Stub!"); }
-                    public void noAnnotation() { throw new RuntimeException("Stub!"); }
-                    public void system() { throw new RuntimeException("Stub!"); }
-                    public void module() { throw new RuntimeException("Stub!"); }
-                    }
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public static class NestedModule {
-                    public NestedModule() { throw new RuntimeException("Stub!"); }
-                    public void noAnnotation() { throw new RuntimeException("Stub!"); }
-                    public void module() { throw new RuntimeException("Stub!"); }
-                    }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class PublicClass {
-                    public PublicClass() { throw new RuntimeException("Stub!"); }
-                    public void noAnnotation() { throw new RuntimeException("Stub!"); }
-                    public void system() { throw new RuntimeException("Stub!"); }
-                    public void module() { throw new RuntimeException("Stub!"); }
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public static class NestedDefault {
-                    public NestedDefault() { throw new RuntimeException("Stub!"); }
-                    public void noAnnotation() { throw new RuntimeException("Stub!"); }
-                    public void system() { throw new RuntimeException("Stub!"); }
-                    public void module() { throw new RuntimeException("Stub!"); }
-                    }
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public static class NestedModule {
-                    public NestedModule() { throw new RuntimeException("Stub!"); }
-                    public void noAnnotation() { throw new RuntimeException("Stub!"); }
-                    public void module() { throw new RuntimeException("Stub!"); }
-                    }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class SystemClass2 {
-                    public SystemClass2() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class ModuleClass {
-                    public ModuleClass() { throw new RuntimeException("Stub!"); }
-                    public void noAnnotation() { throw new RuntimeException("Stub!"); }
-                    public void module() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf("""
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class SystemClass {
+                public SystemClass() { throw new RuntimeException("Stub!"); }
+                public void noAnnotation() { throw new RuntimeException("Stub!"); }
+                public void system() { throw new RuntimeException("Stub!"); }
+                public void module() { throw new RuntimeException("Stub!"); }
+                public void moduleAndSystem() { throw new RuntimeException("Stub!"); }
+                public void referFromModuleToSystem(test.pkg.SystemClass2 arg) { throw new RuntimeException("Stub!"); }
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public static class NestedDefault {
+                public NestedDefault() { throw new RuntimeException("Stub!"); }
+                public void noAnnotation() { throw new RuntimeException("Stub!"); }
+                public void system() { throw new RuntimeException("Stub!"); }
+                public void module() { throw new RuntimeException("Stub!"); }
+                }
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public static class NestedModule {
+                public NestedModule() { throw new RuntimeException("Stub!"); }
+                public void noAnnotation() { throw new RuntimeException("Stub!"); }
+                public void module() { throw new RuntimeException("Stub!"); }
+                }
+                }
+                """,
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class PublicClass {
+                public PublicClass() { throw new RuntimeException("Stub!"); }
+                public void noAnnotation() { throw new RuntimeException("Stub!"); }
+                public void system() { throw new RuntimeException("Stub!"); }
+                public void module() { throw new RuntimeException("Stub!"); }
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public static class NestedDefault {
+                public NestedDefault() { throw new RuntimeException("Stub!"); }
+                public void noAnnotation() { throw new RuntimeException("Stub!"); }
+                public void system() { throw new RuntimeException("Stub!"); }
+                public void module() { throw new RuntimeException("Stub!"); }
+                }
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public static class NestedModule {
+                public NestedModule() { throw new RuntimeException("Stub!"); }
+                public void noAnnotation() { throw new RuntimeException("Stub!"); }
+                public void module() { throw new RuntimeException("Stub!"); }
+                }
+                }
+                """,
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class SystemClass2 {
+                public SystemClass2() { throw new RuntimeException("Stub!"); }
+                }
+                """,
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class ModuleClass {
+                public ModuleClass() { throw new RuntimeException("Stub!"); }
+                public void noAnnotation() { throw new RuntimeException("Stub!"); }
+                public void module() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -682,9 +674,12 @@
                 }
                 """,
             apiLint = "",
-            expectedFail = DefaultLintErrorMessage,
+            expectedFail = """
+                1 new API lint issues were found.
+                See tools/metalava/API-LINT.md for how to handle these.
+                """,
             expectedIssues = """
-                src/test/pkg/ModuleClassExtendingPublic.java:9: error: Missing nullability on method `method2` return [MissingNullability] [See https://s.android.com/api-guidelines#annotations]
+                src/test/pkg/ModuleClassExtendingPublic.java:9: error: Missing nullability on method `method2` return [MissingNullability]
                 """
         )
     }
diff --git a/src/test/java/com/android/tools/metalava/SubtractApiTest.kt b/src/test/java/com/android/tools/metalava/SubtractApiTest.kt
index a74c598..c348b33 100644
--- a/src/test/java/com/android/tools/metalava/SubtractApiTest.kt
+++ b/src/test/java/com/android/tools/metalava/SubtractApiTest.kt
@@ -71,19 +71,17 @@
                   }
                 }
                 """,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class OnlyInNew {
-                    private OnlyInNew() { throw new RuntimeException("Stub!"); }
-                    public void method1() { throw new RuntimeException("Stub!"); }
-                    public void method5() { throw new RuntimeException("Stub!"); }
-                    public void method6() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class OnlyInNew {
+                private OnlyInNew() { throw new RuntimeException("Stub!"); }
+                public void method1() { throw new RuntimeException("Stub!"); }
+                public void method5() { throw new RuntimeException("Stub!"); }
+                public void method6() { throw new RuntimeException("Stub!"); }
+                }
+                """
             ),
             stubsSourceList = """
                 TESTROOT/stubs/test/pkg/OnlyInNew.java
diff --git a/src/test/java/com/android/tools/metalava/SymlinkTest.kt b/src/test/java/com/android/tools/metalava/SymlinkTest.kt
index 16187ff..e32a40c 100644
--- a/src/test/java/com/android/tools/metalava/SymlinkTest.kt
+++ b/src/test/java/com/android/tools/metalava/SymlinkTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.tools.metalava
 
+import com.android.tools.lint.checks.infrastructure.TestFiles.source
 import org.junit.Test
 import java.io.File
 
@@ -37,20 +38,9 @@
         val before = System.getProperty("user.dir")
         try {
             check(
-                expectedIssues = "TESTROOT/src/test/pkg/sub1/sub2/sub3: info: Ignoring symlink during source file discovery directory traversal [IgnoringSymlink]",
-                projectSetup = { dir ->
-                    // Add a symlink from deep in the source tree back out to the
-                    // root, which makes a cycle
-                    val file = File(dir, "src/test/pkg/sub1/sub2")
-                    file.mkdirs()
-                    val symlink = File(file, "sub3").toPath()
-                    java.nio.file.Files.createSymbolicLink(symlink, dir.toPath())
-
-                    val git = File(file, ".git").toPath()
-                    java.nio.file.Files.createSymbolicLink(git, dir.toPath())
-
-                    // Write implicit source files to be discovered by our crawl.
-                    File(dir, "src/test/pkg/Foo.java").writeText(
+                expectedIssues = "TESTROOT/src/test/pkg/sub1/sub2/sub3: info: Ignoring symlink during package.html discovery directory traversal [IgnoringSymlink]",
+                sourceFiles = arrayOf(
+                    java(
                         """
                         package test.pkg;
                         import android.annotation.Nullable;
@@ -62,8 +52,10 @@
                             @Nullable public Double method2(@NonNull Double factor1, @NonNull Double factor2) { }
                             @Nullable public Double method3(@NonNull Double factor1, @NonNull Double factor2) { }
                         }
-                        """)
-                    File(dir, "src/test/pkg/sub1/package.html").writeText(
+                        """
+                    ),
+                    source(
+                        "src/test/pkg/sub1/package.html",
                         """
                         <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
                         <!-- not a body tag: <body> -->
@@ -75,7 +67,21 @@
                         Another line.<br>
                         </BODY>
                         </html>
-                        """)
+                        """
+                    ).indented(),
+                    nonNullSource,
+                    nullableSource
+                ),
+                projectSetup = { dir ->
+                    // Add a symlink from deep in the source tree back out to the
+                    // root, which makes a cycle
+                    val file = File(dir, "src/test/pkg/sub1/sub2")
+                    file.mkdirs()
+                    val symlink = File(file, "sub3").toPath()
+                    java.nio.file.Files.createSymbolicLink(symlink, dir.toPath())
+
+                    val git = File(file, ".git").toPath()
+                    java.nio.file.Files.createSymbolicLink(git, dir.toPath())
                 },
                 // Empty source path: don't pick up random directory stuff
                 extraArguments = arrayOf(
@@ -83,28 +89,26 @@
                     ARG_SOURCE_PATH, ""
                 ),
                 checkCompilation = false, // needs androidx.annotations in classpath
-                stubFiles = arrayOf(
-                    java(
-                        """
-                        package test.pkg;
-                        @SuppressWarnings({"unchecked", "deprecation", "all"})
-                        public class Foo {
-                        public Foo() { throw new RuntimeException("Stub!"); }
-                        /** These are the docs for method1. */
-                        @android.annotation.Nullable
-                        public java.lang.Double method1(@android.annotation.NonNull java.lang.Double factor1, @android.annotation.NonNull java.lang.Double factor2) { throw new RuntimeException("Stub!"); }
-                        /** These are the docs for method2. It can sometimes return null. */
-                        @android.annotation.Nullable
-                        public java.lang.Double method2(@android.annotation.NonNull java.lang.Double factor1, @android.annotation.NonNull java.lang.Double factor2) { throw new RuntimeException("Stub!"); }
-                        @android.annotation.Nullable
-                        public java.lang.Double method3(@android.annotation.NonNull java.lang.Double factor1, @android.annotation.NonNull java.lang.Double factor2) { throw new RuntimeException("Stub!"); }
-                        }
-                        """
-                    )
+                stubs = arrayOf(
+                    """
+                    package test.pkg;
+                    @SuppressWarnings({"unchecked", "deprecation", "all"})
+                    public class Foo {
+                    public Foo() { throw new RuntimeException("Stub!"); }
+                    /** These are the docs for method1. */
+                    @android.annotation.Nullable
+                    public java.lang.Double method1(@android.annotation.NonNull java.lang.Double factor1, @android.annotation.NonNull java.lang.Double factor2) { throw new RuntimeException("Stub!"); }
+                    /** These are the docs for method2. It can sometimes return null. */
+                    @android.annotation.Nullable
+                    public java.lang.Double method2(@android.annotation.NonNull java.lang.Double factor1, @android.annotation.NonNull java.lang.Double factor2) { throw new RuntimeException("Stub!"); }
+                    @android.annotation.Nullable
+                    public java.lang.Double method3(@android.annotation.NonNull java.lang.Double factor1, @android.annotation.NonNull java.lang.Double factor2) { throw new RuntimeException("Stub!"); }
+                    }
+                    """
                 )
             )
         } finally {
             System.setProperty("user.dir", before)
         }
     }
-}
+}
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/metalava/SystemServiceCheckTest.kt b/src/test/java/com/android/tools/metalava/SystemServiceCheckTest.kt
index 425b061..43f1405 100644
--- a/src/test/java/com/android/tools/metalava/SystemServiceCheckTest.kt
+++ b/src/test/java/com/android/tools/metalava/SystemServiceCheckTest.kt
@@ -341,6 +341,20 @@
                     }
                     """
                 ),
+                java(
+                    """
+                    package test.pkg;
+
+                    @android.annotation.SystemService
+                    public class MyTest2 {
+                        // Old suppress syntax
+                        @android.annotation.SuppressLint({"Doclava10","Doclava125"})
+                        @android.annotation.RequiresPermission(anyOf={"foo.bar.PERMISSION1","foo.bar.PERMISSION2"})
+                        public void myMethod1() {
+                        }
+                    }
+                    """
+                ),
                 systemServiceSource
             ),
             manifest = """<?xml version="1.0" encoding="UTF-8"?>
diff --git a/src/test/java/com/android/tools/metalava/apilevels/ApiGeneratorTest.kt b/src/test/java/com/android/tools/metalava/apilevels/ApiGeneratorTest.kt
index 9c4da1e..2f7d722 100644
--- a/src/test/java/com/android/tools/metalava/apilevels/ApiGeneratorTest.kt
+++ b/src/test/java/com/android/tools/metalava/apilevels/ApiGeneratorTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.tools.metalava.apilevels
 
+import com.android.sdklib.repository.AndroidSdkHandler
 import com.android.tools.lint.LintCliClient
 import com.android.tools.lint.checks.ApiLookup
 import com.android.tools.metalava.ARG_ANDROID_JAR_PATTERN
@@ -106,6 +107,10 @@
                 return super.findResource(relativePath)
             }
 
+            override fun getSdk(): AndroidSdkHandler? {
+                return null
+            }
+
             override fun getCacheDir(name: String?, create: Boolean): File? {
                 return temporaryFolder.newFolder()
             }
diff --git a/src/test/java/com/android/tools/metalava/model/AnnotationTargetTest.kt b/src/test/java/com/android/tools/metalava/model/AnnotationTargetTest.kt
deleted file mode 100644
index bab3f48..0000000
--- a/src/test/java/com/android/tools/metalava/model/AnnotationTargetTest.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.metalava.model
-
-import com.android.tools.metalava.model.AnnotationTarget.INTERNAL
-import org.junit.Assert.assertTrue
-import org.junit.Test
-import java.lang.reflect.Modifier
-
-class AnnotationTargetTest {
-    @Test
-    fun `All annotation targets contain INTERNAL`() {
-        // Kotlin reflection can't list top-level items yet, rely on Java reflection for now.
-        Class.forName("${AnnotationTarget::class.qualifiedName}Kt").constants
-            .also { assertTrue(it.isNotEmpty()) }
-            .forEach { (name, value) ->
-                val targets = value as Collection<*>
-                assertTrue("$name: should contain $INTERNAL but doesn't: $targets",
-                        targets.contains(INTERNAL))
-            }
-    }
-
-    private val Class<*>.constants get() = methods
-            .filter { Modifier.isStatic(it.modifiers) }
-            .filter { it.name.startsWith("get") }
-            .map { it.name to it.invoke(null) }
-}
diff --git a/src/test/java/com/android/tools/metalava/model/TypeItemTest.kt b/src/test/java/com/android/tools/metalava/model/TypeItemTest.kt
index 1772272..908248d 100644
--- a/src/test/java/com/android/tools/metalava/model/TypeItemTest.kt
+++ b/src/test/java/com/android/tools/metalava/model/TypeItemTest.kt
@@ -51,23 +51,4 @@
         assertThat(TypeItem.equalsWithoutSpace("true", " true  false")).isFalse()
         assertThat(TypeItem.equalsWithoutSpace("false ", "falser")).isFalse()
     }
-
-    @Test
-    fun testToLambdaFormat() {
-        fun check(typeName: String, expected: String = typeName) {
-            assertThat(TypeItem.toLambdaFormat(typeName)).isEqualTo(expected)
-        }
-
-        // Expected to pass string through unchanged
-        check("androidx.pkg.Foo")
-        check("kotlin.jvm.functions<<>")
-
-        check("kotlin.jvm.functions.Function0<kotlin.Unit>", "() -> kotlin.Unit")
-        check("kotlin.jvm.functions.Function1<pkg.Foo, pkg.Bar>", "(pkg.Foo) -> pkg.Bar")
-        check(
-            "kotlin.jvm.functions.Function2<Integer, String, Map<Integer, String>>",
-            "(Integer, String) -> Map<Integer, String>"
-        )
-        check("kotlin.jvm.functions<<>")
-    }
 }
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/metalava/model/psi/JavadocTest.kt b/src/test/java/com/android/tools/metalava/model/psi/JavadocTest.kt
index 3a0909b..b3365b2 100644
--- a/src/test/java/com/android/tools/metalava/model/psi/JavadocTest.kt
+++ b/src/test/java/com/android/tools/metalava/model/psi/JavadocTest.kt
@@ -38,7 +38,7 @@
         check(
             sourceFiles = sourceFiles,
             showAnnotations = showAnnotations,
-            stubFiles = arrayOf(java(source)),
+            stubs = arrayOf(source),
             compatibilityMode = compatibilityMode,
             expectedIssues = warnings,
             checkCompilation = true,
@@ -148,18 +148,18 @@
                     import test.pkg2.OtherClass;
                     import java.io.IOException;
                     /**
-                     *  Blah blah {@link test.pkg2.OtherClass OtherClass} blah blah.
-                     *  Referencing <b>field</b> {@link test.pkg2.OtherClass#foo OtherClass#foo},
-                     *  and referencing method {@link test.pkg2.OtherClass#bar(int,boolean) OtherClass#bar(int,
+                     *  Blah blah {@link OtherClass} blah blah.
+                     *  Referencing <b>field</b> {@link OtherClass#foo},
+                     *  and referencing method {@link OtherClass#bar(int,
                      *   boolean)}.
                      *  And relative method reference {@link #baz()}.
                      *  And relative field reference {@link #importance}.
                      *  Here's an already fully qualified reference: {@link test.pkg2.OtherClass}.
-                     *  And here's one in the same package: {@link test.pkg1.LocalClass LocalClass}.
+                     *  And here's one in the same package: {@link LocalClass}.
                      *
                      *  @deprecated For some reason
-                     *  @see test.pkg2.OtherClass
-                     *  @see test.pkg2.OtherClass#bar(int, boolean)
+                     *  @see OtherClass
+                     *  @see OtherClass#bar(int, boolean)
                      */
                     @SuppressWarnings({"unchecked", "deprecation", "all"})
                     @Deprecated
@@ -167,10 +167,10 @@
                     public SomeClass() { throw new RuntimeException("Stub!"); }
                     /**
                      * My method.
-                     * @param focus The focus to find. One of {@link test.pkg2.OtherClass#FOCUS_INPUT OtherClass#FOCUS_INPUT} or
-                     *         {@link test.pkg2.OtherClass#FOCUS_ACCESSIBILITY OtherClass#FOCUS_ACCESSIBILITY}.
-                     * @throws java.io.IOException when blah blah blah
-                     * @throws {@link java.lang.RuntimeException RuntimeException} when blah blah blah
+                     * @param focus The focus to find. One of {@link OtherClass#FOCUS_INPUT} or
+                     *         {@link OtherClass#FOCUS_ACCESSIBILITY}.
+                     * @throws IOException when blah blah blah
+                     * @throws {@link RuntimeException} when blah blah blah
                      */
                     public void baz(int focus) throws java.io.IOException { throw new RuntimeException("Stub!"); }
                     public boolean importance;
@@ -210,8 +210,8 @@
                        * My method.
                        * @param focus The focus to find. One of {@link OtherClass#FOCUS_INPUT} or
                        *         {@link OtherClass#FOCUS_ACCESSIBILITY}.
-                       * @throws java.io.IOException when blah blah blah
-                       * @throws {@link java.lang.RuntimeException} when blah blah blah
+                       * @throws IOException when blah blah blah
+                       * @throws {@link RuntimeException} when blah blah blah
                        */
                        public void baz(int focus) throws IOException;
                        public boolean importance;
@@ -269,7 +269,7 @@
                  * @param focus The focus to find. One of {@link test.pkg2.OtherClass#FOCUS_INPUT OtherClass#FOCUS_INPUT} or
                  *         {@link test.pkg2.OtherClass#FOCUS_ACCESSIBILITY OtherClass#FOCUS_ACCESSIBILITY}.
                  * @throws java.io.IOException when blah blah blah
-                 * @throws {@link java.lang.RuntimeException} when blah blah blah
+                 * @throws {@link java.lang.RuntimeException RuntimeException} when blah blah blah
                  */
                 public void baz(int focus) throws java.io.IOException { throw new RuntimeException("Stub!"); }
                 public boolean importance;
@@ -416,78 +416,7 @@
                 /**
                  * <p>
                  * Window content may be retrieved with
-                 * {@link android.view.accessibility.AccessibilityEvent#getSource() AccessibilityEvent.getSource()}.
-                 * Mention AccessibilityRecords here.
-                 * </p>
-                 */
-                @SuppressWarnings({"unchecked", "deprecation", "all"})
-                public abstract class AccessibilityService {
-                public AccessibilityService() { throw new RuntimeException("Stub!"); }
-                }
-                """
-        )
-    }
-
-        @Test
-    fun `Rewrite relative documentation links in doc-stubs but preserve custom link text`() {
-        checkStubs(
-            docStubs = true,
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package android.accessibilityservice;
-
-                    import android.view.accessibility.AccessibilityEvent;
-                    import android.view.accessibility.AccessibilityRecord;
-
-                    /**
-                     * <p>
-                     * Window content may be retrieved with
-                     * {@link AccessibilityEvent#getSource() this_method}.
-                     * Mention AccessibilityRecords here.
-                     * </p>
-                     */
-                    @SuppressWarnings("all")
-                    public abstract class AccessibilityService {
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package android.view.accessibility;
-
-                    @SuppressWarnings("all")
-                    public final class AccessibilityEvent extends AccessibilityRecord {
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package android.view.accessibility;
-
-                    @SuppressWarnings("all")
-                    public class AccessibilityRecord {
-                        public AccessibilityNodeInfo getSource() {
-                            return null;
-                        }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package android.view.accessibility;
-                    public class AccessibilityNodeInfo {}
-                    """
-                )
-            ),
-            warnings = "",
-            source = """
-                package android.accessibilityservice;
-                import android.view.accessibility.AccessibilityEvent;
-                /**
-                 * <p>
-                 * Window content may be retrieved with
-                 * {@link android.view.accessibility.AccessibilityEvent#getSource() this_method}.
+                 * {@link android.view.accessibility.AccessibilityEvent#getSource() AccessibilityEvent#getSource()}.
                  * Mention AccessibilityRecords here.
                  * </p>
                  */
@@ -1027,37 +956,35 @@
                 )
             ),
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package android.view;
-                    import android.graphics.Insets;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public final class WindowInsets {
-                    public WindowInsets() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * Returns a copy of this WindowInsets with selected system window insets replaced
-                     * with new values.
-                     *
-                     * @param left New left inset in pixels
-                     * @param top New top inset in pixels
-                     * @param right New right inset in pixels
-                     * @param bottom New bottom inset in pixels
-                     * @return A modified copy of this WindowInsets
-                     * @deprecated use {@link android.view.WindowInsets.Builder#Builder(android.view.WindowInsets) Builder#Builder(WindowInsets)} with
-                     *             {@link android.view.WindowInsets.Builder#setSystemWindowInsets(android.graphics.Insets) Builder#setSystemWindowInsets(Insets)} instead.
-                     */
-                    @Deprecated
-                    public android.view.WindowInsets replaceSystemWindowInsets(int left, int top, int right, int bottom) { throw new RuntimeException("Stub!"); }
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public static class Builder {
-                    public Builder() { throw new RuntimeException("Stub!"); }
-                    public Builder(android.view.WindowInsets insets) { throw new RuntimeException("Stub!"); }
-                    public android.view.WindowInsets.Builder setSystemWindowInsets(android.graphics.Insets systemWindowInsets) { throw new RuntimeException("Stub!"); }
-                    }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package android.view;
+                import android.graphics.Insets;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public final class WindowInsets {
+                public WindowInsets() { throw new RuntimeException("Stub!"); }
+                /**
+                 * Returns a copy of this WindowInsets with selected system window insets replaced
+                 * with new values.
+                 *
+                 * @param left New left inset in pixels
+                 * @param top New top inset in pixels
+                 * @param right New right inset in pixels
+                 * @param bottom New bottom inset in pixels
+                 * @return A modified copy of this WindowInsets
+                 * @deprecated use {@link android.view.WindowInsets.Builder#Builder(android.view.WindowInsets) Builder#Builder(WindowInsets)} with
+                 *             {@link android.view.WindowInsets.Builder#setSystemWindowInsets(android.graphics.Insets) Builder#setSystemWindowInsets(Insets)} instead.
+                 */
+                @Deprecated
+                public android.view.WindowInsets replaceSystemWindowInsets(int left, int top, int right, int bottom) { throw new RuntimeException("Stub!"); }
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public static class Builder {
+                public Builder() { throw new RuntimeException("Stub!"); }
+                public Builder(android.view.WindowInsets insets) { throw new RuntimeException("Stub!"); }
+                public android.view.WindowInsets.Builder setSystemWindowInsets(android.graphics.Insets systemWindowInsets) { throw new RuntimeException("Stub!"); }
+                }
+                }
+                """
             )
         )
     }
@@ -1109,45 +1036,39 @@
                     """
                 )
             ),
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    import test.pkg.bar.Bar;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Foo {
-                    public Foo() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * @see test.pkg.bar.Bar
-                     */
-                    public void bar() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg.bar;
-                    import test.pkg.baz.Baz;
-                    import test.pkg.Foo;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Bar {
-                    public Bar() { throw new RuntimeException("Stub!"); }
-                    /** @see test.pkg.baz.Baz */
-                    public void baz(test.pkg.baz.Baz baz) { throw new RuntimeException("Stub!"); }
-                    /** @see test.pkg.Foo */
-                    public void foo(test.pkg.Foo foo) { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg.baz;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Baz {
-                    public Baz() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                import test.pkg.bar.Bar;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Foo {
+                public Foo() { throw new RuntimeException("Stub!"); }
+                /**
+                 * @see Bar
+                 */
+                public void bar() { throw new RuntimeException("Stub!"); }
+                }
+                """,
+                """
+                package test.pkg.bar;
+                import test.pkg.baz.Baz;
+                import test.pkg.Foo;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Bar {
+                public Bar() { throw new RuntimeException("Stub!"); }
+                /** @see Baz */
+                public void baz(test.pkg.baz.Baz baz) { throw new RuntimeException("Stub!"); }
+                /** @see Foo */
+                public void foo(test.pkg.Foo foo) { throw new RuntimeException("Stub!"); }
+                }
+                """,
+                """
+                package test.pkg.baz;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Baz {
+                public Baz() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
diff --git a/src/test/java/com/android/tools/metalava/stub/StubsTest.kt b/src/test/java/com/android/tools/metalava/stub/StubsTest.kt
index 84249a0..cef474e 100644
--- a/src/test/java/com/android/tools/metalava/stub/StubsTest.kt
+++ b/src/test/java/com/android/tools/metalava/stub/StubsTest.kt
@@ -18,15 +18,13 @@
 
 package com.android.tools.metalava.stub
 
-import com.android.tools.lint.checks.infrastructure.LintDetectorTest.source
 import com.android.tools.lint.checks.infrastructure.TestFile
 import com.android.tools.metalava.ARG_CHECK_API
-import com.android.tools.metalava.ARG_EXCLUDE_ALL_ANNOTATIONS
+import com.android.tools.metalava.ARG_EXCLUDE_ANNOTATIONS
 import com.android.tools.metalava.ARG_EXCLUDE_DOCUMENTATION_FROM_STUBS
 import com.android.tools.metalava.ARG_HIDE_PACKAGE
 import com.android.tools.metalava.ARG_KOTLIN_STUBS
 import com.android.tools.metalava.ARG_PASS_THROUGH_ANNOTATION
-import com.android.tools.metalava.ARG_EXCLUDE_ANNOTATION
 import com.android.tools.metalava.ARG_UPDATE_API
 import com.android.tools.metalava.DriverTest
 import com.android.tools.metalava.FileFormat
@@ -68,7 +66,7 @@
         check(
             sourceFiles = sourceFiles,
             showAnnotations = showAnnotations,
-            stubFiles = arrayOf(java(source)),
+            stubs = arrayOf(source),
             compatibilityMode = compatibilityMode,
             expectedIssues = warnings,
             checkCompilation = true,
@@ -177,39 +175,33 @@
                 )
             ),
             expectedIssues = "",
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public interface MyInterface2<T extends java.lang.Number> extends test.pkg.MyBaseInterface {
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public abstract static class Range<T extends java.lang.Comparable<? super T>> {
-                    public Range() { throw new RuntimeException("Stub!"); }
-                    }
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public static class TtsSpan<C extends test.pkg.MyInterface<?>> {
-                    public TtsSpan() { throw new RuntimeException("Stub!"); }
-                    }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public interface MyInterface<T> extends test.pkg.MyBaseInterface {
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public interface MyBaseInterface {
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public interface MyInterface2<T extends java.lang.Number> extends test.pkg.MyBaseInterface {
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public abstract static class Range<T extends java.lang.Comparable<? super T>> {
+                public Range() { throw new RuntimeException("Stub!"); }
+                }
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public static class TtsSpan<C extends test.pkg.MyInterface<?>> {
+                public TtsSpan() { throw new RuntimeException("Stub!"); }
+                }
+                }
+                """,
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public interface MyInterface<T> extends test.pkg.MyBaseInterface {
+                }
+                """,
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public interface MyBaseInterface {
+                }
+                """
             )
         )
     }
@@ -462,13 +454,13 @@
 
                     @SuppressWarnings("ALL")
                     public abstract class Foo {
-                        /** @deprecated */ @Deprecated private static final long field1 = 5;
-                        /** @deprecated */ @Deprecated private static volatile long field2 = 5;
-                        /** @deprecated */ @Deprecated public static strictfp final synchronized void method1() { }
-                        /** @deprecated */ @Deprecated public static final synchronized native void method2();
-                        /** @deprecated */ @Deprecated protected static final class Inner1 { }
-                        /** @deprecated */ @Deprecated protected static abstract  class Inner2 { }
-                        /** @deprecated */ @Deprecated protected interface Inner3 {
+                        @Deprecated private static final long field1 = 5;
+                        @Deprecated private static volatile long field2 = 5;
+                        @Deprecated public static strictfp final synchronized void method1() { }
+                        @Deprecated public static final synchronized native void method2();
+                        @Deprecated protected static final class Inner1 { }
+                        @Deprecated protected static abstract  class Inner2 { }
+                        @Deprecated protected interface Inner3 {
                             protected default void method3() { }
                             static void method4() { }
                         }
@@ -482,25 +474,20 @@
                 @SuppressWarnings({"unchecked", "deprecation", "all"})
                 public abstract class Foo {
                 public Foo() { throw new RuntimeException("Stub!"); }
-                /** @deprecated */
                 @Deprecated
                 public static final synchronized void method1() { throw new RuntimeException("Stub!"); }
-                /** @deprecated */
                 @Deprecated
                 public static final synchronized native void method2();
-                /** @deprecated */
                 @SuppressWarnings({"unchecked", "deprecation", "all"})
                 @Deprecated
                 protected static final class Inner1 {
                 protected Inner1() { throw new RuntimeException("Stub!"); }
                 }
-                /** @deprecated */
                 @SuppressWarnings({"unchecked", "deprecation", "all"})
                 @Deprecated
                 protected abstract static class Inner2 {
                 protected Inner2() { throw new RuntimeException("Stub!"); }
                 }
-                /** @deprecated */
                 @SuppressWarnings({"unchecked", "deprecation", "all"})
                 @Deprecated
                 protected static interface Inner3 {
@@ -1370,7 +1357,7 @@
                     @android.annotation.Nullable
                     public java.lang.String getProperty2() { throw new RuntimeException("Stub!"); }
                     /** property doc */
-                    public void setProperty2(@android.annotation.Nullable java.lang.String property2) { throw new RuntimeException("Stub!"); }
+                    public void setProperty2(@android.annotation.Nullable java.lang.String p) { throw new RuntimeException("Stub!"); }
                     @android.annotation.NonNull
                     public java.lang.String getProperty1() { throw new RuntimeException("Stub!"); }
                     public int someField2;
@@ -1876,8 +1863,8 @@
                       }
                     }
                     """,
-            stubFiles = arrayOf(
-                java(
+            stubs =
+                arrayOf(
                     """
                     package my.pkg;
                     @SuppressWarnings({"unchecked", "deprecation", "all"})
@@ -1886,7 +1873,6 @@
                     }
                     """
                 )
-            )
         )
     }
 
@@ -1911,16 +1897,15 @@
                     }
                     """,
             docStubs = true,
-            stubFiles = arrayOf(
-                java(
+            stubs =
+            arrayOf(
+                """
+                    package my.pkg;
+                    @SuppressWarnings({"unchecked", "deprecation", "all"})
+                    public class String {
+                    public String(@androidx.annotation.NonNull char[] value) { throw new RuntimeException("Stub!"); }
+                    }
                     """
-                        package my.pkg;
-                        @SuppressWarnings({"unchecked", "deprecation", "all"})
-                        public class String {
-                        public String(@androidx.annotation.NonNull char[] value) { throw new RuntimeException("Stub!"); }
-                        }
-                    """
-                )
             )
         )
     }
@@ -1945,29 +1930,25 @@
                       }
                     }
                     """,
-            stubFiles = if (SUPPORT_TYPE_USE_ANNOTATIONS) {
+            stubs = if (SUPPORT_TYPE_USE_ANNOTATIONS) {
                 arrayOf(
-                    java(
-                        """
-                        package my.pkg;
-                        @SuppressWarnings({"unchecked", "deprecation", "all"})
-                        public class String {
-                        public String(char @androidx.annotation.NonNull [] value) { throw new RuntimeException("Stub!"); }
-                        }
-                        """
-                    )
+                    """
+                    package my.pkg;
+                    @SuppressWarnings({"unchecked", "deprecation", "all"})
+                    public class String {
+                    public String(char @androidx.annotation.NonNull [] value) { throw new RuntimeException("Stub!"); }
+                    }
+                    """
                 )
             } else {
                 arrayOf(
-                    java(
-                        """
-                        package my.pkg;
-                        @SuppressWarnings({"unchecked", "deprecation", "all"})
-                        public class String {
-                        public String(char[] value) { throw new RuntimeException("Stub!"); }
-                        }
-                        """
-                    )
+                    """
+                    package my.pkg;
+                    @SuppressWarnings({"unchecked", "deprecation", "all"})
+                    public class String {
+                    public String(char[] value) { throw new RuntimeException("Stub!"); }
+                    }
+                    """
                 )
             }
         )
@@ -2003,17 +1984,14 @@
                       }
                     }
                     """,
-            stubFiles = arrayOf(
-                java(
+            stubs = arrayOf(
                     """
                     package my.pkg;
                     @SuppressWarnings({"unchecked", "deprecation", "all"})
                     public class String {
                     public String(@libcore.util.NonNull char[] value) { throw new RuntimeException("Stub!"); }
                     }
-                    """
-                )
-            )
+                    """)
         )
     }
 
@@ -2055,52 +2033,6 @@
     }
 
     @Test
-    fun `Skip RequiresApi annotation`() {
-        check(
-            extraArguments = arrayOf(
-                ARG_EXCLUDE_ANNOTATION, "androidx.annotation.RequiresApi"
-            ),
-            sourceFiles = arrayOf(
-                java(
-                    """
-                    package my.pkg;
-                    public class MyClass {
-                        @androidx.annotation.RequiresApi(21)
-                        public void testMethod() {}
-                    }
-                    """
-                ),
-                requiresApiSource
-            ),
-            expectedIssues = "",
-            api = """
-                    package androidx.annotation {
-                      public abstract class RequiresApi implements java.lang.annotation.Annotation {
-                      }
-                    }
-                    package my.pkg {
-                      public class MyClass {
-                        ctor public MyClass();
-                        method public void testMethod();
-                      }
-                    }
-                    """,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package my.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class MyClass {
-                    public MyClass() { throw new RuntimeException("Stub!"); }
-                    public void testMethod() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
-            )
-        )
-    }
-
-    @Test
     fun `Test inaccessible constructors`() {
         // If the constructors of a class are not visible, and the class has subclasses,
         // those subclass stubs will need to reference these inaccessible constructors.
@@ -2160,43 +2092,35 @@
                       }
                     }
                     """,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class MyClass1 {
-                    MyClass1() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class MySubClass1 extends test.pkg.MyClass1 {
-                    MySubClass1() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class MyClass2 {
-                    MyClass2() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class MySubClass2 extends test.pkg.MyClass2 {
-                    public MySubClass2() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class MyClass1 {
+                MyClass1() { throw new RuntimeException("Stub!"); }
+                }
+                """,
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class MySubClass1 extends test.pkg.MyClass1 {
+                MySubClass1() { throw new RuntimeException("Stub!"); }
+                }
+                """,
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class MyClass2 {
+                MyClass2() { throw new RuntimeException("Stub!"); }
+                }
+                """,
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class MySubClass2 extends test.pkg.MyClass2 {
+                public MySubClass2() { throw new RuntimeException("Stub!"); }
+                }
+                """
             ),
             stubsSourceList = """
                 TESTROOT/stubs/test/pkg/MyClass1.java
@@ -2632,16 +2556,14 @@
                     """
                 )
             ),
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package android.content.res;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public interface XmlResourceParser extends org.xmlpull.v1.XmlPullParser,  android.util.AttributeSet, java.lang.AutoCloseable {
-                    public void close();
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package android.content.res;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public interface XmlResourceParser extends org.xmlpull.v1.XmlPullParser,  android.util.AttributeSet, java.lang.AutoCloseable {
+                public void close();
+                }
+                """
             )
         )
     }
@@ -3467,22 +3389,18 @@
                   }
                 }
                 """,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    /** My package docs */
-                    package test.pkg;
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public abstract class Class1 {
-                    public Class1() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                /** My package docs */
+                package test.pkg;
+                """,
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public abstract class Class1 {
+                public Class1() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -3511,31 +3429,27 @@
                   }
                 }
                 """,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    @androidx.annotation.RestrictTo(androidx.annotation.RestrictTo.Scope.SUBCLASSES)
-                    package test.pkg;
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public abstract class Class1 {
-                    public Class1() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                @androidx.annotation.RestrictTo(androidx.annotation.RestrictTo.Scope.SUBCLASSES)
+                package test.pkg;
+                """,
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public abstract class Class1 {
+                public Class1() { throw new RuntimeException("Stub!"); }
+                }
+                """
             ),
             extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation")
         )
     }
 
     @Test
-    fun `Ensure we emit both deprecated javadoc and annotation with exclude-all-annotations`() {
+    fun `Ensure we emit both deprecated javadoc and annotation with exclude-annotations`() {
         check(
-            extraArguments = arrayOf(ARG_EXCLUDE_ALL_ANNOTATIONS),
+            extraArguments = arrayOf(ARG_EXCLUDE_ANNOTATIONS),
             compatibilityMode = false,
             sourceFiles = arrayOf(
                 java(
@@ -3553,21 +3467,19 @@
                     """
                 )
             ),
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Foo {
-                    public Foo() { throw new RuntimeException("Stub!"); }
-                    /**
-                     * @deprecated Use checkPermission instead.
-                     */
-                    @Deprecated
-                    protected boolean inClass(java.lang.String name) { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Foo {
+                public Foo() { throw new RuntimeException("Stub!"); }
+                /**
+                 * @deprecated Use checkPermission instead.
+                 */
+                @Deprecated
+                protected boolean inClass(java.lang.String name) { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -3575,7 +3487,7 @@
     @Test
     fun `Ensure we emit runtime and deprecated annotations in stubs with exclude-annotations`() {
         check(
-            extraArguments = arrayOf(ARG_EXCLUDE_ALL_ANNOTATIONS),
+            extraArguments = arrayOf(ARG_EXCLUDE_ANNOTATIONS),
             compatibilityMode = false,
             sourceFiles = arrayOf(
                 java(
@@ -3622,19 +3534,17 @@
                     """
                 )
             ),
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    /** @deprecated */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    @Deprecated
-                    @test.pkg.MyRuntimeRetentionAnnotation
-                    public class Foo {
-                    private Foo() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                /** @deprecated */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                @Deprecated
+                @test.pkg.MyRuntimeRetentionAnnotation
+                public class Foo {
+                private Foo() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -3691,23 +3601,21 @@
                     """
                 )
             ),
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    /** @deprecated */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    @Deprecated
-                    @test.pkg.MyClassRetentionAnnotation
-                    @test.pkg.MyRuntimeRetentionAnnotation
-                    public class Foo {
-                    private Foo() { throw new RuntimeException("Stub!"); }
-                    @Deprecated
-                    public void bar() { throw new RuntimeException("Stub!"); }
-                    @Deprecated protected int foo;
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                /** @deprecated */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                @Deprecated
+                @test.pkg.MyClassRetentionAnnotation
+                @test.pkg.MyRuntimeRetentionAnnotation
+                public class Foo {
+                private Foo() { throw new RuntimeException("Stub!"); }
+                @Deprecated
+                public void bar() { throw new RuntimeException("Stub!"); }
+                @Deprecated protected int foo;
+                }
+                """
             )
         )
     }
@@ -3892,7 +3800,7 @@
         check(
             extraArguments = arrayOf(
                 ARG_UPDATE_API,
-                ARG_EXCLUDE_ALL_ANNOTATIONS
+                ARG_EXCLUDE_ANNOTATIONS
             ),
             compatibilityMode = false,
             sourceFiles = arrayOf(
@@ -3919,11 +3827,10 @@
               }
             }
             """,
-            stubFiles = arrayOf(
-                source(
-                    "test/pkg/Foo.java",
-                    "This file should not be generated since --update-api is supplied."
-                )
+            stubs = arrayOf(
+                """
+                This file should not be generated since --update-api is supplied.
+                """
             )
         )
     }
@@ -3933,7 +3840,7 @@
         check(
             extraArguments = arrayOf(
                 ARG_CHECK_API,
-                ARG_EXCLUDE_ALL_ANNOTATIONS
+                ARG_EXCLUDE_ANNOTATIONS
             ),
             compatibilityMode = false,
             sourceFiles = arrayOf(
@@ -4049,27 +3956,23 @@
                   }
                 }
                 """,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class PublicApi {
-                    public PublicApi() { throw new RuntimeException("Stub!"); }
-                    public test.pkg.HiddenType getHiddenType() { throw new RuntimeException("Stub!"); }
-                    public test.pkg.HiddenType4 getHiddenType4() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class PublicInterface {
-                    public PublicInterface() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class PublicApi {
+                public PublicApi() { throw new RuntimeException("Stub!"); }
+                public test.pkg.HiddenType getHiddenType() { throw new RuntimeException("Stub!"); }
+                public test.pkg.HiddenType4 getHiddenType4() { throw new RuntimeException("Stub!"); }
+                }
+                """,
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class PublicInterface {
+                public PublicInterface() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -4106,16 +4009,14 @@
                   }
                 }
                 """,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class PublicApi {
-                    public PublicApi(test.pkg.PublicApi.HiddenInner inner) { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class PublicApi {
+                public PublicApi(test.pkg.PublicApi.HiddenInner inner) { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -4173,19 +4074,17 @@
                   }
                 }
                 """,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    /** @deprecated */
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    @Deprecated
-                    public class BasicPoolEntryRef extends test.pkg.WeakRef<test.pkg.BasicPoolEntry> {
-                    @Deprecated
-                    public BasicPoolEntryRef(test.pkg.BasicPoolEntry entry) { super((test.pkg.BasicPoolEntry)null); throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                /** @deprecated */
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                @Deprecated
+                public class BasicPoolEntryRef extends test.pkg.WeakRef<test.pkg.BasicPoolEntry> {
+                @Deprecated
+                public BasicPoolEntryRef(test.pkg.BasicPoolEntry entry) { super((test.pkg.BasicPoolEntry)null); throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -4251,25 +4150,21 @@
                   }
                 }
                 """,
-            stubFiles = arrayOf(
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Orange {
-                    private Orange() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                ),
-                java(
-                    """
-                    package test.pkg;
-                    @SuppressWarnings({"unchecked", "deprecation", "all"})
-                    public class Alpha extends test.pkg.Charlie<test.pkg.Orange> {
-                    private Alpha() { throw new RuntimeException("Stub!"); }
-                    }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Orange {
+                private Orange() { throw new RuntimeException("Stub!"); }
+                }
+                """,
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class Alpha extends test.pkg.Charlie<test.pkg.Orange> {
+                private Alpha() { throw new RuntimeException("Stub!"); }
+                }
+                """
             )
         )
     }
@@ -4378,31 +4273,28 @@
                 """
                 )
             ),
-            stubFiles = arrayOf(
-                kotlin(
-                    """
-                        /* My file header */
-                        // Another comment
-                        package test.pkg
-                        /** My class doc */
-                        @file:Suppress("ALL")
-                        class Kotlin : test.pkg.Parent() {
-                        open fun Kotlin(open property1: java.lang.String!, open arg2: int): test.pkg.Kotlin! = error("Stub!")
-                        open fun method(): java.lang.String = error("Stub!")
-                        /** My method doc */
-                        open fun otherMethod(open ok: boolean, open times: int): void = error("Stub!")
-                        }
-                    """
-                ),
-                kotlin(
-                    """
-                        package test.pkg
-                        @file:Suppress("ALL")
-                        open class ExtendableClass<T> {
-                        open fun ExtendableClass(): test.pkg.ExtendableClass<T!>! = error("Stub!")
-                        }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                    /* My file header */
+                    // Another comment
+                    package test.pkg
+                    /** My class doc */
+                    @file:Suppress("ALL")
+                    class Kotlin : test.pkg.Parent() {
+                    open fun Kotlin(open property1: java.lang.String!, open arg2: int): test.pkg.Kotlin! = error("Stub!")
+                    open fun method(): java.lang.String = error("Stub!")
+                    /** My method doc */
+                    open fun otherMethod(open ok: boolean, open times: int): void = error("Stub!")
+                    open fun getProperty1(): java.lang.String = error("Stub!")
+                    }
+                """,
+                """
+                    package test.pkg
+                    @file:Suppress("ALL")
+                    open class ExtendableClass<T> {
+                    open fun ExtendableClass(): test.pkg.ExtendableClass<T!>! = error("Stub!")
+                    }
+                """
             )
         )
     }
@@ -4423,16 +4315,14 @@
                     interface MyInterface2
                 """)
             ),
-            stubFiles = arrayOf(
-                kotlin(
-                    """
-                        package test.pkg
-                        @file:Suppress("ALL")
-                        class MainClass : test.pkg.MyParentClass(), test.pkg.MyInterface1, test.pkg.MyInterface2 {
-                        open fun MainClass(): test.pkg.MainClass! = error("Stub!")
-                        }
-                    """
-                )
+            stubs = arrayOf(
+                """
+                    package test.pkg
+                    @file:Suppress("ALL")
+                    class MainClass : test.pkg.MyParentClass(), test.pkg.MyInterface1, test.pkg.MyInterface2 {
+                    open fun MainClass(): test.pkg.MainClass! = error("Stub!")
+                    }
+                """
             )
         )
     }
@@ -4472,48 +4362,14 @@
                     """
                 )
             ),
-            stubFiles = arrayOf(
-                java(
-                    """
-                        package test.pkg;
-                        @SuppressWarnings({"unchecked", "deprecation", "all"})
-                        public class MainClass extends test.pkg.MyParentClass implements test.pkg.MyInterface1, test.pkg.MyInterface2 {
-                        public MainClass() { throw new RuntimeException("Stub!"); }
-                        }
-                    """
-                )
-            )
-        )
-    }
-
-    @Test
-    fun `NaN constants`() {
-        check(
-            checkCompilation = true,
-            sourceFiles = arrayOf(
-                java(
-                    """
+            stubs = arrayOf(
+                """
                     package test.pkg;
-
-                    public class MyClass {
-                        public static final float floatNaN = 0.0f / 0.0f;
-                        public static final double doubleNaN = 0.0d / 0.0;
+                    @SuppressWarnings({"unchecked", "deprecation", "all"})
+                    public class MainClass extends test.pkg.MyParentClass implements test.pkg.MyInterface1, test.pkg.MyInterface2 {
+                    public MainClass() { throw new RuntimeException("Stub!"); }
                     }
-                    """
-                )
-            ),
-            stubFiles = arrayOf(
-                java(
-                    """
-                        package test.pkg;
-                        @SuppressWarnings({"unchecked", "deprecation", "all"})
-                        public class MyClass {
-                        public MyClass() { throw new RuntimeException("Stub!"); }
-                        public static final double doubleNaN = (0.0/0.0);
-                        public static final float floatNaN = (0.0f/0.0f);
-                        }
-                    """
-                )
+                """
             )
         )
     }
diff --git a/stub-annotations/src/main/java/androidx/annotation/DisplayContext.java b/stub-annotations/src/main/java/androidx/annotation/DisplayContext.java
deleted file mode 100644
index 342a642..0000000
--- a/stub-annotations/src/main/java/androidx/annotation/DisplayContext.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.annotation;
-
-import static java.lang.annotation.ElementType.CONSTRUCTOR;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/** Stub only annotation. Do not use directly. */
-@Retention(CLASS)
-@Target({METHOD, CONSTRUCTOR, TYPE, PARAMETER})
-public @interface DisplayContext { }
diff --git a/stub-annotations/src/main/java/androidx/annotation/NonUiContext.java b/stub-annotations/src/main/java/androidx/annotation/NonUiContext.java
deleted file mode 100644
index 846c8ba..0000000
--- a/stub-annotations/src/main/java/androidx/annotation/NonUiContext.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.annotation;
-
-import static java.lang.annotation.ElementType.CONSTRUCTOR;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/** Stub only annotation. Do not use directly. */
-@Retention(CLASS)
-@Target({METHOD, CONSTRUCTOR, TYPE, PARAMETER})
-public @interface NonUiContext { }
diff --git a/stub-annotations/src/main/java/androidx/annotation/UiContext.java b/stub-annotations/src/main/java/androidx/annotation/UiContext.java
deleted file mode 100644
index e438520..0000000
--- a/stub-annotations/src/main/java/androidx/annotation/UiContext.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.annotation;
-
-import static java.lang.annotation.ElementType.CONSTRUCTOR;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/** Stub only annotation. Do not use directly. */
-@Retention(CLASS)
-@Target({METHOD, CONSTRUCTOR, TYPE, PARAMETER})
-public @interface UiContext { }