Skip to content

Commit

Permalink
Split the Zipline API validator into its own module (#1060)
Browse files Browse the repository at this point in the history
After implementation there isn't much code shared with the
Kotlin compiler plugin. Lets keep these separate for
simplicity, and to avoid dragging compiler plugin dependencies
into the CLI.
  • Loading branch information
swankjesse committed Jun 26, 2023
1 parent 0fa3347 commit 7d087ba
Show file tree
Hide file tree
Showing 21 changed files with 121 additions and 100 deletions.
5 changes: 3 additions & 2 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
rootProject.name = "zipline-root"

include(":zipline")
include(":zipline-testing")
include(":zipline-api-validator")
include(":zipline-bytecode")
include(":zipline-cli")
include(":zipline-gradle-plugin")
include(":zipline-kotlin-plugin")
include(":zipline-kotlin-plugin-tests")
include(":zipline-bytecode")
include(":zipline-loader")
include(":zipline-loader-testing")
include(":zipline-profiler")
include(":zipline-testing")

enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
45 changes: 45 additions & 0 deletions zipline-api-validator/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import com.vanniktech.maven.publish.JavadocJar
import com.vanniktech.maven.publish.KotlinJvm
import com.vanniktech.maven.publish.MavenPublishBaseExtension
import org.gradle.api.plugins.JavaPlugin.TEST_TASK_NAME
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.TEST_COMPILATION_NAME

plugins {
kotlin("jvm")
kotlin("kapt")
id("com.vanniktech.maven.publish.base")
}

dependencies {
api(kotlin("compiler-embeddable"))
api(libs.okio.core)

kapt(libs.auto.service.compiler)
compileOnly(libs.auto.service.annotations)

testImplementation(projects.zipline)
testImplementation(libs.assertk)
testImplementation(libs.junit)
testImplementation(libs.kotlin.test)
}

// In order to simplify writing test schemas, inject the test sources and
// test classpath as properties into the test runtime. This allows testing
// the FIR-based parser on sources written inside the test case. Cool!
tasks.named<Test>(TEST_TASK_NAME).configure {
val compilation = kotlin.target.compilations.getByName(TEST_COMPILATION_NAME)

val sources = compilation.defaultSourceSet.kotlin.sourceDirectories.files
systemProperty("zipline.internal.sources", sources.joinToString(separator = File.pathSeparator))

val classpath = project.configurations.getByName(compilation.compileDependencyConfigurationName).files
systemProperty("zipline.internal.classpath", classpath.joinToString(separator = File.pathSeparator))
}

configure<MavenPublishBaseExtension> {
configure(
KotlinJvm(
javadocJar = JavadocJar.Empty()
)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package app.cash.zipline.api.compatibility
package app.cash.zipline.api.validator

import app.cash.zipline.api.fir.FirZiplineApi
import app.cash.zipline.api.toml.TomlZiplineApi
import app.cash.zipline.api.toml.TomlZiplineFunction
import app.cash.zipline.api.toml.TomlZiplineService
import app.cash.zipline.api.validator.fir.FirZiplineApi
import app.cash.zipline.api.validator.toml.TomlZiplineApi
import app.cash.zipline.api.validator.toml.TomlZiplineFunction
import app.cash.zipline.api.validator.toml.TomlZiplineService

sealed interface ApiCompatibilityDecision

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package app.cash.zipline.api.fir
package app.cash.zipline.api.validator.fir

import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirClass
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package app.cash.zipline.api.fir
package app.cash.zipline.api.validator.fir

import app.cash.zipline.kotlin.signatureHash
data class FirZiplineApi(
val services: List<FirZiplineService>,
)

/** An interface that extends from ZiplineService. */
data class FirZiplineService(
val name: String,
val functions: List<FirZiplineFunction>,
)

data class FirZiplineFunction(
val id: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package app.cash.zipline.api.fir
package app.cash.zipline.api.validator.fir

import app.cash.zipline.kotlin.BridgedInterface.Companion.NON_INTERFACE_FUNCTION_NAMES
import app.cash.zipline.kotlin.FqPackageName
import app.cash.zipline.kotlin.classId
import java.io.File
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.isSupertypeOf
Expand All @@ -38,6 +35,9 @@ import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.fir.types.FirTypeProjectionWithVariance
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.FirUserTypeRef
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance

fun readFirZiplineApi(
Expand All @@ -50,8 +50,8 @@ fun readFirZiplineApi(
}
}

private val ziplineFqPackage = FqPackageName("app.cash.zipline")
private val ziplineServiceClassId = ziplineFqPackage.classId("ZiplineService")
private val ziplineServiceClassId =
ClassId(FqName("app.cash.zipline"), Name.identifier("ZiplineService"))

/**
* Read the frontend intermediate representation of a program and emit its ZiplineService
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package app.cash.zipline.api.fir
package app.cash.zipline.api.validator.fir

import java.io.File
import org.jetbrains.kotlin.KtVirtualFileSourceFile
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package app.cash.zipline.api.fir
package app.cash.zipline.api.validator.fir

data class FirZiplineApi(
val services: List<FirZiplineService>,
import okio.ByteString.Companion.encodeUtf8

internal fun String.signatureHash(): String =
encodeUtf8().sha256().substring(0, 6).base64() // In base64, 6 bytes takes 8 chars.

/** Don't bridge these. */
internal val NON_INTERFACE_FUNCTION_NAMES = setOf(
"equals",
"hashCode",
"toString",
)
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package app.cash.zipline.api.toml
package app.cash.zipline.api.validator.toml

data class TomlZiplineApi(
val services: List<TomlZiplineService>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package app.cash.zipline.api.toml
package app.cash.zipline.api.validator.toml

import okio.BufferedSource
import okio.ByteString.Companion.encodeUtf8
import okio.IOException
import okio.Options

fun BufferedSource.readZiplineApi(): TomlZiplineApi {
fun BufferedSource.readTomlZiplineApi(): TomlZiplineApi {
return TomlZiplineApiReader(this).readServices()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package app.cash.zipline.api.toml
package app.cash.zipline.api.validator.toml

import okio.BufferedSink

fun BufferedSink.writeZiplineApi(api: TomlZiplineApi) {
fun BufferedSink.writeTomlZiplineApi(api: TomlZiplineApi) {
TomlZiplineApiWriter(this).writeApi(api)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package app.cash.zipline.api.compatibility
package app.cash.zipline.api.validator

import app.cash.zipline.api.fir.FirZiplineApi
import app.cash.zipline.api.fir.FirZiplineFunction
import app.cash.zipline.api.fir.FirZiplineService
import app.cash.zipline.api.toml.TomlZiplineApi
import app.cash.zipline.api.toml.TomlZiplineFunction
import app.cash.zipline.api.toml.TomlZiplineService
import app.cash.zipline.kotlin.signatureHash
import app.cash.zipline.api.validator.fir.FirZiplineApi
import app.cash.zipline.api.validator.fir.FirZiplineFunction
import app.cash.zipline.api.validator.fir.FirZiplineService
import app.cash.zipline.api.validator.fir.signatureHash
import app.cash.zipline.api.validator.toml.TomlZiplineApi
import app.cash.zipline.api.validator.toml.TomlZiplineFunction
import app.cash.zipline.api.validator.toml.TomlZiplineService
import assertk.assertThat
import assertk.assertions.containsExactly
import assertk.assertions.isEqualTo
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package app.cash.zipline.api.fir
package app.cash.zipline.api.validator.fir

import app.cash.zipline.ZiplineService
import assertk.assertThat
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package app.cash.zipline.api.toml
package app.cash.zipline.api.validator.toml

import assertk.assertThat
import assertk.assertions.isEqualTo
import okio.Buffer
import org.junit.Test

internal class ZiplineApiTomlReaderTest {
internal class TomlZiplineApiReaderTest {
@Test
fun happyPath() {
val toml = Buffer().writeUtf8(
Expand All @@ -37,7 +37,7 @@ internal class ZiplineApiTomlReaderTest {
""".trimMargin(),
)

val ziplineApi = toml.readZiplineApi()
val ziplineApi = toml.readTomlZiplineApi()
assertThat(ziplineApi).isEqualTo(
TomlZiplineApi(
services = listOf(
Expand Down Expand Up @@ -70,7 +70,7 @@ internal class ZiplineApiTomlReaderTest {
""".trimMargin(),
)

val ziplineApi = toml.readZiplineApi()
val ziplineApi = toml.readTomlZiplineApi()
assertThat(ziplineApi).isEqualTo(
TomlZiplineApi(
services = listOf(
Expand Down Expand Up @@ -108,7 +108,7 @@ internal class ZiplineApiTomlReaderTest {
""".trimMargin(),
)

val ziplineApi = toml.readZiplineApi()
val ziplineApi = toml.readTomlZiplineApi()
assertThat(ziplineApi).isEqualTo(
TomlZiplineApi(
services = listOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package app.cash.zipline.api.toml
package app.cash.zipline.api.validator.toml

import assertk.assertThat
import assertk.assertions.isEqualTo
import okio.Buffer
import org.junit.Test

internal class ZiplineApiTomlWriterTest {
internal class TomlZiplineApiWriterTest {
@Test
fun happyPath() {
val buffer = Buffer().apply {
writeZiplineApi(
writeTomlZiplineApi(
TomlZiplineApi(
services = listOf(
TomlZiplineService(
Expand Down Expand Up @@ -64,7 +64,7 @@ internal class ZiplineApiTomlWriterTest {
@Test
fun multipleServices() {
val buffer = Buffer().apply {
writeZiplineApi(
writeTomlZiplineApi(
TomlZiplineApi(
services = listOf(
TomlZiplineService(
Expand Down
1 change: 1 addition & 0 deletions zipline-cli/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ kotlin {
}

dependencies {
api(projects.ziplineApiValidator)
api(projects.ziplineLoader)
implementation(libs.okHttp.core)
implementation(libs.picocli)
Expand Down
2 changes: 2 additions & 0 deletions zipline-gradle-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ kotlin {
dependencies {
implementation(kotlin("gradle-plugin-api"))
implementation(projects.zipline)
implementation(projects.ziplineApiValidator)
implementation(projects.ziplineBytecode)
implementation(projects.ziplineKotlinPlugin)
implementation(projects.ziplineLoader)
Expand Down Expand Up @@ -71,6 +72,7 @@ tasks {
}
)
systemProperty("ziplineVersion", project.version)
dependsOn(":zipline-api-validator:publishAllPublicationsToTestMavenRepository")
dependsOn(":zipline-bytecode:publishAllPublicationsToTestMavenRepository")
dependsOn(":zipline-gradle-plugin:publishAllPublicationsToTestMavenRepository")
dependsOn(":zipline-kotlin-plugin:publishAllPublicationsToTestMavenRepository")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@

package app.cash.zipline.gradle

import app.cash.zipline.api.compatibility.ActualApiHasProblems
import app.cash.zipline.api.compatibility.ExpectedApiIsUpToDate
import app.cash.zipline.api.compatibility.ExpectedApiRequiresUpdates
import app.cash.zipline.api.compatibility.makeApiCompatibilityDecision
import app.cash.zipline.api.fir.readFirZiplineApi
import app.cash.zipline.api.toml.TomlZiplineApi
import app.cash.zipline.api.toml.readZiplineApi
import app.cash.zipline.api.toml.writeZiplineApi
import app.cash.zipline.api.validator.ActualApiHasProblems
import app.cash.zipline.api.validator.ExpectedApiIsUpToDate
import app.cash.zipline.api.validator.ExpectedApiRequiresUpdates
import app.cash.zipline.api.validator.fir.readFirZiplineApi
import app.cash.zipline.api.validator.makeApiCompatibilityDecision
import app.cash.zipline.api.validator.toml.TomlZiplineApi
import app.cash.zipline.api.validator.toml.readTomlZiplineApi
import app.cash.zipline.api.validator.toml.writeTomlZiplineApi
import javax.inject.Inject
import okio.buffer
import okio.sink
Expand All @@ -38,7 +38,7 @@ import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction

@Suppress("unused") // Public API for Gradle plugin users.
abstract class ZiplineApiValidationTask @Inject constructor(
abstract class ZiplineApiValidatorTask @Inject constructor(
fileCollectionFactory: FileCollectionFactory,
@Input val mode: Mode,
) : DefaultTask() {
Expand Down Expand Up @@ -69,7 +69,7 @@ abstract class ZiplineApiValidationTask @Inject constructor(
val tomlFile = ziplineApiFile.get().asFile

val expectedZiplineApi = when {
tomlFile.exists() -> tomlFile.source().buffer().use { it.readZiplineApi() }
tomlFile.exists() -> tomlFile.source().buffer().use { it.readTomlZiplineApi() }
else -> TomlZiplineApi(listOf())
}

Expand Down Expand Up @@ -99,7 +99,7 @@ abstract class ZiplineApiValidationTask @Inject constructor(

Mode.Dump -> {
logger.info("Updated $tomlFileRelative because Zipline API has changed")
tomlFile.sink().buffer().use { it.writeZiplineApi(decision.updatedApi) }
tomlFile.sink().buffer().use { it.writeTomlZiplineApi(decision.updatedApi) }
}
}
}
Expand Down
Loading

0 comments on commit 7d087ba

Please sign in to comment.