check-flagged-apis: parse API signature files
Teach check-flagged-apis to extract flagged APIs from API signature files.
To keep things simple, only consider fields for now: support for classes
and methods will be added in a later CL.
Note: `m frameworks-base-api-current.txt` will generate an API signature
file that includes both the platform and mainline APIs.
Bug: 334870672
Test: atest --host check-flagged-apis-test
Test: check-flagged-apis --api-signature out/target/product/mainline_x86/obj/ETC/frameworks-base-api-current.txt_intermediates/frameworks-base-api-current.txt
Change-Id: Ic244b896672569f44af793796189b34c1f9d0c36
diff --git a/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt b/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt
index af8be11..5fede7b 100644
--- a/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt
+++ b/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt
@@ -17,8 +17,16 @@
package com.android.checkflaggedapis
+import com.android.tools.metalava.model.BaseItemVisitor
+import com.android.tools.metalava.model.FieldItem
+import com.android.tools.metalava.model.text.ApiFile
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.ProgramResult
+import com.github.ajalt.clikt.parameters.options.help
+import com.github.ajalt.clikt.parameters.options.option
+import com.github.ajalt.clikt.parameters.options.required
+import com.github.ajalt.clikt.parameters.types.path
+import java.io.InputStream
/**
* Class representing the fully qualified name of a class, method or field.
@@ -70,11 +78,58 @@
override fun toString(): String = name.toString()
}
-class CheckCommand : CliktCommand() {
+class CheckCommand :
+ CliktCommand(
+ help =
+ """
+Check that all flagged APIs are used in the correct way.
+
+This tool reads the API signature file and checks that all flagged APIs are used in the correct way.
+
+The tool will exit with a non-zero exit code if any flagged APIs are found to be used in the incorrect way.
+""") {
+ private val apiSignaturePath by
+ option("--api-signature")
+ .help(
+ """
+ Path to API signature file.
+ Usually named *current.txt.
+ Tip: `m frameworks-base-api-current.txt` will generate a file that includes all platform and mainline APIs.
+ """)
+ .path(mustExist = true, canBeDir = false, mustBeReadable = true)
+ .required()
+
override fun run() {
- println("hello world")
+ @Suppress("UNUSED_VARIABLE")
+ val flaggedSymbols =
+ apiSignaturePath.toFile().inputStream().use {
+ parseApiSignature(apiSignaturePath.toString(), it)
+ }
throw ProgramResult(0)
}
}
+internal fun parseApiSignature(path: String, input: InputStream): Set<Pair<Symbol, Flag>> {
+ // TODO(334870672): add support for classes and metods
+ val output = mutableSetOf<Pair<Symbol, Flag>>()
+ val visitor =
+ object : BaseItemVisitor() {
+ override fun visitField(field: FieldItem) {
+ val flag =
+ field.modifiers
+ .findAnnotation("android.annotation.FlaggedApi")
+ ?.findAttribute("value")
+ ?.value
+ ?.value() as? String
+ if (flag != null) {
+ val symbol = Symbol.create(field.baselineElementId())
+ output.add(Pair(symbol, Flag(flag)))
+ }
+ }
+ }
+ val codebase = ApiFile.parseApi(path, input)
+ codebase.accept(visitor)
+ return output
+}
+
fun main(args: Array<String>) = CheckCommand().main(args)