203: Fix compilation
This commit is contained in:
+70
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
+132
@@ -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<PsiClass>(5)
|
||||||
|
|
||||||
|
val consumer = AdapterProcessor<PsiMethod, PsiClass>(
|
||||||
|
CommonProcessors.UniqueProcessor<PsiClass>(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<PsiElement>()
|
||||||
|
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<NavigatablePsiElement>()
|
||||||
|
|
||||||
|
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())
|
||||||
|
}
|
||||||
|
|
||||||
+2
-2
@@ -12,10 +12,10 @@ import java.io.File
|
|||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
||||||
abstract class AbstractConfigureKotlinInTempDirTest : AbstractConfigureKotlinTest() {
|
abstract class AbstractConfigureKotlinInTempDirTest : AbstractConfigureKotlinTest() {
|
||||||
override fun getProjectDirOrFile(): Path {
|
override fun getProjectDirOrFile(isDirectoryBasedProject: Boolean): Path {
|
||||||
val tempDir = FileUtil.generateRandomTemporaryPath()
|
val tempDir = FileUtil.generateRandomTemporaryPath()
|
||||||
FileUtil.createTempDirectory("temp", null)
|
FileUtil.createTempDirectory("temp", null)
|
||||||
myFilesToDelete.add(tempDir.toPath())
|
getTempDir().scheduleDelete(tempDir.toPath())
|
||||||
|
|
||||||
FileUtil.copyDir(File(projectRoot), tempDir)
|
FileUtil.copyDir(File(projectRoot), tempDir)
|
||||||
|
|
||||||
|
|||||||
+5
-4
@@ -105,13 +105,14 @@ abstract class AbstractConfigureKotlinTest : PlatformTestCase() {
|
|||||||
val modules: Array<Module>
|
val modules: Array<Module>
|
||||||
get() = ModuleManager.getInstance(myProject).modules
|
get() = ModuleManager.getInstance(myProject).modules
|
||||||
|
|
||||||
override fun getProjectDirOrFile(): Path {
|
override fun getProjectDirOrFile(isDirectoryBasedProject: Boolean): Path {
|
||||||
val projectFilePath = projectRoot + "/projectFile.ipr"
|
val projectFilePath = projectRoot + "/projectFile.ipr"
|
||||||
TestCase.assertTrue("Project file should exists " + projectFilePath, File(projectFilePath).exists())
|
TestCase.assertTrue("Project file should exists " + projectFilePath, File(projectFilePath).exists())
|
||||||
return File(projectFilePath).toPath()
|
return File(projectFilePath).toPath()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun doCreateAndOpenProject(projectFile: Path): Project {
|
override fun doCreateAndOpenProject(): Project {
|
||||||
|
val projectFile = getProjectDirOrFile(isCreateDirectoryBasedProject)
|
||||||
return loadProjectCompat(projectFile)
|
return loadProjectCompat(projectFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,14 +239,14 @@ abstract class AbstractConfigureKotlinTest : PlatformTestCase() {
|
|||||||
private val pathToNonexistentRuntimeJar: String
|
private val pathToNonexistentRuntimeJar: String
|
||||||
get() {
|
get() {
|
||||||
val pathToTempKotlinRuntimeJar = FileUtil.getTempDirectory() + "/" + PathUtil.KOTLIN_JAVA_STDLIB_JAR
|
val pathToTempKotlinRuntimeJar = FileUtil.getTempDirectory() + "/" + PathUtil.KOTLIN_JAVA_STDLIB_JAR
|
||||||
myFilesToDelete.add(Paths.get(pathToTempKotlinRuntimeJar))
|
tempDir.scheduleDelete(Paths.get(pathToTempKotlinRuntimeJar))
|
||||||
return pathToTempKotlinRuntimeJar
|
return pathToTempKotlinRuntimeJar
|
||||||
}
|
}
|
||||||
|
|
||||||
private val pathToNonexistentJsJar: String
|
private val pathToNonexistentJsJar: String
|
||||||
get() {
|
get() {
|
||||||
val pathToTempKotlinRuntimeJar = FileUtil.getTempDirectory() + "/" + PathUtil.JS_LIB_JAR_NAME
|
val pathToTempKotlinRuntimeJar = FileUtil.getTempDirectory() + "/" + PathUtil.JS_LIB_JAR_NAME
|
||||||
myFilesToDelete.add(Paths.get(pathToTempKotlinRuntimeJar))
|
tempDir.scheduleDelete(Paths.get(pathToTempKotlinRuntimeJar))
|
||||||
return pathToTempKotlinRuntimeJar
|
return pathToTempKotlinRuntimeJar
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+211
@@ -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<PsiElement> {
|
||||||
|
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<KtObjectDeclaration>()!!
|
||||||
|
assert(!handler.canMove(arrayOf<PsiElement>(objectDeclaration), null, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testLocalClass() = doTest { rootDir, handler ->
|
||||||
|
val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!
|
||||||
|
assert(!handler.canMove(arrayOf<PsiElement>(klass), null, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testLocalFun() = doTest { rootDir, handler ->
|
||||||
|
val function = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtNamedFunction>()!!
|
||||||
|
assert(!handler.canMove(arrayOf<PsiElement>(function), null, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testLocalVal() = doTest { rootDir, handler ->
|
||||||
|
val property = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtProperty>()!!
|
||||||
|
assert(!handler.canMove(arrayOf<PsiElement>(property), null, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testMemberFun() = doTest { rootDir, handler ->
|
||||||
|
val function = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtNamedFunction>()!!
|
||||||
|
assert(!handler.canMove(arrayOf<PsiElement>(function), null, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testMemberVal() = doTest { rootDir, handler ->
|
||||||
|
val property = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtProperty>()!!
|
||||||
|
assert(!handler.canMove(arrayOf<PsiElement>(property), null, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testNestedClass() = doTest { rootDir, handler ->
|
||||||
|
val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!
|
||||||
|
assert(handler.canMove(arrayOf<PsiElement>(klass), null, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testInnerClass() = doTest { rootDir, handler ->
|
||||||
|
val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!
|
||||||
|
assert(handler.canMove(arrayOf<PsiElement>(klass), null, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testTopLevelClass() = doTest { rootDir, handler ->
|
||||||
|
val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!
|
||||||
|
assert(handler.canMove(arrayOf<PsiElement>(klass), null, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testTopLevelFun() = doTest { rootDir, handler ->
|
||||||
|
val function = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtNamedFunction>()!!
|
||||||
|
assert(handler.canMove(arrayOf<PsiElement>(function), null, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testTopLevelVal() = doTest { rootDir, handler ->
|
||||||
|
val property = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtProperty>()!!
|
||||||
|
assert(handler.canMove(arrayOf<PsiElement>(property), null, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testMultipleNestedClasses() = doTest { rootDir, handler ->
|
||||||
|
val classes = getElementsAtCarets(rootDir, "test.kt").map { it.getNonStrictParentOfType<KtClass>()!! }
|
||||||
|
assert(handler.canMove(classes.toTypedArray(), null, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testNestedAndTopLevelClass() = doTest { rootDir, handler ->
|
||||||
|
val classes = getElementsAtCarets(rootDir, "test.kt").map { it.getNonStrictParentOfType<KtClass>()!! }
|
||||||
|
assert(!handler.canMove(classes.toTypedArray(), null, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testMultipleTopLevelDeclarations() = doTest { rootDir, handler ->
|
||||||
|
val declarations = getElementsAtCarets(rootDir, "test.kt").map { it.getNonStrictParentOfType<KtNamedDeclaration>()!! }
|
||||||
|
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<KtNamedDeclaration>()!! }
|
||||||
|
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<KtNamedDeclaration>()!! }
|
||||||
|
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<KtNamedDeclaration>()!! } + getPsiFile(
|
||||||
|
rootDir,
|
||||||
|
"test2.kt"
|
||||||
|
)
|
||||||
|
assert(!handler.canMove(elements.toTypedArray(), null, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testCommonTargets() = doTest { rootDir, handler ->
|
||||||
|
val elementsToMove = arrayOf<PsiElement>(getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!)
|
||||||
|
|
||||||
|
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<PsiElement>(getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!)
|
||||||
|
val targetFile = getPsiFile(rootDir, "test2.kt") as KtFile
|
||||||
|
|
||||||
|
val topLevelTarget = targetFile.declarations.firstIsInstance<KtClass>()
|
||||||
|
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<KtClass>()
|
||||||
|
assert(nestedTarget.name == "C")
|
||||||
|
assert(!handler.canMove(elementsToMove, nestedTarget, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testNestedClassToClass() = doTest { rootDir, handler ->
|
||||||
|
val elementsToMove = arrayOf<PsiElement>(getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!)
|
||||||
|
val targetFile = getPsiFile(rootDir, "test2.kt") as KtFile
|
||||||
|
|
||||||
|
val topLevelTarget = targetFile.declarations.firstIsInstance<KtClass>()
|
||||||
|
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<KtClass>()
|
||||||
|
assert(nestedTarget.name == "C")
|
||||||
|
assert(handler.canMove(elementsToMove, nestedTarget, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testTypeAlias() = doTest { rootDir, handler ->
|
||||||
|
val typeAlias = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtTypeAlias>()!!
|
||||||
|
assert(handler.canMove(arrayOf<PsiElement>(typeAlias), null, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testTopLevelClassInScript() = doTest { rootDir, handler ->
|
||||||
|
val klass = getElementAtCaret(rootDir, "test.kts").getNonStrictParentOfType<KtClass>()!!
|
||||||
|
assert(handler.canMove(arrayOf<PsiElement>(klass), null, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testTopLevelFunInScript() = doTest { rootDir, handler ->
|
||||||
|
val function = getElementAtCaret(rootDir, "test.kts").getNonStrictParentOfType<KtNamedFunction>()!!
|
||||||
|
assert(handler.canMove(arrayOf<PsiElement>(function), null, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testTopLevelValInScript() = doTest { rootDir, handler ->
|
||||||
|
val property = getElementAtCaret(rootDir, "test.kts").getNonStrictParentOfType<KtProperty>()!!
|
||||||
|
assert(handler.canMove(arrayOf<PsiElement>(property), null, null))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user