[AA] KT-58580 Add KotlinDeclarationProviderMerger
- A proper merging strategy for declaration providers is required for cases where the main declaration provider created by `createDeclarationProvider` can't provide all declarations that the original declaration providers can provide. Then, only a sublist of the declaration providers should be merged, while keeping the unmergeable declaration providers intact. ^KT-58580 fixed
This commit is contained in:
committed by
Space Team
parent
fba0648005
commit
915c412929
+1
-1
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.analysis.api.lifetime.KtReadActionConfinementDefault
|
||||
import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtensionProvider
|
||||
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.StandaloneProjectFactory
|
||||
import org.jetbrains.kotlin.analysis.decompiler.psi.BuiltInDefinitionFile
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtBuiltinsModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModuleScopeProvider
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModuleScopeProviderImpl
|
||||
import org.jetbrains.kotlin.analysis.providers.*
|
||||
@@ -69,6 +68,7 @@ object AnalysisApiBaseTestServiceRegistrar: AnalysisApiTestServiceRegistrar() {
|
||||
} finally {
|
||||
BuiltInDefinitionFile.FILTER_OUT_CLASSES_EXISTING_AS_JVM_CLASS_FILES = filter
|
||||
}
|
||||
registerService(KotlinDeclarationProviderMerger::class.java, KotlinStaticDeclarationProviderMerger(project))
|
||||
registerService(KotlinPackageProviderFactory::class.java, KotlinStaticPackageProviderFactory(project, allKtFiles))
|
||||
registerService(KotlinReferenceProvidersService::class.java, HLApiReferenceProviderService::class.java)
|
||||
registerService(KotlinResolutionScopeProvider::class.java, KotlinByModulesResolutionScopeProvider::class.java)
|
||||
|
||||
+35
-4
@@ -49,9 +49,40 @@ public abstract class KotlinDeclarationProvider {
|
||||
|
||||
public abstract class KotlinDeclarationProviderFactory {
|
||||
public abstract fun createDeclarationProvider(scope: GlobalSearchScope, contextualModule: KtModule?): KotlinDeclarationProvider
|
||||
|
||||
public companion object {
|
||||
public fun getInstance(project: Project): KotlinDeclarationProviderFactory =
|
||||
project.getService(KotlinDeclarationProviderFactory::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
public fun Project.createDeclarationProvider(scope: GlobalSearchScope, module: KtModule?): KotlinDeclarationProvider {
|
||||
return getService(KotlinDeclarationProviderFactory::class.java)
|
||||
.createDeclarationProvider(scope, module)
|
||||
}
|
||||
/**
|
||||
* While the main declaration provider created via [createDeclarationProvider] is scope-based, there are other declaration providers which
|
||||
* are not, such as file-based declaration providers. Not all declarations provided by such declaration providers can be provided by the
|
||||
* main declaration provider, even if the correct scope is provided (such as a file-based scope). For example, the main declaration provider
|
||||
* may be based on an index which doesn't contain the declarations provided by file-based declaration providers.
|
||||
*
|
||||
* Hence, [KotlinDeclarationProvider]s cannot just be combined by combining the scopes of all declaration providers and calling
|
||||
* [createDeclarationProvider]. [KotlinDeclarationProviderMerger] should implement proper merging logic that takes these concerns into
|
||||
* account.
|
||||
*/
|
||||
public abstract class KotlinDeclarationProviderMerger {
|
||||
/**
|
||||
* Merges [declarationProviders] if possible, creating a combined declaration provider that should be more efficient compared to calling
|
||||
* separate declaration providers. Not all given declaration providers might be mergeable, or there might be multiple separate sets of
|
||||
* declaration providers which can be merged individually, so the resulting declaration provider may be a composite Kotlin declaration
|
||||
* provider.
|
||||
*/
|
||||
public abstract fun mergeDeclarationProviders(declarationProviders: List<KotlinDeclarationProvider>): KotlinDeclarationProvider
|
||||
|
||||
public companion object {
|
||||
public fun getInstance(project: Project): KotlinDeclarationProviderMerger =
|
||||
project.getService(KotlinDeclarationProviderMerger::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
public fun Project.createDeclarationProvider(scope: GlobalSearchScope, module: KtModule?): KotlinDeclarationProvider =
|
||||
KotlinDeclarationProviderFactory.getInstance(this).createDeclarationProvider(scope, module)
|
||||
|
||||
public fun Project.mergeDeclarationProviders(declarationProviders: List<KotlinDeclarationProvider>): KotlinDeclarationProvider =
|
||||
KotlinDeclarationProviderMerger.getInstance(this).mergeDeclarationProviders(declarationProviders)
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.analysis.providers.impl
|
||||
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProviderMerger
|
||||
import org.jetbrains.kotlin.analysis.providers.impl.declarationProviders.CompositeKotlinDeclarationProvider
|
||||
|
||||
public abstract class KotlinDeclarationProviderMergerBase : KotlinDeclarationProviderMerger() {
|
||||
override fun mergeDeclarationProviders(declarationProviders: List<KotlinDeclarationProvider>): KotlinDeclarationProvider {
|
||||
// We should flatten declaration providers before merging so that the merger has access to all declaration providers, and also after
|
||||
// merging because composite declaration providers may be created by the merger.
|
||||
return CompositeKotlinDeclarationProvider.createFlattened(
|
||||
mergeToList(
|
||||
CompositeKotlinDeclarationProvider.flatten(declarationProviders)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
protected abstract fun mergeToList(declarationProviders: List<KotlinDeclarationProvider>): List<KotlinDeclarationProvider>
|
||||
}
|
||||
+15
-3
@@ -21,13 +21,14 @@ import com.intellij.util.containers.CollectionFactory
|
||||
import com.intellij.util.indexing.FileContent
|
||||
import com.intellij.util.indexing.FileContentImpl
|
||||
import com.intellij.util.io.URLUtil
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinBuiltInDecompiler
|
||||
import org.jetbrains.kotlin.analysis.decompiler.stub.file.ClsKotlinBinaryClassCache
|
||||
import org.jetbrains.kotlin.analysis.decompiler.stub.file.KotlinClsStubBuilder
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProviderFactory
|
||||
import org.jetbrains.kotlin.analysis.providers.createDeclarationProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.impl.util.mergeOnly
|
||||
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.name.*
|
||||
@@ -39,7 +40,7 @@ import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerial
|
||||
|
||||
public class KotlinStaticDeclarationProvider internal constructor(
|
||||
private val index: KotlinStaticDeclarationIndex,
|
||||
private val scope: GlobalSearchScope,
|
||||
public val scope: GlobalSearchScope,
|
||||
) : KotlinDeclarationProvider() {
|
||||
|
||||
private val KtElement.inScope: Boolean
|
||||
@@ -118,7 +119,6 @@ public class KotlinStaticDeclarationProvider internal constructor(
|
||||
getTopLevelProperties(callableId).mapTo(this) { it.containingKtFile }
|
||||
getTopLevelFunctions(callableId).mapTo(this) { it.containingKtFile }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class KotlinStaticDeclarationProviderFactory(
|
||||
@@ -368,3 +368,15 @@ public class KotlinFakeClsStubsCache {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class KotlinStaticDeclarationProviderMerger(private val project: Project) : KotlinDeclarationProviderMergerBase() {
|
||||
override fun mergeToList(declarationProviders: List<KotlinDeclarationProvider>): List<KotlinDeclarationProvider> =
|
||||
declarationProviders.mergeOnly<_, KotlinStaticDeclarationProvider> { providers ->
|
||||
val combinedScope = GlobalSearchScope.union(providers.map { it.scope })
|
||||
project.createDeclarationProvider(combinedScope, module = null).apply {
|
||||
check(this is KotlinStaticDeclarationProvider) {
|
||||
"`KotlinStaticDeclarationProvider` can only be merged into a combined declaration provider of the same type."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-1
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
public class CompositeKotlinDeclarationProvider private constructor(
|
||||
private val providers: List<KotlinDeclarationProvider>
|
||||
public val providers: List<KotlinDeclarationProvider>
|
||||
) : KotlinDeclarationProvider() {
|
||||
override fun getClassLikeDeclarationByClassId(classId: ClassId): KtClassLikeDeclaration? {
|
||||
return providers.firstNotNullOfOrNull { it.getClassLikeDeclarationByClassId(classId) }
|
||||
@@ -75,5 +75,16 @@ public class CompositeKotlinDeclarationProvider private constructor(
|
||||
else -> CompositeKotlinDeclarationProvider(providers)
|
||||
}
|
||||
}
|
||||
|
||||
public fun createFlattened(providers: List<KotlinDeclarationProvider>): KotlinDeclarationProvider =
|
||||
create(if (providers.size > 1) flatten(providers) else providers)
|
||||
|
||||
public fun flatten(providers: List<KotlinDeclarationProvider>): List<KotlinDeclarationProvider> =
|
||||
providers.flatMap { provider ->
|
||||
when (provider) {
|
||||
is CompositeKotlinDeclarationProvider -> provider.providers
|
||||
else -> listOf(provider)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -141,6 +141,7 @@ public class StandaloneAnalysisAPISessionBuilder(
|
||||
kotlinCoreProjectEnvironment.environment.jarFileSystem as CoreJarFileSystem
|
||||
)
|
||||
)
|
||||
registerService(KotlinDeclarationProviderMerger::class.java, KotlinStaticDeclarationProviderMerger(this))
|
||||
registerService(KotlinPackageProviderFactory::class.java, KotlinStaticPackageProviderFactory(project, ktFiles))
|
||||
|
||||
registerService(KtAnalysisSessionProvider::class.java, KtFirAnalysisSessionProvider(this))
|
||||
|
||||
+4
@@ -159,6 +159,10 @@ internal fun configureProjectEnvironment(
|
||||
KotlinDeclarationProviderFactory::class.java,
|
||||
KotlinStaticDeclarationProviderFactory(project, ktFiles)
|
||||
)
|
||||
project.registerService(
|
||||
KotlinDeclarationProviderMerger::class.java,
|
||||
KotlinStaticDeclarationProviderMerger(project)
|
||||
)
|
||||
project.registerService(
|
||||
KotlinPackageProviderFactory::class.java,
|
||||
KotlinStaticPackageProviderFactory(project, ktFiles)
|
||||
|
||||
+2
-5
@@ -6,13 +6,11 @@
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.providers
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.caches.NullableCaffeineCache
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.llFirModuleData
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.createDeclarationProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.mergeDeclarationProviders
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirCompositeCachedSymbolNamesProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolNamesProvider
|
||||
@@ -118,8 +116,7 @@ internal class LLFirCombinedKotlinSymbolProvider private constructor(
|
||||
companion object {
|
||||
fun merge(session: LLFirSession, project: Project, providers: List<LLFirKotlinSymbolProvider>): FirSymbolProvider? =
|
||||
if (providers.size > 1) {
|
||||
val combinedScope = GlobalSearchScope.union(providers.map { it.session.llFirModuleData.ktModule.contentScope })
|
||||
val declarationProvider = project.createDeclarationProvider(combinedScope, session.ktModule)
|
||||
val declarationProvider = project.mergeDeclarationProviders(providers.map { it.declarationProvider })
|
||||
LLFirCombinedKotlinSymbolProvider(session, project, providers, declarationProvider)
|
||||
} else providers.singleOrNull()
|
||||
}
|
||||
|
||||
+2
@@ -26,6 +26,8 @@ import org.jetbrains.kotlin.psi.KtProperty
|
||||
* @see LLFirCombinedKotlinSymbolProvider
|
||||
*/
|
||||
internal abstract class LLFirKotlinSymbolProvider(session: FirSession) : FirSymbolProvider(session) {
|
||||
abstract val declarationProvider: KotlinDeclarationProvider
|
||||
|
||||
/**
|
||||
* This function is optimized for a known [classLikeDeclaration].
|
||||
*/
|
||||
|
||||
+2
@@ -109,6 +109,8 @@ internal class LLFirProvider(
|
||||
|
||||
@NoMutableState
|
||||
internal inner class SymbolProvider : LLFirKotlinSymbolProvider(session) {
|
||||
override val declarationProvider: KotlinDeclarationProvider get() = providerHelper.declarationProvider
|
||||
|
||||
override val symbolNamesProvider: FirSymbolNamesProvider get() = providerHelper.symbolNameCache
|
||||
|
||||
override fun getClassLikeSymbolByClassId(classId: ClassId): FirClassLikeSymbol<*>? {
|
||||
|
||||
+2
-2
@@ -6,7 +6,6 @@
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.providers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirFileBuilder
|
||||
import org.jetbrains.kotlin.analysis.providers.impl.declarationProviders.CompositeKotlinDeclarationProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.CompositeKotlinPackageProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolve.extensions.LLFirResolveExtensionTool
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolve.extensions.llResolveExtensionTool
|
||||
@@ -14,6 +13,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.util.FirElementFinder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.LLFirKotlinSymbolNamesProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinPackageProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.impl.declarationProviders.CompositeKotlinDeclarationProvider
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.config.AnalysisFlags
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
@@ -43,7 +43,7 @@ internal class LLFirProviderHelper(
|
||||
) {
|
||||
private val extensionTool: LLFirResolveExtensionTool? = firSession.llResolveExtensionTool
|
||||
|
||||
private val declarationProvider = CompositeKotlinDeclarationProvider.create(
|
||||
val declarationProvider = CompositeKotlinDeclarationProvider.create(
|
||||
listOfNotNull(
|
||||
mainDeclarationProvider,
|
||||
extensionTool?.declarationProvider,
|
||||
|
||||
+5
-5
@@ -5,10 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.stubBased.deserialization
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirKotlinSymbolProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.LLFirKotlinSymbolNamesProvider
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirKotlinSymbolProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.LLFirKotlinSymbolNamesProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.createDeclarationProvider
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
@@ -19,8 +19,8 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||
import org.jetbrains.kotlin.fir.deserialization.SingleModuleDataProvider
|
||||
import org.jetbrains.kotlin.fir.java.deserialization.JvmClassFileBasedSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.java.deserialization.KotlinBuiltins
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolNamesProvider
|
||||
import org.jetbrains.kotlin.fir.realPsi
|
||||
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.*
|
||||
@@ -52,10 +52,10 @@ internal open class JvmStubBasedFirDeserializedSymbolProvider(
|
||||
scope: GlobalSearchScope,
|
||||
private val initialOrigin: FirDeclarationOrigin
|
||||
) : LLFirKotlinSymbolProvider(session) {
|
||||
private val declarationProvider = project.createDeclarationProvider(scope, module = null)
|
||||
|
||||
private val moduleData = moduleDataProvider.getModuleData(null)
|
||||
|
||||
final override val declarationProvider = project.createDeclarationProvider(scope, module = null)
|
||||
|
||||
override val symbolNamesProvider: FirSymbolNamesProvider = LLFirKotlinSymbolNamesProvider.cached(session, declarationProvider)
|
||||
|
||||
private val typeAliasCache: FirCache<ClassId, FirTypeAliasSymbol?, StubBasedFirDeserializationContext?> =
|
||||
|
||||
Reference in New Issue
Block a user