findDecompiledDeclaration: narrow decompiled declaration search scope
Search scope of library that descriptor originated from Introduce API that matches binaries and its' sources via IdeaModuleInfos
This commit is contained in:
@@ -127,7 +127,7 @@ interface ModuleInfo {
|
|||||||
fun modulesWhoseInternalsAreVisible(): Collection<ModuleInfo> = listOf()
|
fun modulesWhoseInternalsAreVisible(): Collection<ModuleInfo> = listOf()
|
||||||
fun dependencyOnBuiltIns(): DependencyOnBuiltIns = DependenciesOnBuiltIns.LAST
|
fun dependencyOnBuiltIns(): DependencyOnBuiltIns = DependenciesOnBuiltIns.LAST
|
||||||
val capabilities: Map<ModuleDescriptor.Capability<*>, Any?>
|
val capabilities: Map<ModuleDescriptor.Capability<*>, Any?>
|
||||||
get() = emptyMap()
|
get() = mapOf(Capability to this)
|
||||||
|
|
||||||
//TODO: (module refactoring) provide dependency on builtins after runtime in IDEA
|
//TODO: (module refactoring) provide dependency on builtins after runtime in IDEA
|
||||||
interface DependencyOnBuiltIns {
|
interface DependencyOnBuiltIns {
|
||||||
@@ -146,6 +146,10 @@ interface ModuleInfo {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val Capability = ModuleDescriptor.Capability<ModuleInfo>("ModuleInfo")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class AnalyzerFacade<in P : PlatformAnalysisParameters> {
|
abstract class AnalyzerFacade<in P : PlatformAnalysisParameters> {
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ interface IdeaModuleInfo : ModuleInfo {
|
|||||||
val moduleOrigin: ModuleOrigin
|
val moduleOrigin: ModuleOrigin
|
||||||
|
|
||||||
override val capabilities: Map<ModuleDescriptor.Capability<*>, Any?>
|
override val capabilities: Map<ModuleDescriptor.Capability<*>, Any?>
|
||||||
get() = mapOf(OriginCapability to moduleOrigin)
|
get() = super.capabilities + mapOf(OriginCapability to moduleOrigin)
|
||||||
|
|
||||||
override fun dependencies(): List<IdeaModuleInfo>
|
override fun dependencies(): List<IdeaModuleInfo>
|
||||||
}
|
}
|
||||||
@@ -176,7 +176,7 @@ private class ModuleTestSourceScope(module: Module) : ModuleSourceScope(module)
|
|||||||
override fun toString() = "ModuleTestSourceScope($module)"
|
override fun toString() = "ModuleTestSourceScope($module)"
|
||||||
}
|
}
|
||||||
|
|
||||||
open class LibraryInfo(val project: Project, val library: Library) : IdeaModuleInfo, LibraryModuleInfo {
|
class LibraryInfo(val project: Project, val library: Library) : IdeaModuleInfo, LibraryModuleInfo, BinaryModuleInfo {
|
||||||
override val moduleOrigin: ModuleOrigin
|
override val moduleOrigin: ModuleOrigin
|
||||||
get() = ModuleOrigin.LIBRARY
|
get() = ModuleOrigin.LIBRARY
|
||||||
|
|
||||||
@@ -201,6 +201,9 @@ open class LibraryInfo(val project: Project, val library: Library) : IdeaModuleI
|
|||||||
|
|
||||||
override fun isJsLibrary(): Boolean = KotlinJavaScriptLibraryDetectionUtil.isKotlinJavaScriptLibrary(library)
|
override fun isJsLibrary(): Boolean = KotlinJavaScriptLibraryDetectionUtil.isKotlinJavaScriptLibrary(library)
|
||||||
|
|
||||||
|
override val sourcesModuleInfo: SourceForBinaryModuleInfo
|
||||||
|
get() = LibrarySourceInfo(project, library)
|
||||||
|
|
||||||
override fun getLibraryRoots(): Collection<String> =
|
override fun getLibraryRoots(): Collection<String> =
|
||||||
library.getFiles(OrderRootType.CLASSES).map(PathUtil::getLocalPath).filterNotNull()
|
library.getFiles(OrderRootType.CLASSES).map(PathUtil::getLocalPath).filterNotNull()
|
||||||
|
|
||||||
@@ -214,13 +217,15 @@ open class LibraryInfo(val project: Project, val library: Library) : IdeaModuleI
|
|||||||
override fun hashCode(): Int = 43 * library.hashCode()
|
override fun hashCode(): Int = 43 * library.hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
data class LibrarySourceInfo(val project: Project, val library: Library) : IdeaModuleInfo {
|
data class LibrarySourceInfo(val project: Project, val library: Library) : IdeaModuleInfo, SourceForBinaryModuleInfo {
|
||||||
override val moduleOrigin: ModuleOrigin
|
override val moduleOrigin: ModuleOrigin
|
||||||
get() = ModuleOrigin.OTHER
|
get() = ModuleOrigin.OTHER
|
||||||
|
|
||||||
override val name: Name = Name.special("<sources for library ${library.name}>")
|
override val name: Name = Name.special("<sources for library ${library.name}>")
|
||||||
|
|
||||||
override fun contentScope() = GlobalSearchScope.EMPTY_SCOPE
|
override fun contentScope(): GlobalSearchScope = GlobalSearchScope.EMPTY_SCOPE
|
||||||
|
|
||||||
|
override fun sourceScope(): GlobalSearchScope = LibrarySourceScope(project, library)
|
||||||
|
|
||||||
override val isLibrary: Boolean
|
override val isLibrary: Boolean
|
||||||
get() = true
|
get() = true
|
||||||
@@ -233,6 +238,9 @@ data class LibrarySourceInfo(val project: Project, val library: Library) : IdeaM
|
|||||||
return listOf(LibraryInfo(project, library))
|
return listOf(LibraryInfo(project, library))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val binariesModuleInfo: BinaryModuleInfo
|
||||||
|
get() = LibraryInfo(project, library)
|
||||||
|
|
||||||
override fun toString() = "LibrarySourceInfo(libraryName=${library.name})"
|
override fun toString() = "LibrarySourceInfo(libraryName=${library.name})"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,6 +271,8 @@ internal object NotUnderContentRootModuleInfo : IdeaModuleInfo {
|
|||||||
private class LibraryWithoutSourceScope(project: Project, private val library: Library) :
|
private class LibraryWithoutSourceScope(project: Project, private val library: Library) :
|
||||||
LibraryScopeBase(project, library.getFiles(OrderRootType.CLASSES), arrayOf<VirtualFile>()) {
|
LibraryScopeBase(project, library.getFiles(OrderRootType.CLASSES), arrayOf<VirtualFile>()) {
|
||||||
|
|
||||||
|
override fun getFileRoot(file: VirtualFile): VirtualFile? = myIndex.getClassRootForFile(file)
|
||||||
|
|
||||||
override fun equals(other: Any?) = other is LibraryWithoutSourceScope && library == other.library
|
override fun equals(other: Any?) = other is LibraryWithoutSourceScope && library == other.library
|
||||||
|
|
||||||
override fun hashCode() = library.hashCode()
|
override fun hashCode() = library.hashCode()
|
||||||
@@ -270,6 +280,18 @@ private class LibraryWithoutSourceScope(project: Project, private val library: L
|
|||||||
override fun toString() = "LibraryWithoutSourceScope($library)"
|
override fun toString() = "LibraryWithoutSourceScope($library)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class LibrarySourceScope(project: Project, private val library: Library) :
|
||||||
|
LibraryScopeBase(project, arrayOf<VirtualFile>(), library.getFiles(OrderRootType.SOURCES)) {
|
||||||
|
|
||||||
|
override fun getFileRoot(file: VirtualFile): VirtualFile? = myIndex.getSourceRootForFile(file)
|
||||||
|
|
||||||
|
override fun equals(other: Any?) = other is LibrarySourceScope && library == other.library
|
||||||
|
|
||||||
|
override fun hashCode() = library.hashCode()
|
||||||
|
|
||||||
|
override fun toString() = "LibrarySourceScope($library)"
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: (module refactoring) android sdk has modified scope
|
//TODO: (module refactoring) android sdk has modified scope
|
||||||
private class SdkScope(project: Project, private val sdk: Sdk) :
|
private class SdkScope(project: Project, private val sdk: Sdk) :
|
||||||
LibraryScopeBase(project, sdk.rootProvider.getFiles(OrderRootType.CLASSES), arrayOf<VirtualFile>()) {
|
LibraryScopeBase(project, sdk.rootProvider.getFiles(OrderRootType.CLASSES), arrayOf<VirtualFile>()) {
|
||||||
@@ -290,3 +312,13 @@ enum class ModuleOrigin {
|
|||||||
LIBRARY,
|
LIBRARY,
|
||||||
OTHER
|
OTHER
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface BinaryModuleInfo : IdeaModuleInfo {
|
||||||
|
val sourcesModuleInfo: SourceForBinaryModuleInfo?
|
||||||
|
fun binariesScope(): GlobalSearchScope = contentScope()
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SourceForBinaryModuleInfo : IdeaModuleInfo {
|
||||||
|
val binariesModuleInfo: BinaryModuleInfo
|
||||||
|
fun sourceScope(): GlobalSearchScope
|
||||||
|
}
|
||||||
+17
-20
@@ -18,11 +18,13 @@ package org.jetbrains.kotlin.idea.decompiler.navigation
|
|||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.search.EverythingGlobalScope
|
import com.intellij.psi.search.EverythingGlobalScope
|
||||||
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
|
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.*
|
import org.jetbrains.kotlin.idea.caches.resolve.BinaryModuleInfo
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.LOG
|
||||||
import org.jetbrains.kotlin.idea.decompiler.KtDecompiledFile
|
import org.jetbrains.kotlin.idea.decompiler.KtDecompiledFile
|
||||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.DecompiledTextIndexer
|
import org.jetbrains.kotlin.idea.decompiler.textBuilder.DecompiledTextIndexer
|
||||||
import org.jetbrains.kotlin.idea.stubindex.*
|
import org.jetbrains.kotlin.idea.stubindex.*
|
||||||
@@ -50,21 +52,16 @@ fun findDecompiledDeclaration(
|
|||||||
if (isLocal(referencedDescriptor)) return null
|
if (isLocal(referencedDescriptor)) return null
|
||||||
if (referencedDescriptor is PackageFragmentDescriptor || referencedDescriptor is PackageViewDescriptor) return null
|
if (referencedDescriptor is PackageFragmentDescriptor || referencedDescriptor is PackageViewDescriptor) return null
|
||||||
|
|
||||||
val decompiledFiles = findDecompiledFilesForDescriptor(project, referencedDescriptor)
|
val binaryInfo = referencedDescriptor.module.getCapability(ModuleInfo.Capability) as? BinaryModuleInfo
|
||||||
|
|
||||||
val referencedModule = referencedDescriptor.module
|
val scope = binaryInfo?.binariesScope() ?:
|
||||||
return decompiledFiles.asSequence().mapNotNull { file ->
|
// TODO: can't return null right now, have to deal with builtins
|
||||||
val moduleInfo = file.getNullableModuleInfo()
|
KotlinSourceFilterScope.libraryClassFiles(EverythingGlobalScope(project), project)
|
||||||
val libraryInfo = when (moduleInfo) {
|
|
||||||
is LibraryInfo -> moduleInfo
|
|
||||||
is LibrarySourceInfo -> LibraryInfo(project, moduleInfo.library)
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
val libraryModule = libraryInfo?.let { file.getResolutionFacade().findModuleDescriptor(it) }
|
|
||||||
if (libraryModule != null
|
|
||||||
&& referencedModule.name != KotlinBuiltIns.BUILTINS_MODULE_NAME
|
|
||||||
&& referencedModule.name != libraryModule.name) return@mapNotNull null
|
|
||||||
|
|
||||||
|
val decompiledFiles = findDecompiledFilesForDescriptor(project, referencedDescriptor, scope)
|
||||||
|
|
||||||
|
return decompiledFiles.asSequence().mapNotNull {
|
||||||
|
file ->
|
||||||
ByDescriptorIndexer.getDeclarationForDescriptor(referencedDescriptor, file)
|
ByDescriptorIndexer.getDeclarationForDescriptor(referencedDescriptor, file)
|
||||||
}.firstOrNull()
|
}.firstOrNull()
|
||||||
}
|
}
|
||||||
@@ -80,19 +77,19 @@ private fun isLocal(descriptor: DeclarationDescriptor): Boolean {
|
|||||||
|
|
||||||
private fun findDecompiledFilesForDescriptor(
|
private fun findDecompiledFilesForDescriptor(
|
||||||
project: Project,
|
project: Project,
|
||||||
referencedDescriptor: DeclarationDescriptor
|
referencedDescriptor: DeclarationDescriptor,
|
||||||
|
scope: GlobalSearchScope
|
||||||
): Collection<KtDecompiledFile> {
|
): Collection<KtDecompiledFile> {
|
||||||
return findCandidateDeclarationsInIndex(project, referencedDescriptor).mapNotNullTo(LinkedHashSet()) {
|
return findCandidateDeclarationsInIndex(project, referencedDescriptor, scope).mapNotNullTo(LinkedHashSet()) {
|
||||||
it?.containingFile as? KtDecompiledFile
|
it?.containingFile as? KtDecompiledFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findCandidateDeclarationsInIndex(
|
private fun findCandidateDeclarationsInIndex(
|
||||||
project: Project,
|
project: Project,
|
||||||
referencedDescriptor: DeclarationDescriptor
|
referencedDescriptor: DeclarationDescriptor,
|
||||||
|
scope: GlobalSearchScope
|
||||||
): Collection<KtDeclaration?> {
|
): Collection<KtDeclaration?> {
|
||||||
val scope = KotlinSourceFilterScope.libraryClassFiles(EverythingGlobalScope(project), project)
|
|
||||||
|
|
||||||
val containingClass = DescriptorUtils.getParentOfType(referencedDescriptor, ClassDescriptor::class.java, false)
|
val containingClass = DescriptorUtils.getParentOfType(referencedDescriptor, ClassDescriptor::class.java, false)
|
||||||
if (containingClass != null) {
|
if (containingClass != null) {
|
||||||
return KotlinFullClassNameIndex.getInstance().get(containingClass.fqNameSafe.asString(), project, scope)
|
return KotlinFullClassNameIndex.getInstance().get(containingClass.fqNameSafe.asString(), project, scope)
|
||||||
|
|||||||
Reference in New Issue
Block a user