Skip to content

Commit

Permalink
Use native gummy bears type descriptors
Browse files Browse the repository at this point in the history
  • Loading branch information
ogolberg committed Nov 7, 2023
1 parent 1f16499 commit 7e1c3a5
Show file tree
Hide file tree
Showing 11 changed files with 165 additions and 25 deletions.
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ nexus = "1.3.0"
ktlint = "0.50.0"
spotless = "6.21.0"
protokt = "1.0.0-alpha.10"
protobuf = "3.24.0"

# test
junit = "5.10.0"
Expand All @@ -23,6 +24,7 @@ kotlin-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.
spotless = { module = "com.diffplug.spotless:spotless-plugin-gradle", version.ref = "spotless" }
gradle-publish = { module = "com.gradle.publish:plugin-publish-plugin", version = "1.2.0" }
protokt-extensions = { module = "com.toasttab.protokt:protokt-extensions", version.ref = "protokt" }
protobuf-java = { module = "com.google.protobuf:protobuf-java", version.ref = "protobuf" }

# test
junit = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" }
Expand Down
1 change: 1 addition & 0 deletions plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ plugins {
dependencies {
implementation(projects.core)
implementation(projects.animalSnifferFormat)
implementation(libs.protobuf.java)

testImplementation(libs.testkit.junit5)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import org.gradle.api.Action

abstract class ExpediterExtension {
var application: ApplicationClassSelector = ApplicationClassSelector(configuration = "runtimeClasspath", sourceSet = "main")
var platform: PlatformClassSelector = PlatformClassSelector(platformClassloader = true)
var platform: PlatformClassSelector = PlatformClassSelector()

val ignoreSpec = IgnoreSpec()

Expand All @@ -34,7 +34,6 @@ abstract class ExpediterExtension {
}

fun platform(configure: Action<PlatformClassSelector>) {
platform = PlatformClassSelector(false)
configure.execute(platform)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,23 +44,31 @@ class ExpediterPlugin : Plugin<Project> {

jvmVersion = extension.platform.jvmVersion

val animalSnifferConfigurations = extension.platform.animalSnifferConfigurations.toMutableList()
val expediterConfigurations = extension.platform.expediterConfigurations.toMutableList()

if (extension.platform.androidSdk != null) {
val config = project.configurations.create("_expediter_animal_sniffer_")
val config = project.configurations.create("_expediter_type_descriptors_")
project.dependencies.add(
config.name,
"com.toasttab.android:gummy-bears-api-${extension.platform.androidSdk}:0.5.1@signature"
"com.toasttab.android:gummy-bears-api-${extension.platform.androidSdk}:0.6.0@expediter"
)
animalSnifferConfigurations.add(config.name)
expediterConfigurations.add(config.name)
}

for (conf in expediterConfigurations) {
typeDescriptors.from(project.configurations.getByName(conf))
}

for (conf in extension.platform.animalSnifferConfigurations) {
animalSnifferSignatures.from(project.configurations.getByName(conf))
}

if (extension.platform.jvmVersion != null && extension.platform.androidSdk != null) {
logger.warn("Both jvmVersion and androidSdk are set.")
}

for (conf in animalSnifferConfigurations) {
animalSnifferSignatures.from(project.configurations.getByName(conf))
for (conf in extension.platform.configurations) {
platformArtifactCollection(selector.artifacts(conf))
}

ignore = extension.ignoreSpec.buildIgnore()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
package com.toasttab.expediter.gradle

import com.toasttab.expediter.ClasspathApplicationTypesProvider
import com.toasttab.expediter.ClasspathScanner
import com.toasttab.expediter.Expediter
import com.toasttab.expediter.TypeParsers
import com.toasttab.expediter.ignore.Ignore
import com.toasttab.expediter.issue.IssueReport
import com.toasttab.expediter.sniffer.AnimalSnifferParser
Expand All @@ -39,30 +41,39 @@ import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.TaskAction
import protokt.v1.toasttab.expediter.v1.TypeDescriptors
import java.io.File
import java.util.zip.GZIPInputStream

@CacheableTask
abstract class ExpediterTask : DefaultTask() {
private val configurationArtifacts = mutableListOf<ArtifactCollection>()
private val applicationConfigurationArtifacts = mutableListOf<ArtifactCollection>()
private val platformConfigurationArtifacts = mutableListOf<ArtifactCollection>()

@get:InputFiles
@get:PathSensitive(PathSensitivity.ABSOLUTE)
val artifacts: FileCollection get() {
return if (configurationArtifacts.isEmpty()) {
project.objects.fileCollection()
} else {
configurationArtifacts.map {
it.artifactFiles
}.reduce(FileCollection::plus)
}
val applicationArtifacts get() = applicationConfigurationArtifacts.asFileCollection()

@get:InputFiles
@get:PathSensitive(PathSensitivity.ABSOLUTE)
val platformArtifacts get() = platformConfigurationArtifacts.asFileCollection()

private fun Collection<ArtifactCollection>.asFileCollection() = if (isEmpty()) {
project.objects.fileCollection()
} else {
map { it.artifactFiles }.reduce(FileCollection::plus)
}

@get:InputFiles
@get:PathSensitive(PathSensitivity.ABSOLUTE)
abstract val files: ConfigurableFileCollection

fun artifactCollection(artifactCollection: ArtifactCollection) {
configurationArtifacts.add(artifactCollection)
applicationConfigurationArtifacts.add(artifactCollection)
}

fun platformArtifactCollection(artifactCollection: ArtifactCollection) {
platformConfigurationArtifacts.add(artifactCollection)
}

@OutputFile
Expand All @@ -79,6 +90,10 @@ abstract class ExpediterTask : DefaultTask() {
@get:PathSensitive(PathSensitivity.RELATIVE)
abstract val animalSnifferSignatures: ConfigurableFileCollection

@get:InputFiles
@get:PathSensitive(PathSensitivity.RELATIVE)
abstract val typeDescriptors: ConfigurableFileCollection

@InputFile
@PathSensitive(PathSensitivity.RELATIVE)
@Optional
Expand All @@ -95,13 +110,27 @@ abstract class ExpediterTask : DefaultTask() {
providers.add(JvmTypeProvider.forTarget(it))
}

if (!platformArtifacts.isEmpty) {
providers.add(
InMemoryPlatformTypeProvider(
ClasspathScanner(platformArtifacts).scan { i, _ -> TypeParsers.typeDescriptor(i) }
)
)
}

for (signaturesFile in animalSnifferSignatures) {
signaturesFile.inputStream().buffered().use {
providers.add(InMemoryPlatformTypeProvider(AnimalSnifferParser.parse(it)))
}
}

if (jvmVersion == null && animalSnifferSignatures.isEmpty) {
for (descriptorFile in typeDescriptors) {
GZIPInputStream(descriptorFile.inputStream().buffered()).use {
providers.add(InMemoryPlatformTypeProvider(TypeDescriptors.deserialize(it).types))
}
}

if (jvmVersion == null && animalSnifferSignatures.isEmpty && typeDescriptors.isEmpty) {
logger.warn("No platform APIs specified, falling back to the platform classloader of the current JVM.")

providers.add(PlatformClassloaderTypeProvider)
Expand All @@ -115,7 +144,7 @@ abstract class ExpediterTask : DefaultTask() {

val issues = Expediter(
ignore,
ClasspathApplicationTypesProvider(artifacts + files),
ClasspathApplicationTypesProvider(applicationArtifacts + files),
PlatformTypeProviderChain(
providers
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,21 @@
package com.toasttab.expediter.gradle

class PlatformClassSelector(
var platformClassloader: Boolean,
val animalSnifferConfigurations: MutableList<String> = mutableListOf(),
val expediterConfigurations: MutableList<String> = mutableListOf(),
val configurations: MutableList<String> = mutableListOf(),
var androidSdk: Int? = null,
var jvmVersion: Int? = null
) {
fun animalSnifferConfiguration(configuration: String) {
animalSnifferConfigurations.add(configuration)
}

fun expediterConfiguration(configuration: String) {
expediterConfigurations.add(configuration)
}

fun configuration(configuration: String) {
configurations.add(configuration)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,35 @@ class ExpediterPluginIntegrationTest {

val report = IssueReport.fromJson(project.dir.resolve("build/expediter.json").readText())

expectThat(report.issues).contains(
Issue.MissingMember(
"test/Caller",
MemberAccess.MethodAccess(
"java/util/concurrent/ConcurrentHashMap",
null,
MemberSymbolicReference(
"computeIfAbsent",
"(Ljava/lang/Object;Ljava/util/function/Function;)Ljava/lang/Object;"
),
MethodAccessType.VIRTUAL
)
),

Issue.MissingType(
"com/fasterxml/jackson/databind/introspect/POJOPropertyBuilder",
"java/util/stream/Collectors"
)
)
}

@Test
fun `android compat source only`(project: TestProject) {
project.createRunner()
.withArguments("check")
.buildAndFail()

val report = IssueReport.fromJson(project.dir.resolve("build/expediter.json").readText())

expectThat(report.issues).containsExactlyInAnyOrder(
Issue.MissingMember(
"test/Caller",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
plugins {
java
id("com.toasttab.expediter")
id("com.toasttab.testkit.coverage") version "0.0.2"
}

repositories {
mavenCentral()
}

expediter {
failOnIssues = true

application {
sourceSet("main")
}

platform {
androidSdk = 19

configuration("runtimeClasspath")
}
}

dependencies {
implementation("com.fasterxml.jackson.core:jackson-databind:2.15.2")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rootProject.name = "test"
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2023 Toast Inc.
*
* 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 test;

import java.util.concurrent.ConcurrentHashMap;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Caller {
void f() {
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();

map.put("a", "b");

map.computeIfAbsent("a", k -> "b");

map.hashCode();
}

void g() {
ObjectMapper mapper = new ObjectMapper();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ repositories {
expediter {
failOnIssues = true

application {
sourceSet("main")
}

platform {
androidSdk = 19
}
}

dependencies {
implementation("com.fasterxml.jackson.core:jackson-databind:2.15.2")
}

0 comments on commit 7e1c3a5

Please sign in to comment.