FIR IDE: abstract DeclarationProvider

This commit is contained in:
Ilya Kirillov
2021-06-14 17:05:53 +02:00
parent 7fe2adc37e
commit a483098303
10 changed files with 96 additions and 29 deletions
@@ -5,11 +5,9 @@
package org.jetbrains.kotlin.idea.fir.low.level.api
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.stubs.StringStubIndexExtension
import com.intellij.psi.stubs.StubIndex
import com.intellij.psi.stubs.StubIndexKey
import org.jetbrains.kotlin.idea.stubindex.*
@@ -19,10 +17,8 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
/*
* Move to another module
*/
internal class IndexHelper(val project: Project, private val scope: GlobalSearchScope) {
internal class DeclarationProviderByIndexesImpl(val project: Project, private val scope: GlobalSearchScope) : DeclarationProvider() {
private val stubIndex: StubIndex = StubIndex.getInstance()
private inline fun <INDEX_KEY : Any, reified PSI : PsiElement> firstMatchingOrNull(
@@ -43,12 +39,12 @@ internal class IndexHelper(val project: Project, private val scope: GlobalSearch
return result
}
fun classFromIndexByClassId(classId: ClassId) = firstMatchingOrNull(
override fun getClassByClassId(classId: ClassId) = firstMatchingOrNull(
KotlinFullClassNameIndex.KEY,
classId.asStringForIndexes(),
) { candidate -> candidate.containingKtFile.packageFqName == classId.packageFqName }
fun typeAliasFromIndexByClassId(classId: ClassId): KtTypeAlias? = firstMatchingOrNull<String, KtTypeAlias>(
override fun getTypeAliasByClassId(classId: ClassId): KtTypeAlias? = firstMatchingOrNull<String, KtTypeAlias>(
KotlinTopLevelTypeAliasFqNameIndex.KEY,
key = classId.asStringForIndexes(),
) { candidate -> candidate.containingKtFile.packageFqName == classId.packageFqName }
@@ -57,15 +53,14 @@ internal class IndexHelper(val project: Project, private val scope: GlobalSearch
key = classId.asString(),
)
fun getTopLevelProperties(callableId: CallableId): Collection<KtProperty> =
override fun getTopLevelProperties(callableId: CallableId): Collection<KtProperty> =
KotlinTopLevelPropertyFqnNameIndex.getInstance()[callableId.asStringForIndexes(), project, scope]
fun getTopLevelFunctions(callableId: CallableId): Collection<KtNamedFunction> =
override fun getTopLevelFunctions(callableId: CallableId): Collection<KtNamedFunction> =
KotlinTopLevelFunctionFqnNameIndex.getInstance()[callableId.asStringForIndexes(), project, scope]
fun getClassNamesInPackage(packageFqName: FqName): Set<Name> =
override fun getClassNamesInPackage(packageFqName: FqName): Set<Name> =
KotlinTopLevelClassByPackageIndex.getInstance()
.get(packageFqName.asStringForIndexes(), project, scope)
.mapNotNullTo(hashSetOf()) { it.nameAsName }
@@ -80,7 +75,5 @@ internal class IndexHelper(val project: Project, private val scope: GlobalSearch
private fun ClassId.asStringForIndexes(): String =
asSingleFqName().asStringForIndexes()
private fun getShortName(fqName: String) = Name.identifier(fqName.substringAfterLast('.'))
}
}
@@ -0,0 +1,27 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.fir.low.level.api
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.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtTypeAlias
abstract class DeclarationProvider {
abstract fun getClassByClassId(classId: ClassId): KtClassOrObject?
abstract fun getTypeAliasByClassId(classId: ClassId): KtTypeAlias?
abstract fun getTopLevelProperties(callableId: CallableId): Collection<KtProperty>
abstract fun getTopLevelFunctions(callableId: CallableId): Collection<KtNamedFunction>
abstract fun getClassNamesInPackage(packageFqName: FqName): Set<Name>
}
@@ -0,0 +1,7 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.fir.low.level.api
@@ -0,0 +1,7 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.fir.low.level.api
@@ -0,0 +1,13 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.fir.low.level.api.api
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.idea.fir.low.level.api.DeclarationProvider
abstract class FirModuleResolveStateConfigurator {
abstract fun createDeclarationProvider(scope: GlobalSearchScope): DeclarationProvider
}
@@ -0,0 +1,16 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.fir.low.level.api.api
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.idea.fir.low.level.api.DeclarationProvider
import org.jetbrains.kotlin.idea.fir.low.level.api.DeclarationProviderByIndexesImpl
class FirModuleResolveStateConfiguratorIdeImpl(private val project: Project) : FirModuleResolveStateConfigurator() {
override fun createDeclarationProvider(scope: GlobalSearchScope): DeclarationProvider =
DeclarationProviderByIndexesImpl(project, scope)
}
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.providers
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.NoMutableState
import org.jetbrains.kotlin.fir.ThreadSafeMutableState
@@ -21,7 +20,7 @@ import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo
import org.jetbrains.kotlin.idea.fir.low.level.api.IndexHelper
import org.jetbrains.kotlin.idea.fir.low.level.api.DeclarationProvider
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveStateConfigurator
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.FirFileBuilder
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCache
@@ -37,18 +36,17 @@ internal class FirIdeProvider(
val kotlinScopeProvider: FirKotlinScopeProvider,
firFileBuilder: FirFileBuilder,
val cache: ModuleFileCache,
searchScope: GlobalSearchScope,
private val declarationProvider: DeclarationProvider,
) : FirProvider() {
override val symbolProvider: FirSymbolProvider = SymbolProvider()
private val indexHelper = IndexHelper(project, searchScope)
private val packageExistenceChecker = ServiceManager.getService(project, FirModuleResolveStateConfigurator::class.java)
.createPackageExistingCheckerForModule(moduleInfo)
private val providerHelper = FirProviderHelper(
cache,
firFileBuilder,
indexHelper,
declarationProvider,
packageExistenceChecker,
)
@@ -103,7 +101,7 @@ internal class FirIdeProvider(
}
override fun getClassNamesInPackage(fqName: FqName): Set<Name> =
indexHelper.getClassNamesInPackage(fqName)
declarationProvider.getClassNamesInPackage(fqName)
@NoMutableState
private inner class SymbolProvider : FirSymbolProvider(session) {
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.idea.fir.low.level.api.IndexHelper
import org.jetbrains.kotlin.idea.fir.low.level.api.DeclarationProvider
import org.jetbrains.kotlin.idea.fir.low.level.api.PackageExistenceChecker
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.FirFileBuilder
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCache
@@ -28,15 +28,15 @@ import java.util.*
internal class FirProviderHelper(
private val cache: ModuleFileCache,
private val firFileBuilder: FirFileBuilder,
private val indexHelper: IndexHelper,
private val declarationProvider: DeclarationProvider,
private val packageExistenceChecker: PackageExistenceChecker,
) {
fun getFirClassifierByFqName(classId: ClassId): FirClassLikeDeclaration<*>? {
if (classId.isLocal) return null
return executeOrReturnDefaultValueOnPCE(null) {
cache.classifierByClassId.computeIfAbsent(classId) {
val ktClass = when (val klass = indexHelper.classFromIndexByClassId(classId)) {
null -> indexHelper.typeAliasFromIndexByClassId(classId)
val ktClass = when (val klass = declarationProvider.getClassByClassId(classId)) {
null -> declarationProvider.getTypeAliasByClassId(classId)
else -> if (klass.getClassId() == null) null else klass
} ?: return@computeIfAbsent Optional.empty()
val firFile = firFileBuilder.buildRawFirFileWithCaching(ktClass.containingKtFile, cache, preferLazyBodies = true)
@@ -55,8 +55,8 @@ internal class FirProviderHelper(
return executeOrReturnDefaultValueOnPCE(emptyList()) {
cache.callableByCallableId.computeIfAbsent(callableId) {
val files = Sets.newIdentityHashSet<KtFile>().apply {
indexHelper.getTopLevelFunctions(callableId).mapTo(this) { it.containingKtFile }
indexHelper.getTopLevelProperties(callableId).mapTo(this) { it.containingKtFile }
declarationProvider.getTopLevelFunctions(callableId).mapTo(this) { it.containingKtFile }
declarationProvider.getTopLevelProperties(callableId).mapTo(this) { it.containingKtFile }
}
@OptIn(ExperimentalStdlibApi::class)
buildList {
@@ -29,10 +29,10 @@ import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.fir.session.*
import org.jetbrains.kotlin.idea.caches.project.*
import org.jetbrains.kotlin.idea.caches.resolve.IDEPackagePartProvider
import org.jetbrains.kotlin.idea.fir.low.level.api.*
import org.jetbrains.kotlin.idea.fir.low.level.api.FirPhaseRunner
import org.jetbrains.kotlin.idea.fir.low.level.api.IdeFirPhaseManager
import org.jetbrains.kotlin.idea.fir.low.level.api.IdeSessionComponents
import org.jetbrains.kotlin.idea.fir.low.level.api.SealedClassInheritorsProviderIdeImpl
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveStateConfigurator
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.FirFileBuilder
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCacheImpl
import org.jetbrains.kotlin.idea.fir.low.level.api.fir.caches.FirThreadSafeCachesFactory
@@ -58,6 +58,7 @@ import java.nio.file.Paths
internal object FirIdeSessionFactory {
fun createSourcesSession(
project: Project,
configurator: FirModuleResolveStateConfigurator,
moduleInfo: ModuleSourceInfo,
builtinsAndCloneableSession: FirIdeBuiltinsAndCloneableSession,
firPhaseRunner: FirPhaseRunner,
@@ -97,7 +98,7 @@ internal object FirIdeSessionFactory {
scopeProvider,
firFileBuilder,
cache,
searchScope
configurator.createDeclarationProvider(searchScope),
)
register(FirProvider::class, provider)
@@ -130,6 +131,7 @@ internal object FirIdeSessionFactory {
.mapTo(this) {
createSourcesSession(
project,
configurator,
it,
builtinsAndCloneableSession,
firPhaseRunner,
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.idea.fir.low.level.api.sessions
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project
import kotlinx.collections.immutable.PersistentMap
import kotlinx.collections.immutable.persistentMapOf
@@ -16,6 +17,7 @@ import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.session.FirModuleInfoBasedModuleData
import org.jetbrains.kotlin.idea.caches.project.LibraryModificationTracker
import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveStateConfigurator
import org.jetbrains.kotlin.idea.fir.low.level.api.FirPhaseRunner
import org.jetbrains.kotlin.idea.fir.low.level.api.util.addValueFor
import org.jetbrains.kotlin.idea.fir.low.level.api.util.executeWithoutPCE
@@ -25,6 +27,7 @@ import java.util.concurrent.ConcurrentHashMap
internal class FirIdeSessionProviderStorage(private val project: Project) {
private val sessionsCache = ConcurrentHashMap<ModuleSourceInfo, FromModuleViewSessionCache>()
private val configurator = ServiceManager.getService(project, FirModuleResolveStateConfigurator::class.java)
private val librariesCache by cachedValue(project, LibraryModificationTracker.getInstance(project)) { LibrariesCache() }
@@ -42,6 +45,7 @@ internal class FirIdeSessionProviderStorage(private val project: Project) {
val session = executeWithoutPCE {
FirIdeSessionFactory.createSourcesSession(
project,
configurator,
rootModule,
builtinsAndCloneableSession,
firPhaseRunner,