From 99258662931a298f0adf38fca6a84c0d797a4537 Mon Sep 17 00:00:00 2001 From: Florian Kistner Date: Wed, 5 Aug 2020 19:34:35 +0200 Subject: [PATCH] 203: Fix compilation --- .../kotlin/idea/debugger/TypeUtils.kt.203 | 70 ++++++ .../markers/OverridenPropertyMarker.kt.203 | 132 +++++++++++ ...bstractConfigureKotlinInTempDirTest.kt.203 | 4 +- .../AbstractConfigureKotlinTest.kt.203 | 9 +- .../MoveKotlinDeclarationsHandlerTest.kt.203 | 211 ++++++++++++++++++ .../run/AbstractRunConfigurationTest.kt.203 | 77 +++++++ 6 files changed, 497 insertions(+), 6 deletions(-) create mode 100644 idea/jvm-debugger/jvm-debugger-util/src/org/jetbrains/kotlin/idea/debugger/TypeUtils.kt.203 create mode 100644 idea/src/org/jetbrains/kotlin/idea/highlighter/markers/OverridenPropertyMarker.kt.203 create mode 100644 idea/tests/org/jetbrains/kotlin/idea/refactoring/move/MoveKotlinDeclarationsHandlerTest.kt.203 create mode 100644 idea/tests/org/jetbrains/kotlin/idea/run/AbstractRunConfigurationTest.kt.203 diff --git a/idea/jvm-debugger/jvm-debugger-util/src/org/jetbrains/kotlin/idea/debugger/TypeUtils.kt.203 b/idea/jvm-debugger/jvm-debugger-util/src/org/jetbrains/kotlin/idea/debugger/TypeUtils.kt.203 new file mode 100644 index 00000000000..de5c1790f0b --- /dev/null +++ b/idea/jvm-debugger/jvm-debugger-util/src/org/jetbrains/kotlin/idea/debugger/TypeUtils.kt.203 @@ -0,0 +1,70 @@ +/* + * Copyright 2000-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.debugger + +import com.intellij.psi.JavaPsiFacade +import com.intellij.psi.search.GlobalSearchScope +import com.sun.jdi.ClassType +import org.jetbrains.kotlin.builtins.DefaultBuiltIns +import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap +import org.jetbrains.kotlin.codegen.AsmUtil +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies +import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaClassDescriptor +import org.jetbrains.kotlin.idea.util.application.runReadAction +import org.jetbrains.kotlin.resolve.jvm.JvmClassName +import com.sun.jdi.Type as JdiType +import org.jetbrains.org.objectweb.asm.Type as AsmType + +fun JdiType.isSubtype(className: String): Boolean = isSubtype(AsmType.getObjectType(className)) + +fun JdiType.isSubtype(type: AsmType): Boolean { + if (this.signature() == type.descriptor) { + return true + } + + if (type.sort != AsmType.OBJECT || this !is ClassType) { + return false + } + + val superTypeName = type.className + + if (allInterfaces().any { it.name() == superTypeName }) { + return true + } + + var superClass = superclass() + while (superClass != null) { + if (superClass.name() == superTypeName) { + return true + } + superClass = superClass.superclass() + } + + return false +} + +fun AsmType.getClassDescriptor( + scope: GlobalSearchScope, + mapBuiltIns: Boolean = true, + moduleDescriptor: ModuleDescriptor = DefaultBuiltIns.Instance.builtInsModule +): ClassDescriptor? { + if (AsmUtil.isPrimitive(this)) return null + + val jvmName = JvmClassName.byInternalName(internalName).fqNameForClassNameWithoutDollars + + if (mapBuiltIns) { + val mappedName = JavaToKotlinClassMap.mapJavaToKotlin(jvmName) + if (mappedName != null) { + moduleDescriptor.findClassAcrossModuleDependencies(mappedName)?.let { return it } + } + } + + return runReadAction { + scope.project?.let(JavaPsiFacade::getInstance)?.findClasses(jvmName.asString(), scope)?.firstOrNull()?.getJavaClassDescriptor() + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/OverridenPropertyMarker.kt.203 b/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/OverridenPropertyMarker.kt.203 new file mode 100644 index 00000000000..ca39519da9f --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/OverridenPropertyMarker.kt.203 @@ -0,0 +1,132 @@ +/* + * Copyright 2010-2015 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.highlighter.markers + +import com.intellij.codeInsight.daemon.impl.GutterIconTooltipHelper +import com.intellij.ide.util.DefaultPsiElementCellRenderer +import com.intellij.ide.util.PsiClassListCellRenderer +import com.intellij.java.analysis.JavaAnalysisBundle +import com.intellij.openapi.progress.ProgressManager +import com.intellij.openapi.project.DumbService +import com.intellij.psi.NavigatablePsiElement +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiMethod +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.search.PsiElementProcessor +import com.intellij.psi.search.PsiElementProcessorAdapter +import com.intellij.util.AdapterProcessor +import com.intellij.util.CommonProcessors +import com.intellij.util.Function +import org.jetbrains.kotlin.idea.KotlinBundle +import org.jetbrains.kotlin.idea.search.declarationsSearch.forEachOverridingMethod +import org.jetbrains.kotlin.idea.search.declarationsSearch.toPossiblyFakeLightMethods +import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinDefinitionsSearcher +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.psi.* +import java.awt.event.MouseEvent +import javax.swing.JComponent + +fun getOverriddenPropertyTooltip(property: KtNamedDeclaration): String? { + val overriddenInClassesProcessor = PsiElementProcessor.CollectElementsWithLimit(5) + + val consumer = AdapterProcessor( + CommonProcessors.UniqueProcessor(PsiElementProcessorAdapter(overriddenInClassesProcessor)), + Function { method: PsiMethod? -> method?.containingClass } + ) + + for (method in property.toPossiblyFakeLightMethods()) { + if (!overriddenInClassesProcessor.isOverflow) { + method.forEachOverridingMethod(processor = consumer::process) + } + } + + val isImplemented = isImplemented(property) + if (overriddenInClassesProcessor.isOverflow) { + return if (isImplemented) + KotlinBundle.message("overridden.marker.implementations.multiple") + else + KotlinBundle.message("overridden.marker.overrides.multiple") + } + + val collectedClasses = overriddenInClassesProcessor.collection + if (collectedClasses.isEmpty()) return null + + val start = if (isImplemented) + KotlinBundle.message("overridden.marker.implementation") + else + KotlinBundle.message("overridden.marker.overrides") + + val pattern = "    {0}" + return GutterIconTooltipHelper.composeText(collectedClasses.sortedWith(PsiClassListCellRenderer().comparator), start, pattern) +} + +fun buildNavigateToPropertyOverriddenDeclarationsPopup(e: MouseEvent?, element: PsiElement?): NavigationPopupDescriptor? { + val propertyOrParameter = element?.parent as? KtNamedDeclaration ?: return null + val project = propertyOrParameter.project + + if (DumbService.isDumb(project)) { + DumbService.getInstance(project)?.showDumbModeNotification( + KotlinBundle.message("highlighter.notification.text.navigation.to.overriding.classes.is.not.possible.during.index.update")) + return null + } + + val psiPropertyMethods = propertyOrParameter.toPossiblyFakeLightMethods() + val elementProcessor = CommonProcessors.CollectUniquesProcessor() + val ktPsiMethodProcessor = Runnable { + KotlinDefinitionsSearcher.processPropertyImplementationsMethods( + psiPropertyMethods, + GlobalSearchScope.allScope(project), + elementProcessor + ) + } + + if (!ProgressManager.getInstance().runProcessWithProgressSynchronously( + /* runnable */ ktPsiMethodProcessor, + JavaAnalysisBundle.message("searching.for.overriding.methods"), + /* can be canceled */ true, + project, + e?.component as JComponent? + ) + ) { + return null + } + + val renderer = DefaultPsiElementCellRenderer() + val navigatingOverrides = elementProcessor.results + .sortedWith(renderer.comparator) + .filterIsInstance() + + return NavigationPopupDescriptor( + navigatingOverrides, + KotlinBundle.message("overridden.marker.implementations.choose.implementation.title", propertyOrParameter.name.toString()), + KotlinBundle.message("overridden.marker.implementations.choose.implementation.find.usages", propertyOrParameter.name.toString()), renderer + ) +} + + +fun isImplemented(declaration: KtNamedDeclaration): Boolean { + if (declaration.hasModifier(KtTokens.ABSTRACT_KEYWORD)) return true + + var parent = declaration.parent + parent = if (parent is KtClassBody) parent.getParent() else parent + + if (parent !is KtClass) return false + + return parent.isInterface() && (declaration !is KtDeclarationWithBody || !declaration.hasBody()) && (declaration !is KtDeclarationWithInitializer || !declaration.hasInitializer()) +} + diff --git a/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinInTempDirTest.kt.203 b/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinInTempDirTest.kt.203 index cfcd81c9c2b..766f38dc50f 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinInTempDirTest.kt.203 +++ b/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinInTempDirTest.kt.203 @@ -12,10 +12,10 @@ import java.io.File import java.nio.file.Path abstract class AbstractConfigureKotlinInTempDirTest : AbstractConfigureKotlinTest() { - override fun getProjectDirOrFile(): Path { + override fun getProjectDirOrFile(isDirectoryBasedProject: Boolean): Path { val tempDir = FileUtil.generateRandomTemporaryPath() FileUtil.createTempDirectory("temp", null) - myFilesToDelete.add(tempDir.toPath()) + getTempDir().scheduleDelete(tempDir.toPath()) FileUtil.copyDir(File(projectRoot), tempDir) diff --git a/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinTest.kt.203 b/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinTest.kt.203 index d454e5dc70e..5efbf4bb50c 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinTest.kt.203 +++ b/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinTest.kt.203 @@ -105,13 +105,14 @@ abstract class AbstractConfigureKotlinTest : PlatformTestCase() { val modules: Array get() = ModuleManager.getInstance(myProject).modules - override fun getProjectDirOrFile(): Path { + override fun getProjectDirOrFile(isDirectoryBasedProject: Boolean): Path { val projectFilePath = projectRoot + "/projectFile.ipr" TestCase.assertTrue("Project file should exists " + projectFilePath, File(projectFilePath).exists()) return File(projectFilePath).toPath() } - override fun doCreateAndOpenProject(projectFile: Path): Project { + override fun doCreateAndOpenProject(): Project { + val projectFile = getProjectDirOrFile(isCreateDirectoryBasedProject) return loadProjectCompat(projectFile) } @@ -238,14 +239,14 @@ abstract class AbstractConfigureKotlinTest : PlatformTestCase() { private val pathToNonexistentRuntimeJar: String get() { val pathToTempKotlinRuntimeJar = FileUtil.getTempDirectory() + "/" + PathUtil.KOTLIN_JAVA_STDLIB_JAR - myFilesToDelete.add(Paths.get(pathToTempKotlinRuntimeJar)) + tempDir.scheduleDelete(Paths.get(pathToTempKotlinRuntimeJar)) return pathToTempKotlinRuntimeJar } private val pathToNonexistentJsJar: String get() { val pathToTempKotlinRuntimeJar = FileUtil.getTempDirectory() + "/" + PathUtil.JS_LIB_JAR_NAME - myFilesToDelete.add(Paths.get(pathToTempKotlinRuntimeJar)) + tempDir.scheduleDelete(Paths.get(pathToTempKotlinRuntimeJar)) return pathToTempKotlinRuntimeJar } diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/MoveKotlinDeclarationsHandlerTest.kt.203 b/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/MoveKotlinDeclarationsHandlerTest.kt.203 new file mode 100644 index 00000000000..253a941114d --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/MoveKotlinDeclarationsHandlerTest.kt.203 @@ -0,0 +1,211 @@ +/* + * 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.refactoring.move + +import com.intellij.openapi.fileEditor.FileDocumentManager +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.JavaPsiFacade +import com.intellij.psi.PsiDocumentManager +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.idea.core.util.toPsiDirectory +import org.jetbrains.kotlin.idea.core.util.toPsiFile +import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.MoveKotlinDeclarationsHandler +import org.jetbrains.kotlin.idea.test.KotlinMultiFileTestCase +import org.jetbrains.kotlin.idea.test.PluginTestCaseBase +import org.jetbrains.kotlin.idea.test.extractMultipleMarkerOffsets +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType +import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance +import org.junit.runner.RunWith + +@RunWith(JUnit3WithIdeaConfigurationRunner::class) +class MoveKotlinDeclarationsHandlerTest : KotlinMultiFileTestCase() { + override fun getTestDataPath() = PluginTestCaseBase.getTestDataPathBase() + + override fun getTestRoot() = "/refactoring/moveHandler/declarations" + + private fun doTest(action: (rootDir: VirtualFile, handler: MoveKotlinDeclarationsHandler) -> Unit) { + val path = "$testDataPath$testRoot/${getTestName(true)}" + val rootDir = createTestProjectStructure(myProject, myModule, path, false) + prepareProject(rootDir) + PsiDocumentManager.getInstance(myProject).commitAllDocuments() + action(rootDir, MoveKotlinDeclarationsHandler()) + } + + private fun getPsiDirectory(rootDir: VirtualFile, path: String) = rootDir.findFileByRelativePath(path)!!.toPsiDirectory(project)!! + + private fun getPsiFile(rootDir: VirtualFile, path: String) = rootDir.findFileByRelativePath(path)!!.toPsiFile(project)!! + + private fun getElementAtCaret(rootDir: VirtualFile, path: String) = getElementsAtCarets(rootDir, path).single() + + private fun getElementsAtCarets(rootDir: VirtualFile, path: String): List { + val file = getPsiFile(rootDir, path) + val document = FileDocumentManager.getInstance().getDocument(file.virtualFile)!! + return document.extractMultipleMarkerOffsets(project).map { file.findElementAt(it)!! } + } + + fun testObjectLiteral() = doTest { rootDir, handler -> + val objectDeclaration = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType()!! + assert(!handler.canMove(arrayOf(objectDeclaration), null, null)) + } + + fun testLocalClass() = doTest { rootDir, handler -> + val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType()!! + assert(!handler.canMove(arrayOf(klass), null, null)) + } + + fun testLocalFun() = doTest { rootDir, handler -> + val function = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType()!! + assert(!handler.canMove(arrayOf(function), null, null)) + } + + fun testLocalVal() = doTest { rootDir, handler -> + val property = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType()!! + assert(!handler.canMove(arrayOf(property), null, null)) + } + + fun testMemberFun() = doTest { rootDir, handler -> + val function = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType()!! + assert(!handler.canMove(arrayOf(function), null, null)) + } + + fun testMemberVal() = doTest { rootDir, handler -> + val property = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType()!! + assert(!handler.canMove(arrayOf(property), null, null)) + } + + fun testNestedClass() = doTest { rootDir, handler -> + val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType()!! + assert(handler.canMove(arrayOf(klass), null, null)) + } + + fun testInnerClass() = doTest { rootDir, handler -> + val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType()!! + assert(handler.canMove(arrayOf(klass), null, null)) + } + + fun testTopLevelClass() = doTest { rootDir, handler -> + val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType()!! + assert(handler.canMove(arrayOf(klass), null, null)) + } + + fun testTopLevelFun() = doTest { rootDir, handler -> + val function = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType()!! + assert(handler.canMove(arrayOf(function), null, null)) + } + + fun testTopLevelVal() = doTest { rootDir, handler -> + val property = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType()!! + assert(handler.canMove(arrayOf(property), null, null)) + } + + fun testMultipleNestedClasses() = doTest { rootDir, handler -> + val classes = getElementsAtCarets(rootDir, "test.kt").map { it.getNonStrictParentOfType()!! } + assert(handler.canMove(classes.toTypedArray(), null, null)) + } + + fun testNestedAndTopLevelClass() = doTest { rootDir, handler -> + val classes = getElementsAtCarets(rootDir, "test.kt").map { it.getNonStrictParentOfType()!! } + assert(!handler.canMove(classes.toTypedArray(), null, null)) + } + + fun testMultipleTopLevelDeclarations() = doTest { rootDir, handler -> + val declarations = getElementsAtCarets(rootDir, "test.kt").map { it.getNonStrictParentOfType()!! } + assert(handler.canMove(declarations.toTypedArray(), null, null)) + } + + fun testMultipleTopLevelDeclarationsInDifferentFiles() = doTest { rootDir, handler -> + val declarations = listOf("test.kt", "test2.kt").flatMap { getElementsAtCarets(rootDir, it) } + .map { it.getNonStrictParentOfType()!! } + assert(handler.canMove(declarations.toTypedArray(), null, null)) + + val files = listOf("test.kt", "test2.kt").map { getPsiFile(rootDir, it) } + assert(handler.canMove(files.toTypedArray(), null, null)) + } + + fun testMultipleTopLevelDeclarationsInDifferentDirs() = doTest { rootDir, handler -> + val declarations = listOf("test1/test.kt", "test2/test2.kt").flatMap { getElementsAtCarets(rootDir, it) } + .map { it.getNonStrictParentOfType()!! } + assert(!handler.canMove(declarations.toTypedArray(), null, null)) + + val files = listOf("test1/test.kt", "test2/test2.kt").map { getPsiFile(rootDir, it) } + assert(!handler.canMove(files.toTypedArray(), null, null)) + } + + fun testFileAndTopLevelDeclarations() = doTest { rootDir, handler -> + val elements = getElementsAtCarets(rootDir, "test.kt").map { it.getNonStrictParentOfType()!! } + getPsiFile( + rootDir, + "test2.kt" + ) + assert(!handler.canMove(elements.toTypedArray(), null, null)) + } + + fun testCommonTargets() = doTest { rootDir, handler -> + val elementsToMove = arrayOf(getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType()!!) + + val targetPackage = JavaPsiFacade.getInstance(project).findPackage("pack")!! + assert(handler.canMove(elementsToMove, targetPackage, null)) + + val targetDirectory = getPsiDirectory(rootDir, "pack") + assert(handler.canMove(elementsToMove, targetDirectory, null)) + + val targetFile = getPsiFile(rootDir, "pack/test2.kt") + assert(handler.canMove(elementsToMove, targetFile, null)) + } + + fun testTopLevelClassToClass() = doTest { rootDir, handler -> + val elementsToMove = arrayOf(getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType()!!) + val targetFile = getPsiFile(rootDir, "test2.kt") as KtFile + + val topLevelTarget = targetFile.declarations.firstIsInstance() + assert(topLevelTarget.name == "B") + assert(!handler.canMove(elementsToMove, topLevelTarget, null)) + + val annotationTarget = targetFile.declarations.first { it.name == "Ann" } as KtClass + assert(!handler.canMove(elementsToMove, annotationTarget, null)) + + val nestedTarget = topLevelTarget.declarations.firstIsInstance() + assert(nestedTarget.name == "C") + assert(!handler.canMove(elementsToMove, nestedTarget, null)) + } + + fun testNestedClassToClass() = doTest { rootDir, handler -> + val elementsToMove = arrayOf(getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType()!!) + val targetFile = getPsiFile(rootDir, "test2.kt") as KtFile + + val topLevelTarget = targetFile.declarations.firstIsInstance() + assert(topLevelTarget.name == "B") + assert(handler.canMove(elementsToMove, topLevelTarget, null)) + + val annotationTarget = targetFile.declarations.first { it.name == "Ann" } as KtClass + assert(!handler.canMove(elementsToMove, annotationTarget, null)) + + val nestedTarget = topLevelTarget.declarations.firstIsInstance() + assert(nestedTarget.name == "C") + assert(handler.canMove(elementsToMove, nestedTarget, null)) + } + + fun testTypeAlias() = doTest { rootDir, handler -> + val typeAlias = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType()!! + assert(handler.canMove(arrayOf(typeAlias), null, null)) + } + + fun testTopLevelClassInScript() = doTest { rootDir, handler -> + val klass = getElementAtCaret(rootDir, "test.kts").getNonStrictParentOfType()!! + assert(handler.canMove(arrayOf(klass), null, null)) + } + + fun testTopLevelFunInScript() = doTest { rootDir, handler -> + val function = getElementAtCaret(rootDir, "test.kts").getNonStrictParentOfType()!! + assert(handler.canMove(arrayOf(function), null, null)) + } + + fun testTopLevelValInScript() = doTest { rootDir, handler -> + val property = getElementAtCaret(rootDir, "test.kts").getNonStrictParentOfType()!! + assert(handler.canMove(arrayOf(property), null, null)) + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/run/AbstractRunConfigurationTest.kt.203 b/idea/tests/org/jetbrains/kotlin/idea/run/AbstractRunConfigurationTest.kt.203 new file mode 100644 index 00000000000..ae6f9f20859 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/run/AbstractRunConfigurationTest.kt.203 @@ -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.test.KotlinCodeInsightTestCase +import org.jetbrains.kotlin.idea.test.PluginTestCaseBase.mockJdk +import org.jetbrains.kotlin.idea.util.application.runWriteAction +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 = createTestProjectStructure(project, configModule, srcPath, false) + PsiTestUtil.addSourceRoot(module, srcDir, false) + } else { + srcDir = null + } + + val testPath = "$moduleDir/test" + val testDir: VirtualFile? + + if (File(testPath).exists()) { + testDir = if (srcDir == null) { + createTestProjectStructure(project, configModule, testPath, 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