FIR: use FirCachesFactory in BuiltInsPackageFragment.tryGetSyntheticFunctionalInterface

This commit is contained in:
Ilya Kirillov
2021-03-29 15:33:59 +02:00
committed by teamcityserver
parent ba2315430b
commit f361312e45
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.caches.firCachesFactory
import org.jetbrains.kotlin.fir.caches.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildRegularClass
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction
@@ -47,11 +47,8 @@ open class FirBuiltinSymbolProvider(
val moduleData: FirModuleData,
val kotlinScopeProvider: FirKotlinScopeProvider
) : FirSymbolProvider(session) {
private data class SyntheticFunctionalInterfaceSymbolKey(val kind: FunctionClassKind, val arity: Int)
private val allPackageFragments = loadBuiltIns().groupBy { it.fqName }
private val syntheticFunctionalInterfaceSymbols = mutableMapOf<SyntheticFunctionalInterfaceSymbolKey, FirRegularClassSymbol>()
private val syntheticFunctionalInterfaceCache = SyntheticFunctionalInterfaceCache(moduleData, kotlinScopeProvider)
private fun loadBuiltIns(): List<BuiltInsPackageFragment> {
val classLoader = this::class.java.classLoader
@@ -61,7 +58,7 @@ open class FirBuiltinSymbolProvider(
return packageFqNames.map { fqName ->
val resourcePath = BuiltInSerializerProtocol.getBuiltInsFilePath(fqName)
val inputStream = streamProvider(resourcePath) ?: throw IllegalStateException("Resource not found in classpath: $resourcePath")
BuiltInsPackageFragment(inputStream, fqName)
BuiltInsPackageFragment(inputStream, fqName, moduleData, kotlinScopeProvider)
}
}
@@ -73,164 +70,9 @@ open class FirBuiltinSymbolProvider(
override fun getClassLikeSymbolByFqName(classId: ClassId): FirRegularClassSymbol? {
return allPackageFragments[classId.packageFqName]?.firstNotNullOfOrNull {
it.getClassLikeSymbolByFqName(classId)
} ?: trySyntheticFunctionalInterface(classId)
} ?: syntheticFunctionalInterfaceCache.tryGetSyntheticFunctionalInterface(classId)
}
private fun trySyntheticFunctionalInterface(classId: ClassId): FirRegularClassSymbol? {
return with(classId) {
val className = relativeClassName.asString()
val kind = FunctionClassKind.byClassNamePrefix(packageFqName, className) ?: return@with null
val prefix = kind.classNamePrefix
val arity = className.substring(prefix.length).toIntOrNull() ?: return null
syntheticFunctionalInterfaceSymbols.getOrPut(SyntheticFunctionalInterfaceSymbolKey(kind, arity)) {
FirRegularClassSymbol(this).apply symbol@{
buildRegularClass klass@{
moduleData = this@FirBuiltinSymbolProvider.moduleData
origin = FirDeclarationOrigin.BuiltIns
name = relativeClassName.shortName()
status = FirResolvedDeclarationStatusImpl(
Visibilities.Public,
Modality.ABSTRACT,
EffectiveVisibility.Public
).apply {
isExpect = false
isActual = false
isInner = false
isCompanion = false
isData = false
isInline = false
}
classKind = ClassKind.INTERFACE
scopeProvider = kotlinScopeProvider
symbol = this@symbol
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
typeParameters.addAll(
(1..arity).map {
buildTypeParameter {
moduleData = this@FirBuiltinSymbolProvider.moduleData
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
origin = FirDeclarationOrigin.BuiltIns
name = Name.identifier("P$it")
symbol = FirTypeParameterSymbol()
variance = Variance.IN_VARIANCE
isReified = false
bounds += session.builtinTypes.nullableAnyType
}
},
)
typeParameters.add(
buildTypeParameter {
moduleData = this@FirBuiltinSymbolProvider.moduleData
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
origin = FirDeclarationOrigin.BuiltIns
name = Name.identifier("R")
symbol = FirTypeParameterSymbol()
variance = Variance.OUT_VARIANCE
isReified = false
bounds += session.builtinTypes.nullableAnyType
},
)
val name = OperatorNameConventions.INVOKE
val functionStatus = FirResolvedDeclarationStatusImpl(
Visibilities.Public,
Modality.ABSTRACT,
EffectiveVisibility.Public
).apply {
isExpect = false
isActual = false
isOverride = false
isOperator = true
isInfix = false
isInline = false
isTailRec = false
isExternal = false
isSuspend =
kind == FunctionClassKind.SuspendFunction ||
kind == FunctionClassKind.KSuspendFunction
}
val typeArguments = typeParameters.map {
buildResolvedTypeRef {
type = ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false)
}
}
fun createSuperType(
kind: FunctionClassKind,
): FirResolvedTypeRef {
return buildResolvedTypeRef {
type = ConeClassLikeLookupTagImpl(kind.classId(arity))
.constructClassType(typeArguments.map { it.type }.toTypedArray(), isNullable = false)
}
}
superTypeRefs += when (kind) {
FunctionClassKind.Function -> listOf(
buildResolvedTypeRef {
type = ConeClassLikeLookupTagImpl(StandardClassIds.Function)
.constructClassType(arrayOf(typeArguments.last().type), isNullable = false)
}
)
FunctionClassKind.SuspendFunction -> listOf(
buildResolvedTypeRef {
type = ConeClassLikeLookupTagImpl(StandardClassIds.Function)
.constructClassType(arrayOf(typeArguments.last().type), isNullable = false)
}
)
FunctionClassKind.KFunction -> listOf(
buildResolvedTypeRef {
type = ConeClassLikeLookupTagImpl(StandardClassIds.KFunction)
.constructClassType(arrayOf(typeArguments.last().type), isNullable = false)
},
createSuperType(FunctionClassKind.Function)
)
FunctionClassKind.KSuspendFunction -> listOf(
buildResolvedTypeRef {
type = ConeClassLikeLookupTagImpl(StandardClassIds.KFunction)
.constructClassType(arrayOf(typeArguments.last().type), isNullable = false)
},
createSuperType(FunctionClassKind.SuspendFunction)
)
}
addDeclaration(
buildSimpleFunction {
moduleData = this@FirBuiltinSymbolProvider.moduleData
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
origin = FirDeclarationOrigin.BuiltIns
returnTypeRef = typeArguments.last()
this.name = name
status = functionStatus
symbol = FirNamedFunctionSymbol(
CallableId(packageFqName, relativeClassName, name)
)
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
valueParameters += typeArguments.dropLast(1).mapIndexed { index, typeArgument ->
val parameterName = Name.identifier("p${index + 1}")
buildValueParameter {
moduleData = this@FirBuiltinSymbolProvider.moduleData
origin = FirDeclarationOrigin.BuiltIns
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
returnTypeRef = typeArgument
this.name = parameterName
symbol = FirVariableSymbol(parameterName)
defaultValue = null
isCrossinline = false
isNoinline = false
isVararg = false
}
}
dispatchReceiverType = classId.defaultType(this@klass.typeParameters.map { it.symbol })
}
)
}
}
}
}
}
private fun FunctionClassKind.classId(arity: Int) = ClassId(packageFqName, numberedClassName(arity))
@FirSymbolProviderInternals
override fun getTopLevelCallableSymbolsTo(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) {
@@ -254,7 +96,10 @@ open class FirBuiltinSymbolProvider(
override fun getTopLevelPropertySymbolsTo(destination: MutableList<FirPropertySymbol>, packageFqName: FqName, name: Name) {
}
private inner class BuiltInsPackageFragment(stream: InputStream, val fqName: FqName) {
private class BuiltInsPackageFragment(
stream: InputStream, val fqName: FqName, val moduleData: FirModuleData,
val kotlinScopeProvider: FirKotlinScopeProvider,
) {
private val binaryVersionAndPackageFragment = BinaryVersionAndPackageFragment.createFromStream(stream)
@@ -268,23 +113,22 @@ open class FirBuiltinSymbolProvider(
private val memberDeserializer by lazy {
FirDeserializationContext.createForPackage(
fqName, packageProto.`package`, nameResolver, moduleData,
FirBuiltinAnnotationDeserializer(session),
FirConstDeserializer(session),
FirBuiltinAnnotationDeserializer(moduleData.session),
FirConstDeserializer(moduleData.session),
containerSource = null
).memberDeserializer
}
private val lookup = session.firCachesFactory.createCacheWithPostCompute(
private val lookup = moduleData.session.firCachesFactory.createCacheWithPostCompute(
{ classId: ClassId, context: FirDeserializationContext? -> FirRegularClassSymbol(classId) to context }
) { classId, symbol, parentContext ->
val classData = classDataFinder.findClassData(classId)!!
val classProto = classData.classProto
deserializeClassToSymbol(
classId, classProto, symbol, nameResolver, session,
moduleData,
defaultAnnotationDeserializer =null, kotlinScopeProvider, parentContext,
containerSource =null,
classId, classProto, symbol, nameResolver, moduleData.session, moduleData,
null, kotlinScopeProvider, parentContext,
null,
origin = FirDeclarationOrigin.BuiltIns,
this::findAndDeserializeClass,
)
@@ -332,7 +176,171 @@ private data class BinaryVersionAndPackageFragment(
}
val packageFragment = ProtoBuf.PackageFragment.parseFrom(stream, BuiltInSerializerProtocol.extensionRegistry)
return BinaryVersionAndPackageFragment(version, packageFragment)
return BinaryVersionAndPackageFragment(version, packageFragment)
}
}
}
private class SyntheticFunctionalInterfaceCache(private val moduleData: FirModuleData, private val kotlinScopeProvider: FirKotlinScopeProvider) {
private val syntheticFunctionalInterfaceCache =
moduleData.session.firCachesFactory.createCache(::createSyntheticFunctionalInterface)
fun tryGetSyntheticFunctionalInterface(classId: ClassId): FirRegularClassSymbol? {
return syntheticFunctionalInterfaceCache.getValue(classId)
}
private fun createSyntheticFunctionalInterface(classId: ClassId): FirRegularClassSymbol? {
return with(classId) {
val className = relativeClassName.asString()
val kind = FunctionClassKind.byClassNamePrefix(packageFqName, className) ?: return@with null
val prefix = kind.classNamePrefix
val arity = className.substring(prefix.length).toIntOrNull() ?: return null
FirRegularClassSymbol(classId).apply symbol@{
buildRegularClass klass@{
moduleData = this@SyntheticFunctionalInterfaceCache.moduleData
origin = FirDeclarationOrigin.BuiltIns
name = relativeClassName.shortName()
status = FirResolvedDeclarationStatusImpl(
Visibilities.Public,
Modality.ABSTRACT,
EffectiveVisibility.Public
).apply {
isExpect = false
isActual = false
isInner = false
isCompanion = false
isData = false
isInline = false
}
classKind = ClassKind.INTERFACE
scopeProvider = kotlinScopeProvider
symbol = this@symbol
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
typeParameters.addAll(
(1..arity).map {
buildTypeParameter {
moduleData = this@SyntheticFunctionalInterfaceCache.moduleData
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
origin = FirDeclarationOrigin.BuiltIns
name = Name.identifier("P$it")
symbol = FirTypeParameterSymbol()
variance = Variance.IN_VARIANCE
isReified = false
bounds += moduleData.session.builtinTypes.nullableAnyType
}
},
)
typeParameters.add(
buildTypeParameter {
moduleData = this@SyntheticFunctionalInterfaceCache.moduleData
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
origin = FirDeclarationOrigin.BuiltIns
name = Name.identifier("R")
symbol = FirTypeParameterSymbol()
variance = Variance.OUT_VARIANCE
isReified = false
bounds += moduleData.session.builtinTypes.nullableAnyType
},
)
val name = OperatorNameConventions.INVOKE
val functionStatus = FirResolvedDeclarationStatusImpl(
Visibilities.Public,
Modality.ABSTRACT,
EffectiveVisibility.Public
).apply {
isExpect = false
isActual = false
isOverride = false
isOperator = true
isInfix = false
isInline = false
isTailRec = false
isExternal = false
isSuspend =
kind == FunctionClassKind.SuspendFunction ||
kind == FunctionClassKind.KSuspendFunction
}
val typeArguments = typeParameters.map {
buildResolvedTypeRef {
type = ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false)
}
}
fun createSuperType(
kind: FunctionClassKind,
): FirResolvedTypeRef {
return buildResolvedTypeRef {
type = ConeClassLikeLookupTagImpl(kind.classId(arity))
.constructClassType(typeArguments.map { it.type }.toTypedArray(), isNullable = false)
}
}
superTypeRefs += when (kind) {
FunctionClassKind.Function -> listOf(
buildResolvedTypeRef {
type = ConeClassLikeLookupTagImpl(StandardClassIds.Function)
.constructClassType(arrayOf(typeArguments.last().type), isNullable = false)
}
)
FunctionClassKind.SuspendFunction -> listOf(
buildResolvedTypeRef {
type = ConeClassLikeLookupTagImpl(StandardClassIds.Function)
.constructClassType(arrayOf(typeArguments.last().type), isNullable = false)
}
)
FunctionClassKind.KFunction -> listOf(
buildResolvedTypeRef {
type = ConeClassLikeLookupTagImpl(StandardClassIds.KFunction)
.constructClassType(arrayOf(typeArguments.last().type), isNullable = false)
},
createSuperType(FunctionClassKind.Function)
)
FunctionClassKind.KSuspendFunction -> listOf(
buildResolvedTypeRef {
type = ConeClassLikeLookupTagImpl(StandardClassIds.KFunction)
.constructClassType(arrayOf(typeArguments.last().type), isNullable = false)
},
createSuperType(FunctionClassKind.SuspendFunction)
)
}
addDeclaration(
buildSimpleFunction {
moduleData = this@SyntheticFunctionalInterfaceCache.moduleData
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
origin = FirDeclarationOrigin.BuiltIns
returnTypeRef = typeArguments.last()
this.name = name
status = functionStatus
symbol = FirNamedFunctionSymbol(
CallableId(packageFqName, relativeClassName, name)
)
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
valueParameters += typeArguments.dropLast(1).mapIndexed { index, typeArgument ->
val parameterName = Name.identifier("p${index + 1}")
buildValueParameter {
moduleData = this@SyntheticFunctionalInterfaceCache.moduleData
origin = FirDeclarationOrigin.BuiltIns
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
returnTypeRef = typeArgument
this.name = parameterName
symbol = FirVariableSymbol(parameterName)
defaultValue = null
isCrossinline = false
isNoinline = false
isVararg = false
}
}
dispatchReceiverType = classId.defaultType(this@klass.typeParameters.map { it.symbol })
}
)
}
}
}
}
private fun FunctionClassKind.classId(arity: Int) = ClassId(packageFqName, numberedClassName(arity))
}