diff --git a/platform/lang-api/src/com/intellij/execution/actions/ConfigurationFromContext.java b/platform/lang-api/src/com/intellij/execution/actions/ConfigurationFromContext.java
index 60a03a8edc84..3e5444ced855 100644
--- a/platform/lang-api/src/com/intellij/execution/actions/ConfigurationFromContext.java
+++ b/platform/lang-api/src/com/intellij/execution/actions/ConfigurationFromContext.java
@@ -142,6 +142,10 @@ public abstract class ConfigurationFromContext {
if (PsiTreeUtil.isAncestor(configuration2.getSourceElement(), configuration1.getSourceElement(), true)) {
return -1;
}
+ // If neither configuration1 nor configuration2 are preferred to each other, then these are considered equal.
+ if (!configuration1.isPreferredTo(configuration2) && !configuration2.isPreferredTo(configuration1)) {
+ return 0;
+ }
if (!configuration1.isPreferredTo(configuration2)) {
return 1;
}
diff --git a/plugins/kotlin/gradle/gradle-java/resources/kotlin.gradle.gradle-java.xml b/plugins/kotlin/gradle/gradle-java/resources/kotlin.gradle.gradle-java.xml
index 302d2a448ab5..22c7f865bfbb 100644
--- a/plugins/kotlin/gradle/gradle-java/resources/kotlin.gradle.gradle-java.xml
+++ b/plugins/kotlin/gradle/gradle-java/resources/kotlin.gradle.gradle-java.xml
@@ -24,6 +24,11 @@
qualifiedName="org.jetbrains.kotlin.mppProjectResolve"
interface="org.jetbrains.kotlin.idea.gradleJava.configuration.mpp.KotlinMppGradleProjectResolverExtension"
dynamic="true"/>
+
+
@@ -143,6 +148,13 @@
+
+
+
+
+
+
+
diff --git a/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/extensions/KotlinMultiplatformCommonProducersProvider.kt b/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/extensions/KotlinMultiplatformCommonProducersProvider.kt
new file mode 100644
index 000000000000..730cc729740a
--- /dev/null
+++ b/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/extensions/KotlinMultiplatformCommonProducersProvider.kt
@@ -0,0 +1,19 @@
+// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package org.jetbrains.kotlin.idea.gradleJava.extensions
+
+import com.intellij.execution.actions.ConfigurationFromContext
+import com.intellij.openapi.extensions.ExtensionPointName
+
+/**
+ * Common interface for Run configurations producers that apply to multiplatform modules.
+ * This interface must be implemented by every producer that apply to multiplatform modules.
+ */
+interface KotlinMultiplatformCommonProducersProvider {
+ companion object {
+ val EP_NAME: ExtensionPointName =
+ ExtensionPointName.create("org.jetbrains.kotlin.idea.gradleJava.kotlinMultiplatformProducersProvider")
+ }
+
+ fun isProducedByCommonProducer(configuration: ConfigurationFromContext): Boolean
+
+}
\ No newline at end of file
diff --git a/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/run/jvmTestClassUtils.kt b/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/run/jvmTestClassUtils.kt
index 4acdcd68f9ce..8b5c01f9a10a 100644
--- a/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/run/jvmTestClassUtils.kt
+++ b/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/run/jvmTestClassUtils.kt
@@ -9,6 +9,7 @@ import com.intellij.psi.PsiClass
import com.intellij.psi.PsiMethod
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.idea.extensions.KotlinTestFrameworkProvider
+import org.jetbrains.kotlin.idea.gradleJava.extensions.KotlinMultiplatformCommonProducersProvider
internal fun ConfigurationFromContext.isJpsJunitConfiguration(): Boolean {
for (extension in KotlinTestFrameworkProvider.EP_NAME.extensionList) {
@@ -21,6 +22,13 @@ internal fun ConfigurationFromContext.isJpsJunitConfiguration(): Boolean {
return isProducedBy(AbstractPatternBasedConfigurationProducer::class.java)
}
+fun ConfigurationFromContext.isProvidedByMultiplatformProducer(): Boolean {
+ for (extension in KotlinMultiplatformCommonProducersProvider.EP_NAME.extensionList) {
+ if (extension.isProducedByCommonProducer(this)) return true
+ }
+ return false
+}
+
internal fun canRunJvmTests(): Boolean {
return KotlinTestFrameworkProvider.EP_NAME.extensionList.any { it.canRunJvmTests }
}
diff --git a/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/testing/KotlinMultiplatformAllInDirectoryConfigurationProducer.kt b/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/testing/KotlinMultiplatformAllInDirectoryConfigurationProducer.kt
index 76da3b37588e..3ef049f39b2d 100644
--- a/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/testing/KotlinMultiplatformAllInDirectoryConfigurationProducer.kt
+++ b/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/testing/KotlinMultiplatformAllInDirectoryConfigurationProducer.kt
@@ -8,22 +8,26 @@ import com.intellij.openapi.project.modules
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.base.facet.isMultiPlatformModule
import org.jetbrains.kotlin.idea.base.facet.platform.platform
+import org.jetbrains.kotlin.idea.gradleJava.extensions.KotlinMultiplatformCommonProducersProvider
import org.jetbrains.kotlin.idea.gradleJava.run.MultiplatformTestTasksChooser
+import org.jetbrains.kotlin.idea.gradleJava.run.isProvidedByMultiplatformProducer
import org.jetbrains.kotlin.platform.isCommon
import org.jetbrains.plugins.gradle.execution.test.runner.AllInDirectoryGradleConfigurationProducer
import org.jetbrains.plugins.gradle.util.createTestWildcardFilter
class KotlinMultiplatformAllInDirectoryConfigurationProducer
- : AllInDirectoryGradleConfigurationProducer() {
+ : AllInDirectoryGradleConfigurationProducer(), KotlinMultiplatformCommonProducersProvider {
private val mppTestTasksChooser = MultiplatformTestTasksChooser()
override fun isPreferredConfiguration(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean {
return !other.isProducedBy(KotlinMultiplatformAllInPackageConfigurationProducer::class.java) && super.isPreferredConfiguration(self, other)
+ && !other.isProvidedByMultiplatformProducer()
}
override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean {
- return !other.isProducedBy(KotlinMultiplatformAllInPackageConfigurationProducer::class.java) && super.shouldReplace(self, other)
+ return !other.isProducedBy(KotlinMultiplatformAllInPackageConfigurationProducer::class.java) && super.shouldReplace(self, other) &&
+ !other.isProvidedByMultiplatformProducer()
}
override fun findExistingConfiguration(context: ConfigurationContext): RunnerAndConfigurationSettings? {
@@ -55,4 +59,8 @@ class KotlinMultiplatformAllInDirectoryConfigurationProducer
return tasks.map { TestTasksToRun(it, wildcardFilter) }
}
+
+ override fun isProducedByCommonProducer(configuration: ConfigurationFromContext): Boolean {
+ return configuration.isProducedBy(this.javaClass)
+ }
}
\ No newline at end of file
diff --git a/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/testing/KotlinMultiplatformAllInPackageConfigurationProducer.kt b/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/testing/KotlinMultiplatformAllInPackageConfigurationProducer.kt
index bd261755e4f3..5ff362cbc9fc 100644
--- a/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/testing/KotlinMultiplatformAllInPackageConfigurationProducer.kt
+++ b/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/testing/KotlinMultiplatformAllInPackageConfigurationProducer.kt
@@ -6,20 +6,25 @@ import com.intellij.execution.actions.ConfigurationFromContext
import com.intellij.openapi.project.modules
import com.intellij.psi.PsiPackage
import org.jetbrains.kotlin.idea.base.facet.isMultiPlatformModule
+import org.jetbrains.kotlin.idea.gradleJava.extensions.KotlinMultiplatformCommonProducersProvider
import org.jetbrains.kotlin.idea.gradleJava.run.MultiplatformTestTasksChooser
+import org.jetbrains.kotlin.idea.gradleJava.run.isProvidedByMultiplatformProducer
import org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer
import org.jetbrains.plugins.gradle.util.createTestFilterFrom
-class KotlinMultiplatformAllInPackageConfigurationProducer: AllInPackageGradleConfigurationProducer() {
+class KotlinMultiplatformAllInPackageConfigurationProducer: AllInPackageGradleConfigurationProducer(),
+ KotlinMultiplatformCommonProducersProvider {
private val mppTestTasksChooser = MultiplatformTestTasksChooser()
override fun isPreferredConfiguration(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean {
- return other.isProducedBy(KotlinMultiplatformAllInDirectoryConfigurationProducer::class.java) || super.isPreferredConfiguration(self, other)
+ return other.isProducedBy(KotlinMultiplatformAllInDirectoryConfigurationProducer::class.java) ||
+ super.isPreferredConfiguration(self, other) && !other.isProvidedByMultiplatformProducer()
}
override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean {
- return other.isProducedBy(KotlinMultiplatformAllInDirectoryConfigurationProducer::class.java) || super.shouldReplace(self, other)
+ return other.isProducedBy(KotlinMultiplatformAllInDirectoryConfigurationProducer::class.java) ||
+ super.shouldReplace(self, other) && !other.isProvidedByMultiplatformProducer()
}
override fun getAllTestsTaskToRun(
@@ -38,4 +43,8 @@ class KotlinMultiplatformAllInPackageConfigurationProducer: AllInPackageGradleCo
return tasks.map { TestTasksToRun(it, wildcardFilter) }
}
+
+ override fun isProducedByCommonProducer(configuration: ConfigurationFromContext): Boolean {
+ return configuration.isProducedBy(this.javaClass)
+ }
}
\ No newline at end of file
diff --git a/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/testing/common/KotlinMultiplatformCommonTestClassGradleConfigurationProducer.kt b/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/testing/common/KotlinMultiplatformCommonTestClassGradleConfigurationProducer.kt
index 95a97afb742a..2501a8efeaff 100644
--- a/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/testing/common/KotlinMultiplatformCommonTestClassGradleConfigurationProducer.kt
+++ b/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/testing/common/KotlinMultiplatformCommonTestClassGradleConfigurationProducer.kt
@@ -4,14 +4,30 @@ package org.jetbrains.kotlin.idea.gradleJava.testing.common
import com.intellij.execution.RunnerAndConfigurationSettings
import com.intellij.execution.actions.ConfigurationContext
+import com.intellij.execution.actions.ConfigurationFromContext
import com.intellij.openapi.module.Module
import org.jetbrains.kotlin.idea.gradleJava.run.AbstractKotlinMultiplatformTestClassGradleConfigurationProducer
+import org.jetbrains.kotlin.idea.gradleJava.extensions.KotlinMultiplatformCommonProducersProvider
+import org.jetbrains.kotlin.idea.gradleJava.run.isProvidedByMultiplatformProducer
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.isCommon
import org.jetbrains.kotlin.platform.jvm.isJvm
-class KotlinMultiplatformCommonTestClassGradleConfigurationProducer : AbstractKotlinMultiplatformTestClassGradleConfigurationProducer() {
+class KotlinMultiplatformCommonTestClassGradleConfigurationProducer : AbstractKotlinMultiplatformTestClassGradleConfigurationProducer(),
+ KotlinMultiplatformCommonProducersProvider {
override fun isApplicable(module: Module, platform: TargetPlatform) = platform.isCommon() || platform.isJvm()
+ override fun isPreferredConfiguration(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean {
+ return !other.isProvidedByMultiplatformProducer() || super.isPreferredConfiguration(self, other)
+ }
+
+ override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean {
+ return !other.isProvidedByMultiplatformProducer() || super.shouldReplace(self, other)
+ }
+
override fun findExistingConfiguration(context: ConfigurationContext): RunnerAndConfigurationSettings? = null
+
+ override fun isProducedByCommonProducer(configuration: ConfigurationFromContext): Boolean {
+ return configuration.isProducedBy(this.javaClass)
+ }
}
\ No newline at end of file
diff --git a/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/testing/common/KotlinMultiplatformCommonTestMethodGradleConfigurationProducer.kt b/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/testing/common/KotlinMultiplatformCommonTestMethodGradleConfigurationProducer.kt
index 5117043a7b48..37141f6b2b1b 100644
--- a/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/testing/common/KotlinMultiplatformCommonTestMethodGradleConfigurationProducer.kt
+++ b/plugins/kotlin/gradle/gradle-java/src/org/jetbrains/kotlin/idea/gradleJava/testing/common/KotlinMultiplatformCommonTestMethodGradleConfigurationProducer.kt
@@ -4,13 +4,29 @@ package org.jetbrains.kotlin.idea.gradleJava.testing.common
import com.intellij.execution.RunnerAndConfigurationSettings
import com.intellij.execution.actions.ConfigurationContext
+import com.intellij.execution.actions.ConfigurationFromContext
import com.intellij.openapi.module.Module
import org.jetbrains.kotlin.idea.gradleJava.run.AbstractKotlinMultiplatformTestMethodGradleConfigurationProducer
+import org.jetbrains.kotlin.idea.gradleJava.extensions.KotlinMultiplatformCommonProducersProvider
+import org.jetbrains.kotlin.idea.gradleJava.run.isProvidedByMultiplatformProducer
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.isCommon
import org.jetbrains.kotlin.platform.jvm.isJvm
-class KotlinMultiplatformCommonTestMethodGradleConfigurationProducer : AbstractKotlinMultiplatformTestMethodGradleConfigurationProducer() {
+class KotlinMultiplatformCommonTestMethodGradleConfigurationProducer : AbstractKotlinMultiplatformTestMethodGradleConfigurationProducer(),
+ KotlinMultiplatformCommonProducersProvider {
override fun isApplicable(module: Module, platform: TargetPlatform) = platform.isCommon() || platform.isJvm()
override fun findExistingConfiguration(context: ConfigurationContext): RunnerAndConfigurationSettings? = null
+
+ override fun isPreferredConfiguration(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean {
+ return !other.isProvidedByMultiplatformProducer() || super.isPreferredConfiguration(self, other)
+ }
+
+ override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean {
+ return !other.isProvidedByMultiplatformProducer() || super.shouldReplace(self, other)
+ }
+
+ override fun isProducedByCommonProducer(configuration: ConfigurationFromContext): Boolean {
+ return configuration.isProducedBy(this.javaClass)
+ }
}
\ No newline at end of file