FIR: use FirCachesFactory in BuiltInsPackageFragment.tryGetSyntheticFunctionalInterface
This commit is contained in:
committed by
teamcityserver
parent
ba2315430b
commit
f361312e45
+130
-122
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.builtins.StandardNames
|
|||||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
|
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.fir.*
|
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.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.builder.buildRegularClass
|
import org.jetbrains.kotlin.fir.declarations.builder.buildRegularClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction
|
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction
|
||||||
@@ -47,11 +47,8 @@ open class FirBuiltinSymbolProvider(
|
|||||||
val moduleData: FirModuleData,
|
val moduleData: FirModuleData,
|
||||||
val kotlinScopeProvider: FirKotlinScopeProvider
|
val kotlinScopeProvider: FirKotlinScopeProvider
|
||||||
) : FirSymbolProvider(session) {
|
) : FirSymbolProvider(session) {
|
||||||
|
|
||||||
private data class SyntheticFunctionalInterfaceSymbolKey(val kind: FunctionClassKind, val arity: Int)
|
|
||||||
|
|
||||||
private val allPackageFragments = loadBuiltIns().groupBy { it.fqName }
|
private val allPackageFragments = loadBuiltIns().groupBy { it.fqName }
|
||||||
private val syntheticFunctionalInterfaceSymbols = mutableMapOf<SyntheticFunctionalInterfaceSymbolKey, FirRegularClassSymbol>()
|
private val syntheticFunctionalInterfaceCache = SyntheticFunctionalInterfaceCache(moduleData, kotlinScopeProvider)
|
||||||
|
|
||||||
private fun loadBuiltIns(): List<BuiltInsPackageFragment> {
|
private fun loadBuiltIns(): List<BuiltInsPackageFragment> {
|
||||||
val classLoader = this::class.java.classLoader
|
val classLoader = this::class.java.classLoader
|
||||||
@@ -61,7 +58,7 @@ open class FirBuiltinSymbolProvider(
|
|||||||
return packageFqNames.map { fqName ->
|
return packageFqNames.map { fqName ->
|
||||||
val resourcePath = BuiltInSerializerProtocol.getBuiltInsFilePath(fqName)
|
val resourcePath = BuiltInSerializerProtocol.getBuiltInsFilePath(fqName)
|
||||||
val inputStream = streamProvider(resourcePath) ?: throw IllegalStateException("Resource not found in classpath: $resourcePath")
|
val inputStream = streamProvider(resourcePath) ?: throw IllegalStateException("Resource not found in classpath: $resourcePath")
|
||||||
BuiltInsPackageFragment(inputStream, fqName)
|
BuiltInsPackageFragment(inputStream, fqName, moduleData, kotlinScopeProvider)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,19 +70,134 @@ open class FirBuiltinSymbolProvider(
|
|||||||
override fun getClassLikeSymbolByFqName(classId: ClassId): FirRegularClassSymbol? {
|
override fun getClassLikeSymbolByFqName(classId: ClassId): FirRegularClassSymbol? {
|
||||||
return allPackageFragments[classId.packageFqName]?.firstNotNullOfOrNull {
|
return allPackageFragments[classId.packageFqName]?.firstNotNullOfOrNull {
|
||||||
it.getClassLikeSymbolByFqName(classId)
|
it.getClassLikeSymbolByFqName(classId)
|
||||||
} ?: trySyntheticFunctionalInterface(classId)
|
} ?: syntheticFunctionalInterfaceCache.tryGetSyntheticFunctionalInterface(classId)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun trySyntheticFunctionalInterface(classId: ClassId): FirRegularClassSymbol? {
|
|
||||||
|
@FirSymbolProviderInternals
|
||||||
|
override fun getTopLevelCallableSymbolsTo(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) {
|
||||||
|
allPackageFragments[packageFqName]?.flatMapTo(destination) {
|
||||||
|
it.getTopLevelCallableSymbols(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@FirSymbolProviderInternals
|
||||||
|
override fun getTopLevelFunctionSymbolsTo(destination: MutableList<FirNamedFunctionSymbol>, packageFqName: FqName, name: Name) {
|
||||||
|
getTopLevelFunctionSymbolsToByPackageFragments(destination, packageFqName, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun getTopLevelFunctionSymbolsToByPackageFragments(destination: MutableList<FirNamedFunctionSymbol>, packageFqName: FqName, name: Name) {
|
||||||
|
allPackageFragments[packageFqName]?.flatMapTo(destination) {
|
||||||
|
it.getTopLevelFunctionSymbols(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@FirSymbolProviderInternals
|
||||||
|
override fun getTopLevelPropertySymbolsTo(destination: MutableList<FirPropertySymbol>, packageFqName: FqName, name: Name) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BuiltInsPackageFragment(
|
||||||
|
stream: InputStream, val fqName: FqName, val moduleData: FirModuleData,
|
||||||
|
val kotlinScopeProvider: FirKotlinScopeProvider,
|
||||||
|
) {
|
||||||
|
|
||||||
|
private val binaryVersionAndPackageFragment = BinaryVersionAndPackageFragment.createFromStream(stream)
|
||||||
|
|
||||||
|
val version: BuiltInsBinaryVersion get() = binaryVersionAndPackageFragment.version
|
||||||
|
val packageProto: ProtoBuf.PackageFragment get() = binaryVersionAndPackageFragment.packageFragment
|
||||||
|
|
||||||
|
private val nameResolver = NameResolverImpl(packageProto.strings, packageProto.qualifiedNames)
|
||||||
|
|
||||||
|
val classDataFinder = ProtoBasedClassDataFinder(packageProto, nameResolver, version) { SourceElement.NO_SOURCE }
|
||||||
|
|
||||||
|
private val memberDeserializer by lazy {
|
||||||
|
FirDeserializationContext.createForPackage(
|
||||||
|
fqName, packageProto.`package`, nameResolver, moduleData,
|
||||||
|
FirBuiltinAnnotationDeserializer(moduleData.session),
|
||||||
|
FirConstDeserializer(moduleData.session),
|
||||||
|
containerSource = null
|
||||||
|
).memberDeserializer
|
||||||
|
}
|
||||||
|
|
||||||
|
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, moduleData.session, moduleData,
|
||||||
|
null, kotlinScopeProvider, parentContext,
|
||||||
|
null,
|
||||||
|
origin = FirDeclarationOrigin.BuiltIns,
|
||||||
|
this::findAndDeserializeClass,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getClassLikeSymbolByFqName(classId: ClassId): FirRegularClassSymbol? =
|
||||||
|
findAndDeserializeClass(classId)
|
||||||
|
|
||||||
|
private fun findAndDeserializeClass(
|
||||||
|
classId: ClassId,
|
||||||
|
parentContext: FirDeserializationContext? = null,
|
||||||
|
): FirRegularClassSymbol? {
|
||||||
|
val classIdExists = classId in classDataFinder.allClassIds
|
||||||
|
if (!classIdExists) return null
|
||||||
|
return lookup.getValue(classId, parentContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getTopLevelCallableSymbols(name: Name): List<FirCallableSymbol<*>> {
|
||||||
|
return getTopLevelFunctionSymbols(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getTopLevelFunctionSymbols(name: Name): List<FirNamedFunctionSymbol> {
|
||||||
|
return packageProto.`package`.functionList.filter { nameResolver.getName(it.name) == name }.map {
|
||||||
|
memberDeserializer.loadFunction(it).symbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private data class BinaryVersionAndPackageFragment(
|
||||||
|
val version: BuiltInsBinaryVersion,
|
||||||
|
val packageFragment: ProtoBuf.PackageFragment,
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
fun createFromStream(stream: InputStream): BinaryVersionAndPackageFragment {
|
||||||
|
val version = BuiltInsBinaryVersion.readFrom(stream)
|
||||||
|
|
||||||
|
if (!version.isCompatible()) {
|
||||||
|
// TODO: report a proper diagnostic
|
||||||
|
throw UnsupportedOperationException(
|
||||||
|
"Kotlin built-in definition format version is not supported: " +
|
||||||
|
"expected ${BuiltInsBinaryVersion.INSTANCE}, actual $version. " +
|
||||||
|
"Please update Kotlin",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val packageFragment = ProtoBuf.PackageFragment.parseFrom(stream, BuiltInSerializerProtocol.extensionRegistry)
|
||||||
|
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) {
|
return with(classId) {
|
||||||
val className = relativeClassName.asString()
|
val className = relativeClassName.asString()
|
||||||
val kind = FunctionClassKind.byClassNamePrefix(packageFqName, className) ?: return@with null
|
val kind = FunctionClassKind.byClassNamePrefix(packageFqName, className) ?: return@with null
|
||||||
val prefix = kind.classNamePrefix
|
val prefix = kind.classNamePrefix
|
||||||
val arity = className.substring(prefix.length).toIntOrNull() ?: return null
|
val arity = className.substring(prefix.length).toIntOrNull() ?: return null
|
||||||
syntheticFunctionalInterfaceSymbols.getOrPut(SyntheticFunctionalInterfaceSymbolKey(kind, arity)) {
|
FirRegularClassSymbol(classId).apply symbol@{
|
||||||
FirRegularClassSymbol(this).apply symbol@{
|
|
||||||
buildRegularClass klass@{
|
buildRegularClass klass@{
|
||||||
moduleData = this@FirBuiltinSymbolProvider.moduleData
|
moduleData = this@SyntheticFunctionalInterfaceCache.moduleData
|
||||||
origin = FirDeclarationOrigin.BuiltIns
|
origin = FirDeclarationOrigin.BuiltIns
|
||||||
name = relativeClassName.shortName()
|
name = relativeClassName.shortName()
|
||||||
status = FirResolvedDeclarationStatusImpl(
|
status = FirResolvedDeclarationStatusImpl(
|
||||||
@@ -107,27 +219,27 @@ open class FirBuiltinSymbolProvider(
|
|||||||
typeParameters.addAll(
|
typeParameters.addAll(
|
||||||
(1..arity).map {
|
(1..arity).map {
|
||||||
buildTypeParameter {
|
buildTypeParameter {
|
||||||
moduleData = this@FirBuiltinSymbolProvider.moduleData
|
moduleData = this@SyntheticFunctionalInterfaceCache.moduleData
|
||||||
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
||||||
origin = FirDeclarationOrigin.BuiltIns
|
origin = FirDeclarationOrigin.BuiltIns
|
||||||
name = Name.identifier("P$it")
|
name = Name.identifier("P$it")
|
||||||
symbol = FirTypeParameterSymbol()
|
symbol = FirTypeParameterSymbol()
|
||||||
variance = Variance.IN_VARIANCE
|
variance = Variance.IN_VARIANCE
|
||||||
isReified = false
|
isReified = false
|
||||||
bounds += session.builtinTypes.nullableAnyType
|
bounds += moduleData.session.builtinTypes.nullableAnyType
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
typeParameters.add(
|
typeParameters.add(
|
||||||
buildTypeParameter {
|
buildTypeParameter {
|
||||||
moduleData = this@FirBuiltinSymbolProvider.moduleData
|
moduleData = this@SyntheticFunctionalInterfaceCache.moduleData
|
||||||
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
||||||
origin = FirDeclarationOrigin.BuiltIns
|
origin = FirDeclarationOrigin.BuiltIns
|
||||||
name = Name.identifier("R")
|
name = Name.identifier("R")
|
||||||
symbol = FirTypeParameterSymbol()
|
symbol = FirTypeParameterSymbol()
|
||||||
variance = Variance.OUT_VARIANCE
|
variance = Variance.OUT_VARIANCE
|
||||||
isReified = false
|
isReified = false
|
||||||
bounds += session.builtinTypes.nullableAnyType
|
bounds += moduleData.session.builtinTypes.nullableAnyType
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
val name = OperatorNameConventions.INVOKE
|
val name = OperatorNameConventions.INVOKE
|
||||||
@@ -196,7 +308,7 @@ open class FirBuiltinSymbolProvider(
|
|||||||
}
|
}
|
||||||
addDeclaration(
|
addDeclaration(
|
||||||
buildSimpleFunction {
|
buildSimpleFunction {
|
||||||
moduleData = this@FirBuiltinSymbolProvider.moduleData
|
moduleData = this@SyntheticFunctionalInterfaceCache.moduleData
|
||||||
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
||||||
origin = FirDeclarationOrigin.BuiltIns
|
origin = FirDeclarationOrigin.BuiltIns
|
||||||
returnTypeRef = typeArguments.last()
|
returnTypeRef = typeArguments.last()
|
||||||
@@ -209,7 +321,7 @@ open class FirBuiltinSymbolProvider(
|
|||||||
valueParameters += typeArguments.dropLast(1).mapIndexed { index, typeArgument ->
|
valueParameters += typeArguments.dropLast(1).mapIndexed { index, typeArgument ->
|
||||||
val parameterName = Name.identifier("p${index + 1}")
|
val parameterName = Name.identifier("p${index + 1}")
|
||||||
buildValueParameter {
|
buildValueParameter {
|
||||||
moduleData = this@FirBuiltinSymbolProvider.moduleData
|
moduleData = this@SyntheticFunctionalInterfaceCache.moduleData
|
||||||
origin = FirDeclarationOrigin.BuiltIns
|
origin = FirDeclarationOrigin.BuiltIns
|
||||||
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
||||||
returnTypeRef = typeArgument
|
returnTypeRef = typeArgument
|
||||||
@@ -228,111 +340,7 @@ open class FirBuiltinSymbolProvider(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun FunctionClassKind.classId(arity: Int) = ClassId(packageFqName, numberedClassName(arity))
|
private fun FunctionClassKind.classId(arity: Int) = ClassId(packageFqName, numberedClassName(arity))
|
||||||
|
|
||||||
@FirSymbolProviderInternals
|
|
||||||
override fun getTopLevelCallableSymbolsTo(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) {
|
|
||||||
allPackageFragments[packageFqName]?.flatMapTo(destination) {
|
|
||||||
it.getTopLevelCallableSymbols(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@FirSymbolProviderInternals
|
|
||||||
override fun getTopLevelFunctionSymbolsTo(destination: MutableList<FirNamedFunctionSymbol>, packageFqName: FqName, name: Name) {
|
|
||||||
getTopLevelFunctionSymbolsToByPackageFragments(destination, packageFqName, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun getTopLevelFunctionSymbolsToByPackageFragments(destination: MutableList<FirNamedFunctionSymbol>, packageFqName: FqName, name: Name) {
|
|
||||||
allPackageFragments[packageFqName]?.flatMapTo(destination) {
|
|
||||||
it.getTopLevelFunctionSymbols(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@FirSymbolProviderInternals
|
|
||||||
override fun getTopLevelPropertySymbolsTo(destination: MutableList<FirPropertySymbol>, packageFqName: FqName, name: Name) {
|
|
||||||
}
|
|
||||||
|
|
||||||
private inner class BuiltInsPackageFragment(stream: InputStream, val fqName: FqName) {
|
|
||||||
|
|
||||||
private val binaryVersionAndPackageFragment = BinaryVersionAndPackageFragment.createFromStream(stream)
|
|
||||||
|
|
||||||
val version: BuiltInsBinaryVersion get() = binaryVersionAndPackageFragment.version
|
|
||||||
val packageProto: ProtoBuf.PackageFragment get() = binaryVersionAndPackageFragment.packageFragment
|
|
||||||
|
|
||||||
private val nameResolver = NameResolverImpl(packageProto.strings, packageProto.qualifiedNames)
|
|
||||||
|
|
||||||
val classDataFinder = ProtoBasedClassDataFinder(packageProto, nameResolver, version) { SourceElement.NO_SOURCE }
|
|
||||||
|
|
||||||
private val memberDeserializer by lazy {
|
|
||||||
FirDeserializationContext.createForPackage(
|
|
||||||
fqName, packageProto.`package`, nameResolver, moduleData,
|
|
||||||
FirBuiltinAnnotationDeserializer(session),
|
|
||||||
FirConstDeserializer(session),
|
|
||||||
containerSource = null
|
|
||||||
).memberDeserializer
|
|
||||||
}
|
|
||||||
|
|
||||||
private val lookup = 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,
|
|
||||||
origin = FirDeclarationOrigin.BuiltIns,
|
|
||||||
this::findAndDeserializeClass,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getClassLikeSymbolByFqName(classId: ClassId): FirRegularClassSymbol? =
|
|
||||||
findAndDeserializeClass(classId)
|
|
||||||
|
|
||||||
private fun findAndDeserializeClass(
|
|
||||||
classId: ClassId,
|
|
||||||
parentContext: FirDeserializationContext? = null,
|
|
||||||
): FirRegularClassSymbol? {
|
|
||||||
val classIdExists = classId in classDataFinder.allClassIds
|
|
||||||
if (!classIdExists) return null
|
|
||||||
return lookup.getValue(classId, parentContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getTopLevelCallableSymbols(name: Name): List<FirCallableSymbol<*>> {
|
|
||||||
return getTopLevelFunctionSymbols(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getTopLevelFunctionSymbols(name: Name): List<FirNamedFunctionSymbol> {
|
|
||||||
return packageProto.`package`.functionList.filter { nameResolver.getName(it.name) == name }.map {
|
|
||||||
memberDeserializer.loadFunction(it).symbol
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private data class BinaryVersionAndPackageFragment(
|
|
||||||
val version: BuiltInsBinaryVersion,
|
|
||||||
val packageFragment: ProtoBuf.PackageFragment,
|
|
||||||
) {
|
|
||||||
companion object {
|
|
||||||
fun createFromStream(stream: InputStream): BinaryVersionAndPackageFragment {
|
|
||||||
val version = BuiltInsBinaryVersion.readFrom(stream)
|
|
||||||
|
|
||||||
if (!version.isCompatible()) {
|
|
||||||
// TODO: report a proper diagnostic
|
|
||||||
throw UnsupportedOperationException(
|
|
||||||
"Kotlin built-in definition format version is not supported: " +
|
|
||||||
"expected ${BuiltInsBinaryVersion.INSTANCE}, actual $version. " +
|
|
||||||
"Please update Kotlin",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val packageFragment = ProtoBuf.PackageFragment.parseFrom(stream, BuiltInSerializerProtocol.extensionRegistry)
|
|
||||||
return BinaryVersionAndPackageFragment(version, packageFragment)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user