diff --git a/cli/build.gradle.kts b/cli/build.gradle.kts index d3abb9f..975abd2 100644 --- a/cli/build.gradle.kts +++ b/cli/build.gradle.kts @@ -4,7 +4,8 @@ plugins { alias(libs.plugins.shadow) } -val ANDROID = "_android_lib_" +val ANDROID_LIB = "_android_lib_" +val ANDROID_DESCRIPTORS = "_android_descriptors_" tasks { shadowJar { @@ -16,16 +17,23 @@ tasks { test { systemProperty("classes", sourceSets.main.get().kotlin.classesDirectory.get().asFile.path) systemProperty("libraries", configurations.getAt("testRuntimeClasspath").asPath) - systemProperty("android-libraries", configurations.getAt(ANDROID).asPath) + systemProperty("android-libraries", configurations.getAt(ANDROID_LIB).asPath) + systemProperty("android-descriptors", configurations.getAt(ANDROID_DESCRIPTORS).asPath) } } -configurations.create(ANDROID).isTransitive = false +configurations.create(ANDROID_LIB).isTransitive = false +configurations.create(ANDROID_DESCRIPTORS).isTransitive = false dependencies { implementation(libs.clikt) implementation(libs.protobuf.java) implementation(projects.core) - add(ANDROID, libs.timber) + addProvider(ANDROID_DESCRIPTORS, libs.gummy.bears) { + artifact { + extension = "expediter" + } + } + add(ANDROID_LIB, libs.timber) } diff --git a/cli/src/main/kotlin/com/toasttab/expediter/cli/ExpediterCliCommand.kt b/cli/src/main/kotlin/com/toasttab/expediter/cli/ExpediterCliCommand.kt index c2908ea..1058061 100644 --- a/cli/src/main/kotlin/com/toasttab/expediter/cli/ExpediterCliCommand.kt +++ b/cli/src/main/kotlin/com/toasttab/expediter/cli/ExpediterCliCommand.kt @@ -33,6 +33,7 @@ import com.toasttab.expediter.types.ClassfileSource import com.toasttab.expediter.types.ClassfileSourceType import protokt.v1.toasttab.expediter.v1.TypeDescriptors import java.io.File +import java.util.zip.GZIPInputStream class ExpediterCliCommand : CliktCommand() { val output: String by option().required() @@ -43,13 +44,13 @@ class ExpediterCliCommand : CliktCommand() { val platformDescriptors: String? by option() val projectName: String by option().default("project") - fun ignores() = ignoresFiles.flatMap { + private fun ignores() = ignoresFiles.flatMap { File(it).inputStream().use { IssueReport.fromJson(it).issues } }.toSet() - fun appTypes() = ClasspathApplicationTypesProvider( + private fun appTypes() = ClasspathApplicationTypesProvider( projectClasses.map { ClassfileSource(File(it), ClassfileSourceType.SOURCE_SET, it) } + libraries.map { ClassfileSource(File(it), ClassfileSourceType.EXTERNAL_DEPENDENCY, it) } ) @@ -62,7 +63,7 @@ class ExpediterCliCommand : CliktCommand() { JvmTypeProvider.forTarget(jvm) } else if (platformFile != null) { InMemoryPlatformTypeProvider( - platformFile.inputStream().use { + GZIPInputStream(platformFile.inputStream().buffered()).use { TypeDescriptors.deserialize(it) }.types ) diff --git a/cli/src/test/kotlin/com/toasttab/expediter/cli/ExpediterCliCommandIntegrationTest.kt b/cli/src/test/kotlin/com/toasttab/expediter/cli/ExpediterCliCommandIntegrationTest.kt index e6ca889..a13cdff 100644 --- a/cli/src/test/kotlin/com/toasttab/expediter/cli/ExpediterCliCommandIntegrationTest.kt +++ b/cli/src/test/kotlin/com/toasttab/expediter/cli/ExpediterCliCommandIntegrationTest.kt @@ -17,6 +17,9 @@ package com.toasttab.expediter.cli import com.toasttab.expediter.issue.Issue import com.toasttab.expediter.issue.IssueReport +import com.toasttab.expediter.types.MemberAccess +import com.toasttab.expediter.types.MemberSymbolicReference +import com.toasttab.expediter.types.MethodAccessType import org.junit.jupiter.api.Test import org.junit.jupiter.api.io.TempDir import strikt.api.expectThat @@ -56,11 +59,46 @@ class ExpediterCliCommandIntegrationTest { } @Test - fun `run on android library`() { + fun `run on self with descriptors`() { val output = dir.resolve("expediter.json") + println(System.getProperty("android-descriptors")) + ExpediterCliCommand().main( - listOf( + System.getProperty("libraries").split(File.pathSeparatorChar).flatMap { + listOf("--libraries", it) + } + listOf( + "--project-classes", System.getProperty("classes"), + "--output", output.toString(), + "--platform-descriptors", System.getProperty("android-descriptors") + ) + ) + + val report = output.inputStream().use { + IssueReport.fromJson(it) + } + + expectThat(report.issues).contains( + Issue.MissingMember( + "com/toasttab/expediter/types/InspectedTypes", + MemberAccess.MethodAccess( + "java/util/concurrent/ConcurrentMap", + ref = MemberSymbolicReference( + "computeIfAbsent", + "(Ljava/lang/Object;Ljava/util/function/Function;)Ljava/lang/Object;" + ), + accessType = MethodAccessType.INTERFACE + ) + ) + ) + } + + @Test + fun `run on android library`() { + val output = dir.resolve("expediter.json") + + main( + arrayOf( "--project-classes", System.getProperty("android-libraries"), "--output", diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b94df41..69ec66f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,6 +10,7 @@ spotless = "6.25.0" protokt = "1.0.0-beta.1" protobuf = "4.26.1" shadow = "8.1.1" +gummy-bears = "0.8.0" # test junit = "5.10.2" @@ -36,8 +37,10 @@ junit = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" } strikt-core = { module = "io.strikt:strikt-core", version.ref = "strikt" } testkit-junit5 = { module = "com.toasttab.gradle.testkit:junit5", version.ref = "testkit-plugin" } timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" } +gummy-bears = { module = "com.toasttab.android:gummy-bears-api-21", version.ref = "gummy-bears" } [plugins] +build-config = { id = "com.github.gmazzo.buildconfig", version = "5.3.5" } serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin"} gradle-publish = { id = "com.gradle.plugin-publish", version = "1.2.1" } testkit-plugin = { id = "com.toasttab.testkit" , version.ref = "testkit-plugin" } diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index f40f203..0e955c9 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -3,6 +3,7 @@ plugins { `kotlin-dsl` `plugin-publishing-conventions` alias(libs.plugins.testkit.plugin) + alias(libs.plugins.build.config) } dependencies { @@ -19,6 +20,11 @@ testkitTests { replaceToken("PROTOBUF_VERSION", libs.versions.protobuf.get()) } +buildConfig { + packageName.set("com.toasttab.expediter.gradle") + buildConfigField("String", "GUMMY_BEARS_VERSION", "\"${libs.versions.gummy.bears.get()}\"") +} + gradlePlugin { plugins { create("expediter") { diff --git a/plugin/src/main/kotlin/com/toasttab/expediter/gradle/config/AndroidSpec.kt b/plugin/src/main/kotlin/com/toasttab/expediter/gradle/config/AndroidSpec.kt index 65f6d2a..03336d3 100644 --- a/plugin/src/main/kotlin/com/toasttab/expediter/gradle/config/AndroidSpec.kt +++ b/plugin/src/main/kotlin/com/toasttab/expediter/gradle/config/AndroidSpec.kt @@ -1,9 +1,11 @@ package com.toasttab.expediter.gradle.config +import com.toasttab.expediter.gradle.BuildConfig + open class AndroidSpec { var sdk: Int? = null var coreLibraryDesugaring: Boolean = false - var gummyBearsVersion: String = "0.8.0" + var gummyBearsVersion: String = BuildConfig.GUMMY_BEARS_VERSION fun artifact(): String { val base = "com.toasttab.android:gummy-bears-api-$sdk:$gummyBearsVersion"