[AA] Add abstraction for composite provider creation and merging
- Composite declaration providers and declaration provider mergers are extremely similar to the composite package providers and (newly to be implemented) package provider mergers. This commit extracts the common parts into a `KotlinCompositeProviderFactory`. ^KT-61791
This commit is contained in:
committed by
Space Team
parent
0e6cc92958
commit
c63dde4f7e
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.impl.util.mergeOnly
|
||||
|
||||
/**
|
||||
* A composite provider should only contain providers of the same base type as the composite provider itself, so implementations of
|
||||
* [KotlinCompositeProvider] should always be a subtype of their type argument [P].
|
||||
*/
|
||||
public interface KotlinCompositeProvider<P> {
|
||||
public val providers: List<P>
|
||||
}
|
||||
|
||||
/**
|
||||
* [KotlinCompositeProviderFactory] is used by various composite providers to share code related to provider creation and flattening.
|
||||
*/
|
||||
public class KotlinCompositeProviderFactory<P>(
|
||||
private val emptyProvider: P,
|
||||
private val composeProviders: (List<P>) -> P,
|
||||
) {
|
||||
public fun create(providers: List<P>): P = when (providers.size) {
|
||||
0 -> emptyProvider
|
||||
1 -> providers.single()
|
||||
else -> composeProviders(providers)
|
||||
}
|
||||
|
||||
public fun createFlattened(providers: List<P>): P =
|
||||
create(if (providers.size > 1) flatten(providers) else providers)
|
||||
|
||||
public fun flatten(providers: List<P>): List<P> =
|
||||
providers.flatMap { provider ->
|
||||
// `KotlinCompositeProvider<P>` should always be a provider of type `P` itself, so the cast is legal. Still, suppressing the
|
||||
// error is unfortunate, but to properly type this, we'd need to be able to restrict `KotlinCompositeProvider<P>` to be a
|
||||
// subtype of `P`, which is not possible in Kotlin.
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
when (provider) {
|
||||
is KotlinCompositeProvider<*> -> (provider as KotlinCompositeProvider<P>).providers
|
||||
else -> listOf(provider)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the given [factory] to merge all providers of type [T] with the given [mergeTargets] strategy. Other providers (not of type [T]) are
|
||||
* added to the resulting composite provider unmerged.
|
||||
*/
|
||||
public inline fun <P : Any, reified T : P> List<P>.mergeSpecificProviders(
|
||||
factory: KotlinCompositeProviderFactory<P>,
|
||||
crossinline mergeTargets: (List<T>) -> P,
|
||||
): P {
|
||||
// We should flatten providers before merging so that the merger has access to all individual providers, and also after merging because
|
||||
// composite providers may be created by the merger.
|
||||
return factory.createFlattened(factory.flatten(this).mergeOnly<_, T> { mergeTargets(it) })
|
||||
}
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
}
|
||||
+6
-5
@@ -20,7 +20,6 @@ import com.intellij.psi.stubs.StubElement
|
||||
import com.intellij.util.indexing.FileContent
|
||||
import com.intellij.util.indexing.FileContentImpl
|
||||
import org.jetbrains.kotlin.analysis.decompiler.psi.BuiltInsVirtualFileProvider
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinBuiltInDecompiler
|
||||
import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinBuiltInFileType
|
||||
import org.jetbrains.kotlin.analysis.decompiler.stub.file.ClsKotlinBinaryClassCache
|
||||
@@ -28,8 +27,9 @@ 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.KotlinDeclarationProviderMerger
|
||||
import org.jetbrains.kotlin.analysis.providers.createDeclarationProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.impl.util.mergeOnly
|
||||
import org.jetbrains.kotlin.analysis.providers.impl.declarationProviders.CompositeKotlinDeclarationProvider
|
||||
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.name.*
|
||||
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.psi.stubs.KotlinClassOrObjectStub
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
||||
import org.jetbrains.kotlin.psi.stubs.impl.*
|
||||
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
public class KotlinStaticDeclarationProvider internal constructor(
|
||||
private val index: KotlinStaticDeclarationIndex,
|
||||
@@ -373,9 +374,9 @@ public class KotlinFakeClsStubsCache {
|
||||
}
|
||||
}
|
||||
|
||||
public class KotlinStaticDeclarationProviderMerger(private val project: Project) : KotlinDeclarationProviderMergerBase() {
|
||||
override fun mergeToList(declarationProviders: List<KotlinDeclarationProvider>): List<KotlinDeclarationProvider> =
|
||||
declarationProviders.mergeOnly<_, KotlinStaticDeclarationProvider> { providers ->
|
||||
public class KotlinStaticDeclarationProviderMerger(private val project: Project) : KotlinDeclarationProviderMerger() {
|
||||
override fun mergeDeclarationProviders(declarationProviders: List<KotlinDeclarationProvider>): KotlinDeclarationProvider =
|
||||
declarationProviders.mergeSpecificProviders<_, KotlinStaticDeclarationProvider>(CompositeKotlinDeclarationProvider.factory) { providers ->
|
||||
val combinedScope = GlobalSearchScope.union(providers.map { it.scope })
|
||||
project.createDeclarationProvider(combinedScope, module = null).apply {
|
||||
check(this is KotlinStaticDeclarationProvider) {
|
||||
|
||||
+9
-19
@@ -6,6 +6,8 @@
|
||||
package org.jetbrains.kotlin.analysis.providers.impl.declarationProviders
|
||||
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.impl.KotlinCompositeProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.impl.KotlinCompositeProviderFactory
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -13,8 +15,8 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
public class CompositeKotlinDeclarationProvider private constructor(
|
||||
public val providers: List<KotlinDeclarationProvider>
|
||||
) : KotlinDeclarationProvider() {
|
||||
override val providers: List<KotlinDeclarationProvider>
|
||||
) : KotlinDeclarationProvider(), KotlinCompositeProvider<KotlinDeclarationProvider> {
|
||||
override fun getClassLikeDeclarationByClassId(classId: ClassId): KtClassLikeDeclaration? {
|
||||
return providers.firstNotNullOfOrNull { it.getClassLikeDeclarationByClassId(classId) }
|
||||
}
|
||||
@@ -68,23 +70,11 @@ public class CompositeKotlinDeclarationProvider private constructor(
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public fun create(providers: List<KotlinDeclarationProvider>): KotlinDeclarationProvider {
|
||||
return when (providers.size) {
|
||||
0 -> EmptyKotlinDeclarationProvider
|
||||
1 -> providers.single()
|
||||
else -> CompositeKotlinDeclarationProvider(providers)
|
||||
}
|
||||
}
|
||||
public val factory: KotlinCompositeProviderFactory<KotlinDeclarationProvider> = KotlinCompositeProviderFactory(
|
||||
EmptyKotlinDeclarationProvider,
|
||||
::CompositeKotlinDeclarationProvider,
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
public fun create(providers: List<KotlinDeclarationProvider>): KotlinDeclarationProvider = factory.create(providers)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user