diff --git a/idea/build.gradle.kts b/idea/build.gradle.kts index 97e312df69e..1c1e059e621 100644 --- a/idea/build.gradle.kts +++ b/idea/build.gradle.kts @@ -162,6 +162,8 @@ dependencies { testCompile(intellijPluginDep("copyright")) testCompile(intellijPluginDep("properties")) testCompile(intellijPluginDep("java-i18n")) + testCompile(intellijPluginDep("junit")) + testCompileOnly(intellijDep()) testCompileOnly(commonDep("com.google.code.findbugs", "jsr305")) testCompileOnly(intellijPluginDep("gradle")) diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleTestRunConfigurationTest.kt b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleTestRunConfigurationTest.kt index c7c7a863e2a..ec7edce09fb 100644 --- a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleTestRunConfigurationTest.kt +++ b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleTestRunConfigurationTest.kt @@ -5,17 +5,13 @@ package org.jetbrains.kotlin.idea.codeInsight.gradle -import com.intellij.execution.PsiLocation -import com.intellij.execution.actions.ConfigurationContext -import com.intellij.execution.actions.ConfigurationFromContext -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.psi.PsiManager import org.junit.Test import com.intellij.testFramework.runInEdtAndWait import com.intellij.util.PlatformUtils import org.jetbrains.kotlin.idea.run.KotlinGradleRunConfiguration import org.jetbrains.kotlin.idea.run.KotlinJvmTestClassGradleConfigurationProducer import org.jetbrains.kotlin.idea.run.KotlinJvmTestMethodGradleConfigurationProducer +import org.jetbrains.kotlin.idea.run.getConfiguration import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer import org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer @@ -36,34 +32,25 @@ class GradleTestRunConfigurationTest : GradleImportingTestCase() { val javaFile = files.first { it.name == "MyTest.java" } val kotlinFile = files.first { it.name == "MyKotlinTest.kt" } - val javaClassConfiguration = getConfiguration(javaFile, "MyTest") + val javaClassConfiguration = getConfiguration(javaFile, myProject, "MyTest") javaClassConfiguration.isProducedBy(TestClassGradleConfigurationProducer::class.java) assert(javaClassConfiguration.configuration !is KotlinGradleRunConfiguration) - val javaMethodConfiguration = getConfiguration(javaFile, "testA") + val javaMethodConfiguration = getConfiguration(javaFile, myProject, "testA") javaMethodConfiguration.isProducedBy(TestMethodGradleConfigurationProducer::class.java) assert(javaMethodConfiguration.configuration !is KotlinGradleRunConfiguration) - val kotlinClassConfiguration = getConfiguration(kotlinFile, "MyKotlinTest") + val kotlinClassConfiguration = getConfiguration(kotlinFile, myProject, "MyKotlinTest") kotlinClassConfiguration.isProducedBy(KotlinJvmTestClassGradleConfigurationProducer::class.java) assert(kotlinClassConfiguration.configuration is KotlinGradleRunConfiguration) - val kotlinFunctionConfiguration = getConfiguration(kotlinFile, "testA") + val kotlinFunctionConfiguration = getConfiguration(kotlinFile, myProject, "testA") kotlinFunctionConfiguration.isProducedBy(KotlinJvmTestMethodGradleConfigurationProducer::class.java) assert(kotlinFunctionConfiguration.configuration is KotlinGradleRunConfiguration) } } } - private fun getConfiguration(file: VirtualFile, pattern: String): ConfigurationFromContext { - val psiFile = PsiManager.getInstance(myTestFixture.project).findFile(file) ?: error("PsiFile not found for $file") - val offset = psiFile.text.indexOf(pattern) - val psiElement = psiFile.findElementAt(offset) - val location = PsiLocation(psiElement) - val context = ConfigurationContext.createEmptyContextForLocation(location) - return context.configurationsFromContext.orEmpty().singleOrNull() ?: error("Configuration not found for pattern $pattern") - } - override fun testDataDirName(): String { return "testRunConfigurations" } diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/KotlinJUnitConfigurationType.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/KotlinJUnitConfigurationType.kt new file mode 100644 index 00000000000..9038e18d29b --- /dev/null +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/KotlinJUnitConfigurationType.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.run + +import com.intellij.execution.ExecutionBundle +import com.intellij.execution.configurations.ConfigurationFactory +import com.intellij.execution.configurations.ConfigurationType +import com.intellij.execution.configurations.ConfigurationTypeUtil +import com.intellij.execution.configurations.RunConfiguration +import com.intellij.execution.junit.JUnitConfiguration +import com.intellij.icons.AllIcons +import com.intellij.openapi.project.Project +import javax.swing.Icon + +class KotlinJUnitConfigurationType : ConfigurationType { + val factory = object : ConfigurationFactory(this) { + override fun createTemplateConfiguration(project: Project): RunConfiguration { + return KotlinJUnitConfiguration("", project, this) + } + } + + companion object { + val instance: KotlinJUnitConfigurationType + get() = ConfigurationTypeUtil.findConfigurationType(KotlinJUnitConfigurationType::class.java) + } + + override fun getConfigurationFactories(): Array = arrayOf(factory) + + override fun getDisplayName() = ExecutionBundle.message("junit.configuration.display.name") + override fun getConfigurationTypeDescription() = ExecutionBundle.message("junit.configuration.description") + override fun getIcon(): Icon = AllIcons.RunConfigurations.Junit + override fun getId() = "KotlinJUnit" + override fun getTag() = "junit" + override fun isDumbAware() = false +} + +class KotlinJUnitConfiguration(name: String, project: Project, configurationFactory: ConfigurationFactory) : + JUnitConfiguration(name, project, configurationFactory) \ No newline at end of file diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/KotlinJUnitRunConfigurationProducer.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/KotlinJUnitRunConfigurationProducer.kt index aa66d552518..13ac8881dfd 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/KotlinJUnitRunConfigurationProducer.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/KotlinJUnitRunConfigurationProducer.kt @@ -12,6 +12,7 @@ import com.intellij.execution.RunnerAndConfigurationSettings import com.intellij.execution.actions.ConfigurationContext import com.intellij.execution.actions.ConfigurationFromContext import com.intellij.execution.actions.RunConfigurationProducer +import com.intellij.execution.configurations.ConfigurationFactory import com.intellij.execution.configurations.ModuleBasedConfiguration import com.intellij.execution.junit.* import com.intellij.execution.testframework.AbstractPatternBasedConfigurationProducer @@ -32,8 +33,13 @@ import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.psiUtil.getParentOfType class KotlinJUnitRunConfigurationProducer : RunConfigurationProducer(JUnitConfigurationType.getInstance()) { + override fun getConfigurationFactory(): ConfigurationFactory { + return KotlinJUnitConfigurationType.instance.factory + } + override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean { - return other.isProducedBy(JUnitConfigurationProducer::class.java) || other.isProducedBy(AbstractPatternBasedConfigurationProducer::class.java) + return other.isProducedBy(JUnitConfigurationProducer::class.java) + || other.isProducedBy(AbstractPatternBasedConfigurationProducer::class.java) } private fun isAvailableInMpp(context: ConfigurationContext): Boolean { diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/KotlinPatternConfigurationProducer.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/KotlinPatternConfigurationProducer.kt index a48f7e22ef0..8ba2b36e7fe 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/KotlinPatternConfigurationProducer.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/run/KotlinPatternConfigurationProducer.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.run import com.intellij.execution.actions.ConfigurationContext import com.intellij.execution.actions.ConfigurationFromContext +import com.intellij.execution.configurations.ConfigurationFactory import com.intellij.execution.junit.JUnitConfiguration import com.intellij.execution.junit.PatternConfigurationProducer import com.intellij.execution.junit.TestClassConfigurationProducer @@ -28,6 +29,10 @@ import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.psi.KtClassOrObject class KotlinPatternConfigurationProducer : PatternConfigurationProducer() { + override fun getConfigurationFactory(): ConfigurationFactory { + return KotlinJUnitConfigurationType.instance.factory + } + override fun setupConfigurationFromContext( configuration: JUnitConfiguration, context: ConfigurationContext, diff --git a/idea/resources/META-INF/jvm.xml b/idea/resources/META-INF/jvm.xml index 7ad320b160b..93c68d93cd8 100644 --- a/idea/resources/META-INF/jvm.xml +++ b/idea/resources/META-INF/jvm.xml @@ -110,6 +110,7 @@ + diff --git a/idea/resources/META-INF/jvm.xml.183 b/idea/resources/META-INF/jvm.xml.183 index 144e9db1a83..c6591a0b127 100644 --- a/idea/resources/META-INF/jvm.xml.183 +++ b/idea/resources/META-INF/jvm.xml.183 @@ -115,6 +115,7 @@ + diff --git a/idea/testData/runConfigurations/junit/Simple/module/test/MyJavaTest.java b/idea/testData/runConfigurations/junit/Simple/module/test/MyJavaTest.java new file mode 100644 index 00000000000..a39cb9bb5dc --- /dev/null +++ b/idea/testData/runConfigurations/junit/Simple/module/test/MyJavaTest.java @@ -0,0 +1,11 @@ +import org.junit.Test; + +public class MyJavaTest { + @Test + public void testA() { + } + + @Test + public void testB() { + } +} \ No newline at end of file diff --git a/idea/testData/runConfigurations/junit/Simple/module/test/MyKotlinTest.kt b/idea/testData/runConfigurations/junit/Simple/module/test/MyKotlinTest.kt new file mode 100644 index 00000000000..b716ac97ded --- /dev/null +++ b/idea/testData/runConfigurations/junit/Simple/module/test/MyKotlinTest.kt @@ -0,0 +1,11 @@ +import org.junit.Test + +class MyKotlinTest { + @Test + fun testA() { + } + + @Test + fun testB() { + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/run/AbstractRunConfigurationTest.kt b/idea/tests/org/jetbrains/kotlin/idea/run/AbstractRunConfigurationTest.kt new file mode 100644 index 00000000000..bf857409d68 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/run/AbstractRunConfigurationTest.kt @@ -0,0 +1,77 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.run + +import com.intellij.openapi.module.Module +import com.intellij.openapi.vfs.LocalFileSystem +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.PsiDocumentManager +import com.intellij.testFramework.PsiTestUtil +import org.jetbrains.kotlin.idea.util.application.runWriteAction +import org.jetbrains.kotlin.idea.test.KotlinCodeInsightTestCase +import org.jetbrains.kotlin.idea.test.PluginTestCaseBase.* +import java.io.File + +abstract class AbstractRunConfigurationTest : @Suppress("DEPRECATION") KotlinCodeInsightTestCase() { + fun getTestProject() = myProject!! + override fun getModule() = myModule!! + + protected fun configureModule(moduleDir: String, outputParentDir: VirtualFile, configModule: Module = module): CreateModuleResult { + val srcPath = "$moduleDir/src" + val srcDir: VirtualFile? + + if (File(srcPath).exists()) { + srcDir = PsiTestUtil.createTestProjectStructure(project, configModule, srcPath, myFilesToDelete, false) + PsiTestUtil.addSourceRoot(module, srcDir, false) + } else { + srcDir = null + } + + val testPath = "$moduleDir/test" + val testDir: VirtualFile? + + if (File(testPath).exists()) { + testDir = if (srcDir == null) { + PsiTestUtil.createTestProjectStructure(project, configModule, testPath, myFilesToDelete, false) + } else { + val canonicalPath = File(testPath).canonicalPath.replace(File.separatorChar, '/') + LocalFileSystem.getInstance().refreshAndFindFileByPath(canonicalPath) + } + + if (testDir != null) { + PsiTestUtil.addSourceRoot(module, testDir, true) + } + } else { + testDir = null + } + + val (srcOutDir, testOutDir) = runWriteAction { + val outDir = outputParentDir.createChildDirectory(this, "out") + val srcOutDir = outDir.createChildDirectory(this, "production") + val testOutDir = outDir.createChildDirectory(this, "test") + + PsiTestUtil.setCompilerOutputPath(configModule, srcOutDir.url, false) + PsiTestUtil.setCompilerOutputPath(configModule, testOutDir.url, true) + + Pair(srcOutDir, testOutDir) + } + + PsiDocumentManager.getInstance(getTestProject()).commitAllDocuments() + + return CreateModuleResult(configModule, srcDir, testDir, srcOutDir, testOutDir) + } + + protected class CreateModuleResult( + val module: Module, + val srcDir: VirtualFile?, + val testDir: VirtualFile?, + val srcOutputDir: VirtualFile, + val testOutputDir: VirtualFile + ) + + protected fun moduleDirPath(moduleName: String) = "${testDataPath}${getTestName(false)}/$moduleName" + override fun getTestProjectJdk() = mockJdk() +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/run/KotlinJUnitRunConfigurationTest.kt b/idea/tests/org/jetbrains/kotlin/idea/run/KotlinJUnitRunConfigurationTest.kt new file mode 100644 index 00000000000..4f4e779aaca --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/run/KotlinJUnitRunConfigurationTest.kt @@ -0,0 +1,93 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.run + +import com.intellij.execution.PsiLocation +import com.intellij.execution.actions.ConfigurationContext +import com.intellij.execution.actions.ConfigurationFromContext +import com.intellij.execution.junit.TestInClassConfigurationProducer +import com.intellij.openapi.application.PathManager +import com.intellij.openapi.project.Project +import com.intellij.openapi.roots.ModuleRootModificationUtil.updateModel +import com.intellij.openapi.roots.OrderRootType +import com.intellij.openapi.roots.ui.configuration.libraryEditor.NewLibraryEditor +import com.intellij.openapi.vfs.JarFileSystem +import com.intellij.openapi.vfs.LocalFileSystem +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.PsiManager +import com.intellij.util.PlatformUtils +import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil +import org.jetbrains.kotlin.idea.test.PluginTestCaseBase.* +import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner +import org.junit.runner.RunWith +import java.io.File + +@RunWith(JUnit3WithIdeaConfigurationRunner::class) +class KotlinJUnitRunConfigurationTest : AbstractRunConfigurationTest() { + fun testSimple() { + if (!PlatformUtils.isIntelliJ()) { + return + } + + val createResult = configureModule(moduleDirPath("module"), getTestProject().baseDir!!) + val testDir = createResult.testDir!! + + ConfigLibraryUtil.configureKotlinRuntimeAndSdk(module, addJdk(testRootDisposable, ::mockJdk)) + + try { + attachJUnitLibrary() + + val javaFile = testDir.findChild("MyJavaTest.java")!! + val kotlinFile = testDir.findChild("MyKotlinTest.kt")!! + + val javaClassConfiguration = getConfiguration(javaFile, project, "MyTest") + javaClassConfiguration.isProducedBy(TestInClassConfigurationProducer::class.java) + assert(javaClassConfiguration.configuration !is KotlinJUnitConfiguration) + + val javaMethodConfiguration = getConfiguration(javaFile, project, "testA") + javaMethodConfiguration.isProducedBy(TestInClassConfigurationProducer::class.java) + assert(javaMethodConfiguration.configuration !is KotlinJUnitConfiguration) + + val kotlinClassConfiguration = getConfiguration(kotlinFile, project, "MyKotlinTest") + kotlinClassConfiguration.isProducedBy(KotlinJUnitRunConfigurationProducer::class.java) + assert(kotlinClassConfiguration.configuration is KotlinJUnitConfiguration) + + val kotlinFunctionConfiguration = getConfiguration(kotlinFile, project, "testA") + kotlinFunctionConfiguration.isProducedBy(KotlinJUnitRunConfigurationProducer::class.java) + assert(kotlinFunctionConfiguration.configuration is KotlinJUnitConfiguration) + } finally { + detachJUnitLibrary() + } + } + + private fun attachJUnitLibrary() { + val platformPath = PathManager.getHomePath().replace(File.separatorChar, '/') + val junitLibraryFile = File("$platformPath/lib/junit-4.12.jar") + val junitLibraryVirtualFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(junitLibraryFile.canonicalPath)!! + + updateModel(module) { model -> + val editor = NewLibraryEditor() + editor.name = "JUnit" + editor.addRoot(JarFileSystem.getInstance().getJarRootForLocalFile(junitLibraryVirtualFile)!!, OrderRootType.CLASSES) + ConfigLibraryUtil.addLibrary(editor, model) + } + } + + private fun detachJUnitLibrary() { + ConfigLibraryUtil.removeLibrary(module, "JUnit") + } + + override fun getTestDataPath() = getTestDataPathBase() + "/runConfigurations/junit/" +} + +fun getConfiguration(file: VirtualFile, project: Project, pattern: String): ConfigurationFromContext { + val psiFile = PsiManager.getInstance(project).findFile(file) ?: error("PsiFile not found for $file") + val offset = psiFile.text.indexOf(pattern) + val psiElement = psiFile.findElementAt(offset) + val location = PsiLocation(psiElement) + val context = ConfigurationContext.createEmptyContextForLocation(location) + return context.configurationsFromContext.orEmpty().singleOrNull() ?: error("Configuration not found for pattern $pattern") +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/run/RunConfigurationTest.kt b/idea/tests/org/jetbrains/kotlin/idea/run/RunConfigurationTest.kt index f6ae18ba5b7..9b5281fb5b0 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/run/RunConfigurationTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/run/RunConfigurationTest.kt @@ -11,10 +11,8 @@ import com.intellij.execution.actions.ConfigurationContext import com.intellij.openapi.module.Module import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.roots.ModuleRootModificationUtil -import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.JavaPsiFacade import com.intellij.psi.PsiComment -import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiManager import com.intellij.refactoring.RefactoringFactory import com.intellij.testFramework.MapDataContext @@ -28,7 +26,6 @@ import org.jetbrains.kotlin.idea.search.allScope import org.jetbrains.kotlin.idea.stubindex.KotlinFullClassNameIndex import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelFunctionFqnNameIndex import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil -import org.jetbrains.kotlin.idea.test.KotlinCodeInsightTestCase import org.jetbrains.kotlin.idea.test.PluginTestCaseBase.* import org.jetbrains.kotlin.idea.test.configureLanguageAndApiVersion import org.jetbrains.kotlin.idea.util.application.runWriteAction @@ -43,10 +40,7 @@ import java.util.* private const val RUN_PREFIX = "// RUN:" @RunWith(JUnit3WithIdeaConfigurationRunner::class) -class RunConfigurationTest: KotlinCodeInsightTestCase() { - fun getTestProject() = myProject!! - override fun getModule() = myModule!! - +class RunConfigurationTest : AbstractRunConfigurationTest() { fun testMainInTest() { val createResult = configureModule(moduleDirPath("module"), getTestProject().baseDir!!) configureLanguageAndApiVersion( @@ -108,7 +102,7 @@ class RunConfigurationTest: KotlinCodeInsightTestCase() { } } - createResult.srcDir.children.filter { it.extension == "kt" }.forEach { + createResult.srcDir?.children?.filter { it.extension == "kt" }?.forEach { val psiFile = PsiManager.getInstance(createResult.module.project).findFile(it) if (psiFile is KtFile) { psiFile.acceptChildren(object : KtVisitorVoid() { @@ -216,7 +210,7 @@ class RunConfigurationTest: KotlinCodeInsightTestCase() { private fun doTest(configureRuntime: (Module, Sdk) -> Unit) { val baseDir = getTestProject().baseDir!! val createModuleResult = configureModule(moduleDirPath("module"), baseDir) - val srcDir = createModuleResult.srcDir + val srcDir = createModuleResult.srcDir!! configureRuntime(createModuleResult.module, addJdk(testRootDisposable, ::mockJdk)) @@ -264,41 +258,5 @@ class RunConfigurationTest: KotlinCodeInsightTestCase() { return createConfigurationFromElement(mainFunction, save) as KotlinRunConfiguration } - private fun configureModule(moduleDir: String, outputParentDir: VirtualFile, configModule: Module = module): CreateModuleResult { - val srcPath = moduleDir + "/src" - val srcDir = PsiTestUtil.createTestProjectStructure(project, configModule, srcPath, myFilesToDelete, true) - - val testPath = moduleDir + "/test" - if (File(testPath).exists()) { - val testDir = PsiTestUtil.createTestProjectStructure(project, configModule, testPath, myFilesToDelete, false) - PsiTestUtil.addSourceRoot(module, testDir, true) - } - - val (srcOutDir, testOutDir) = runWriteAction { - val outDir = outputParentDir.createChildDirectory(this, "out") - val srcOutDir = outDir.createChildDirectory(this, "production") - val testOutDir = outDir.createChildDirectory(this, "test") - - PsiTestUtil.setCompilerOutputPath(configModule, srcOutDir.url, false) - PsiTestUtil.setCompilerOutputPath(configModule, testOutDir.url, true) - - Pair(srcOutDir, testOutDir) - } - - PsiDocumentManager.getInstance(getTestProject()).commitAllDocuments() - - return CreateModuleResult(configModule, srcDir, srcOutDir, testOutDir) - } - - private fun moduleDirPath(moduleName: String) = "${testDataPath}${getTestName(false)}/$moduleName" - override fun getTestDataPath() = getTestDataPathBase() + "/run/" - override fun getTestProjectJdk() = mockJdk() - - private class CreateModuleResult( - val module: Module, - val srcDir: VirtualFile, - val srcOutputDir: VirtualFile, - val testOutputDir: VirtualFile - ) }