diff --git a/docs/changelog.md b/docs/changelog.md index b7d4d367b..96203e539 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -18,6 +18,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 disabledFeature("Feature") } ``` +- Dependencies can now selectively contribute to generation process. + ```groovy + laboratory { + featureFactory() + featureSourceFactory() + sourcedStorage() + optionFactory() + + dependency(project(":feature"), [ + DependencyContribution.FeatureFactory, + DependencyContribution.FeatureSourceFactory, + DependencyContribution.OptionFactory, + DependencyContribution.SourcedStorage, + ]) + } + ``` ### Changed - Gradle tasks are now always registered when plugin is applied in a project. If there is nothing to generate tasks will clear their respective output directories. diff --git a/docs/gradle-plugin.md b/docs/gradle-plugin.md index 3b974a7de..b4a6429f2 100644 --- a/docs/gradle-plugin.md +++ b/docs/gradle-plugin.md @@ -658,6 +658,9 @@ laboratory { // Includes feature flags that are used for generation of feature factories, sourced storage and option factory. dependency(project(":some-project")) + // By default dependency contributes to all declared generators but it can be selectively applied + // by passing a contribution list. + dependency(project(":some-project"), [DependencyContribution.FeatureFactory, DependencyContribution.OptionFactory]) // If typesafe project accessors are enabled. dependency(projects.someProject) } diff --git a/laboratory/gradle-plugin/api/gradle-plugin.api b/laboratory/gradle-plugin/api/gradle-plugin.api index a91f62f87..3ed5778fd 100644 --- a/laboratory/gradle-plugin/api/gradle-plugin.api +++ b/laboratory/gradle-plugin/api/gradle-plugin.api @@ -8,6 +8,16 @@ public final class io/mehow/laboratory/gradle/ChildFeatureFlagsInput : java/io/S public final fun feature (Ljava/lang/String;Lorg/gradle/api/Action;)V } +public final class io/mehow/laboratory/gradle/DependencyContribution : java/lang/Enum { + public static final field FeatureFactory Lio/mehow/laboratory/gradle/DependencyContribution; + public static final field FeatureSourceFactory Lio/mehow/laboratory/gradle/DependencyContribution; + public static final field OptionFactory Lio/mehow/laboratory/gradle/DependencyContribution; + public static final field SourcedStorage Lio/mehow/laboratory/gradle/DependencyContribution; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lio/mehow/laboratory/gradle/DependencyContribution; + public static fun values ()[Lio/mehow/laboratory/gradle/DependencyContribution; +} + public final class io/mehow/laboratory/gradle/DeprecationLevel : java/lang/Enum { public static final field Error Lio/mehow/laboratory/gradle/DeprecationLevel; public static final field Hidden Lio/mehow/laboratory/gradle/DeprecationLevel; @@ -68,7 +78,11 @@ public final class io/mehow/laboratory/gradle/FeatureFlagInput$MultiOption : io/ public abstract class io/mehow/laboratory/gradle/LaboratoryExtension { public fun ()V public final fun dependency (Lorg/gradle/api/Project;)V + public final fun dependency (Lorg/gradle/api/Project;Ljava/util/Collection;)V public final fun dependency (Lorg/gradle/api/internal/catalog/DelegatingProjectDependency;)V + public final fun dependency (Lorg/gradle/api/internal/catalog/DelegatingProjectDependency;Ljava/util/Collection;)V + public static synthetic fun dependency$default (Lio/mehow/laboratory/gradle/LaboratoryExtension;Lorg/gradle/api/Project;Ljava/util/Collection;ILjava/lang/Object;)V + public static synthetic fun dependency$default (Lio/mehow/laboratory/gradle/LaboratoryExtension;Lorg/gradle/api/internal/catalog/DelegatingProjectDependency;Ljava/util/Collection;ILjava/lang/Object;)V public final fun disabledFeature (Ljava/lang/String;)V public final fun disabledFeature (Ljava/lang/String;Lorg/gradle/api/Action;)V public static synthetic fun disabledFeature$default (Lio/mehow/laboratory/gradle/LaboratoryExtension;Ljava/lang/String;Lorg/gradle/api/Action;ILjava/lang/Object;)V diff --git a/laboratory/gradle-plugin/src/main/kotlin/io/mehow/laboratory/gradle/DependencyContribution.kt b/laboratory/gradle-plugin/src/main/kotlin/io/mehow/laboratory/gradle/DependencyContribution.kt new file mode 100644 index 000000000..11c179c28 --- /dev/null +++ b/laboratory/gradle-plugin/src/main/kotlin/io/mehow/laboratory/gradle/DependencyContribution.kt @@ -0,0 +1,19 @@ +package io.mehow.laboratory.gradle + +/** + * Possible contributions of a dependency to feature flag generation. See [LaboratoryExtension.dependency] + * for more info. + */ +public enum class DependencyContribution { + /** Contribute to [LaboratoryExtension.featureFactory]. */ + FeatureFactory, + + /** Contribute to [LaboratoryExtension.featureSourceFactory]. */ + FeatureSourceFactory, + + /** Contribute to [LaboratoryExtension.optionFactory]. */ + OptionFactory, + + /** Contribute to [LaboratoryExtension.sourcedStorage]. */ + SourcedStorage, +} diff --git a/laboratory/gradle-plugin/src/main/kotlin/io/mehow/laboratory/gradle/LaboratoryExtension.kt b/laboratory/gradle-plugin/src/main/kotlin/io/mehow/laboratory/gradle/LaboratoryExtension.kt index 94d1b033b..105fdf949 100644 --- a/laboratory/gradle-plugin/src/main/kotlin/io/mehow/laboratory/gradle/LaboratoryExtension.kt +++ b/laboratory/gradle-plugin/src/main/kotlin/io/mehow/laboratory/gradle/LaboratoryExtension.kt @@ -20,9 +20,13 @@ public abstract class LaboratoryExtension { private val packageNameProvider = PackageNameProvider() - private val mutableDependencies = mutableListOf() + private val externalDependencies = mutableMapOf>() - internal val factoryFeatureFlags get() = featureFlags + mutableDependencies + internal val factoryFeatureFlags get() = buildMap { + DependencyContribution.entries.forEach { entry -> + put(entry, featureFlags + externalDependencies[entry].orEmpty()) + } + } internal lateinit var project: Project @@ -147,21 +151,38 @@ public abstract class LaboratoryExtension { /** * Includes a [project] during feature flags contribution to [featureFactory], [featureSourcesFactory], - * [sourcedStorage] or [optionFactory]. Included project must have Laboratory plugin applied. + * [sourcedStorage] or [optionFactory]. Contribution can be selective applied by supplying [contributeTo] collection. + * + * Included project must have Laboratory plugin applied. */ - public fun dependency(project: DelegatingProjectDependency) { - dependency(project.dependencyProject) + @JvmOverloads + public fun dependency( + project: DelegatingProjectDependency, + contributeTo: Collection = DependencyContribution.entries, + ) { + dependency(project.dependencyProject, contributeTo) } /** * Includes a [project] during feature flags contribution to [featureFactory], [featureSourcesFactory], - * [sourcedStorage] or [optionFactory]. Included project must have Laboratory plugin applied. + * [sourcedStorage] or [optionFactory]. Contribution can be selective applied by supplying [contributeTo] collection. + * + * Included project must have Laboratory plugin applied. */ - public fun dependency(project: Project) { + @JvmOverloads + public fun dependency( + project: Project, + contributeTo: Collection = DependencyContribution.entries, + ) { + require(contributeTo.isNotEmpty()) { + "Dependency in project '${this.project.name}' on '${project.name}' must have at least one contribution" + } this.project.evaluationDependsOn(project.path) val laboratoryExtension = requireNotNull(project.extensions.findByType(LaboratoryExtension::class.java)) { "Cannot depend on a project without laboratory plugin" } - mutableDependencies += laboratoryExtension.featureFlags + contributeTo.forEach { entry -> + externalDependencies[entry] = externalDependencies[entry].orEmpty() + laboratoryExtension.featureFlags + } } } diff --git a/laboratory/gradle-plugin/src/main/kotlin/io/mehow/laboratory/gradle/LaboratoryPlugin.kt b/laboratory/gradle-plugin/src/main/kotlin/io/mehow/laboratory/gradle/LaboratoryPlugin.kt index 68eb4afbf..88ee50653 100644 --- a/laboratory/gradle-plugin/src/main/kotlin/io/mehow/laboratory/gradle/LaboratoryPlugin.kt +++ b/laboratory/gradle-plugin/src/main/kotlin/io/mehow/laboratory/gradle/LaboratoryPlugin.kt @@ -62,7 +62,7 @@ public class LaboratoryPlugin : Plugin { task.group = PluginName task.description = "Generate feature factory" task.factory.set(extension.factoryInput) - task.features.set(extension.factoryFeatureFlags) + task.features.set(extension.factoryFeatureFlags.getValue(DependencyContribution.FeatureFactory)) task.outputDirectory.set(layout.buildDirectory.dir("generated/laboratory/code/feature-factory")) } } @@ -75,7 +75,7 @@ public class LaboratoryPlugin : Plugin { task.group = PluginName task.description = "Generate sourced feature storage" task.storage.set(extension.storageInput) - task.features.set(extension.factoryFeatureFlags) + task.features.set(extension.factoryFeatureFlags.getValue(DependencyContribution.SourcedStorage)) task.outputDirectory.set(layout.buildDirectory.dir("generated/laboratory/code/sourced-storage")) } } @@ -88,7 +88,7 @@ public class LaboratoryPlugin : Plugin { task.group = PluginName task.description = "Generate option factory" task.factory.set(extension.optionFactoryInput) - task.features.set(extension.factoryFeatureFlags) + task.features.set(extension.factoryFeatureFlags.getValue(DependencyContribution.OptionFactory)) task.outputDirectory.set(layout.buildDirectory.dir("generated/laboratory/code/option-factory")) } } @@ -101,7 +101,7 @@ public class LaboratoryPlugin : Plugin { task.group = PluginName task.description = "Generate feature source factory" task.factory.set(extension.featureSourcesFactory) - task.features.set(extension.factoryFeatureFlags) + task.features.set(extension.factoryFeatureFlags.getValue(DependencyContribution.FeatureSourceFactory)) task.outputDirectory.set(layout.buildDirectory.dir("generated/laboratory/code/feature-source-factory")) } } diff --git a/laboratory/gradle-plugin/src/test/kotlin/io/mehow/laboratory/gradle/DependencyContributionSpec.kt b/laboratory/gradle-plugin/src/test/kotlin/io/mehow/laboratory/gradle/DependencyContributionSpec.kt new file mode 100644 index 000000000..06238259d --- /dev/null +++ b/laboratory/gradle-plugin/src/test/kotlin/io/mehow/laboratory/gradle/DependencyContributionSpec.kt @@ -0,0 +1,364 @@ +package io.mehow.laboratory.gradle + +import io.kotest.core.spec.style.FunSpec +import io.kotest.matchers.shouldBe +import io.kotest.matchers.string.shouldContain +import org.gradle.testkit.runner.GradleRunner +import org.gradle.testkit.runner.TaskOutcome + +class DependencyContributionSpec : FunSpec({ + lateinit var gradleRunner: GradleRunner + + cleanBuildDirs() + + beforeTest { + gradleRunner = GradleRunner.create() + .withPluginClasspath() + .withArguments( + "generateFeatureFactory", + "generateSourcedFeatureStorage", + "generateOptionFactory", + "generateFeatureSourceFactory", + "--stacktrace", + ) + } + + test("generates only feature factory") { + val fixture = "dependency-contribution-feature-factory".toFixture() + + val result = gradleRunner.withProjectDir(fixture).build() + + result.task(":generateFeatureFactory")!!.outcome shouldBe TaskOutcome.SUCCESS + result.task(":generateFeatureSourceFactory")!!.outcome shouldBe TaskOutcome.SUCCESS + result.task(":generateOptionFactory")!!.outcome shouldBe TaskOutcome.SUCCESS + result.task(":generateSourcedFeatureStorage")!!.outcome shouldBe TaskOutcome.SUCCESS + + fixture.featureFactoryFile("GeneratedFeatureFactory").readText() shouldContain """ + |private object GeneratedFeatureFactory : FeatureFactory { + | @Suppress("UNCHECKED_CAST") + | override fun create(): Set>> = setOf( + | Class.forName("FeatureA") + | ) as Set>> + |} + """.trimMargin() + + fixture.featureSourceStorageFile("GeneratedFeatureSourceFactory").readText() shouldContain """ + |private object GeneratedFeatureSourceFactory : FeatureFactory { + | override fun create(): Set>> = emptySet>>() + |} + """.trimMargin() + + fixture.optionFactoryFile("GeneratedOptionFactory").readText() shouldContain """ + |private object GeneratedOptionFactory : OptionFactory { + | override fun create(key: String, name: String): Feature<*>? = null + |} + """.trimMargin() + + fixture.sourcedStorageFile("SourcedGeneratedFeatureStorage").readText() shouldContain """ + |internal fun FeatureStorage.Companion.sourcedBuilder(localSource: FeatureStorage): BuildingStep = + | Builder(localSource, emptyMap()) + | + |internal interface BuildingStep { + | public fun build(): FeatureStorage + |} + | + |private data class Builder( + | private val localSource: FeatureStorage, + | private val remoteSources: Map, + |) : BuildingStep { + | override fun build(): FeatureStorage = sourced(localSource, remoteSources) + |} + """.trimMargin() + } + + test("generates only feature source factory") { + val fixture = "dependency-contribution-feature-source-factory".toFixture() + + val result = gradleRunner.withProjectDir(fixture).build() + + result.task(":generateFeatureFactory")!!.outcome shouldBe TaskOutcome.SUCCESS + result.task(":generateFeatureSourceFactory")!!.outcome shouldBe TaskOutcome.SUCCESS + result.task(":generateOptionFactory")!!.outcome shouldBe TaskOutcome.SUCCESS + result.task(":generateSourcedFeatureStorage")!!.outcome shouldBe TaskOutcome.SUCCESS + + fixture.featureFactoryFile("GeneratedFeatureFactory").readText() shouldContain """ + |private object GeneratedFeatureFactory : FeatureFactory { + | override fun create(): Set>> = emptySet>>() + |} + """.trimMargin() + + fixture.featureSourceStorageFile("GeneratedFeatureSourceFactory").readText() shouldContain """ + |private object GeneratedFeatureSourceFactory : FeatureFactory { + | @Suppress("UNCHECKED_CAST") + | override fun create(): Set>> = setOf( + | Class.forName("FeatureA${"\${'$'}"}Source") + | ) as Set>> + |} + """.trimMargin() + + fixture.optionFactoryFile("GeneratedOptionFactory").readText() shouldContain """ + |private object GeneratedOptionFactory : OptionFactory { + | override fun create(key: String, name: String): Feature<*>? = null + |} + """.trimMargin() + + fixture.sourcedStorageFile("SourcedGeneratedFeatureStorage").readText() shouldContain """ + |internal fun FeatureStorage.Companion.sourcedBuilder(localSource: FeatureStorage): BuildingStep = + | Builder(localSource, emptyMap()) + | + |internal interface BuildingStep { + | public fun build(): FeatureStorage + |} + | + |private data class Builder( + | private val localSource: FeatureStorage, + | private val remoteSources: Map, + |) : BuildingStep { + | override fun build(): FeatureStorage = sourced(localSource, remoteSources) + |} + """.trimMargin() + } + + test("generates only option factory") { + val fixture = "dependency-contribution-option-factory".toFixture() + + val result = gradleRunner.withProjectDir(fixture).build() + + result.task(":generateFeatureFactory")!!.outcome shouldBe TaskOutcome.SUCCESS + result.task(":generateFeatureSourceFactory")!!.outcome shouldBe TaskOutcome.SUCCESS + result.task(":generateOptionFactory")!!.outcome shouldBe TaskOutcome.SUCCESS + result.task(":generateSourcedFeatureStorage")!!.outcome shouldBe TaskOutcome.SUCCESS + + fixture.featureFactoryFile("GeneratedFeatureFactory").readText() shouldContain """ + |private object GeneratedFeatureFactory : FeatureFactory { + | override fun create(): Set>> = emptySet>>() + |} + """.trimMargin() + + fixture.featureSourceStorageFile("GeneratedFeatureSourceFactory").readText() shouldContain """ + |private object GeneratedFeatureSourceFactory : FeatureFactory { + | override fun create(): Set>> = emptySet>>() + |} + """.trimMargin() + + fixture.optionFactoryFile("GeneratedOptionFactory").readText() shouldContain """ + |private object GeneratedOptionFactory : OptionFactory { + | override fun create(key: String, name: String): Feature<*>? = when (key) { + | "FeatureA" -> when (name) { + | "First" -> FeatureA.First + | else -> null + | } + | else -> null + | } + |} + """.trimMargin() + + fixture.sourcedStorageFile("SourcedGeneratedFeatureStorage").readText() shouldContain """ + |internal fun FeatureStorage.Companion.sourcedBuilder(localSource: FeatureStorage): BuildingStep = + | Builder(localSource, emptyMap()) + | + |internal interface BuildingStep { + | public fun build(): FeatureStorage + |} + | + |private data class Builder( + | private val localSource: FeatureStorage, + | private val remoteSources: Map, + |) : BuildingStep { + | override fun build(): FeatureStorage = sourced(localSource, remoteSources) + |} + """.trimMargin() + } + + test("generates only sourced storage") { + val fixture = "dependency-contribution-sourced-storage".toFixture() + + val result = gradleRunner.withProjectDir(fixture).build() + + result.task(":generateFeatureFactory")!!.outcome shouldBe TaskOutcome.SUCCESS + result.task(":generateFeatureSourceFactory")!!.outcome shouldBe TaskOutcome.SUCCESS + result.task(":generateOptionFactory")!!.outcome shouldBe TaskOutcome.SUCCESS + result.task(":generateSourcedFeatureStorage")!!.outcome shouldBe TaskOutcome.SUCCESS + + fixture.featureFactoryFile("GeneratedFeatureFactory").readText() shouldContain """ + |private object GeneratedFeatureFactory : FeatureFactory { + | override fun create(): Set>> = emptySet>>() + |} + """.trimMargin() + + fixture.featureSourceStorageFile("GeneratedFeatureSourceFactory").readText() shouldContain """ + |private object GeneratedFeatureSourceFactory : FeatureFactory { + | override fun create(): Set>> = emptySet>>() + |} + """.trimMargin() + + fixture.optionFactoryFile("GeneratedOptionFactory").readText() shouldContain """ + |private object GeneratedOptionFactory : OptionFactory { + | override fun create(key: String, name: String): Feature<*>? = null + |} + """.trimMargin() + + fixture.sourcedStorageFile("SourcedGeneratedFeatureStorage").readText() shouldContain """ + |internal fun FeatureStorage.Companion.sourcedBuilder(localSource: FeatureStorage): RemoteStep = + | Builder(localSource, emptyMap()) + | + |internal interface RemoteStep { + | public fun remoteSource(source: FeatureStorage): BuildingStep + |} + | + |internal interface BuildingStep { + | public fun build(): FeatureStorage + |} + | + |private data class Builder( + | private val localSource: FeatureStorage, + | private val remoteSources: Map, + |) : RemoteStep, BuildingStep { + | override fun remoteSource(source: FeatureStorage): BuildingStep = copy( + | remoteSources = remoteSources + ("Remote" to source) + | ) + | + | override fun build(): FeatureStorage = sourced(localSource, remoteSources) + |} + """.trimMargin() + } + + test("generates all contributed features explicitly") { + val fixture = "dependency-contribution-all-explicit".toFixture() + + val result = gradleRunner.withProjectDir(fixture).build() + + result.task(":generateFeatureFactory")!!.outcome shouldBe TaskOutcome.SUCCESS + result.task(":generateFeatureSourceFactory")!!.outcome shouldBe TaskOutcome.SUCCESS + result.task(":generateOptionFactory")!!.outcome shouldBe TaskOutcome.SUCCESS + result.task(":generateSourcedFeatureStorage")!!.outcome shouldBe TaskOutcome.SUCCESS + + fixture.featureFactoryFile("GeneratedFeatureFactory").readText() shouldContain """ + |private object GeneratedFeatureFactory : FeatureFactory { + | @Suppress("UNCHECKED_CAST") + | override fun create(): Set>> = setOf( + | Class.forName("FeatureA") + | ) as Set>> + |} + """.trimMargin() + + fixture.featureSourceStorageFile("GeneratedFeatureSourceFactory").readText() shouldContain """ + |private object GeneratedFeatureSourceFactory : FeatureFactory { + | @Suppress("UNCHECKED_CAST") + | override fun create(): Set>> = setOf( + | Class.forName("FeatureA${"\${'$'}"}Source") + | ) as Set>> + |} + """.trimMargin() + + fixture.optionFactoryFile("GeneratedOptionFactory").readText() shouldContain """ + |private object GeneratedOptionFactory : OptionFactory { + | override fun create(key: String, name: String): Feature<*>? = when (key) { + | "FeatureA" -> when (name) { + | "First" -> FeatureA.First + | else -> null + | } + | else -> null + | } + |} + """.trimMargin() + + fixture.sourcedStorageFile("SourcedGeneratedFeatureStorage").readText() shouldContain """ + |internal fun FeatureStorage.Companion.sourcedBuilder(localSource: FeatureStorage): RemoteStep = + | Builder(localSource, emptyMap()) + | + |internal interface RemoteStep { + | public fun remoteSource(source: FeatureStorage): BuildingStep + |} + | + |internal interface BuildingStep { + | public fun build(): FeatureStorage + |} + | + |private data class Builder( + | private val localSource: FeatureStorage, + | private val remoteSources: Map, + |) : RemoteStep, BuildingStep { + | override fun remoteSource(source: FeatureStorage): BuildingStep = copy( + | remoteSources = remoteSources + ("Remote" to source) + | ) + | + | override fun build(): FeatureStorage = sourced(localSource, remoteSources) + |} + """.trimMargin() + } + + test("generates all contributed features implicitly") { + val fixture = "dependency-contribution-all-implicit".toFixture() + + val result = gradleRunner.withProjectDir(fixture).build() + + result.task(":generateFeatureFactory")!!.outcome shouldBe TaskOutcome.SUCCESS + result.task(":generateFeatureSourceFactory")!!.outcome shouldBe TaskOutcome.SUCCESS + result.task(":generateOptionFactory")!!.outcome shouldBe TaskOutcome.SUCCESS + result.task(":generateSourcedFeatureStorage")!!.outcome shouldBe TaskOutcome.SUCCESS + + fixture.featureFactoryFile("GeneratedFeatureFactory").readText() shouldContain """ + |private object GeneratedFeatureFactory : FeatureFactory { + | @Suppress("UNCHECKED_CAST") + | override fun create(): Set>> = setOf( + | Class.forName("FeatureA") + | ) as Set>> + |} + """.trimMargin() + + fixture.featureSourceStorageFile("GeneratedFeatureSourceFactory").readText() shouldContain """ + |private object GeneratedFeatureSourceFactory : FeatureFactory { + | @Suppress("UNCHECKED_CAST") + | override fun create(): Set>> = setOf( + | Class.forName("FeatureA${"\${'$'}"}Source") + | ) as Set>> + |} + """.trimMargin() + + fixture.optionFactoryFile("GeneratedOptionFactory").readText() shouldContain """ + |private object GeneratedOptionFactory : OptionFactory { + | override fun create(key: String, name: String): Feature<*>? = when (key) { + | "FeatureA" -> when (name) { + | "First" -> FeatureA.First + | else -> null + | } + | else -> null + | } + |} + """.trimMargin() + + fixture.sourcedStorageFile("SourcedGeneratedFeatureStorage").readText() shouldContain """ + |internal fun FeatureStorage.Companion.sourcedBuilder(localSource: FeatureStorage): RemoteStep = + | Builder(localSource, emptyMap()) + | + |internal interface RemoteStep { + | public fun remoteSource(source: FeatureStorage): BuildingStep + |} + | + |internal interface BuildingStep { + | public fun build(): FeatureStorage + |} + | + |private data class Builder( + | private val localSource: FeatureStorage, + | private val remoteSources: Map, + |) : RemoteStep, BuildingStep { + | override fun remoteSource(source: FeatureStorage): BuildingStep = copy( + | remoteSources = remoteSources + ("Remote" to source) + | ) + | + | override fun build(): FeatureStorage = sourced(localSource, remoteSources) + |} + """.trimMargin() + } + + test("fails to depend on a project with no contributions") { + val fixture = "dependency-contribution-none".toFixture() + + val result = gradleRunner.withProjectDir(fixture).buildAndFail() + + @Suppress("MaxLineLength") + result.output shouldContain "Dependency in project 'dependency-contribution-none' on 'feature' must have at least one contribution" + } +}) diff --git a/laboratory/gradle-plugin/src/test/projects/dependency-contribution-all-explicit/build.gradle b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-all-explicit/build.gradle new file mode 100644 index 000000000..da111e966 --- /dev/null +++ b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-all-explicit/build.gradle @@ -0,0 +1,20 @@ +import io.mehow.laboratory.gradle.DependencyContribution + +plugins { + id "org.jetbrains.kotlin.jvm" + id "io.mehow.laboratory" +} + +laboratory { + featureFactory() + featureSourceFactory() + sourcedStorage() + optionFactory() + + dependency(project(":feature"), [ + DependencyContribution.FeatureFactory, + DependencyContribution.FeatureSourceFactory, + DependencyContribution.OptionFactory, + DependencyContribution.SourcedStorage, + ]) +} diff --git a/laboratory/gradle-plugin/src/test/projects/dependency-contribution-all-explicit/feature/build.gradle b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-all-explicit/feature/build.gradle new file mode 100644 index 000000000..c60290109 --- /dev/null +++ b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-all-explicit/feature/build.gradle @@ -0,0 +1,12 @@ +plugins { + id "org.jetbrains.kotlin.jvm" + id "io.mehow.laboratory" +} + +laboratory { + feature("FeatureA") { + withDefaultOption("First") + + withSource("Remote") + } +} diff --git a/laboratory/gradle-plugin/src/test/projects/dependency-contribution-all-explicit/settings.gradle b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-all-explicit/settings.gradle new file mode 100644 index 000000000..baef9cf87 --- /dev/null +++ b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-all-explicit/settings.gradle @@ -0,0 +1 @@ +include ":feature" diff --git a/laboratory/gradle-plugin/src/test/projects/dependency-contribution-all-implicit/build.gradle b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-all-implicit/build.gradle new file mode 100644 index 000000000..36da2ed07 --- /dev/null +++ b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-all-implicit/build.gradle @@ -0,0 +1,15 @@ +import io.mehow.laboratory.gradle.DependencyContribution + +plugins { + id "org.jetbrains.kotlin.jvm" + id "io.mehow.laboratory" +} + +laboratory { + featureFactory() + featureSourceFactory() + sourcedStorage() + optionFactory() + + dependency(project(":feature"), [DependencyContribution.FeatureFactory, DependencyContribution.FeatureSourceFactory, DependencyContribution.OptionFactory, DependencyContribution.SourcedStorage]) +} diff --git a/laboratory/gradle-plugin/src/test/projects/dependency-contribution-all-implicit/feature/build.gradle b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-all-implicit/feature/build.gradle new file mode 100644 index 000000000..c60290109 --- /dev/null +++ b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-all-implicit/feature/build.gradle @@ -0,0 +1,12 @@ +plugins { + id "org.jetbrains.kotlin.jvm" + id "io.mehow.laboratory" +} + +laboratory { + feature("FeatureA") { + withDefaultOption("First") + + withSource("Remote") + } +} diff --git a/laboratory/gradle-plugin/src/test/projects/dependency-contribution-all-implicit/settings.gradle b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-all-implicit/settings.gradle new file mode 100644 index 000000000..baef9cf87 --- /dev/null +++ b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-all-implicit/settings.gradle @@ -0,0 +1 @@ +include ":feature" diff --git a/laboratory/gradle-plugin/src/test/projects/dependency-contribution-feature-factory/build.gradle b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-feature-factory/build.gradle new file mode 100644 index 000000000..d82ddd8d0 --- /dev/null +++ b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-feature-factory/build.gradle @@ -0,0 +1,15 @@ +import io.mehow.laboratory.gradle.DependencyContribution + +plugins { + id "org.jetbrains.kotlin.jvm" + id "io.mehow.laboratory" +} + +laboratory { + featureFactory() + featureSourceFactory() + sourcedStorage() + optionFactory() + + dependency(project(":feature"), [DependencyContribution.FeatureFactory]) +} diff --git a/laboratory/gradle-plugin/src/test/projects/dependency-contribution-feature-factory/feature/build.gradle b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-feature-factory/feature/build.gradle new file mode 100644 index 000000000..c60290109 --- /dev/null +++ b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-feature-factory/feature/build.gradle @@ -0,0 +1,12 @@ +plugins { + id "org.jetbrains.kotlin.jvm" + id "io.mehow.laboratory" +} + +laboratory { + feature("FeatureA") { + withDefaultOption("First") + + withSource("Remote") + } +} diff --git a/laboratory/gradle-plugin/src/test/projects/dependency-contribution-feature-factory/settings.gradle b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-feature-factory/settings.gradle new file mode 100644 index 000000000..baef9cf87 --- /dev/null +++ b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-feature-factory/settings.gradle @@ -0,0 +1 @@ +include ":feature" diff --git a/laboratory/gradle-plugin/src/test/projects/dependency-contribution-feature-source-factory/build.gradle b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-feature-source-factory/build.gradle new file mode 100644 index 000000000..e467f8f16 --- /dev/null +++ b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-feature-source-factory/build.gradle @@ -0,0 +1,15 @@ +import io.mehow.laboratory.gradle.DependencyContribution + +plugins { + id "org.jetbrains.kotlin.jvm" + id "io.mehow.laboratory" +} + +laboratory { + featureFactory() + featureSourceFactory() + sourcedStorage() + optionFactory() + + dependency(project(":feature"), [DependencyContribution.FeatureSourceFactory]) +} diff --git a/laboratory/gradle-plugin/src/test/projects/dependency-contribution-feature-source-factory/feature/build.gradle b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-feature-source-factory/feature/build.gradle new file mode 100644 index 000000000..c60290109 --- /dev/null +++ b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-feature-source-factory/feature/build.gradle @@ -0,0 +1,12 @@ +plugins { + id "org.jetbrains.kotlin.jvm" + id "io.mehow.laboratory" +} + +laboratory { + feature("FeatureA") { + withDefaultOption("First") + + withSource("Remote") + } +} diff --git a/laboratory/gradle-plugin/src/test/projects/dependency-contribution-feature-source-factory/settings.gradle b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-feature-source-factory/settings.gradle new file mode 100644 index 000000000..baef9cf87 --- /dev/null +++ b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-feature-source-factory/settings.gradle @@ -0,0 +1 @@ +include ":feature" diff --git a/laboratory/gradle-plugin/src/test/projects/dependency-contribution-none/build.gradle b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-none/build.gradle new file mode 100644 index 000000000..440b3bfa9 --- /dev/null +++ b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-none/build.gradle @@ -0,0 +1,13 @@ +plugins { + id "org.jetbrains.kotlin.jvm" + id "io.mehow.laboratory" +} + +laboratory { + featureFactory() + featureSourceFactory() + sourcedStorage() + optionFactory() + + dependency(project(":feature"), []) +} diff --git a/laboratory/gradle-plugin/src/test/projects/dependency-contribution-none/feature/build.gradle b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-none/feature/build.gradle new file mode 100644 index 000000000..c60290109 --- /dev/null +++ b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-none/feature/build.gradle @@ -0,0 +1,12 @@ +plugins { + id "org.jetbrains.kotlin.jvm" + id "io.mehow.laboratory" +} + +laboratory { + feature("FeatureA") { + withDefaultOption("First") + + withSource("Remote") + } +} diff --git a/laboratory/gradle-plugin/src/test/projects/dependency-contribution-none/settings.gradle b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-none/settings.gradle new file mode 100644 index 000000000..baef9cf87 --- /dev/null +++ b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-none/settings.gradle @@ -0,0 +1 @@ +include ":feature" diff --git a/laboratory/gradle-plugin/src/test/projects/dependency-contribution-option-factory/build.gradle b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-option-factory/build.gradle new file mode 100644 index 000000000..ec410a0fd --- /dev/null +++ b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-option-factory/build.gradle @@ -0,0 +1,15 @@ +import io.mehow.laboratory.gradle.DependencyContribution + +plugins { + id "org.jetbrains.kotlin.jvm" + id "io.mehow.laboratory" +} + +laboratory { + featureFactory() + featureSourceFactory() + sourcedStorage() + optionFactory() + + dependency(project(":feature"), [DependencyContribution.OptionFactory]) +} diff --git a/laboratory/gradle-plugin/src/test/projects/dependency-contribution-option-factory/feature/build.gradle b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-option-factory/feature/build.gradle new file mode 100644 index 000000000..c60290109 --- /dev/null +++ b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-option-factory/feature/build.gradle @@ -0,0 +1,12 @@ +plugins { + id "org.jetbrains.kotlin.jvm" + id "io.mehow.laboratory" +} + +laboratory { + feature("FeatureA") { + withDefaultOption("First") + + withSource("Remote") + } +} diff --git a/laboratory/gradle-plugin/src/test/projects/dependency-contribution-option-factory/settings.gradle b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-option-factory/settings.gradle new file mode 100644 index 000000000..baef9cf87 --- /dev/null +++ b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-option-factory/settings.gradle @@ -0,0 +1 @@ +include ":feature" diff --git a/laboratory/gradle-plugin/src/test/projects/dependency-contribution-sourced-storage/build.gradle b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-sourced-storage/build.gradle new file mode 100644 index 000000000..f341c9470 --- /dev/null +++ b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-sourced-storage/build.gradle @@ -0,0 +1,15 @@ +import io.mehow.laboratory.gradle.DependencyContribution + +plugins { + id "org.jetbrains.kotlin.jvm" + id "io.mehow.laboratory" +} + +laboratory { + featureFactory() + featureSourceFactory() + sourcedStorage() + optionFactory() + + dependency(project(":feature"), [DependencyContribution.SourcedStorage]) +} diff --git a/laboratory/gradle-plugin/src/test/projects/dependency-contribution-sourced-storage/feature/build.gradle b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-sourced-storage/feature/build.gradle new file mode 100644 index 000000000..c60290109 --- /dev/null +++ b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-sourced-storage/feature/build.gradle @@ -0,0 +1,12 @@ +plugins { + id "org.jetbrains.kotlin.jvm" + id "io.mehow.laboratory" +} + +laboratory { + feature("FeatureA") { + withDefaultOption("First") + + withSource("Remote") + } +} diff --git a/laboratory/gradle-plugin/src/test/projects/dependency-contribution-sourced-storage/settings.gradle b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-sourced-storage/settings.gradle new file mode 100644 index 000000000..baef9cf87 --- /dev/null +++ b/laboratory/gradle-plugin/src/test/projects/dependency-contribution-sourced-storage/settings.gradle @@ -0,0 +1 @@ +include ":feature"