AA: populate index for built-ins
This commit is contained in:
committed by
Ilya Kirillov
parent
529a29ae52
commit
df95602e06
+1
-1
@@ -40,7 +40,7 @@ object AnalysisApiBaseTestServiceRegistrar: AnalysisApiTestServiceRegistrar() {
|
|||||||
|
|
||||||
registerService(KtModuleScopeProvider::class.java, KtModuleScopeProviderImpl())
|
registerService(KtModuleScopeProvider::class.java, KtModuleScopeProviderImpl())
|
||||||
registerService(KotlinAnnotationsResolverFactory::class.java, KotlinStaticAnnotationsResolverFactory(allKtFiles))
|
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(KotlinPackageProviderFactory::class.java, KotlinStaticPackageProviderFactory(allKtFiles))
|
||||||
registerService(KotlinReferenceProvidersService::class.java, HLApiReferenceProviderService::class.java)
|
registerService(KotlinReferenceProvidersService::class.java, HLApiReferenceProviderService::class.java)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ dependencies {
|
|||||||
implementation(project(":compiler:frontend.java"))
|
implementation(project(":compiler:frontend.java"))
|
||||||
implementation(project(":core:compiler.common"))
|
implementation(project(":core:compiler.common"))
|
||||||
implementation(project(":analysis:project-structure"))
|
implementation(project(":analysis:project-structure"))
|
||||||
|
implementation(project(":analysis:decompiled:decompiler-to-file-stubs"))
|
||||||
|
implementation(project(":analysis:decompiled:decompiler-to-psi"))
|
||||||
implementation(intellijCore())
|
implementation(intellijCore())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+124
-38
@@ -5,16 +5,23 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.analysis.providers.impl
|
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.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.KotlinDeclarationProvider
|
||||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProviderFactory
|
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProviderFactory
|
||||||
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
|
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
|
||||||
import org.jetbrains.kotlin.name.CallableId
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.*
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.stubs.impl.*
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
|
||||||
|
|
||||||
public class KotlinStaticDeclarationIndex {
|
public class KotlinStaticDeclarationIndex {
|
||||||
internal val facadeFileMap: MutableMap<FqName, MutableSet<KtFile>> = mutableMapOf()
|
internal val facadeFileMap: MutableMap<FqName, MutableSet<KtFile>> = mutableMapOf()
|
||||||
@@ -51,14 +58,12 @@ public class KotlinStaticDeclarationProvider internal constructor(
|
|||||||
}
|
}
|
||||||
?: emptyList()
|
?: emptyList()
|
||||||
|
|
||||||
|
|
||||||
override fun getTopLevelKotlinClassLikeDeclarationNamesInPackage(packageFqName: FqName): Set<Name> {
|
override fun getTopLevelKotlinClassLikeDeclarationNamesInPackage(packageFqName: FqName): Set<Name> {
|
||||||
val classifiers = index.classMap[packageFqName].orEmpty() + index.typeAliasMap[packageFqName].orEmpty()
|
val classifiers = index.classMap[packageFqName].orEmpty() + index.typeAliasMap[packageFqName].orEmpty()
|
||||||
return classifiers.filter { it.inScope }
|
return classifiers.filter { it.inScope }
|
||||||
.mapNotNullTo(mutableSetOf()) { it.nameAsName }
|
.mapNotNullTo(mutableSetOf()) { it.nameAsName }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun getTopLevelCallableNamesInPackage(packageFqName: FqName): Set<Name> {
|
override fun getTopLevelCallableNamesInPackage(packageFqName: FqName): Set<Name> {
|
||||||
val callables = index.topLevelPropertyMap[packageFqName].orEmpty() + index.topLevelFunctionMap[packageFqName].orEmpty()
|
val callables = index.topLevelPropertyMap[packageFqName].orEmpty() + index.topLevelFunctionMap[packageFqName].orEmpty()
|
||||||
return callables
|
return callables
|
||||||
@@ -66,7 +71,6 @@ public class KotlinStaticDeclarationProvider internal constructor(
|
|||||||
.mapNotNullTo(mutableSetOf()) { it.nameAsName }
|
.mapNotNullTo(mutableSetOf()) { it.nameAsName }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun findFilesForFacadeByPackage(packageFqName: FqName): Collection<KtFile> =
|
override fun findFilesForFacadeByPackage(packageFqName: FqName): Collection<KtFile> =
|
||||||
index.facadeFileMap[packageFqName]
|
index.facadeFileMap[packageFqName]
|
||||||
?.filter { ktFile ->
|
?.filter { ktFile ->
|
||||||
@@ -97,67 +101,149 @@ public class KotlinStaticDeclarationProvider internal constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class KotlinStaticDeclarationProviderFactory(
|
public class KotlinStaticDeclarationProviderFactory(
|
||||||
files: Collection<KtFile>
|
private val project: Project,
|
||||||
|
files: Collection<KtFile>,
|
||||||
|
private val jarFileSystem: CoreJarFileSystem = CoreJarFileSystem(),
|
||||||
) : KotlinDeclarationProviderFactory() {
|
) : KotlinDeclarationProviderFactory() {
|
||||||
|
|
||||||
private val index = KotlinStaticDeclarationIndex()
|
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) {
|
override fun visitElement(element: PsiElement) {
|
||||||
element.acceptChildren(this)
|
element.acceptChildren(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitKtFile(file: KtFile) {
|
override fun visitKtFile(file: KtFile) {
|
||||||
if (file.hasTopLevelCallables()) {
|
addToFacadeFileMap(file)
|
||||||
index.facadeFileMap.computeIfAbsent(file.packageFqName) {
|
|
||||||
mutableSetOf()
|
|
||||||
}.add(file)
|
|
||||||
}
|
|
||||||
super.visitKtFile(file)
|
super.visitKtFile(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitClassOrObject(classOrObject: KtClassOrObject) {
|
override fun visitClassOrObject(classOrObject: KtClassOrObject) {
|
||||||
classOrObject.getClassId()?.let { classId ->
|
addToClassMap(classOrObject)
|
||||||
index.classMap.computeIfAbsent(classId.packageFqName) {
|
|
||||||
mutableSetOf()
|
|
||||||
}.add(classOrObject)
|
|
||||||
}
|
|
||||||
super.visitClassOrObject(classOrObject)
|
super.visitClassOrObject(classOrObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitTypeAlias(typeAlias: KtTypeAlias) {
|
override fun visitTypeAlias(typeAlias: KtTypeAlias) {
|
||||||
typeAlias.getClassId()?.let { classId ->
|
addToTypeAliasMap(typeAlias)
|
||||||
index.typeAliasMap.computeIfAbsent(classId.packageFqName) {
|
|
||||||
mutableSetOf()
|
|
||||||
}.add(typeAlias)
|
|
||||||
}
|
|
||||||
super.visitTypeAlias(typeAlias)
|
super.visitTypeAlias(typeAlias)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitNamedFunction(function: KtNamedFunction) {
|
override fun visitNamedFunction(function: KtNamedFunction) {
|
||||||
if (function.isTopLevel) {
|
addToFunctionMap(function)
|
||||||
val packageFqName = (function.parent as KtFile).packageFqName
|
|
||||||
index.topLevelFunctionMap.computeIfAbsent(packageFqName) {
|
|
||||||
mutableSetOf()
|
|
||||||
}.add(function)
|
|
||||||
}
|
|
||||||
super.visitNamedFunction(function)
|
super.visitNamedFunction(function)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitProperty(property: KtProperty) {
|
override fun visitProperty(property: KtProperty) {
|
||||||
if (property.isTopLevel) {
|
addToPropertyMap(property)
|
||||||
val packageFqName = (property.parent as KtFile).packageFqName
|
|
||||||
index.topLevelPropertyMap.computeIfAbsent(packageFqName) {
|
|
||||||
mutableSetOf()
|
|
||||||
}.add(property)
|
|
||||||
}
|
|
||||||
super.visitProperty(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 {
|
init {
|
||||||
val recorder = KtDeclarationRecorder(index)
|
// Indexing built-ins
|
||||||
|
loadBuiltIns()
|
||||||
|
|
||||||
|
// Indexing user source files
|
||||||
|
val recorder = KtDeclarationRecorder()
|
||||||
files.forEach {
|
files.forEach {
|
||||||
it.accept(recorder)
|
it.accept(recorder)
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-1
@@ -117,7 +117,14 @@ public class StandaloneAnalysisAPISessionBuilder(
|
|||||||
|
|
||||||
registerService(KtModuleScopeProvider::class.java, KtModuleScopeProviderImpl())
|
registerService(KtModuleScopeProvider::class.java, KtModuleScopeProviderImpl())
|
||||||
registerService(KotlinAnnotationsResolverFactory::class.java, KotlinStaticAnnotationsResolverFactory(ktFiles))
|
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(KotlinPackageProviderFactory::class.java, KotlinStaticPackageProviderFactory(ktFiles))
|
||||||
|
|
||||||
registerService(KtAnalysisSessionProvider::class.java, KtFirAnalysisSessionProvider(this))
|
registerService(KtAnalysisSessionProvider::class.java, KtFirAnalysisSessionProvider(this))
|
||||||
|
|||||||
+1
-1
@@ -157,7 +157,7 @@ internal fun configureProjectEnvironment(
|
|||||||
)
|
)
|
||||||
project.picoContainer.registerComponentInstance(
|
project.picoContainer.registerComponentInstance(
|
||||||
KotlinDeclarationProviderFactory::class.qualifiedName,
|
KotlinDeclarationProviderFactory::class.qualifiedName,
|
||||||
KotlinStaticDeclarationProviderFactory(ktFiles)
|
KotlinStaticDeclarationProviderFactory(project, ktFiles)
|
||||||
)
|
)
|
||||||
project.picoContainer.registerComponentInstance(
|
project.picoContainer.registerComponentInstance(
|
||||||
KotlinPackageProviderFactory::class.qualifiedName,
|
KotlinPackageProviderFactory::class.qualifiedName,
|
||||||
|
|||||||
Reference in New Issue
Block a user