Add native run tasks data to KotlinTarget.

This commit is contained in:
Konstantin Tskhovrebov
2020-04-07 15:47:29 +03:00
parent dae8872aba
commit e1a88de314
16 changed files with 185 additions and 67 deletions
@@ -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.model.project.ModuleData
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.util.Key import com.intellij.openapi.util.Key
import com.intellij.serialization.PropertyMapping
import com.intellij.util.containers.MultiMap import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments 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.gradle.*
import org.jetbrains.kotlin.idea.util.CopyableDataNodeUserDataProperty import org.jetbrains.kotlin.idea.util.CopyableDataNodeUserDataProperty
import org.jetbrains.plugins.gradle.util.GradleConstants import org.jetbrains.plugins.gradle.util.GradleConstants
import java.io.File import java.io.File
import java.io.Serializable import java.io.Serializable
import com.intellij.openapi.externalSystem.model.Key as ExternalKey import com.intellij.openapi.externalSystem.model.Key as ExternalKey
import com.intellij.serialization.PropertyMapping
var DataNode<out ModuleData>.kotlinSourceSet: KotlinSourceSetInfo? var DataNode<out ModuleData>.kotlinSourceSet: KotlinSourceSetInfo?
by CopyableDataNodeUserDataProperty(Key.create("KOTLIN_SOURCE_SET")) by CopyableDataNodeUserDataProperty(Key.create("KOTLIN_SOURCE_SET"))
@@ -49,7 +49,7 @@ class KotlinSourceSetInfo @PropertyMapping("kotlinModule") constructor(val kotli
var isTestModule: Boolean = false var isTestModule: Boolean = false
var sourceSetIdsByName: MutableMap<String, String> = LinkedHashMap() var sourceSetIdsByName: MutableMap<String, String> = LinkedHashMap()
var dependsOn: List<String> = emptyList() var dependsOn: List<String> = emptyList()
var externalSystemTestTasks: Collection<ExternalSystemTestTask> = emptyList() var externalSystemRunTasks: Collection<ExternalSystemRunTask> = emptyList()
} }
class KotlinAndroidSourceSetData @PropertyMapping("sourceSetInfos") constructor(val sourceSetInfos: List<KotlinSourceSetInfo> class KotlinAndroidSourceSetData @PropertyMapping("sourceSetInfos") constructor(val sourceSetInfos: List<KotlinSourceSetInfo>
@@ -15,7 +15,7 @@ import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.util.Key import com.intellij.openapi.util.Key
import com.intellij.util.containers.MultiMap import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments 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.gradle.*
import org.jetbrains.kotlin.idea.util.CopyableDataNodeUserDataProperty import org.jetbrains.kotlin.idea.util.CopyableDataNodeUserDataProperty
import org.jetbrains.plugins.gradle.util.GradleConstants import org.jetbrains.plugins.gradle.util.GradleConstants
@@ -45,7 +45,7 @@ class KotlinSourceSetInfo(val kotlinModule: KotlinModule) : Serializable {
var isTestModule: Boolean = false var isTestModule: Boolean = false
var sourceSetIdsByName: MutableMap<String, String> = LinkedHashMap() var sourceSetIdsByName: MutableMap<String, String> = LinkedHashMap()
var dependsOn: List<String> = emptyList() var dependsOn: List<String> = emptyList()
var externalSystemTestTasks: Collection<ExternalSystemTestTask> = emptyList() var externalSystemRunTasks: Collection<ExternalSystemRunTask> = emptyList()
} }
class KotlinAndroidSourceSetData( class KotlinAndroidSourceSetData(
@@ -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.K2JVMCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.ManualLanguageFeatureSetting import org.jetbrains.kotlin.cli.common.arguments.ManualLanguageFeatureSetting
import org.jetbrains.kotlin.cli.common.arguments.parseCommandLineArguments import org.jetbrains.kotlin.cli.common.arguments.parseCommandLineArguments
import org.jetbrains.kotlin.config.ExternalSystemTestTask import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.gradle.* 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.GradlePropertiesFileFacade.Companion.KOTLIN_NOT_IMPORTED_COMMON_SOURCE_SETS_SETTING
import org.jetbrains.kotlin.idea.configuration.klib.KotlinNativeLibrariesDependencySubstitutor 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 sourceSetMap = projectDataNode.getUserData(GradleProjectResolver.RESOLVED_SOURCE_SETS)!!
val sourceSetToTestTasks = calculateTestTasks(mppModel, gradleModule, resolverCtx) val sourceSetToRunTasks = calculateRunTasks(mppModel, gradleModule, resolverCtx)
val sourceSetToCompilationData = LinkedHashMap<KotlinSourceSet, MutableSet<GradleSourceSetData>>() val sourceSetToCompilationData = LinkedHashMap<KotlinSourceSet, MutableSet<GradleSourceSetData>>()
for (target in mppModel.targets) { for (target in mppModel.targets) {
@@ -336,8 +335,8 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtensionComp
gradleModule, gradleModule,
resolverCtx resolverCtx
) ?: continue ) ?: continue
kotlinSourceSet.externalSystemTestTasks = kotlinSourceSet.externalSystemRunTasks =
compilation.sourceSets.firstNotNullResult { sourceSetToTestTasks[it] } ?: emptyList() compilation.sourceSets.firstNotNullResult { sourceSetToRunTasks[it] } ?: emptyList()
if (compilation.platform == KotlinPlatform.JVM || compilation.platform == KotlinPlatform.ANDROID) { if (compilation.platform == KotlinPlatform.JVM || compilation.platform == KotlinPlatform.ANDROID) {
compilationData.targetCompatibility = (kotlinSourceSet.compilerArguments as? K2JVMCompilerArguments)?.jvmTarget compilationData.targetCompatibility = (kotlinSourceSet.compilerArguments as? K2JVMCompilerArguments)?.jvmTarget
@@ -396,7 +395,7 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtensionComp
} }
val kotlinSourceSet = createSourceSetInfo(sourceSet, gradleModule, resolverCtx) ?: continue val kotlinSourceSet = createSourceSetInfo(sourceSet, gradleModule, resolverCtx) ?: continue
kotlinSourceSet.externalSystemTestTasks = sourceSetToTestTasks[sourceSet] ?: emptyList() kotlinSourceSet.externalSystemRunTasks = sourceSetToRunTasks[sourceSet] ?: emptyList()
val sourceSetDataNode = val sourceSetDataNode =
(existingSourceSetDataNode ?: mainModuleNode.createChild(GradleSourceSetData.KEY, sourceSetData)).also { (existingSourceSetDataNode ?: mainModuleNode.createChild(GradleSourceSetData.KEY, sourceSetData)).also {
@@ -419,19 +418,38 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtensionComp
//TODO improve passing version of used multiplatform //TODO improve passing version of used multiplatform
} }
private fun calculateTestTasks( private fun calculateRunTasks(
mppModel: KotlinMPPGradleModel, mppModel: KotlinMPPGradleModel,
gradleModule: IdeaModule, gradleModule: IdeaModule,
resolverCtx: ProjectResolverContext resolverCtx: ProjectResolverContext
): Map<KotlinSourceSet, Collection<ExternalSystemTestTask>> { ): Map<KotlinSourceSet, Collection<ExternalSystemRunTask>> {
val sourceSetToTestTasks: MutableMap<KotlinSourceSet, MutableCollection<ExternalSystemTestTask>> = HashMap() val sourceSetToRunTasks: MutableMap<KotlinSourceSet, MutableCollection<ExternalSystemRunTask>> = HashMap()
val dependsOnReverseGraph: MutableMap<String, MutableSet<KotlinSourceSet>> = HashMap() val dependsOnReverseGraph: MutableMap<String, MutableSet<KotlinSourceSet>> = HashMap()
mppModel.targets.forEach { target -> mppModel.targets.forEach { target ->
target.compilations.forEach { compilation -> target.compilations.forEach { compilation ->
val testTasks = target.testTasks.filter { testTask -> testTask.compilationName == compilation.name } val testRunTasks = target.testRunTasks
.map { ExternalSystemTestTask(it.taskName, getKotlinModuleId(gradleModule, compilation, resolverCtx), target.name) } .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 -> compilation.sourceSets.forEach { sourceSet ->
sourceSetToTestTasks.getOrPut(sourceSet) { LinkedHashSet() } += testTasks sourceSetToRunTasks.getOrPut(sourceSet) { LinkedHashSet() } += allRunTasks
sourceSet.dependsOnSourceSets.forEach { dependentModule -> sourceSet.dependsOnSourceSets.forEach { dependentModule ->
dependsOnReverseGraph.getOrPut(dependentModule) { LinkedHashSet() } += sourceSet dependsOnReverseGraph.getOrPut(dependentModule) { LinkedHashSet() } += sourceSet
} }
@@ -440,10 +458,10 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtensionComp
} }
mppModel.sourceSets.forEach { (sourceSetName, sourceSet) -> mppModel.sourceSets.forEach { (sourceSetName, sourceSet) ->
dependsOnReverseGraph[sourceSetName]?.forEach { dependingSourceSet -> dependsOnReverseGraph[sourceSetName]?.forEach { dependingSourceSet ->
sourceSetToTestTasks.getOrPut(sourceSet) { LinkedHashSet() } += sourceSetToTestTasks[dependingSourceSet] ?: emptyList() sourceSetToRunTasks.getOrPut(sourceSet) { LinkedHashSet() } += sourceSetToRunTasks[dependingSourceSet] ?: emptyList()
} }
} }
return sourceSetToTestTasks return sourceSetToRunTasks
} }
fun populateContentRoots( fun populateContentRoots(
@@ -150,7 +150,7 @@ class KotlinSourceSetDataService : AbstractProjectDataService<GradleSourceSetDat
kind = kotlinSourceSet.kotlinModule.kind kind = kotlinSourceSet.kotlinModule.kind
isTestModule = kotlinSourceSet.isTestModule isTestModule = kotlinSourceSet.isTestModule
externalSystemTestTasks = ArrayList(kotlinSourceSet.externalSystemTestTasks) externalSystemRunTasks = ArrayList(kotlinSourceSet.externalSystemRunTasks)
externalProjectId = kotlinSourceSet.gradleModuleId externalProjectId = kotlinSourceSet.gradleModuleId
@@ -56,7 +56,7 @@ open class KotlinTestTasksResolver : AbstractProjectResolverExtension() {
): MutableCollection<TaskData> { ): MutableCollection<TaskData> {
val testTaskNames = mutableSetOf<String>().apply { val testTaskNames = mutableSetOf<String>().apply {
mppModel.targets.forEach { target -> mppModel.targets.forEach { target ->
target.testTasks.forEach { testTaskModel -> target.testRunTasks.forEach { testTaskModel ->
add(testTaskModel.taskName) add(testTaskModel.taskName)
} }
} }
@@ -53,7 +53,7 @@ open class KotlinTestTasksResolver : AbstractProjectResolverExtension() {
): MutableCollection<TaskData> { ): MutableCollection<TaskData> {
val testTaskNames = mutableSetOf<String>().apply { val testTaskNames = mutableSetOf<String>().apply {
mppModel.targets.forEach { target -> mppModel.targets.forEach { target ->
target.testTasks.forEach { testTaskModel -> target.testRunTasks.forEach { testTaskModel ->
add(testTaskModel.taskName) add(testTaskModel.taskName)
} }
} }
@@ -53,7 +53,7 @@ open class KotlinTestTasksResolver : AbstractProjectResolverExtension() {
): MutableCollection<TaskData> { ): MutableCollection<TaskData> {
val testTaskNames = mutableSetOf<String>().apply { val testTaskNames = mutableSetOf<String>().apply {
mppModel.targets.forEach { target -> mppModel.targets.forEach { target ->
target.testTasks.forEach { testTaskModel -> target.testRunTasks.forEach { testTaskModel ->
add(testTaskModel.taskName) add(testTaskModel.taskName)
} }
} }
@@ -19,7 +19,7 @@ import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod import com.intellij.psi.PsiMethod
import org.jetbrains.kotlin.idea.caches.project.isNewMPPModule 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.project.platform
import org.jetbrains.kotlin.idea.util.module import org.jetbrains.kotlin.idea.util.module
import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.platform.TargetPlatform
@@ -83,7 +83,7 @@ abstract class AbstractKotlinMultiplatformTestMethodGradleConfigurationProducer
val availableTargets = val availableTargets =
classes classes
.mapNotNull { psiClass -> psiClass.module } .mapNotNull { psiClass -> psiClass.module }
.flatMap { module -> module.externalSystemTestTasks() } .flatMap { module -> module.externalSystemTestRunTasks() }
.map { extTask -> extTask.targetName } .map { extTask -> extTask.targetName }
.distinct() .distinct()
@@ -9,8 +9,8 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.ExternalSystemTestTask import org.jetbrains.kotlin.config.ExternalSystemRunTask
import org.jetbrains.kotlin.idea.facet.externalSystemTestTasks import org.jetbrains.kotlin.idea.facet.externalSystemTestRunTasks
import org.jetbrains.kotlin.idea.util.module import org.jetbrains.kotlin.idea.util.module
import org.jetbrains.plugins.gradle.execution.test.runner.* import org.jetbrains.plugins.gradle.execution.test.runner.*
import org.jetbrains.plugins.gradle.util.TasksToRun import org.jetbrains.plugins.gradle.util.TasksToRun
@@ -47,7 +47,7 @@ class MultiplatformTestTasksChooser : TestTasksChooser() {
val module = element.module ?: continue val module = element.module ?: continue
val sourceFile = getSourceFile(element) ?: 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) { for ((group, tasksInGroup) in groupedTasks) {
if (tasksInGroup.isEmpty()) { if (tasksInGroup.isEmpty()) {
@@ -59,7 +59,7 @@ class MultiplatformTestTasksChooser : TestTasksChooser() {
tasksMap[sourceFile.path] = TasksToRun.Impl(presentableName, getTaskNames(task)) tasksMap[sourceFile.path] = TasksToRun.Impl(presentableName, getTaskNames(task))
} else { } else {
for (task in tasksInGroup) { for (task in tasksInGroup) {
val rawTaskName = ':' + task.testName val rawTaskName = ':' + task.taskName
val presentableName = if (group != null) "$group ($rawTaskName)" else rawTaskName val presentableName = if (group != null) "$group ($rawTaskName)" else rawTaskName
val tasksMap = tasks.getOrPut(presentableName) { LinkedHashMap() } val tasksMap = tasks.getOrPut(presentableName) { LinkedHashMap() }
tasksMap[sourceFile.path] = TasksToRun.Impl(presentableName, getTaskNames(task)) tasksMap[sourceFile.path] = TasksToRun.Impl(presentableName, getTaskNames(task))
@@ -91,10 +91,10 @@ class MultiplatformTestTasksChooser : TestTasksChooser() {
super.chooseTestTasks(project, context, testTasks, consumer) super.chooseTestTasks(project, context, testTasks, consumer)
} }
private fun getTaskNames(task: ExternalSystemTestTask): List<String> { private fun getTaskNames(task: ExternalSystemRunTask): List<String> {
return listOf("clean" + task.testName.capitalize(), task.testName) return listOf("clean" + task.taskName.capitalize(), task.taskName)
} }
} }
private val ExternalSystemTestTask.presentableName: String private val ExternalSystemRunTask.presentableName: String
get() = targetName ?: (":$testName") get() = targetName ?: (":$taskName")
@@ -14,9 +14,9 @@ import com.intellij.openapi.roots.impl.ModuleOrderEntryImpl
import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil
import org.jetbrains.jps.model.module.JpsModuleSourceRootType import org.jetbrains.jps.model.module.JpsModuleSourceRootType
import org.jetbrains.jps.util.JpsPathUtil 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.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.isHMPPEnabled
import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.idea.project.platform import org.jetbrains.kotlin.idea.project.platform
@@ -90,7 +90,7 @@ class ModuleInfo(
private val rootModel = module.rootManager private val rootModel = module.rootManager
private val expectedDependencyNames = HashSet<String>() private val expectedDependencyNames = HashSet<String>()
private val expectedSourceRoots = HashSet<String>() private val expectedSourceRoots = HashSet<String>()
private val expectedExternalSystemTestTasks = ArrayList<ExternalSystemTestTask>() private val expectedExternalSystemTestTasks = ArrayList<ExternalSystemTestRunTask>()
private val sourceFolderByPath by lazy { private val sourceFolderByPath by lazy {
rootModel.contentEntries.asSequence() rootModel.contentEntries.asSequence()
@@ -161,7 +161,7 @@ class ModuleInfo(
} }
fun externalSystemTestTask(taskName: String, projectId: String, targetName: String) { 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) { 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( 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()}"
) )
} }
@@ -140,16 +140,44 @@ val KotlinMultiplatformVersion?.isNewMPP: Boolean
val KotlinMultiplatformVersion?.isHmpp: Boolean val KotlinMultiplatformVersion?.isHmpp: Boolean
get() = this == KotlinMultiplatformVersion.M3 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 { companion object {
fun fromStringRepresentation(line: String) = 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 { class KotlinFacetSettings {
@@ -231,7 +259,7 @@ class KotlinFacetSettings {
return field return field
} }
var externalSystemTestTasks: List<ExternalSystemTestTask> = emptyList() var externalSystemRunTasks: List<ExternalSystemRunTask> = emptyList()
@Suppress("DEPRECATION_ERROR") @Suppress("DEPRECATION_ERROR")
@Deprecated( @Deprecated(
@@ -126,8 +126,15 @@ private fun readV2AndLaterConfig(element: Element): KotlinFacetSettings {
this.targetPlatform = targetPlatform this.targetPlatform = targetPlatform
readElementsList(element, "implements", "implement")?.let { implementedModuleNames = it } readElementsList(element, "implements", "implement")?.let { implementedModuleNames = it }
readElementsList(element, "dependsOnModuleNames", "dependsOn")?.let { dependsOnModuleNames = it } readElementsList(element, "dependsOnModuleNames", "dependsOn")?.let { dependsOnModuleNames = it }
readElementsList(element, "externalSystemTestTasks", "externalSystemTestTask")?.let { element.getChild("externalSystemTestTasks")?.let {
externalSystemTestTasks = it.mapNotNull { ExternalSystemTestTask.fromStringRepresentation(it) } 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 { element.getChild("sourceSets")?.let {
@@ -318,12 +325,24 @@ private fun KotlinFacetSettings.writeLatestConfig(element: Element) {
if (isHmppEnabled) { if (isHmppEnabled) {
element.setAttribute("isHmppProject", mppVersion.isHmpp.toString()) element.setAttribute("isHmppProject", mppVersion.isHmpp.toString())
} }
if (externalSystemTestTasks.isNotEmpty()) { if (externalSystemRunTasks.isNotEmpty()) {
saveElementsList( element.addContent(
element, Element("externalSystemTestTasks").apply {
externalSystemTestTasks.map { it.toStringRepresentation() }, externalSystemRunTasks.forEach { task ->
"externalSystemTestTasks", when(task) {
"externalSystemTestTask" is ExternalSystemTestRunTask -> {
addContent(
Element("externalSystemTestTask").apply { addContent(task.toStringRepresentation()) }
)
}
is ExternalSystemNativeMainRunTask -> {
addContent(
Element("externalSystemNativeMainRunTask").apply { addContent(task.toStringRepresentation()) }
)
}
}
}
}
) )
} }
if (pureKotlinSourceFolders.isNotEmpty()) { if (pureKotlinSourceFolders.isNotEmpty()) {
@@ -146,7 +146,8 @@ interface KotlinTarget : Serializable {
val disambiguationClassifier: String? val disambiguationClassifier: String?
val platform: KotlinPlatform val platform: KotlinPlatform
val compilations: Collection<KotlinCompilation> val compilations: Collection<KotlinCompilation>
val testTasks: Collection<KotlinTestTask> val testRunTasks: Collection<KotlinTestRunTask>
val nativeMainRunTasks: Collection<KotlinNativeMainRunTask>
val jar: KotlinTargetJar? val jar: KotlinTargetJar?
val konanArtifacts: List<KonanArtifactModel> val konanArtifacts: List<KonanArtifactModel>
@@ -155,11 +156,18 @@ interface KotlinTarget : Serializable {
} }
} }
interface KotlinTestTask : Serializable { interface KotlinRunTask : Serializable {
val taskName: String val taskName: String
val compilationName: String val compilationName: String
} }
interface KotlinTestRunTask : KotlinRunTask
interface KotlinNativeMainRunTask : KotlinRunTask {
val entryPoint: String
val debuggable: Boolean
}
interface ExtraFeatures : Serializable { interface ExtraFeatures : Serializable {
val coroutinesState: String? val coroutinesState: String?
val isHMPPEnabled: Boolean val isHMPPEnabled: Boolean
@@ -375,7 +375,10 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
} }
} }
val jar = buildTargetJar(gradleTarget, project) 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 artifacts = konanArtifacts(gradleTarget)
val target = KotlinTargetImpl( val target = KotlinTargetImpl(
gradleTarget.name, gradleTarget.name,
@@ -383,7 +386,8 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
disambiguationClassifier, disambiguationClassifier,
platform, platform,
compilations, compilations,
testTasks, testRunTasks,
nativeMainRunTasks,
jar, jar,
artifacts artifacts
) )
@@ -419,7 +423,23 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
) )
} }
private fun buildTestTasks(project: Project, gradleTarget: Named): Collection<KotlinTestTask> { private fun buildNativeMainRunTasks(gradleTarget: Named): Collection<KotlinNativeMainRunTask> {
val executableBinaries = (gradleTarget::class.java.getMethodOrNull("getBinaries")?.invoke(gradleTarget) as? Collection<Any>)
?.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<KotlinTestRunTask> {
val getTestRunsMethod = gradleTarget.javaClass.getMethodOrNull("getTestRuns") val getTestRunsMethod = gradleTarget.javaClass.getMethodOrNull("getTestRuns")
if (getTestRunsMethod != null) { if (getTestRunsMethod != null) {
val testRuns = getTestRunsMethod?.invoke(gradleTarget) as? Iterable<Any> val testRuns = getTestRunsMethod?.invoke(gradleTarget) as? Iterable<Any>
@@ -441,7 +461,7 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
val compilation = it.javaClass.getMethodOrNull("getCompilation")?.invoke(it) val compilation = it.javaClass.getMethodOrNull("getCompilation")?.invoke(it)
val compilationName = compilation?.javaClass?.getMethodOrNull("getCompilationName")?.invoke(compilation)?.toString() val compilationName = compilation?.javaClass?.getMethodOrNull("getCompilationName")?.invoke(compilation)?.toString()
?: KotlinCompilation.TEST_COMPILATION_NAME ?: KotlinCompilation.TEST_COMPILATION_NAME
KotlinTestTaskImpl(name, compilationName) KotlinTestRunTaskImpl(name, compilationName)
}.toList() }.toList()
} }
return emptyList() return emptyList()
@@ -482,7 +502,7 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
testTaskDisambiguationClassifier != null && testTaskDisambiguationClassifier != null &&
testTaskDisambiguationClassifier.startsWith(targetDisambiguationClassifier.orEmpty()) 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? { private fun buildTargetJar(gradleTarget: Named, project: Project): KotlinTargetJar? {
@@ -162,7 +162,8 @@ data class KotlinTargetImpl(
override val disambiguationClassifier: String?, override val disambiguationClassifier: String?,
override val platform: KotlinPlatform, override val platform: KotlinPlatform,
override val compilations: Collection<KotlinCompilation>, override val compilations: Collection<KotlinCompilation>,
override val testTasks: Collection<KotlinTestTask>, override val testRunTasks: Collection<KotlinTestRunTask>,
override val nativeMainRunTasks: Collection<KotlinNativeMainRunTask>,
override val jar: KotlinTargetJar?, override val jar: KotlinTargetJar?,
override val konanArtifacts: List<KonanArtifactModel> override val konanArtifacts: List<KonanArtifactModel>
) : KotlinTarget { ) : KotlinTarget {
@@ -178,9 +179,23 @@ data class KotlinTargetImpl(
cloningCache[initialCompilation] = it cloningCache[initialCompilation] = it
} }
}.toList(), }.toList(),
target.testTasks.map { initialTestTask -> target.testRunTasks.map { initialTestTask ->
(cloningCache[initialTestTask] as? KotlinTestTask) (cloningCache[initialTestTask] as? KotlinTestRunTask)
?: KotlinTestTaskImpl(initialTestTask.taskName, initialTestTask.compilationName).also { ?: 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 cloningCache[initialTestTask] = it
} }
}, },
@@ -189,10 +204,17 @@ data class KotlinTargetImpl(
) )
} }
data class KotlinTestTaskImpl( data class KotlinTestRunTaskImpl(
override val taskName: String, override val taskName: String,
override val compilationName: 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( data class ExtraFeaturesImpl(
override val coroutinesState: String?, override val coroutinesState: String?,
@@ -194,11 +194,14 @@ fun KotlinFacet.configureFacet(
module.externalCompilerVersion = compilerVersion module.externalCompilerVersion = compilerVersion
} }
fun Module.externalSystemTestTasks(): List<ExternalSystemTestTask> { private fun Module.externalSystemRunTasks(): List<ExternalSystemRunTask> {
val settingsProvider = KotlinFacetSettingsProvider.getInstance(project) ?: return emptyList() val settingsProvider = KotlinFacetSettingsProvider.getInstance(project) ?: return emptyList()
return settingsProvider.getInitializedSettings(this).externalSystemTestTasks return settingsProvider.getInitializedSettings(this).externalSystemRunTasks
} }
fun Module.externalSystemTestRunTasks() = externalSystemRunTasks().filterIsInstance<ExternalSystemTestRunTask>()
fun Module.externalSystemNativeMainRunTasks() = externalSystemRunTasks().filterIsInstance<ExternalSystemNativeMainRunTask>()
@Suppress("DEPRECATION_ERROR", "DeprecatedCallableAddReplaceWith") @Suppress("DEPRECATION_ERROR", "DeprecatedCallableAddReplaceWith")
@Deprecated( @Deprecated(
message = "IdePlatform is deprecated and will be removed soon, please, migrate to org.jetbrains.kotlin.platform.TargetPlatform", message = "IdePlatform is deprecated and will be removed soon, please, migrate to org.jetbrains.kotlin.platform.TargetPlatform",