From f6679f27f4cdfd298e9ae3897cd4837b2aa5d1a8 Mon Sep 17 00:00:00 2001 From: Sergey Igushkin Date: Tue, 9 Jul 2019 18:12:14 +0300 Subject: [PATCH] Add test tasks to the Gradle model built for MPP Add `testTasks` to KotlinTarget model class, build them based on task names until proper test runs API is available. --- .../src/KotlinMPPGradleModel.kt | 5 +++ .../src/KotlinMPPGradleModelBuilder.kt | 40 ++++++++++++++++--- .../src/KotlinMPPGradleModelImpl.kt | 10 +++++ 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModel.kt b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModel.kt index 576ff2b9740..ea33eda3edc 100644 --- a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModel.kt +++ b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModel.kt @@ -140,6 +140,7 @@ interface KotlinTarget : Serializable { val disambiguationClassifier: String? val platform: KotlinPlatform val compilations: Collection + val testTasks: Collection val jar: KotlinTargetJar? companion object { @@ -147,6 +148,10 @@ interface KotlinTarget : Serializable { } } +interface KotlinTestTask : Serializable { + val taskName: String +} + interface ExtraFeatures : Serializable { val coroutinesState: String? val isHMPPEnabled: Boolean diff --git a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt index 207f8e9d025..ad62e926dd6 100644 --- a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt +++ b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt @@ -5,10 +5,7 @@ package org.jetbrains.kotlin.gradle -import org.gradle.api.Named -import org.gradle.api.NamedDomainObjectContainer -import org.gradle.api.Project -import org.gradle.api.Task +import org.gradle.api.* import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.Dependency import org.gradle.api.artifacts.component.ProjectComponentIdentifier @@ -249,7 +246,8 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService { buildCompilation(it, disambiguationClassifier, sourceSetMap, dependencyResolver, project, dependencyMapper) } val jar = buildTargetJar(gradleTarget, project) - val target = KotlinTargetImpl(gradleTarget.name, targetPresetName, disambiguationClassifier, platform, compilations, jar) + val testTasks = buildTestTasks(project, gradleTarget) + val target = KotlinTargetImpl(gradleTarget.name, targetPresetName, disambiguationClassifier, platform, compilations, testTasks, jar) compilations.forEach { it.disambiguationClassifier = target.disambiguationClassifier it.platform = target.platform @@ -257,6 +255,38 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService { return target } + private fun buildTestTasks(project: Project, gradleTarget: Named): Collection { + // TODO: use the test runs API to extract the test tasks once it is available + + // Otherwise, find the Kotlin test task with names matching the target name. This is a workaround that makes assumptions about + // the tasks naming logic and is therefore an unstable and temporary solution until test runs API is implemented: + @Suppress("UNCHECKED_CAST") + val kotlinTestTaskClass = try { + gradleTarget.javaClass.classLoader.loadClass("org.jetbrains.kotlin.gradle.tasks.KotlinTest") as Class + } catch (_: ClassNotFoundException) { + return emptyList() + } + + val targetDisambiguationClassifier = run { + val getDisambiguationClassifier = gradleTarget.javaClass.getMethodOrNull("getDisambiguationClassifier") + ?: return emptyList() + + getDisambiguationClassifier(gradleTarget) as String? + } + + // The 'targetName' of a test task matches the target disambiguation classifier, potentially with suffix, e.g. jsBrowser + val getTargetName = kotlinTestTaskClass.getDeclaredMethodOrNull("getTargetName") ?: return emptyList() + + return project.tasks.filter { kotlinTestTaskClass.isInstance(it) }.mapNotNull { task -> + val testTaskDisambiguationClassifier = getTargetName(task) as String? + task.name.takeIf { + targetDisambiguationClassifier.isNullOrEmpty() || + testTaskDisambiguationClassifier != null && + testTaskDisambiguationClassifier.startsWith(targetDisambiguationClassifier.orEmpty()) + } + }.map(::KotlinTestTaskImpl) + } + private fun buildTargetJar(gradleTarget: Named, project: Project): KotlinTargetJar? { val targetClass = gradleTarget.javaClass val getArtifactsTaskName = targetClass.getMethodOrNull("getArtifactsTaskName") ?: return null diff --git a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelImpl.kt b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelImpl.kt index 0b29f0dafeb..cb28d556c70 100644 --- a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelImpl.kt +++ b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelImpl.kt @@ -132,6 +132,7 @@ data class KotlinTargetImpl( override val disambiguationClassifier: String?, override val platform: KotlinPlatform, override val compilations: Collection, + override val testTasks: Collection, override val jar: KotlinTargetJar? ) : KotlinTarget { override fun toString() = name @@ -146,10 +147,19 @@ data class KotlinTargetImpl( cloningCache[initialCompilation] = it } }.toList(), + target.testTasks.map { initialTestTask -> + (cloningCache[initialTestTask] as? KotlinTestTask) ?: KotlinTestTaskImpl(initialTestTask.taskName).also { + cloningCache[initialTestTask] = it + } + }, KotlinTargetJarImpl(target.jar?.archiveFile) ) } +data class KotlinTestTaskImpl( + override val taskName: String +) : KotlinTestTask + data class ExtraFeaturesImpl( override val coroutinesState: String?, override val isHMPPEnabled: Boolean