Kotlin Ultimate: Support Mocha run configurations for Kotlin sources
#KT-16814 In Progress
This commit is contained in:
+10
@@ -0,0 +1,10 @@
|
|||||||
|
<component name="libraryTable">
|
||||||
|
<library name="javascript-support">
|
||||||
|
<CLASSES>
|
||||||
|
<root url="file://$PROJECT_DIR$/ideaSDK/plugins/JavaScriptLanguage/lib" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES />
|
||||||
|
<jarDirectory url="file://$PROJECT_DIR$/ideaSDK/plugins/JavaScriptLanguage/lib" recursive="false" />
|
||||||
|
</library>
|
||||||
|
</component>
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
<component name="libraryTable">
|
||||||
|
<library name="nodejs-support">
|
||||||
|
<CLASSES>
|
||||||
|
<root url="file://$PROJECT_DIR$/dependencies/nodejs_plugin/NodeJS/lib" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES />
|
||||||
|
<jarDirectory url="file://$PROJECT_DIR$/dependencies/nodejs_plugin/NodeJS/lib" recursive="false" />
|
||||||
|
</library>
|
||||||
|
</component>
|
||||||
@@ -27,6 +27,8 @@
|
|||||||
<orderEntry type="library" scope="PROVIDED" name="gradle-and-groovy-plugin" level="project" />
|
<orderEntry type="library" scope="PROVIDED" name="gradle-and-groovy-plugin" level="project" />
|
||||||
<orderEntry type="library" scope="PROVIDED" name="junit-plugin" level="project" />
|
<orderEntry type="library" scope="PROVIDED" name="junit-plugin" level="project" />
|
||||||
<orderEntry type="library" scope="PROVIDED" name="diagram-support" level="project" />
|
<orderEntry type="library" scope="PROVIDED" name="diagram-support" level="project" />
|
||||||
|
<orderEntry type="library" scope="PROVIDED" name="javascript-support" level="project" />
|
||||||
|
<orderEntry type="library" scope="PROVIDED" name="nodejs-support" level="project" />
|
||||||
<orderEntry type="library" scope="PROVIDED" name="intellij-core" level="project" />
|
<orderEntry type="library" scope="PROVIDED" name="intellij-core" level="project" />
|
||||||
<orderEntry type="library" name="idea-full" level="project" />
|
<orderEntry type="library" name="idea-full" level="project" />
|
||||||
<orderEntry type="library" name="protobuf" level="project" />
|
<orderEntry type="library" name="protobuf" level="project" />
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<idea-plugin>
|
||||||
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
|
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.nodejs.KotlinMochaRunConfigurationProducer"/>
|
||||||
|
</extensions>
|
||||||
|
</idea-plugin>
|
||||||
@@ -6,4 +6,5 @@
|
|||||||
<depends optional="true">com.intellij.css</depends>
|
<depends optional="true">com.intellij.css</depends>
|
||||||
<depends optional="true">com.intellij.jsp</depends>
|
<depends optional="true">com.intellij.jsp</depends>
|
||||||
<depends optional="true">com.intellij.diagram</depends>
|
<depends optional="true">com.intellij.diagram</depends>
|
||||||
|
<depends optional="true" config-file="kotlin-nodejs.xml">NodeJS</depends>
|
||||||
</idea-plugin>
|
</idea-plugin>
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.js
|
||||||
|
|
||||||
|
import com.intellij.openapi.module.Module
|
||||||
|
import com.intellij.openapi.roots.CompilerModuleExtension
|
||||||
|
import com.intellij.openapi.roots.ModuleRootManager
|
||||||
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
private fun addSingleModulePaths(target: Module, result: MutableList<String>) {
|
||||||
|
val compilerExtension = CompilerModuleExtension.getInstance(target) ?: return
|
||||||
|
result.addIfNotNull(compilerExtension.compilerOutputPath?.path)
|
||||||
|
result.addIfNotNull(compilerExtension.compilerOutputPathForTests?.let { "${it.path}/lib" })
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getJsClasspath(module: Module): List<String> {
|
||||||
|
val result = ArrayList<String>()
|
||||||
|
ModuleRootManager.getInstance(module).orderEntries().recursively().forEachModule {
|
||||||
|
addSingleModulePaths(it, result)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
package org.jetbrains.kotlin.idea.nodejs
|
||||||
|
|
||||||
|
import com.intellij.execution.RunManager
|
||||||
|
import com.intellij.execution.actions.ConfigurationContext
|
||||||
|
import com.intellij.execution.configuration.EnvironmentVariablesData
|
||||||
|
import com.intellij.lang.javascript.ecmascript6.TypeScriptUtil
|
||||||
|
import com.intellij.openapi.module.ModuleUtilCore
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.util.Ref
|
||||||
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
|
import com.intellij.openapi.vfs.LocalFileSystem
|
||||||
|
import com.intellij.openapi.vfs.VfsUtilCore
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
|
import com.intellij.psi.util.PsiUtilCore
|
||||||
|
import com.intellij.util.SmartList
|
||||||
|
import com.intellij.util.containers.SmartHashSet
|
||||||
|
import com.jetbrains.nodejs.mocha.MochaUtil
|
||||||
|
import com.jetbrains.nodejs.mocha.execution.*
|
||||||
|
import com.jetbrains.nodejs.util.NodeJsCoffeeUtil
|
||||||
|
import org.jetbrains.kotlin.idea.js.getJsClasspath
|
||||||
|
import org.jetbrains.kotlin.idea.js.getJsOutputFilePath
|
||||||
|
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
|
||||||
|
import org.jetbrains.kotlin.js.resolve.JsPlatform
|
||||||
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||||
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class KotlinMochaRunConfigurationProducer : MochaRunConfigurationProducer() {
|
||||||
|
private data class TestElementInfo(val runSettings: MochaRunSettings, val enclosingTestElement: PsiElement)
|
||||||
|
private data class TestElementPath(val suiteNames: List<String>, val testName: String?)
|
||||||
|
|
||||||
|
// 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!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copied from MochaRunConfigurationProducer.isActiveFor()
|
||||||
|
private fun isActiveFor(element: PsiElement, context: ConfigurationContext): Boolean {
|
||||||
|
val file = PsiUtilCore.getVirtualFile(element) ?: return false
|
||||||
|
if (isTestRunnerPackageAvailableFor(element.project, file)) return true
|
||||||
|
|
||||||
|
if (context.getOriginalConfiguration(MochaConfigurationType.getInstance()) is MochaRunConfiguration) return true
|
||||||
|
|
||||||
|
val roots = collectMochaTestRoots(element.project)
|
||||||
|
if (roots.isEmpty()) return false
|
||||||
|
|
||||||
|
val dirs = SmartHashSet<VirtualFile>()
|
||||||
|
for (root in roots) {
|
||||||
|
if (root.isDirectory) {
|
||||||
|
dirs.add(root)
|
||||||
|
}
|
||||||
|
else if (root == file) return true
|
||||||
|
}
|
||||||
|
return VfsUtilCore.isUnder(file, dirs)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createSuiteOrTestData(element: PsiElement): TestElementPath? {
|
||||||
|
val declaration = element.getNonStrictParentOfType<KtNamedDeclaration>() ?: return null
|
||||||
|
val klass = when (declaration) {
|
||||||
|
is KtClassOrObject -> declaration
|
||||||
|
is KtNamedFunction -> declaration.containingClassOrObject ?: return null
|
||||||
|
else -> return null
|
||||||
|
}
|
||||||
|
val suiteNames = klass.parentsWithSelf
|
||||||
|
.filterIsInstance<KtClassOrObject>()
|
||||||
|
.mapNotNull { it.name }
|
||||||
|
.toList()
|
||||||
|
.asReversed()
|
||||||
|
val testName = (declaration as? KtNamedFunction)?.name
|
||||||
|
return TestElementPath(suiteNames, testName)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createTestElementRunInfo(element: PsiElement, originalSettings: MochaRunSettings): TestElementInfo? {
|
||||||
|
val module = ModuleUtilCore.findModuleForPsiElement(element) ?: return null
|
||||||
|
if (TargetPlatformDetector.getPlatform(module) !is JsPlatform) return null
|
||||||
|
val project = module.project
|
||||||
|
val testFilePath = getJsOutputFilePath(module, true, false) ?: return null
|
||||||
|
val settings = if (originalSettings.workingDir.isBlank()) {
|
||||||
|
val workingDir = FileUtil.toSystemDependentName(project.baseDir.path)
|
||||||
|
originalSettings.builder().setWorkingDir(workingDir).build()
|
||||||
|
}
|
||||||
|
else originalSettings
|
||||||
|
val (suiteNames, testName) = createSuiteOrTestData(element) ?: return null
|
||||||
|
val builder = settings.builder()
|
||||||
|
builder.setTestFilePath(testFilePath)
|
||||||
|
if (settings.ui.isEmpty()) {
|
||||||
|
builder.setUi(MochaUtil.UI_BDD)
|
||||||
|
}
|
||||||
|
if (testName == null) {
|
||||||
|
builder.setTestKind(MochaTestKind.SUITE)
|
||||||
|
builder.setSuiteNames(suiteNames)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
builder.setTestKind(MochaTestKind.TEST)
|
||||||
|
builder.setTestNames(suiteNames + testName)
|
||||||
|
}
|
||||||
|
|
||||||
|
val nodeJsClasspath = getJsClasspath(module).joinToString(File.pathSeparator) {
|
||||||
|
val basePath = project.basePath ?: return@joinToString it
|
||||||
|
FileUtil.getRelativePath(basePath, it, '/') ?: it
|
||||||
|
}
|
||||||
|
builder.setEnvData(EnvironmentVariablesData.create(mapOf("NODE_PATH" to nodeJsClasspath), true))
|
||||||
|
|
||||||
|
return TestElementInfo(builder.build(), element)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isConfigurationFromCompatibleContext(configuration: MochaRunConfiguration, context: ConfigurationContext): Boolean {
|
||||||
|
val element = context.psiLocation ?: return false
|
||||||
|
val (thisRunSettings, _) = createTestElementRunInfo(element, configuration.runSettings) ?: return false
|
||||||
|
val thatRunSettings = configuration.runSettings
|
||||||
|
val thisTestKind = thisRunSettings.testKind
|
||||||
|
if (thisTestKind != thatRunSettings.testKind) return false
|
||||||
|
return when {
|
||||||
|
thisTestKind == MochaTestKind.DIRECTORY -> thisRunSettings.testDirPath == thatRunSettings.testDirPath
|
||||||
|
thisTestKind == MochaTestKind.PATTERN -> thisRunSettings.testFilePattern == thatRunSettings.testFilePattern
|
||||||
|
thisTestKind == MochaTestKind.TEST_FILE -> thisRunSettings.testFilePath == thatRunSettings.testFilePath
|
||||||
|
thisTestKind == MochaTestKind.SUITE -> thisRunSettings.testFilePath == thatRunSettings.testFilePath && thisRunSettings.suiteNames == thatRunSettings.suiteNames
|
||||||
|
thisTestKind != MochaTestKind.TEST -> false
|
||||||
|
else -> thisRunSettings.testFilePath == thatRunSettings.testFilePath && thisRunSettings.testNames == thatRunSettings.testNames
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setupConfigurationFromCompatibleContext(
|
||||||
|
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
|
||||||
|
if (runSettings.testKind == MochaTestKind.DIRECTORY) return false
|
||||||
|
configuration.runSettings = runSettings
|
||||||
|
sourceElement.set(enclosingTestElement)
|
||||||
|
configuration.setGeneratedName()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,6 +25,13 @@
|
|||||||
</sequential>
|
</sequential>
|
||||||
</macrodef>
|
</macrodef>
|
||||||
|
|
||||||
|
<macrodef name="get-nodejs-intellij-plugin">
|
||||||
|
<sequential>
|
||||||
|
<get src="http://plugins.jetbrains.com/plugin/download?updateId=37668" dest="${download}/nodejs_plugin.zip" usetimestamp="true"/>
|
||||||
|
<unzip src="${download}/nodejs_plugin.zip" dest="dependencies/nodejs_plugin" overwrite="true"/>
|
||||||
|
</sequential>
|
||||||
|
</macrodef>
|
||||||
|
|
||||||
<target name="fetch-extras">
|
<target name="fetch-extras">
|
||||||
<mkdir dir="${download}"/>
|
<mkdir dir="${download}"/>
|
||||||
|
|
||||||
@@ -33,6 +40,8 @@
|
|||||||
<get-spring-library lib="spring-context" version="4.2.0.RELEASE"/>
|
<get-spring-library lib="spring-context" version="4.2.0.RELEASE"/>
|
||||||
<get-spring-library lib="spring-tx" version="4.2.0.RELEASE"/>
|
<get-spring-library lib="spring-tx" version="4.2.0.RELEASE"/>
|
||||||
<get-spring-library lib="spring-web" version="4.2.0.RELEASE"/>
|
<get-spring-library lib="spring-web" version="4.2.0.RELEASE"/>
|
||||||
|
|
||||||
|
<get-nodejs-intellij-plugin/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!-- Override fetch-third-party from the main buildfile -->
|
<!-- Override fetch-third-party from the main buildfile -->
|
||||||
|
|||||||
Reference in New Issue
Block a user