191: Fix test running for common modules in MPP/Gradle (KT-29908)
This commit is contained in:
+20
-126
@@ -15,14 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.jetbrains.kotlin.idea.run
|
package org.jetbrains.kotlin.idea.run
|
||||||
|
|
||||||
|
import com.intellij.execution.Location
|
||||||
import com.intellij.execution.actions.ConfigurationContext
|
import com.intellij.execution.actions.ConfigurationContext
|
||||||
import com.intellij.execution.actions.ConfigurationFromContext
|
import com.intellij.execution.actions.ConfigurationFromContext
|
||||||
import com.intellij.execution.actions.RunConfigurationProducer
|
|
||||||
import com.intellij.execution.junit.PatternConfigurationProducer
|
|
||||||
import com.intellij.ide.plugins.PluginManager
|
import com.intellij.ide.plugins.PluginManager
|
||||||
import com.intellij.openapi.extensions.PluginId.getId
|
import com.intellij.openapi.extensions.PluginId.getId
|
||||||
import com.intellij.openapi.externalSystem.service.execution.ExternalSystemRunConfiguration
|
import com.intellij.openapi.externalSystem.service.execution.ExternalSystemRunConfiguration
|
||||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
|
||||||
import com.intellij.openapi.util.Ref
|
import com.intellij.openapi.util.Ref
|
||||||
import com.intellij.openapi.util.component1
|
import com.intellij.openapi.util.component1
|
||||||
import com.intellij.openapi.util.component2
|
import com.intellij.openapi.util.component2
|
||||||
@@ -32,7 +30,6 @@ import com.intellij.psi.PsiMethod
|
|||||||
import org.jetbrains.kotlin.idea.caches.project.isMPPModule
|
import org.jetbrains.kotlin.idea.caches.project.isMPPModule
|
||||||
import org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer
|
import org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer
|
||||||
import org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer
|
import org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer
|
||||||
import org.jetbrains.plugins.gradle.util.GradleConstants
|
|
||||||
|
|
||||||
private val IS_JUNIT_ENABLED by lazy { isPluginEnabled("JUnit") }
|
private val IS_JUNIT_ENABLED by lazy { isPluginEnabled("JUnit") }
|
||||||
private val IS_TESTNG_ENABLED by lazy { isPluginEnabled("TestNG-J") }
|
private val IS_TESTNG_ENABLED by lazy { isPluginEnabled("TestNG-J") }
|
||||||
@@ -71,31 +68,19 @@ class KotlinTestClassGradleConfigurationProducer : TestClassGradleConfigurationP
|
|||||||
sourceElement: Ref<PsiElement>
|
sourceElement: Ref<PsiElement>
|
||||||
): Boolean {
|
): Boolean {
|
||||||
if (!IS_TEST_FRAMEWORK_PLUGIN_ENABLED) return false
|
if (!IS_TEST_FRAMEWORK_PLUGIN_ENABLED) return false
|
||||||
|
context.module?.asJvmModule() ?: return false
|
||||||
|
|
||||||
val contextLocation = context.location ?: return false
|
return super.doSetupConfigurationFromContext(configuration, context, sourceElement)
|
||||||
val module = context.module?.asJvmModule() ?: return false
|
}
|
||||||
|
|
||||||
if (RunConfigurationProducer.getInstance(PatternConfigurationProducer::class.java).isMultipleElementsSelected(context)) {
|
override fun getPsiClassForLocation(contextLocation: Location<*>): PsiClass? {
|
||||||
return false
|
val leaf = contextLocation.psiElement ?: return null
|
||||||
}
|
return getTestClass(leaf)
|
||||||
val leaf = context.location?.psiElement ?: return false
|
}
|
||||||
val testClass = getTestClass(leaf) ?: return false
|
|
||||||
sourceElement.set(testClass)
|
|
||||||
|
|
||||||
if (!ExternalSystemApiUtil.isExternalSystemAwareModule(GradleConstants.SYSTEM_ID, module)) return false
|
override fun getPsiMethodForLocation(contextLocation: Location<*>): PsiMethod? {
|
||||||
|
val leaf = contextLocation.psiElement ?: return null
|
||||||
val projectPath = resolveProjectPath(module) ?: return false
|
return getTestMethod(leaf)
|
||||||
|
|
||||||
val tasksToRun = getTasksToRun(module)
|
|
||||||
if (tasksToRun.isEmpty()) return false
|
|
||||||
|
|
||||||
configuration.settings.externalProjectPath = projectPath
|
|
||||||
configuration.settings.taskNames = tasksToRun
|
|
||||||
configuration.settings.scriptParameters = String.format("--tests \"%s\"", testClass.qualifiedName)
|
|
||||||
configuration.name = testClass.name ?: "unknown"
|
|
||||||
|
|
||||||
JavaRunConfigurationExtensionManagerUtil.getInstance().extendCreatedConfiguration(configuration, contextLocation)
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFirstRun(fromContext: ConfigurationFromContext, context: ConfigurationContext, performRunnable: Runnable) {
|
override fun onFirstRun(fromContext: ConfigurationFromContext, context: ConfigurationContext, performRunnable: Runnable) {
|
||||||
@@ -109,32 +94,9 @@ class KotlinTestClassGradleConfigurationProducer : TestClassGradleConfigurationP
|
|||||||
|
|
||||||
override fun doIsConfigurationFromContext(configuration: ExternalSystemRunConfiguration, context: ConfigurationContext): Boolean {
|
override fun doIsConfigurationFromContext(configuration: ExternalSystemRunConfiguration, context: ConfigurationContext): Boolean {
|
||||||
if (!IS_TEST_FRAMEWORK_PLUGIN_ENABLED) return false
|
if (!IS_TEST_FRAMEWORK_PLUGIN_ENABLED) return false
|
||||||
|
context.module?.asJvmModule() ?: return false
|
||||||
|
|
||||||
val leaf = context.location?.psiElement ?: return false
|
return super.doIsConfigurationFromContext(configuration, context)
|
||||||
val module = context.module?.asJvmModule() ?: return false
|
|
||||||
|
|
||||||
if (RunConfigurationProducer.getInstance(PatternConfigurationProducer::class.java).isMultipleElementsSelected(context)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getTestMethod(leaf) != null) return false
|
|
||||||
|
|
||||||
val testClass = getTestClass(leaf)
|
|
||||||
if (testClass == null || testClass.qualifiedName == null) return false
|
|
||||||
|
|
||||||
|
|
||||||
val projectPath = resolveProjectPath(module) ?: return false
|
|
||||||
if (projectPath != configuration.settings.externalProjectPath) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (!configuration.settings.taskNames.containsAll(getTasksToRun(module))) return false
|
|
||||||
|
|
||||||
val scriptParameters = configuration.settings.scriptParameters + ' '
|
|
||||||
val i = scriptParameters.indexOf("--tests ")
|
|
||||||
if (i == -1) return false
|
|
||||||
|
|
||||||
val str = scriptParameters.substringAfter("--tests ").trim() + ' '
|
|
||||||
return str.startsWith("\"" + testClass.qualifiedName + "\"" + ' ') && !str.contains("--tests")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,24 +107,14 @@ class KotlinTestMethodGradleConfigurationProducer : TestMethodGradleConfiguratio
|
|||||||
sourceElement: Ref<PsiElement>
|
sourceElement: Ref<PsiElement>
|
||||||
): Boolean {
|
): Boolean {
|
||||||
if (!IS_TEST_FRAMEWORK_PLUGIN_ENABLED) return false
|
if (!IS_TEST_FRAMEWORK_PLUGIN_ENABLED) return false
|
||||||
|
|
||||||
val contextLocation = context.location ?: return false
|
|
||||||
context.module?.asJvmModule() ?: return false
|
context.module?.asJvmModule() ?: return false
|
||||||
|
|
||||||
if (RunConfigurationProducer.getInstance(PatternConfigurationProducer::class.java).isMultipleElementsSelected(context)) {
|
return super.doSetupConfigurationFromContext(configuration, context, sourceElement)
|
||||||
return false
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val psiMethod = getTestMethod(contextLocation.psiElement) ?: return false
|
override fun getPsiMethodForLocation(contextLocation: Location<*>): PsiMethod? {
|
||||||
sourceElement.set(psiMethod)
|
val leaf = contextLocation.psiElement ?: return null
|
||||||
|
return getTestMethod(leaf)
|
||||||
val containingClass = psiMethod.containingClass ?: return false
|
|
||||||
|
|
||||||
|
|
||||||
if (!applyTestMethodConfiguration(configuration, context, psiMethod, containingClass)) return false
|
|
||||||
|
|
||||||
JavaRunConfigurationExtensionManagerUtil.getInstance().extendCreatedConfiguration(configuration, contextLocation)
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFirstRun(fromContext: ConfigurationFromContext, context: ConfigurationContext, performRunnable: Runnable) {
|
override fun onFirstRun(fromContext: ConfigurationFromContext, context: ConfigurationContext, performRunnable: Runnable) {
|
||||||
@@ -176,66 +128,8 @@ class KotlinTestMethodGradleConfigurationProducer : TestMethodGradleConfiguratio
|
|||||||
|
|
||||||
override fun doIsConfigurationFromContext(configuration: ExternalSystemRunConfiguration, context: ConfigurationContext): Boolean {
|
override fun doIsConfigurationFromContext(configuration: ExternalSystemRunConfiguration, context: ConfigurationContext): Boolean {
|
||||||
if (!IS_TEST_FRAMEWORK_PLUGIN_ENABLED) return false
|
if (!IS_TEST_FRAMEWORK_PLUGIN_ENABLED) return false
|
||||||
|
context.module?.asJvmModule() ?: return false
|
||||||
|
|
||||||
if (RunConfigurationProducer.getInstance(PatternConfigurationProducer::class.java).isMultipleElementsSelected(context)) {
|
return super.doIsConfigurationFromContext(configuration, context)
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
val contextLocation = context.location ?: return false
|
|
||||||
val module = context.module?.asJvmModule() ?: return false
|
|
||||||
|
|
||||||
val psiMethod = getTestMethod(contextLocation.psiElement) ?: return false
|
|
||||||
|
|
||||||
val containingClass = psiMethod.containingClass ?: return false
|
|
||||||
|
|
||||||
|
|
||||||
val projectPath = resolveProjectPath(module) ?: return false
|
|
||||||
|
|
||||||
if (projectPath != configuration.settings.externalProjectPath) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (!configuration.settings.taskNames.containsAll(getTasksToRun(module))) return false
|
|
||||||
|
|
||||||
val scriptParameters = configuration.settings.scriptParameters + ' '
|
|
||||||
val testFilter = createTestFilter(containingClass, psiMethod)
|
|
||||||
return scriptParameters.contains(testFilter!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun applyTestMethodConfiguration(
|
|
||||||
configuration: ExternalSystemRunConfiguration,
|
|
||||||
context: ConfigurationContext,
|
|
||||||
psiMethod: PsiMethod,
|
|
||||||
vararg containingClasses: PsiClass
|
|
||||||
): Boolean {
|
|
||||||
val module = context.module ?: return false
|
|
||||||
|
|
||||||
if (!ExternalSystemApiUtil.isExternalSystemAwareModule(GradleConstants.SYSTEM_ID, module)) return false
|
|
||||||
|
|
||||||
val projectPath = resolveProjectPath(module) ?: return false
|
|
||||||
|
|
||||||
val tasksToRun = getTasksToRun(module)
|
|
||||||
if (tasksToRun.isEmpty()) return false
|
|
||||||
|
|
||||||
configuration.settings.externalProjectPath = projectPath
|
|
||||||
configuration.settings.taskNames = tasksToRun
|
|
||||||
|
|
||||||
val params = containingClasses.joinToString("") { aClass -> createTestFilter(aClass, psiMethod) ?: "" }
|
|
||||||
|
|
||||||
configuration.settings.scriptParameters = params.trim()
|
|
||||||
configuration.name = (if (containingClasses.size == 1) containingClasses[0].name + "." else "") + psiMethod.name
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
private fun createTestFilter(aClass: PsiClass, psiMethod: PsiMethod): String? {
|
|
||||||
return createTestFilter(aClass.qualifiedName, psiMethod.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createTestFilter(aClass: String?, method: String?): String? {
|
|
||||||
if (aClass == null) return null
|
|
||||||
val testFilterPattern = aClass + if (method == null) "" else '.' + method
|
|
||||||
return "--tests \"$testFilterPattern\" "
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.run
|
||||||
|
|
||||||
|
import com.intellij.openapi.externalSystem.model.ProjectKeys
|
||||||
|
import com.intellij.openapi.externalSystem.model.task.TaskData
|
||||||
|
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
||||||
|
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil
|
||||||
|
import com.intellij.openapi.module.Module
|
||||||
|
import org.jetbrains.kotlin.config.KotlinFacetSettingsProvider
|
||||||
|
import org.jetbrains.kotlin.idea.configuration.KotlinTargetData
|
||||||
|
import org.jetbrains.kotlin.platform.impl.isCommon
|
||||||
|
import org.jetbrains.plugins.gradle.execution.test.runner.GradleTestTasksProvider
|
||||||
|
import org.jetbrains.plugins.gradle.service.project.GradleProjectResolverUtil
|
||||||
|
import org.jetbrains.plugins.gradle.util.GradleConstants
|
||||||
|
|
||||||
|
class KotlinMPPGradleTestTasksProvider : GradleTestTasksProvider {
|
||||||
|
private companion object {
|
||||||
|
const val TASK_NAME_SUFFIX = "Test"
|
||||||
|
const val CLEAN_NAME_PREFIX = "clean"
|
||||||
|
|
||||||
|
val ALLOWED_TARGETS = listOf("jvm")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTasks(module: Module): List<String> {
|
||||||
|
if (!isTestCommonModule(module)) {
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
val projectPath = ExternalSystemApiUtil.getExternalProjectPath(module) ?: return emptyList()
|
||||||
|
val externalProjectInfo = ExternalSystemUtil.getExternalProjectInfo(module.project, GradleConstants.SYSTEM_ID, projectPath)
|
||||||
|
?: return emptyList()
|
||||||
|
|
||||||
|
val moduleData = GradleProjectResolverUtil.findModule(externalProjectInfo.externalProjectStructure, projectPath)
|
||||||
|
?: return emptyList()
|
||||||
|
|
||||||
|
val gradlePath = GradleProjectResolverUtil.getGradlePath(module) ?: return emptyList()
|
||||||
|
val taskNamePrefix = if (gradlePath.endsWith(':')) gradlePath else "$gradlePath:"
|
||||||
|
|
||||||
|
val kotlinTaskNameCandidates = ExternalSystemApiUtil.findAll(moduleData, KotlinTargetData.KEY)
|
||||||
|
.filter { it.data.externalName in ALLOWED_TARGETS }
|
||||||
|
.mapTo(mutableSetOf()) { it.data.externalName + TASK_NAME_SUFFIX }
|
||||||
|
|
||||||
|
return ExternalSystemApiUtil.findAll(moduleData, ProjectKeys.TASK)
|
||||||
|
.filter { it.data.name in kotlinTaskNameCandidates }
|
||||||
|
.flatMap { getTaskNames(it.data, taskNamePrefix) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isTestCommonModule(module: Module): Boolean {
|
||||||
|
val settings = KotlinFacetSettingsProvider.getInstance(module.project).getInitializedSettings(module)
|
||||||
|
return settings.platform.isCommon && settings.isTestModule
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getTaskNames(task: TaskData, namePrefix: String): List<String> {
|
||||||
|
val name = task.name
|
||||||
|
return listOf(namePrefix + CLEAN_NAME_PREFIX + name.capitalize(), namePrefix + name)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<idea-plugin>
|
||||||
|
<extensionPoints>
|
||||||
|
<extensionPoint qualifiedName="org.jetbrains.kotlin.gradleProjectImportHandler" area="IDEA_PROJECT"
|
||||||
|
interface="org.jetbrains.kotlin.idea.configuration.GradleProjectImportHandler"/>
|
||||||
|
|
||||||
|
<extensionPoint qualifiedName="org.jetbrains.kotlin.gradleModelFacade"
|
||||||
|
interface="org.jetbrains.kotlin.idea.inspections.gradle.KotlinGradleModelFacade"/>
|
||||||
|
</extensionPoints>
|
||||||
|
|
||||||
|
<extensions defaultExtensionNs="org.jetbrains.kotlin">
|
||||||
|
<buildSystemTypeDetector implementation="org.jetbrains.kotlin.idea.configuration.GradleDetector"/>
|
||||||
|
</extensions>
|
||||||
|
|
||||||
|
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
|
||||||
|
<orderEnumerationHandlerFactory implementation="org.jetbrains.kotlin.idea.gradle.execution.KotlinGradleOrderEnumerationHandler$Factory" order="first"/>
|
||||||
|
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinMPPGradleProjectResolver"/>
|
||||||
|
<testTasksProvider implementation="org.jetbrains.kotlin.idea.run.KotlinMPPGradleTestTasksProvider"/>
|
||||||
|
</extensions>
|
||||||
|
|
||||||
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
|
<projectTaskRunner implementation="org.jetbrains.kotlin.idea.gradle.execution.KotlinMPPGradleProjectTaskRunner" order="first, before gradle"/>
|
||||||
|
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinSourceSetDataService"/>
|
||||||
|
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectSettingsDataService"/>
|
||||||
|
</extensions>
|
||||||
|
</idea-plugin>
|
||||||
Reference in New Issue
Block a user