[FIR] Refactor deserialized dependency providers and session factories with FirModuleData

This commit is contained in:
Dmitriy Novozhilov
2021-04-30 16:57:46 +03:00
committed by TeamCityServer
parent 24f1f7b7b2
commit 02c58b7a8f
23 changed files with 566 additions and 196 deletions
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.fir.deserialization
import com.intellij.openapi.progress.ProcessCanceledException
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.caches.*
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.metadata.deserialization.NameResolver
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.serialization.deserialization.getName
import java.nio.file.Path
class PackagePartsCacheData(
val proto: ProtoBuf.Package,
@@ -36,13 +37,30 @@ class PackagePartsCacheData(
}
}
abstract class LibraryPathFilter {
abstract fun accepts(path: Path?): Boolean
object TakeAll : LibraryPathFilter() {
override fun accepts(path: Path?): Boolean {
return true
}
}
class LibraryList(val libs: Set<Path>) : LibraryPathFilter() {
override fun accepts(path: Path?): Boolean {
if (path == null) return false
return libs.any { path.startsWith(it) }
}
}
}
typealias DeserializedClassPostProcessor = (FirRegularClassSymbol) -> Unit
abstract class AbstractFirDeserializedSymbolsProvider(
val moduleData: FirModuleData,
val kotlinScopeProvider: FirKotlinScopeProvider
) : FirSymbolProvider(moduleData.session) {
session: FirSession,
val moduleDataProvider: ModuleDataProvider,
val kotlinScopeProvider: FirKotlinScopeProvider,
) : FirSymbolProvider(session) {
// ------------------------ Caches ------------------------
private val packagePartsCache = session.firCachesFactory.createCache(::tryComputePackagePartInfos)
@@ -75,6 +93,7 @@ abstract class AbstractFirDeserializedSymbolsProvider(
val nameResolver: NameResolver,
val classProto: ProtoBuf.Class,
val annotationDeserializer: AbstractAnnotationDeserializer,
val containingLibraryPath: Path?,
val sourceElement: DeserializedContainerSource,
val classPostProcessor: DeserializedClassPostProcessor
) : ClassMetadataFindResult()
@@ -107,7 +126,8 @@ abstract class AbstractFirDeserializedSymbolsProvider(
): Pair<FirRegularClassSymbol?, DeserializedClassPostProcessor?> {
return when (val result = extractClassMetadata(classId, parentContext)) {
is ClassMetadataFindResult.Metadata -> {
val (nameResolver, classProto, annotationDeserializer, sourceElement, postProcessor) = result
val (nameResolver, classProto, annotationDeserializer, containingLibrary, sourceElement, postProcessor) = result
val moduleData = moduleDataProvider.getModuleData(containingLibrary) ?: return null to null
val symbol = FirRegularClassSymbol(classId)
deserializeClassToSymbol(
classId,
@@ -158,6 +178,20 @@ abstract class AbstractFirDeserializedSymbolsProvider(
return packagePartsCache.getValue(packageFqName)
}
private fun getClass(
classId: ClassId,
parentContext: FirDeserializationContext? = null
): FirRegularClassSymbol? {
return classCache.getValue(classId, parentContext)
}
private fun getTypeAlias(
classId: ClassId,
): FirTypeAliasSymbol? {
if (!classId.relativeClassName.isOneSegmentFQN()) return null
return typeAliasCache.getValue(classId)
}
// ------------------------ SymbolProvider methods ------------------------
@FirSymbolProviderInternals
@@ -181,19 +215,5 @@ abstract class AbstractFirDeserializedSymbolsProvider(
return getClass(classId) ?: getTypeAlias(classId)
}
private fun getClass(
classId: ClassId,
parentContext: FirDeserializationContext? = null
): FirRegularClassSymbol? {
return classCache.getValue(classId, parentContext)
}
private fun getTypeAlias(
classId: ClassId,
): FirTypeAliasSymbol? {
if (!classId.relativeClassName.isOneSegmentFQN()) return null
return typeAliasCache.getValue(classId)
}
override fun getPackage(fqName: FqName): FqName? = null
}
@@ -0,0 +1,57 @@
/*
* 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.fir.deserialization
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
import org.jetbrains.kotlin.utils.addToStdlib.same
import java.nio.file.Path
abstract class ModuleDataProvider {
abstract val platform: TargetPlatform
abstract val analyzerServices: PlatformDependentAnalyzerServices
abstract val allModuleData: Collection<FirModuleData>
abstract fun getModuleData(path: Path?): FirModuleData?
}
class SingleModuleDataProvider(private val moduleData: FirModuleData) : ModuleDataProvider() {
override val platform: TargetPlatform
get() = moduleData.platform
override val analyzerServices: PlatformDependentAnalyzerServices
get() = moduleData.analyzerServices
override val allModuleData: Collection<FirModuleData>
get() = listOf(moduleData)
override fun getModuleData(path: Path?): FirModuleData {
return moduleData
}
}
class MultipleModuleDataProvider(private val moduleDataWithFilters: Map<FirModuleData, LibraryPathFilter>) : ModuleDataProvider() {
init {
require(moduleDataWithFilters.isNotEmpty()) { "ModuleDataProvider must contain at least one module data" }
require(moduleDataWithFilters.keys.same { it.platform }) { "All module data should have same target platform" }
require(moduleDataWithFilters.keys.same { it.analyzerServices }) { "All module data should have same analyzerServices" }
}
override val platform: TargetPlatform = allModuleData.first().platform
override val analyzerServices: PlatformDependentAnalyzerServices = allModuleData.first().analyzerServices
override val allModuleData: Collection<FirModuleData>
get() = moduleDataWithFilters.keys
override fun getModuleData(path: Path?): FirModuleData? {
for ((session, filter) in moduleDataWithFilters.entries) {
if (filter.accepts(path)) {
return session
}
}
return null
}
}