Skip to content

use Extension to control the targets container, so that Gradle will generate Kotlin DSL accessors #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ binaryCompatibilityValidator {
}

// BCV will automatically register a target for testFixtures, but it must be enabled manually
targets.named("testFixtures") {
targets.testFixtures {
enabled.set(true)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ private fun FunSpec.createTestFixturesProject(
|}
|
|binaryCompatibilityValidator {
| testFixtures {
| targets.testFixtures {
| enabled.set($bcvTestFixturesTargetEnabled)
| }
|}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ tasks.jar {
}

binaryCompatibilityValidator {
kotlinJvm {
targets.kotlinJvm {
inputJar.set(tasks.jar.flatMap { it.archiveFile })
}
}
6 changes: 3 additions & 3 deletions modules/bcv-gradle-plugin/api/bcv-gradle-plugin.api
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public abstract class dev/adamko/kotlin/binary_compatibility_validator/BCVPlugin
public final class dev/adamko/kotlin/binary_compatibility_validator/BCVPlugin$Companion {
}

public abstract interface class dev/adamko/kotlin/binary_compatibility_validator/BCVProjectExtension : dev/adamko/kotlin/binary_compatibility_validator/targets/BCVTargetSpec, org/gradle/api/plugins/ExtensionAware {
public abstract class dev/adamko/kotlin/binary_compatibility_validator/BCVProjectExtension : dev/adamko/kotlin/binary_compatibility_validator/targets/BCVTargetSpec, org/gradle/api/plugins/ExtensionAware {
public abstract fun getEnabled ()Lorg/gradle/api/provider/Property;
public abstract fun getIgnoredClasses ()Lorg/gradle/api/provider/SetProperty;
public abstract fun getIgnoredMarkers ()Lorg/gradle/api/provider/SetProperty;
Expand All @@ -23,7 +23,7 @@ public abstract interface class dev/adamko/kotlin/binary_compatibility_validator
public abstract fun getPublicClasses ()Lorg/gradle/api/provider/SetProperty;
public abstract fun getPublicMarkers ()Lorg/gradle/api/provider/SetProperty;
public abstract fun getPublicPackages ()Lorg/gradle/api/provider/SetProperty;
public abstract fun getTargets ()Lorg/gradle/api/NamedDomainObjectContainer;
public final fun getTargets ()Lorg/gradle/api/NamedDomainObjectContainer;
}

public abstract class dev/adamko/kotlin/binary_compatibility_validator/BCVProjectPlugin : org/gradle/api/Plugin {
Expand Down Expand Up @@ -94,7 +94,7 @@ public abstract class dev/adamko/kotlin/binary_compatibility_validator/tasks/BCV
public abstract fun getOutputApiBuildDir ()Lorg/gradle/api/file/DirectoryProperty;
public abstract fun getProjectName ()Lorg/gradle/api/provider/Property;
public abstract fun getRuntimeClasspath ()Lorg/gradle/api/file/ConfigurableFileCollection;
public abstract fun getTargets ()Lorg/gradle/api/NamedDomainObjectContainer;
public final fun getTargets ()Lorg/gradle/api/NamedDomainObjectContainer;
}

public abstract class dev/adamko/kotlin/binary_compatibility_validator/tasks/BCVDefaultTask : org/gradle/api/DefaultTask {
Expand Down
37 changes: 24 additions & 13 deletions modules/bcv-gradle-plugin/src/main/kotlin/BCVProjectExtension.kt
Original file line number Diff line number Diff line change
@@ -1,51 +1,62 @@
package dev.adamko.kotlin.binary_compatibility_validator

import dev.adamko.kotlin.binary_compatibility_validator.internal.BCVInternalApi
import dev.adamko.kotlin.binary_compatibility_validator.internal.adding
import dev.adamko.kotlin.binary_compatibility_validator.internal.domainObjectContainer
import dev.adamko.kotlin.binary_compatibility_validator.targets.BCVTarget
import dev.adamko.kotlin.binary_compatibility_validator.targets.BCVTargetSpec
import javax.inject.Inject
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.model.ObjectFactory
import org.gradle.api.model.ReplacedBy
import org.gradle.api.plugins.ExtensionAware
import org.gradle.api.provider.Property
import org.gradle.api.provider.SetProperty

interface BCVProjectExtension : BCVTargetSpec, ExtensionAware {
abstract class BCVProjectExtension
@BCVInternalApi
@Inject
constructor(
private val objects: ObjectFactory
) : BCVTargetSpec, ExtensionAware {

/** Sets the default [BCVTarget.enabled] value for all [targets]. */
override val enabled: Property<Boolean>
abstract override val enabled: Property<Boolean>

/** Sets the default [BCVTarget.ignoredPackages] value for all [targets]. */
override val ignoredPackages: SetProperty<String>
abstract override val ignoredPackages: SetProperty<String>

/** Sets the default [BCVTarget.publicMarkers] for all [targets] */
override val publicMarkers: SetProperty<String>
abstract override val publicMarkers: SetProperty<String>

/** Sets the default [BCVTarget.publicPackages] for all [targets] */
override val publicPackages: SetProperty<String>
abstract override val publicPackages: SetProperty<String>

/** Sets the default [BCVTarget.publicClasses] for all [targets] */
override val publicClasses: SetProperty<String>
abstract override val publicClasses: SetProperty<String>

/** Sets the default [BCVTarget.ignoredMarkers] value for all [targets]. */
override val ignoredMarkers: SetProperty<String>
abstract override val ignoredMarkers: SetProperty<String>

@get:ReplacedBy("ignoredMarkers")
@Deprecated("renamed to ignoredMarkers", ReplaceWith("ignoredMarkers"))
val nonPublicMarkers: SetProperty<String>
abstract val nonPublicMarkers: SetProperty<String>

/** Sets the default [BCVTarget.ignoredClasses] value for all [targets]. */
override val ignoredClasses: SetProperty<String>
abstract override val ignoredClasses: SetProperty<String>

/**
* The directory that contains the API declarations.
*
* Defaults to [BCVPlugin.API_DIR].
*/
val outputApiDir: DirectoryProperty
abstract val outputApiDir: DirectoryProperty

val projectName: Property<String>
abstract val projectName: Property<String>

val kotlinxBinaryCompatibilityValidatorVersion: Property<String>
abstract val kotlinxBinaryCompatibilityValidatorVersion: Property<String>

val targets: NamedDomainObjectContainer<BCVTarget>
val targets: NamedDomainObjectContainer<BCVTarget> =
extensions.adding("targets") { objects.domainObjectContainer() }
}
4 changes: 0 additions & 4 deletions modules/bcv-gradle-plugin/src/main/kotlin/BCVProjectPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,6 @@ constructor(
ignoredPackages.convention(extension.ignoredPackages)
}

extension.targets.all {
extension.extensions.add(platformType, this)
}

return extension
}

Expand Down
48 changes: 48 additions & 0 deletions modules/bcv-gradle-plugin/src/main/kotlin/internal/gradleUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package dev.adamko.kotlin.binary_compatibility_validator.internal

import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.NamedDomainObjectFactory
import org.gradle.api.model.ObjectFactory
import org.gradle.api.plugins.ExtensionContainer
import org.gradle.kotlin.dsl.*


/**
* Create a new [NamedDomainObjectContainer], using
* [org.gradle.kotlin.dsl.domainObjectContainer]
* (but [T] is `reified`).
*
* @param[factory] an optional factory for creating elements
* @see org.gradle.kotlin.dsl.domainObjectContainer
*/
internal inline fun <reified T : Any> ObjectFactory.domainObjectContainer(
factory: NamedDomainObjectFactory<T>? = null
): NamedDomainObjectContainer<T> =
if (factory == null) {
domainObjectContainer(T::class)
} else {
domainObjectContainer(T::class, factory)
}


/**
* [Add][ExtensionContainer.add] a value (from [valueProvider]) with [name], and return the value.
*
* Adding an extension is especially useful for improving the DSL in build scripts when [T] is a
* [NamedDomainObjectContainer].
* Using an extension will allow Gradle to generate
* [type-safe model accessors](https://docs.gradle.org/current/userguide/kotlin_dsl.html#kotdsl:accessor_applicability)
* for added types.
*
* ([name] should match the property name. This has to be done manually because using a
* delegated-property provider means Gradle can't introspect the types properly, so it fails to
* create accessors).
*/
internal inline fun <reified T : Any> ExtensionContainer.adding(
name: String,
crossinline valueProvider: () -> T,
): T {
val value: T = valueProvider()
add<T>(name, value)
return value
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package dev.adamko.kotlin.binary_compatibility_validator.tasks

import dev.adamko.kotlin.binary_compatibility_validator.internal.BCVInternalApi
import dev.adamko.kotlin.binary_compatibility_validator.internal.adding
import dev.adamko.kotlin.binary_compatibility_validator.internal.domainObjectContainer
import dev.adamko.kotlin.binary_compatibility_validator.targets.BCVTarget
import dev.adamko.kotlin.binary_compatibility_validator.workers.BCVSignaturesWorker
import java.io.*
import javax.inject.Inject
import kotlinx.validation.api.*
import org.gradle.api.*
import org.gradle.api.file.*
import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.Property
import org.gradle.api.tasks.*
import org.gradle.kotlin.dsl.*
Expand All @@ -21,10 +24,12 @@ abstract class BCVApiGenerateTask
constructor(
private val workers: WorkerExecutor,
private val fs: FileSystemOperations,
private val objects: ObjectFactory,
) : BCVDefaultTask() {

@get:Nested
abstract val targets: NamedDomainObjectContainer<BCVTarget>
val targets: NamedDomainObjectContainer<BCVTarget> =
extensions.adding("targets") { objects.domainObjectContainer() }

@get:InputFiles
@get:PathSensitive(PathSensitivity.RELATIVE)
Expand Down