[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.FileContent
|
||||||
import com.intellij.util.indexing.FileContentImpl
|
import com.intellij.util.indexing.FileContentImpl
|
||||||
import org.jetbrains.kotlin.analysis.decompiler.psi.BuiltInsVirtualFileProvider
|
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.KotlinBuiltInDecompiler
|
||||||
import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinBuiltInFileType
|
import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinBuiltInFileType
|
||||||
import org.jetbrains.kotlin.analysis.decompiler.stub.file.ClsKotlinBinaryClassCache
|
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.project.structure.KtModule
|
||||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
|
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
|
||||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProviderFactory
|
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.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.fileClasses.javaFileFacadeFqName
|
||||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
import org.jetbrains.kotlin.name.*
|
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.elements.KtStubElementTypes
|
||||||
import org.jetbrains.kotlin.psi.stubs.impl.*
|
import org.jetbrains.kotlin.psi.stubs.impl.*
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
|
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
public class KotlinStaticDeclarationProvider internal constructor(
|
public class KotlinStaticDeclarationProvider internal constructor(
|
||||||
private val index: KotlinStaticDeclarationIndex,
|
private val index: KotlinStaticDeclarationIndex,
|
||||||
@@ -373,9 +374,9 @@ public class KotlinFakeClsStubsCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class KotlinStaticDeclarationProviderMerger(private val project: Project) : KotlinDeclarationProviderMergerBase() {
|
public class KotlinStaticDeclarationProviderMerger(private val project: Project) : KotlinDeclarationProviderMerger() {
|
||||||
override fun mergeToList(declarationProviders: List<KotlinDeclarationProvider>): List<KotlinDeclarationProvider> =
|
override fun mergeDeclarationProviders(declarationProviders: List<KotlinDeclarationProvider>): KotlinDeclarationProvider =
|
||||||
declarationProviders.mergeOnly<_, KotlinStaticDeclarationProvider> { providers ->
|
declarationProviders.mergeSpecificProviders<_, KotlinStaticDeclarationProvider>(CompositeKotlinDeclarationProvider.factory) { providers ->
|
||||||
val combinedScope = GlobalSearchScope.union(providers.map { it.scope })
|
val combinedScope = GlobalSearchScope.union(providers.map { it.scope })
|
||||||
project.createDeclarationProvider(combinedScope, module = null).apply {
|
project.createDeclarationProvider(combinedScope, module = null).apply {
|
||||||
check(this is KotlinStaticDeclarationProvider) {
|
check(this is KotlinStaticDeclarationProvider) {
|
||||||
|
|||||||
+9
-19
@@ -6,6 +6,8 @@
|
|||||||
package org.jetbrains.kotlin.analysis.providers.impl.declarationProviders
|
package org.jetbrains.kotlin.analysis.providers.impl.declarationProviders
|
||||||
|
|
||||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
|
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.CallableId
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
@@ -13,8 +15,8 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
|
||||||
public class CompositeKotlinDeclarationProvider private constructor(
|
public class CompositeKotlinDeclarationProvider private constructor(
|
||||||
public val providers: List<KotlinDeclarationProvider>
|
override val providers: List<KotlinDeclarationProvider>
|
||||||
) : KotlinDeclarationProvider() {
|
) : KotlinDeclarationProvider(), KotlinCompositeProvider<KotlinDeclarationProvider> {
|
||||||
override fun getClassLikeDeclarationByClassId(classId: ClassId): KtClassLikeDeclaration? {
|
override fun getClassLikeDeclarationByClassId(classId: ClassId): KtClassLikeDeclaration? {
|
||||||
return providers.firstNotNullOfOrNull { it.getClassLikeDeclarationByClassId(classId) }
|
return providers.firstNotNullOfOrNull { it.getClassLikeDeclarationByClassId(classId) }
|
||||||
}
|
}
|
||||||
@@ -68,23 +70,11 @@ public class CompositeKotlinDeclarationProvider private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
public fun create(providers: List<KotlinDeclarationProvider>): KotlinDeclarationProvider {
|
public val factory: KotlinCompositeProviderFactory<KotlinDeclarationProvider> = KotlinCompositeProviderFactory(
|
||||||
return when (providers.size) {
|
EmptyKotlinDeclarationProvider,
|
||||||
0 -> EmptyKotlinDeclarationProvider
|
::CompositeKotlinDeclarationProvider,
|
||||||
1 -> providers.single()
|
)
|
||||||
else -> CompositeKotlinDeclarationProvider(providers)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun createFlattened(providers: List<KotlinDeclarationProvider>): KotlinDeclarationProvider =
|
public fun create(providers: List<KotlinDeclarationProvider>): KotlinDeclarationProvider = factory.create(providers)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user