[AA] Add KotlinPackageProviderMerger
- In parallel to Kotlin declaration provider merging, we need a proper merging strategy for package providers as well, because resolve extensions may define additional package providers. - Additionally, other non-scope-based package providers may be added in the future, and the merger preserves these out of the box. ^KT-61791
This commit is contained in:
committed by
Space Team
parent
c63dde4f7e
commit
b9e3d848a6
+22
-1
@@ -76,6 +76,27 @@ public abstract class KotlinPackageProviderFactory {
|
||||
public abstract fun createPackageProvider(searchScope: GlobalSearchScope): KotlinPackageProvider
|
||||
}
|
||||
|
||||
/**
|
||||
* [KotlinPackageProviderMerger] allows merging multiple [KotlinPackageProvider]s into a more efficient package provider.
|
||||
*
|
||||
* Package providers should not be naively merged by combining scopes and calling [createPackageProvider], because there may be additional
|
||||
* package providers which do not operate based on scopes (e.g. resolve extension package providers).
|
||||
*/
|
||||
public abstract class KotlinPackageProviderMerger {
|
||||
/**
|
||||
* Merges [packageProviders] if possible, creating a combined package provider that should be more efficient compared to invoking
|
||||
* separate package providers.
|
||||
*/
|
||||
public abstract fun mergePackageProviders(packageProviders: List<KotlinPackageProvider>): KotlinPackageProvider
|
||||
|
||||
public companion object {
|
||||
public fun getInstance(project: Project): KotlinPackageProviderMerger = project.getService(KotlinPackageProviderMerger::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
public fun Project.createPackageProvider(searchScope: GlobalSearchScope): KotlinPackageProvider =
|
||||
this.getService(KotlinPackageProviderFactory::class.java)
|
||||
.createPackageProvider(searchScope)
|
||||
.createPackageProvider(searchScope)
|
||||
|
||||
public fun Project.mergePackageProviders(packageProviders: List<KotlinPackageProvider>): KotlinPackageProvider =
|
||||
KotlinPackageProviderMerger.getInstance(this).mergePackageProviders(packageProviders)
|
||||
|
||||
+2
-4
@@ -13,11 +13,9 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.platform.jvm.isJvm
|
||||
|
||||
|
||||
public abstract class KotlinPackageProviderBase(
|
||||
protected val
|
||||
project: Project,
|
||||
protected val searchScope: GlobalSearchScope
|
||||
protected val project: Project,
|
||||
public val searchScope: GlobalSearchScope,
|
||||
) : KotlinPackageProvider() {
|
||||
|
||||
override fun doesPackageExist(packageFqName: FqName, platform: TargetPlatform): Boolean {
|
||||
|
||||
+17
-2
@@ -9,13 +9,16 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinPackageProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinPackageProviderFactory
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinPackageProviderMerger
|
||||
import org.jetbrains.kotlin.analysis.providers.createPackageProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.impl.packageProviders.CompositeKotlinPackageProvider
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
public class KotlinStaticPackageProvider(
|
||||
project: Project,
|
||||
scope: GlobalSearchScope,
|
||||
internal val scope: GlobalSearchScope,
|
||||
files: Collection<KtFile>
|
||||
) : KotlinPackageProviderBase(project, scope) {
|
||||
private val kotlinPackageToSubPackages: Map<FqName, Set<Name>> = run {
|
||||
@@ -48,4 +51,16 @@ public class KotlinStaticPackageProviderFactory(
|
||||
override fun createPackageProvider(searchScope: GlobalSearchScope): KotlinPackageProvider {
|
||||
return KotlinStaticPackageProvider(project, searchScope, files)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class KotlinStaticPackageProviderMerger(private val project: Project) : KotlinPackageProviderMerger() {
|
||||
override fun mergePackageProviders(packageProviders: List<KotlinPackageProvider>): KotlinPackageProvider =
|
||||
packageProviders.mergeSpecificProviders<_, KotlinStaticPackageProvider>(CompositeKotlinPackageProvider.factory) { providers ->
|
||||
val combinedScope = GlobalSearchScope.union(providers.map { it.scope })
|
||||
project.createPackageProvider(combinedScope).apply {
|
||||
check(this is KotlinStaticPackageProvider) {
|
||||
"`${KotlinStaticPackageProvider::class.simpleName}` can only be merged into a combined package provider of the same type."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.packageProviders
|
||||
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinPackageProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.impl.KotlinCompositeProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.impl.KotlinCompositeProviderFactory
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
|
||||
public class CompositeKotlinPackageProvider private constructor(
|
||||
override val providers: List<KotlinPackageProvider>,
|
||||
) : KotlinPackageProvider(), KotlinCompositeProvider<KotlinPackageProvider> {
|
||||
override fun doesPackageExist(packageFqName: FqName, platform: TargetPlatform): Boolean {
|
||||
return providers.any { it.doesPackageExist(packageFqName, platform) }
|
||||
}
|
||||
|
||||
override fun doesKotlinOnlyPackageExist(packageFqName: FqName): Boolean {
|
||||
return providers.any { it.doesKotlinOnlyPackageExist(packageFqName) }
|
||||
}
|
||||
|
||||
override fun doesPlatformSpecificPackageExist(packageFqName: FqName, platform: TargetPlatform): Boolean {
|
||||
return providers.any { it.doesPlatformSpecificPackageExist(packageFqName, platform) }
|
||||
}
|
||||
|
||||
override fun getSubPackageFqNames(packageFqName: FqName, platform: TargetPlatform, nameFilter: (Name) -> Boolean): Set<Name> {
|
||||
return providers.flatMapTo(mutableSetOf()) { it.getSubPackageFqNames(packageFqName, platform, nameFilter) }
|
||||
}
|
||||
|
||||
override fun getKotlinOnlySubPackagesFqNames(packageFqName: FqName, nameFilter: (Name) -> Boolean): Set<Name> {
|
||||
return providers.flatMapTo(mutableSetOf()) { it.getKotlinOnlySubPackagesFqNames(packageFqName, nameFilter) }
|
||||
}
|
||||
|
||||
override fun getPlatformSpecificSubPackagesFqNames(
|
||||
packageFqName: FqName,
|
||||
platform: TargetPlatform,
|
||||
nameFilter: (Name) -> Boolean
|
||||
): Set<Name> {
|
||||
return providers.flatMapTo(mutableSetOf()) { it.getPlatformSpecificSubPackagesFqNames(packageFqName, platform, nameFilter) }
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public val factory: KotlinCompositeProviderFactory<KotlinPackageProvider> = KotlinCompositeProviderFactory(
|
||||
EmptyKotlinPackageProvider,
|
||||
::CompositeKotlinPackageProvider,
|
||||
)
|
||||
|
||||
public fun create(providers: List<KotlinPackageProvider>): KotlinPackageProvider = factory.create(providers)
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.packageProviders
|
||||
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinPackageProvider
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
|
||||
internal object EmptyKotlinPackageProvider : KotlinPackageProvider() {
|
||||
override fun doesPackageExist(packageFqName: FqName, platform: TargetPlatform): Boolean = false
|
||||
|
||||
override fun doesKotlinOnlyPackageExist(packageFqName: FqName): Boolean = false
|
||||
|
||||
override fun doesPlatformSpecificPackageExist(packageFqName: FqName, platform: TargetPlatform): Boolean = false
|
||||
|
||||
override fun getSubPackageFqNames(packageFqName: FqName, platform: TargetPlatform, nameFilter: (Name) -> Boolean): Set<Name> =
|
||||
emptySet()
|
||||
|
||||
override fun getKotlinOnlySubPackagesFqNames(packageFqName: FqName, nameFilter: (Name) -> Boolean): Set<Name> = emptySet()
|
||||
|
||||
override fun getPlatformSpecificSubPackagesFqNames(
|
||||
packageFqName: FqName,
|
||||
platform: TargetPlatform,
|
||||
nameFilter: (Name) -> Boolean,
|
||||
): Set<Name> = emptySet()
|
||||
}
|
||||
Reference in New Issue
Block a user