All Downloads are FREE. Search and download functionalities are using the official Maven repository.

kotlinx.kover.gradle.plugin.appliers.tasks.VariantReportsSet.kt Maven / Gradle / Ivy

There is a newer version: 0.9.0-RC
Show newest version
/*
 * Copyright 2017-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
 */

package kotlinx.kover.gradle.plugin.appliers.tasks

import kotlinx.kover.gradle.plugin.appliers.artifacts.AbstractVariantArtifacts
import kotlinx.kover.gradle.plugin.commons.*
import kotlinx.kover.gradle.plugin.dsl.KoverVerifyBound
import kotlinx.kover.gradle.plugin.dsl.internal.KoverReportFiltersConfigImpl
import kotlinx.kover.gradle.plugin.dsl.internal.KoverReportSetConfigImpl
import kotlinx.kover.gradle.plugin.dsl.internal.KoverVerifyRuleImpl
import kotlinx.kover.gradle.plugin.tasks.reports.*
import kotlinx.kover.gradle.plugin.tasks.services.KoverPrintLogTask
import kotlinx.kover.gradle.plugin.tools.CoverageTool
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.artifacts.Configuration
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.TaskContainer
import org.gradle.api.tasks.TaskProvider
import org.gradle.kotlin.dsl.register
import org.gradle.language.base.plugins.LifecycleBasePlugin


internal class VariantReportsSet(
    private val project: Project,
    private val variantName: String,
    private val type: ReportVariantType,
    private val toolProvider: Provider,
    private val config: KoverReportSetConfigImpl,
    private val reporterConfiguration: Configuration,
    private val koverDisabled: Provider
) {
    private val htmlTask: TaskProvider
    private val xmlTask: TaskProvider
    private val binTask: TaskProvider
    private val doVerifyTask: TaskProvider
    private val logTask: TaskProvider

    init {
        htmlTask = project.tasks.createReportTask(
            htmlReportTaskName(variantName),
            "Task to generate HTML coverage report for ${variantSuffix()}"
        )
        xmlTask = project.tasks.createReportTask(
            xmlReportTaskName(variantName),
            "Task to generate XML coverage report for ${variantSuffix()}"
        )
        binTask = project.tasks.createReportTask(
            binaryReportTaskName(variantName),
            "Task to generate binary coverage report in IntelliJ format for ${variantSuffix()}"
        )

        doVerifyTask = project.tasks.createReportTask(
            verifyCachedTaskName(variantName),
            "Task to validate coverage bounding rules for ${variantSuffix()}"
        )
        val verifyTask = project.tasks.register(verifyTaskName(variantName))

        logTask = project.tasks.createReportTask(
            logTaskName(variantName),
            "Task to print coverage to log for ${variantSuffix()}"
        )
        val printCoverageTask = project.tasks.register(printLogTaskName(variantName))

        val runOnCheck = mutableListOf>>>()

        htmlTask.configure {
            onlyIf { printPath(); true }

            reportDir.convention(config.html.htmlDir)
            title.convention(config.html.title.orElse(project.name))
            charset.convention(config.html.charset)
            filters.set((config.filters).convert())
        }
        runOnCheck += config.html.onCheck.map { run ->
            if (run) listOf(htmlTask) else emptyList()
        }

        xmlTask.configure {
            reportFile.convention(config.xml.xmlFile)
            title.convention(config.xml.title)
            filters.set((config.filters).convert())
        }
        runOnCheck += config.xml.onCheck.map { run ->
            if (run) listOf(xmlTask) else emptyList()
        }

        binTask.configure {
            file.convention(config.binary.file)
            filters.set((config.filters).convert())
        }
        runOnCheck += config.binary.onCheck.map { run ->
            if (run) listOf(binTask) else emptyList()
        }


        doVerifyTask.configure {
            val resultRules = config.verify.rules
            val converted = resultRules.map { rules -> rules.map { it.convert() } }

            filters.set((config.filters).convert())
            rules.addAll(converted)

            // path can't be changed
            resultFile.convention(project.layout.buildDirectory.file(verificationErrorsPath(variantName)))

            description = "Cacheable task for performing verification for ${variantSuffix()}"
        }
        verifyTask.configure {
            warningInsteadOfFailure.convention(config.verify.warningInsteadOfFailure)
            errorFile.convention(doVerifyTask.flatMap { it.resultFile })

            shouldRunAfter(htmlTask)
            shouldRunAfter(xmlTask)
            shouldRunAfter(binTask)
            shouldRunAfter(logTask)

            dependsOn(doVerifyTask)

            group = LifecycleBasePlugin.VERIFICATION_GROUP

            // always execute
            outputs.upToDateWhen { false }

            val koverDisabledProvider = koverDisabled
            onlyIf { !koverDisabledProvider.get() }
        }
        runOnCheck += config.verify.onCheck.map { run ->
            if (run) listOf(verifyTask) else emptyList()
        }

        printCoverageTask.configure {
            fileWithMessage.convention(logTask.flatMap { it.outputFile })
            onlyIf {
                fileWithMessage.asFile.get().exists()
            }

            // always execute
            outputs.upToDateWhen { false }
        }

        logTask.configure {
            header.convention(config.log.header)
            lineFormat.convention(config.log.format)
            groupBy.convention(config.log.groupBy)
            coverageUnits.convention(config.log.coverageUnits)
            aggregationForGroup.convention(config.log.aggregationForGroup)

            outputFile.convention(project.layout.buildDirectory.file(coverageLogPath(variantName)))

            filters.set((config.filters).convert())

            finalizedBy(printCoverageTask)
        }
        runOnCheck += config.log.onCheck.map { run ->
            if (run) listOf(logTask) else emptyList()
        }


        project.tasks
            .matching { it.name == LifecycleBasePlugin.CHECK_TASK_NAME }
            .configureEach { dependsOn(runOnCheck) }
    }

    internal fun assign(variant: AbstractVariantArtifacts) {
        htmlTask.assign(variant)
        xmlTask.assign(variant)
        binTask.assign(variant)
        doVerifyTask.assign(variant)
        logTask.assign(variant)
    }

    private inline fun  TaskContainer.createReportTask(
        name: String,
        taskDescription: String
    ): TaskProvider {
        val task = register(name)
        // extract property to variable so as not to create a closure to `this`
        val koverDisabledProvider = koverDisabled
        task.configure {
            group = LifecycleBasePlugin.VERIFICATION_GROUP
            description = taskDescription
            tool.convention(toolProvider)
            reportClasspath.from(reporterConfiguration)

            onlyIf { !koverDisabledProvider.get() }
        }
        return task
    }

    private fun  TaskProvider.assign(variant: AbstractVariantArtifacts) {
        configure {
            dependsOn(variant.artifactGenTask)
            dependsOn(variant.consumerConfiguration)

            localArtifact.set(variant.artifactGenTask.flatMap { task -> task.artifactFile })
            externalArtifacts.from(variant.consumerConfiguration)
        }
    }

    private fun variantSuffix(): String {
        return when (type) {
            ReportVariantType.TOTAL -> "all code."
            ReportVariantType.ANDROID -> "'$variantName' Android build variant"
            ReportVariantType.JVM -> "Kotlin JVM"
            ReportVariantType.CUSTOM -> "custom report variant '$variantName'"
        }
    }

    private fun KoverReportFiltersConfigImpl.convert(): Provider {
        return project.provider {
            ReportFilters(
                includesImpl.classes.get(), includesImpl.annotations.get(),
                excludesImpl.classes.get(), excludesImpl.annotations.get()
            )
        }
    }
}


private fun KoverVerifyRuleImpl.convert(): VerificationRule {
    return VerificationRule(!disabled.get(), name, groupBy.get(), bounds.map { it.convert() })
}

private fun KoverVerifyBound.convert(): VerificationBound {
    return VerificationBound(minValue.orNull?.toBigDecimal(), maxValue.orNull?.toBigDecimal(), coverageUnits.get(), aggregationForGroup.get())
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy