diff --git a/build.gradle.kts b/build.gradle.kts index 5ea59cdd..ad7ff6c7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,8 +1,11 @@ -import org.jetbrains.kotlin.gradle.plugin.* +import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { kotlin("jvm") + `kotlin-dsl` + `java-gradle-plugin` `maven-publish` signing @@ -51,8 +54,8 @@ java { } -tasks.register("functionalTest") { - group = "verification" +val functionalTest by tasks.registering(Test::class) { + group = LifecycleBasePlugin.VERIFICATION_GROUP testClassesDirs = sourceSets["functionalTest"].output.classesDirs classpath = sourceSets["functionalTest"].runtimeClasspath @@ -65,8 +68,7 @@ tasks.register("functionalTest") { // Create a configuration to register the dependencies against doFirst { val file = File(temporaryDir, "plugin-classpath.txt") - file - .writeText(sourceSets["functionalTest"].compileClasspath.joinToString("\n")) + file.writeText(sourceSets["functionalTest"].compileClasspath.joinToString("\n")) systemProperties["plugin-classpath"] = file.absolutePath // used in build scripts of functional tests @@ -74,10 +76,10 @@ tasks.register("functionalTest") { } } -tasks.check { dependsOn("functionalTest") } +tasks.check { dependsOn(functionalTest) } -tasks.withType().configureEach { +tasks.withType().configureEach { kotlinOptions { allWarningsAsErrors = true @@ -104,7 +106,7 @@ publishing { addMavenRepository(project) addMavenMetadata() - publications.withType(MavenPublication::class).all { + publications.withType().configureEach { signPublicationIfKeyPresent(project) } } diff --git a/buildSrc/src/main/kotlin/PublicationMavenCentral.kt b/buildSrc/src/main/kotlin/PublicationMavenCentral.kt index 14d0f56e..017b50e1 100644 --- a/buildSrc/src/main/kotlin/PublicationMavenCentral.kt +++ b/buildSrc/src/main/kotlin/PublicationMavenCentral.kt @@ -34,7 +34,7 @@ fun MavenPublication.signPublicationIfKeyPresent(project: Project) { } fun PublishingExtension.addMavenMetadata() { - publications.withType(MavenPublication::class) { + publications.withType().configureEach { pom { if (!name.isPresent) { name.set(artifactId) diff --git a/src/main/kotlin/kotlinx/kover/api/KoverConfig.kt b/src/main/kotlin/kotlinx/kover/api/KoverConfig.kt index 73e74bdf..43488498 100644 --- a/src/main/kotlin/kotlinx/kover/api/KoverConfig.kt +++ b/src/main/kotlin/kotlinx/kover/api/KoverConfig.kt @@ -10,32 +10,32 @@ import org.gradle.api.model.* import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property import org.gradle.api.tasks.* +import org.gradle.kotlin.dsl.* import javax.annotation.* import javax.inject.* public open class KoverProjectConfig @Inject constructor(objects: ObjectFactory) { - internal val filters: KoverProjectFilters = objects.newInstance(KoverProjectFilters::class.java, objects) + internal val filters: KoverProjectFilters = objects.newInstance() - internal val instrumentation: KoverProjectInstrumentation = - objects.newInstance(KoverProjectInstrumentation::class.java) + internal val instrumentation: KoverProjectInstrumentation = objects.newInstance() - internal val xmlReport: KoverProjectXmlConfig = objects.newInstance(KoverProjectXmlConfig::class.java, objects) + internal val xmlReport: KoverProjectXmlConfig = objects.newInstance() - internal val htmlReport: KoverProjectHtmlConfig = objects.newInstance(KoverProjectHtmlConfig::class.java, objects) + internal val htmlReport: KoverProjectHtmlConfig = objects.newInstance() - internal val verify: KoverVerifyConfig = objects.newInstance(KoverVerifyConfig::class.java, objects) + internal val verify: KoverVerifyConfig = objects.newInstance(objects) /** * Specifies whether instrumentation is disabled for all test tasks of current project. * * `false` by default. */ - public val isDisabled: Property = objects.property(Boolean::class.java) + public val isDisabled: Property = objects.property() /** * Specifies the coverage engine variant to be used to collect execution data. */ - public val engine: Property = objects.property(CoverageEngineVariant::class.java) + public val engine: Property = objects.property() /** * Configures filtering for all Kover's tasks of current project by class names and source sets. @@ -90,7 +90,7 @@ public open class KoverProjectConfig @Inject constructor(objects: ObjectFactory) replaceWith = ReplaceWith("engine"), level = DeprecationLevel.ERROR ) - public val coverageEngine: Property = objects.property(CoverageEngine::class.java) + public val coverageEngine: Property = objects.property() @get:Internal @Deprecated( @@ -98,7 +98,7 @@ public open class KoverProjectConfig @Inject constructor(objects: ObjectFactory) replaceWith = ReplaceWith("engine"), level = DeprecationLevel.ERROR ) - public val intellijEngineVersion: Property = objects.property(String::class.java) + public val intellijEngineVersion: Property = objects.property() @get:Internal @Deprecated( @@ -106,7 +106,7 @@ public open class KoverProjectConfig @Inject constructor(objects: ObjectFactory) replaceWith = ReplaceWith("engine"), level = DeprecationLevel.ERROR ) - public val jacocoEngineVersion: Property = objects.property(String::class.java) + public val jacocoEngineVersion: Property = objects.property() @get:Internal @Deprecated( @@ -147,9 +147,9 @@ public open class KoverProjectConfig @Inject constructor(objects: ObjectFactory) public open class KoverExtension public open class KoverProjectFilters @Inject constructor(private val objects: ObjectFactory) { - internal val classes: Property = objects.property(KoverClassFilter::class.java) + internal val classes: Property = objects.property() - internal val sourceSets: Property = objects.property(KoverSourceSetFilter::class.java) + internal val sourceSets: Property = objects.property() /** * Configures class filter in order to include and exclude specific classes. @@ -164,7 +164,7 @@ public open class KoverProjectFilters @Inject constructor(private val objects: O * Excludes have priority over includes. */ public fun classes(config: Action) { - val classFilter = objects.newInstance(KoverClassFilter::class.java) + val classFilter = objects.newInstance() config.execute(classFilter) classes.set(classFilter) } @@ -173,7 +173,7 @@ public open class KoverProjectFilters @Inject constructor(private val objects: O * Configures source set filter. */ public fun sourceSets(config: Action) { - val sourceSetFilters = objects.newInstance(KoverSourceSetFilter::class.java) + val sourceSetFilters = objects.newInstance() config.execute(sourceSetFilters) sourceSets.set(sourceSetFilters) } @@ -187,14 +187,14 @@ public open class KoverProjectInstrumentation { } public open class KoverProjectXmlConfig @Inject constructor(objects: ObjectFactory) { - internal val filters: KoverProjectFilters = objects.newInstance(KoverProjectFilters::class.java, objects) + internal val filters: KoverProjectFilters = objects.newInstance() /** * Specifies whether the XML report generation task should be executed before the `check` task (if it exists) of the current project. * * `false` by default. */ - public val onCheck: Property = objects.property(Boolean::class.java) + public val onCheck: Property = objects.property() /** * Specifies file path of generated XML report file with coverage data. @@ -213,14 +213,14 @@ public open class KoverProjectXmlConfig @Inject constructor(objects: ObjectFacto } public open class KoverProjectHtmlConfig @Inject constructor(private val objects: ObjectFactory) { - internal val taskFilters: KoverProjectFilters = objects.newInstance(KoverProjectFilters::class.java, objects) + internal val taskFilters: KoverProjectFilters = objects.newInstance() /** * Specifies whether the HTML report generation task should be executed before the `check` task (if it exists) of the current project. * * `false` by default. */ - public val onCheck: Property = objects.property(Boolean::class.java) + public val onCheck: Property = objects.property() /** * Specifies directory path of generated HTML report. @@ -240,11 +240,11 @@ public open class KoverProjectHtmlConfig @Inject constructor(private val objects public open class KoverMergedConfig @Inject constructor(objects: ObjectFactory) { - internal var isEnabled: Property = objects.property(Boolean::class.java) - internal val filters: KoverMergedFilters = objects.newInstance(KoverMergedFilters::class.java, objects) - internal val xmlReport: KoverMergedXmlConfig = objects.newInstance(KoverMergedXmlConfig::class.java, objects) - internal val htmlReport: KoverMergedHtmlConfig = objects.newInstance(KoverMergedHtmlConfig::class.java, objects) - internal val verify: KoverVerifyConfig = objects.newInstance(KoverVerifyConfig::class.java, objects) + internal val isEnabled: Property = objects.property() + internal val filters: KoverMergedFilters = objects.newInstance() + internal val xmlReport: KoverMergedXmlConfig = objects.newInstance() + internal val htmlReport: KoverMergedHtmlConfig = objects.newInstance() + internal val verify: KoverVerifyConfig = objects.newInstance() /** * Create Kover tasks for generating merged reports. @@ -283,15 +283,15 @@ public open class KoverMergedConfig @Inject constructor(objects: ObjectFactory) } public open class KoverMergedFilters @Inject constructor(private val objects: ObjectFactory) { - internal val classes: Property = objects.property(KoverClassFilter::class.java) + internal val classes: Property = objects.property() - internal val projects: Property = objects.property(KoverProjectsFilter::class.java) + internal val projects: Property = objects.property() /** * Configures class filter. */ public fun classes(config: Action) { - val classFilter = objects.newInstance(KoverClassFilter::class.java) + val classFilter = objects.newInstance() config.execute(classFilter) classes.set(classFilter) } @@ -300,7 +300,7 @@ public open class KoverMergedFilters @Inject constructor(private val objects: Ob * Configures projects filter. */ public fun projects(config: Action) { - val projectsFilters = objects.newInstance(KoverProjectsFilter::class.java) + val projectsFilters = objects.newInstance() config.execute(projectsFilters) projects.set(projectsFilters) } @@ -308,12 +308,12 @@ public open class KoverMergedFilters @Inject constructor(private val objects: Ob public open class KoverMergedXmlConfig @Inject constructor(private val objects: ObjectFactory) { - internal val classFilter: Property = objects.property(KoverClassFilter::class.java) + internal val classFilter: Property = objects.property() /** * Specifies whether the merged XML report generation task should be executed before the `check` task (if it exists) of the current project. */ - public val onCheck: Property = objects.property(Boolean::class.java) + public val onCheck: Property = objects.property() /** * Specifies file path of generated XML report file with coverage data. @@ -324,19 +324,19 @@ public open class KoverMergedXmlConfig @Inject constructor(private val objects: * Override class filter for the merged XML report generation task. */ public fun overrideClassFilter(config: Action) { - val newClassFilter = objects.newInstance(KoverClassFilter::class.java) + val newClassFilter = objects.newInstance() config.execute(newClassFilter) classFilter.set(newClassFilter) } } public open class KoverMergedHtmlConfig @Inject constructor(private val objects: ObjectFactory) { - internal val classFilter: Property = objects.property(KoverClassFilter::class.java) + internal val classFilter: Property = objects.property() /** * Specifies whether the merged HTML report generation task should be executed before the `check` task (if it exists) of the current project. */ - public val onCheck: Property = objects.property(Boolean::class.java) + public val onCheck: Property = objects.property() /** * Specifies directory path of generated HTML report. @@ -347,7 +347,7 @@ public open class KoverMergedHtmlConfig @Inject constructor(private val objects: * Override class filter for the merged HTML report generation task. */ public fun overrideClassFilter(config: Action) { - val newClassFilter = objects.newInstance(KoverClassFilter::class.java) + val newClassFilter = objects.newInstance() config.execute(newClassFilter) classFilter.set(newClassFilter) } @@ -365,20 +365,20 @@ public open class KoverProjectsFilter { public open class KoverVerifyConfig @Inject constructor(private val objects: ObjectFactory) { - internal val rules: ListProperty = objects.listProperty(VerificationRule::class.java) + internal val rules: ListProperty = objects.listProperty() /** * Specifies whether the verification task should be executed before the `check` task (if it exists) of the current project. * * By default, `true` for project reports and `false` for merged. */ - public val onCheck: Property = objects.property(Boolean::class.java).value(true) + public val onCheck: Property = objects.property().value(true) /** * Add new coverage verification rule to check after test task execution. */ public fun rule(configureRule: Action) { - rules.add(objects.newInstance(VerificationRule::class.java, objects).also { configureRule.execute(it) }) + rules.add(objects.newInstance().also { configureRule.execute(it) }) } } @@ -424,10 +424,10 @@ public open class KoverSourceSetFilter { public open class VerificationRule @Inject constructor(private val objects: ObjectFactory) { @get:Nested @get:Optional - internal val classFilter: Property = objects.property(KoverClassFilter::class.java) + internal val classFilter: Property = objects.property() @get:Nested - internal val bounds: ListProperty = objects.listProperty(VerificationBound::class.java) + internal val bounds: ListProperty = objects.listProperty() /** * Specifies that the rule will be checked during verification. @@ -454,7 +454,7 @@ public open class VerificationRule @Inject constructor(private val objects: Obje */ public fun overrideClassFilter(config: Action) { if (!classFilter.isPresent) { - classFilter.set(objects.newInstance(KoverClassFilter::class.java)) + classFilter.set(objects.newInstance()) } config.execute(classFilter.get()) } @@ -463,7 +463,7 @@ public open class VerificationRule @Inject constructor(private val objects: Obje * Add a constraint on the value of the code coverage metric. */ public fun bound(configureBound: Action) { - bounds.add(objects.newInstance(VerificationBound::class.java).also { configureBound.execute(it) }) + bounds.add(objects.newInstance().also { configureBound.execute(it) }) } } diff --git a/src/main/kotlin/kotlinx/kover/api/KoverTaskExtension.kt b/src/main/kotlin/kotlinx/kover/api/KoverTaskExtension.kt index fa29c968..d6f15d51 100644 --- a/src/main/kotlin/kotlinx/kover/api/KoverTaskExtension.kt +++ b/src/main/kotlin/kotlinx/kover/api/KoverTaskExtension.kt @@ -9,19 +9,21 @@ import org.gradle.api.model.* import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property import org.gradle.api.tasks.* +import org.gradle.kotlin.dsl.* import java.io.* +import javax.inject.Inject /** * Extension for Kover plugin that additionally configures test tasks and * runs them with coverage agent to generate coverage execution data. */ -public open class KoverTaskExtension(objects: ObjectFactory) { +public open class KoverTaskExtension @Inject constructor(objects: ObjectFactory) { /** * Specifies whether instrumentation is disabled for an extended test task. */ @get:Input @get:JvmName("getIsDisabled") - public val isDisabled: Property = objects.property(Boolean::class.java) + public val isDisabled: Property = objects.property() /** * Specifies file path of generated binary file with coverage data. @@ -38,7 +40,7 @@ public open class KoverTaskExtension(objects: ObjectFactory) { * It's possible to use `*` and `?` wildcards. */ @get:Input - public val includes: ListProperty = objects.listProperty(String::class.java) + public val includes: ListProperty = objects.listProperty() /** * Specifies class instrumentation exclusion rules. @@ -49,7 +51,7 @@ public open class KoverTaskExtension(objects: ObjectFactory) { * It's possible to use `*` and `?` wildcards. */ @get:Input - public val excludes: ListProperty = objects.listProperty(String::class.java) + public val excludes: ListProperty = objects.listProperty() // DEPRECATIONS @@ -60,5 +62,5 @@ public open class KoverTaskExtension(objects: ObjectFactory) { replaceWith = ReplaceWith("reportFile"), level = DeprecationLevel.ERROR ) - public val binaryReportFile: Property = objects.property(File::class.java) + public val binaryReportFile: Property = objects.property() } diff --git a/src/main/kotlin/kotlinx/kover/appliers/KoverMergedApplier.kt b/src/main/kotlin/kotlinx/kover/appliers/KoverMergedApplier.kt index 6c1da980..c0ca4256 100644 --- a/src/main/kotlin/kotlinx/kover/appliers/KoverMergedApplier.kt +++ b/src/main/kotlin/kotlinx/kover/appliers/KoverMergedApplier.kt @@ -16,11 +16,17 @@ import kotlinx.kover.api.KoverPaths.MERGED_HTML_REPORT_DEFAULT_PATH import kotlinx.kover.api.KoverPaths.MERGED_VERIFICATION_REPORT_DEFAULT_PATH import kotlinx.kover.api.KoverPaths.MERGED_XML_REPORT_DEFAULT_PATH import kotlinx.kover.tasks.* -import org.gradle.api.* -import org.gradle.api.file.* +import org.gradle.api.Action +import org.gradle.api.GradleException +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.file.ArchiveOperations import org.gradle.api.provider.Provider -import org.gradle.api.tasks.testing.* -import org.gradle.configurationcache.extensions.* +import org.gradle.api.tasks.testing.Test +import org.gradle.configurationcache.extensions.serviceOf +import org.gradle.kotlin.dsl.create +import org.gradle.kotlin.dsl.findByType +import org.gradle.kotlin.dsl.getByType internal fun Project.applyMerged() { val extension = createMergedExtension() @@ -28,18 +34,18 @@ internal fun Project.applyMerged() { } private fun Project.createMergedExtension(): KoverMergedConfig { - val extension = extensions.create(KoverNames.MERGED_EXTENSION_NAME, KoverMergedConfig::class.java, objects) - extension.isEnabled.set(false) - extension.filters.classes.set(KoverClassFilter()) - extension.filters.projects.set(KoverProjectsFilter()) - extension.xmlReport.onCheck.set(false) - extension.xmlReport.reportFile.set(layout.buildDirectory.file(MERGED_XML_REPORT_DEFAULT_PATH)) - extension.xmlReport.classFilter.set(extension.filters.classes) - extension.htmlReport.onCheck.set(false) - extension.htmlReport.reportDir.set(layout.buildDirectory.dir(MERGED_HTML_REPORT_DEFAULT_PATH)) - extension.htmlReport.classFilter.set(extension.filters.classes) - extension.verify.onCheck.set(false) - return extension + return extensions.create(KoverNames.MERGED_EXTENSION_NAME).apply { + isEnabled.convention(false) + filters.classes.convention(KoverClassFilter()) + filters.projects.convention(KoverProjectsFilter()) + xmlReport.onCheck.convention(false) + xmlReport.reportFile.convention(layout.buildDirectory.file(MERGED_XML_REPORT_DEFAULT_PATH)) + xmlReport.classFilter.convention(filters.classes) + htmlReport.onCheck.convention(false) + htmlReport.reportDir.convention(layout.buildDirectory.dir(MERGED_HTML_REPORT_DEFAULT_PATH)) + htmlReport.classFilter.convention(filters.classes) + verify.onCheck.convention(false) + } } private class ProcessMergeExtensionAction(private val extension: KoverMergedConfig) : Action { @@ -61,7 +67,7 @@ private class ProcessMergeExtensionAction(private val extension: KoverMergedConf testsProvider, { e -> e.xmlReport.filters.sourceSets.get() } ) { - it.reportFile.set(extension.xmlReport.reportFile) + it.reportFile.convention(extension.xmlReport.reportFile) it.description = "Generates code coverage XML report for all enabled test tasks in specified projects." } @@ -73,7 +79,7 @@ private class ProcessMergeExtensionAction(private val extension: KoverMergedConf testsProvider, { e -> e.htmlReport.taskFilters.sourceSets.get() } ) { - it.reportDir.set(extension.htmlReport.reportDir) + it.reportDir.convention(extension.htmlReport.reportDir) it.description = "Generates code coverage HTML report for all enabled test tasks in specified projects." } @@ -85,8 +91,8 @@ private class ProcessMergeExtensionAction(private val extension: KoverMergedConf testsProvider, { e -> e.filters.sourceSets.get() } ) { - it.rules.set(extension.verify.rules) - it.resultFile.set(container.layout.buildDirectory.file(MERGED_VERIFICATION_REPORT_DEFAULT_PATH)) + it.rules.convention(extension.verify.rules) + it.resultFile.convention(container.layout.buildDirectory.file(MERGED_VERIFICATION_REPORT_DEFAULT_PATH)) it.description = "Verifies code coverage metrics of specified projects based on specified rules." } // TODO `onlyIf` block moved out from config lambda because of bug in Kotlin compiler - it implicitly adds closure on `Project` inside onlyIf's lambda @@ -96,15 +102,16 @@ private class ProcessMergeExtensionAction(private val extension: KoverMergedConf verifyTask.shouldRunAfter(xmlTask, htmlTask) container.tasks.create(MERGED_REPORT_TASK_NAME) { - it.group = VERIFICATION_GROUP - it.dependsOn(xmlTask) - it.dependsOn(htmlTask) - it.description = "Generates code coverage HTML and XML reports for all enabled test tasks in one project." + group = VERIFICATION_GROUP + dependsOn(xmlTask) + dependsOn(htmlTask) + description = "Generates code coverage HTML and XML reports for all enabled test tasks in one project." } - container.tasks.configureEach { - if (it.name == CHECK_TASK_NAME) { - it.dependsOn(container.provider { + container.tasks + .matching { it.name == CHECK_TASK_NAME } + .configureEach { + dependsOn(container.provider { val tasks = mutableListOf() if (extension.xmlReport.onCheck.get()) { tasks += xmlTask @@ -119,7 +126,6 @@ private class ProcessMergeExtensionAction(private val extension: KoverMergedConf tasks }) } - } } } @@ -132,14 +138,14 @@ private inline fun Project.createMergedTask( crossinline filterExtractor: (KoverProjectConfig) -> KoverSourceSetFilter, crossinline block: (T) -> Unit ): T { - val task = tasks.create(taskName, T::class.java) { - it.files.set(mergedFilesProvider(extensionByProject, filterExtractor)) - it.engine.set(engineProvider) - it.dependsOn(testsProvider) - - it.classFilter.set(classFilter) - it.group = VERIFICATION_GROUP - block(it) + val task = tasks.create(taskName) { + files.convention(mergedFilesProvider(extensionByProject, filterExtractor)) + engine.convention(engineProvider) + dependsOn(testsProvider) + + this@create.classFilter.convention(classFilter) + group = VERIFICATION_GROUP + block(this) } // TODO `onlyIf` block moved out from config lambda because of bug in Kotlin compiler - it implicitly adds closure on `Project` inside onlyIf's lambda // execute task only if there is at least one binary report @@ -156,11 +162,11 @@ private fun Project.projectsExtensionsProvider( val projects = filterProjects(extension.filters.projects.get(), allProjects) val notAppliedProjects = - projects.filter { it.extensions.findByType(KoverProjectConfig::class.java) == null }.map { it.path } + projects.filter { it.extensions.findByType() == null }.map { it.path } if (notAppliedProjects.isNotEmpty()) { throw GradleException("Can't create Kover merge tasks: Kover plugin not applied in projects $notAppliedProjects") } - projects.associateWith { it.extensions.getByType(KoverProjectConfig::class.java) } + projects.associateWith { it.extensions.getByType() } } } @@ -169,10 +175,13 @@ private inline fun Project.mergedFilesProvider( extensionByProject: Provider>, crossinline filterExtractor: (KoverProjectConfig) -> KoverSourceSetFilter ): Provider> { - return provider { - extensionByProject.get() - .map { (project, extension) -> project.path to project.projectFiles(filterExtractor(extension), extension) } - .associate { it } + return extensionByProject.map { extension -> + extension.map { (project, extension) -> + project.path to project.projectFiles( + filterExtractor(extension), + extension + ) + }.associate { it } } } @@ -210,7 +219,7 @@ private fun Project.engineProvider(extensionByProject: Provider().engine val containerPath = path return provider { diff --git a/src/main/kotlin/kotlinx/kover/appliers/KoverProjectApplier.kt b/src/main/kotlin/kotlinx/kover/appliers/KoverProjectApplier.kt index ee17236f..e357294a 100644 --- a/src/main/kotlin/kotlinx/kover/appliers/KoverProjectApplier.kt +++ b/src/main/kotlin/kotlinx/kover/appliers/KoverProjectApplier.kt @@ -17,6 +17,7 @@ import org.gradle.api.artifacts.* import org.gradle.api.file.ArchiveOperations import org.gradle.api.provider.* import org.gradle.api.tasks.testing.* +import org.gradle.kotlin.dsl.* import org.gradle.configurationcache.extensions.* import java.io.* @@ -26,8 +27,8 @@ internal fun Project.applyToProject() { val engineProvider = engineProvider(config, extension.engine) - tasks.withType(Test::class.java).configureEach { t -> - t.applyToTestTask(extension, engineProvider) + tasks.withType().configureEach { + applyToTestTask(extension, engineProvider) } val testsProvider = instrumentedTasksProvider(extension) @@ -72,16 +73,17 @@ internal fun Project.applyToProject() { verifyTask.shouldRunAfter(xmlTask, htmlTask) tasks.create(KoverNames.REPORT_TASK_NAME) { - it.group = KoverNames.VERIFICATION_GROUP - it.dependsOn(xmlTask) - it.dependsOn(htmlTask) - it.description = "Generates code coverage HTML and XML reports for all enabled test tasks in one project." + group = KoverNames.VERIFICATION_GROUP + dependsOn(xmlTask) + dependsOn(htmlTask) + description = "Generates code coverage HTML and XML reports for all enabled test tasks in one project." } - tasks.configureEach { - if (it.name == KoverNames.CHECK_TASK_NAME) { - it.dependsOn(provider { + tasks + .matching { it.name == KoverNames.CHECK_TASK_NAME } + .configureEach { + dependsOn(provider { // don't add dependency if Kover is disabled if (extension.isDisabled.get()) { return@provider emptyList() @@ -100,7 +102,6 @@ internal fun Project.applyToProject() { } tasks }) - } } } @@ -112,13 +113,13 @@ private inline fun Project.createTask( testsProvider: Provider>, crossinline block: (T) -> Unit ): T { - val task = tasks.create(taskName, T::class.java) { - it.files.put(path, projectFilesProvider(extension, filters.sourceSets)) - it.engine.set(engineProvider) - it.dependsOn(testsProvider) - it.classFilter.set(filters.classes) - it.group = KoverNames.VERIFICATION_GROUP - block(it) + val task = tasks.create(taskName) { + files.put(path, projectFilesProvider(extension, filters.sourceSets)) + engine.set(engineProvider) + dependsOn(testsProvider) + classFilter.set(filters.classes) + group = KoverNames.VERIFICATION_GROUP + block(this) } // TODO `onlyIf` block moved out from config lambda because of bug in Kotlin compiler - it implicitly adds closure on `Project` inside onlyIf's lambda @@ -131,22 +132,22 @@ private inline fun Project.createTask( } private fun Project.createProjectExtension(): KoverProjectConfig { - val extension = extensions.create(KoverNames.PROJECT_EXTENSION_NAME, KoverProjectConfig::class.java, objects) + val extension = extensions.create(KoverNames.PROJECT_EXTENSION_NAME, KoverProjectConfig::class) // default values - extension.isDisabled.set(false) - extension.engine.set(DefaultIntellijEngine) - extension.filters.classes.set(KoverClassFilter()) - extension.filters.sourceSets.set(KoverSourceSetFilter()) - extension.xmlReport.reportFile.set(layout.buildDirectory.file(KoverPaths.PROJECT_XML_REPORT_DEFAULT_PATH)) - extension.xmlReport.onCheck.set(false) - extension.xmlReport.filters.classes.set(extension.filters.classes) - extension.xmlReport.filters.sourceSets.set(extension.filters.sourceSets) - extension.htmlReport.reportDir.set(layout.buildDirectory.dir(KoverPaths.PROJECT_HTML_REPORT_DEFAULT_PATH)) - extension.htmlReport.onCheck.set(false) - extension.htmlReport.taskFilters.classes.set(extension.filters.classes) - extension.htmlReport.taskFilters.sourceSets.set(extension.filters.sourceSets) - extension.verify.onCheck.set(true) + extension.isDisabled.convention(false) + extension.engine.convention(DefaultIntellijEngine) + extension.filters.classes.convention(KoverClassFilter()) + extension.filters.sourceSets.convention(KoverSourceSetFilter()) + extension.xmlReport.reportFile.convention(layout.buildDirectory.file(KoverPaths.PROJECT_XML_REPORT_DEFAULT_PATH)) + extension.xmlReport.onCheck.convention(false) + extension.xmlReport.filters.classes.convention(extension.filters.classes) + extension.xmlReport.filters.sourceSets.convention(extension.filters.sourceSets) + extension.htmlReport.reportDir.convention(layout.buildDirectory.dir(KoverPaths.PROJECT_HTML_REPORT_DEFAULT_PATH)) + extension.htmlReport.onCheck.convention(false) + extension.htmlReport.taskFilters.classes.convention(extension.filters.classes) + extension.htmlReport.taskFilters.sourceSets.convention(extension.filters.sourceSets) + extension.verify.onCheck.convention(true) return extension } @@ -157,10 +158,10 @@ private fun Project.createEngineConfig(engineVariantProvider: Provider + config.defaultDependencies { val variant = engineVariantProvider.get() EngineManager.dependencies(variant).forEach { - default.add(dependencies.create(it)) + add(dependencies.create(it)) } } return config @@ -200,10 +201,10 @@ internal fun Project.projectFiles( } internal fun Project.instrumentedTasks(extension: KoverProjectConfig): List { - return tasks.withType(Test::class.java).asSequence() + return tasks.withType().asSequence() // task can be disabled in the project extension .filterNot { extension.instrumentation.excludeTasks.contains(it.name) } - .filterNot { t -> t.extensions.getByType(KoverTaskExtension::class.java).isDisabled.get() } + .filterNot { t -> t.extensions.getByType().isDisabled.get() } .toList() } @@ -217,10 +218,10 @@ private fun Project.binaryReports(extension: KoverProjectConfig): List { return emptyList() } - return tasks.withType(Test::class.java).asSequence() + return tasks.withType().asSequence() // task can be disabled in the project extension .filterNot { extension.instrumentation.excludeTasks.contains(it.name) } - .map { t -> t.extensions.getByType(KoverTaskExtension::class.java) } + .map { t -> t.extensions.getByType() } // process binary report only from tasks with enabled cover .filterNot { e -> e.isDisabled.get() } .map { e -> e.reportFile.get().asFile } diff --git a/src/main/kotlin/kotlinx/kover/appliers/KoverTaskApplier.kt b/src/main/kotlin/kotlinx/kover/appliers/KoverTaskApplier.kt index 6b7f7013..60fe018d 100644 --- a/src/main/kotlin/kotlinx/kover/appliers/KoverTaskApplier.kt +++ b/src/main/kotlin/kotlinx/kover/appliers/KoverTaskApplier.kt @@ -5,15 +5,23 @@ package kotlinx.kover.appliers import kotlinx.kover.api.* -import kotlinx.kover.engines.commons.* -import kotlinx.kover.tasks.* -import org.gradle.api.* +import kotlinx.kover.engines.commons.AgentFilters +import kotlinx.kover.engines.commons.EngineManager +import kotlinx.kover.tasks.EngineDetails +import org.gradle.api.Action +import org.gradle.api.Named +import org.gradle.api.Project +import org.gradle.api.Task import org.gradle.api.file.RegularFile -import org.gradle.api.provider.* -import org.gradle.api.tasks.* -import org.gradle.api.tasks.testing.* -import org.gradle.process.* -import java.io.* +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.Nested +import org.gradle.api.tasks.OutputFile +import org.gradle.api.tasks.testing.Test +import org.gradle.kotlin.dsl.create +import org.gradle.process.CommandLineArgumentProvider +import java.io.File internal fun Test.applyToTestTask( @@ -49,16 +57,16 @@ internal fun Test.applyToTestTask( } private fun Task.createTaskExtension(projectExtension: KoverProjectConfig): KoverTaskExtension { - val taskExtension = - extensions.create(KoverNames.TASK_EXTENSION_NAME, KoverTaskExtension::class.java, project.objects) + val taskExtension = extensions.create(KoverNames.TASK_EXTENSION_NAME, project.objects) - taskExtension.isDisabled.set(false) - val layout = project.layout - taskExtension.reportFile.set(project.provider { - val engine = projectExtension.engine.get() + taskExtension.isDisabled.convention(false) + + val reportFile = project.layout.buildDirectory.zip(projectExtension.engine) { buildDir, engine -> val suffix = if (engine.vendor == CoverageEngineVendor.INTELLIJ) ".ic" else ".exec" - layout.buildDirectory.get().file("kover/$name$suffix") - }) + buildDir.file("kover/$name$suffix") + } + + taskExtension.reportFile.convention(reportFile) return taskExtension } diff --git a/src/main/kotlin/kotlinx/kover/engines/intellij/IntellijReports.kt b/src/main/kotlin/kotlinx/kover/engines/intellij/IntellijReports.kt index d4c330ff..cf108596 100644 --- a/src/main/kotlin/kotlinx/kover/engines/intellij/IntellijReports.kt +++ b/src/main/kotlin/kotlinx/kover/engines/intellij/IntellijReports.kt @@ -32,10 +32,10 @@ internal fun Task.intellijReport( val argsFile = File(temporaryDir, "intellijreport.json") argsFile.writeReportsJson(projectFiles, filters, xmlFile, htmlDir) - exec.javaexec { e -> - e.mainClass.set("com.intellij.rt.coverage.report.Main") - e.classpath = classpath - e.args = mutableListOf(argsFile.canonicalPath) + exec.javaexec { + mainClass.set("com.intellij.rt.coverage.report.Main") + this@javaexec.classpath = classpath + args = mutableListOf(argsFile.canonicalPath) } } diff --git a/src/main/kotlin/kotlinx/kover/engines/intellij/IntellijVerification.kt b/src/main/kotlin/kotlinx/kover/engines/intellij/IntellijVerification.kt index 6750ce1f..cabfe03e 100644 --- a/src/main/kotlin/kotlinx/kover/engines/intellij/IntellijVerification.kt +++ b/src/main/kotlin/kotlinx/kover/engines/intellij/IntellijVerification.kt @@ -17,7 +17,6 @@ import java.math.BigDecimal import java.math.RoundingMode import java.util.TreeMap -@Suppress("UNUSED_PARAMETER") internal fun Task.intellijVerification( exec: ExecOperations, projectFiles: Map, @@ -28,19 +27,19 @@ internal fun Task.intellijVerification( val aggRequest = File(temporaryDir, "agg-request.json") val groupedRules = groupRules(classFilter, rules) aggRequest.writeAggJson(projectFiles, groupedRules) - exec.javaexec { e -> - e.mainClass.set("com.intellij.rt.coverage.aggregate.Main") - e.classpath = classpath - e.args = mutableListOf(aggRequest.canonicalPath) + exec.javaexec { + mainClass.set("com.intellij.rt.coverage.aggregate.Main") + this@javaexec.classpath = classpath + args = mutableListOf(aggRequest.canonicalPath) } val verifyRequest = File(temporaryDir, "verify-request.json") val verifyResponseFile = File(temporaryDir, "verify-result.json") verifyRequest.writeVerifyJson(groupedRules, verifyResponseFile) - exec.javaexec { e -> - e.mainClass.set("com.intellij.rt.coverage.verify.Main") - e.classpath = classpath - e.args = mutableListOf(verifyRequest.canonicalPath) + exec.javaexec { + mainClass.set("com.intellij.rt.coverage.verify.Main") + this@javaexec.classpath = classpath + args = mutableListOf(verifyRequest.canonicalPath) } val violations = verifyResponseFile.readJsonObject() diff --git a/src/main/kotlin/kotlinx/kover/lookup/adapters/AndroidPluginAdapter.kt b/src/main/kotlin/kotlinx/kover/lookup/adapters/AndroidPluginAdapter.kt index a3965572..31d1aad8 100644 --- a/src/main/kotlin/kotlinx/kover/lookup/adapters/AndroidPluginAdapter.kt +++ b/src/main/kotlin/kotlinx/kover/lookup/adapters/AndroidPluginAdapter.kt @@ -8,6 +8,7 @@ import com.android.build.gradle.* import kotlinx.kover.api.* import kotlinx.kover.lookup.* import org.gradle.api.* +import org.gradle.kotlin.dsl.* /** * Adapter to get sources and outputs of Android Gradle plugin. @@ -17,7 +18,7 @@ internal class AndroidPluginAdapter : LookupAdapter() { override fun lookup(project: Project, sourceSetFilters: KoverSourceSetFilter): Dirs { project.plugins.findPlugin("android") ?: return Dirs() - val extension = project.extensions.findByType(BaseExtension::class.java) ?: return Dirs() + val extension = project.extensions.findByType() ?: return Dirs() val sourceDirs = extension.sourceSets.asSequence() .filter { filterSourceSet(it.name, sourceSetFilters) } diff --git a/src/main/kotlin/kotlinx/kover/lookup/adapters/JavaPluginAdapter.kt b/src/main/kotlin/kotlinx/kover/lookup/adapters/JavaPluginAdapter.kt index d7989a41..de8b6181 100644 --- a/src/main/kotlin/kotlinx/kover/lookup/adapters/JavaPluginAdapter.kt +++ b/src/main/kotlin/kotlinx/kover/lookup/adapters/JavaPluginAdapter.kt @@ -7,6 +7,7 @@ package kotlinx.kover.lookup.adapters import kotlinx.kover.api.* import kotlinx.kover.lookup.LookupAdapter import org.gradle.api.* +import org.gradle.kotlin.dsl.* import org.gradle.api.tasks.* /** @@ -18,9 +19,7 @@ internal class JavaPluginAdapter : LookupAdapter() { override fun lookup(project: Project, sourceSetFilters: KoverSourceSetFilter): Dirs { project.plugins.findPlugin("java") ?: return Dirs() - val sourceSetContainer = project.extensions.findByType( - SourceSetContainer::class.java - ) ?: return Dirs() + val sourceSetContainer = project.extensions.findByType() ?: return Dirs() val sourceSets = sourceSetContainer.filter { filterSourceSet(it.name, sourceSetFilters) } diff --git a/src/main/kotlin/kotlinx/kover/lookup/adapters/KotlinAndroidPluginAdapter.kt b/src/main/kotlin/kotlinx/kover/lookup/adapters/KotlinAndroidPluginAdapter.kt index 5ac17979..2258d33f 100644 --- a/src/main/kotlin/kotlinx/kover/lookup/adapters/KotlinAndroidPluginAdapter.kt +++ b/src/main/kotlin/kotlinx/kover/lookup/adapters/KotlinAndroidPluginAdapter.kt @@ -8,6 +8,7 @@ import kotlinx.kover.api.* import kotlinx.kover.lookup.LookupAdapter import org.gradle.api.* import org.jetbrains.kotlin.gradle.dsl.* +import org.gradle.kotlin.dsl.* /** * Adapter to get sources and outputs of Kotlin Android Gradle plugin. @@ -18,7 +19,7 @@ internal class KotlinAndroidPluginAdapter : LookupAdapter() { override fun lookup(project: Project, sourceSetFilters: KoverSourceSetFilter): Dirs { project.plugins.findPlugin("kotlin-android") ?: return Dirs() - val extension = project.extensions.findByType(KotlinAndroidProjectExtension::class.java) ?: return Dirs() + val extension = project.extensions.findByType() ?: return Dirs() val sourceDirs = extension.target.compilations .filter { !it.name.endsWith("Test") } diff --git a/src/main/kotlin/kotlinx/kover/lookup/adapters/KotlinMultiplatformPluginAdapter.kt b/src/main/kotlin/kotlinx/kover/lookup/adapters/KotlinMultiplatformPluginAdapter.kt index a9d0c2db..e67bda7d 100644 --- a/src/main/kotlin/kotlinx/kover/lookup/adapters/KotlinMultiplatformPluginAdapter.kt +++ b/src/main/kotlin/kotlinx/kover/lookup/adapters/KotlinMultiplatformPluginAdapter.kt @@ -12,6 +12,7 @@ import org.gradle.api.file.* import org.gradle.internal.metaobject.* import org.jetbrains.kotlin.gradle.dsl.* import org.jetbrains.kotlin.gradle.plugin.* +import org.gradle.kotlin.dsl.* /** * Adapter to get sources and outputs of Kotlin Multi-Platform Gradle plugin. @@ -23,7 +24,7 @@ internal class KotlinMultiplatformPluginAdapter : LookupAdapter() { project.plugins.findPlugin("kotlin-multiplatform") ?: return Dirs() val extension = try { - project.extensions.findByType(KotlinMultiplatformExtension::class.java) ?: return Dirs() + project.extensions.findByType() ?: return Dirs() } catch (e: ClassNotFoundException) { return findByReflection(project) } catch (e: NoClassDefFoundError) { diff --git a/src/main/kotlin/kotlinx/kover/tasks/KoverReportTask.kt b/src/main/kotlin/kotlinx/kover/tasks/KoverReportTask.kt index 5e5af09b..88683606 100644 --- a/src/main/kotlin/kotlinx/kover/tasks/KoverReportTask.kt +++ b/src/main/kotlin/kotlinx/kover/tasks/KoverReportTask.kt @@ -9,6 +9,7 @@ import org.gradle.api.* import org.gradle.api.file.* import org.gradle.api.provider.* import org.gradle.api.tasks.* +import org.gradle.kotlin.dsl.* import org.gradle.configurationcache.extensions.* import org.gradle.process.* import java.io.* @@ -16,14 +17,13 @@ import java.io.* // TODO make internal in 0.7 version - for now it public to save access to deprecated fields to print deprecation message public abstract class KoverReportTask : DefaultTask() { @get:Nested - internal val files: MapProperty = - project.objects.mapProperty(String::class.java, ProjectFiles::class.java) + internal val files: MapProperty = project.objects.mapProperty() @get:Nested - internal val classFilter: Property = project.objects.property(KoverClassFilter::class.java) + internal val classFilter: Property = project.objects.property() @get:Nested - internal val engine: Property = project.objects.property(EngineDetails::class.java) + internal val engine: Property = project.objects.property() // exec operations to launch Java applications @get:Internal diff --git a/src/main/kotlin/kotlinx/kover/tasks/KoverVerificationTask.kt b/src/main/kotlin/kotlinx/kover/tasks/KoverVerificationTask.kt index 69421c4b..9786c566 100644 --- a/src/main/kotlin/kotlinx/kover/tasks/KoverVerificationTask.kt +++ b/src/main/kotlin/kotlinx/kover/tasks/KoverVerificationTask.kt @@ -6,12 +6,13 @@ import org.gradle.api.* import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.ListProperty import org.gradle.api.tasks.* +import org.gradle.kotlin.dsl.* // TODO make internal in 0.7 version - for now it public to save access to deprecated fields to print deprecation message @CacheableTask public open class KoverVerificationTask : KoverReportTask() { @get:Nested - internal val rules: ListProperty = project.objects.listProperty(VerificationRule::class.java) + internal val rules: ListProperty = project.objects.listProperty() @get:OutputFile internal val resultFile: RegularFileProperty = project.objects.fileProperty()