diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt index c99f068dc1f..d77d4d45d69 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt @@ -30,9 +30,9 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPlugin import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSetFactory import org.jetbrains.kotlin.gradle.targets.js.KotlinJsPlugin -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin import org.jetbrains.kotlin.gradle.tasks.KOTLIN_COMPILER_EMBEDDABLE import org.jetbrains.kotlin.gradle.tasks.KOTLIN_MODULE_GROUP +import org.jetbrains.kotlin.gradle.testing.internal.KotlinTestsRegistry import org.jetbrains.kotlin.gradle.utils.checkGradleCompatibility import org.jetbrains.kotlin.gradle.utils.loadPropertyFromResources import javax.inject.Inject @@ -73,6 +73,8 @@ abstract class KotlinBasePluginWrapper( project.kotlinExtension.sourceSets = kotlinSourceSetContainer(kotlinSourceSetFactory(project)) } + project.extensions.add(KotlinTestsRegistry.PROJECT_EXTENSION_NAME, createTestRegistry(project)) + val plugin = getPlugin(project, kotlinGradleBuildServices) setupAttributeMatchingStrategy(project) @@ -80,6 +82,8 @@ abstract class KotlinBasePluginWrapper( plugin.apply(project) } + internal open fun createTestRegistry(project: Project) = KotlinTestsRegistry(project) + private fun setupAttributeMatchingStrategy(project: Project) = with(project.dependencies.attributesSchema) { KotlinPlatformType.setupAttributesMatchingStrategy(this) KotlinUsages.setupAttributesMatchingStrategy(this) @@ -144,6 +148,8 @@ open class KotlinJsPluginWrapper @Inject constructor( override val projectExtensionClass: KClass get() = KotlinJsProjectExtension::class + + override fun createTestRegistry(project: Project) = KotlinTestsRegistry(project, "test") } open class KotlinMultiplatformPluginWrapper @Inject constructor( diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt index 6ed99662103..12ec60f5e58 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt @@ -26,7 +26,7 @@ import org.jetbrains.kotlin.gradle.dsl.kotlinExtension import org.jetbrains.kotlin.gradle.plugin.mpp.* import org.jetbrains.kotlin.gradle.targets.jvm.tasks.KotlinJvmTest import org.jetbrains.kotlin.gradle.tasks.createOrRegisterTask -import org.jetbrains.kotlin.gradle.testing.internal.registerTestTask +import org.jetbrains.kotlin.gradle.testing.internal.kotlinTestRegistry import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName import java.util.concurrent.Callable @@ -383,7 +383,7 @@ abstract class KotlinTargetConfigurator(project, platformType), KotlinJsTargetDsl { val testTaskName get() = lowerCamelCaseName(disambiguationClassifier, testTaskNameSuffix) - val testTask - get() = project.getOrCreateAggregatedTestTask( + val testTask: TaskHolder + get() = project.kotlinTestRegistry.getOrCreateAggregatedTestTask( name = testTaskName, - description = "Run JS tests for all platforms", - reportName = "jsAll", - parent = project.allTestsTask.doGetTask() + description = "Run JS tests for all platforms" ) val runTaskName get() = lowerCamelCaseName(disambiguationClassifier, runTaskNameSuffix) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/KotlinJsSubTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/KotlinJsSubTarget.kt index 06141a1ba7d..4a0ee17d573 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/KotlinJsSubTarget.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/KotlinJsSubTarget.kt @@ -17,8 +17,7 @@ import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest import org.jetbrains.kotlin.gradle.tasks.createOrRegisterTask import org.jetbrains.kotlin.gradle.testing.internal.configureConventions -import org.jetbrains.kotlin.gradle.testing.internal.registerTestTask -import org.jetbrains.kotlin.gradle.testing.internal.registerTestTaskInAggregate +import org.jetbrains.kotlin.gradle.testing.internal.kotlinTestRegistry import org.jetbrains.kotlin.utils.addIfNotNull abstract class KotlinJsSubTarget( @@ -86,8 +85,7 @@ abstract class KotlinJsSubTarget( testJs.configureConventions() } - registerTestTaskInAggregate(testJs, target.testTask.doGetTask()) - registerTestTask(testJs) + target.project.kotlinTestRegistry.registerTestTask(testJs, target.testTask.doGetTask()) project.whenEvaluated { testJs.configure { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt index 2c4180af4de..59f3ecbec73 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt @@ -18,14 +18,13 @@ import org.gradle.api.plugins.BasePlugin import org.gradle.api.tasks.Copy import org.gradle.api.tasks.Exec import org.gradle.language.base.plugins.LifecycleBasePlugin -import org.jetbrains.kotlin.gradle.dsl.KotlinNativeBinaryContainer import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.MAIN_COMPILATION_NAME import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.TEST_COMPILATION_NAME import org.jetbrains.kotlin.gradle.plugin.mpp.* import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeTest import org.jetbrains.kotlin.gradle.tasks.* import org.jetbrains.kotlin.gradle.testing.internal.configureConventions -import org.jetbrains.kotlin.gradle.testing.internal.registerTestTask +import org.jetbrains.kotlin.gradle.testing.internal.kotlinTestRegistry import java.io.File import java.util.* @@ -145,7 +144,7 @@ open class KotlinNativeTargetConfigurator( testTask.configureConventions() } - registerTestTask(testTask) + kotlinTestRegistry.registerTestTask(testTask) } else { tasks.create(taskName, Exec::class.java).apply { group = RUN_GROUP diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/testing/internal/KotlinTestsRegistry.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/testing/internal/KotlinTestsRegistry.kt new file mode 100644 index 00000000000..46fe56db362 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/testing/internal/KotlinTestsRegistry.kt @@ -0,0 +1,112 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle.testing.internal + +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.plugins.JavaBasePlugin +import org.gradle.api.tasks.testing.AbstractTestTask +import org.gradle.language.base.plugins.LifecycleBasePlugin +import org.jetbrains.kotlin.gradle.plugin.TaskHolder +import org.jetbrains.kotlin.gradle.tasks.createOrRegisterTask +import org.jetbrains.kotlin.gradle.tasks.locateTask + +/** + * Internal service for creating aggregated test tasks and registering all test tasks. + * See [KotlinTestReport] for more details about aggregated test tasks. + */ +class KotlinTestsRegistry(val project: Project, val allTestsTaskName: String = "allTests") { + val allTestsTask: TaskHolder + get() = doGetOrCreateAggregatedTestTask( + name = allTestsTaskName, + description = "Runs the tests for all targets and create aggregated report" + ) { + project.tasks.maybeCreate(LifecycleBasePlugin.CHECK_TASK_NAME) + .dependsOn(it.getTaskOrProvider()) + } + + fun registerTestTask( + taskHolder: TaskHolder, + aggregate: KotlinTestReport = allTestsTask.doGetTask() + ) { + val project = taskHolder.project + + project.tasks.getByName(LifecycleBasePlugin.CHECK_TASK_NAME).dependsOn(taskHolder.name) + project.cleanAllTestTask.dependsOn(cleanTaskName(taskHolder.name)) + aggregate.dependsOn(taskHolder.name) + + taskHolder.configure { task -> + aggregate.registerTestTask(task) + ijListenTestTask(task) + } + } + + fun getOrCreateAggregatedTestTask( + name: String, + description: String, + parent: TaskHolder? = allTestsTask + ): TaskHolder { + if (name == parent?.name) return parent + + return doGetOrCreateAggregatedTestTask(name, description, parent?.doGetTask()) + } + + private fun doGetOrCreateAggregatedTestTask( + name: String, + description: String, + parent: KotlinTestReport? = null, + configure: (TaskHolder) -> Unit = {} + ): TaskHolder { + val existed = project.locateTask(name) + if (existed != null) return existed + + val reportName = name + + val aggregate: TaskHolder = project.createOrRegisterTask(name) { aggregate -> + aggregate.description = description + aggregate.group = JavaBasePlugin.VERIFICATION_GROUP + + aggregate.destinationDir = project.testReportsDir.resolve(reportName) + + if (System.getProperty("idea.active") != null) { + aggregate.extensions.extraProperties.set("idea.internal.test", true) + } + + project.gradle.taskGraph.whenReady { graph -> + aggregate.maybeOverrideReporting(graph) + } + + parent?.addChild(aggregate) + } + + parent?.dependsOn(aggregate.getTaskOrProvider()) + + configure(aggregate) + + return aggregate + } + + private fun cleanTaskName(taskName: String): String { + check(taskName.isNotEmpty()) + return "clean" + taskName.capitalize() + } + + private val Project.cleanAllTestTask: Task + get() { + val taskName = cleanTaskName(allTestsTask.name) + return tasks.findByName(taskName) + ?: tasks.create(taskName, Task::class.java).also { + tasks.getByName(LifecycleBasePlugin.CLEAN_TASK_NAME).dependsOn(it) + } + } + + companion object { + const val PROJECT_EXTENSION_NAME = "kotlinTestRegistry" + } +} + +internal val Project.kotlinTestRegistry: KotlinTestsRegistry + get() = extensions.getByName(KotlinTestsRegistry.PROJECT_EXTENSION_NAME) as KotlinTestsRegistry \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/testing/internal/testsRegistry.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/testing/internal/testsRegistry.kt deleted file mode 100644 index 148c16e11f4..00000000000 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/testing/internal/testsRegistry.kt +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.gradle.testing.internal - -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.plugins.JavaBasePlugin -import org.gradle.api.tasks.testing.AbstractTestTask -import org.gradle.language.base.plugins.LifecycleBasePlugin -import org.jetbrains.kotlin.gradle.plugin.TaskHolder -import org.jetbrains.kotlin.gradle.tasks.createOrRegisterTask -import org.jetbrains.kotlin.gradle.tasks.locateTask - -internal val Project.allTestsTask: TaskHolder - get() = getOrCreateAggregatedTestTask( - name = "allTests", - description = "Runs the tests for all targets and create aggregated report", - reportName = "all" - ) { - tasks.maybeCreate(LifecycleBasePlugin.CHECK_TASK_NAME) - .dependsOn(it.getTaskOrProvider()) - } - -internal fun Project.getOrCreateAggregatedTestTask( - name: String, - description: String, - reportName: String, - parent: KotlinTestReport? = null, - configure: (TaskHolder) -> Unit = {} -): TaskHolder { - val existed = locateTask(name) - if (existed != null) return existed - - val aggregate: TaskHolder = createOrRegisterTask(name) { aggregate -> - aggregate.description = description - aggregate.group = JavaBasePlugin.VERIFICATION_GROUP - - aggregate.destinationDir = testReportsDir.resolve(reportName) - - if (System.getProperty("idea.active") != null) { - aggregate.extensions.extraProperties.set("idea.internal.test", true) - } - - project.gradle.taskGraph.whenReady { graph -> - aggregate.maybeOverrideReporting(graph) - } - - parent?.addChild(aggregate) - } - - parent?.dependsOn(aggregate.getTaskOrProvider()) - - configure(aggregate) - - return aggregate -} - -private fun cleanTaskName(taskName: String): String { - check(taskName.isNotEmpty()) - return "clean" + taskName.capitalize() -} - -private val Project.cleanAllTestTask: Task - get() { - val taskName = cleanTaskName(allTestsTask.name) - return tasks.findByName(taskName) - ?: tasks.create(taskName, Task::class.java).also { - tasks.getByName(LifecycleBasePlugin.CLEAN_TASK_NAME).dependsOn(it) - } - } - -@Suppress("UnstableApiUsage") -internal fun registerTestTask(taskHolder: TaskHolder) { - registerTestTaskInAggregate(taskHolder, taskHolder.project.allTestsTask.doGetTask()) -} - -internal fun registerTestTaskInAggregate( - taskHolder: TaskHolder, - allTests: KotlinTestReport -) { - val project = taskHolder.project - - project.tasks.getByName(LifecycleBasePlugin.CHECK_TASK_NAME).dependsOn(taskHolder.name) - project.cleanAllTestTask.dependsOn(cleanTaskName(taskHolder.name)) - allTests.dependsOn(taskHolder.name) - - taskHolder.configure { task -> - allTests.registerTestTask(task) - ijListenTestTask(task) - } -} \ No newline at end of file