[FIR] Extract SyntheticFunctionsCache from builtins provider into separate one

This is needed because now set of available synthetic functional interfaces
  depends on session, because each module can contain different plugins,
  which provide different kinds of functional types
This commit is contained in:
Dmitriy Novozhilov
2023-01-18 16:48:25 +02:00
committed by Space Team
parent e0c8f2354a
commit 87a9103cc6
12 changed files with 316 additions and 186 deletions
@@ -5,43 +5,33 @@
package org.jetbrains.kotlin.fir.resolve.providers.impl
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.ThreadSafeMutableState
import org.jetbrains.kotlin.fir.caches.createCache
import org.jetbrains.kotlin.fir.caches.firCachesFactory
import org.jetbrains.kotlin.fir.caches.getValue
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.builder.buildRegularClass
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction
import org.jetbrains.kotlin.fir.declarations.builder.buildTypeParameter
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.utils.addDeclaration
import org.jetbrains.kotlin.fir.deserialization.FirBuiltinAnnotationDeserializer
import org.jetbrains.kotlin.fir.deserialization.FirConstDeserializer
import org.jetbrains.kotlin.fir.deserialization.FirDeserializationContext
import org.jetbrains.kotlin.fir.deserialization.deserializeClassToSymbol
import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotation
import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyAnnotationArgumentMapping
import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
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.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
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.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.builtins.BuiltInsBinaryVersion
import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.serialization.deserialization.ProtoBasedClassDataFinder
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
import org.jetbrains.kotlin.serialization.deserialization.getName
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.util.OperatorNameConventions
import java.io.InputStream
@ThreadSafeMutableState
@@ -50,8 +40,13 @@ open class FirBuiltinSymbolProvider(
val moduleData: FirModuleData,
val kotlinScopeProvider: FirKotlinScopeProvider
) : FirSymbolProvider(session) {
private val syntheticFunctionalInterfaceProvider = FirBuiltinSyntheticFunctionalInterfaceProvider(
session,
moduleData,
kotlinScopeProvider
)
private val allPackageFragments = loadBuiltIns().groupBy { it.fqName }
private val syntheticFunctionalInterfaceCache = SyntheticFunctionalInterfaceCache(session, moduleData, kotlinScopeProvider)
private fun loadBuiltIns(): List<BuiltInsPackageFragment> {
val classLoader = this::class.java.classLoader
@@ -73,7 +68,7 @@ open class FirBuiltinSymbolProvider(
override fun getClassLikeSymbolByClassId(classId: ClassId): FirRegularClassSymbol? {
return allPackageFragments[classId.packageFqName]?.firstNotNullOfOrNull {
it.getClassLikeSymbolByClassId(classId)
} ?: syntheticFunctionalInterfaceCache.tryGetSyntheticFunctionalInterface(classId)
} ?: syntheticFunctionalInterfaceProvider.getClassLikeSymbolByClassId(classId)
}
override fun computePackageSetWithTopLevelCallables(): Set<String> =
@@ -199,155 +194,3 @@ private data class BinaryVersionAndPackageFragment(
}
}
private class SyntheticFunctionalInterfaceCache(
private val session: FirSession,
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 = session.functionalTypeService.getKindByClassNamePrefix(packageFqName, className) ?: return 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()
containingDeclarationSymbol = this@symbol
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()
containingDeclarationSymbol = this@symbol
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 == ConeFunctionalTypeKind.SuspendFunction ||
kind == ConeFunctionalTypeKind.KSuspendFunction
}
val typeArguments = typeParameters.map {
ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false).toFirResolvedTypeRef()
}
fun createSuperType(kind: ConeFunctionalTypeKind): FirResolvedTypeRef {
return kind.classId(arity).toLookupTag()
.constructClassType(typeArguments.map { it.type }.toTypedArray(), isNullable = false)
.toFirResolvedTypeRef()
}
if (kind.isReflectType) {
superTypeRefs += StandardClassIds.KFunction.toLookupTag()
.constructClassType(arrayOf(typeArguments.last().type), isNullable = false)
.toFirResolvedTypeRef()
superTypeRefs += createSuperType(kind.nonReflectKind())
} else {
superTypeRefs += StandardClassIds.Function.toLookupTag()
.constructClassType(arrayOf(typeArguments.last().type), isNullable = false)
.toFirResolvedTypeRef()
}
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
containingFunctionSymbol = this@buildSimpleFunction.symbol
origin = FirDeclarationOrigin.BuiltIns
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
returnTypeRef = typeArgument
this.name = parameterName
symbol = FirValueParameterSymbol(parameterName)
defaultValue = null
isCrossinline = false
isNoinline = false
isVararg = false
}
}
dispatchReceiverType = classId.defaultType(this@klass.typeParameters.map { it.symbol })
kind.annotationOnInvokeClassId?.let { annotationClassId ->
annotations += buildAnnotation {
annotationTypeRef = annotationClassId
.constructClassLikeType(emptyArray(), isNullable = false)
.toFirResolvedTypeRef()
argumentMapping = FirEmptyAnnotationArgumentMapping
}
}
}
)
}
}
}
}
private fun ConeFunctionalTypeKind.classId(arity: Int) = ClassId(packageFqName, numberedClassName(arity))
}