convert KotlinRunConfigurationProducer to new API, allowing it to coexist with KotlinJUnitRunConfigurationProducer correctly

#KT-2604 Fixed
This commit is contained in:
Dmitry Jemerov
2015-07-02 17:50:22 +02:00
committed by Nikolay Krasko
parent 9d650b6154
commit 49714d0817
2 changed files with 46 additions and 63 deletions
+1 -1
View File
@@ -391,7 +391,7 @@
<configurationType implementation="org.jetbrains.kotlin.idea.run.JetRunConfigurationType"/>
<configurationType implementation="org.jetbrains.kotlin.idea.k2jsrun.K2JSRunConfigurationType"/>
<programRunner implementation="org.jetbrains.kotlin.idea.k2jsrun.K2JSBrowserProgramRunner"/>
<configurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinRunConfigurationProducer"/>
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinRunConfigurationProducer"/>
<codeInsight.lineMarkerProvider language="jet" implementationClass="org.jetbrains.kotlin.idea.highlighter.markers.KotlinLineMarkerProvider"/>
<codeInsight.lineMarkerProvider language="jet" implementationClass="org.jetbrains.kotlin.idea.highlighter.KotlinRecursiveCallLineMarkerProvider"/>
<codeInsight.lineMarkerProvider language="JAVA"
@@ -19,13 +19,14 @@ package org.jetbrains.kotlin.idea.run
import com.intellij.execution.Location
import com.intellij.execution.RunnerAndConfigurationSettings
import com.intellij.execution.actions.ConfigurationContext
import com.intellij.execution.actions.RunConfigurationProducer
import com.intellij.execution.junit.RuntimeConfigurationProducer
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.DumbService
import com.intellij.openapi.util.Comparing
import com.intellij.openapi.util.Ref
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.PsiElement
import com.intellij.psi.impl.ElementBase
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.util.NotNullFunction
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
@@ -36,46 +37,38 @@ import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
public class KotlinRunConfigurationProducer : RuntimeConfigurationProducer(JetRunConfigurationType.getInstance()), Cloneable {
override fun clone(): KotlinRunConfigurationProducer {
return super<RuntimeConfigurationProducer>.clone() as KotlinRunConfigurationProducer
public class KotlinRunConfigurationProducer : RunConfigurationProducer<JetRunConfiguration>(JetRunConfigurationType.getInstance()) {
override fun setupConfigurationFromContext(configuration: JetRunConfiguration,
context: ConfigurationContext,
sourceElement: Ref<PsiElement>): Boolean {
val location = context.getLocation() ?: return false
val module = context.getModule() ?: return false
val container = getEntryPointContainer(location)
val startClassFQName = getStartClassFqName(container) ?: return false
setupConfigurationByQName(module, configuration, startClassFQName)
return true
}
private var mySourceElement: PsiElement? = null
override fun getSourceElement(): PsiElement? {
return mySourceElement
}
override fun createConfigurationByElement(location: Location<*>, configurationContext: ConfigurationContext): RunnerAndConfigurationSettings? {
val container = getEntryPointContainer(location) ?: return null
mySourceElement = container as PsiElement?
val startClassFQName = getStartClassFqName(container)
if (startClassFQName == null) return null
val module = location.getModule()
assert(module != null)
return createConfigurationByQName(module, configurationContext, startClassFQName)
}
private fun getStartClassFqName(container: JetDeclarationContainer?): FqName? {
if (container == null) return null
if (container is JetFile) return PackageClassUtils.getPackageClassFqName((container as JetFile?).getPackageFqName())
if (container is JetClassOrObject) {
private fun getStartClassFqName(container: JetDeclarationContainer?): FqName? = when(container) {
null -> null
is JetFile -> PackageClassUtils.getPackageClassFqName(container.getPackageFqName())
is JetClassOrObject -> {
if (container is JetObjectDeclaration && container.isCompanion()) {
val containerClass = PsiTreeUtil.getParentOfType<JetClass>(container, javaClass<JetClass>())
return containerClass?.getFqName()
val containerClass = container.getParentOfType<JetClass>(true)
containerClass?.getFqName()
} else {
container.getFqName()
}
return container?.getFqName()
}
throw IllegalArgumentException("Invalid entry-point container: " + (container as PsiElement?).getText())
else -> throw IllegalArgumentException("Invalid entry-point container: " + (container as PsiElement).getText())
}
private fun getEntryPointContainer(location: Location<*>): JetDeclarationContainer? {
private fun getEntryPointContainer(location: Location<*>?): JetDeclarationContainer? {
if (location == null) return null
if (DumbService.getInstance(location.getProject()).isDumb()) return null
val module = location.getModule() ?: return null
@@ -88,51 +81,41 @@ public class KotlinRunConfigurationProducer : RuntimeConfigurationProducer(JetRu
if (!(psiFile is JetFile && ProjectRootsUtil.isInProjectOrLibSource(psiFile))) return null
val resolutionFacade = psiFile.getResolutionFacade()
val mainFunctionDetector = MainFunctionDetector(object : NotNullFunction<JetNamedFunction, FunctionDescriptor> {
override fun `fun`(function: JetNamedFunction): FunctionDescriptor {
return resolutionFacade.resolveToDescriptor(function) as FunctionDescriptor
}
})
val mainFunctionDetector = MainFunctionDetector { resolutionFacade.resolveToDescriptor(it) as FunctionDescriptor }
var currentElement = PsiTreeUtil.getNonStrictParentOfType<PsiElement>(locationElement, javaClass<JetClassOrObject>(), javaClass<JetFile>()) as JetDeclarationContainer
var currentElement = locationElement.declarationContainer(false)
while (currentElement != null) {
var entryPointContainer = currentElement
if (entryPointContainer is JetClass) {
entryPointContainer = entryPointContainer.getCompanionObjects().singleOrNull() as JetDeclarationContainer
entryPointContainer = entryPointContainer.getCompanionObjects().singleOrNull()
}
if (entryPointContainer != null && mainFunctionDetector.hasMain(entryPointContainer.getDeclarations())) return entryPointContainer
currentElement = PsiTreeUtil.getParentOfType<PsiElement>(currentElement as PsiElement?, javaClass<JetClassOrObject>(), javaClass<JetFile>()) as JetDeclarationContainer
currentElement = (currentElement as PsiElement).declarationContainer(true)
}
return null
}
private fun createConfigurationByQName(module: Module, context: ConfigurationContext, fqName: FqName): RunnerAndConfigurationSettings {
val settings = cloneTemplateConfiguration(module.getProject(), context)
val configuration = settings.getConfiguration() as JetRunConfiguration
private fun PsiElement.declarationContainer(strict: Boolean): JetDeclarationContainer? {
val element = if (strict)
PsiTreeUtil.getParentOfType(this, javaClass<JetClassOrObject>(), javaClass<JetFile>())
else
PsiTreeUtil.getNonStrictParentOfType(this, javaClass<JetClassOrObject>(), javaClass<JetFile>())
return element as JetDeclarationContainer?
}
private fun setupConfigurationByQName(module: Module,
configuration: JetRunConfiguration,
fqName: FqName) {
configuration.setModule(module)
configuration.setName(StringUtil.trimEnd(fqName.asString(), "." + PackageClassUtils.getPackageClassName(fqName)))
configuration.setRunClass(fqName.asString())
return settings
}
override fun findExistingByElement(location: Location<*>?, existingConfigurations: List<RunnerAndConfigurationSettings>, context: ConfigurationContext?): RunnerAndConfigurationSettings? {
val startClassFQName = getStartClassFqName(getEntryPointContainer(location)) ?: return null
override fun isConfigurationFromContext(configuration: JetRunConfiguration, context: ConfigurationContext): Boolean {
val startClassFQName = getStartClassFqName(getEntryPointContainer(context.getLocation())) ?: return false
for (existingConfiguration in existingConfigurations) {
if (existingConfiguration.getType() is JetRunConfigurationType) {
val jetConfiguration = existingConfiguration.getConfiguration() as JetRunConfiguration
if (Comparing.equal(jetConfiguration.getRunClass(), startClassFQName.asString())) {
if (Comparing.equal<Module>(location!!.getModule(), jetConfiguration.getConfigurationModule().getModule())) {
return existingConfiguration
}
}
}
}
return null
}
override fun compareTo(o: Any?): Int {
return RuntimeConfigurationProducer.PREFERED
return configuration.getRunClass() == startClassFQName.asString() &&
context.getModule() == configuration.getConfigurationModule().getModule()
}
}