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:
Alexey Sedunov
2018-03-22 19:59:22 +03:00
parent 3e91346240
commit b52b07ec79
13 changed files with 294 additions and 144 deletions
@@ -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
}
}
@@ -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()
@@ -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)
@@ -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()