Skip to content

Commit 37c8cec

Browse files
committed
Support reading classes from resulting jar and allow configuring tasks without registering extension
1 parent 7d29849 commit 37c8cec

File tree

3 files changed

+52
-24
lines changed

3 files changed

+52
-24
lines changed

src/main/kotlin/BinaryCompatibilityValidatorPlugin.kt

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ private fun Project.configureKotlinCompilation(
179179
val apiDirProvider = targetConfig.apiDir
180180
val apiBuildDir = apiDirProvider.map { buildDir.resolve(it) }
181181

182-
val apiBuild = task<KotlinApiBuildTask>(targetConfig.apiTaskName("Build"), extension) {
182+
val apiBuild = task<KotlinApiBuildTask>(targetConfig.apiTaskName("Build")) {
183183
// Do not enable task for empty umbrella modules
184184
isEnabled =
185185
apiCheckEnabled(projectName, extension) && compilation.allKotlinSourceSets.any { it.kotlin.srcDirs.any { it.exists() } }
@@ -199,6 +199,9 @@ private fun Project.configureKotlinCompilation(
199199
files(provider<Any> { if (isEnabled) compilation.compileDependencyFiles else emptyList<Any>() })
200200
}
201201
outputApiDir = apiBuildDir.get()
202+
ignoredPackages = extension.ignoredPackages
203+
ignoredClasses = extension.ignoredClasses
204+
nonPublicMarkers = extension.nonPublicMarkers
202205
}
203206
configureCheckTasks(apiBuildDir, apiBuild, extension, targetConfig, commonApiDump, commonApiCheck)
204207
}
@@ -216,14 +219,17 @@ private fun Project.configureApiTasks(
216219
) {
217220
val projectName = project.name
218221
val apiBuildDir = targetConfig.apiDir.map { buildDir.resolve(it) }
219-
val apiBuild = task<KotlinApiBuildTask>(targetConfig.apiTaskName("Build"), extension) {
222+
val apiBuild = task<KotlinApiBuildTask>(targetConfig.apiTaskName("Build")) {
220223
isEnabled = apiCheckEnabled(projectName, extension)
221224
// 'group' is not specified deliberately so it will be hidden from ./gradlew tasks
222225
description =
223226
"Builds Kotlin API for 'main' compilations of $projectName. Complementary task and shouldn't be called manually"
224227
inputClassesDirs = files(provider<Any> { if (isEnabled) sourceSet.output.classesDirs else emptyList<Any>() })
225228
inputDependencies = files(provider<Any> { if (isEnabled) sourceSet.output.classesDirs else emptyList<Any>() })
226229
outputApiDir = apiBuildDir.get()
230+
ignoredPackages = extension.ignoredPackages
231+
ignoredClasses = extension.ignoredClasses
232+
nonPublicMarkers = extension.nonPublicMarkers
227233
}
228234

229235
configureCheckTasks(apiBuildDir, apiBuild, extension, targetConfig)
@@ -247,16 +253,7 @@ private fun Project.configureCheckTasks(
247253
isEnabled = apiCheckEnabled(projectName, extension) && apiBuild.map { it.enabled }.getOrElse(true)
248254
group = "verification"
249255
description = "Checks signatures of public API against the golden value in API folder for $projectName"
250-
run {
251-
val d = apiCheckDir.get()
252-
projectApiDir = if (d.exists()) {
253-
d
254-
} else {
255-
nonExistingProjectApiDir = d.toString()
256-
null
257-
}
258-
this.apiBuildDir = apiBuildDir.get()
259-
}
256+
compareApiDumps(apiReferenceDir = apiCheckDir.get(), apiBuildDir = apiBuildDir.get())
260257
dependsOn(apiBuild)
261258
}
262259

src/main/kotlin/KotlinApiBuildTask.kt

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,21 @@ import org.gradle.api.*
1010
import org.gradle.api.file.*
1111
import org.gradle.api.tasks.*
1212
import java.io.*
13+
import java.util.jar.JarFile
1314
import javax.inject.Inject
1415

1516
open class KotlinApiBuildTask @Inject constructor(
16-
private val extension: ApiValidationExtension
1717
) : DefaultTask() {
1818

1919
@InputFiles
20+
@Optional
2021
@PathSensitive(PathSensitivity.RELATIVE)
21-
lateinit var inputClassesDirs: FileCollection
22+
var inputClassesDirs: FileCollection? = null
23+
24+
@InputFile
25+
@Optional
26+
@PathSensitive(PathSensitivity.RELATIVE)
27+
val inputJar: RegularFileProperty = this.project.objects.fileProperty()
2228

2329
@InputFiles
2430
@PathSensitive(PathSensitivity.RELATIVE)
@@ -28,13 +34,13 @@ open class KotlinApiBuildTask @Inject constructor(
2834
lateinit var outputApiDir: File
2935

3036
@get:Input
31-
val ignoredPackages : Set<String> get() = extension.ignoredPackages
37+
var ignoredPackages : Set<String> = emptySet()
3238

3339
@get:Input
34-
val nonPublicMarkers : Set<String> get() = extension.nonPublicMarkers
40+
var nonPublicMarkers : Set<String> = emptySet()
3541

3642
@get:Input
37-
val ignoredClasses : Set<String> get() = extension.ignoredClasses
43+
var ignoredClasses : Set<String> = emptySet()
3844

3945
@get:Internal
4046
internal val projectName = project.name
@@ -44,17 +50,32 @@ open class KotlinApiBuildTask @Inject constructor(
4450
cleanup(outputApiDir)
4551
outputApiDir.mkdirs()
4652

47-
val signatures = inputClassesDirs.asFileTree.asSequence()
48-
.filter {
49-
!it.isDirectory && it.name.endsWith(".class") && !it.name.startsWith("META-INF/")
50-
}
51-
.map { it.inputStream() }
52-
.loadApiFromJvmClasses()
53+
val inputClassesDirs = inputClassesDirs
54+
if (listOfNotNull(inputClassesDirs, inputJar.orNull).size != 1) {
55+
throw GradleException("KotlinApiBuildTask should have either inputClassesDirs, or inputJar properties set")
56+
}
57+
val signatures = when {
58+
inputClassesDirs != null ->
59+
inputClassesDirs.asFileTree.asSequence()
60+
.filter {
61+
!it.isDirectory && it.name.endsWith(".class") && !it.name.startsWith("META-INF/")
62+
}
63+
.map { it.inputStream() }
64+
.loadApiFromJvmClasses()
65+
inputJar.isPresent ->
66+
JarFile(inputJar.get().asFile)
67+
.loadApiFromJvmClasses()
68+
else ->
69+
error("Unreachable")
70+
}
71+
72+
73+
val filteredSignatures = signatures
5374
.filterOutNonPublic(ignoredPackages, ignoredClasses)
5475
.filterOutAnnotated(nonPublicMarkers.map { it.replace(".", "/") }.toSet())
5576

5677
outputApiDir.resolve("$projectName.api").bufferedWriter().use { writer ->
57-
signatures
78+
filteredSignatures
5879
.sortedBy { it.name }
5980
.forEach { api ->
6081
writer.append(api.signature).appendLine(" {")

src/main/kotlin/KotlinApiCompareTask.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@ open class KotlinApiCompareTask @Inject constructor(private val objects: ObjectF
3232
@Optional
3333
var nonExistingProjectApiDir: String? = null
3434

35+
fun compareApiDumps(apiReferenceDir: File, apiBuildDir: File) {
36+
if (apiReferenceDir.exists()) {
37+
projectApiDir = apiReferenceDir
38+
} else {
39+
projectApiDir = null
40+
nonExistingProjectApiDir = apiReferenceDir.toString()
41+
}
42+
this.apiBuildDir = apiBuildDir
43+
}
44+
3545
@InputDirectory
3646
@PathSensitive(PathSensitivity.RELATIVE)
3747
lateinit var apiBuildDir: File

0 commit comments

Comments
 (0)