FIR: join KotlinDeserializedJvmSymbolsProvider and JavaSymbolProvider

This allows reusing class finder results.
This commit is contained in:
pyos
2021-09-09 13:48:42 +02:00
committed by TeamCityServer
parent 0181c80ddb
commit cac0cf6a50
7 changed files with 97 additions and 100 deletions
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
import org.jetbrains.kotlin.fir.FirRenderer
import org.jetbrains.kotlin.fir.createSessionForTests
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCompositeSymbolProvider
import org.jetbrains.kotlin.fir.resolve.symbolProvider
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.name.ClassId
@@ -142,13 +141,10 @@ abstract class AbstractFirTypeEnhancementTest : KtUsefulTestCase() {
val javaFirDump = StringBuilder().also { builder ->
val renderer = FirRenderer(builder)
val symbolProvider = session.symbolProvider as FirCompositeSymbolProvider
val javaProvider = symbolProvider.providers.filterIsInstance<JavaSymbolProvider>().first()
val processedJavaClasses = mutableSetOf<FirJavaClass>()
fun processClassWithChildren(psiClass: PsiClass, parentFqName: FqName) {
val classId = psiClass.classId(parentFqName)
val javaClass = javaProvider.getClassLikeSymbolByClassId(classId)?.fir
val javaClass = session.symbolProvider.getClassLikeSymbolByClassId(classId)?.fir
?: throw AssertionError(classId.asString())
if (javaClass !is FirJavaClass || javaClass in processedJavaClasses) {
return
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.extensions.extensionService
import org.jetbrains.kotlin.fir.extensions.registerExtensions
import org.jetbrains.kotlin.fir.java.FirCliSession
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.java.JavaSymbolProviderWrapper
import org.jetbrains.kotlin.fir.java.deserialization.KotlinDeserializedJvmSymbolsProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirDependenciesSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
@@ -146,19 +147,14 @@ object FirSessionFactory {
register(FirProvider::class, firProvider)
val symbolProviderForBinariesFromIncrementalCompilation = providerAndScopeForIncrementalCompilation?.let {
FirCompositeSymbolProvider(
KotlinDeserializedJvmSymbolsProvider(
this@session,
listOfNotNull(
KotlinDeserializedJvmSymbolsProvider(
this@session,
SingleModuleDataProvider(moduleData),
kotlinScopeProvider,
it.packagePartProvider,
projectEnvironment.getKotlinClassFinder(it.scope),
projectEnvironment.getJavaClassFinder(it.scope)
),
projectEnvironment.getJavaSymbolProvider(this, moduleData, it.scope)
)
SingleModuleDataProvider(moduleData),
kotlinScopeProvider,
it.packagePartProvider,
projectEnvironment.getKotlinClassFinder(it.scope),
projectEnvironment.getJavaClassFinder(it.scope),
projectEnvironment.getJavaSymbolProvider(this, moduleData, it.scope)
)
}
@@ -170,7 +166,7 @@ object FirSessionFactory {
listOfNotNull(
firProvider.symbolProvider,
symbolProviderForBinariesFromIncrementalCompilation,
projectEnvironment.getJavaSymbolProvider(this, moduleData, scope),
JavaSymbolProviderWrapper(this, projectEnvironment.getJavaSymbolProvider(this, moduleData, scope)),
dependenciesSymbolProvider,
)
)
@@ -213,12 +209,13 @@ object FirSessionFactory {
val kotlinScopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
val deserializedProviderForIncrementalCompilation = KotlinDeserializedJvmSymbolsProvider(
session = this,
moduleDataProvider = moduleDataProvider,
kotlinScopeProvider = kotlinScopeProvider,
packagePartProvider = packagePartProvider,
kotlinClassFinder = projectEnvironment.getKotlinClassFinder(scope),
javaClassFinder = projectEnvironment.getJavaClassFinder(scope)
this,
moduleDataProvider,
kotlinScopeProvider,
packagePartProvider,
projectEnvironment.getKotlinClassFinder(scope),
projectEnvironment.getJavaClassFinder(scope),
projectEnvironment.getJavaSymbolProvider(this, moduleDataProvider.allModuleData.last(), scope)
)
val builtinsModuleData = createModuleDataForBuiltins(
@@ -233,7 +230,6 @@ object FirSessionFactory {
deserializedProviderForIncrementalCompilation,
FirBuiltinSymbolProvider(this, builtinsModuleData, kotlinScopeProvider),
FirCloneableSymbolProvider(this, builtinsModuleData, kotlinScopeProvider),
projectEnvironment.getJavaSymbolProvider(this, moduleDataProvider.allModuleData.last(), scope),
FirDependenciesSymbolProviderImpl(this)
)
)
@@ -91,6 +91,10 @@ abstract class AbstractFirDeserializedSymbolsProvider(
// ------------------------ Deserialization methods ------------------------
sealed class ClassMetadataFindResult {
data class NoMetadata(
val classPostProcessor: DeserializedClassPostProcessor
) : ClassMetadataFindResult()
data class Metadata(
val nameResolver: NameResolver,
val classProto: ProtoBuf.Class,
@@ -125,6 +129,7 @@ abstract class AbstractFirDeserializedSymbolsProvider(
parentContext: FirDeserializationContext? = null
): Pair<FirRegularClassSymbol?, DeserializedClassPostProcessor?> {
return when (val result = extractClassMetadata(classId, parentContext)) {
is ClassMetadataFindResult.NoMetadata -> FirRegularClassSymbol(classId) to result.classPostProcessor
is ClassMetadataFindResult.Metadata -> {
val (nameResolver, classProto, annotationDeserializer, containingLibrary, sourceElement, postProcessor) = result
val moduleData = moduleDataProvider.getModuleData(containingLibrary) ?: return null to null
@@ -25,9 +25,7 @@ import org.jetbrains.kotlin.fir.types.constructClassLikeType
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.utils.DFS
class JavaScopeProvider(
val symbolProvider: JavaSymbolProvider
) : FirScopeProvider() {
object JavaScopeProvider : FirScopeProvider() {
override fun getUseSiteMemberScope(
klass: FirClass,
useSiteSession: FirSession,
@@ -74,7 +72,7 @@ class JavaScopeProvider(
return if (regularClass is FirJavaClass) useSiteSession.declaredMemberScopeWithLazyNestedScope(
regularClass,
existingNames = regularClass.existingNestedClassifierNames,
symbolProvider = symbolProvider
symbolProvider = useSiteSession.symbolProvider
) else useSiteSession.declaredMemberScope(regularClass)
}
@@ -51,59 +51,67 @@ import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
import org.jetbrains.kotlin.types.Variance.INVARIANT
import org.jetbrains.kotlin.util.OperatorNameConventions
@ThreadSafeMutableState
class JavaSymbolProvider(
session: FirSession,
val baseModuleData: FirModuleData,
val project: Project,
private val searchScope: GlobalSearchScope,
) : FirSymbolProvider(session) {
companion object {
val VALUE_METHOD_NAME = Name.identifier("value")
}
class JavaSymbolProviderWrapper(session: FirSession, private val javaSymbolProvider: JavaSymbolProvider) : FirSymbolProvider(session) {
private val classCache =
session.firCachesFactory.createCacheWithPostCompute<ClassId, FirRegularClassSymbol?, Nothing?, JavaClass?>(
createValue = { classId, _ ->
val foundClass = findClass(classId)
if (foundClass == null) {
null to null
} else {
FirRegularClassSymbol(classId) to foundClass
}
session.firCachesFactory.createCacheWithPostCompute(
createValue = { classId: ClassId, parentClassSymbol: FirRegularClassSymbol? ->
javaSymbolProvider.findClass(classId)?.let { FirRegularClassSymbol(classId) to (it to parentClassSymbol) }
?: null to (null to null)
},
postCompute = { _, classSymbol, javaClass ->
postCompute = { _, classSymbol, (javaClass, parentClassSymbol) ->
if (classSymbol != null && javaClass != null) {
convertJavaClassToFir(classSymbol, javaClass)
javaSymbolProvider.convertJavaClassToFir(classSymbol, parentClassSymbol, javaClass)
}
}
)
override fun getPackage(fqName: FqName): FqName? =
javaSymbolProvider.getPackage(fqName)
override fun getClassLikeSymbolByClassId(classId: ClassId): FirRegularClassSymbol? {
return try {
if (!javaSymbolProvider.hasTopLevelClassOf(classId)) return null
getFirJavaClass(classId)
} catch (e: ProcessCanceledException) {
null
}
}
private fun getFirJavaClass(classId: ClassId): FirRegularClassSymbol? =
classCache.getValue(classId, classId.outerClassId?.let { getFirJavaClass(it) })
@OptIn(FirSymbolProviderInternals::class)
override fun getTopLevelCallableSymbolsTo(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) {}
@OptIn(FirSymbolProviderInternals::class)
override fun getTopLevelFunctionSymbolsTo(destination: MutableList<FirNamedFunctionSymbol>, packageFqName: FqName, name: Name) {}
@OptIn(FirSymbolProviderInternals::class)
override fun getTopLevelPropertySymbolsTo(destination: MutableList<FirPropertySymbol>, packageFqName: FqName, name: Name) {}
}
@ThreadSafeMutableState
class JavaSymbolProvider(
private val session: FirSession,
val baseModuleData: FirModuleData,
val project: Project,
private val searchScope: GlobalSearchScope,
) {
companion object {
val VALUE_METHOD_NAME = Name.identifier("value")
}
private val packageCache = session.firCachesFactory.createCache(::findPackage)
private val knownClassNamesInPackage = session.firCachesFactory.createCache<FqName, Set<String>?>(::getKnownClassNames)
private val scopeProvider = JavaScopeProvider(this)
private val facade: KotlinJavaPsiFacade get() = KotlinJavaPsiFacade.getInstance(project)
private val parentClassTypeParameterStackCache = mutableMapOf<FirRegularClassSymbol, JavaTypeParameterStack>()
private val parentClassEffectiveVisibilityCache = mutableMapOf<FirRegularClassSymbol, EffectiveVisibility>()
private fun findClass(classId: ClassId): JavaClass? =
facade.findClass(JavaClassFinder.Request(classId), searchScope)
fun findClass(classId: ClassId, knownContent: ByteArray? = null): JavaClass? =
facade.findClass(JavaClassFinder.Request(classId, knownContent), searchScope)
?.takeIf { !it.hasDifferentClassId(classId) && !it.hasMetadataAnnotation() }
@FirSymbolProviderInternals
override fun getTopLevelCallableSymbolsTo(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) {
}
@FirSymbolProviderInternals
override fun getTopLevelFunctionSymbolsTo(destination: MutableList<FirNamedFunctionSymbol>, packageFqName: FqName, name: Name) {
}
@FirSymbolProviderInternals
override fun getTopLevelPropertySymbolsTo(destination: MutableList<FirPropertySymbol>, packageFqName: FqName, name: Name) {
}
private fun JavaTypeParameter.toFirTypeParameter(javaTypeParameterStack: JavaTypeParameterStack): FirTypeParameter {
return buildTypeParameter {
moduleData = this@JavaSymbolProvider.baseModuleData
@@ -131,19 +139,8 @@ class JavaSymbolProvider(
private fun List<JavaTypeParameter>.convertTypeParameters(stack: JavaTypeParameterStack): List<FirTypeParameter> =
map { it.toFirTypeParameter(stack) }
override fun getClassLikeSymbolByClassId(classId: ClassId): FirRegularClassSymbol? {
return try {
if (!hasTopLevelClassOf(classId)) return null
getFirJavaClass(classId)
} catch (e: ProcessCanceledException) {
null
}
}
private fun getFirJavaClass(classId: ClassId): FirRegularClassSymbol? {
// Enforce loading of outer class first
classId.outerClassId?.let { getFirJavaClass(it) }
return classCache.getValue(classId, null)
fun getPackage(fqName: FqName): FqName? {
return packageCache.getValue(fqName)?.fqName
}
private fun JavaClass.hasDifferentClassId(lookupClassId: ClassId): Boolean =
@@ -162,14 +159,13 @@ class JavaSymbolProvider(
}
}
private fun convertJavaClassToFir(classSymbol: FirRegularClassSymbol, javaClass: JavaClass): FirJavaClass {
fun convertJavaClassToFir(
classSymbol: FirRegularClassSymbol,
parentClassSymbol: FirRegularClassSymbol?,
javaClass: JavaClass,
): FirJavaClass {
val classId = classSymbol.classId
val javaTypeParameterStack = JavaTypeParameterStack()
val outerClassId = classId.outerClassId
val parentClassSymbol = if (outerClassId != null) {
getClassLikeSymbolByClassId(outerClassId)
} else null
if (parentClassSymbol != null) {
val parentStack = parentClassTypeParameterStackCache[parentClassSymbol]
@@ -179,7 +175,7 @@ class JavaSymbolProvider(
}
}
parentClassTypeParameterStackCache[classSymbol] = javaTypeParameterStack
val firJavaClass = createFirJavaClass(javaClass, classSymbol, outerClassId, parentClassSymbol, classId, javaTypeParameterStack)
val firJavaClass = createFirJavaClass(javaClass, classSymbol, parentClassSymbol, classId, javaTypeParameterStack)
parentClassTypeParameterStackCache.remove(classSymbol)
parentClassEffectiveVisibilityCache.remove(classSymbol)
@@ -197,7 +193,6 @@ class JavaSymbolProvider(
private fun createFirJavaClass(
javaClass: JavaClass,
classSymbol: FirRegularClassSymbol,
outerClassId: ClassId?,
parentClassSymbol: FirRegularClassSymbol?,
classId: ClassId,
javaTypeParameterStack: JavaTypeParameterStack,
@@ -213,12 +208,12 @@ class JavaSymbolProvider(
this@buildJavaClass.visibility = visibility
classKind = javaClass.classKind
modality = if (classKind == ClassKind.ANNOTATION_CLASS || classKind == ClassKind.ENUM_CLASS) Modality.FINAL else javaClass.modality
this.isTopLevel = outerClassId == null
this.isTopLevel = classId.outerClassId == null
isStatic = javaClass.isStatic
javaPackage = packageCache.getValue(classSymbol.classId.packageFqName)
this.javaTypeParameterStack = javaTypeParameterStack
existingNestedClassifierNames += javaClass.innerClassNames
scopeProvider = this@JavaSymbolProvider.scopeProvider
scopeProvider = JavaScopeProvider
val selfEffectiveVisibility = visibility.toEffectiveVisibility(parentClassSymbol?.toLookupTag(), forClass = true)
val parentEffectiveVisibility = parentClassSymbol?.let {
@@ -555,10 +550,6 @@ class JavaSymbolProvider(
isNullable = false,
)
override fun getPackage(fqName: FqName): FqName? {
return packageCache.getValue(fqName)?.fqName
}
private fun findPackage(fqName: FqName): JavaPackage? {
return try {
val facade = KotlinJavaPsiFacade.getInstance(project)
@@ -569,7 +560,7 @@ class JavaSymbolProvider(
}
}
private fun hasTopLevelClassOf(classId: ClassId): Boolean {
fun hasTopLevelClassOf(classId: ClassId): Boolean {
val knownNames = knownClassNamesInPackage.getValue(classId.packageFqName) ?: return true
return classId.relativeClassName.topLevelName() in knownNames
}
@@ -43,6 +43,7 @@ open class KotlinDeserializedJvmSymbolsProvider(
private val packagePartProvider: PackagePartProvider,
private val kotlinClassFinder: KotlinClassFinder,
javaClassFinder: JavaClassFinder,
private val javaSymbolProvider: JavaSymbolProvider
) : AbstractFirDeserializedSymbolsProvider(session, moduleDataProvider, kotlinScopeProvider) {
private val knownNameInPackageCache = KnownNameInPackageCache(session, javaClassFinder)
private val annotationsLoader = AnnotationsLoader(session, kotlinClassFinder)
@@ -101,7 +102,12 @@ open class KotlinDeserializedJvmSymbolsProvider(
}
val kotlinClass = when (result) {
is KotlinClassFinder.Result.KotlinClass -> result
is KotlinClassFinder.Result.ClassFileContent -> return null
is KotlinClassFinder.Result.ClassFileContent -> {
val javaClass = javaSymbolProvider.findClass(classId, result.content) ?: return null
return ClassMetadataFindResult.NoMetadata { symbol ->
javaSymbolProvider.convertJavaClassToFir(symbol, classId.outerClassId?.let(::getClass), javaClass)
}
}
null -> return ClassMetadataFindResult.ShouldDeserializeViaParent
}
if (kotlinClass.kotlinJvmBinaryClass.classHeader.kind != KotlinClassHeader.Kind.CLASS) return null
@@ -121,6 +127,9 @@ open class KotlinDeserializedJvmSymbolsProvider(
)
}
override fun getPackage(fqName: FqName): FqName? =
javaSymbolProvider.getPackage(fqName)
private fun loadAnnotationsFromClassFile(
kotlinClass: KotlinClassFinder.Result.KotlinClass,
symbol: FirRegularClassSymbol
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider
import org.jetbrains.kotlin.fir.deserialization.FirDeserializationContext
import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider
import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
import org.jetbrains.kotlin.fir.java.JavaSymbolProviderWrapper
import org.jetbrains.kotlin.fir.java.deserialization.KotlinDeserializedJvmSymbolsProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirDependenciesSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
@@ -150,7 +151,7 @@ internal object FirIdeSessionFactory {
this,
providers = listOf(
provider.symbolProvider,
JavaSymbolProvider(this@session, moduleData, project, searchScope),
JavaSymbolProviderWrapper(this@session, JavaSymbolProvider(this@session, moduleData, project, searchScope)),
),
dependencyProvider
)
@@ -214,10 +215,10 @@ internal object FirIdeSessionFactory {
kotlinScopeProvider,
packagePartProvider,
kotlinClassFinder,
javaClassFinder
javaClassFinder,
JavaSymbolProvider(this@session, mainModuleData, project, searchScope)
)
)
add(JavaSymbolProvider(this@session, mainModuleData, project, searchScope))
addAll((builtinsAndCloneableSession.symbolProvider as FirCompositeSymbolProvider).providers)
}
)
@@ -239,10 +240,11 @@ internal object FirIdeSessionFactory {
kotlinScopeProvider: FirKotlinScopeProvider,
packagePartProvider: PackagePartProvider,
kotlinClassFinder: KotlinClassFinder,
javaClassFinder: JavaClassFinder
javaClassFinder: JavaClassFinder,
javaSymbolProvider: JavaSymbolProvider
) : KotlinDeserializedJvmSymbolsProvider(
session, moduleDataProvider, kotlinScopeProvider, packagePartProvider, kotlinClassFinder,
javaClassFinder
javaClassFinder, javaSymbolProvider
) {
override fun getClass(
classId: ClassId,