Introduce AbstractResolverForProject

Previously, ResolverForProjectImpl had multiple callbacks in
constructor. Some of those callbacks were used only to overcome module
visibility and provide an ability to inject IDE-specific logic into
compiler (ResolverForProject is in the 'compiler'-module)

This commit introduces abstract class which implements
environment-independent logic (previously, this logic had been stored in
ResolverForProjectImpl) with several abstract met hods (previously,
callbacks). Then, we provide few concrete implementations of
AbstractResolverForProject with clear semantics:

- IdeaResolverForProject: resolver used in IDE, where we have indices,
  oracles, multiple modules, etc.
- ResolverForSingleModuleProject: resolver for project with only one
  module, commonly used for CLI compiler/tests
- one anonymous implementation for MultimoduleTests

This refactoring achieves several things:
- now it is easier to see what kinds of ResolverForProject you might see
  in some particular environment (previously, one had to inspect all
  call-sites of constructor)
- we can easily add IDE-specific logic in IdeaResolverForProject without
  adding noisy callbacks (which most probably wouldn't have any other
  non-trivial implementations)
This commit is contained in:
Dmitry Savvinov
2019-09-23 18:44:58 +03:00
parent 48719c4050
commit bfacc1a3c5
8 changed files with 253 additions and 162 deletions
@@ -54,7 +54,6 @@ abstract class ResolverForProject<M : ModuleInfo> {
abstract val name: String
abstract val allModules: Collection<M>
abstract val builtInsProvider: (M) -> KotlinBuiltIns
override fun toString() = name
@@ -79,7 +78,6 @@ class EmptyResolverForProject<M : ModuleInfo> : ResolverForProject<M>() {
override fun descriptorForModule(moduleInfo: M) = diagnoseUnknownModuleInfo(listOf(moduleInfo))
override val allModules: Collection<M> = listOf()
override fun diagnoseUnknownModuleInfo(infos: List<ModuleInfo>) = throw IllegalStateException("Should not be called for $infos")
override val builtInsProvider: (M) -> KotlinBuiltIns = { DefaultBuiltIns.Instance }
}
data class ModuleContent<out M : ModuleInfo>(
@@ -128,7 +126,7 @@ class LazyModuleDependencies<M : ModuleInfo>(
storageManager: StorageManager,
private val module: M,
firstDependency: M? = null,
private val resolverForProject: ResolverForProjectImpl<M>
private val resolverForProject: AbstractResolverForProject<M>
) : ModuleDependencies {
private val dependencies = storageManager.createLazyValue {
val moduleDescriptor = resolverForProject.descriptorForModule(module)
@@ -16,20 +16,15 @@ import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.psi.KtFile
class ResolverForProjectImpl<M : ModuleInfo>(
abstract class AbstractResolverForProject<M : ModuleInfo>(
private val debugName: String,
private val projectContext: ProjectContext,
protected val projectContext: ProjectContext,
modules: Collection<M>,
private val modulesContent: (M) -> ModuleContent<M>,
private val moduleLanguageSettingsProvider: LanguageSettingsProvider,
private val resolverForModuleFactoryByPlatform: (TargetPlatform?) -> ResolverForModuleFactory,
private val invalidateOnOOCB: Boolean,
override val builtInsProvider: (M) -> KotlinBuiltIns,
private val fallbackModificationTracker: ModificationTracker? = null,
private val delegateResolver: ResolverForProject<M> = EmptyResolverForProject(),
private val sdkDependency: (M) -> M?,
private val packageOracleFactory: PackageOracleFactory = PackageOracleFactory.OptimisticFactory,
private val isReleaseCoroutines: Boolean? = null
private val packageOracleFactory: PackageOracleFactory = PackageOracleFactory.OptimisticFactory
) : ResolverForProject<M>() {
private class ModuleData(
@@ -58,6 +53,11 @@ class ResolverForProjectImpl<M : ModuleInfo>(
assert(moduleInfoToResolvableInfo.values.toSet() == modules.toSet())
}
abstract fun sdkDependency(module: M): M?
abstract fun modulesContent(module: M): ModuleContent<M>
abstract fun builtInsForModule(module: M): KotlinBuiltIns
abstract fun createResolverForModule(descriptor: ModuleDescriptor, moduleInfo: M): ResolverForModule
override fun tryGetResolverForModule(moduleInfo: M): ResolverForModule? {
if (!isCorrectModuleInfo(moduleInfo)) {
return null
@@ -108,25 +108,9 @@ class ResolverForProjectImpl<M : ModuleInfo>(
resolverByModuleDescriptor.getOrPut(descriptor) {
checkModuleIsCorrect(module)
ResolverForModuleComputationTracker.getInstance(projectContext.project)
?.onResolverComputed(module)
ResolverForModuleComputationTracker.getInstance(projectContext.project)?.onResolverComputed(module)
val moduleContent = modulesContent(module)
val languageVersionSettings =
moduleLanguageSettingsProvider.getLanguageVersionSettings(module, projectContext.project, isReleaseCoroutines)
// FIXME(dsavvinov): make sure that module.platform returns platform with the same JvmTarget as this one
val targetPlatformVersion = moduleLanguageSettingsProvider.getTargetPlatform(module, projectContext.project)
val resolverForModuleFactory = resolverForModuleFactoryByPlatform(module.platform)
resolverForModuleFactory.createResolverForModule(
descriptor as ModuleDescriptorImpl,
projectContext.withModule(descriptor),
moduleContent,
this@ResolverForProjectImpl,
languageVersionSettings
)
createResolverForModule(descriptor, module)
}
}
}
@@ -153,7 +137,7 @@ class ResolverForProjectImpl<M : ModuleInfo>(
private fun doGetDescriptorForModule(module: M): ModuleDescriptorImpl {
val moduleFromThisResolver = moduleInfoToResolvableInfo[module]
?: return delegateResolver.descriptorForModule(module) as ModuleDescriptorImpl
?: return delegateResolver.descriptorForModule(module) as ModuleDescriptorImpl
return projectContext.storageManager.compute {
var moduleData = descriptorByModule.getOrPut(moduleFromThisResolver) {
@@ -183,24 +167,20 @@ class ResolverForProjectImpl<M : ModuleInfo>(
val moduleDescriptor = ModuleDescriptorImpl(
module.name,
projectContext.storageManager,
builtInsProvider(module),
builtInsForModule(module),
module.platform,
module.capabilities,
module.stableName
)
moduleInfoByDescriptor[moduleDescriptor] = module
setupModuleDescriptor(module, moduleDescriptor)
val modificationTracker = (module as? TrackableModuleInfo)?.createModificationTracker() ?: if (invalidateOnOOCB) {
KotlinModificationTrackerService.getInstance(projectContext.project).outOfBlockModificationTracker
} else {
null
}
val modificationTracker = (module as? TrackableModuleInfo)?.createModificationTracker() ?: fallbackModificationTracker
return ModuleData(moduleDescriptor, modificationTracker)
}
}
private class DelegatingPackageFragmentProvider<M : ModuleInfo>(
private val resolverForProject: ResolverForProjectImpl<M>,
private val resolverForProject: AbstractResolverForProject<M>,
private val module: ModuleDescriptor,
moduleContent: ModuleContent<M>,
private val packageOracle: PackageOracle
@@ -0,0 +1,51 @@
/*
* Copyright 2010-2019 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.analyzer
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.context.ProjectContext
import org.jetbrains.kotlin.context.withModule
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.psi.KtFile
class ResolverForSingleModuleProject<M : ModuleInfo>(
debugName: String,
projectContext: ProjectContext,
module: M,
private val resolverForModuleFactory: ResolverForModuleFactory,
private val searchScope: GlobalSearchScope,
private val builtIns: KotlinBuiltIns = DefaultBuiltIns.Instance,
private val languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
private val syntheticFiles: Collection<KtFile> = emptyList(),
private val sdkDependency: M? = null
) : AbstractResolverForProject<M>(
debugName,
projectContext,
listOf(module),
null,
EmptyResolverForProject(),
PackageOracleFactory.OptimisticFactory
) {
override fun sdkDependency(module: M): M? = sdkDependency
override fun modulesContent(module: M): ModuleContent<M> = ModuleContent(module, syntheticFiles, searchScope)
override fun builtInsForModule(module: M): KotlinBuiltIns = builtIns
override fun createResolverForModule(descriptor: ModuleDescriptor, moduleInfo: M): ResolverForModule =
resolverForModuleFactory.createResolverForModule(
descriptor as ModuleDescriptorImpl,
projectContext.withModule(descriptor),
modulesContent(moduleInfo),
this,
languageVersionSettings
)
}