Skip to content

Commit b42f190

Browse files
committed
Avoid using project.name for ignored projects check
> The project's name is not necessarily unique within a project hierarchy. You should use the getPath() method for a unique identifier for the project. See https://docs.gradle.org/current/javadoc/org/gradle/api/Project.html#getName().
1 parent 18cd0df commit b42f190

File tree

4 files changed

+69
-39
lines changed

4 files changed

+69
-39
lines changed

src/functionalTest/kotlin/kotlinx/validation/test/SubprojectsWithPluginOnRootTests.kt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import kotlinx.validation.api.runner
1414
import kotlinx.validation.api.test
1515
import org.assertj.core.api.Assertions
1616
import org.junit.Test
17+
import kotlin.test.assertContains
1718
import kotlin.test.assertTrue
1819

1920
internal class SubprojectsWithPluginOnRootTests : BaseKotlinGradleTest() {
@@ -317,4 +318,39 @@ internal class SubprojectsWithPluginOnRootTests : BaseKotlinGradleTest() {
317318
Assertions.assertThat(apiSub2.readText()).isEqualToIgnoringNewLines("")
318319
}
319320
}
321+
322+
/**
323+
* https://github.com/Kotlin/binary-compatibility-validator/issues/257
324+
*/
325+
@Test
326+
fun `using project name instead of path should not be ignored`() {
327+
val runner = test {
328+
createProjectHierarchyWithPluginOnRoot()
329+
rootProjectDir.resolve("build.gradle.kts").writeText(
330+
"""
331+
apiValidation {
332+
ignoredProjects += listOf(
333+
"subsub1"
334+
)
335+
}
336+
""".trimIndent()
337+
)
338+
339+
runner {
340+
arguments.add(":apiCheck")
341+
}
342+
}
343+
344+
try {
345+
runner.build()
346+
error("Should have failed.")
347+
} catch (t: Throwable) {
348+
assertContains(
349+
t.stackTraceToString(),
350+
"""
351+
Cannot find excluded project subsub1 in all projects: [:, :sub1, :sub2, :sub1:subsub1, :sub1:subsub2]
352+
""".trimIndent()
353+
)
354+
}
355+
}
320356
}

src/main/kotlin/BinaryCompatibilityValidatorPlugin.kt

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.gradle.plugin.*
1717
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
1818
import org.jetbrains.kotlin.konan.target.HostManager
1919
import org.jetbrains.kotlin.library.abi.ExperimentalLibraryAbiReader
20-
import org.jetbrains.kotlin.library.abi.LibraryAbiReader
2120
import java.io.*
2221
import java.util.*
2322

@@ -35,7 +34,7 @@ public class BinaryCompatibilityValidatorPlugin : Plugin<Project> {
3534
private fun Project.validateExtension(extension: ApiValidationExtension) {
3635
afterEvaluate {
3736
val ignored = extension.ignoredProjects
38-
val all = allprojects.map { it.name }
37+
val all = allprojects.map { it.path }
3938
for (project in ignored) {
4039
require(project in all) { "Cannot find excluded project $project in all projects: $all" }
4140
}
@@ -55,7 +54,7 @@ public class BinaryCompatibilityValidatorPlugin : Plugin<Project> {
5554
extension: ApiValidationExtension,
5655
action: Action<AppliedPlugin>
5756
) = project.pluginManager.withPlugin(name) {
58-
if (project.name in extension.ignoredProjects) return@withPlugin
57+
if (project.path in extension.ignoredProjects) return@withPlugin
5958
action.execute(it)
6059
}
6160

@@ -64,7 +63,7 @@ public class BinaryCompatibilityValidatorPlugin : Plugin<Project> {
6463
extension: ApiValidationExtension,
6564
jvmRuntimeClasspath: NamedDomainObjectProvider<Configuration>
6665
) = configurePlugin("kotlin-multiplatform", project, extension) {
67-
if (project.name in extension.ignoredProjects) return@configurePlugin
66+
if (project.path in extension.ignoredProjects) return@configurePlugin
6867
val kotlin = project.kotlinMultiplatform
6968

7069
// Create common tasks for multiplatform
@@ -208,16 +207,16 @@ private fun Project.configureKotlinCompilation(
208207
commonApiCheck: TaskProvider<Task>? = null,
209208
useOutput: Boolean = false,
210209
) {
211-
val projectName = project.name
210+
val projectPath = project.path
212211
val dumpFileName = project.jvmDumpFileName
213212
val apiDirProvider = targetConfig.apiDir
214213
val apiBuildDir = apiDirProvider.flatMap { f -> layout.buildDirectory.asFile.map { it.resolve(f) } }
215214

216215
val apiBuild = task<KotlinApiBuildTask>(targetConfig.apiTaskName("Build")) {
217-
isEnabled = apiCheckEnabled(projectName, extension)
216+
isEnabled = apiCheckEnabled(projectPath, extension)
218217
// 'group' is not specified deliberately, so it will be hidden from ./gradlew tasks
219218
description =
220-
"Builds Kotlin API for 'main' compilations of $projectName. Complementary task and shouldn't be called manually"
219+
"Builds Kotlin API for 'main' compilations of $projectPath. Complementary task and shouldn't be called manually"
221220
if (useOutput) {
222221
// Workaround for #4
223222
inputClassesDirs.from(compilation.output.classesDirs)
@@ -240,19 +239,19 @@ internal val Project.apiValidationExtensionOrNull: ApiValidationExtension?
240239
.map { it.extensions.findByType(ApiValidationExtension::class.java) }
241240
.firstOrNull { it != null }
242241

243-
private fun apiCheckEnabled(projectName: String, extension: ApiValidationExtension): Boolean =
244-
projectName !in extension.ignoredProjects && !extension.validationDisabled
242+
private fun apiCheckEnabled(projectPath: String, extension: ApiValidationExtension): Boolean =
243+
projectPath !in extension.ignoredProjects && !extension.validationDisabled
245244

246245
@OptIn(ExperimentalBCVApi::class)
247-
private fun klibAbiCheckEnabled(projectName: String, extension: ApiValidationExtension): Boolean =
248-
projectName !in extension.ignoredProjects && !extension.validationDisabled && extension.klib.enabled
246+
private fun klibAbiCheckEnabled(projectPath: String, extension: ApiValidationExtension): Boolean =
247+
projectPath !in extension.ignoredProjects && !extension.validationDisabled && extension.klib.enabled
249248

250249
private fun Project.configureApiTasks(
251250
extension: ApiValidationExtension,
252251
targetConfig: TargetConfig = TargetConfig(this, extension),
253252
jvmRuntimeClasspath: NamedDomainObjectProvider<Configuration>,
254253
) {
255-
val projectName = project.name
254+
val projectPath = project.path
256255
val dumpFileName = project.jvmDumpFileName
257256
val apiBuildDir = targetConfig.apiDir.flatMap { f -> layout.buildDirectory.asFile.map { it.resolve(f) } }
258257
val sourceSetsOutputsProvider = project.provider {
@@ -262,10 +261,10 @@ private fun Project.configureApiTasks(
262261
}
263262

264263
val apiBuild = task<KotlinApiBuildTask>(targetConfig.apiTaskName("Build")) {
265-
isEnabled = apiCheckEnabled(projectName, extension)
264+
isEnabled = apiCheckEnabled(projectPath, extension)
266265
// 'group' is not specified deliberately, so it will be hidden from ./gradlew tasks
267266
description =
268-
"Builds Kotlin API for 'main' compilations of $projectName. Complementary task and shouldn't be called manually"
267+
"Builds Kotlin API for 'main' compilations of $projectPath. Complementary task and shouldn't be called manually"
269268
inputClassesDirs.from(sourceSetsOutputsProvider)
270269
outputApiFile.fileProvider(apiBuildDir.map { it.resolve(dumpFileName) })
271270
runtimeClasspath.from(jvmRuntimeClasspath)
@@ -281,25 +280,25 @@ private fun Project.configureCheckTasks(
281280
commonApiDump: TaskProvider<Task>? = null,
282281
commonApiCheck: TaskProvider<Task>? = null,
283282
) {
284-
val projectName = project.name
283+
val projectPath = project.path
285284
val apiCheckDir = targetConfig.apiDir.map {
286285
projectDir.resolve(it).also { r ->
287286
logger.debug("Configuring api for ${targetConfig.targetName ?: "jvm"} to $r")
288287
}
289288
}
290289
val apiCheck = task<KotlinApiCompareTask>(targetConfig.apiTaskName("Check")) {
291-
isEnabled = apiCheckEnabled(projectName, extension) && apiBuild.map { it.enabled }.getOrElse(true)
290+
isEnabled = apiCheckEnabled(projectPath, extension) && apiBuild.map { it.enabled }.getOrElse(true)
292291
group = "verification"
293-
description = "Checks signatures of public API against the golden value in API folder for $projectName"
292+
description = "Checks signatures of public API against the golden value in API folder for $projectPath"
294293
projectApiFile.fileProvider(apiCheckDir.map { it.resolve(jvmDumpFileName) })
295294
generatedApiFile.set(apiBuild.flatMap { it.outputApiFile })
296295
}
297296

298297
val dumpFileName = project.jvmDumpFileName
299298
val apiDump = task<SyncFile>(targetConfig.apiTaskName("Dump")) {
300-
isEnabled = apiCheckEnabled(projectName, extension) && apiBuild.map { it.enabled }.getOrElse(true)
299+
isEnabled = apiCheckEnabled(projectPath, extension) && apiBuild.map { it.enabled }.getOrElse(true)
301300
group = "other"
302-
description = "Syncs the API file for $projectName"
301+
description = "Syncs the API file for $projectPath"
303302
from.set(apiBuild.flatMap { it.outputApiFile })
304303
to.fileProvider(apiCheckDir.map { it.resolve(dumpFileName) })
305304
}
@@ -398,16 +397,16 @@ private class KlibValidationPipelineBuilder(
398397

399398
private fun Project.checkKlibsTask(klibDumpConfig: TargetConfig) =
400399
project.task<KotlinApiCompareTask>(klibDumpConfig.apiTaskName("Check")) {
401-
isEnabled = klibAbiCheckEnabled(project.name, extension)
400+
isEnabled = klibAbiCheckEnabled(project.path, extension)
402401
group = "verification"
403402
description =
404-
"Checks signatures of a public KLib ABI against the golden value in ABI folder for ${project.name}"
403+
"Checks signatures of a public KLib ABI against the golden value in ABI folder for ${project.path}"
405404
}
406405

407406
private fun Project.dumpKlibsTask(klibDumpConfig: TargetConfig) =
408407
project.task<SyncFile>(klibDumpConfig.apiTaskName("Dump")) {
409-
isEnabled = klibAbiCheckEnabled(project.name, extension)
410-
description = "Syncs the KLib ABI file for ${project.name}"
408+
isEnabled = klibAbiCheckEnabled(project.path, extension)
409+
description = "Syncs the KLib ABI file for ${project.path}"
411410
group = "other"
412411
onlyIf {
413412
it as SyncFile
@@ -424,7 +423,7 @@ private class KlibValidationPipelineBuilder(
424423
klibDumpConfig.apiTaskName("ExtractForValidation")
425424
)
426425
{
427-
isEnabled = klibAbiCheckEnabled(project.name, extension)
426+
isEnabled = klibAbiCheckEnabled(project.path, extension)
428427
description = "Prepare a reference KLib ABI file by removing all unsupported targets from " +
429428
"the golden file stored in the project"
430429
group = "other"
@@ -443,7 +442,7 @@ private class KlibValidationPipelineBuilder(
443442
klibDumpConfig.apiTaskName("MergeInferred")
444443
)
445444
{
446-
isEnabled = klibAbiCheckEnabled(project.name, extension)
445+
isEnabled = klibAbiCheckEnabled(project.path, extension)
447446
description = "Merges multiple KLib ABI dump files generated for " +
448447
"different targets (including inferred dumps for unsupported targets) " +
449448
"into a single merged KLib ABI dump"
@@ -456,7 +455,7 @@ private class KlibValidationPipelineBuilder(
456455
klibMergeDir: Provider<File>,
457456
runtimeClasspath: NamedDomainObjectProvider<Configuration>
458457
) = project.task<KotlinKlibMergeAbiTask>(klibDumpConfig.apiTaskName("Merge")) {
459-
isEnabled = klibAbiCheckEnabled(project.name, extension)
458+
isEnabled = klibAbiCheckEnabled(project.path, extension)
460459
description = "Merges multiple KLib ABI dump files generated for " +
461460
"different targets into a single merged KLib ABI dump"
462461
mergedApiFile.fileProvider(klibMergeDir.map { it.resolve(klibDumpFileName) })
@@ -577,11 +576,11 @@ private class KlibValidationPipelineBuilder(
577576
apiBuildDir: Provider<File>,
578577
runtimeClasspath: NamedDomainObjectProvider<Configuration>
579578
): TaskProvider<KotlinKlibAbiBuildTask> {
580-
val projectName = project.name
579+
val projectPath = project.path
581580
val buildTask = project.task<KotlinKlibAbiBuildTask>(targetConfig.apiTaskName("Build")) {
582-
isEnabled = klibAbiCheckEnabled(projectName, extension)
581+
isEnabled = klibAbiCheckEnabled(projectPath, extension)
583582
// 'group' is not specified deliberately, so it will be hidden from ./gradlew tasks
584-
description = "Builds Kotlin KLib ABI dump for 'main' compilations of $projectName. " +
583+
description = "Builds Kotlin KLib ABI dump for 'main' compilations of $projectPath. " +
585584
"Complementary task and shouldn't be called manually"
586585
this.target.set(target)
587586
klibFile.from(compilation.output.classesDirs)
@@ -594,7 +593,7 @@ private class KlibValidationPipelineBuilder(
594593

595594
private fun Project.mergeDependencyForUnsupportedTarget(targetConfig: TargetConfig): TaskProvider<DefaultTask> {
596595
return project.task<DefaultTask>(targetConfig.apiTaskName("Build")) {
597-
isEnabled = apiCheckEnabled(project.name, extension)
596+
isEnabled = apiCheckEnabled(project.path, extension)
598597

599598
doLast {
600599
logger.warn(
@@ -613,7 +612,7 @@ private class KlibValidationPipelineBuilder(
613612
): TaskProvider<KotlinKlibInferAbiTask> {
614613
val targetName = targetConfig.targetName!!
615614
return project.task<KotlinKlibInferAbiTask>(targetConfig.apiTaskName("Infer")) {
616-
isEnabled = klibAbiCheckEnabled(project.name, extension)
615+
isEnabled = klibAbiCheckEnabled(project.path, extension)
617616
description = "Try to infer the dump for unsupported target $targetName using dumps " +
618617
"generated for supported targets."
619618
group = "other"

src/main/kotlin/BuildTaskBase.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,6 @@ public abstract class BuildTaskBase : WorkerAwareTaskBase() {
4848
@get:Input
4949
public val publicClasses: SetProperty<String> = stringSetProperty { publicClasses }
5050

51-
@get:Internal
52-
internal val projectName = project.name
53-
5451
internal fun fillCommonParams(params: BuildParametersBase) {
5552
params.ignoredPackages.set(ignoredPackages)
5653
params.nonPublicMarkers.set(nonPublicMarkers)

src/main/kotlin/KotlinApiCompareTask.kt

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ package kotlinx.validation
88
import com.github.difflib.DiffUtils
99
import com.github.difflib.UnifiedDiffUtils
1010
import java.io.*
11-
import javax.inject.Inject
1211
import org.gradle.api.*
1312
import org.gradle.api.file.RegularFileProperty
1413
import org.gradle.api.tasks.*
@@ -23,7 +22,7 @@ public open class KotlinApiCompareTask : DefaultTask() {
2322
@get:PathSensitive(PathSensitivity.RELATIVE)
2423
public val generatedApiFile: RegularFileProperty = project.objects.fileProperty()
2524

26-
private val projectName = project.name
25+
private val projectPath = project.path
2726

2827
private val rootDir = project.rootDir
2928

@@ -51,10 +50,9 @@ public open class KotlinApiCompareTask : DefaultTask() {
5150
if (diff != null) diffSet.add(diff)
5251
if (diffSet.isNotEmpty()) {
5352
val diffText = diffSet.joinToString("\n\n")
54-
val subject = projectName
5553
error(
56-
"API check failed for project $subject.\n$diffText\n\n" +
57-
"You can run :$subject:apiDump task to overwrite API declarations"
54+
"API check failed for project $projectPath.\n$diffText\n\n" +
55+
"You can run $projectPath:apiDump task to overwrite API declarations"
5856
)
5957
}
6058
}

0 commit comments

Comments
 (0)