From df95602e06e688eeea5bb3edee3fe58f49a37fb1 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Tue, 6 Sep 2022 11:12:53 -0700 Subject: [PATCH] AA: populate index for built-ins --- .../AnalysisApiBaseTestServiceRegistrar.kt | 2 +- .../analysis-api-providers/build.gradle.kts | 2 + .../impl/KotlinStaticDeclarationProvider.kt | 162 ++++++++++++++---- .../StandaloneAnalysisAPISessionBuilder.kt | 9 +- .../api/standalone/StandaloneUtils.kt | 2 +- 5 files changed, 136 insertions(+), 41 deletions(-) diff --git a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/configurators/AnalysisApiBaseTestServiceRegistrar.kt b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/configurators/AnalysisApiBaseTestServiceRegistrar.kt index 6f4d89c921f..b86d7c60f3e 100644 --- a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/configurators/AnalysisApiBaseTestServiceRegistrar.kt +++ b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/configurators/AnalysisApiBaseTestServiceRegistrar.kt @@ -40,7 +40,7 @@ object AnalysisApiBaseTestServiceRegistrar: AnalysisApiTestServiceRegistrar() { registerService(KtModuleScopeProvider::class.java, KtModuleScopeProviderImpl()) registerService(KotlinAnnotationsResolverFactory::class.java, KotlinStaticAnnotationsResolverFactory(allKtFiles)) - registerService(KotlinDeclarationProviderFactory::class.java, KotlinStaticDeclarationProviderFactory(allKtFiles)) + registerService(KotlinDeclarationProviderFactory::class.java, KotlinStaticDeclarationProviderFactory(project, allKtFiles)) registerService(KotlinPackageProviderFactory::class.java, KotlinStaticPackageProviderFactory(allKtFiles)) registerService(KotlinReferenceProvidersService::class.java, HLApiReferenceProviderService::class.java) } diff --git a/analysis/analysis-api-providers/build.gradle.kts b/analysis/analysis-api-providers/build.gradle.kts index 4aede978038..d4c41e941c1 100644 --- a/analysis/analysis-api-providers/build.gradle.kts +++ b/analysis/analysis-api-providers/build.gradle.kts @@ -8,6 +8,8 @@ dependencies { implementation(project(":compiler:frontend.java")) implementation(project(":core:compiler.common")) implementation(project(":analysis:project-structure")) + implementation(project(":analysis:decompiled:decompiler-to-file-stubs")) + implementation(project(":analysis:decompiled:decompiler-to-psi")) implementation(intellijCore()) } diff --git a/analysis/analysis-api-providers/src/org/jetbrains/kotlin/analysis/providers/impl/KotlinStaticDeclarationProvider.kt b/analysis/analysis-api-providers/src/org/jetbrains/kotlin/analysis/providers/impl/KotlinStaticDeclarationProvider.kt index d676fc47d8d..d32fa3efbf8 100644 --- a/analysis/analysis-api-providers/src/org/jetbrains/kotlin/analysis/providers/impl/KotlinStaticDeclarationProvider.kt +++ b/analysis/analysis-api-providers/src/org/jetbrains/kotlin/analysis/providers/impl/KotlinStaticDeclarationProvider.kt @@ -5,16 +5,23 @@ package org.jetbrains.kotlin.analysis.providers.impl -import com.intellij.psi.PsiElement +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem +import com.intellij.psi.* import com.intellij.psi.search.GlobalSearchScope +import com.intellij.util.indexing.FileContent +import com.intellij.util.indexing.FileContentImpl +import com.intellij.util.io.URLUtil +import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinBuiltInDecompiler import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProviderFactory import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName -import org.jetbrains.kotlin.name.CallableId -import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.idea.KotlinLanguage +import org.jetbrains.kotlin.name.* import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.stubs.impl.* +import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol public class KotlinStaticDeclarationIndex { internal val facadeFileMap: MutableMap> = mutableMapOf() @@ -51,14 +58,12 @@ public class KotlinStaticDeclarationProvider internal constructor( } ?: emptyList() - override fun getTopLevelKotlinClassLikeDeclarationNamesInPackage(packageFqName: FqName): Set { val classifiers = index.classMap[packageFqName].orEmpty() + index.typeAliasMap[packageFqName].orEmpty() return classifiers.filter { it.inScope } .mapNotNullTo(mutableSetOf()) { it.nameAsName } } - override fun getTopLevelCallableNamesInPackage(packageFqName: FqName): Set { val callables = index.topLevelPropertyMap[packageFqName].orEmpty() + index.topLevelFunctionMap[packageFqName].orEmpty() return callables @@ -66,7 +71,6 @@ public class KotlinStaticDeclarationProvider internal constructor( .mapNotNullTo(mutableSetOf()) { it.nameAsName } } - override fun findFilesForFacadeByPackage(packageFqName: FqName): Collection = index.facadeFileMap[packageFqName] ?.filter { ktFile -> @@ -97,67 +101,149 @@ public class KotlinStaticDeclarationProvider internal constructor( } public class KotlinStaticDeclarationProviderFactory( - files: Collection + private val project: Project, + files: Collection, + private val jarFileSystem: CoreJarFileSystem = CoreJarFileSystem(), ) : KotlinDeclarationProviderFactory() { private val index = KotlinStaticDeclarationIndex() - private class KtDeclarationRecorder(private val index: KotlinStaticDeclarationIndex) : KtVisitorVoid() { + private val psiManager = PsiManager.getInstance(project) + private val builtInDecompiler = KotlinBuiltInDecompiler() + + private fun loadBuiltIns() { + val classLoader = this::class.java.classLoader + StandardClassIds.builtInsPackages.forEach { builtInPackageFqName -> + val resourcePath = BuiltInSerializerProtocol.getBuiltInsFilePath(builtInPackageFqName) + classLoader.getResource(resourcePath)?.let { resourceUrl -> + // "file:///path/to/stdlib.jar!/builtin/package/.kotlin_builtins + // -> ("path/to/stdlib.jar", "builtin/package/.kotlin_builtins") + URLUtil.splitJarUrl(resourceUrl.path)?.let { + val jarPath = it.first + val builtInFile = it.second + val pathToQuery = jarPath + URLUtil.JAR_SEPARATOR + builtInFile + jarFileSystem.findFileByPath(pathToQuery)?.let { vf -> + val fileContent = FileContentImpl.createByFile(vf, project) + createKtFileStub(fileContent)?.let { ktFileStub -> loadIndexFromFileStub(ktFileStub) } + } + } + } + } + } + + private fun createKtFileStub( + fileContent: FileContent, + ): KotlinFileStubImpl? { + val ktFileStub = builtInDecompiler.stubBuilder.buildFileStub(fileContent) as? KotlinFileStubImpl ?: return null + val fakeFile = object : KtFile(KtClassFileViewProvider(psiManager, fileContent.file), isCompiled = true) { + override fun getStub() = ktFileStub + + override fun isPhysical() = false + } + ktFileStub.psi = fakeFile + return ktFileStub + } + + private class KtClassFileViewProvider( + psiManager: PsiManager, + virtualFile: VirtualFile, + ) : SingleRootFileViewProvider(psiManager, virtualFile, true, KotlinLanguage.INSTANCE) + + private fun loadIndexFromFileStub( + fileStubImpl: KotlinFileStubImpl, + ) { + addToFacadeFileMap(fileStubImpl.psi) + fileStubImpl.childrenStubs.forEach { stubElement -> + when (stubElement) { + is KotlinClassStubImpl -> + addToClassMap(stubElement.psi) + is KotlinTypeAliasStubImpl -> + addToTypeAliasMap(stubElement.psi) + is KotlinFunctionStubImpl -> + addToFunctionMap(stubElement.psi) + is KotlinPropertyStubImpl -> + addToPropertyMap(stubElement.psi) + } + } + } + + private inner class KtDeclarationRecorder : KtVisitorVoid() { override fun visitElement(element: PsiElement) { element.acceptChildren(this) } override fun visitKtFile(file: KtFile) { - if (file.hasTopLevelCallables()) { - index.facadeFileMap.computeIfAbsent(file.packageFqName) { - mutableSetOf() - }.add(file) - } + addToFacadeFileMap(file) super.visitKtFile(file) } override fun visitClassOrObject(classOrObject: KtClassOrObject) { - classOrObject.getClassId()?.let { classId -> - index.classMap.computeIfAbsent(classId.packageFqName) { - mutableSetOf() - }.add(classOrObject) - } + addToClassMap(classOrObject) super.visitClassOrObject(classOrObject) } override fun visitTypeAlias(typeAlias: KtTypeAlias) { - typeAlias.getClassId()?.let { classId -> - index.typeAliasMap.computeIfAbsent(classId.packageFqName) { - mutableSetOf() - }.add(typeAlias) - } + addToTypeAliasMap(typeAlias) super.visitTypeAlias(typeAlias) } override fun visitNamedFunction(function: KtNamedFunction) { - if (function.isTopLevel) { - val packageFqName = (function.parent as KtFile).packageFqName - index.topLevelFunctionMap.computeIfAbsent(packageFqName) { - mutableSetOf() - }.add(function) - } + addToFunctionMap(function) super.visitNamedFunction(function) } override fun visitProperty(property: KtProperty) { - if (property.isTopLevel) { - val packageFqName = (property.parent as KtFile).packageFqName - index.topLevelPropertyMap.computeIfAbsent(packageFqName) { - mutableSetOf() - }.add(property) - } + addToPropertyMap(property) super.visitProperty(property) } } + private fun addToFacadeFileMap(file: KtFile) { + if (!file.hasTopLevelCallables()) return + index.facadeFileMap.computeIfAbsent(file.packageFqName) { + mutableSetOf() + }.add(file) + } + + private fun addToClassMap(classOrObject: KtClassOrObject) { + classOrObject.getClassId()?.let { classId -> + index.classMap.computeIfAbsent(classId.packageFqName) { + mutableSetOf() + }.add(classOrObject) + } + } + + private fun addToTypeAliasMap(typeAlias: KtTypeAlias) { + typeAlias.getClassId()?.let { classId -> + index.typeAliasMap.computeIfAbsent(classId.packageFqName) { + mutableSetOf() + }.add(typeAlias) + } + } + + private fun addToFunctionMap(function: KtNamedFunction) { + if (!function.isTopLevel) return + val packageFqName = (function.parent as KtFile).packageFqName + index.topLevelFunctionMap.computeIfAbsent(packageFqName) { + mutableSetOf() + }.add(function) + } + + private fun addToPropertyMap(property: KtProperty) { + if (!property.isTopLevel) return + val packageFqName = (property.parent as KtFile).packageFqName + index.topLevelPropertyMap.computeIfAbsent(packageFqName) { + mutableSetOf() + }.add(property) + } + init { - val recorder = KtDeclarationRecorder(index) + // Indexing built-ins + loadBuiltIns() + + // Indexing user source files + val recorder = KtDeclarationRecorder() files.forEach { it.accept(recorder) } diff --git a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/StandaloneAnalysisAPISessionBuilder.kt b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/StandaloneAnalysisAPISessionBuilder.kt index 79064a2cd1f..a6b164a201c 100644 --- a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/StandaloneAnalysisAPISessionBuilder.kt +++ b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/StandaloneAnalysisAPISessionBuilder.kt @@ -117,7 +117,14 @@ public class StandaloneAnalysisAPISessionBuilder( registerService(KtModuleScopeProvider::class.java, KtModuleScopeProviderImpl()) registerService(KotlinAnnotationsResolverFactory::class.java, KotlinStaticAnnotationsResolverFactory(ktFiles)) - registerService(KotlinDeclarationProviderFactory::class.java, KotlinStaticDeclarationProviderFactory(ktFiles)) + registerService( + KotlinDeclarationProviderFactory::class.java, + KotlinStaticDeclarationProviderFactory( + this, + ktFiles, + kotlinCoreProjectEnvironment.environment.jarFileSystem as CoreJarFileSystem + ) + ) registerService(KotlinPackageProviderFactory::class.java, KotlinStaticPackageProviderFactory(ktFiles)) registerService(KtAnalysisSessionProvider::class.java, KtFirAnalysisSessionProvider(this)) diff --git a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/StandaloneUtils.kt b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/StandaloneUtils.kt index 87589e9d27a..ea5254820f2 100644 --- a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/StandaloneUtils.kt +++ b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/StandaloneUtils.kt @@ -157,7 +157,7 @@ internal fun configureProjectEnvironment( ) project.picoContainer.registerComponentInstance( KotlinDeclarationProviderFactory::class.qualifiedName, - KotlinStaticDeclarationProviderFactory(ktFiles) + KotlinStaticDeclarationProviderFactory(project, ktFiles) ) project.picoContainer.registerComponentInstance( KotlinPackageProviderFactory::class.qualifiedName,