[Injection] Make component containers composition more granular and flexible
Previously, containers set-up was performed by calls to static functions like 'createContainerForLazyResolve', which would set-up whole container from scratch. This has several issues: - complicates code re-use and encourages copy-paste of one and the same set-up logic - complicates composition of multiplatform containers (because each set-up method relies on the fact that it should take an empty container and compose it completely) The idea of this commit is to split set-up methods into smaller ones, with finer areas of responsibility, which allows to re-use them in various scenarios (and, in particularly motivating composition of multiplatform container)
This commit is contained in:
@@ -22,11 +22,10 @@ import org.jetbrains.kotlin.container.StorageComponentContainer
|
||||
import org.jetbrains.kotlin.container.useImpl
|
||||
import org.jetbrains.kotlin.container.useInstance
|
||||
import org.jetbrains.kotlin.context.ModuleContext
|
||||
import org.jetbrains.kotlin.contracts.ContractDeserializerImpl
|
||||
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
|
||||
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.platform.subplatformOfType
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.platform.TargetPlatformVersion
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.calls.components.ClassicTypeSystemContextForCS
|
||||
@@ -35,7 +34,6 @@ import org.jetbrains.kotlin.resolve.calls.tower.KotlinResolutionStatelessCallbac
|
||||
import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker
|
||||
import org.jetbrains.kotlin.resolve.lazy.*
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
|
||||
import org.jetbrains.kotlin.types.SubstitutingScopeProviderImpl
|
||||
import org.jetbrains.kotlin.types.expressions.DeclarationScopeProviderForLocalClassifierAnalyzer
|
||||
import org.jetbrains.kotlin.types.expressions.LocalClassDescriptorHolder
|
||||
@@ -78,9 +76,32 @@ private fun StorageComponentContainer.configurePlatformIndependentComponents() {
|
||||
useImpl<ExperimentalUsageChecker>()
|
||||
useImpl<ExperimentalUsageChecker.Overrides>()
|
||||
useImpl<ExperimentalUsageChecker.ClassifierUsage>()
|
||||
|
||||
useImpl<ContractDeserializerImpl>()
|
||||
useImpl<CompilerDeserializationConfiguration>()
|
||||
|
||||
useImpl<ClassicTypeSystemContextForCS>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually, those should be present in 'configurePlatformIndependentComponents',
|
||||
* but, unfortunately, this is currently impossible, because in some lightweight
|
||||
* containers (see [createContainerForBodyResolve] and similar) some dependencies
|
||||
* are missing
|
||||
*
|
||||
* If you're not doing some trickery with containers, you should use them.
|
||||
*/
|
||||
fun StorageComponentContainer.configureStandardResolveComponents() {
|
||||
useImpl<ResolveSession>()
|
||||
useImpl<LazyTopDownAnalyzer>()
|
||||
useImpl<AnnotationResolverImpl>()
|
||||
}
|
||||
|
||||
fun StorageComponentContainer.configureIncrementalCompilation(lookupTracker: LookupTracker, expectActualTracker: ExpectActualTracker) {
|
||||
useInstance(lookupTracker)
|
||||
useInstance(expectActualTracker)
|
||||
}
|
||||
|
||||
fun createContainerForBodyResolve(
|
||||
moduleContext: ModuleContext,
|
||||
bindingTrace: BindingTrace,
|
||||
@@ -163,13 +184,11 @@ fun createContainerForLazyResolve(
|
||||
): StorageComponentContainer = createContainer("LazyResolve", compilerServices) {
|
||||
configureModule(moduleContext, platform, compilerServices, bindingTrace, languageVersionSettings)
|
||||
|
||||
useInstance(declarationProviderFactory)
|
||||
configureStandardResolveComponents()
|
||||
|
||||
useInstance(declarationProviderFactory)
|
||||
useImpl<SubstitutingScopeProviderImpl>()
|
||||
|
||||
useImpl<AnnotationResolverImpl>()
|
||||
useImpl<CompilerDeserializationConfiguration>()
|
||||
targetEnvironment.configure(this)
|
||||
|
||||
useImpl<ResolveSession>()
|
||||
useImpl<LazyTopDownAnalyzer>()
|
||||
useImpl<SubstitutingScopeProviderImpl>()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,15 +66,24 @@ private val DEFAULT_CLASH_RESOLVERS = listOf<PlatformExtensionsClashResolver<*>>
|
||||
PlatformExtensionsClashResolver.FallbackToDefault(DynamicTypesSettings(), DynamicTypesSettings::class.java)
|
||||
)
|
||||
|
||||
fun StorageComponentContainer.configureDefaultCheckers() {
|
||||
DEFAULT_DECLARATION_CHECKERS.forEach { useInstance(it) }
|
||||
DEFAULT_CALL_CHECKERS.forEach { useInstance(it) }
|
||||
DEFAULT_TYPE_CHECKERS.forEach { useInstance(it) }
|
||||
DEFAULT_CLASSIFIER_USAGE_CHECKERS.forEach { useInstance(it) }
|
||||
DEFAULT_ANNOTATION_CHECKERS.forEach { useInstance(it) }
|
||||
DEFAULT_CLASH_RESOLVERS.forEach { useClashResolver(it) }
|
||||
}
|
||||
|
||||
|
||||
abstract class PlatformConfiguratorBase(
|
||||
private val dynamicTypesSettings: DynamicTypesSettings? = null,
|
||||
additionalDeclarationCheckers: List<DeclarationChecker> = emptyList(),
|
||||
additionalCallCheckers: List<CallChecker> = emptyList(),
|
||||
additionalTypeCheckers: List<AdditionalTypeChecker> = emptyList(),
|
||||
additionalClassifierUsageCheckers: List<ClassifierUsageChecker> = emptyList(),
|
||||
additionalAnnotationCheckers: List<AdditionalAnnotationChecker> = emptyList(),
|
||||
additionalClashResolvers: List<PlatformExtensionsClashResolver<*>> = emptyList(),
|
||||
private val additionalDeclarationCheckers: List<DeclarationChecker> = emptyList(),
|
||||
private val additionalCallCheckers: List<CallChecker> = emptyList(),
|
||||
private val additionalTypeCheckers: List<AdditionalTypeChecker> = emptyList(),
|
||||
private val additionalClassifierUsageCheckers: List<ClassifierUsageChecker> = emptyList(),
|
||||
private val additionalAnnotationCheckers: List<AdditionalAnnotationChecker> = emptyList(),
|
||||
private val additionalClashResolvers: List<PlatformExtensionsClashResolver<*>> = emptyList(),
|
||||
private val identifierChecker: IdentifierChecker? = null,
|
||||
private val overloadFilter: OverloadFilter? = null,
|
||||
private val platformToKotlinClassMap: PlatformToKotlinClassMap? = null,
|
||||
@@ -82,33 +91,32 @@ abstract class PlatformConfiguratorBase(
|
||||
private val overridesBackwardCompatibilityHelper: OverridesBackwardCompatibilityHelper? = null,
|
||||
private val declarationReturnTypeSanitizer: DeclarationReturnTypeSanitizer? = null
|
||||
) : PlatformConfigurator {
|
||||
private val declarationCheckers: List<DeclarationChecker> = DEFAULT_DECLARATION_CHECKERS + additionalDeclarationCheckers
|
||||
private val callCheckers: List<CallChecker> = DEFAULT_CALL_CHECKERS + additionalCallCheckers
|
||||
private val typeCheckers: List<AdditionalTypeChecker> = DEFAULT_TYPE_CHECKERS + additionalTypeCheckers
|
||||
private val classifierUsageCheckers: List<ClassifierUsageChecker> =
|
||||
DEFAULT_CLASSIFIER_USAGE_CHECKERS + additionalClassifierUsageCheckers
|
||||
private val annotationCheckers: List<AdditionalAnnotationChecker> = DEFAULT_ANNOTATION_CHECKERS + additionalAnnotationCheckers
|
||||
private val clashResolvers: List<PlatformExtensionsClashResolver<*>> = DEFAULT_CLASH_RESOLVERS + additionalClashResolvers
|
||||
|
||||
override val platformSpecificContainer = composeContainer(this::class.java.simpleName) {
|
||||
useInstanceIfNotNull(dynamicTypesSettings)
|
||||
declarationCheckers.forEach { useInstance(it) }
|
||||
callCheckers.forEach { useInstance(it) }
|
||||
typeCheckers.forEach { useInstance(it) }
|
||||
classifierUsageCheckers.forEach { useInstance(it) }
|
||||
annotationCheckers.forEach { useInstance(it) }
|
||||
clashResolvers.forEach { useClashResolver(it) }
|
||||
useInstanceIfNotNull(identifierChecker)
|
||||
useInstanceIfNotNull(overloadFilter)
|
||||
useInstanceIfNotNull(platformToKotlinClassMap)
|
||||
useInstanceIfNotNull(delegationFilter)
|
||||
useInstanceIfNotNull(overridesBackwardCompatibilityHelper)
|
||||
useInstanceIfNotNull(declarationReturnTypeSanitizer)
|
||||
configureDefaultCheckers()
|
||||
configureExtensionsAndCheckers(this)
|
||||
}
|
||||
|
||||
override fun configureModuleDependentCheckers(container: StorageComponentContainer) {
|
||||
container.useImpl<ExperimentalMarkerDeclarationAnnotationChecker>()
|
||||
}
|
||||
|
||||
private fun configureExtensionsAndCheckers(container: StorageComponentContainer) {
|
||||
with(container) {
|
||||
useInstanceIfNotNull(dynamicTypesSettings)
|
||||
additionalDeclarationCheckers.forEach { useInstance(it) }
|
||||
additionalCallCheckers.forEach { useInstance(it) }
|
||||
additionalTypeCheckers.forEach { useInstance(it) }
|
||||
additionalClassifierUsageCheckers.forEach { useInstance(it) }
|
||||
additionalAnnotationCheckers.forEach { useInstance(it) }
|
||||
additionalClashResolvers.forEach { useClashResolver(it) }
|
||||
useInstanceIfNotNull(identifierChecker)
|
||||
useInstanceIfNotNull(overloadFilter)
|
||||
useInstanceIfNotNull(platformToKotlinClassMap)
|
||||
useInstanceIfNotNull(delegationFilter)
|
||||
useInstanceIfNotNull(overridesBackwardCompatibilityHelper)
|
||||
useInstanceIfNotNull(declarationReturnTypeSanitizer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createContainer(id: String, compilerServices: PlatformDependentCompilerServices, init: StorageComponentContainer.() -> Unit) =
|
||||
|
||||
Reference in New Issue
Block a user