diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt index 16c46f6df28..183b360cb77 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.fir.session -import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.annotations.TestOnly import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl @@ -147,16 +146,19 @@ object FirSessionFactory { register(FirProvider::class, firProvider) val symbolProviderForBinariesFromIncrementalCompilation = providerAndScopeForIncrementalCompilation?.let { - val javaSymbolProvider = projectEnvironment.getJavaSymbolProvider(this, moduleData, it.scope) - - KotlinDeserializedJvmSymbolsProvider( + FirCompositeSymbolProvider( this@session, - SingleModuleDataProvider(moduleData), - kotlinScopeProvider, - it.packagePartProvider, - projectEnvironment.getKotlinClassFinder(it.scope), - javaSymbolProvider, - projectEnvironment.getJavaClassFinder(it.scope) + listOfNotNull( + KotlinDeserializedJvmSymbolsProvider( + this@session, + SingleModuleDataProvider(moduleData), + kotlinScopeProvider, + it.packagePartProvider, + projectEnvironment.getKotlinClassFinder(it.scope), + projectEnvironment.getJavaClassFinder(it.scope) + ), + projectEnvironment.getJavaSymbolProvider(this, moduleData, it.scope) + ) ) } @@ -208,8 +210,6 @@ object FirSessionFactory { registerCommonComponents(languageVersionSettings) registerCommonJavaComponents() - val javaSymbolProvider = projectEnvironment.getJavaSymbolProvider(this, moduleDataProvider.allModuleData.last(), scope) - val kotlinScopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped) val deserializedProviderForIncrementalCompilation = KotlinDeserializedJvmSymbolsProvider( @@ -218,7 +218,6 @@ object FirSessionFactory { kotlinScopeProvider = kotlinScopeProvider, packagePartProvider = packagePartProvider, kotlinClassFinder = projectEnvironment.getKotlinClassFinder(scope), - javaSymbolProvider = javaSymbolProvider, javaClassFinder = projectEnvironment.getJavaClassFinder(scope) ) @@ -234,7 +233,7 @@ object FirSessionFactory { deserializedProviderForIncrementalCompilation, FirBuiltinSymbolProvider(this, builtinsModuleData, kotlinScopeProvider), FirCloneableSymbolProvider(this, builtinsModuleData, kotlinScopeProvider), - javaSymbolProvider, // TODO: looks like it can be removed + projectEnvironment.getJavaSymbolProvider(this, moduleDataProvider.allModuleData.last(), scope), FirDependenciesSymbolProviderImpl(this) ) ) diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/AbstractFirDeserializedSymbolsProvider.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/AbstractFirDeserializedSymbolsProvider.kt index 8500b5dab6a..179481412f1 100644 --- a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/AbstractFirDeserializedSymbolsProvider.kt +++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/AbstractFirDeserializedSymbolsProvider.kt @@ -100,8 +100,6 @@ abstract class AbstractFirDeserializedSymbolsProvider( val classPostProcessor: DeserializedClassPostProcessor ) : ClassMetadataFindResult() - class ClassWithoutMetadata(val symbol: FirRegularClassSymbol?) : ClassMetadataFindResult() - object ShouldDeserializeViaParent : ClassMetadataFindResult() } @@ -146,7 +144,6 @@ abstract class AbstractFirDeserializedSymbolsProvider( ) symbol to postProcessor } - is ClassMetadataFindResult.ClassWithoutMetadata -> result.symbol to null ClassMetadataFindResult.ShouldDeserializeViaParent -> findAndDeserializeClassViaParent(classId) to null null -> null to null } diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt index f333bf4c43c..7efb1de6513 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt @@ -42,7 +42,6 @@ import org.jetbrains.kotlin.load.java.JavaClassFinder import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.load.java.structure.impl.JavaElementImpl -import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName @@ -63,14 +62,22 @@ class JavaSymbolProvider( } private val classCache = - session.firCachesFactory.createCacheWithPostCompute( - createValue = ::findAndConvertJavaClass, + session.firCachesFactory.createCacheWithPostCompute( + createValue = { classId, _ -> + val foundClass = findClass(classId) + if (foundClass == null) { + null to null + } else { + FirRegularClassSymbol(classId) to foundClass + } + }, postCompute = { _, classSymbol, javaClass -> if (classSymbol != null && javaClass != null) { convertJavaClassToFir(classSymbol, javaClass) } } ) + private val packageCache = session.firCachesFactory.createCache(::findPackage) private val knownClassNamesInPackage = session.firCachesFactory.createCache?>(::getKnownClassNames) @@ -80,10 +87,9 @@ class JavaSymbolProvider( private val parentClassTypeParameterStackCache = mutableMapOf() private val parentClassEffectiveVisibilityCache = mutableMapOf() - private fun findClass( - classId: ClassId, - content: KotlinClassFinder.Result.ClassFileContent?, - ): JavaClass? = facade.findClass(JavaClassFinder.Request(classId, previouslyFoundClassFileContent = content?.content), searchScope) + private fun findClass(classId: ClassId): JavaClass? = + facade.findClass(JavaClassFinder.Request(classId), searchScope) + ?.takeIf { !it.hasDifferentClassId(classId) && !it.hasMetadataAnnotation() } @FirSymbolProviderInternals override fun getTopLevelCallableSymbolsTo(destination: MutableList>, packageFqName: FqName, name: Name) { @@ -133,27 +139,10 @@ class JavaSymbolProvider( } } - fun getFirJavaClass(classId: ClassId, content: KotlinClassFinder.Result.ClassFileContent? = null): FirRegularClassSymbol? { + private fun getFirJavaClass(classId: ClassId): FirRegularClassSymbol? { // Enforce loading of outer class first classId.outerClassId?.let { getFirJavaClass(it) } - - return classCache.getValue(classId, content) - } - - private fun findAndConvertJavaClass( - classId: ClassId, - content: KotlinClassFinder.Result.ClassFileContent? - ): Pair { - val foundClass = findClass(classId, content) - return if (foundClass == null || - foundClass.hasDifferentClassId(classId) || - foundClass.hasMetadataAnnotation() - ) { - null to null - } else { - val symbol = FirRegularClassSymbol(classId) - symbol to foundClass - } + return classCache.getValue(classId, null) } private fun JavaClass.hasDifferentClassId(lookupClassId: ClassId): Boolean = diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt index eb8ef821206..c98dc5d0b4e 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt @@ -42,7 +42,6 @@ open class KotlinDeserializedJvmSymbolsProvider( kotlinScopeProvider: FirKotlinScopeProvider, private val packagePartProvider: PackagePartProvider, private val kotlinClassFinder: KotlinClassFinder, - private val javaSymbolProvider: JavaSymbolProvider, javaClassFinder: JavaClassFinder, ) : AbstractFirDeserializedSymbolsProvider(session, moduleDataProvider, kotlinScopeProvider) { private val knownNameInPackageCache = KnownNameInPackageCache(session, javaClassFinder) @@ -102,9 +101,7 @@ open class KotlinDeserializedJvmSymbolsProvider( } val kotlinClass = when (result) { is KotlinClassFinder.Result.KotlinClass -> result - is KotlinClassFinder.Result.ClassFileContent -> { - return ClassMetadataFindResult.ClassWithoutMetadata(readClassFromClassFile(classId, result)) - } + is KotlinClassFinder.Result.ClassFileContent -> return null null -> return ClassMetadataFindResult.ShouldDeserializeViaParent } if (kotlinClass.kotlinJvmBinaryClass.classHeader.kind != KotlinClassHeader.Kind.CLASS) return null @@ -144,10 +141,6 @@ open class KotlinDeserializedJvmSymbolsProvider( symbol.fir.replaceDeprecation(symbol.fir.getDeprecationInfos(session.languageVersionSettings.apiVersion)) } - private fun readClassFromClassFile(classId: ClassId, classFile: KotlinClassFinder.Result.ClassFileContent): FirRegularClassSymbol? { - return javaSymbolProvider.getFirJavaClass(classId, classFile) - } - private fun KotlinClassFinder.Result.KotlinClass.extractMetadata(): Pair? { val data = kotlinJvmBinaryClass.classHeader.data ?: return null val strings = kotlinJvmBinaryClass.classHeader.strings ?: return null diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/providers/FirThreadSafeSymbolProviderWrapper.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/providers/FirThreadSafeSymbolProviderWrapper.kt deleted file mode 100644 index 9205617bd9a..00000000000 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/providers/FirThreadSafeSymbolProviderWrapper.kt +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.idea.fir.low.level.api.providers - -import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider -import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals -import org.jetbrains.kotlin.name.CallableId -import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol -import org.jetbrains.kotlin.idea.fir.low.level.api.annotations.PrivateForInline -import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name -import java.util.concurrent.locks.ReadWriteLock -import java.util.concurrent.locks.ReentrantReadWriteLock -import kotlin.concurrent.withLock - -internal class FirThreadSafeSymbolProviderWrapper(private val provider: FirSymbolProvider) : FirSymbolProvider(provider.session) { - private val lock = ReentrantReadWriteLock() - private val classesCache = ThreadSafeCache>(lock) - private val topLevelCache = ThreadSafeCache>>(lock) - private val packages = ThreadSafeCache(lock) - - override fun getClassLikeSymbolByFqName(classId: ClassId): FirClassLikeSymbol<*>? = - classesCache.getOrCompute(classId) { - provider.getClassLikeSymbolByFqName(classId) - } - - override fun getTopLevelCallableSymbols(packageFqName: FqName, name: Name): List> = - topLevelCache.getOrCompute(CallableId(packageFqName, name)) { - provider.getTopLevelCallableSymbols(packageFqName, name) - } ?: emptyList() - - override fun getTopLevelFunctionSymbols(packageFqName: FqName, name: Name): List { - return getTopLevelCallableSymbols(packageFqName, name).filterIsInstance() - } - - override fun getTopLevelPropertySymbols(packageFqName: FqName, name: Name): List { - return getTopLevelCallableSymbols(packageFqName, name).filterIsInstance() - } - - @FirSymbolProviderInternals - override fun getTopLevelCallableSymbolsTo(destination: MutableList>, packageFqName: FqName, name: Name) { - error("Should not be called for wrapper") - } - - @FirSymbolProviderInternals - override fun getTopLevelFunctionSymbolsTo(destination: MutableList, packageFqName: FqName, name: Name) { - destination += getTopLevelFunctionSymbols(packageFqName, name) - } - - @FirSymbolProviderInternals - override fun getTopLevelPropertySymbolsTo(destination: MutableList, packageFqName: FqName, name: Name) { - destination += getTopLevelPropertySymbols(packageFqName, name) - } - - override fun getPackage(fqName: FqName): FqName? = - packages.getOrCompute(fqName) { provider.getPackage(fqName) } -} - -private class ThreadSafeCache(private val lock: ReadWriteLock) { - private val map = HashMap() - - @OptIn(PrivateForInline::class) - inline fun getOrCompute(key: KEY, compute: () -> VALUE?): VALUE? { - var value = lock.readLock().withLock { map[key] } - if (value == null) { - lock.writeLock().withLock { - value = compute() ?: NULLABLE_VALUE - map[key] = value!! - } - } - @Suppress("UNCHECKED_CAST") - return when (value) { - NULLABLE_VALUE -> null - null -> error("We should not read null from map here") - else -> value as VALUE - } - } -} - -@Suppress("ClassName") -@PrivateForInline -internal object NULLABLE_VALUE \ No newline at end of file diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt index c10f0c17ed7..95abe6ea0d1 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt @@ -46,7 +46,6 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirIdeBuiltinsAndCl import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirIdeLibrariesSessionProvider import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirIdeProvider import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirModuleWithDependenciesSymbolProvider -import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirThreadSafeSymbolProviderWrapper import org.jetbrains.kotlin.idea.fir.low.level.api.util.checkCanceled import org.jetbrains.kotlin.load.java.JavaClassFinder import org.jetbrains.kotlin.load.java.JavaClassFinderImpl @@ -197,8 +196,6 @@ internal object FirIdeSessionFactory { registerCommonJavaComponents() registerJavaSpecificResolveComponents() - val javaSymbolProvider = JavaSymbolProvider(this, mainModuleData, project, searchScope) - val kotlinScopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped) val moduleDataProvider = project.stateConfigurator.createModuleDataProvider(mainModuleInfo) @@ -210,19 +207,16 @@ internal object FirIdeSessionFactory { @OptIn(ExperimentalStdlibApi::class) buildList { add( - FirThreadSafeSymbolProviderWrapper( - KotlinDeserializedJvmSymbolsProviderForIde( - this@session, - moduleDataProvider, - kotlinScopeProvider, - packagePartProvider, - kotlinClassFinder, - javaSymbolProvider, - javaClassFinder - ) + KotlinDeserializedJvmSymbolsProviderForIde( + this@session, + moduleDataProvider, + kotlinScopeProvider, + packagePartProvider, + kotlinClassFinder, + javaClassFinder ) ) - add(javaSymbolProvider) + add(JavaSymbolProvider(this@session, mainModuleData, project, searchScope)) addAll((builtinsAndCloneableSession.symbolProvider as FirCompositeSymbolProvider).providers) } ) @@ -244,11 +238,10 @@ internal object FirIdeSessionFactory { kotlinScopeProvider: FirKotlinScopeProvider, packagePartProvider: PackagePartProvider, kotlinClassFinder: KotlinClassFinder, - javaSymbolProvider: JavaSymbolProvider, javaClassFinder: JavaClassFinder ) : KotlinDeserializedJvmSymbolsProvider( session, moduleDataProvider, kotlinScopeProvider, packagePartProvider, kotlinClassFinder, - javaSymbolProvider, javaClassFinder + javaClassFinder ) { override fun getClass( classId: ClassId,