From e1a88de3143584b39b5fc8be9c865140fa03cde9 Mon Sep 17 00:00:00 2001 From: Konstantin Tskhovrebov Date: Tue, 7 Apr 2020 15:47:29 +0300 Subject: [PATCH] Add native run tasks data to KotlinTarget. --- .../idea/configuration/KotlinMPPDataNodes.kt | 6 +-- .../configuration/KotlinMPPDataNodes.kt.191 | 4 +- .../KotlinMPPGradleProjectResolver.kt | 46 +++++++++++++------ .../KotlinSourceSetDataService.kt | 2 +- .../gradle/testing/KotlinTestTasksResolver.kt | 2 +- .../testing/KotlinTestTasksResolver.kt.191 | 2 +- .../testing/KotlinTestTasksResolver.kt.192 | 2 +- ...inTestMethodGradleConfigurationProducer.kt | 4 +- .../idea/run/MultiplatformTestTasksChooser.kt | 16 +++---- .../kotlin/gradle/projectStructureDSL.kt | 12 ++--- .../kotlin/config/KotlinFacetSettings.kt | 38 +++++++++++++-- .../kotlin/config/facetSerialization.kt | 35 ++++++++++---- .../src/KotlinMPPGradleModel.kt | 12 ++++- .../src/KotlinMPPGradleModelBuilder.kt | 30 ++++++++++-- .../src/KotlinMPPGradleModelImpl.kt | 34 +++++++++++--- .../jetbrains/kotlin/idea/facet/facetUtils.kt | 7 ++- 16 files changed, 185 insertions(+), 67 deletions(-) diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPDataNodes.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPDataNodes.kt index 2766a45788e..5299edca6ab 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPDataNodes.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPDataNodes.kt @@ -13,16 +13,16 @@ import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceTyp import com.intellij.openapi.externalSystem.model.project.ModuleData import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.util.Key +import com.intellij.serialization.PropertyMapping import com.intellij.util.containers.MultiMap import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments -import org.jetbrains.kotlin.config.ExternalSystemTestTask +import org.jetbrains.kotlin.config.ExternalSystemRunTask import org.jetbrains.kotlin.gradle.* import org.jetbrains.kotlin.idea.util.CopyableDataNodeUserDataProperty import org.jetbrains.plugins.gradle.util.GradleConstants import java.io.File import java.io.Serializable import com.intellij.openapi.externalSystem.model.Key as ExternalKey -import com.intellij.serialization.PropertyMapping var DataNode.kotlinSourceSet: KotlinSourceSetInfo? by CopyableDataNodeUserDataProperty(Key.create("KOTLIN_SOURCE_SET")) @@ -49,7 +49,7 @@ class KotlinSourceSetInfo @PropertyMapping("kotlinModule") constructor(val kotli var isTestModule: Boolean = false var sourceSetIdsByName: MutableMap = LinkedHashMap() var dependsOn: List = emptyList() - var externalSystemTestTasks: Collection = emptyList() + var externalSystemRunTasks: Collection = emptyList() } class KotlinAndroidSourceSetData @PropertyMapping("sourceSetInfos") constructor(val sourceSetInfos: List diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPDataNodes.kt.191 b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPDataNodes.kt.191 index ff139fb3697..5327f633aa9 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPDataNodes.kt.191 +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPDataNodes.kt.191 @@ -15,7 +15,7 @@ import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.util.Key import com.intellij.util.containers.MultiMap import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments -import org.jetbrains.kotlin.config.ExternalSystemTestTask +import org.jetbrains.kotlin.config.ExternalSystemRunTask import org.jetbrains.kotlin.gradle.* import org.jetbrains.kotlin.idea.util.CopyableDataNodeUserDataProperty import org.jetbrains.plugins.gradle.util.GradleConstants @@ -45,7 +45,7 @@ class KotlinSourceSetInfo(val kotlinModule: KotlinModule) : Serializable { var isTestModule: Boolean = false var sourceSetIdsByName: MutableMap = LinkedHashMap() var dependsOn: List = emptyList() - var externalSystemTestTasks: Collection = emptyList() + var externalSystemRunTasks: Collection = emptyList() } class KotlinAndroidSourceSetData( diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPGradleProjectResolver.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPGradleProjectResolver.kt index 9b86accbdb9..be6def2f0f6 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPGradleProjectResolver.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPGradleProjectResolver.kt @@ -33,8 +33,7 @@ import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.ManualLanguageFeatureSetting import org.jetbrains.kotlin.cli.common.arguments.parseCommandLineArguments -import org.jetbrains.kotlin.config.ExternalSystemTestTask -import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.gradle.* import org.jetbrains.kotlin.idea.configuration.GradlePropertiesFileFacade.Companion.KOTLIN_NOT_IMPORTED_COMMON_SOURCE_SETS_SETTING import org.jetbrains.kotlin.idea.configuration.klib.KotlinNativeLibrariesDependencySubstitutor @@ -283,7 +282,7 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtensionComp val sourceSetMap = projectDataNode.getUserData(GradleProjectResolver.RESOLVED_SOURCE_SETS)!! - val sourceSetToTestTasks = calculateTestTasks(mppModel, gradleModule, resolverCtx) + val sourceSetToRunTasks = calculateRunTasks(mppModel, gradleModule, resolverCtx) val sourceSetToCompilationData = LinkedHashMap>() for (target in mppModel.targets) { @@ -336,8 +335,8 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtensionComp gradleModule, resolverCtx ) ?: continue - kotlinSourceSet.externalSystemTestTasks = - compilation.sourceSets.firstNotNullResult { sourceSetToTestTasks[it] } ?: emptyList() + kotlinSourceSet.externalSystemRunTasks = + compilation.sourceSets.firstNotNullResult { sourceSetToRunTasks[it] } ?: emptyList() if (compilation.platform == KotlinPlatform.JVM || compilation.platform == KotlinPlatform.ANDROID) { compilationData.targetCompatibility = (kotlinSourceSet.compilerArguments as? K2JVMCompilerArguments)?.jvmTarget @@ -396,7 +395,7 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtensionComp } val kotlinSourceSet = createSourceSetInfo(sourceSet, gradleModule, resolverCtx) ?: continue - kotlinSourceSet.externalSystemTestTasks = sourceSetToTestTasks[sourceSet] ?: emptyList() + kotlinSourceSet.externalSystemRunTasks = sourceSetToRunTasks[sourceSet] ?: emptyList() val sourceSetDataNode = (existingSourceSetDataNode ?: mainModuleNode.createChild(GradleSourceSetData.KEY, sourceSetData)).also { @@ -419,19 +418,38 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtensionComp //TODO improve passing version of used multiplatform } - private fun calculateTestTasks( + private fun calculateRunTasks( mppModel: KotlinMPPGradleModel, gradleModule: IdeaModule, resolverCtx: ProjectResolverContext - ): Map> { - val sourceSetToTestTasks: MutableMap> = HashMap() + ): Map> { + val sourceSetToRunTasks: MutableMap> = HashMap() val dependsOnReverseGraph: MutableMap> = HashMap() mppModel.targets.forEach { target -> target.compilations.forEach { compilation -> - val testTasks = target.testTasks.filter { testTask -> testTask.compilationName == compilation.name } - .map { ExternalSystemTestTask(it.taskName, getKotlinModuleId(gradleModule, compilation, resolverCtx), target.name) } + val testRunTasks = target.testRunTasks + .filter { task -> task.compilationName == compilation.name } + .map { + ExternalSystemTestRunTask( + it.taskName, + getKotlinModuleId(gradleModule, compilation, resolverCtx), + target.name + ) + } + val nativeMainRunTasks = target.nativeMainRunTasks + .filter { task -> task.compilationName == compilation.name } + .map { + ExternalSystemNativeMainRunTask( + it.taskName, + getKotlinModuleId(gradleModule, compilation, resolverCtx), + target.name, + it.entryPoint, + it.debuggable + ) + } + val allRunTasks = testRunTasks + nativeMainRunTasks compilation.sourceSets.forEach { sourceSet -> - sourceSetToTestTasks.getOrPut(sourceSet) { LinkedHashSet() } += testTasks + sourceSetToRunTasks.getOrPut(sourceSet) { LinkedHashSet() } += allRunTasks sourceSet.dependsOnSourceSets.forEach { dependentModule -> dependsOnReverseGraph.getOrPut(dependentModule) { LinkedHashSet() } += sourceSet } @@ -440,10 +458,10 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtensionComp } mppModel.sourceSets.forEach { (sourceSetName, sourceSet) -> dependsOnReverseGraph[sourceSetName]?.forEach { dependingSourceSet -> - sourceSetToTestTasks.getOrPut(sourceSet) { LinkedHashSet() } += sourceSetToTestTasks[dependingSourceSet] ?: emptyList() + sourceSetToRunTasks.getOrPut(sourceSet) { LinkedHashSet() } += sourceSetToRunTasks[dependingSourceSet] ?: emptyList() } } - return sourceSetToTestTasks + return sourceSetToRunTasks } fun populateContentRoots( diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinSourceSetDataService.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinSourceSetDataService.kt index 1e25c01cabd..3cc09fa368d 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinSourceSetDataService.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinSourceSetDataService.kt @@ -150,7 +150,7 @@ class KotlinSourceSetDataService : AbstractProjectDataService { val testTaskNames = mutableSetOf().apply { mppModel.targets.forEach { target -> - target.testTasks.forEach { testTaskModel -> + target.testRunTasks.forEach { testTaskModel -> add(testTaskModel.taskName) } } diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/gradle/testing/KotlinTestTasksResolver.kt.191 b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/gradle/testing/KotlinTestTasksResolver.kt.191 index 8ddc3a2d687..47098ca4e86 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/gradle/testing/KotlinTestTasksResolver.kt.191 +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/gradle/testing/KotlinTestTasksResolver.kt.191 @@ -53,7 +53,7 @@ open class KotlinTestTasksResolver : AbstractProjectResolverExtension() { ): MutableCollection { val testTaskNames = mutableSetOf().apply { mppModel.targets.forEach { target -> - target.testTasks.forEach { testTaskModel -> + target.testRunTasks.forEach { testTaskModel -> add(testTaskModel.taskName) } } diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/gradle/testing/KotlinTestTasksResolver.kt.192 b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/gradle/testing/KotlinTestTasksResolver.kt.192 index 70c80d51b36..03ea2057af3 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/gradle/testing/KotlinTestTasksResolver.kt.192 +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/gradle/testing/KotlinTestTasksResolver.kt.192 @@ -53,7 +53,7 @@ open class KotlinTestTasksResolver : AbstractProjectResolverExtension() { ): MutableCollection { val testTaskNames = mutableSetOf().apply { mppModel.targets.forEach { target -> - target.testTasks.forEach { testTaskModel -> + target.testRunTasks.forEach { testTaskModel -> add(testTaskModel.taskName) } } diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/AbstractKotlinTestMethodGradleConfigurationProducer.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/AbstractKotlinTestMethodGradleConfigurationProducer.kt index c762950eba9..5582c7d3c93 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/AbstractKotlinTestMethodGradleConfigurationProducer.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/AbstractKotlinTestMethodGradleConfigurationProducer.kt @@ -19,7 +19,7 @@ import com.intellij.psi.PsiClass import com.intellij.psi.PsiElement import com.intellij.psi.PsiMethod import org.jetbrains.kotlin.idea.caches.project.isNewMPPModule -import org.jetbrains.kotlin.idea.facet.externalSystemTestTasks +import org.jetbrains.kotlin.idea.facet.externalSystemTestRunTasks import org.jetbrains.kotlin.idea.project.platform import org.jetbrains.kotlin.idea.util.module import org.jetbrains.kotlin.platform.TargetPlatform @@ -83,7 +83,7 @@ abstract class AbstractKotlinMultiplatformTestMethodGradleConfigurationProducer val availableTargets = classes .mapNotNull { psiClass -> psiClass.module } - .flatMap { module -> module.externalSystemTestTasks() } + .flatMap { module -> module.externalSystemTestRunTasks() } .map { extTask -> extTask.targetName } .distinct() diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/MultiplatformTestTasksChooser.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/MultiplatformTestTasksChooser.kt index f13a1d977f4..c64ecaffa30 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/MultiplatformTestTasksChooser.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/MultiplatformTestTasksChooser.kt @@ -9,8 +9,8 @@ import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.config.ExternalSystemTestTask -import org.jetbrains.kotlin.idea.facet.externalSystemTestTasks +import org.jetbrains.kotlin.config.ExternalSystemRunTask +import org.jetbrains.kotlin.idea.facet.externalSystemTestRunTasks import org.jetbrains.kotlin.idea.util.module import org.jetbrains.plugins.gradle.execution.test.runner.* import org.jetbrains.plugins.gradle.util.TasksToRun @@ -47,7 +47,7 @@ class MultiplatformTestTasksChooser : TestTasksChooser() { val module = element.module ?: continue val sourceFile = getSourceFile(element) ?: continue - val groupedTasks = module.externalSystemTestTasks().groupBy { it.targetName } + val groupedTasks = module.externalSystemTestRunTasks().groupBy { it.targetName } for ((group, tasksInGroup) in groupedTasks) { if (tasksInGroup.isEmpty()) { @@ -59,7 +59,7 @@ class MultiplatformTestTasksChooser : TestTasksChooser() { tasksMap[sourceFile.path] = TasksToRun.Impl(presentableName, getTaskNames(task)) } else { for (task in tasksInGroup) { - val rawTaskName = ':' + task.testName + val rawTaskName = ':' + task.taskName val presentableName = if (group != null) "$group ($rawTaskName)" else rawTaskName val tasksMap = tasks.getOrPut(presentableName) { LinkedHashMap() } tasksMap[sourceFile.path] = TasksToRun.Impl(presentableName, getTaskNames(task)) @@ -91,10 +91,10 @@ class MultiplatformTestTasksChooser : TestTasksChooser() { super.chooseTestTasks(project, context, testTasks, consumer) } - private fun getTaskNames(task: ExternalSystemTestTask): List { - return listOf("clean" + task.testName.capitalize(), task.testName) + private fun getTaskNames(task: ExternalSystemRunTask): List { + return listOf("clean" + task.taskName.capitalize(), task.taskName) } } -private val ExternalSystemTestTask.presentableName: String - get() = targetName ?: (":$testName") \ No newline at end of file +private val ExternalSystemRunTask.presentableName: String + get() = targetName ?: (":$taskName") \ No newline at end of file diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/projectStructureDSL.kt b/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/projectStructureDSL.kt index 18efc49461f..1207592e470 100644 --- a/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/projectStructureDSL.kt +++ b/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/projectStructureDSL.kt @@ -14,9 +14,9 @@ import com.intellij.openapi.roots.impl.ModuleOrderEntryImpl import com.intellij.openapi.util.io.FileUtil import org.jetbrains.jps.model.module.JpsModuleSourceRootType import org.jetbrains.jps.util.JpsPathUtil -import org.jetbrains.kotlin.config.ExternalSystemTestTask +import org.jetbrains.kotlin.config.ExternalSystemTestRunTask import org.jetbrains.kotlin.idea.facet.KotlinFacet -import org.jetbrains.kotlin.idea.facet.externalSystemTestTasks +import org.jetbrains.kotlin.idea.facet.externalSystemTestRunTasks import org.jetbrains.kotlin.idea.project.isHMPPEnabled import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.idea.project.platform @@ -90,7 +90,7 @@ class ModuleInfo( private val rootModel = module.rootManager private val expectedDependencyNames = HashSet() private val expectedSourceRoots = HashSet() - private val expectedExternalSystemTestTasks = ArrayList() + private val expectedExternalSystemTestTasks = ArrayList() private val sourceFolderByPath by lazy { rootModel.contentEntries.asSequence() @@ -161,7 +161,7 @@ class ModuleInfo( } fun externalSystemTestTask(taskName: String, projectId: String, targetName: String) { - expectedExternalSystemTestTasks.add(ExternalSystemTestTask(taskName, projectId, targetName)) + expectedExternalSystemTestTasks.add(ExternalSystemTestRunTask(taskName, projectId, targetName)) } fun libraryDependency(libraryName: String, scope: DependencyScope) { @@ -279,9 +279,9 @@ class ModuleInfo( } } - if ((!module.externalSystemTestTasks().containsAll(expectedExternalSystemTestTasks)) || (projectInfo.exhaustiveTestsList && (module.externalSystemTestTasks() != expectedExternalSystemTestTasks))) { + if ((!module.externalSystemTestRunTasks().containsAll(expectedExternalSystemTestTasks)) || (projectInfo.exhaustiveTestsList && (module.externalSystemTestRunTasks() != expectedExternalSystemTestTasks))) { projectInfo.messageCollector.report( - "Module '${module.name}': Expected tests list $expectedExternalSystemTestTasks doesn't match the actual one: ${module.externalSystemTestTasks()}" + "Module '${module.name}': Expected tests list $expectedExternalSystemTestTasks doesn't match the actual one: ${module.externalSystemTestRunTasks()}" ) } diff --git a/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinFacetSettings.kt b/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinFacetSettings.kt index c11fbd99dfa..2e2ec9eb36d 100644 --- a/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinFacetSettings.kt +++ b/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinFacetSettings.kt @@ -140,16 +140,44 @@ val KotlinMultiplatformVersion?.isNewMPP: Boolean val KotlinMultiplatformVersion?.isHmpp: Boolean get() = this == KotlinMultiplatformVersion.M3 -data class ExternalSystemTestTask(val testName: String, val externalSystemProjectId: String, val targetName: String?) { +interface ExternalSystemRunTask { + val taskName: String + val externalSystemProjectId: String + val targetName: String? +} - fun toStringRepresentation() = "$testName|$externalSystemProjectId|$targetName" +data class ExternalSystemTestRunTask( + override val taskName: String, + override val externalSystemProjectId: String, + override val targetName: String? +) : ExternalSystemRunTask { + + fun toStringRepresentation() = "$taskName|$externalSystemProjectId|$targetName" companion object { fun fromStringRepresentation(line: String) = - line.split("|").let { if (it.size == 3) ExternalSystemTestTask(it[0], it[1], it[2]) else null } + line.split("|").let { if (it.size == 3) ExternalSystemTestRunTask(it[0], it[1], it[2]) else null } } - override fun toString() = "$testName@$externalSystemProjectId [$targetName]" + override fun toString() = "$taskName@$externalSystemProjectId [$targetName]" +} + +data class ExternalSystemNativeMainRunTask( + override val taskName: String, + override val externalSystemProjectId: String, + override val targetName: String?, + val entryPoint: String, + val debuggable: Boolean, +) : ExternalSystemRunTask { + + fun toStringRepresentation() = "$taskName|$externalSystemProjectId|$targetName|$entryPoint|$debuggable" + + companion object { + fun fromStringRepresentation(line: String): ExternalSystemNativeMainRunTask? = + line.split("|").let { + if (it.size == 5) ExternalSystemNativeMainRunTask(it[0], it[1], it[2], it[3], it[4].toBoolean()) else null + } + } } class KotlinFacetSettings { @@ -231,7 +259,7 @@ class KotlinFacetSettings { return field } - var externalSystemTestTasks: List = emptyList() + var externalSystemRunTasks: List = emptyList() @Suppress("DEPRECATION_ERROR") @Deprecated( diff --git a/idea/idea-jps-common/src/org/jetbrains/kotlin/config/facetSerialization.kt b/idea/idea-jps-common/src/org/jetbrains/kotlin/config/facetSerialization.kt index 1c4fd51330c..5d751b901eb 100644 --- a/idea/idea-jps-common/src/org/jetbrains/kotlin/config/facetSerialization.kt +++ b/idea/idea-jps-common/src/org/jetbrains/kotlin/config/facetSerialization.kt @@ -126,8 +126,15 @@ private fun readV2AndLaterConfig(element: Element): KotlinFacetSettings { this.targetPlatform = targetPlatform readElementsList(element, "implements", "implement")?.let { implementedModuleNames = it } readElementsList(element, "dependsOnModuleNames", "dependsOn")?.let { dependsOnModuleNames = it } - readElementsList(element, "externalSystemTestTasks", "externalSystemTestTask")?.let { - externalSystemTestTasks = it.mapNotNull { ExternalSystemTestTask.fromStringRepresentation(it) } + element.getChild("externalSystemTestTasks")?.let { + val testRunTasks = it.getChildren("externalSystemTestTask") + .mapNotNull { (it.content.firstOrNull() as? Text)?.textTrim } + .mapNotNull { ExternalSystemTestRunTask.fromStringRepresentation(it) } + val nativeMainRunTasks = it.getChildren("externalSystemNativeMainRunTask") + .mapNotNull { (it.content.firstOrNull() as? Text)?.textTrim } + .mapNotNull { ExternalSystemNativeMainRunTask.fromStringRepresentation(it) } + + externalSystemRunTasks = testRunTasks + nativeMainRunTasks } element.getChild("sourceSets")?.let { @@ -318,12 +325,24 @@ private fun KotlinFacetSettings.writeLatestConfig(element: Element) { if (isHmppEnabled) { element.setAttribute("isHmppProject", mppVersion.isHmpp.toString()) } - if (externalSystemTestTasks.isNotEmpty()) { - saveElementsList( - element, - externalSystemTestTasks.map { it.toStringRepresentation() }, - "externalSystemTestTasks", - "externalSystemTestTask" + if (externalSystemRunTasks.isNotEmpty()) { + element.addContent( + Element("externalSystemTestTasks").apply { + externalSystemRunTasks.forEach { task -> + when(task) { + is ExternalSystemTestRunTask -> { + addContent( + Element("externalSystemTestTask").apply { addContent(task.toStringRepresentation()) } + ) + } + is ExternalSystemNativeMainRunTask -> { + addContent( + Element("externalSystemNativeMainRunTask").apply { addContent(task.toStringRepresentation()) } + ) + } + } + } + } ) } if (pureKotlinSourceFolders.isNotEmpty()) { diff --git a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModel.kt b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModel.kt index a0b2651d79d..a6940469f8e 100644 --- a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModel.kt +++ b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModel.kt @@ -146,7 +146,8 @@ interface KotlinTarget : Serializable { val disambiguationClassifier: String? val platform: KotlinPlatform val compilations: Collection - val testTasks: Collection + val testRunTasks: Collection + val nativeMainRunTasks: Collection val jar: KotlinTargetJar? val konanArtifacts: List @@ -155,11 +156,18 @@ interface KotlinTarget : Serializable { } } -interface KotlinTestTask : Serializable { +interface KotlinRunTask : Serializable { val taskName: String val compilationName: String } +interface KotlinTestRunTask : KotlinRunTask + +interface KotlinNativeMainRunTask : KotlinRunTask { + val entryPoint: String + val debuggable: Boolean +} + 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 373509f7963..13b85061249 100644 --- a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt +++ b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt @@ -375,7 +375,10 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService { } } val jar = buildTargetJar(gradleTarget, project) - val testTasks = buildTestTasks(project, gradleTarget) + val testRunTasks = buildTestRunTasks(project, gradleTarget) + val nativeMainRunTasks = + if (platform == KotlinPlatform.NATIVE) buildNativeMainRunTasks(gradleTarget) + else emptyList() val artifacts = konanArtifacts(gradleTarget) val target = KotlinTargetImpl( gradleTarget.name, @@ -383,7 +386,8 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService { disambiguationClassifier, platform, compilations, - testTasks, + testRunTasks, + nativeMainRunTasks, jar, artifacts ) @@ -419,7 +423,23 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService { ) } - private fun buildTestTasks(project: Project, gradleTarget: Named): Collection { + private fun buildNativeMainRunTasks(gradleTarget: Named): Collection { + val executableBinaries = (gradleTarget::class.java.getMethodOrNull("getBinaries")?.invoke(gradleTarget) as? Collection) + ?.filter { it.javaClass.name == "org.jetbrains.kotlin.gradle.plugin.mpp.Executable" } ?: return emptyList() + return executableBinaries.map { binary -> + val compilationName = binary.javaClass.getMethodOrNull("getCompilation")?.invoke(binary)?.let { + it.javaClass.getMethodOrNull("getCompilationName")?.invoke(it)?.toString() + } ?: KotlinCompilation.MAIN_COMPILATION_NAME + KotlinNativeMainRunTaskImpl( + binary::class.java.getMethod("getRunTaskName").invoke(binary) as String, + compilationName, + binary::class.java.getMethod("getEntryPoint").invoke(binary) as String, + binary::class.java.getMethod("getDebuggable").invoke(binary) as Boolean + ) + } + } + + private fun buildTestRunTasks(project: Project, gradleTarget: Named): Collection { val getTestRunsMethod = gradleTarget.javaClass.getMethodOrNull("getTestRuns") if (getTestRunsMethod != null) { val testRuns = getTestRunsMethod?.invoke(gradleTarget) as? Iterable @@ -441,7 +461,7 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService { val compilation = it.javaClass.getMethodOrNull("getCompilation")?.invoke(it) val compilationName = compilation?.javaClass?.getMethodOrNull("getCompilationName")?.invoke(compilation)?.toString() ?: KotlinCompilation.TEST_COMPILATION_NAME - KotlinTestTaskImpl(name, compilationName) + KotlinTestRunTaskImpl(name, compilationName) }.toList() } return emptyList() @@ -482,7 +502,7 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService { testTaskDisambiguationClassifier != null && testTaskDisambiguationClassifier.startsWith(targetDisambiguationClassifier.orEmpty()) } - }.map { KotlinTestTaskImpl(it, KotlinCompilation.TEST_COMPILATION_NAME) } + }.map { KotlinTestRunTaskImpl(it, KotlinCompilation.TEST_COMPILATION_NAME) } } private fun buildTargetJar(gradleTarget: Named, project: Project): KotlinTargetJar? { diff --git a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelImpl.kt b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelImpl.kt index a4ba166c8be..32b66df33b8 100644 --- a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelImpl.kt +++ b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelImpl.kt @@ -162,7 +162,8 @@ data class KotlinTargetImpl( override val disambiguationClassifier: String?, override val platform: KotlinPlatform, override val compilations: Collection, - override val testTasks: Collection, + override val testRunTasks: Collection, + override val nativeMainRunTasks: Collection, override val jar: KotlinTargetJar?, override val konanArtifacts: List ) : KotlinTarget { @@ -178,9 +179,23 @@ data class KotlinTargetImpl( cloningCache[initialCompilation] = it } }.toList(), - target.testTasks.map { initialTestTask -> - (cloningCache[initialTestTask] as? KotlinTestTask) - ?: KotlinTestTaskImpl(initialTestTask.taskName, initialTestTask.compilationName).also { + target.testRunTasks.map { initialTestTask -> + (cloningCache[initialTestTask] as? KotlinTestRunTask) + ?: KotlinTestRunTaskImpl( + initialTestTask.taskName, + initialTestTask.compilationName + ).also { + cloningCache[initialTestTask] = it + } + }, + target.nativeMainRunTasks.map { initialTestTask -> + (cloningCache[initialTestTask] as? KotlinNativeMainRunTask) + ?: KotlinNativeMainRunTaskImpl( + initialTestTask.taskName, + initialTestTask.compilationName, + initialTestTask.entryPoint, + initialTestTask.debuggable + ).also { cloningCache[initialTestTask] = it } }, @@ -189,10 +204,17 @@ data class KotlinTargetImpl( ) } -data class KotlinTestTaskImpl( +data class KotlinTestRunTaskImpl( override val taskName: String, override val compilationName: String -) : KotlinTestTask +) : KotlinTestRunTask + +data class KotlinNativeMainRunTaskImpl( + override val taskName: String, + override val compilationName: String, + override val entryPoint: String, + override val debuggable: Boolean +) : KotlinNativeMainRunTask data class ExtraFeaturesImpl( override val coroutinesState: String?, diff --git a/idea/src/org/jetbrains/kotlin/idea/facet/facetUtils.kt b/idea/src/org/jetbrains/kotlin/idea/facet/facetUtils.kt index 8b9d9785e16..38b2cef7790 100644 --- a/idea/src/org/jetbrains/kotlin/idea/facet/facetUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/facet/facetUtils.kt @@ -194,11 +194,14 @@ fun KotlinFacet.configureFacet( module.externalCompilerVersion = compilerVersion } -fun Module.externalSystemTestTasks(): List { +private fun Module.externalSystemRunTasks(): List { val settingsProvider = KotlinFacetSettingsProvider.getInstance(project) ?: return emptyList() - return settingsProvider.getInitializedSettings(this).externalSystemTestTasks + return settingsProvider.getInitializedSettings(this).externalSystemRunTasks } +fun Module.externalSystemTestRunTasks() = externalSystemRunTasks().filterIsInstance() +fun Module.externalSystemNativeMainRunTasks() = externalSystemRunTasks().filterIsInstance() + @Suppress("DEPRECATION_ERROR", "DeprecatedCallableAddReplaceWith") @Deprecated( message = "IdePlatform is deprecated and will be removed soon, please, migrate to org.jetbrains.kotlin.platform.TargetPlatform",