Run/test line markers: aggregate results across implementing modules

This commit is contained in:
Pavel V. Talanov
2018-07-11 19:23:28 +02:00
parent 0fff8ebf71
commit 01f1917d2a
2 changed files with 48 additions and 25 deletions
@@ -21,10 +21,14 @@ import com.intellij.execution.lineMarker.ExecutorAction
import com.intellij.execution.lineMarker.RunLineMarkerContributor
import com.intellij.icons.AllIcons
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.TargetPlatformKind
import org.jetbrains.kotlin.idea.MainFunctionDetector
import org.jetbrains.kotlin.idea.caches.project.implementingModules
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.js.KotlinJSRunConfigurationDataProvider
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.idea.project.targetPlatform
import org.jetbrains.kotlin.idea.util.module
import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.resolve.TargetPlatform
@@ -41,25 +45,34 @@ class KotlinRunLineMarkerContributor : RunLineMarkerContributor() {
}
if (detector.isMain(function)) {
val platform = TargetPlatformDetector.getPlatform(function.containingKtFile)
val isAvailable = when (platform) {
is JvmPlatform -> true
is JsPlatform, is TargetPlatform.Common -> {
RunConfigurationProducer
.getProducers(function.project)
.asSequence()
.filterIsInstance<KotlinJSRunConfigurationDataProvider<*>>()
.filter { !it.isForTests }
.mapNotNull { it.getConfigurationData(function) }
.firstOrNull() != null
}
else -> false
}
if (!isAvailable) return null
val platform = function.containingKtFile.module?.targetPlatform ?: return null
if (!platform.acceptsAsEntryPoint(function)) return null
return RunLineMarkerContributor.Info(AllIcons.RunConfigurations.TestState.Run, null, ExecutorAction.getActions(0))
}
return null
}
private fun TargetPlatformKind<*>.acceptsAsEntryPoint(function: KtNamedFunction): Boolean {
return when (this) {
is TargetPlatformKind.Common -> {
val module = function.containingKtFile.module ?: return false
return module.implementingModules.any { implementingModule ->
implementingModule.targetPlatform?.takeIf { it !is TargetPlatformKind.Common }?.acceptsAsEntryPoint(function) ?: false
}
}
is TargetPlatformKind.Jvm -> true
is TargetPlatformKind.JavaScript -> {
RunConfigurationProducer
.getProducers(function.project)
.asSequence()
.filterIsInstance<KotlinJSRunConfigurationDataProvider<*>>()
.filter { !it.isForTests }
.mapNotNull { it.getConfigurationData(function) }
.firstOrNull() != null
}
}
}
}
@@ -30,14 +30,15 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.asJava.toLightMethods
import org.jetbrains.kotlin.config.TargetPlatformKind
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.js.KotlinJSRunConfigurationDataProvider
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.idea.project.targetPlatform
import org.jetbrains.kotlin.idea.util.projectStructure.module
import org.jetbrains.kotlin.idea.util.string.joinWithEscape
import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtNamedDeclaration
@@ -45,8 +46,6 @@ import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
import org.jetbrains.kotlin.resolve.TargetPlatform.Common
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import javax.swing.Icon
class KotlinTestRunLineMarkerContributor : RunLineMarkerContributor() {
@@ -151,12 +150,23 @@ class KotlinTestRunLineMarkerContributor : RunLineMarkerContributor() {
// To prevent IDEA failing on red code
val descriptor = declaration.resolveToDescriptorIfAny() ?: return null
val platform = TargetPlatformDetector.getPlatform(declaration.containingKtFile)
val icon = when (platform) {
is JvmPlatform -> getJavaTestIcon(declaration)
is JsPlatform, is Common -> getJavaScriptTestIcon(declaration, descriptor)
else -> return null
} ?: return null
val icon = getTestIcon(declaration, descriptor) ?: return null
return RunLineMarkerContributor.Info(icon, { "Run Test" }, ExecutorAction.getActions())
}
private fun getTestIcon(declaration: KtNamedDeclaration, descriptor: DeclarationDescriptor): Icon? {
val module = declaration.module ?: return null
val targetPlatformKind = module.targetPlatform ?: return null
return when (targetPlatformKind) {
is TargetPlatformKind.JavaScript -> getJavaScriptTestIcon(declaration, descriptor)
is TargetPlatformKind.Jvm -> getJavaTestIcon(declaration)
is TargetPlatformKind.Common -> {
val icons = listOfNotNull(getJavaScriptTestIcon(declaration, descriptor), getJavaTestIcon(declaration))
when (icons.size) {
0 -> null
else -> icons.distinct().singleOrNull() ?: AllIcons.RunConfigurations.TestState.Run
}
}
}
}
}