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 160f6fc045a..8d40c68ed4e 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 @@ -25,6 +25,7 @@ import org.gradle.language.jvm.tasks.ProcessResources 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.utils.lowerCamelCaseName import java.util.concurrent.Callable @@ -272,7 +273,7 @@ abstract class AbstractKotlinTargetConfigurator isVisible = false isCanBeResolved = true // Needed for IDE import description = - "Runtime dependencies for $compilation (deprecated, use '${compilation.runtimeOnlyConfigurationName} ' instead)." + "Runtime dependencies for $compilation (deprecated, use '${compilation.runtimeOnlyConfigurationName} ' instead)." } val runtimeOnlyConfiguration = configurations.maybeCreate(compilation.runtimeOnlyConfigurationName).apply { @@ -361,23 +362,27 @@ abstract class KotlinTargetConfigurator) { - val testCompilation = target.compilations.findByName(KotlinCompilation.TEST_COMPILATION_NAME) as? KotlinCompilationToRunnableFiles<*> - ?: return // Otherwise, there is no runtime classpath + val testCompilation = + target.compilations.findByName(KotlinCompilation.TEST_COMPILATION_NAME) as? KotlinCompilationToRunnableFiles<*> + ?: return // Otherwise, there is no runtime classpath - target.project.tasks.create(lowerCamelCaseName(target.disambiguationClassifier, testTaskNameSuffix), KotlinJvmTest::class.java).apply { - registerTestTask(this) + val testTaskName = lowerCamelCaseName(target.disambiguationClassifier, testTaskNameSuffix) + val testTask = target.project.createOrRegisterTask(testTaskName) { testTask -> + testTask.targetName = target.disambiguationClassifier + } - targetName = target.disambiguationClassifier - - project.afterEvaluate { - // use afterEvaluate to override the JavaPlugin defaults for Test tasks - conventionMapping.map("testClassesDirs") { testCompilation.output.classesDirs } - conventionMapping.map("classpath") { testCompilation.runtimeDependencyFiles } - description = "Runs the unit tests." - group = JavaBasePlugin.VERIFICATION_GROUP - target.project.tasks.findByName(JavaBasePlugin.CHECK_TASK_NAME)?.dependsOn(this@apply) + testTask.project.afterEvaluate { + // use afterEvaluate to override the JavaPlugin defaults for Test tasks + testTask.configure { testTask -> + testTask.conventionMapping.map("testClassesDirs") { testCompilation.output.classesDirs } + testTask.conventionMapping.map("classpath") { testCompilation.runtimeDependencyFiles } + testTask.description = "Runs the unit tests." + testTask.group = JavaBasePlugin.VERIFICATION_GROUP + testTask.project.tasks.findByName(JavaBasePlugin.CHECK_TASK_NAME)?.dependsOn(testTask) } } + + registerTestTask(testTask) } private fun addJar(configuration: Configuration, jarArtifact: PublishArtifact) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LegacyTaskHolder.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LegacyTaskHolder.kt index b70d8ce6c24..1418e72d0de 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LegacyTaskHolder.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LegacyTaskHolder.kt @@ -5,9 +5,16 @@ package org.jetbrains.kotlin.gradle.plugin +import org.gradle.api.Project import org.gradle.api.Task -class LegacyTaskHolder(private val task: T) : TaskHolder { +class LegacyTaskHolder(private val task: T) : TaskHolder { + override val project: Project + get() = task.project + + override val name: String + get() = task.name + override fun doGetTask() = task override fun getTaskOrProvider(): Any = task diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/TaskHolder.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/TaskHolder.kt index 9fe5fd2cc22..c1fcb0e312d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/TaskHolder.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/TaskHolder.kt @@ -24,7 +24,9 @@ import org.gradle.api.Project * Reference to a org.gradle.api.Task or org.gradle.api.TaskProvider necessary in order to support flexible creation of tasks. * For gradle versions < 4.9 tasks are created meanwhile for gradle with version >= 4.9 tasks are registered */ -interface TaskHolder { +interface TaskHolder { + val project: Project + val name: String /** * Returns Task itself if task was created or TaskProvider if task was registered. diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/TaskProviderHolder.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/TaskProviderHolder.kt index f39219344c8..04816d4254b 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/TaskProviderHolder.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/TaskProviderHolder.kt @@ -16,14 +16,15 @@ package org.jetbrains.kotlin.gradle.plugin +import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.tasks.TaskProvider -class TaskProviderHolder( - private val name: String, +class TaskProviderHolder( + override val name: String, + override val project: Project, private val provider: TaskProvider ) : TaskHolder { - override fun getTaskOrProvider(): Any = provider override fun doGetTask(): T = provider.get() diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsCompilationTestsConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsCompilationTestsConfigurator.kt index 419e1c1a71b..b9366b82d3e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsCompilationTestsConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsCompilationTestsConfigurator.kt @@ -5,7 +5,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationToRunnableFiles import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile -import org.jetbrains.kotlin.gradle.tasks.registerTask +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.utils.addIfNotNull @@ -40,7 +40,7 @@ internal class KotlinJsCompilationTestsConfigurator( // apply plugin (cannot do it lazy) val nodeJs = NodeJsPlugin[target.project] - registerTask(project, testTaskName, KotlinJsTest::class.java) { testJs -> + val testJs = project.createOrRegisterTask(testTaskName) { testJs -> testJs.group = LifecycleBasePlugin.VERIFICATION_GROUP testJs.dependsOn(compileTestKotlin2Js, nodeJs.nodeJsSetupTask) @@ -54,7 +54,8 @@ internal class KotlinJsCompilationTestsConfigurator( testJs.nodeModulesToLoad.add(compileTestKotlin2Js.outputFile.name) testJs.configureConventions() - registerTestTask(testJs) } + + registerTestTask(testJs) } } \ No newline at end of file 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 99fc67ac858..2c4180af4de 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 @@ -129,24 +129,23 @@ open class KotlinNativeTargetConfigurator( val taskName = binary.runTaskName ?: return if (binary.isDefaultTestExecutable) { - tasks.create(taskName, KotlinNativeTest::class.java).apply { - tasks.maybeCreate(LifecycleBasePlugin.CHECK_TASK_NAME).dependsOn(this) + val testTask = createOrRegisterTask(taskName) { testTask -> + testTask.group = LifecycleBasePlugin.VERIFICATION_GROUP + testTask.description = "Executes Kotlin/Native unit tests for target ${binary.target.name}." + testTask.targetName = binary.compilation.target.targetName - group = LifecycleBasePlugin.VERIFICATION_GROUP - description = "Executes Kotlin/Native unit tests for target ${binary.target.name}." - targetName = binary.compilation.target.targetName + testTask.enabled = binary.target.konanTarget.isCurrentHost - enabled = binary.target.konanTarget.isCurrentHost + testTask.executable = binary.outputFile + testTask.workingDir = project.projectDir.absolutePath - executable = binary.outputFile - workingDir = project.projectDir.absolutePath + testTask.onlyIf { binary.outputFile.exists() } + testTask.dependsOn(binary.linkTaskName) - onlyIf { binary.outputFile.exists() } - dependsOn(binary.linkTaskName) - configureConventions() - - registerTestTask(this) + testTask.configureConventions() } + + 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/tasks/TasksProvider.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/TasksProvider.kt index cdb3834b6e5..d0f00981dc8 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/TasksProvider.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/TasksProvider.kt @@ -31,9 +31,17 @@ internal val canLocateTask = org.jetbrains.kotlin.gradle.utils.isGradleVersionAt * Registers the task with [name] and [type] and initialization script [body] * If Gradle with version <4.9 is used the task will be created */ -internal fun registerTask(project: Project, name: String, type: Class, body: (T) -> (Unit)): TaskHolder { +@JvmName("registerTaskOld") +@Deprecated("please use Project.createOrRegisterTask", ReplaceWith("project.createOrRegisterTask(name, body)")) +internal fun registerTask(project: Project, name: String, type: Class, body: (T) -> (Unit)): TaskHolder = + project.createOrRegisterTask(name, type, body) + +internal inline fun Project.createOrRegisterTask(name: String, noinline body: (T) -> (Unit)): TaskHolder = + createOrRegisterTask(name, T::class.java, body) + +internal fun Project.createOrRegisterTask(name: String, type: Class, body: (T) -> (Unit)): TaskHolder { return if (useLazyTaskConfiguration) { - TaskProviderHolder(name, project.tasks.register(name, type) { with(it, body) }) + TaskProviderHolder(name, project, project.tasks.register(name, type) { with(it, body) }) } else { val result = LegacyTaskHolder(project.tasks.create(name, type)) with(result.doGetTask(), body) @@ -41,13 +49,14 @@ internal fun registerTask(project: Project, name: String, type: Class } } + /** * Locates a task by [name] and [type], without triggering its creation or configuration. */ internal fun locateTask(project: Project, name: String, type: Class): TaskHolder? = if (canLocateTask) { try { - TaskProviderHolder(name, project.tasks.named(name, type)) + TaskProviderHolder(name, project, project.tasks.named(name, type)) } catch (e: UnknownTaskException) { null } @@ -89,7 +98,7 @@ internal open class KotlinTasksProvider(val targetName: String) { name: String, compilation: KotlinCompilation<*>, configureAction: (Kotlin2JsCompile) -> Unit - ): TaskHolder { + ): TaskHolder { val properties = PropertiesProvider(project) val taskClass = taskOrWorkersTask(properties) val result = registerTask(project, name, taskClass) { @@ -104,7 +113,7 @@ internal open class KotlinTasksProvider(val targetName: String) { name: String, compilation: KotlinCompilation<*>, configureAction: (KotlinCompileCommon) -> (Unit) - ): TaskHolder { + ): TaskHolder { val properties = PropertiesProvider(project) val taskClass = taskOrWorkersTask(properties) val result = registerTask(project, name, taskClass) { @@ -115,7 +124,7 @@ internal open class KotlinTasksProvider(val targetName: String) { } open fun configure( - kotlinTaskHolder: TaskHolder>, + kotlinTaskHolder: TaskHolder>, project: Project, propertiesProvider: PropertiesProvider, compilation: KotlinCompilation<*> @@ -149,7 +158,7 @@ internal class AndroidTasksProvider(targetName: String) : KotlinTasksProvider(ta RegexTaskToFriendTaskMapper.Android(targetName) override fun configure( - kotlinTaskHolder: TaskHolder>, + kotlinTaskHolder: TaskHolder>, project: Project, propertiesProvider: PropertiesProvider, compilation: KotlinCompilation<*> 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 index 4430332dbd9..895a920e694 100644 --- 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 @@ -34,31 +34,34 @@ private val Project.allTestsTask: TaskHolder private fun cleanTaskName(taskName: String) = "clean" + taskName.capitalize() @Suppress("UnstableApiUsage") -internal fun registerTestTask(task: AbstractTestTask) { - val project = task.project +internal fun registerTestTask(taskHolder: TaskHolder) { + val project = taskHolder.project val allTests = project.allTestsTask.doGetTask() - project.tasks.maybeCreate(LifecycleBasePlugin.CHECK_TASK_NAME).dependsOn(task) - project.tasks.maybeCreate(cleanTaskName(allTests.name)).dependsOn(cleanTaskName(task.name)) + val tasks = project.tasks + tasks.maybeCreate(LifecycleBasePlugin.CHECK_TASK_NAME).dependsOn(taskHolder.name) + tasks.maybeCreate(cleanTaskName(allTests.name)).dependsOn(cleanTaskName(taskHolder.name)) + allTests.dependsOn(taskHolder.name) - allTests.dependsOn(task) - allTests.registerTestTask(task) + taskHolder.configure { task -> + allTests.registerTestTask(task) - project.gradle.taskGraph.whenReady { - if (it.hasTask(allTests)) { - // when [allTestsTask] task enabled, test failure should be reported only on [allTestsTask], - // not at individual target's test tasks. To do that, we need: - // - disable all reporting in test tasks - // - enable [checkFailedTests] on [allTestsTask] + project.gradle.taskGraph.whenReady { + if (it.hasTask(allTests)) { + // when [allTestsTask] task enabled, test failure should be reported only on [allTestsTask], + // not at individual target's test tasks. To do that, we need: + // - disable all reporting in test tasks + // - enable [checkFailedTests] on [allTestsTask] - task.ignoreFailures = true - task.reports.html.isEnabled = false - task.reports.junitXml.isEnabled = false + task.ignoreFailures = true + task.reports.html.isEnabled = false + task.reports.junitXml.isEnabled = false - allTests.checkFailedTests = true - allTests.ignoreFailures = false + allTests.checkFailedTests = true + allTests.ignoreFailures = false + } } - } - ijListenTestTask(task) + ijListenTestTask(task) + } } \ No newline at end of file