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 gnu.trove.THashSet
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.getBinaryLibrariesModuleInfos
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.lexer.KtTokens
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.debugText.getDebugText
@@ -201,20 +199,6 @@ object SourceNavigationHelper {
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? {
// Copied from JavaPsiImplementationHelperImpl:getOriginalClass()
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.PlatformDataKeys
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.*
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.config.TargetPlatformKind
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.stubindex.KotlinClassShortNameIndex
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.KtNamedFunction
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
@@ -39,12 +43,30 @@ import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.BindingContext
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)
return when (target) {
is PsiClass -> target
is KtClassOrObject -> SourceNavigationHelper.getOriginalPsiClassOrCreateLightClass(target)
is KtClassOrObject -> getOriginalPsiClassOrCreateLightClass(target, module)
is KtNamedFunction -> { // Factory methods
val functionName = target.name
val functionDescriptor = target.analyze()[BindingContext.FUNCTION, target] ?: return null
@@ -53,7 +75,7 @@ class KotlinTypeHierarchyProvider : JavaTypeHierarchyProvider() {
if (returnTypeText != functionName) return null
val classOrObject = KotlinClassShortNameIndex.getInstance()[functionName, project, project.allScope()].singleOrNull()
?: return null
SourceNavigationHelper.getOriginalPsiClassOrCreateLightClass(classOrObject)
getOriginalPsiClassOrCreateLightClass(classOrObject, module)
}
else -> null
}
@@ -63,7 +85,7 @@ class KotlinTypeHierarchyProvider : JavaTypeHierarchyProvider() {
val offset = editor.caretModel.offset
val element = file.findElementAt(offset) ?: return null
val classOrObject = element.getNonStrictParentOfType<KtClassOrObject>() ?: return null
return SourceNavigationHelper.getOriginalPsiClassOrCreateLightClass(classOrObject)
return getOriginalPsiClassOrCreateLightClass(classOrObject, file.module)
}
override fun getTarget(dataContext: DataContext): PsiElement? {
@@ -73,11 +95,11 @@ class KotlinTypeHierarchyProvider : JavaTypeHierarchyProvider() {
if (editor != null) {
val file = PsiDocumentManager.getInstance(project).getPsiFile(editor.document) ?: 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)
if (element is KtClassOrObject) return SourceNavigationHelper.getOriginalPsiClassOrCreateLightClass((element as KtClassOrObject?)!!)
if (element is KtClassOrObject) return getOriginalPsiClassOrCreateLightClass(element, element.module)
return null
}