KT-62859 [LL FIR] Compute origin per declaration in StubBasedFirDeserializedSymbolProvider

Since `createStubBasedFirSymbolProviderForClassFiles` works for
builtins (after 866368cf), the provider sometimes has to handle
declarations from builtins (`Any?.toString()` or `arrayOf`, for example)

To provide correct origin for such declarations, we have to compute
the origin on the per-declaration basis instead of always setting
`Library` or `BuiltIn` origin

Providing correct origins should improve the consistency of
deserialized fir declarations

To reduce duplication, `getContainerSource` now also uses
`getDeclarationOriginFor`
This commit is contained in:
Roman Golyshev
2023-10-26 13:39:46 +02:00
committed by teamcity
parent 16608c8a1f
commit ece43fe9c6
3 changed files with 45 additions and 13 deletions
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtFile
@LLFirInternals
class LLStubBasedLibrarySymbolProviderFactory(private val project: Project) : LLFirLibrarySymbolProviderFactory() {
@@ -107,7 +108,6 @@ private class StubBasedBuiltInsSymbolProvider(
kotlinScopeProvider,
project,
createBuiltInsScope(project),
FirDeclarationOrigin.BuiltIns
) {
private val syntheticFunctionInterfaceProvider = FirBuiltinSyntheticFunctionInterfaceProvider(
session,
@@ -119,6 +119,11 @@ private class StubBasedBuiltInsSymbolProvider(
return super.getClassLikeSymbolByClassId(classId)
?: syntheticFunctionInterfaceProvider.getClassLikeSymbolByClassId(classId)
}
override fun getDeclarationOriginFor(file: KtFile): FirDeclarationOrigin {
// this provider operates only on builtins files, no need to check anything
return FirDeclarationOrigin.BuiltIns
}
}
private fun createBuiltInsScope(project: Project): GlobalSearchScope {
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolNamesProvider
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.load.kotlin.FacadeClassSource
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.stubs.impl.*
@@ -53,7 +54,6 @@ internal open class StubBasedFirDeserializedSymbolProvider(
private val kotlinScopeProvider: FirKotlinScopeProvider,
project: Project,
scope: GlobalSearchScope,
private val initialOrigin: FirDeclarationOrigin
) : LLFirKotlinSymbolProvider(session) {
private val moduleData = moduleDataProvider.getModuleData(null)
@@ -83,6 +83,24 @@ internal open class StubBasedFirDeserializedSymbolProvider(
final override val packageProvider = project.createPackageProvider(scope)
/**
* Computes the origin for the declarations coming from [file].
*
* We assume that a stub Kotlin declaration might come only from Library or from BuiltIns.
* We do the decision based upon the extension of the [file].
*
* This method is left open so the inheritors can provide more optimal/strict implementations.
*/
protected open fun getDeclarationOriginFor(file: KtFile): FirDeclarationOrigin {
val virtualFile = file.virtualFile
return if (virtualFile.extension == BuiltInSerializerProtocol.BUILTINS_FILE_EXTENSION) {
FirDeclarationOrigin.BuiltIns
} else {
FirDeclarationOrigin.Library
}
}
private fun findAndDeserializeTypeAlias(
classId: ClassId,
context: StubBasedFirDeserializationContext?,
@@ -98,7 +116,8 @@ internal open class StubBasedFirDeserializedSymbolProvider(
classId.packageFqName,
classId.relativeClassName,
classLikeDeclaration,
null, null, symbol, initialOrigin
null, null, symbol,
initialOrigin = getDeclarationOriginFor(classLikeDeclaration.containingKtFile)
)
rootContext.memberDeserializer.loadTypeAlias(classLikeDeclaration, symbol)
}
@@ -131,7 +150,7 @@ internal open class StubBasedFirDeserializedSymbolProvider(
parentContext = context,
containerSource = JvmStubDeserializedContainerSource(classId),
deserializeNestedClass = this::getClass,
initialOrigin = initialOrigin
initialOrigin = getDeclarationOriginFor(classLikeDeclaration.containingKtFile)
)
return symbol
}
@@ -147,15 +166,20 @@ internal open class StubBasedFirDeserializedSymbolProvider(
return ArrayList<FirNamedFunctionSymbol>(topLevelFunctions.size).apply {
for (function in topLevelFunctions) {
val functionStub = function.stub as? KotlinFunctionStubImpl ?: loadStubByElement(function)
val containerSource = getFacadeContainerSource(function.containingKtFile, functionStub?.origin)
val functionFile = function.containingKtFile
val containerSource = getContainerSource(functionFile, functionStub?.origin)
val functionOrigin = getDeclarationOriginFor(functionFile)
if (initialOrigin != FirDeclarationOrigin.BuiltIns && containerSource.className.internalName in KotlinBuiltins) {
if (functionOrigin != FirDeclarationOrigin.BuiltIns &&
containerSource is FacadeClassSource &&
containerSource.className.internalName in KotlinBuiltins
) {
continue
}
val symbol = FirNamedFunctionSymbol(callableId)
val rootContext = StubBasedFirDeserializationContext
.createRootContext(session, moduleData, callableId, function, symbol, initialOrigin, containerSource)
.createRootContext(session, moduleData, callableId, function, symbol, functionOrigin, containerSource)
add(rootContext.memberDeserializer.loadFunction(function, null, session, symbol).symbol)
}
@@ -168,11 +192,13 @@ internal open class StubBasedFirDeserializedSymbolProvider(
return buildList {
for (property in topLevelProperties) {
val propertyStub = property.stub as? KotlinPropertyStubImpl ?: loadStubByElement(property)
val containerSource = getFacadeContainerSource(property.containingKtFile, propertyStub?.origin)
val propertyFile = property.containingKtFile
val containerSource = getContainerSource(propertyFile, propertyStub?.origin)
val propertyOrigin = getDeclarationOriginFor(propertyFile)
val symbol = FirPropertySymbol(callableId)
val rootContext = StubBasedFirDeserializationContext
.createRootContext(session, moduleData, callableId, property, symbol, initialOrigin, containerSource)
.createRootContext(session, moduleData, callableId, property, symbol, propertyOrigin, containerSource)
add(rootContext.memberDeserializer.loadProperty(property, null, symbol).symbol)
}
@@ -180,7 +206,7 @@ internal open class StubBasedFirDeserializedSymbolProvider(
}
private fun getContainerSource(file: KtFile, origin: KotlinStubOrigin?): DeserializedContainerSource {
if (file.virtualFile.extension == BuiltInSerializerProtocol.BUILTINS_FILE_EXTENSION) {
if (getDeclarationOriginFor(file) == FirDeclarationOrigin.BuiltIns) {
require(origin is KotlinStubOrigin.Facade) {
"Expected builtins file to have Facade origin, got origin=$origin instead"
}
@@ -289,6 +315,7 @@ internal open class StubBasedFirDeserializedSymbolProvider(
@FirSymbolProviderInternals
override fun getClassLikeSymbolByClassId(classId: ClassId, classLikeDeclaration: KtClassLikeDeclaration): FirClassLikeSymbol<*>? {
val annotationDeserializer = StubBasedAnnotationDeserializer(session)
val classOrigin = getDeclarationOriginFor(classLikeDeclaration.containingKtFile)
val deserializationContext = StubBasedFirDeserializationContext(
moduleData,
classId.packageFqName,
@@ -299,13 +326,13 @@ internal open class StubBasedFirDeserializedSymbolProvider(
parent = null,
containingSymbol = null,
owner = null,
initialOrigin
classOrigin
),
annotationDeserializer,
containerSource = null,
outerClassSymbol = null,
outerTypeParameters = emptyList(),
initialOrigin,
classOrigin,
classLikeDeclaration,
)
@@ -73,7 +73,7 @@ internal fun createStubBasedFirSymbolProviderForScopeLimitedByFiles(
project, baseScope, fileFilter,
symbolProviderFactory = { reducedScope: GlobalSearchScope ->
StubBasedFirDeserializedSymbolProvider(
session, moduleDataProvider, kotlinScopeProvider, project, reducedScope, FirDeclarationOrigin.Library,
session, moduleDataProvider, kotlinScopeProvider, project, reducedScope,
)
}
)