diff --git a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt index 5b5f7a069ca..f6f7438660b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt @@ -127,7 +127,7 @@ interface ModuleInfo { fun modulesWhoseInternalsAreVisible(): Collection = listOf() fun dependencyOnBuiltIns(): DependencyOnBuiltIns = DependenciesOnBuiltIns.LAST val capabilities: Map, 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") + } } abstract class AnalyzerFacade { @@ -271,4 +275,4 @@ interface LanguageSettingsProvider { companion object { fun getInstance(project: Project) = ServiceManager.getService(project, LanguageSettingsProvider::class.java) ?: Default } -} +} \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IdeaModuleInfos.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IdeaModuleInfos.kt index 4dc46cae396..35c74270c61 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IdeaModuleInfos.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IdeaModuleInfos.kt @@ -44,7 +44,7 @@ interface IdeaModuleInfo : ModuleInfo { val moduleOrigin: ModuleOrigin override val capabilities: Map, Any?> - get() = mapOf(OriginCapability to moduleOrigin) + get() = super.capabilities + mapOf(OriginCapability to moduleOrigin) override fun dependencies(): List } @@ -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 = 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("") - 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()) { + 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(), 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()) { @@ -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 +} \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/navigation/findDecompiledDeclaration.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/navigation/findDecompiledDeclaration.kt index 29064734d7a..886014b1ef8 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/navigation/findDecompiledDeclaration.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/navigation/findDecompiledDeclaration.kt @@ -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 { - 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 { - 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)