diff --git a/kover-gradle-plugin/api/kover-gradle-plugin.api b/kover-gradle-plugin/api/kover-gradle-plugin.api index 77fb0ea4..ebeb8728 100644 --- a/kover-gradle-plugin/api/kover-gradle-plugin.api +++ b/kover-gradle-plugin/api/kover-gradle-plugin.api @@ -42,6 +42,7 @@ public abstract interface class kotlinx/kover/gradle/plugin/dsl/KoverBinaryTaskC } public abstract interface class kotlinx/kover/gradle/plugin/dsl/KoverCurrentProjectVariantsConfig : kotlinx/kover/gradle/plugin/dsl/KoverVariantConfig { + public abstract fun copyVariant (Ljava/lang/String;Ljava/lang/String;)V public abstract fun createVariant (Ljava/lang/String;Lorg/gradle/api/Action;)V public abstract fun instrumentation (Lorg/gradle/api/Action;)V public abstract fun providedVariant (Ljava/lang/String;Lorg/gradle/api/Action;)V diff --git a/kover-gradle-plugin/src/main/kotlin/kotlinx/kover/gradle/plugin/appliers/FinalizeKover.kt b/kover-gradle-plugin/src/main/kotlin/kotlinx/kover/gradle/plugin/appliers/FinalizeKover.kt index 3cdcfe65..26431ed3 100644 --- a/kover-gradle-plugin/src/main/kotlin/kotlinx/kover/gradle/plugin/appliers/FinalizeKover.kt +++ b/kover-gradle-plugin/src/main/kotlin/kotlinx/kover/gradle/plugin/appliers/FinalizeKover.kt @@ -17,7 +17,6 @@ import kotlinx.kover.gradle.plugin.commons.ReportVariantType import kotlinx.kover.gradle.plugin.commons.TOTAL_VARIANT_NAME import kotlinx.kover.gradle.plugin.dsl.internal.KoverReportSetConfigImpl import kotlinx.kover.gradle.plugin.dsl.internal.KoverVariantCreateConfigImpl -import org.gradle.api.provider.Provider import org.gradle.kotlin.dsl.newInstance @@ -59,13 +58,6 @@ internal fun KoverContext.finalizing(origins: AllVariantOrigins) { jvmVariant?.let { variantArtifacts[JVM_VARIANT_NAME] = it } androidVariants.forEach { variantArtifacts[it.variantName] = it } - val availableVariants = variantArtifacts.keys + projectExtension.current.customVariants.keys - projectExtension.reports.byName.forEach { (requestedVariant, _) -> - if (requestedVariant !in availableVariants) { - throw KoverIllegalConfigException("It is not possible to configure the '$requestedVariant' variant because it does not exist") - } - } - val totalVariant = TotalVariantArtifacts(project, toolProvider, koverBucketConfiguration, variantConfig(TOTAL_VARIANT_NAME), projectExtension) variantArtifacts.values.forEach { totalVariant.mergeWith(it) } @@ -103,6 +95,8 @@ internal fun KoverContext.finalizing(origins: AllVariantOrigins) { } } + variantArtifacts[name] = customVariant + VariantReportsSet( project, name, @@ -112,7 +106,21 @@ internal fun KoverContext.finalizing(origins: AllVariantOrigins) { reporterClasspath, projectExtension.koverDisabled ).assign(customVariant) + } + + projectExtension.current.variantsToCopy.forEach { (name, originVariantName) -> + val originalVariant = variantArtifacts[originVariantName] + ?: throw KoverIllegalConfigException("Cannot create a variant '$name': the original variant '$originVariantName' does not exist.") + VariantReportsSet( + project, + name, + ReportVariantType.CUSTOM, + toolProvider, + reportsConfig(name, project.path), + reporterClasspath, + projectExtension.koverDisabled + ).assign(originalVariant) } androidVariants.forEach { androidVariant -> @@ -126,6 +134,12 @@ internal fun KoverContext.finalizing(origins: AllVariantOrigins) { projectExtension.koverDisabled ).assign(androidVariant) } + + projectExtension.reports.byName.forEach { (requestedVariant, _) -> + if (requestedVariant !in variantArtifacts && requestedVariant !in projectExtension.current.variantsToCopy) { + throw KoverIllegalConfigException("It is not possible to configure the '$requestedVariant' variant because it does not exist") + } + } } private fun KoverContext.variantConfig(variantName: String): KoverVariantCreateConfigImpl { diff --git a/kover-gradle-plugin/src/main/kotlin/kotlinx/kover/gradle/plugin/dsl/KoverProjectExtension.kt b/kover-gradle-plugin/src/main/kotlin/kotlinx/kover/gradle/plugin/dsl/KoverProjectExtension.kt index b56f81ab..de87a638 100644 --- a/kover-gradle-plugin/src/main/kotlin/kotlinx/kover/gradle/plugin/dsl/KoverProjectExtension.kt +++ b/kover-gradle-plugin/src/main/kotlin/kotlinx/kover/gradle/plugin/dsl/KoverProjectExtension.kt @@ -61,6 +61,9 @@ public interface KoverProjectExtension { * // ... * } * + * // copy report variant with different name but the same content + * copyVariant("copyName", "custom") + * * // Configure the variant that is automatically created in the current project * // For example, "jvm" for JVM target or "debug" for Android build variant * providedVariant("jvm") { diff --git a/kover-gradle-plugin/src/main/kotlin/kotlinx/kover/gradle/plugin/dsl/KoverVariantConfig.kt b/kover-gradle-plugin/src/main/kotlin/kotlinx/kover/gradle/plugin/dsl/KoverVariantConfig.kt index 9c3620ee..db0d0139 100644 --- a/kover-gradle-plugin/src/main/kotlin/kotlinx/kover/gradle/plugin/dsl/KoverVariantConfig.kt +++ b/kover-gradle-plugin/src/main/kotlin/kotlinx/kover/gradle/plugin/dsl/KoverVariantConfig.kt @@ -46,6 +46,15 @@ public interface KoverCurrentProjectVariantsConfig: KoverVariantConfig { */ public fun createVariant(variantName: String, block: Action) + /** + * Create custom report variant as a copy of the [originalVariantName] variant, however, with the new name [variantName]. + * + * Copying variants is useful when you have a single variant with coverage information but want to apply different filters for it: + * You cannot configure the copied variant with [KoverVariantCreateConfig], i.e., add information from other variants to the new one. + * However, you can define report filters and rules for it using `reports { variant(variantName) { ... }}`. + */ + public fun copyVariant(variantName: String, originalVariantName: String) + /** * Configure the variant with name [variantName] that is automatically created in the current project. * For example, `"jvm"` for JVM target or `"debug"` for Android build variant. diff --git a/kover-gradle-plugin/src/main/kotlin/kotlinx/kover/gradle/plugin/dsl/internal/VariantsImpl.kt b/kover-gradle-plugin/src/main/kotlin/kotlinx/kover/gradle/plugin/dsl/internal/VariantsImpl.kt index 88d99148..e4a9bae1 100644 --- a/kover-gradle-plugin/src/main/kotlin/kotlinx/kover/gradle/plugin/dsl/internal/VariantsImpl.kt +++ b/kover-gradle-plugin/src/main/kotlin/kotlinx/kover/gradle/plugin/dsl/internal/VariantsImpl.kt @@ -9,7 +9,6 @@ import kotlinx.kover.gradle.plugin.commons.TOTAL_VARIANT_NAME import kotlinx.kover.gradle.plugin.dsl.* import org.gradle.api.Action import org.gradle.api.model.ObjectFactory -import org.gradle.api.provider.Property import org.gradle.kotlin.dsl.newInstance import javax.inject.Inject @@ -17,6 +16,7 @@ internal abstract class KoverCurrentProjectVariantsConfigImpl @Inject constructo KoverVariantConfigImpl(objects), KoverCurrentProjectVariantsConfig { internal val customVariants: MutableMap = mutableMapOf() internal val providedVariants: MutableMap = mutableMapOf() + internal val variantsToCopy: MutableMap = mutableMapOf() internal val instrumentation: KoverProjectInstrumentation = objects.newInstance() init { @@ -42,6 +42,13 @@ internal abstract class KoverCurrentProjectVariantsConfigImpl @Inject constructo block.execute(variantConfig) } + override fun copyVariant(variantName: String, originalVariantName: String) { + if (variantName in variantsToCopy) { + throw KoverIllegalConfigException("The copy of custom variant with name $variantName already created.") + } + variantsToCopy[variantName] = originalVariantName + } + override fun providedVariant(variantName: String, block: Action) { if (variantName == TOTAL_VARIANT_NAME) { throw KoverIllegalConfigException("The provided variant name cannot be empty.")