[LL FIR] KT-57455 Avoid creating optional annotation class providers

- An `OptionalAnnotationClassesProvider` only needs to be created if the
  package part provider may even have optional annotation classes.
- In the IDE case, the package part provider never provides optional
  annotation classes, so especially in the IDE, we can avoid a lot of
  useless symbol providers with this.
This commit is contained in:
Marco Pennekamp
2023-03-20 20:14:21 +01:00
committed by Space Team
parent d3be38476a
commit f9785c1050
6 changed files with 53 additions and 15 deletions
@@ -35,7 +35,7 @@ internal object LLFirLibraryProviderFactory {
val packagePartProvider = project.createPackagePartProvider(scope) val packagePartProvider = project.createPackagePartProvider(scope)
return LLFirModuleWithDependenciesSymbolProvider( return LLFirModuleWithDependenciesSymbolProvider(
session, session,
providers = listOf( providers = listOfNotNull(
JvmClassFileBasedSymbolProvider( JvmClassFileBasedSymbolProvider(
session, session,
moduleDataProvider, moduleDataProvider,
@@ -44,7 +44,7 @@ internal object LLFirLibraryProviderFactory {
VirtualFileFinderFactory.getInstance(project).create(scope), VirtualFileFinderFactory.getInstance(project).create(scope),
LLFirJavaFacadeForBinaries(session, builtinTypes, project.createJavaClassFinder(scope), moduleDataProvider) LLFirJavaFacadeForBinaries(session, builtinTypes, project.createJavaClassFinder(scope), moduleDataProvider)
), ),
OptionalAnnotationClassesProvider(session, moduleDataProvider, kotlinScopeProvider, packagePartProvider), OptionalAnnotationClassesProvider.createIfNeeded(session, moduleDataProvider, kotlinScopeProvider, packagePartProvider),
), ),
LLFirDependenciesSymbolProvider(session, listOf(builtinSymbolProvider)), LLFirDependenciesSymbolProvider(session, listOf(builtinSymbolProvider)),
) )
@@ -60,18 +60,16 @@ internal object LLFirLibraryProviderFactory {
): List<FirSymbolProvider> { ): List<FirSymbolProvider> {
val moduleDataProvider = SingleModuleDataProvider(moduleData) val moduleDataProvider = SingleModuleDataProvider(moduleData)
val packagePartProvider = project.createPackagePartProvider(scope) val packagePartProvider = project.createPackagePartProvider(scope)
return buildList { return listOfNotNull(
add( JvmClassFileBasedSymbolProvider(
JvmClassFileBasedSymbolProvider( session,
session, moduleDataProvider,
moduleDataProvider, kotlinScopeProvider,
kotlinScopeProvider, packagePartProvider,
packagePartProvider, VirtualFileFinderFactory.getInstance(project).create(scope),
VirtualFileFinderFactory.getInstance(project).create(scope), LLFirJavaFacadeForBinaries(session, builtinTypes, project.createJavaClassFinder(scope), moduleDataProvider)
LLFirJavaFacadeForBinaries(session, builtinTypes, project.createJavaClassFinder(scope), moduleDataProvider) ),
) OptionalAnnotationClassesProvider.createIfNeeded(session, moduleDataProvider, kotlinScopeProvider, packagePartProvider),
) )
add(OptionalAnnotationClassesProvider(session, moduleDataProvider, kotlinScopeProvider, packagePartProvider))
}
} }
} }
@@ -37,6 +37,7 @@ internal class PackagePartProviderTestImpl(
return providers.flatMapTo(mutableSetOf()) { it.getAllOptionalAnnotationClasses() }.toList() return providers.flatMapTo(mutableSetOf()) { it.getAllOptionalAnnotationClasses() }.toList()
} }
override fun mayHaveOptionalAnnotationClasses(): Boolean = providers.any { it.mayHaveOptionalAnnotationClasses() }
} }
} }
} }
@@ -84,4 +84,28 @@ class OptionalAnnotationClassesProvider(
override fun getPackage(fqName: FqName): FqName? = override fun getPackage(fqName: FqName): FqName? =
if (optionalAnnotationClassesAndPackages.second.contains(fqName.asString())) fqName else null if (optionalAnnotationClassesAndPackages.second.contains(fqName.asString())) fqName else null
companion object {
/**
* Creates a new [OptionalAnnotationClassesProvider] if [packagePartProvider] has any optional annotation classes. Otherwise, the
* symbol provider does not need to be created because it would provide no symbols.
*/
fun createIfNeeded(
session: FirSession,
moduleDataProvider: ModuleDataProvider,
kotlinScopeProvider: FirKotlinScopeProvider,
packagePartProvider: PackagePartProvider,
defaultDeserializationOrigin: FirDeclarationOrigin = FirDeclarationOrigin.Library,
): OptionalAnnotationClassesProvider? {
if (!packagePartProvider.mayHaveOptionalAnnotationClasses()) return null
return OptionalAnnotationClassesProvider(
session,
moduleDataProvider,
kotlinScopeProvider,
packagePartProvider,
defaultDeserializationOrigin,
)
}
}
} }
@@ -68,4 +68,7 @@ class IncrementalPackagePartProvider(
override fun getAllOptionalAnnotationClasses(): List<ClassData> = override fun getAllOptionalAnnotationClasses(): List<ClassData> =
moduleMappings.flatMap(JvmPackagePartProviderBase.Companion::getAllOptionalAnnotationClasses) + moduleMappings.flatMap(JvmPackagePartProviderBase.Companion::getAllOptionalAnnotationClasses) +
parent.getAllOptionalAnnotationClasses() parent.getAllOptionalAnnotationClasses()
override fun mayHaveOptionalAnnotationClasses(): Boolean =
moduleMappings.any { it.moduleData.optionalAnnotations.isNotEmpty() } || parent.mayHaveOptionalAnnotationClasses()
} }
@@ -66,6 +66,11 @@ abstract class JvmPackagePartProviderBase<MappingsKey> : PackageAndMetadataPartP
getAllOptionalAnnotationClasses(module.mapping) getAllOptionalAnnotationClasses(module.mapping)
} }
override fun mayHaveOptionalAnnotationClasses(): Boolean {
// `loadedModules` is mutable, so even a package part provider without optional annotation classes may have some in the future.
return true
}
companion object { companion object {
fun getAllOptionalAnnotationClasses(module: ModuleMapping): List<ClassData> { fun getAllOptionalAnnotationClasses(module: ModuleMapping): List<ClassData> {
val data = module.moduleData val data = module.moduleData
@@ -28,6 +28,11 @@ interface PackagePartProvider {
fun getAllOptionalAnnotationClasses(): List<ClassData> fun getAllOptionalAnnotationClasses(): List<ClassData>
/**
* Returns `true` if [getAllOptionalAnnotationClasses] may return a non-empty list.
*/
fun mayHaveOptionalAnnotationClasses(): Boolean
object Empty : PackagePartProvider { object Empty : PackagePartProvider {
override fun findPackageParts(packageFqName: String): List<String> = emptyList() override fun findPackageParts(packageFqName: String): List<String> = emptyList()
@@ -35,6 +40,8 @@ interface PackagePartProvider {
override fun getAllOptionalAnnotationClasses(): List<ClassData> = emptyList() override fun getAllOptionalAnnotationClasses(): List<ClassData> = emptyList()
override fun mayHaveOptionalAnnotationClasses(): Boolean = false
override fun computePackageSetWithNonClassDeclarations(): Set<String> = emptySet() override fun computePackageSetWithNonClassDeclarations(): Set<String> = emptySet()
} }
} }