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

name.remal.gradle_plugins.plugins.code_quality.jacoco.JacocoSettingsPlugin.kt Maven / Gradle / Ivy

There is a newer version: 1.9.2
Show newest version
package name.remal.gradle_plugins.plugins.code_quality.jacoco

import name.remal.gradle_plugins.dsl.*
import name.remal.gradle_plugins.dsl.extensions.*
import name.remal.gradle_plugins.plugins.java.JavaAnyPluginId
import name.remal.gradle_plugins.utils.getPredefinedDynamicVersionProperty
import name.remal.version.Version
import name.remal.warn
import org.gradle.api.Project
import org.gradle.api.plugins.ExtensionContainer
import org.gradle.api.plugins.JavaBasePlugin.CHECK_TASK_NAME
import org.gradle.api.plugins.JavaBasePlugin.VERIFICATION_GROUP
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.api.tasks.TaskContainer
import org.gradle.api.tasks.testing.Test
import org.gradle.testing.jacoco.plugins.JacocoPluginExtension
import org.gradle.testing.jacoco.plugins.JacocoTaskExtension
import org.gradle.testing.jacoco.tasks.JacocoCoverageVerification
import org.gradle.testing.jacoco.tasks.JacocoMerge
import org.gradle.testing.jacoco.tasks.JacocoReport
import org.gradle.testing.jacoco.tasks.JacocoReportBase

@Plugin(
    id = "name.remal.jacoco-settings",
    description = "Plugin that configures 'jacoco' plugin if it's applied.",
    tags = ["java", "jacoco", "coverage", "test"]
)
@WithPlugins(JacocoPluginId::class, JavaAnyPluginId::class)
@SimpleTestAdditionalGradleScript("""
    dependencies { testCompile 'junit:junit:4.12' }
    test {
        useJUnit()
        testLogging {
            showExceptions = true
            showCauses = true
            showStackTraces = true
            exceptionFormat = 'FULL'
            stackTraceFilters = ['GROOVY']
        }
    }
    file('src/test/java/T.java').with {
        parentFile.mkdirs()
        write('public class T { @org.junit.Test public void test() {} }', 'UTF-8')
    }
""")
class JacocoSettingsPlugin : BaseReflectiveProjectPlugin() {

    @PluginAction
    fun ExtensionContainer.`Update Jacoco version`(project: Project) {
        val jacoco = this[JacocoPluginExtension::class.java]
        val toolVersionStr = jacoco.toolVersion
        if (toolVersionStr.isNullOrEmpty()) {
            jacoco.toolVersion = project.getPredefinedDynamicVersionProperty("jacoco-core")

        } else {
            val toolVersion = Version.parseOrNull(toolVersionStr)
            val buildVersion = Version.parseOrNull(project.getPredefinedDynamicVersionProperty("jacoco-core"))
            if (toolVersion != null && buildVersion != null) {
                if (toolVersion < buildVersion) {
                    jacoco.toolVersion = buildVersion.toString()
                }
            }
        }
    }

    @PluginAction
    fun TaskContainer.`Turn ON all reports`(extensions: ExtensionContainer) {
        all(JacocoReport::class.java) { task ->
            task.reports.all {
                it.isEnabled = true
            }
        }
    }

    @PluginAction
    fun TaskContainer.`Turn OFF fail on violation`() {
        all(JacocoCoverageVerification::class.java) {
            it.violationRules.isFailOnViolation = false
        }
    }

    @PluginAction("If jacoco task has not execution files set, it crashes. So let's use temp empty execution file by default.")
    fun TaskContainer.tempExecutionFileByDefault(project: Project, sourceSets: SourceSetContainer) {
        all(JacocoReportBase::class.java) {
            it.doSetup(Int.MAX_VALUE) {
                tryCompatibleMethodOrWarn { it.prepareExecutionData() }

                tryCompatibleMethodOrWarn {
                    if (it.sourceDirectoriesCompatible.isEmpty) it.sourceDirectoriesCompatible = sourceSets.main.allJava.sourceDirectories
                    if (it.classDirectoriesCompatible.isEmpty) it.classDirectoriesCompatible = sourceSets.main.output
                }

                tryCompatibleMethodOrWarn { it.applyExcludeFromCodeCoverage() }
            }
        }

        all(JacocoMerge::class.java) {
            it.doSetup(Int.MAX_VALUE) {
                tryCompatibleMethodOrWarn { it.prepareExecutionData() }
            }
        }
    }

    @PluginAction
    fun TaskContainer.`Setup jacoco for all Test tasks`(extensions: ExtensionContainer, tasks: TaskContainer) {
        all(Test::class.java) { testTask ->
            if (JacocoTaskExtension::class.java !in testTask.extensions) {
                val jacoco = extensions[JacocoPluginExtension::class.java]
                jacoco.applyTo(testTask)
            }

            val reportTask = tasks.getOrCreate(testTask.jacocoReportTaskName, JacocoReport::class.java).also { task ->
                task as JacocoReport
                task.mustRunAfter(testTask)
                task.group = VERIFICATION_GROUP
                task.description = "Generates code coverage report for the ${testTask.name} task."
                task.executionData(testTask)

                all(CHECK_TASK_NAME) { it.dependsOn(task) }

                task.onlyIf { testTask.isInTaskGraph }
            }

            tasks.getOrCreate(testTask.jacocoCoverageVerificationTaskName, JacocoCoverageVerification::class.java).also { task ->
                task as JacocoCoverageVerification
                task.mustRunAfter(testTask)
                task.mustRunAfter(reportTask)
                task.group = VERIFICATION_GROUP
                task.description = "Verifies code coverage metrics based on specified rules for the ${testTask.name} task."
                task.executionData(testTask)

                all(CHECK_TASK_NAME) { it.dependsOn(task) }

                task.onlyIf { testTask.isInTaskGraph }
            }
        }
    }


    private inline fun tryCompatibleMethodOrWarn(callback: () -> Unit) {
        try {
            callback()
        } catch (e: CompatibleMethodNotFoundException) {
            logger.warn(e)
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy