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 dependencyOnBuiltIns(): DependencyOnBuiltIns = DependenciesOnBuiltIns.LAST
|
||||
val capabilities: Map<ModuleDescriptor.Capability<*>, Any?>
|
||||
get() = emptyMap()
|
||||
get() = mapOf(Capability to this)
|
||||
|
||||
//TODO: (module refactoring) provide dependency on builtins after runtime in IDEA
|
||||
interface DependencyOnBuiltIns {
|
||||
@@ -146,6 +146,10 @@ interface ModuleInfo {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
companion object {
|
||||
val Capability = ModuleDescriptor.Capability<ModuleInfo>("ModuleInfo")
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AnalyzerFacade<in P : PlatformAnalysisParameters> {
|
||||
@@ -271,4 +275,4 @@ interface LanguageSettingsProvider {
|
||||
companion object {
|
||||
fun getInstance(project: Project) = ServiceManager.getService(project, LanguageSettingsProvider::class.java) ?: Default
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ interface IdeaModuleInfo : ModuleInfo {
|
||||
val moduleOrigin: ModuleOrigin
|
||||
|
||||
override val capabilities: Map<ModuleDescriptor.Capability<*>, Any?>
|
||||
get() = mapOf(OriginCapability to moduleOrigin)
|
||||
get() = super.capabilities + mapOf(OriginCapability to moduleOrigin)
|
||||
|
||||
override fun dependencies(): List<IdeaModuleInfo>
|
||||
}
|
||||
@@ -176,7 +176,7 @@ private class ModuleTestSourceScope(module: Module) : ModuleSourceScope(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
|
||||
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 val sourcesModuleInfo: SourceForBinaryModuleInfo
|
||||
get() = LibrarySourceInfo(project, library)
|
||||
|
||||
override fun getLibraryRoots(): Collection<String> =
|
||||
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()
|
||||
}
|
||||
|
||||
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
|
||||
get() = ModuleOrigin.OTHER
|
||||
|
||||
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
|
||||
get() = true
|
||||
@@ -233,6 +238,9 @@ data class LibrarySourceInfo(val project: Project, val library: Library) : IdeaM
|
||||
return listOf(LibraryInfo(project, library))
|
||||
}
|
||||
|
||||
override val binariesModuleInfo: BinaryModuleInfo
|
||||
get() = LibraryInfo(project, library)
|
||||
|
||||
override fun toString() = "LibrarySourceInfo(libraryName=${library.name})"
|
||||
}
|
||||
|
||||
@@ -263,6 +271,8 @@ internal object NotUnderContentRootModuleInfo : IdeaModuleInfo {
|
||||
private class LibraryWithoutSourceScope(project: Project, private val library: Library) :
|
||||
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 hashCode() = library.hashCode()
|
||||
@@ -270,6 +280,18 @@ private class LibraryWithoutSourceScope(project: Project, private val library: L
|
||||
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
|
||||
private class SdkScope(project: Project, private val sdk: Sdk) :
|
||||
LibraryScopeBase(project, sdk.rootProvider.getFiles(OrderRootType.CLASSES), arrayOf<VirtualFile>()) {
|
||||
@@ -290,3 +312,13 @@ enum class ModuleOrigin {
|
||||
LIBRARY,
|
||||
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.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.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
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.textBuilder.DecompiledTextIndexer
|
||||
import org.jetbrains.kotlin.idea.stubindex.*
|
||||
@@ -50,21 +52,16 @@ fun findDecompiledDeclaration(
|
||||
if (isLocal(referencedDescriptor)) 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
|
||||
return decompiledFiles.asSequence().mapNotNull { file ->
|
||||
val moduleInfo = file.getNullableModuleInfo()
|
||||
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 scope = binaryInfo?.binariesScope() ?:
|
||||
// TODO: can't return null right now, have to deal with builtins
|
||||
KotlinSourceFilterScope.libraryClassFiles(EverythingGlobalScope(project), project)
|
||||
|
||||
val decompiledFiles = findDecompiledFilesForDescriptor(project, referencedDescriptor, scope)
|
||||
|
||||
return decompiledFiles.asSequence().mapNotNull {
|
||||
file ->
|
||||
ByDescriptorIndexer.getDeclarationForDescriptor(referencedDescriptor, file)
|
||||
}.firstOrNull()
|
||||
}
|
||||
@@ -80,19 +77,19 @@ private fun isLocal(descriptor: DeclarationDescriptor): Boolean {
|
||||
|
||||
private fun findDecompiledFilesForDescriptor(
|
||||
project: Project,
|
||||
referencedDescriptor: DeclarationDescriptor
|
||||
referencedDescriptor: DeclarationDescriptor,
|
||||
scope: GlobalSearchScope
|
||||
): Collection<KtDecompiledFile> {
|
||||
return findCandidateDeclarationsInIndex(project, referencedDescriptor).mapNotNullTo(LinkedHashSet()) {
|
||||
return findCandidateDeclarationsInIndex(project, referencedDescriptor, scope).mapNotNullTo(LinkedHashSet()) {
|
||||
it?.containingFile as? KtDecompiledFile
|
||||
}
|
||||
}
|
||||
|
||||
private fun findCandidateDeclarationsInIndex(
|
||||
project: Project,
|
||||
referencedDescriptor: DeclarationDescriptor
|
||||
referencedDescriptor: DeclarationDescriptor,
|
||||
scope: GlobalSearchScope
|
||||
): Collection<KtDeclaration?> {
|
||||
val scope = KotlinSourceFilterScope.libraryClassFiles(EverythingGlobalScope(project), project)
|
||||
|
||||
val containingClass = DescriptorUtils.getParentOfType(referencedDescriptor, ClassDescriptor::class.java, false)
|
||||
if (containingClass != null) {
|
||||
return KotlinFullClassNameIndex.getInstance().get(containingClass.fqNameSafe.asString(), project, scope)
|
||||
|
||||
Reference in New Issue
Block a user