From f408c249f11f98b85a9ccc5d7a989f553339d7a3 Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Mon, 2 Sep 2019 18:48:49 +0900 Subject: [PATCH] Implement class/method run configurations for MPP projects --- ...linTestClassGradleConfigurationProducer.kt | 136 +++++++++++ ...inTestMethodGradleConfigurationProducer.kt | 139 +++++++++++ .../run/KotlinGradleConfigurationProducer.kt | 14 ++ ...otlinGradleTestRunConfigurationProducer.kt | 135 ----------- ...nGradleTestRunConfigurationProducer.kt.183 | 221 ------------------ ...JvmTestClassGradleConfigurationProducer.kt | 21 ++ ...vmTestMethodGradleConfigurationProducer.kt | 20 ++ .../run/KotlinMPPGradleTestTasksProvider.kt | 3 +- ...JvmTestClassGradleConfigurationProducer.kt | 19 ++ ...vmTestMethodGradleConfigurationProducer.kt | 18 ++ .../idea/run/MultiplatformTestTasksChooser.kt | 94 ++++++++ .../kotlin/idea/run/jvmTestClassUtils.kt | 57 +++++ .../kotlin/idea/run/kotlinTestClassUtils.kt | 29 +++ .../KotlinJUnitRunConfigurationProducer.kt | 14 ++ .../jetbrains/kotlin/idea/run/jvmMppUtils.kt | 2 + idea/resources/META-INF/gradle-java.xml | 6 +- idea/resources/META-INF/gradle-java.xml.183 | 4 +- idea/resources/META-INF/gradle-java.xml.as34 | 4 +- idea/resources/META-INF/gradle.xml | 5 + idea/resources/META-INF/gradle.xml.183 | 5 + .../KotlinJSRunConfigurationDataProvider.kt | 2 +- 21 files changed, 584 insertions(+), 364 deletions(-) create mode 100644 idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/AbstractKotlinTestClassGradleConfigurationProducer.kt create mode 100644 idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/AbstractKotlinTestMethodGradleConfigurationProducer.kt create mode 100644 idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinGradleConfigurationProducer.kt delete mode 100644 idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinGradleTestRunConfigurationProducer.kt delete mode 100644 idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinGradleTestRunConfigurationProducer.kt.183 create mode 100644 idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinJvmTestClassGradleConfigurationProducer.kt create mode 100644 idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinJvmTestMethodGradleConfigurationProducer.kt create mode 100644 idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinMultiplatformJvmTestClassGradleConfigurationProducer.kt create mode 100644 idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinMultiplatformJvmTestMethodGradleConfigurationProducer.kt create mode 100644 idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/MultiplatformTestTasksChooser.kt create mode 100644 idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/jvmTestClassUtils.kt create mode 100644 idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/kotlinTestClassUtils.kt diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/AbstractKotlinTestClassGradleConfigurationProducer.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/AbstractKotlinTestClassGradleConfigurationProducer.kt new file mode 100644 index 00000000000..df03b9d6bd3 --- /dev/null +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/AbstractKotlinTestClassGradleConfigurationProducer.kt @@ -0,0 +1,136 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.execution.Location +import com.intellij.execution.actions.ConfigurationContext +import com.intellij.execution.actions.ConfigurationFromContext +import com.intellij.execution.junit.InheritorChooser +import com.intellij.openapi.externalSystem.service.execution.ExternalSystemRunConfiguration +import com.intellij.openapi.module.Module +import com.intellij.openapi.util.Ref +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.project.platform +import org.jetbrains.kotlin.platform.TargetPlatform +import org.jetbrains.plugins.gradle.execution.test.runner.* +import org.jetbrains.plugins.gradle.service.execution.GradleRunConfiguration +import org.jetbrains.plugins.gradle.util.GradleConstants +import org.jetbrains.plugins.gradle.util.GradleExecutionSettingsUtil.createTestFilterFrom + +abstract class AbstractKotlinMultiplatformTestClassGradleConfigurationProducer : AbstractKotlinTestClassGradleConfigurationProducer() { + override val forceGradleRunner: Boolean get() = true + override val hasTestFramework: Boolean get() = true + + private val mppTestTasksChooser = MultiplatformTestTasksChooser() + + abstract fun isApplicable(module: Module, platform: TargetPlatform): Boolean + + final override fun isApplicable(module: Module): Boolean { + if (!module.isNewMPPModule) { + return false + } + + val platform = module.platform ?: return false + return isApplicable(module, platform) + } + + override fun isPreferredConfiguration(self: ConfigurationFromContext?, other: ConfigurationFromContext): Boolean { + return other.isJpsJunitConfiguration() + } + + override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean { + return other.isJpsJunitConfiguration() + } + + override fun onFirstRun(fromContext: ConfigurationFromContext, context: ConfigurationContext, performRunnable: Runnable) { + val inheritorChooser: InheritorChooser = object : InheritorChooser() { + override fun runForClasses(classes: List, method: PsiMethod?, context: ConfigurationContext, runnable: Runnable) { + chooseTestClassConfiguration(fromContext, context, runnable, classes) + } + + override fun runForClass(aClass: PsiClass, psiMethod: PsiMethod?, context: ConfigurationContext, runnable: Runnable) { + chooseTestClassConfiguration(fromContext, context, runnable, listOf(aClass)) + } + } + + val sourceElement = fromContext.sourceElement as PsiClass + if (inheritorChooser.runMethodInAbstractClass(context, performRunnable, null, sourceElement)) { + return + } + + chooseTestClassConfiguration(fromContext, context, performRunnable, listOf(sourceElement)) + } + + private fun chooseTestClassConfiguration( + fromContext: ConfigurationFromContext, + context: ConfigurationContext, + performRunnable: Runnable, + classes: List + ) { + val locationName = classes.singleOrNull()?.name + val dataContext = TestTasksChooser.contextWithLocationName(context.dataContext, locationName) + + mppTestTasksChooser.multiplatformChooseTasks(context.project, dataContext, classes) { tasks -> + val configuration = fromContext.configuration as ExternalSystemRunConfiguration + val settings = configuration.settings + + val createFilter = { clazz: PsiClass -> createTestFilterFrom(clazz, hasSuffix = true) } + if (!settings.applyTestConfiguration(context.module, tasks, classes, createFilter)) { + LOG.warn("Cannot apply class test configuration, uses raw run configuration") + performRunnable.run() + } + configuration.name = classes.joinToString("|") { it.name ?: "" } + performRunnable.run() + } + } +} + +abstract class AbstractKotlinTestClassGradleConfigurationProducer + : TestClassGradleConfigurationProducer(), KotlinGradleConfigurationProducer +{ + override fun isConfigurationFromContext(configuration: ExternalSystemRunConfiguration, context: ConfigurationContext): Boolean { + if (!context.check()) { + return false + } + + if (!forceGradleRunner) { + return super.isConfigurationFromContext(configuration, context) + } + + if (GradleConstants.SYSTEM_ID != configuration.settings.externalSystemId) return false + return doIsConfigurationFromContext(configuration, context) + } + + override fun setupConfigurationFromContext( + configuration: ExternalSystemRunConfiguration, + context: ConfigurationContext, + sourceElement: Ref + ): Boolean { + if (!context.check()) { + return false + } + + if (!forceGradleRunner) { + return super.setupConfigurationFromContext(configuration, context, sourceElement) + } + + if (GradleConstants.SYSTEM_ID != configuration.settings.externalSystemId) return false + if (sourceElement.isNull) return false + + (configuration as? GradleRunConfiguration)?.isScriptDebugEnabled = false + return doSetupConfigurationFromContext(configuration, context, sourceElement) + } + + private fun ConfigurationContext.check(): Boolean { + return hasTestFramework && module != null && isApplicable(module) + } + + override fun getPsiClassForLocation(contextLocation: Location<*>) = getTestClassForKotlinTest(contextLocation) + override fun getPsiMethodForLocation(contextLocation: Location<*>) = getTestMethodForKotlinTest(contextLocation) +} 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 new file mode 100644 index 00000000000..fafbb325a5f --- /dev/null +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/AbstractKotlinTestMethodGradleConfigurationProducer.kt @@ -0,0 +1,139 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.execution.Location +import com.intellij.execution.actions.ConfigurationContext +import com.intellij.execution.actions.ConfigurationFromContext +import com.intellij.execution.junit.InheritorChooser +import com.intellij.openapi.externalSystem.service.execution.ExternalSystemRunConfiguration +import com.intellij.openapi.module.Module +import com.intellij.openapi.util.Ref +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.project.platform +import org.jetbrains.kotlin.platform.TargetPlatform +import org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer +import org.jetbrains.plugins.gradle.execution.test.runner.TestTasksChooser +import org.jetbrains.plugins.gradle.execution.test.runner.applyTestConfiguration +import org.jetbrains.plugins.gradle.service.execution.GradleRunConfiguration +import org.jetbrains.plugins.gradle.util.GradleConstants +import org.jetbrains.plugins.gradle.util.GradleExecutionSettingsUtil.createTestFilterFrom + +abstract class AbstractKotlinMultiplatformTestMethodGradleConfigurationProducer : AbstractKotlinTestMethodGradleConfigurationProducer() { + override val forceGradleRunner: Boolean get() = true + override val hasTestFramework: Boolean get() = true + + private val mppTestTasksChooser = MultiplatformTestTasksChooser() + + abstract fun isApplicable(module: Module, platform: TargetPlatform): Boolean + + final override fun isApplicable(module: Module): Boolean { + if (!module.isNewMPPModule) { + return false + } + + val platform = module.platform ?: return false + return isApplicable(module, platform) + } + + override fun isPreferredConfiguration(self: ConfigurationFromContext?, other: ConfigurationFromContext): Boolean { + return other.isJpsJunitConfiguration() + } + + override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean { + return other.isJpsJunitConfiguration() + } + + override fun onFirstRun(fromContext: ConfigurationFromContext, context: ConfigurationContext, performRunnable: Runnable) { + val psiMethod = fromContext.sourceElement as PsiMethod + val psiClass = psiMethod.containingClass ?: return + + val inheritorChooser = object : InheritorChooser() { + override fun runForClasses(classes: List, method: PsiMethod?, context: ConfigurationContext, runnable: Runnable) { + chooseTestClassConfiguration(fromContext, context, runnable, psiMethod, *classes.toTypedArray()) + } + + override fun runForClass(aClass: PsiClass, psiMethod: PsiMethod, context: ConfigurationContext, runnable: Runnable) { + chooseTestClassConfiguration(fromContext, context, runnable, psiMethod, aClass) + } + } + if (inheritorChooser.runMethodInAbstractClass(context, performRunnable, psiMethod, psiClass)) return + chooseTestClassConfiguration(fromContext, context, performRunnable, psiMethod, psiClass) + } + + private fun chooseTestClassConfiguration( + fromContext: ConfigurationFromContext, + context: ConfigurationContext, + performRunnable: Runnable, + psiMethod: PsiMethod, + vararg classes: PsiClass + ) { + val dataContext = TestTasksChooser.contextWithLocationName(context.dataContext, psiMethod.name) + + mppTestTasksChooser.multiplatformChooseTasks(context.project, dataContext, classes.asList()) { tasks -> + val configuration = fromContext.configuration as ExternalSystemRunConfiguration + val settings = configuration.settings + + val result = settings.applyTestConfiguration(context.module, tasks, *classes) { + createTestFilterFrom(context.location, it, psiMethod, true) + } + + if (result) { + configuration.name = (if (classes.size == 1) classes[0].name!! + "." else "") + psiMethod.name + performRunnable.run() + } else { + LOG.warn("Cannot apply method test configuration, uses raw run configuration") + performRunnable.run() + } + } + } +} + +abstract class AbstractKotlinTestMethodGradleConfigurationProducer + : TestMethodGradleConfigurationProducer(), KotlinGradleConfigurationProducer +{ + override fun isConfigurationFromContext(configuration: ExternalSystemRunConfiguration, context: ConfigurationContext): Boolean { + if (!context.check()) { + return false + } + + if (!forceGradleRunner) { + return super.isConfigurationFromContext(configuration, context) + } + + if (GradleConstants.SYSTEM_ID != configuration.settings.externalSystemId) return false + return doIsConfigurationFromContext(configuration, context) + } + + override fun setupConfigurationFromContext( + configuration: ExternalSystemRunConfiguration, + context: ConfigurationContext, + sourceElement: Ref + ): Boolean { + if (!context.check()) { + return false + } + + if (!forceGradleRunner) { + return super.setupConfigurationFromContext(configuration, context, sourceElement) + } + + if (GradleConstants.SYSTEM_ID != configuration.settings.externalSystemId) return false + if (sourceElement.isNull) return false + + (configuration as? GradleRunConfiguration)?.isScriptDebugEnabled = false + return doSetupConfigurationFromContext(configuration, context, sourceElement) + } + + private fun ConfigurationContext.check(): Boolean { + return hasTestFramework && module != null && isApplicable(module) + } + + override fun getPsiMethodForLocation(contextLocation: Location<*>) = getTestMethodForKotlinTest(contextLocation) +} diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinGradleConfigurationProducer.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinGradleConfigurationProducer.kt new file mode 100644 index 00000000000..acc80b5c4f4 --- /dev/null +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinGradleConfigurationProducer.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.module.Module + +interface KotlinGradleConfigurationProducer { + val forceGradleRunner: Boolean + val hasTestFramework: Boolean + fun isApplicable(module: Module): Boolean +} \ No newline at end of file diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinGradleTestRunConfigurationProducer.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinGradleTestRunConfigurationProducer.kt deleted file mode 100644 index 12626aef688..00000000000 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinGradleTestRunConfigurationProducer.kt +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.kotlin.idea.run - -import com.intellij.execution.Location -import com.intellij.execution.actions.ConfigurationContext -import com.intellij.execution.actions.ConfigurationFromContext -import com.intellij.ide.plugins.PluginManager -import com.intellij.openapi.extensions.PluginId.getId -import com.intellij.openapi.externalSystem.service.execution.ExternalSystemRunConfiguration -import com.intellij.openapi.util.Ref -import com.intellij.openapi.util.component1 -import com.intellij.openapi.util.component2 -import com.intellij.psi.PsiClass -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiMethod -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.TestMethodGradleConfigurationProducer - -private val IS_JUNIT_ENABLED by lazy { isPluginEnabled("JUnit") } -private val IS_TESTNG_ENABLED by lazy { isPluginEnabled("TestNG-J") } -private val IS_TEST_FRAMEWORK_PLUGIN_ENABLED by lazy { IS_JUNIT_ENABLED || IS_TESTNG_ENABLED } - -private fun isPluginEnabled(id: String): Boolean { - return PluginManager.isPluginInstalled(getId(id)) && id !in PluginManager.getDisabledPlugins() -} - -private fun getTestClass(leaf: PsiElement): PsiClass? { - if (IS_JUNIT_ENABLED) { - KotlinJUnitRunConfigurationProducer.getTestClass(leaf)?.let { return it } - } - if (IS_TESTNG_ENABLED) { - KotlinTestNgConfigurationProducer.getTestClassAndMethod(leaf)?.let { (testClass, testMethod) -> - return if (testMethod == null) testClass else null - } - } - return null -} - -private fun getTestMethod(leaf: PsiElement): PsiMethod? { - if (IS_JUNIT_ENABLED) { - KotlinJUnitRunConfigurationProducer.getTestMethod(leaf)?.let { return it } - } - if (IS_TESTNG_ENABLED) { - KotlinTestNgConfigurationProducer.getTestClassAndMethod(leaf)?.second?.let { return it } - } - return null -} - -class KotlinTestClassGradleConfigurationProducer : TestClassGradleConfigurationProducer() { - override fun doSetupConfigurationFromContext( - configuration: ExternalSystemRunConfiguration, - context: ConfigurationContext, - sourceElement: Ref - ): Boolean { - if (!IS_TEST_FRAMEWORK_PLUGIN_ENABLED) return false - context.module?.asJvmModule() ?: return false - - return super.doSetupConfigurationFromContext(configuration, context, sourceElement) - } - - override fun getPsiClassForLocation(contextLocation: Location<*>): PsiClass? { - val leaf = contextLocation.psiElement ?: return null - return getTestClass(leaf) - } - - override fun getPsiMethodForLocation(contextLocation: Location<*>): PsiMethod? { - val leaf = contextLocation.psiElement ?: return null - return getTestMethod(leaf) - } - - override fun onFirstRun(fromContext: ConfigurationFromContext, context: ConfigurationContext, performRunnable: Runnable) { - if (context.location?.module?.isMPPModule == true) { - // TODO: remove hack when IDEA has new API - performRunnable.run() - } else { - super.onFirstRun(fromContext, context, performRunnable) - } - } - - override fun doIsConfigurationFromContext(configuration: ExternalSystemRunConfiguration, context: ConfigurationContext): Boolean { - if (!IS_TEST_FRAMEWORK_PLUGIN_ENABLED) return false - context.module?.asJvmModule() ?: return false - - return super.doIsConfigurationFromContext(configuration, context) - } -} - -class KotlinTestMethodGradleConfigurationProducer : TestMethodGradleConfigurationProducer() { - override fun doSetupConfigurationFromContext( - configuration: ExternalSystemRunConfiguration, - context: ConfigurationContext, - sourceElement: Ref - ): Boolean { - if (!IS_TEST_FRAMEWORK_PLUGIN_ENABLED) return false - context.module?.asJvmModule() ?: return false - - return super.doSetupConfigurationFromContext(configuration, context, sourceElement) - } - - override fun getPsiMethodForLocation(contextLocation: Location<*>): PsiMethod? { - val leaf = contextLocation.psiElement ?: return null - return getTestMethod(leaf) - } - - override fun onFirstRun(fromContext: ConfigurationFromContext, context: ConfigurationContext, performRunnable: Runnable) { - if (context.location?.module?.isMPPModule == true) { - // TODO: remove hack when IDEA has new API - performRunnable.run() - } else { - super.onFirstRun(fromContext, context, performRunnable) - } - } - - override fun doIsConfigurationFromContext(configuration: ExternalSystemRunConfiguration, context: ConfigurationContext): Boolean { - if (!IS_TEST_FRAMEWORK_PLUGIN_ENABLED) return false - context.module?.asJvmModule() ?: return false - - return super.doIsConfigurationFromContext(configuration, context) - } -} diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinGradleTestRunConfigurationProducer.kt.183 b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinGradleTestRunConfigurationProducer.kt.183 deleted file mode 100644 index 8a2c7e8a191..00000000000 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinGradleTestRunConfigurationProducer.kt.183 +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.kotlin.idea.run - -import com.intellij.execution.actions.ConfigurationContext -import com.intellij.execution.actions.RunConfigurationProducer -import com.intellij.execution.junit.PatternConfigurationProducer -import com.intellij.ide.plugins.PluginManager -import com.intellij.openapi.extensions.PluginId.getId -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.component1 -import com.intellij.openapi.util.component2 -import com.intellij.psi.PsiClass -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiMethod -import org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer -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_TESTNG_ENABLED by lazy { isPluginEnabled("TestNG-J") } -private val IS_TEST_FRAMEWORK_PLUGIN_ENABLED by lazy { IS_JUNIT_ENABLED || IS_TESTNG_ENABLED } - -private fun isPluginEnabled(id: String): Boolean { - return PluginManager.isPluginInstalled(getId(id)) && id !in PluginManager.getDisabledPlugins() -} - -private fun getTestClass(leaf: PsiElement): PsiClass? { - if (IS_JUNIT_ENABLED) { - KotlinJUnitRunConfigurationProducer.getTestClass(leaf)?.let { return it } - } - if (IS_TESTNG_ENABLED) { - KotlinTestNgConfigurationProducer.getTestClassAndMethod(leaf)?.let { (testClass, testMethod) -> - return if (testMethod == null) testClass else null - } - } - return null -} - -private fun getTestMethod(leaf: PsiElement): PsiMethod? { - if (IS_JUNIT_ENABLED) { - KotlinJUnitRunConfigurationProducer.getTestMethod(leaf)?.let { return it } - } - if (IS_TESTNG_ENABLED) { - KotlinTestNgConfigurationProducer.getTestClassAndMethod(leaf)?.second?.let { return it } - } - return null -} - -class KotlinTestClassGradleConfigurationProducer : TestClassGradleConfigurationProducer() { - override fun doSetupConfigurationFromContext( - configuration: ExternalSystemRunConfiguration, - context: ConfigurationContext, - sourceElement: Ref - ): Boolean { - if (!IS_TEST_FRAMEWORK_PLUGIN_ENABLED) return false - - val contextLocation = context.location ?: return false - val module = context.module?.asJvmModule() ?: return false - - if (RunConfigurationProducer.getInstance(PatternConfigurationProducer::class.java).isMultipleElementsSelected(context)) { - return false - } - 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 - - val projectPath = resolveProjectPath(module) ?: return false - - 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 doIsConfigurationFromContext(configuration: ExternalSystemRunConfiguration, context: ConfigurationContext): Boolean { - if (!IS_TEST_FRAMEWORK_PLUGIN_ENABLED) return false - - val leaf = context.location?.psiElement ?: return false - 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") - } -} - -class KotlinTestMethodGradleConfigurationProducer : TestMethodGradleConfigurationProducer() { - override fun doSetupConfigurationFromContext( - configuration: ExternalSystemRunConfiguration, - context: ConfigurationContext, - sourceElement: Ref - ): Boolean { - if (!IS_TEST_FRAMEWORK_PLUGIN_ENABLED) return false - - val contextLocation = context.location ?: return false - context.module?.asJvmModule() ?: return false - - if (RunConfigurationProducer.getInstance(PatternConfigurationProducer::class.java).isMultipleElementsSelected(context)) { - return false - } - - val psiMethod = getTestMethod(contextLocation.psiElement) ?: return false - sourceElement.set(psiMethod) - - val containingClass = psiMethod.containingClass ?: return false - - - if (!applyTestMethodConfiguration(configuration, context, psiMethod, containingClass)) return false - - JavaRunConfigurationExtensionManagerUtil.getInstance().extendCreatedConfiguration(configuration, contextLocation) - return true - } - - override fun doIsConfigurationFromContext(configuration: ExternalSystemRunConfiguration, context: ConfigurationContext): Boolean { - if (!IS_TEST_FRAMEWORK_PLUGIN_ENABLED) return false - - if (RunConfigurationProducer.getInstance(PatternConfigurationProducer::class.java).isMultipleElementsSelected(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\" " - } - } -} diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinJvmTestClassGradleConfigurationProducer.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinJvmTestClassGradleConfigurationProducer.kt new file mode 100644 index 00000000000..581c4e1ac84 --- /dev/null +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinJvmTestClassGradleConfigurationProducer.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.execution.Location +import com.intellij.openapi.module.Module +import org.jetbrains.kotlin.idea.caches.project.isNewMPPModule +import org.jetbrains.kotlin.idea.project.platform +import org.jetbrains.kotlin.platform.jvm.isJvm + +class KotlinJvmTestClassGradleConfigurationProducer : AbstractKotlinTestClassGradleConfigurationProducer() { + override val forceGradleRunner get() = false + override val hasTestFramework get() = canRunJvmTests() + override fun isApplicable(module: Module) = module.platform.isJvm() && !module.isNewMPPModule + + override fun getPsiClassForLocation(contextLocation: Location<*>) = getTestClassForJvm(contextLocation) + override fun getPsiMethodForLocation(contextLocation: Location<*>) = getTestMethodForJvm(contextLocation) +} \ No newline at end of file diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinJvmTestMethodGradleConfigurationProducer.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinJvmTestMethodGradleConfigurationProducer.kt new file mode 100644 index 00000000000..3f8e305ed56 --- /dev/null +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinJvmTestMethodGradleConfigurationProducer.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.execution.Location +import com.intellij.openapi.module.Module +import org.jetbrains.kotlin.idea.caches.project.isNewMPPModule +import org.jetbrains.kotlin.idea.project.platform +import org.jetbrains.kotlin.platform.jvm.isJvm + +class KotlinJvmTestMethodGradleConfigurationProducer : AbstractKotlinTestMethodGradleConfigurationProducer() { + override val forceGradleRunner get() = false + override val hasTestFramework get() = canRunJvmTests() + override fun isApplicable(module: Module) = module.platform.isJvm() && !module.isNewMPPModule + + override fun getPsiMethodForLocation(contextLocation: Location<*>) = getTestMethodForJvm(contextLocation) +} \ No newline at end of file diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinMPPGradleTestTasksProvider.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinMPPGradleTestTasksProvider.kt index b176a0b99b3..0cd104807b2 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinMPPGradleTestTasksProvider.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinMPPGradleTestTasksProvider.kt @@ -50,7 +50,8 @@ class KotlinMPPGradleTestTasksProvider : GradleTestTasksProvider { } private fun isMultiplatformTestModule(module: Module): Boolean { - val settings = KotlinFacetSettingsProvider.getInstance(module.project).getInitializedSettings(module) + val settingsProvider = KotlinFacetSettingsProvider.getInstance(module.project) ?: return false + val settings = settingsProvider.getInitializedSettings(module) return settings.isMPPModule && settings.isTestModule } diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinMultiplatformJvmTestClassGradleConfigurationProducer.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinMultiplatformJvmTestClassGradleConfigurationProducer.kt new file mode 100644 index 00000000000..c54cb13258a --- /dev/null +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinMultiplatformJvmTestClassGradleConfigurationProducer.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.execution.Location +import com.intellij.openapi.module.Module +import org.jetbrains.kotlin.platform.TargetPlatform +import org.jetbrains.kotlin.platform.jvm.isJvm + +class KotlinMultiplatformJvmTestClassGradleConfigurationProducer : AbstractKotlinMultiplatformTestClassGradleConfigurationProducer() { + override val forceGradleRunner get() = forceGradleRunnerInMPP() + override fun isApplicable(module: Module, platform: TargetPlatform) = platform.isJvm() + + override fun getPsiClassForLocation(contextLocation: Location<*>) = getTestClassForJvm(contextLocation) + override fun getPsiMethodForLocation(contextLocation: Location<*>) = getTestMethodForJvm(contextLocation) +} \ No newline at end of file diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinMultiplatformJvmTestMethodGradleConfigurationProducer.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinMultiplatformJvmTestMethodGradleConfigurationProducer.kt new file mode 100644 index 00000000000..196dd49c5c1 --- /dev/null +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinMultiplatformJvmTestMethodGradleConfigurationProducer.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.execution.Location +import com.intellij.openapi.module.Module +import org.jetbrains.kotlin.platform.TargetPlatform +import org.jetbrains.kotlin.platform.jvm.isJvm + +class KotlinMultiplatformJvmTestMethodGradleConfigurationProducer : AbstractKotlinMultiplatformTestMethodGradleConfigurationProducer() { + override val forceGradleRunner get() = forceGradleRunnerInMPP() + override fun isApplicable(module: Module, platform: TargetPlatform) = platform.isJvm() + + override fun getPsiMethodForLocation(contextLocation: Location<*>) = getTestMethodForJvm(contextLocation) +} \ No newline at end of file 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 new file mode 100644 index 00000000000..ac8c8e0cfa2 --- /dev/null +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/MultiplatformTestTasksChooser.kt @@ -0,0 +1,94 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.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.idea.util.module +import org.jetbrains.plugins.gradle.execution.test.runner.* +import org.jetbrains.plugins.gradle.util.TasksToRun +import java.util.* +import java.util.function.Consumer + +class MultiplatformTestTasksChooser : TestTasksChooser() { + fun multiplatformChooseTasks( + project: Project, + dataContext: DataContext, + elements: Iterable, + handler: (List>) -> Unit + ) { + val consumer = Consumer>> { handler(it) } + val testTasks = resolveTestTasks(elements) + + when { + testTasks.isEmpty() -> super.chooseTestTasks(project, dataContext, elements, consumer) + testTasks.size == 1 -> consumer.accept(testTasks.values.toList()) + else -> chooseTestTasks(project, dataContext, testTasks, consumer) + } + } + + private fun resolveTestTasks(elements: Iterable): Map> { + val tasks = mutableMapOf>() + + for (element in elements) { + val module = element.module ?: continue + val sourceFile = getSourceFile(element) ?: continue + + val groupedTasks = module.externalSystemTestTasks().groupBy { it.targetName } + + for ((group, tasksInGroup) in groupedTasks) { + if (tasksInGroup.isEmpty()) { + continue + } else if (tasksInGroup.size == 1) { + val task = tasksInGroup[0] + val presentableName = task.presentableName + val tasksMap = tasks.getOrPut(presentableName) { LinkedHashMap() } + tasksMap[sourceFile.path] = TasksToRun.Impl(presentableName, getTaskNames(task)) + } else { + for (task in tasksInGroup) { + val rawTaskName = ':' + task.testName + val presentableName = if (group != null) "$group ($rawTaskName)" else rawTaskName + val tasksMap = tasks.getOrPut(presentableName) { LinkedHashMap() } + tasksMap[sourceFile.path] = TasksToRun.Impl(presentableName, getTaskNames(task)) + } + } + } + } + + return tasks + } + + override fun chooseTestTasks( + project: Project, + context: DataContext, + testTasks: Map>, + consumer: Consumer>> + ) { + if (ApplicationManager.getApplication().isUnitTestMode) { + val result = mutableListOf>() + + for (tasks in testTasks.values) { + result += tasks.mapValues { it.value } + } + + consumer.accept(result) + return + } + + super.chooseTestTasks(project, context, testTasks, consumer) + } + + private fun getTaskNames(task: ExternalSystemTestTask): List { + return listOf("clean" + task.testName.capitalize(), task.testName) + } +} + +private val ExternalSystemTestTask.presentableName: String + get() = targetName ?: (":$testName") \ No newline at end of file diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/jvmTestClassUtils.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/jvmTestClassUtils.kt new file mode 100644 index 00000000000..86f76ce8d51 --- /dev/null +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/jvmTestClassUtils.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.execution.Location +import com.intellij.execution.actions.ConfigurationFromContext +import com.intellij.execution.junit.JUnitConfigurationProducer +import com.intellij.execution.testframework.AbstractPatternBasedConfigurationProducer +import com.intellij.ide.plugins.PluginManager +import com.intellij.openapi.extensions.PluginId.getId +import com.intellij.openapi.util.component1 +import com.intellij.openapi.util.component2 +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiMethod + +private val isJUnitEnabled by lazy { isPluginEnabled("JUnit") } +private val isTestNgEnabled by lazy { isPluginEnabled("TestNG-J") } + +private fun isPluginEnabled(id: String): Boolean { + return PluginManager.isPluginInstalled(getId(id)) && id !in PluginManager.getDisabledPlugins() +} + +internal fun ConfigurationFromContext.isJpsJunitConfiguration(): Boolean { + return isProducedBy(JUnitConfigurationProducer::class.java) + || isProducedBy(AbstractPatternBasedConfigurationProducer::class.java) +} + +internal fun canRunJvmTests() = isJUnitEnabled || isTestNgEnabled + +internal fun getTestClassForJvm(location: Location<*>): PsiClass? { + val leaf = location.psiElement ?: return null + + if (isJUnitEnabled) { + KotlinJUnitRunConfigurationProducer.getTestClass(leaf)?.let { return it } + } + if (isTestNgEnabled) { + KotlinTestNgConfigurationProducer.getTestClassAndMethod(leaf)?.let { (testClass, testMethod) -> + return if (testMethod == null) testClass else null + } + } + return null +} + +internal fun getTestMethodForJvm(location: Location<*>): PsiMethod? { + val leaf = location.psiElement ?: return null + + if (isJUnitEnabled) { + KotlinJUnitRunConfigurationProducer.getTestMethod(leaf)?.let { return it } + } + if (isTestNgEnabled) { + KotlinTestNgConfigurationProducer.getTestClassAndMethod(leaf)?.second?.let { return it } + } + return null +} \ No newline at end of file diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/kotlinTestClassUtils.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/kotlinTestClassUtils.kt new file mode 100644 index 00000000000..b330d8228e3 --- /dev/null +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/kotlinTestClassUtils.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.execution.Location +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiMethod +import org.jetbrains.kotlin.asJava.toLightClass +import org.jetbrains.kotlin.psi.KtClass +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.KtNamedFunction +import org.jetbrains.kotlin.psi.psiUtil.getParentOfType + +internal fun getTestMethodForKotlinTest(location: Location<*>): PsiMethod? { + val leaf = location.psiElement + val function = leaf?.getParentOfType(false) ?: return null + val owner = function.getParentOfType(true) as? KtClass ?: return null + val delegate = owner.toLightClass() ?: return null + return delegate.methods.firstOrNull { it.navigationElement == function } ?: return null +} + +internal fun getTestClassForKotlinTest(location: Location<*>): PsiClass? { + val leaf = location.psiElement + val owner = leaf?.getParentOfType(true) as? KtClass ?: return null + return owner.toLightClass() +} \ No newline at end of file diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/KotlinJUnitRunConfigurationProducer.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/KotlinJUnitRunConfigurationProducer.kt index eb9414519ca..aa66d552518 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/KotlinJUnitRunConfigurationProducer.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/KotlinJUnitRunConfigurationProducer.kt @@ -23,6 +23,7 @@ import com.intellij.psi.PsiMember import com.intellij.psi.PsiMethod import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.asJava.toLightClass +import org.jetbrains.kotlin.idea.caches.project.isNewMPPModule import org.jetbrains.kotlin.idea.util.ProjectRootsUtil import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtFile @@ -35,6 +36,11 @@ class KotlinJUnitRunConfigurationProducer : RunConfigurationProducer - - + + + + diff --git a/idea/resources/META-INF/gradle-java.xml.183 b/idea/resources/META-INF/gradle-java.xml.183 index 5358353589b..eacc9049ca9 100644 --- a/idea/resources/META-INF/gradle-java.xml.183 +++ b/idea/resources/META-INF/gradle-java.xml.183 @@ -24,8 +24,8 @@ - - + + diff --git a/idea/resources/META-INF/gradle-java.xml.as34 b/idea/resources/META-INF/gradle-java.xml.as34 index a1045a58ba4..0bcdf39fd28 100644 --- a/idea/resources/META-INF/gradle-java.xml.as34 +++ b/idea/resources/META-INF/gradle-java.xml.as34 @@ -25,8 +25,8 @@ - - + + diff --git a/idea/resources/META-INF/gradle.xml b/idea/resources/META-INF/gradle.xml index 12fc24f1ab2..8b4e960055b 100644 --- a/idea/resources/META-INF/gradle.xml +++ b/idea/resources/META-INF/gradle.xml @@ -22,6 +22,11 @@ + diff --git a/idea/resources/META-INF/gradle.xml.183 b/idea/resources/META-INF/gradle.xml.183 index e7d22de87aa..e879e3a09df 100644 --- a/idea/resources/META-INF/gradle.xml.183 +++ b/idea/resources/META-INF/gradle.xml.183 @@ -21,6 +21,11 @@ + diff --git a/idea/src/org/jetbrains/kotlin/idea/js/KotlinJSRunConfigurationDataProvider.kt b/idea/src/org/jetbrains/kotlin/idea/js/KotlinJSRunConfigurationDataProvider.kt index 370b7ae2b03..aff6f21da06 100644 --- a/idea/src/org/jetbrains/kotlin/idea/js/KotlinJSRunConfigurationDataProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/js/KotlinJSRunConfigurationDataProvider.kt @@ -15,7 +15,7 @@ interface KotlinJSRunConfigurationData { val jsOutputFilePath: String } -interface KotlinJSRunConfigurationDataProvider { +interface KotlinJSRunConfigurationDataProvider { val isForTests: Boolean fun getConfigurationData(context: ConfigurationContext): T? } \ No newline at end of file