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 index 177d4a202c8..da9d8dfa17b 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinGradleTestRunConfigurationProducer.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/KotlinGradleTestRunConfigurationProducer.kt @@ -29,8 +29,6 @@ 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.project.platform -import org.jetbrains.kotlin.platform.impl.isJvm 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 @@ -74,8 +72,7 @@ class KotlinTestClassGradleConfigurationProducer : TestClassGradleConfigurationP if (!IS_TEST_FRAMEWORK_PLUGIN_ENABLED) return false val contextLocation = context.location ?: return false - val module = context.module ?: return false - if (!module.platform.isJvm) return false + val module = context.module?.asJvmModule() ?: return false if (RunConfigurationProducer.getInstance(PatternConfigurationProducer::class.java).isMultipleElementsSelected(context)) { return false @@ -104,8 +101,7 @@ class KotlinTestClassGradleConfigurationProducer : TestClassGradleConfigurationP if (!IS_TEST_FRAMEWORK_PLUGIN_ENABLED) return false val leaf = context.location?.psiElement ?: return false - val module = context.module ?: return false - if (!module.platform.isJvm) return false + val module = context.module?.asJvmModule() ?: return false if (RunConfigurationProducer.getInstance(PatternConfigurationProducer::class.java).isMultipleElementsSelected(context)) { return false @@ -141,8 +137,7 @@ class KotlinTestMethodGradleConfigurationProducer : TestMethodGradleConfiguratio if (!IS_TEST_FRAMEWORK_PLUGIN_ENABLED) return false val contextLocation = context.location ?: return false - val module = context.module ?: return false - if (!module.platform.isJvm) return false + context.module?.asJvmModule() ?: return false if (RunConfigurationProducer.getInstance(PatternConfigurationProducer::class.java).isMultipleElementsSelected(context)) { return false @@ -168,8 +163,7 @@ class KotlinTestMethodGradleConfigurationProducer : TestMethodGradleConfiguratio } val contextLocation = context.location ?: return false - val module = context.module ?: return false - if (!module.platform.isJvm) return false + val module = context.module?.asJvmModule() ?: return false val psiMethod = getTestMethod(contextLocation.psiElement) ?: return false 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 a6dac68fb4c..7057f43ffb2 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 @@ -11,21 +11,21 @@ import com.intellij.execution.actions.ConfigurationFromContext import com.intellij.execution.actions.RunConfigurationProducer import com.intellij.execution.configurations.ModuleBasedConfiguration import com.intellij.execution.junit.* +import com.intellij.openapi.module.Module import com.intellij.openapi.project.DumbService +import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.util.Ref import com.intellij.psi.PsiClass import com.intellij.psi.PsiElement import com.intellij.psi.PsiMethod import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.asJava.toLightClass -import org.jetbrains.kotlin.idea.project.TargetPlatformDetector import org.jetbrains.kotlin.idea.util.ProjectRootsUtil import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.psiUtil.getParentOfType -import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform class KotlinJUnitRunConfigurationProducer : RunConfigurationProducer(JUnitConfigurationType.getInstance()) { override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean { @@ -62,7 +62,7 @@ class KotlinJUnitRunConfigurationProducer : RunConfigurationProducer).configurationModule.module val configurationModule = configuration.configurationModule.module - return configurationModule == context.location?.module || configurationModule == predefinedModule + return configurationModule == context.location?.module?.asJvmModule() || configurationModule == predefinedModule } override fun setupConfigurationFromContext( @@ -74,6 +74,7 @@ class KotlinJUnitRunConfigurationProducer : RunConfigurationProducer diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/KotlinJUnitRunConfigurationProducer.kt.181 b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/KotlinJUnitRunConfigurationProducer.kt.181 deleted file mode 100644 index 3ee88706f4f..00000000000 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/KotlinJUnitRunConfigurationProducer.kt.181 +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2010-2018 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.execution.* -import com.intellij.execution.actions.ConfigurationContext -import com.intellij.execution.actions.ConfigurationFromContext -import com.intellij.execution.actions.RunConfigurationProducer -import com.intellij.execution.configurations.ModuleBasedConfiguration -import com.intellij.execution.junit.* -import com.intellij.openapi.project.DumbService -import com.intellij.openapi.roots.ModuleRootManager -import com.intellij.openapi.util.Ref -import com.intellij.psi.PsiClass -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiMethod -import com.intellij.psi.util.PsiTreeUtil -import org.jetbrains.kotlin.asJava.toLightClass -import org.jetbrains.kotlin.idea.project.TargetPlatformDetector -import org.jetbrains.kotlin.idea.util.ProjectRootsUtil -import org.jetbrains.kotlin.idea.util.module -import org.jetbrains.kotlin.psi.KtClass -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.psi.KtFunction -import org.jetbrains.kotlin.psi.KtNamedFunction -import org.jetbrains.kotlin.psi.psiUtil.getParentOfType -import org.jetbrains.kotlin.resolve.TargetPlatform -import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform - -class KotlinJUnitRunConfigurationProducer : RunConfigurationProducer(JUnitConfigurationType.getInstance()) { - override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean { - return other.isProducedBy(JUnitConfigurationProducer::class.java) || other.isProducedBy(PatternConfigurationProducer::class.java) - } - - override fun isConfigurationFromContext( - configuration: JUnitConfiguration, - context: ConfigurationContext - ): Boolean { - if (RunConfigurationProducer.getInstance(PatternConfigurationProducer::class.java).isMultipleElementsSelected(context)) { - return false - } - - val leaf = context.location?.psiElement ?: return false - val methodLocation = getTestMethodLocation(leaf) - val testClass = getTestClass(leaf) - val testObject = configuration.testObject - - if (!testObject.isConfiguredByElement(configuration, testClass, methodLocation?.psiElement, null, null)) { - return false - } - - return settingsMatchTemplate(configuration, context) - } - - // copied from JUnitConfigurationProducer in IDEA - private fun settingsMatchTemplate(configuration: JUnitConfiguration, context: ConfigurationContext): Boolean { - val predefinedConfiguration = context.getOriginalConfiguration(JUnitConfigurationType.getInstance()) - - val vmParameters = (predefinedConfiguration as? CommonJavaRunConfigurationParameters)?.vmParameters - if (vmParameters != null && configuration.vmParameters != vmParameters) return false - - val template = RunManager.getInstance(configuration.project).getConfigurationTemplate(configurationFactory) - val predefinedModule = (template.configuration as ModuleBasedConfiguration<*>).configurationModule.module - val configurationModule = configuration.configurationModule.module - return configurationModule == context.location?.module || configurationModule == predefinedModule - } - - override fun setupConfigurationFromContext( - configuration: JUnitConfiguration, - context: ConfigurationContext, - sourceElement: Ref - ): Boolean { - if (DumbService.getInstance(context.project).isDumb) return false - - val location = context.location ?: return false - val leaf = location.psiElement - - if (!ProjectRootsUtil.isInProjectOrLibSource(leaf)) { - return false - } - - if (leaf.containingFile !is KtFile) { - return false - } - - val ktFile = leaf.containingFile as KtFile - - val targetPlatform = TargetPlatformDetector.getPlatform(ktFile) - if (targetPlatform != JvmPlatform && targetPlatform != TargetPlatform.Common) { - return false - } - - val methodLocation = getTestMethodLocation(leaf) - if (methodLocation != null) { - val originalModule = configuration.configurationModule.module - configuration.beMethodConfiguration(methodLocation) - configuration.restoreOriginalModule(originalModule) - JavaRunConfigurationExtensionManager.getInstance().extendCreatedConfiguration(configuration, location) - fixJdkForCommonModule(ktFile, configuration) - return true - } - - val testClass = getTestClass(leaf) - if (testClass != null) { - val originalModule = configuration.configurationModule.module - configuration.beClassConfiguration(testClass) - configuration.restoreOriginalModule(originalModule) - JavaRunConfigurationExtensionManager.getInstance().extendCreatedConfiguration(configuration, location) - fixJdkForCommonModule(ktFile, configuration) - return true - } - - return false - } - - private fun fixJdkForCommonModule(ktFile: KtFile, configuration: JUnitConfiguration) { - val implModule = ktFile.module?.findJvmImplementationModule() ?: return - val sdk = ModuleRootManager.getInstance(implModule).sdk - if (sdk != null) { - configuration.setModule(implModule) - configuration.isAlternativeJrePathEnabled = true - configuration.alternativeJrePath = sdk.homePath - } - } - - override fun onFirstRun(fromContext: ConfigurationFromContext, context: ConfigurationContext, performRunnable: Runnable) { - val leaf = fromContext.sourceElement - getTestClass(leaf)?.let { testClass -> - val fromContextSubstitute = object : ConfigurationFromContext() { - override fun getConfigurationSettings() = fromContext.configurationSettings - - override fun setConfigurationSettings(configurationSettings: RunnerAndConfigurationSettings) { - fromContext.configurationSettings = configurationSettings - } - - override fun getSourceElement() = testClass - } - // TODO: use TestClassConfigurationProducer when constructor becomes public - return object : AbstractTestClassConfigurationProducer(JUnitConfigurationType.getInstance()){} - .onFirstRun(fromContextSubstitute, context, performRunnable) - } - - super.onFirstRun(fromContext, context, performRunnable) - } - - companion object { - fun getTestClass(leaf: PsiElement): PsiClass? { - val containingFile = leaf.containingFile as? KtFile ?: return null - var ktClass = leaf.getParentOfType(false) - if (!ktClass.isJUnitTestClass()) { - ktClass = getTestClassInFile(containingFile) - } - return ktClass?.toLightClass() - } - - fun getTestMethodLocation(leaf: PsiElement): Location? { - val function = leaf.getParentOfType(false) ?: return null - val owner = PsiTreeUtil.getParentOfType(function, KtFunction::class.java, KtClass::class.java) - - if (owner is KtClass) { - val delegate = owner.toLightClass() ?: return null - val method = delegate.methods.firstOrNull() { it.navigationElement == function } ?: return null - val methodLocation = PsiLocation.fromPsiElement(method) - if (JUnitUtil.isTestMethod(methodLocation, false)) { - return methodLocation - } - } - return null - } - - private fun KtClass?.isJUnitTestClass() = - this?.toLightClass()?.let { JUnitUtil.isTestClass(it, false, true) } ?: false - - private fun getTestClassInFile(ktFile: KtFile) = - ktFile.declarations.filterIsInstance().singleOrNull { it.isJUnitTestClass() } - } -} diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/KotlinRunConfigurationProducer.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/KotlinRunConfigurationProducer.kt index 7c004c37184..d2b20d1dc55 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/KotlinRunConfigurationProducer.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/KotlinRunConfigurationProducer.kt @@ -28,12 +28,10 @@ import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName import org.jetbrains.kotlin.idea.MainFunctionDetector import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny -import org.jetbrains.kotlin.idea.project.TargetPlatformDetector import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.idea.util.ProjectRootsUtil import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getParentOfType -import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode class KotlinRunConfigurationProducer : RunConfigurationProducer(KotlinRunConfigurationType.getInstance()) { @@ -42,7 +40,7 @@ class KotlinRunConfigurationProducer : RunConfigurationProducer): Boolean { val location = context.location ?: return false - val module = location.module ?: return false + val module = location.module?.asJvmModule() ?: return false val container = getEntryPointContainer(location) ?: return false val startClassFQName = getStartClassFqName(container) ?: return false @@ -57,14 +55,7 @@ class KotlinRunConfigurationProducer : RunConfigurationProducer(KotlinRunConfigurationType.getInstance()) { - - override fun setupConfigurationFromContext(configuration: KotlinRunConfiguration, - context: ConfigurationContext, - sourceElement: Ref): Boolean { - val location = context.location ?: return false - val module = location.module ?: return false - val container = getEntryPointContainer(location) - val startClassFQName = getStartClassFqName(container) ?: return false - - configuration.setModule(module) - configuration.runClass = startClassFQName - configuration.setGeneratedName() - - return true - } - - private fun getEntryPointContainer(location: Location<*>?): KtDeclarationContainer? { - if (location == null) return null - if (DumbService.getInstance(location.project).isDumb) return null - - val module = location.module ?: return null - - if (TargetPlatformDetector.getPlatform(module) !is JvmPlatform && module.findJvmImplementationModule() == null) { - return null - } - val locationElement = location.psiElement - - return getEntryPointContainer(locationElement) - } - - override fun isConfigurationFromContext(configuration: KotlinRunConfiguration, context: ConfigurationContext): Boolean { - val startClassFQName = getStartClassFqName(getEntryPointContainer(context.location)) ?: return false - - return configuration.runClass == startClassFQName && - context.module == configuration.configurationModule.module - } - - companion object { - fun getEntryPointContainer(locationElement: PsiElement): KtDeclarationContainer? { - val psiFile = locationElement.containingFile - if (!(psiFile is KtFile && ProjectRootsUtil.isInProjectOrLibSource(psiFile))) return null - - val mainFunctionDetector = - MainFunctionDetector(psiFile.languageVersionSettings) { it.resolveToDescriptorIfAny(BodyResolveMode.FULL) } - - var currentElement = locationElement.declarationContainer(false) - while (currentElement != null) { - var entryPointContainer = currentElement - if (entryPointContainer is KtClass) { - entryPointContainer = entryPointContainer.companionObjects.singleOrNull() - } - if (entryPointContainer != null && mainFunctionDetector.hasMain(entryPointContainer.declarations)) return entryPointContainer - currentElement = (currentElement as PsiElement).declarationContainer(true) - } - - return null - } - - fun getStartClassFqName(container: KtDeclarationContainer?): String? = when(container) { - null -> null - is KtFile -> container.javaFileFacadeFqName.asString() - is KtClassOrObject -> { - if (!container.isValid) { - null - } - else if (container is KtObjectDeclaration && container.isCompanion()) { - val containerClass = container.getParentOfType(true) - containerClass?.toLightClass()?.let { ClassUtil.getJVMClassName(it) } - } - else { - container.toLightClass()?.let { ClassUtil.getJVMClassName(it) } - } - } - else -> throw IllegalArgumentException("Invalid entry-point container: " + (container as PsiElement).text) - } - - private fun PsiElement.declarationContainer(strict: Boolean): KtDeclarationContainer? { - val element = if (strict) - PsiTreeUtil.getParentOfType(this, KtClassOrObject::class.java, KtFile::class.java) - else - PsiTreeUtil.getNonStrictParentOfType(this, KtClassOrObject::class.java, KtFile::class.java) - return element as KtDeclarationContainer? - } - - } -} - -fun Module.findJvmImplementationModule(): Module? { - if (!platform.isCommon) return null - return implementingModules.firstOrNull { it.platform.isJvm } -} diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/jvmMppUtils.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/jvmMppUtils.kt new file mode 100644 index 00000000000..0891fa1b53b --- /dev/null +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/jvmMppUtils.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2018 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.module.Module +import org.jetbrains.kotlin.idea.project.platform +import org.jetbrains.kotlin.platform.impl.isJvm + +fun Module.asJvmModule(): Module? { + if (platform.isJvm) return this + + return null +} + diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/jvmMppUtils.kt.181 b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/jvmMppUtils.kt.181 new file mode 100644 index 00000000000..c0ea875cfc6 --- /dev/null +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/jvmMppUtils.kt.181 @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 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.module.Module +import org.jetbrains.kotlin.idea.caches.project.implementingModules +import org.jetbrains.kotlin.idea.project.platform +import org.jetbrains.kotlin.platform.impl.isCommon +import org.jetbrains.kotlin.platform.impl.isJvm + +fun Module.asJvmModule(): Module? { + if (platform.isJvm) return this + + if (platform.isCommon) { + return implementingModules.firstOrNull { it.platform.isJvm } + } + return null +} +