Test Support: KT-22306
Do not show run markers in JS modules when no relevant run configurations are available #KT-22306 Fixed
This commit is contained in:
+10
@@ -49,6 +49,16 @@ public class ForTestCompileRuntime {
|
||||
return assertExists(new File("dist/kotlinc/lib/kotlin-test.jar"));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static File kotlinTestJUnitJarForTests() {
|
||||
return assertExists(new File("dist/kotlinc/lib/kotlin-test-junit.jar"));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static File kotlinTestJsJarForTests() {
|
||||
return assertExists(new File("dist/kotlinc/lib/kotlin-test-js.jar"));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static File reflectJarForTests() {
|
||||
return assertExists(new File("dist/kotlinc/lib/kotlin-reflect.jar"));
|
||||
|
||||
@@ -16,14 +16,19 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.highlighter
|
||||
|
||||
import com.intellij.execution.actions.RunConfigurationProducer
|
||||
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.idea.MainFunctionDetector
|
||||
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.js.resolve.JsPlatform
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
||||
|
||||
class KotlinRunLineMarkerContributor : RunLineMarkerContributor() {
|
||||
override fun getInfo(element: PsiElement): Info? {
|
||||
@@ -36,6 +41,22 @@ 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
|
||||
|
||||
return RunLineMarkerContributor.Info(AllIcons.RunConfigurations.TestState.Run, null, ExecutorAction.getActions(0))
|
||||
}
|
||||
|
||||
|
||||
+10
-6
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.highlighter
|
||||
|
||||
import com.intellij.codeInsight.TestFrameworks
|
||||
import com.intellij.execution.TestStateStorage
|
||||
import com.intellij.execution.actions.RunConfigurationProducer
|
||||
import com.intellij.execution.lineMarker.ExecutorAction
|
||||
import com.intellij.execution.lineMarker.RunLineMarkerContributor
|
||||
import com.intellij.execution.testframework.TestIconMapper
|
||||
@@ -33,10 +34,8 @@ 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.jsOrJsImpl
|
||||
import org.jetbrains.kotlin.idea.js.jsTestOutputFilePath
|
||||
import org.jetbrains.kotlin.idea.js.KotlinJSRunConfigurationDataProvider
|
||||
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
|
||||
import org.jetbrains.kotlin.idea.util.module
|
||||
import org.jetbrains.kotlin.idea.util.string.joinWithEscape
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatform
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -110,12 +109,17 @@ class KotlinTestRunLineMarkerContributor : RunLineMarkerContributor() {
|
||||
private fun getJavaScriptTestIcon(declaration: KtNamedDeclaration, descriptor: DeclarationDescriptor): Icon? {
|
||||
if (!descriptor.isTest()) return null
|
||||
|
||||
val module = declaration.module?.jsOrJsImpl() ?: return null
|
||||
val testFilePath = module.jsTestOutputFilePath ?: return null
|
||||
val runConfigData = RunConfigurationProducer
|
||||
.getProducers(declaration.project)
|
||||
.asSequence()
|
||||
.filterIsInstance<KotlinJSRunConfigurationDataProvider<*>>()
|
||||
.filter { it.isForTests }
|
||||
.mapNotNull { it.getConfigurationData(declaration) }
|
||||
.firstOrNull() ?: return null
|
||||
|
||||
val locations = ArrayList<String>()
|
||||
|
||||
locations += FileUtil.toSystemDependentName(testFilePath)
|
||||
locations += FileUtil.toSystemDependentName(runConfigData.jsOutputFilePath)
|
||||
|
||||
val klass = when (declaration) {
|
||||
is KtClassOrObject -> declaration
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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.js
|
||||
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.psi.PsiElement
|
||||
|
||||
interface KotlinJSRunConfigurationData {
|
||||
val element: PsiElement
|
||||
val module: Module
|
||||
val jsOutputFilePath: String
|
||||
}
|
||||
|
||||
interface KotlinJSRunConfigurationDataProvider<out T : KotlinJSRunConfigurationData> {
|
||||
val isForTests: Boolean
|
||||
fun getConfigurationData(element: PsiElement): T?
|
||||
}
|
||||
+1
-4
@@ -1,6 +1,3 @@
|
||||
// !CHECK_HIGHLIGHTING
|
||||
|
||||
package kotlin.test
|
||||
|
||||
annotation class Test
|
||||
annotation class Ignore
|
||||
package test
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
import kotlin.test.*
|
||||
|
||||
class SimpleTest {
|
||||
@Test fun testFoo() {
|
||||
// Will run
|
||||
}
|
||||
|
||||
@Ignore fun testFooWrong() {
|
||||
// Will not run
|
||||
}
|
||||
}
|
||||
|
||||
@Ignore
|
||||
class TestTest {
|
||||
@Test fun emptyTest() {
|
||||
// Will not run
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -11,8 +11,8 @@ class <lineMarker descr="Run Test">SimpleTest</lineMarker> {
|
||||
}
|
||||
|
||||
@Ignore
|
||||
class TestTest {
|
||||
@Test fun emptyTest() {
|
||||
class <lineMarker descr="Run Test">TestTest</lineMarker> {
|
||||
@Test fun <lineMarker descr="Run Test">emptyTest</lineMarker>() {
|
||||
// Will not run
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,10 @@ fun AbstractMultiModuleTest.setupMppProjectFromDirStructure(testRoot: File) {
|
||||
})
|
||||
}
|
||||
is CoroutinesDependency -> module.enableCoroutines()
|
||||
is KotlinTestDependency -> when (id.platform) {
|
||||
is TargetPlatformKind.Jvm -> module.addLibrary(ForTestCompileRuntime.kotlinTestJUnitJarForTests())
|
||||
is TargetPlatformKind.JavaScript -> module.addLibrary(ForTestCompileRuntime.kotlinTestJsJarForTests(), kind = JSLibraryKind)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -142,6 +146,7 @@ private fun parseDependency(it: String): Dependency {
|
||||
dependencyString.equals("stdlib", ignoreCase = true) -> StdlibDependency
|
||||
dependencyString.equals("fulljdk", ignoreCase = true) -> FullJdkDependency
|
||||
dependencyString.equals("coroutines", ignoreCase = true) -> CoroutinesDependency
|
||||
dependencyString.equals("kotlin-test", ignoreCase = true) -> KotlinTestDependency
|
||||
else -> ModuleDependency(parseModuleId(dependencyString.split("-")))
|
||||
}
|
||||
}
|
||||
@@ -190,4 +195,5 @@ private sealed class Dependency
|
||||
private class ModuleDependency(val moduleId: ModuleId) : Dependency()
|
||||
private object StdlibDependency : Dependency()
|
||||
private object FullJdkDependency : Dependency()
|
||||
private object CoroutinesDependency : Dependency()
|
||||
private object CoroutinesDependency : Dependency()
|
||||
private object KotlinTestDependency : Dependency()
|
||||
@@ -55,6 +55,10 @@ fun AbstractMultiModuleTest.setupMppProjectFromDirStructure(testRoot: File) {
|
||||
})
|
||||
}
|
||||
is CoroutinesDependency -> module.enableCoroutines()
|
||||
is KotlinTestDependency -> when (id.platform) {
|
||||
is TargetPlatformKind.Jvm -> module.addLibrary(ForTestCompileRuntime.kotlinTestJUnitJarForTests())
|
||||
is TargetPlatformKind.JavaScript -> module.addLibrary(ForTestCompileRuntime.kotlinTestJsJarForTests(), kind = JSLibraryKind)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -142,6 +146,7 @@ private fun parseDependency(it: String): Dependency {
|
||||
dependencyString.equals("stdlib", ignoreCase = true) -> StdlibDependency
|
||||
dependencyString.equals("fulljdk", ignoreCase = true) -> FullJdkDependency
|
||||
dependencyString.equals("coroutines", ignoreCase = true) -> CoroutinesDependency
|
||||
dependencyString.equals("kotlin-test", ignoreCase = true) -> KotlinTestDependency
|
||||
else -> ModuleDependency(parseModuleId(dependencyString.split("-")))
|
||||
}
|
||||
}
|
||||
@@ -190,4 +195,5 @@ private sealed class Dependency
|
||||
private class ModuleDependency(val moduleId: ModuleId) : Dependency()
|
||||
private object StdlibDependency : Dependency()
|
||||
private object FullJdkDependency : Dependency()
|
||||
private object CoroutinesDependency : Dependency()
|
||||
private object CoroutinesDependency : Dependency()
|
||||
private object KotlinTestDependency : Dependency()
|
||||
+34
-24
@@ -7,14 +7,16 @@ package org.jetbrains.kotlin.idea.nodejs.cli
|
||||
|
||||
import com.intellij.execution.actions.ConfigurationContext
|
||||
import com.intellij.execution.actions.RunConfigurationProducer
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.util.Ref
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.jetbrains.nodejs.run.NodeJsRunConfiguration
|
||||
import com.jetbrains.nodejs.run.NodeJsRunConfigurationType
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.MainFunctionDetector
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.js.KotlinJSRunConfigurationData
|
||||
import org.jetbrains.kotlin.idea.js.KotlinJSRunConfigurationDataProvider
|
||||
import org.jetbrains.kotlin.idea.js.jsOrJsImpl
|
||||
import org.jetbrains.kotlin.idea.js.jsProductionOutputFilePath
|
||||
import org.jetbrains.kotlin.idea.nodejs.TestElementPath
|
||||
@@ -25,40 +27,51 @@ import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
|
||||
class NodeJsConfigData(
|
||||
override val element: PsiElement,
|
||||
override val module: Module,
|
||||
override val jsOutputFilePath: String
|
||||
) : KotlinJSRunConfigurationData
|
||||
|
||||
private class KotlinNodeJsRunConfigurationProducer :
|
||||
RunConfigurationProducer<NodeJsRunConfiguration>(NodeJsRunConfigurationType.getInstance()) {
|
||||
RunConfigurationProducer<NodeJsRunConfiguration>(NodeJsRunConfigurationType.getInstance()),
|
||||
KotlinJSRunConfigurationDataProvider<NodeJsConfigData> {
|
||||
private val ConfigurationContext?.isAcceptable: Boolean
|
||||
get() {
|
||||
val original = this?.getOriginalConfiguration(null)
|
||||
return original == null || original is NodeJsRunConfiguration
|
||||
}
|
||||
|
||||
override val isForTests: Boolean
|
||||
get() = false
|
||||
|
||||
private fun getConfigurationData(element: PsiElement, context: ConfigurationContext?): NodeJsConfigData? {
|
||||
if (context != null && !context.isAcceptable) return null
|
||||
val jsModule = element.module?.jsOrJsImpl() ?: return null
|
||||
val jsFilePath = jsModule.jsProductionOutputFilePath ?: return null
|
||||
val declaration = element.getNonStrictParentOfType<KtNamedDeclaration>()
|
||||
if (declaration is KtNamedFunction) {
|
||||
val detector = MainFunctionDetector { it.resolveToDescriptorIfAny() }
|
||||
if (!detector.isMain(declaration, false)) return null
|
||||
} else if (!TestElementPath.isModuleAssociatedDir(element, jsModule)) return null
|
||||
return NodeJsConfigData(element, jsModule, jsFilePath)
|
||||
}
|
||||
|
||||
override fun getConfigurationData(element: PsiElement) = getConfigurationData(element, null)
|
||||
|
||||
override fun setupConfigurationFromContext(
|
||||
configuration: NodeJsRunConfiguration,
|
||||
context: ConfigurationContext,
|
||||
sourceElement: Ref<PsiElement>
|
||||
): Boolean {
|
||||
if (!context.isAcceptable) return false
|
||||
|
||||
val psiElement = sourceElement.get() ?: return false
|
||||
val psiFile = psiElement.containingFile ?: return false
|
||||
val jsModule = psiFile.module?.jsOrJsImpl() ?: return false
|
||||
val project = psiFile.project
|
||||
|
||||
val declaration = psiElement.getNonStrictParentOfType<KtNamedDeclaration>()
|
||||
if (declaration is KtNamedFunction) {
|
||||
val detector = MainFunctionDetector { it.resolveToDescriptorIfAny() }
|
||||
if (!detector.isMain(declaration, false)) return false
|
||||
}
|
||||
else if (!TestElementPath.isModuleAssociatedDir(psiElement, jsModule)) return false
|
||||
|
||||
val jsFilePath = jsModule.jsProductionOutputFilePath ?: return false
|
||||
val configData = getConfigurationData(psiElement, context) ?: return false
|
||||
|
||||
if (configuration.workingDirectory.isNullOrBlank()) {
|
||||
configuration.workingDirectory = FileUtil.toSystemDependentName(project.baseDir.path)
|
||||
configuration.workingDirectory = FileUtil.toSystemDependentName(psiElement.project.baseDir.path)
|
||||
}
|
||||
configuration.inputPath = jsFilePath
|
||||
configuration.envs = jsModule.getNodeJsEnvironmentVars(false).envs
|
||||
configuration.inputPath = configData.jsOutputFilePath
|
||||
configuration.envs = configData.module.getNodeJsEnvironmentVars(false).envs
|
||||
configuration.setGeneratedName()
|
||||
configuration.addBuildTask()
|
||||
|
||||
@@ -66,11 +79,8 @@ private class KotlinNodeJsRunConfigurationProducer :
|
||||
}
|
||||
|
||||
override fun isConfigurationFromContext(configuration: NodeJsRunConfiguration, context: ConfigurationContext): Boolean {
|
||||
if (!context.isAcceptable) return false
|
||||
|
||||
val contextPsi = context.psiLocation ?: return false
|
||||
val jsModule = contextPsi.module?.jsOrJsImpl() ?: return false
|
||||
val jsFilePath = jsModule.jsProductionOutputFilePath ?: return false
|
||||
return configuration.inputPath == jsFilePath
|
||||
val configData = getConfigurationData(contextPsi, context) ?: return false
|
||||
return configuration.inputPath == configData.jsOutputFilePath
|
||||
}
|
||||
}
|
||||
+53
-25
@@ -10,35 +10,49 @@ import com.intellij.javascript.jest.JestRunConfiguration
|
||||
import com.intellij.javascript.jest.JestRunConfigurationProducer
|
||||
import com.intellij.javascript.jest.JestRunSettings
|
||||
import com.intellij.javascript.jest.scope.JestScopeKind
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.util.Ref
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.util.PsiUtilCore
|
||||
import org.jetbrains.kotlin.idea.js.KotlinJSRunConfigurationData
|
||||
import org.jetbrains.kotlin.idea.js.jsOrJsImpl
|
||||
import org.jetbrains.kotlin.idea.js.jsTestOutputFilePath
|
||||
import org.jetbrains.kotlin.idea.js.KotlinJSRunConfigurationDataProvider
|
||||
import org.jetbrains.kotlin.idea.nodejs.TestElementInfo
|
||||
import org.jetbrains.kotlin.idea.nodejs.TestElementPath
|
||||
import org.jetbrains.kotlin.idea.nodejs.getNodeJsEnvironmentVars
|
||||
import org.jetbrains.kotlin.idea.run.addBuildTask
|
||||
import org.jetbrains.kotlin.idea.util.projectStructure.module
|
||||
|
||||
private typealias JestTestElementInfo = TestElementInfo<JestRunSettings>
|
||||
typealias JestTestElementInfo = TestElementInfo<JestRunSettings>
|
||||
|
||||
class JestConfigData(
|
||||
override val element: PsiElement,
|
||||
override val module: Module,
|
||||
override val jsOutputFilePath: String,
|
||||
val testElementPath: TestElementPath
|
||||
) : KotlinJSRunConfigurationData
|
||||
|
||||
class KotlinJestRunConfigurationProducer :
|
||||
JestRunConfigurationProducer(),
|
||||
KotlinJSRunConfigurationDataProvider<JestConfigData> {
|
||||
private fun createTestElementRunInfo(
|
||||
configData: JestConfigData,
|
||||
originalSettings: JestRunSettings
|
||||
): JestTestElementInfo {
|
||||
val project = configData.module.project
|
||||
|
||||
class KotlinJestRunConfigurationProducer : JestRunConfigurationProducer() {
|
||||
private fun createTestElementRunInfo(element: PsiElement, originalSettings: JestRunSettings): JestTestElementInfo? {
|
||||
val module = element.module?.jsOrJsImpl() ?: return null
|
||||
val project = module.project
|
||||
val testFilePath = module.jsTestOutputFilePath ?: return null
|
||||
val settings = if (originalSettings.workingDirSystemDependentPath.isBlank()) {
|
||||
val workingDir = FileUtil.toSystemDependentName(project.baseDir.path)
|
||||
originalSettings.toBuilder().setWorkingDir(workingDir).build()
|
||||
} else originalSettings
|
||||
val testElementPath = TestElementPath.forElement(element, module) ?: return null
|
||||
|
||||
val builder = settings.toBuilder()
|
||||
builder.setTestFilePath(testFilePath)
|
||||
when (testElementPath) {
|
||||
builder.setTestFilePath(configData.jsOutputFilePath)
|
||||
when (configData.testElementPath) {
|
||||
is TestElementPath.BySuite -> {
|
||||
val (suiteNames, testName) = testElementPath
|
||||
val (suiteNames, testName) = configData.testElementPath
|
||||
if (testName == null) {
|
||||
builder.setScopeKind(JestScopeKind.SUITE)
|
||||
builder.setTestNames(suiteNames)
|
||||
@@ -52,14 +66,38 @@ class KotlinJestRunConfigurationProducer : JestRunConfigurationProducer() {
|
||||
builder.setScopeKind(JestScopeKind.TEST_FILE)
|
||||
}
|
||||
}
|
||||
builder.setEnvData(module.getNodeJsEnvironmentVars(true))
|
||||
builder.setEnvData(configData.module.getNodeJsEnvironmentVars(true))
|
||||
|
||||
return JestTestElementInfo(builder.build(), element)
|
||||
return JestTestElementInfo(builder.build(), configData.element)
|
||||
}
|
||||
|
||||
override val isForTests: Boolean
|
||||
get() = true
|
||||
|
||||
override fun getConfigurationData(element: PsiElement): JestConfigData? {
|
||||
val module = element.module
|
||||
val jsModule = module?.jsOrJsImpl() ?: return null
|
||||
|
||||
val file = if (jsModule != module) {
|
||||
jsModule.moduleFile
|
||||
} else {
|
||||
PsiUtilCore.getVirtualFile(element)
|
||||
} ?: return null
|
||||
|
||||
val project = module.project
|
||||
|
||||
if (!isTestRunnerPackageAvailableFor(project, file)) return null
|
||||
|
||||
val testFilePath = module.jsTestOutputFilePath ?: return null
|
||||
val testElementPath = TestElementPath.forElement(element, module) ?: return null
|
||||
|
||||
return JestConfigData(element, jsModule, testFilePath, testElementPath)
|
||||
}
|
||||
|
||||
override fun isConfigurationFromCompatibleContext(configuration: JestRunConfiguration, context: ConfigurationContext): Boolean {
|
||||
val element = context.psiLocation ?: return false
|
||||
val (thisRunSettings, _) = createTestElementRunInfo(element, configuration.runSettings) ?: return false
|
||||
val configData = getConfigurationData(element) ?: return false
|
||||
val (thisRunSettings, _) = createTestElementRunInfo(configData, configuration.runSettings)
|
||||
val thatRunSettings = configuration.runSettings
|
||||
|
||||
if (thisRunSettings.configFileSystemDependentPath != thatRunSettings.configFileSystemDependentPath) return false
|
||||
@@ -80,18 +118,8 @@ class KotlinJestRunConfigurationProducer : JestRunConfigurationProducer() {
|
||||
sourceElement: Ref<PsiElement>
|
||||
): Boolean {
|
||||
val element = context.psiLocation ?: return false
|
||||
val module = element.module
|
||||
val jsModule = module?.jsOrJsImpl() ?: return false
|
||||
val file = if (jsModule != module) {
|
||||
jsModule.moduleFile
|
||||
} else {
|
||||
PsiUtilCore.getVirtualFile(element)
|
||||
} ?: return false
|
||||
val project = module.project
|
||||
|
||||
if (!isTestRunnerPackageAvailableFor(project, file)) return false
|
||||
|
||||
val (runSettings, enclosingTestElement) = createTestElementRunInfo(element, configuration.runSettings) ?: return false
|
||||
val configData = getConfigurationData(element) ?: return false
|
||||
val (runSettings, enclosingTestElement) = createTestElementRunInfo(configData, configuration.runSettings)
|
||||
configuration.runSettings = runSettings
|
||||
sourceElement.set(enclosingTestElement)
|
||||
configuration.setGeneratedName()
|
||||
|
||||
+78
-63
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.nodejs.mocha
|
||||
|
||||
import com.intellij.execution.RunManager
|
||||
import com.intellij.execution.actions.ConfigurationContext
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Ref
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
@@ -30,6 +31,8 @@ import com.intellij.util.SmartList
|
||||
import com.intellij.util.containers.SmartHashSet
|
||||
import com.jetbrains.nodejs.mocha.MochaUtil
|
||||
import com.jetbrains.nodejs.mocha.execution.*
|
||||
import org.jetbrains.kotlin.idea.js.KotlinJSRunConfigurationData
|
||||
import org.jetbrains.kotlin.idea.js.KotlinJSRunConfigurationDataProvider
|
||||
import org.jetbrains.kotlin.idea.js.jsOrJsImpl
|
||||
import org.jetbrains.kotlin.idea.js.jsTestOutputFilePath
|
||||
import org.jetbrains.kotlin.idea.nodejs.TestElementInfo
|
||||
@@ -40,79 +43,52 @@ import org.jetbrains.kotlin.idea.util.projectStructure.module
|
||||
|
||||
private typealias MochaTestElementInfo = TestElementInfo<MochaRunSettings>
|
||||
|
||||
class KotlinMochaRunConfigurationProducer : MochaRunConfigurationProducer() {
|
||||
class MochaConfigData(
|
||||
override val element: PsiElement,
|
||||
override val module: Module,
|
||||
override val jsOutputFilePath: String,
|
||||
val testElementPath: TestElementPath
|
||||
) : KotlinJSRunConfigurationData
|
||||
|
||||
class KotlinMochaRunConfigurationProducer : MochaRunConfigurationProducer(), KotlinJSRunConfigurationDataProvider<MochaConfigData> {
|
||||
// Copied from MochaRunConfigurationProducer.collectMochaTestRoots()
|
||||
private fun collectMochaTestRoots(project: Project): List<VirtualFile> {
|
||||
return RunManager
|
||||
.getInstance(project)
|
||||
.getConfigurationsList(MochaConfigurationType.getInstance())
|
||||
.filterIsInstance<MochaRunConfiguration>()
|
||||
.mapNotNullTo(SmartList<VirtualFile>()) { configuration ->
|
||||
val settings = configuration.runSettings
|
||||
val path = when (settings.testKind) {
|
||||
MochaTestKind.DIRECTORY -> settings.testDirPath
|
||||
MochaTestKind.TEST_FILE,
|
||||
MochaTestKind.SUITE,
|
||||
MochaTestKind.TEST -> settings.testFilePath
|
||||
else -> null
|
||||
}
|
||||
if (path.isNullOrBlank()) return@mapNotNullTo null
|
||||
LocalFileSystem.getInstance().findFileByPath(path!!)
|
||||
.getInstance(project)
|
||||
.getConfigurationsList(MochaConfigurationType.getInstance())
|
||||
.filterIsInstance<MochaRunConfiguration>()
|
||||
.mapNotNullTo(SmartList<VirtualFile>()) { configuration ->
|
||||
val settings = configuration.runSettings
|
||||
val path = when (settings.testKind) {
|
||||
MochaTestKind.DIRECTORY -> settings.testDirPath
|
||||
MochaTestKind.TEST_FILE,
|
||||
MochaTestKind.SUITE,
|
||||
MochaTestKind.TEST -> settings.testFilePath
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
// Copied from MochaRunConfigurationProducer.isActiveFor()
|
||||
private fun isActiveFor(element: PsiElement, context: ConfigurationContext): Boolean {
|
||||
val module = element.module
|
||||
val jsModule = module?.jsOrJsImpl() ?: return false
|
||||
val file = if (jsModule != module) {
|
||||
jsModule.moduleFile
|
||||
}
|
||||
else {
|
||||
PsiUtilCore.getVirtualFile(element)
|
||||
} ?: return false
|
||||
val project = module.project
|
||||
|
||||
if (isTestRunnerPackageAvailableFor(project, file)) return true
|
||||
|
||||
if (context.getOriginalConfiguration(MochaConfigurationType.getInstance()) is MochaRunConfiguration) return true
|
||||
|
||||
val roots = collectMochaTestRoots(project)
|
||||
if (roots.isEmpty()) return false
|
||||
|
||||
val dirs = SmartHashSet<VirtualFile>()
|
||||
for (root in roots) {
|
||||
if (root.isDirectory) {
|
||||
dirs.add(root)
|
||||
if (path.isNullOrBlank()) return@mapNotNullTo null
|
||||
LocalFileSystem.getInstance().findFileByPath(path!!)
|
||||
}
|
||||
else if (root == file) return true
|
||||
}
|
||||
return VfsUtilCore.isUnder(file, dirs)
|
||||
}
|
||||
|
||||
private fun createTestElementRunInfo(element: PsiElement, originalSettings: MochaRunSettings): MochaTestElementInfo? {
|
||||
val module = element.module?.jsOrJsImpl() ?: return null
|
||||
val project = module.project
|
||||
val testFilePath = module.jsTestOutputFilePath ?: return null
|
||||
private fun createTestElementRunInfo(configData: MochaConfigData, originalSettings: MochaRunSettings): MochaTestElementInfo {
|
||||
val project = configData.module.project
|
||||
val settings = if (originalSettings.workingDir.isBlank()) {
|
||||
val workingDir = FileUtil.toSystemDependentName(project.baseDir.path)
|
||||
originalSettings.builder().setWorkingDir(workingDir).build()
|
||||
}
|
||||
else originalSettings
|
||||
val testElementPath = TestElementPath.forElement(element, module) ?: return null
|
||||
} else originalSettings
|
||||
val builder = settings.builder()
|
||||
builder.setTestFilePath(testFilePath)
|
||||
builder.setTestFilePath(configData.jsOutputFilePath)
|
||||
if (settings.ui.isEmpty()) {
|
||||
builder.setUi(MochaUtil.UI_BDD)
|
||||
}
|
||||
when (testElementPath) {
|
||||
when (configData.testElementPath) {
|
||||
is TestElementPath.BySuite -> {
|
||||
val (suiteNames, testName) = testElementPath
|
||||
val (suiteNames, testName) = configData.testElementPath
|
||||
if (testName == null) {
|
||||
builder.setTestKind(MochaTestKind.SUITE)
|
||||
builder.setSuiteNames(suiteNames)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
builder.setTestKind(MochaTestKind.TEST)
|
||||
builder.setTestNames(suiteNames + testName)
|
||||
}
|
||||
@@ -123,14 +99,53 @@ class KotlinMochaRunConfigurationProducer : MochaRunConfigurationProducer() {
|
||||
}
|
||||
}
|
||||
|
||||
builder.setEnvData(module.getNodeJsEnvironmentVars(true))
|
||||
builder.setEnvData(configData.module.getNodeJsEnvironmentVars(true))
|
||||
|
||||
return MochaTestElementInfo(builder.build(), element)
|
||||
return MochaTestElementInfo(builder.build(), configData.element)
|
||||
}
|
||||
|
||||
private fun getConfigurationData(element: PsiElement, context: ConfigurationContext?): MochaConfigData? {
|
||||
val module = element.module
|
||||
val jsModule = module?.jsOrJsImpl() ?: return null
|
||||
val file = if (jsModule != module) {
|
||||
jsModule.moduleFile
|
||||
} else {
|
||||
PsiUtilCore.getVirtualFile(element)
|
||||
} ?: return null
|
||||
val project = module.project
|
||||
|
||||
if (isTestRunnerPackageAvailableFor(project, file)) return null
|
||||
|
||||
val testFilePath = module.jsTestOutputFilePath ?: return null
|
||||
val testElementPath = TestElementPath.forElement(element, module) ?: return null
|
||||
|
||||
val configData = MochaConfigData(element, jsModule, testFilePath, testElementPath)
|
||||
|
||||
if (context?.getOriginalConfiguration(MochaConfigurationType.getInstance()) is MochaRunConfiguration) return configData
|
||||
|
||||
val roots = collectMochaTestRoots(project)
|
||||
if (roots.isEmpty()) return null
|
||||
|
||||
val dirs = SmartHashSet<VirtualFile>()
|
||||
for (root in roots) {
|
||||
if (root.isDirectory) {
|
||||
dirs.add(root)
|
||||
} else if (root == file) return configData
|
||||
}
|
||||
return if (VfsUtilCore.isUnder(file, dirs)) configData else configData
|
||||
}
|
||||
|
||||
override val isForTests: Boolean
|
||||
get() = true
|
||||
|
||||
override fun getConfigurationData(element: PsiElement): MochaConfigData? {
|
||||
return getConfigurationData(element)
|
||||
}
|
||||
|
||||
override fun isConfigurationFromCompatibleContext(configuration: MochaRunConfiguration, context: ConfigurationContext): Boolean {
|
||||
val element = context.psiLocation ?: return false
|
||||
val (thisRunSettings, _) = createTestElementRunInfo(element, configuration.runSettings) ?: return false
|
||||
val configData = getConfigurationData(element) ?: return false
|
||||
val (thisRunSettings, _) = createTestElementRunInfo(configData, configuration.runSettings)
|
||||
val thatRunSettings = configuration.runSettings
|
||||
val thisTestKind = thisRunSettings.testKind
|
||||
if (thisTestKind != thatRunSettings.testKind) return false
|
||||
@@ -145,13 +160,13 @@ class KotlinMochaRunConfigurationProducer : MochaRunConfigurationProducer() {
|
||||
}
|
||||
|
||||
override fun setupConfigurationFromCompatibleContext(
|
||||
configuration: MochaRunConfiguration,
|
||||
context: ConfigurationContext,
|
||||
sourceElement: Ref<PsiElement>
|
||||
configuration: MochaRunConfiguration,
|
||||
context: ConfigurationContext,
|
||||
sourceElement: Ref<PsiElement>
|
||||
): Boolean {
|
||||
val element = context.psiLocation ?: return false
|
||||
if (!isActiveFor(element, context)) return false
|
||||
val (runSettings, enclosingTestElement) = createTestElementRunInfo(element, configuration.runSettings) ?: return false
|
||||
val configData = getConfigurationData(element, context) ?: return false
|
||||
val (runSettings, enclosingTestElement) = createTestElementRunInfo(configData, configuration.runSettings)
|
||||
if (runSettings.testKind == MochaTestKind.DIRECTORY) return false
|
||||
configuration.runSettings = runSettings
|
||||
sourceElement.set(enclosingTestElement)
|
||||
|
||||
+32
-17
@@ -18,44 +18,59 @@ package org.jetbrains.kotlin.idea.nodejs.protractor
|
||||
|
||||
import com.intellij.execution.actions.CompatibleRunConfigurationProducer
|
||||
import com.intellij.execution.actions.ConfigurationContext
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleUtilCore
|
||||
import com.intellij.openapi.util.Ref
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.js.KotlinJSRunConfigurationData
|
||||
import org.jetbrains.kotlin.idea.js.KotlinJSRunConfigurationDataProvider
|
||||
import org.jetbrains.kotlin.idea.js.jsOrJsImpl
|
||||
import org.jetbrains.kotlin.idea.js.jsTestOutputFilePath
|
||||
import org.jetbrains.kotlin.idea.nodejs.TestElementPath
|
||||
import org.jetbrains.kotlin.idea.nodejs.getNodeJsEnvironmentVars
|
||||
import org.jetbrains.kotlin.idea.run.addBuildTask
|
||||
import org.jetbrains.kotlin.idea.util.projectStructure.module
|
||||
|
||||
class ProtractorConfigData(
|
||||
override val element: PsiElement,
|
||||
override val module: Module,
|
||||
override val jsOutputFilePath: String
|
||||
) : KotlinJSRunConfigurationData
|
||||
|
||||
class KotlinProtractorRunConfigurationProducer :
|
||||
CompatibleRunConfigurationProducer<KotlinProtractorRunConfiguration>(KotlinProtractorConfigurationType.getInstance()) {
|
||||
CompatibleRunConfigurationProducer<KotlinProtractorRunConfiguration>(KotlinProtractorConfigurationType.getInstance()),
|
||||
KotlinJSRunConfigurationDataProvider<ProtractorConfigData> {
|
||||
override val isForTests: Boolean
|
||||
get() = true
|
||||
|
||||
override fun getConfigurationData(element: PsiElement): ProtractorConfigData? {
|
||||
val module = ModuleUtilCore.findModuleForPsiElement(element) ?: return null
|
||||
if (!TestElementPath.isModuleAssociatedDir(element, module)) return null
|
||||
val jsModule = module.jsOrJsImpl() ?: return null
|
||||
val testFilePath = jsModule.jsTestOutputFilePath ?: return null
|
||||
return ProtractorConfigData(element, module, testFilePath)
|
||||
}
|
||||
|
||||
override fun isConfigurationFromCompatibleContext(
|
||||
configuration: KotlinProtractorRunConfiguration,
|
||||
context: ConfigurationContext
|
||||
configuration: KotlinProtractorRunConfiguration,
|
||||
context: ConfigurationContext
|
||||
): Boolean {
|
||||
val contextPsi = context.psiLocation ?: return false
|
||||
val jsModule = contextPsi.module?.jsOrJsImpl() ?: return false
|
||||
val testFilePath = jsModule.jsTestOutputFilePath ?: return false
|
||||
return configuration.runSettings.testFileSystemDependentPath == FileUtil.toSystemDependentName(testFilePath)
|
||||
val configData = getConfigurationData(contextPsi) ?: return false
|
||||
return configuration.runSettings.testFileSystemDependentPath == FileUtil.toSystemDependentName(configData.jsOutputFilePath)
|
||||
}
|
||||
|
||||
override fun setupConfigurationFromCompatibleContext(
|
||||
configuration: KotlinProtractorRunConfiguration,
|
||||
context: ConfigurationContext,
|
||||
sourceElement: Ref<PsiElement>
|
||||
configuration: KotlinProtractorRunConfiguration,
|
||||
context: ConfigurationContext,
|
||||
sourceElement: Ref<PsiElement>
|
||||
): Boolean {
|
||||
val element = context.psiLocation ?: return false
|
||||
val module = ModuleUtilCore.findModuleForPsiElement(element) ?: return false
|
||||
if (!TestElementPath.isModuleAssociatedDir(element, module)) return false
|
||||
val jsModule = module.jsOrJsImpl() ?: return false
|
||||
val testFilePath = jsModule.jsTestOutputFilePath ?: return false
|
||||
|
||||
val configData = getConfigurationData(element) ?: return false
|
||||
sourceElement.set(element)
|
||||
configuration.runSettings = configuration.runSettings.copy(
|
||||
testFilePath = testFilePath,
|
||||
envData = jsModule.getNodeJsEnvironmentVars(true)
|
||||
testFilePath = configData.jsOutputFilePath,
|
||||
envData = configData.module.getNodeJsEnvironmentVars(true)
|
||||
)
|
||||
configuration.name = configuration.suggestedName()
|
||||
configuration.addBuildTask()
|
||||
|
||||
Reference in New Issue
Block a user