Type Hierarchy: Do not use JVM class mapping in non-JVM modules

#KT-21424 In Progress
This commit is contained in:
Alexey Sedunov
2018-01-25 20:01:42 +03:00
parent 089b34a8a9
commit 7f97d58970
2 changed files with 33 additions and 27 deletions
@@ -18,7 +18,6 @@ import com.intellij.psi.stubs.StringStubIndexExtension
import com.intellij.util.containers.ContainerUtil import com.intellij.util.containers.ContainerUtil
import gnu.trove.THashSet import gnu.trove.THashSet
import org.jetbrains.annotations.TestOnly import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.getBinaryLibrariesModuleInfos import org.jetbrains.kotlin.idea.caches.resolve.getBinaryLibrariesModuleInfos
import org.jetbrains.kotlin.idea.caches.resolve.getLibrarySourcesModuleInfos import org.jetbrains.kotlin.idea.caches.resolve.getLibrarySourcesModuleInfos
@@ -31,7 +30,6 @@ import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelTypeAliasFqNameIndex
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.debugText.getDebugText import org.jetbrains.kotlin.psi.debugText.getDebugText
@@ -201,20 +199,6 @@ object SourceNavigationHelper {
name == declaration.nameAsSafeName name == declaration.nameAsSafeName
} }
fun getOriginalPsiClassOrCreateLightClass(classOrObject: KtClassOrObject): PsiClass? {
val fqName = classOrObject.fqName
if (fqName != null) {
val javaClassId = JavaToKotlinClassMap.mapKotlinToJava(fqName.toUnsafe())
if (javaClassId != null) {
return JavaPsiFacade.getInstance(classOrObject.project).findClass(
javaClassId.asSingleFqName().asString(),
GlobalSearchScope.allScope(classOrObject.project)
)
}
}
return classOrObject.toLightClass()
}
fun getOriginalClass(classOrObject: KtClassOrObject): PsiClass? { fun getOriginalClass(classOrObject: KtClassOrObject): PsiClass? {
// Copied from JavaPsiImplementationHelperImpl:getOriginalClass() // Copied from JavaPsiImplementationHelperImpl:getOriginalClass()
val fqName = classOrObject.fqName ?: return null val fqName = classOrObject.fqName ?: return null
@@ -22,16 +22,20 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.actionSystem.LangDataKeys import com.intellij.openapi.actionSystem.LangDataKeys
import com.intellij.openapi.actionSystem.PlatformDataKeys import com.intellij.openapi.actionSystem.PlatformDataKeys
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.psi.PsiClass import com.intellij.psi.*
import com.intellij.psi.PsiDocumentManager import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.PsiElement import org.jetbrains.kotlin.asJava.toLightClass
import com.intellij.psi.PsiFile import org.jetbrains.kotlin.config.TargetPlatformKind
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.decompiler.navigation.SourceNavigationHelper import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightClass
import org.jetbrains.kotlin.idea.project.targetPlatform
import org.jetbrains.kotlin.idea.search.allScope import org.jetbrains.kotlin.idea.search.allScope
import org.jetbrains.kotlin.idea.stubindex.KotlinClassShortNameIndex import org.jetbrains.kotlin.idea.stubindex.KotlinClassShortNameIndex
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.idea.util.module
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
@@ -39,12 +43,30 @@ import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
class KotlinTypeHierarchyProvider : JavaTypeHierarchyProvider() { class KotlinTypeHierarchyProvider : JavaTypeHierarchyProvider() {
private fun getTargetByReference(project: Project, editor: Editor): PsiElement? { private fun getOriginalPsiClassOrCreateLightClass(classOrObject: KtClassOrObject, module: Module?): PsiClass? {
val fqName = classOrObject.fqName
if (fqName != null && module?.targetPlatform is TargetPlatformKind.Jvm) {
val javaClassId = JavaToKotlinClassMap.mapKotlinToJava(fqName.toUnsafe())
if (javaClassId != null) {
return JavaPsiFacade.getInstance(classOrObject.project).findClass(
javaClassId.asSingleFqName().asString(),
GlobalSearchScope.allScope(classOrObject.project)
)
}
}
return classOrObject.toLightClass() ?: KtFakeLightClass(classOrObject)
}
private fun getTargetByReference(
project: Project,
editor: Editor,
module: Module?
): PsiElement? {
val target = TargetElementUtil.findTargetElement(editor, TargetElementUtil.getInstance().allAccepted) val target = TargetElementUtil.findTargetElement(editor, TargetElementUtil.getInstance().allAccepted)
return when (target) { return when (target) {
is PsiClass -> target is PsiClass -> target
is KtClassOrObject -> SourceNavigationHelper.getOriginalPsiClassOrCreateLightClass(target) is KtClassOrObject -> getOriginalPsiClassOrCreateLightClass(target, module)
is KtNamedFunction -> { // Factory methods is KtNamedFunction -> { // Factory methods
val functionName = target.name val functionName = target.name
val functionDescriptor = target.analyze()[BindingContext.FUNCTION, target] ?: return null val functionDescriptor = target.analyze()[BindingContext.FUNCTION, target] ?: return null
@@ -53,7 +75,7 @@ class KotlinTypeHierarchyProvider : JavaTypeHierarchyProvider() {
if (returnTypeText != functionName) return null if (returnTypeText != functionName) return null
val classOrObject = KotlinClassShortNameIndex.getInstance()[functionName, project, project.allScope()].singleOrNull() val classOrObject = KotlinClassShortNameIndex.getInstance()[functionName, project, project.allScope()].singleOrNull()
?: return null ?: return null
SourceNavigationHelper.getOriginalPsiClassOrCreateLightClass(classOrObject) getOriginalPsiClassOrCreateLightClass(classOrObject, module)
} }
else -> null else -> null
} }
@@ -63,7 +85,7 @@ class KotlinTypeHierarchyProvider : JavaTypeHierarchyProvider() {
val offset = editor.caretModel.offset val offset = editor.caretModel.offset
val element = file.findElementAt(offset) ?: return null val element = file.findElementAt(offset) ?: return null
val classOrObject = element.getNonStrictParentOfType<KtClassOrObject>() ?: return null val classOrObject = element.getNonStrictParentOfType<KtClassOrObject>() ?: return null
return SourceNavigationHelper.getOriginalPsiClassOrCreateLightClass(classOrObject) return getOriginalPsiClassOrCreateLightClass(classOrObject, file.module)
} }
override fun getTarget(dataContext: DataContext): PsiElement? { override fun getTarget(dataContext: DataContext): PsiElement? {
@@ -73,11 +95,11 @@ class KotlinTypeHierarchyProvider : JavaTypeHierarchyProvider() {
if (editor != null) { if (editor != null) {
val file = PsiDocumentManager.getInstance(project).getPsiFile(editor.document) ?: return null val file = PsiDocumentManager.getInstance(project).getPsiFile(editor.document) ?: return null
if (!ProjectRootsUtil.isInProjectOrLibSource(file)) return null if (!ProjectRootsUtil.isInProjectOrLibSource(file)) return null
return getTargetByReference(project, editor) ?: getTargetByContainingElement(editor, file) return getTargetByReference(project, editor, file.module) ?: getTargetByContainingElement(editor, file)
} }
val element = LangDataKeys.PSI_ELEMENT.getData(dataContext) val element = LangDataKeys.PSI_ELEMENT.getData(dataContext)
if (element is KtClassOrObject) return SourceNavigationHelper.getOriginalPsiClassOrCreateLightClass((element as KtClassOrObject?)!!) if (element is KtClassOrObject) return getOriginalPsiClassOrCreateLightClass(element, element.module)
return null return null
} }