DecompiledNavigationUtils -> findDecompiledDeclaration()
This commit is contained in:
+4
-10
@@ -18,16 +18,10 @@ package org.jetbrains.kotlin.idea.codeInsight
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.idea.decompiler.navigation.DecompiledNavigationUtils
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.idea.decompiler.navigation.findDecompiledDeclaration
|
||||
import org.jetbrains.kotlin.idea.references.BuiltInsReferenceResolver
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import org.jetbrains.kotlin.idea.search.allScope
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.*
|
||||
import java.util.*
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.sequenceOfLazyValues
|
||||
|
||||
public object DescriptorToSourceUtilsIde {
|
||||
@@ -52,7 +46,7 @@ public object DescriptorToSourceUtilsIde {
|
||||
// therefore we put both source declaration and decompiled declaration to stream, and afterwards we filter it in getAllDeclarations
|
||||
sequenceOfLazyValues(
|
||||
{ DescriptorToSourceUtils.getSourceFromDescriptor(effectiveReferenced) },
|
||||
{ BuiltInsReferenceResolver.resolveBuiltInSymbol(project, effectiveReferenced) ?: DecompiledNavigationUtils.getDeclarationFromDecompiledClassFile(project, effectiveReferenced) }
|
||||
{ BuiltInsReferenceResolver.resolveBuiltInSymbol(project, effectiveReferenced) ?: findDecompiledDeclaration(project, effectiveReferenced) }
|
||||
)
|
||||
}.filterNotNull()
|
||||
}
|
||||
|
||||
+86
-89
@@ -39,97 +39,94 @@ import org.jetbrains.kotlin.serialization.js.KotlinJavascriptPackageFragment
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
||||
|
||||
object DecompiledNavigationUtils {
|
||||
fun findDecompiledDeclaration(
|
||||
project: Project,
|
||||
referencedDescriptor: DeclarationDescriptor): KtDeclaration? {
|
||||
if (isLocal(referencedDescriptor)) return null
|
||||
|
||||
fun getDeclarationFromDecompiledClassFile(
|
||||
project: Project,
|
||||
referencedDescriptor: DeclarationDescriptor): KtDeclaration? {
|
||||
if (isLocal(referencedDescriptor)) return null
|
||||
val virtualFile = findVirtualFileContainingDescriptor(project, referencedDescriptor) ?: return null
|
||||
|
||||
val virtualFile = findVirtualFileContainingDescriptor(project, referencedDescriptor) ?: return null
|
||||
|
||||
val psiFile = PsiManager.getInstance(project).findFile(virtualFile)
|
||||
if (psiFile !is KtDecompiledFile) {
|
||||
return null
|
||||
}
|
||||
|
||||
return psiFile.getDeclarationForDescriptor(referencedDescriptor)
|
||||
}
|
||||
|
||||
private fun isLocal(descriptor: DeclarationDescriptor): Boolean {
|
||||
if (descriptor is ParameterDescriptor) {
|
||||
return isLocal(descriptor.containingDeclaration)
|
||||
}
|
||||
else {
|
||||
return DescriptorUtils.isLocal(descriptor)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Find virtual file which contains the declaration of descriptor we're navigating to.
|
||||
*/
|
||||
private fun findVirtualFileContainingDescriptor(
|
||||
project: Project,
|
||||
referencedDescriptor: DeclarationDescriptor): VirtualFile? {
|
||||
if (ErrorUtils.isError(referencedDescriptor)) return null
|
||||
|
||||
val containerClassId = getContainerClassId(project, referencedDescriptor) ?: return null
|
||||
|
||||
val scopeToSearchIn = KotlinSourceFilterScope.sourceAndClassFiles(GlobalSearchScope.allScope(project), project)
|
||||
|
||||
val virtualFileFinderFactory: VirtualFileFinderFactory
|
||||
if (isFromKotlinJavasriptMetadata(referencedDescriptor)) {
|
||||
virtualFileFinderFactory = JsVirtualFileFinderFactory.SERVICE.getInstance(project)
|
||||
}
|
||||
else {
|
||||
virtualFileFinderFactory = JvmVirtualFileFinderFactory.SERVICE.getInstance(project)
|
||||
}
|
||||
|
||||
val fileFinder = virtualFileFinderFactory.create(scopeToSearchIn)
|
||||
return fileFinder.findVirtualFileWithHeader(containerClassId)
|
||||
}
|
||||
|
||||
private fun isFromKotlinJavasriptMetadata(referencedDescriptor: DeclarationDescriptor): Boolean {
|
||||
val packageFragmentDescriptor = DescriptorUtils.getParentOfType(referencedDescriptor, PackageFragmentDescriptor::class.java, false)
|
||||
return packageFragmentDescriptor is KotlinJavascriptPackageFragment
|
||||
}
|
||||
|
||||
//TODO: navigate to inner classes
|
||||
//TODO: should we construct proper SourceElement's for decompiled parts / facades?
|
||||
private fun getContainerClassId(project: Project, referencedDescriptor: DeclarationDescriptor): ClassId? {
|
||||
val deserializedCallableContainer = DescriptorUtils.getParentOfType(referencedDescriptor, DeserializedCallableMemberDescriptor::class.java, true)
|
||||
if (deserializedCallableContainer != null) {
|
||||
return getContainerClassId(project, deserializedCallableContainer)
|
||||
}
|
||||
|
||||
val containerDescriptor = DescriptorUtils.getParentOfType(referencedDescriptor, ClassOrPackageFragmentDescriptor::class.java, false)
|
||||
if (containerDescriptor is PackageFragmentDescriptor) {
|
||||
val packageFQN = containerDescriptor.fqName
|
||||
|
||||
if (referencedDescriptor is DeserializedCallableMemberDescriptor) {
|
||||
val partClassName = JvmFileClassUtil.getImplClassName(referencedDescriptor)
|
||||
if (partClassName != null) {
|
||||
val partFQN = packageFQN.child(partClassName)
|
||||
val multifileFacadeJetFiles = StaticFacadeIndexUtil.getMultifileClassForPart(partFQN, GlobalSearchScope.allScope(project), project)
|
||||
if (multifileFacadeJetFiles.isEmpty()) {
|
||||
return ClassId(packageFQN, partClassName)
|
||||
}
|
||||
else {
|
||||
val multifileFacade = multifileFacadeJetFiles.iterator().next()
|
||||
val multifileFacadeName = multifileFacade.virtualFile.nameWithoutExtension
|
||||
return ClassId(packageFQN, Name.identifier(multifileFacadeName))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return getPackageClassId(packageFQN)
|
||||
}
|
||||
if (containerDescriptor is ClassDescriptor) {
|
||||
if (containerDescriptor.containingDeclaration is ClassDescriptor || ExpressionTypingUtils.isLocal(containerDescriptor.containingDeclaration, containerDescriptor)) {
|
||||
return getContainerClassId(project, containerDescriptor.containingDeclaration)
|
||||
}
|
||||
return containerDescriptor.classId
|
||||
}
|
||||
val psiFile = PsiManager.getInstance(project).findFile(virtualFile)
|
||||
if (psiFile !is KtDecompiledFile) {
|
||||
return null
|
||||
}
|
||||
|
||||
return psiFile.getDeclarationForDescriptor(referencedDescriptor)
|
||||
}
|
||||
|
||||
private fun isLocal(descriptor: DeclarationDescriptor): Boolean {
|
||||
if (descriptor is ParameterDescriptor) {
|
||||
return isLocal(descriptor.containingDeclaration)
|
||||
}
|
||||
else {
|
||||
return DescriptorUtils.isLocal(descriptor)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Find virtual file which contains the declaration of descriptor we're navigating to.
|
||||
*/
|
||||
private fun findVirtualFileContainingDescriptor(
|
||||
project: Project,
|
||||
referencedDescriptor: DeclarationDescriptor): VirtualFile? {
|
||||
if (ErrorUtils.isError(referencedDescriptor)) return null
|
||||
|
||||
val containerClassId = getContainerClassId(project, referencedDescriptor) ?: return null
|
||||
|
||||
val scopeToSearchIn = KotlinSourceFilterScope.sourceAndClassFiles(GlobalSearchScope.allScope(project), project)
|
||||
|
||||
val virtualFileFinderFactory: VirtualFileFinderFactory
|
||||
if (isFromKotlinJavasriptMetadata(referencedDescriptor)) {
|
||||
virtualFileFinderFactory = JsVirtualFileFinderFactory.SERVICE.getInstance(project)
|
||||
}
|
||||
else {
|
||||
virtualFileFinderFactory = JvmVirtualFileFinderFactory.SERVICE.getInstance(project)
|
||||
}
|
||||
|
||||
val fileFinder = virtualFileFinderFactory.create(scopeToSearchIn)
|
||||
return fileFinder.findVirtualFileWithHeader(containerClassId)
|
||||
}
|
||||
|
||||
private fun isFromKotlinJavasriptMetadata(referencedDescriptor: DeclarationDescriptor): Boolean {
|
||||
val packageFragmentDescriptor = DescriptorUtils.getParentOfType(referencedDescriptor, PackageFragmentDescriptor::class.java, false)
|
||||
return packageFragmentDescriptor is KotlinJavascriptPackageFragment
|
||||
}
|
||||
|
||||
//TODO: navigate to inner classes
|
||||
//TODO: should we construct proper SourceElement's for decompiled parts / facades?
|
||||
private fun getContainerClassId(project: Project, referencedDescriptor: DeclarationDescriptor): ClassId? {
|
||||
val deserializedCallableContainer = DescriptorUtils.getParentOfType(referencedDescriptor, DeserializedCallableMemberDescriptor::class.java, true)
|
||||
if (deserializedCallableContainer != null) {
|
||||
return getContainerClassId(project, deserializedCallableContainer)
|
||||
}
|
||||
|
||||
val containerDescriptor = DescriptorUtils.getParentOfType(referencedDescriptor, ClassOrPackageFragmentDescriptor::class.java, false)
|
||||
if (containerDescriptor is PackageFragmentDescriptor) {
|
||||
val packageFQN = containerDescriptor.fqName
|
||||
|
||||
if (referencedDescriptor is DeserializedCallableMemberDescriptor) {
|
||||
val partClassName = JvmFileClassUtil.getImplClassName(referencedDescriptor)
|
||||
if (partClassName != null) {
|
||||
val partFQN = packageFQN.child(partClassName)
|
||||
val multifileFacadeJetFiles = StaticFacadeIndexUtil.getMultifileClassForPart(partFQN, GlobalSearchScope.allScope(project), project)
|
||||
if (multifileFacadeJetFiles.isEmpty()) {
|
||||
return ClassId(packageFQN, partClassName)
|
||||
}
|
||||
else {
|
||||
val multifileFacade = multifileFacadeJetFiles.iterator().next()
|
||||
val multifileFacadeName = multifileFacade.virtualFile.nameWithoutExtension
|
||||
return ClassId(packageFQN, Name.identifier(multifileFacadeName))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return getPackageClassId(packageFQN)
|
||||
}
|
||||
if (containerDescriptor is ClassDescriptor) {
|
||||
if (containerDescriptor.containingDeclaration is ClassDescriptor || ExpressionTypingUtils.isLocal(containerDescriptor.containingDeclaration, containerDescriptor)) {
|
||||
return getContainerClassId(project, containerDescriptor.containingDeclaration)
|
||||
}
|
||||
return containerDescriptor.classId
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user