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. {@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. {@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 */
- * 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 */
+ * 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 { }