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.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtFile
@LLFirInternals @LLFirInternals
class LLStubBasedLibrarySymbolProviderFactory(private val project: Project) : LLFirLibrarySymbolProviderFactory() { class LLStubBasedLibrarySymbolProviderFactory(private val project: Project) : LLFirLibrarySymbolProviderFactory() {
@@ -107,7 +108,6 @@ private class StubBasedBuiltInsSymbolProvider(
kotlinScopeProvider, kotlinScopeProvider,
project, project,
createBuiltInsScope(project), createBuiltInsScope(project),
FirDeclarationOrigin.BuiltIns
) { ) {
private val syntheticFunctionInterfaceProvider = FirBuiltinSyntheticFunctionInterfaceProvider( private val syntheticFunctionInterfaceProvider = FirBuiltinSyntheticFunctionInterfaceProvider(
session, session,
@@ -119,6 +119,11 @@ private class StubBasedBuiltInsSymbolProvider(
return super.getClassLikeSymbolByClassId(classId) return super.getClassLikeSymbolByClassId(classId)
?: syntheticFunctionInterfaceProvider.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 { 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.resolve.providers.FirSymbolProviderInternals
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.load.kotlin.FacadeClassSource
import org.jetbrains.kotlin.name.* import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.stubs.impl.* import org.jetbrains.kotlin.psi.stubs.impl.*
@@ -53,7 +54,6 @@ internal open class StubBasedFirDeserializedSymbolProvider(
private val kotlinScopeProvider: FirKotlinScopeProvider, private val kotlinScopeProvider: FirKotlinScopeProvider,
project: Project, project: Project,
scope: GlobalSearchScope, scope: GlobalSearchScope,
private val initialOrigin: FirDeclarationOrigin
) : LLFirKotlinSymbolProvider(session) { ) : LLFirKotlinSymbolProvider(session) {
private val moduleData = moduleDataProvider.getModuleData(null) private val moduleData = moduleDataProvider.getModuleData(null)
@@ -83,6 +83,24 @@ internal open class StubBasedFirDeserializedSymbolProvider(
final override val packageProvider = project.createPackageProvider(scope) 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( private fun findAndDeserializeTypeAlias(
classId: ClassId, classId: ClassId,
context: StubBasedFirDeserializationContext?, context: StubBasedFirDeserializationContext?,
@@ -98,7 +116,8 @@ internal open class StubBasedFirDeserializedSymbolProvider(
classId.packageFqName, classId.packageFqName,
classId.relativeClassName, classId.relativeClassName,
classLikeDeclaration, classLikeDeclaration,
null, null, symbol, initialOrigin null, null, symbol,
initialOrigin = getDeclarationOriginFor(classLikeDeclaration.containingKtFile)
) )
rootContext.memberDeserializer.loadTypeAlias(classLikeDeclaration, symbol) rootContext.memberDeserializer.loadTypeAlias(classLikeDeclaration, symbol)
} }
@@ -131,7 +150,7 @@ internal open class StubBasedFirDeserializedSymbolProvider(
parentContext = context, parentContext = context,
containerSource = JvmStubDeserializedContainerSource(classId), containerSource = JvmStubDeserializedContainerSource(classId),
deserializeNestedClass = this::getClass, deserializeNestedClass = this::getClass,
initialOrigin = initialOrigin initialOrigin = getDeclarationOriginFor(classLikeDeclaration.containingKtFile)
) )
return symbol return symbol
} }
@@ -147,15 +166,20 @@ internal open class StubBasedFirDeserializedSymbolProvider(
return ArrayList<FirNamedFunctionSymbol>(topLevelFunctions.size).apply { return ArrayList<FirNamedFunctionSymbol>(topLevelFunctions.size).apply {
for (function in topLevelFunctions) { for (function in topLevelFunctions) {
val functionStub = function.stub as? KotlinFunctionStubImpl ?: loadStubByElement(function) 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 continue
} }
val symbol = FirNamedFunctionSymbol(callableId) val symbol = FirNamedFunctionSymbol(callableId)
val rootContext = StubBasedFirDeserializationContext 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) add(rootContext.memberDeserializer.loadFunction(function, null, session, symbol).symbol)
} }
@@ -168,11 +192,13 @@ internal open class StubBasedFirDeserializedSymbolProvider(
return buildList { return buildList {
for (property in topLevelProperties) { for (property in topLevelProperties) {
val propertyStub = property.stub as? KotlinPropertyStubImpl ?: loadStubByElement(property) 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 symbol = FirPropertySymbol(callableId)
val rootContext = StubBasedFirDeserializationContext 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) add(rootContext.memberDeserializer.loadProperty(property, null, symbol).symbol)
} }
@@ -180,7 +206,7 @@ internal open class StubBasedFirDeserializedSymbolProvider(
} }
private fun getContainerSource(file: KtFile, origin: KotlinStubOrigin?): DeserializedContainerSource { 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) { require(origin is KotlinStubOrigin.Facade) {
"Expected builtins file to have Facade origin, got origin=$origin instead" "Expected builtins file to have Facade origin, got origin=$origin instead"
} }
@@ -289,6 +315,7 @@ internal open class StubBasedFirDeserializedSymbolProvider(
@FirSymbolProviderInternals @FirSymbolProviderInternals
override fun getClassLikeSymbolByClassId(classId: ClassId, classLikeDeclaration: KtClassLikeDeclaration): FirClassLikeSymbol<*>? { override fun getClassLikeSymbolByClassId(classId: ClassId, classLikeDeclaration: KtClassLikeDeclaration): FirClassLikeSymbol<*>? {
val annotationDeserializer = StubBasedAnnotationDeserializer(session) val annotationDeserializer = StubBasedAnnotationDeserializer(session)
val classOrigin = getDeclarationOriginFor(classLikeDeclaration.containingKtFile)
val deserializationContext = StubBasedFirDeserializationContext( val deserializationContext = StubBasedFirDeserializationContext(
moduleData, moduleData,
classId.packageFqName, classId.packageFqName,
@@ -299,13 +326,13 @@ internal open class StubBasedFirDeserializedSymbolProvider(
parent = null, parent = null,
containingSymbol = null, containingSymbol = null,
owner = null, owner = null,
initialOrigin classOrigin
), ),
annotationDeserializer, annotationDeserializer,
containerSource = null, containerSource = null,
outerClassSymbol = null, outerClassSymbol = null,
outerTypeParameters = emptyList(), outerTypeParameters = emptyList(),
initialOrigin, classOrigin,
classLikeDeclaration, classLikeDeclaration,
) )
@@ -73,7 +73,7 @@ internal fun createStubBasedFirSymbolProviderForScopeLimitedByFiles(
project, baseScope, fileFilter, project, baseScope, fileFilter,
symbolProviderFactory = { reducedScope: GlobalSearchScope -> symbolProviderFactory = { reducedScope: GlobalSearchScope ->
StubBasedFirDeserializedSymbolProvider( StubBasedFirDeserializedSymbolProvider(
session, moduleDataProvider, kotlinScopeProvider, project, reducedScope, FirDeclarationOrigin.Library, session, moduleDataProvider, kotlinScopeProvider, project, reducedScope,
) )
} }
) )