203: Fix compilation

This commit is contained in:
Florian Kistner
2020-08-05 19:34:35 +02:00
parent c792092410
commit 9925866293
6 changed files with 497 additions and 6 deletions
@@ -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()
}
}
@@ -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 = "&nbsp;&nbsp;&nbsp;&nbsp;{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())
}
@@ -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)
@@ -105,13 +105,14 @@ abstract class AbstractConfigureKotlinTest : PlatformTestCase() {
val modules: Array<Module>
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
}
@@ -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()
}