Refactoring: move createResolverForModule() into ResolverForProjectImpl

This commit is contained in:
Dmitry Jemerov
2017-07-26 15:23:51 +02:00
parent fcc067435e
commit aafe7e6f1b
5 changed files with 53 additions and 40 deletions
@@ -43,13 +43,13 @@ class JvmPlatformParameters(
) : PlatformAnalysisParameters
object JvmAnalyzerFacade : AnalyzerFacade<JvmPlatformParameters>() {
object JvmAnalyzerFacade : AnalyzerFacade() {
override fun <M : ModuleInfo> createResolverForModule(
moduleInfo: M,
moduleDescriptor: ModuleDescriptorImpl,
moduleContext: ModuleContext,
moduleContent: ModuleContent,
platformParameters: JvmPlatformParameters,
platformParameters: PlatformAnalysisParameters,
targetEnvironment: TargetEnvironment,
resolverForProject: ResolverForProject<M>,
languageSettingsProvider: LanguageSettingsProvider,
@@ -64,7 +64,7 @@ object JvmAnalyzerFacade : AnalyzerFacade<JvmPlatformParameters>() {
)
val moduleClassResolver = ModuleClassResolverImpl { javaClass ->
val referencedClassModule = platformParameters.moduleByJavaClass(javaClass)
val referencedClassModule = (platformParameters as JvmPlatformParameters).moduleByJavaClass(javaClass)
// We don't have full control over idea resolve api so we allow for a situation which should not happen in Kotlin.
// For example, type in a java library can reference a class declared in a source root (is valid but rare case)
// Providing a fallback strategy in this case can hide future problems, so we should at least log to be able to diagnose those
@@ -75,6 +75,12 @@ class EmptyResolverForProject<M : ModuleInfo> : ResolverForProject<M>() {
}
class ResolverForProjectImpl<M : ModuleInfo>(
val projectContext: ProjectContext,
analyzerFacade: (M) -> AnalyzerFacade,
modulesContent: (M) -> ModuleContent,
platformParameters: PlatformAnalysisParameters,
targetEnvironment: TargetEnvironment,
packagePartProviderFactory: (M, ModuleContent) -> PackagePartProvider,
private val debugName: String,
private val descriptorByModule: Map<M, ModuleDescriptorImpl>,
private val delegateResolver: ResolverForProject<M> = EmptyResolverForProject()
@@ -86,7 +92,17 @@ class ResolverForProjectImpl<M : ModuleInfo>(
return resolverForModuleDescriptor(doGetDescriptorForModule(moduleInfo))
}
internal val resolverByModuleDescriptor: MutableMap<ModuleDescriptor, NotNullLazyValue<ResolverForModule>> = HashMap()
internal val resolverByModuleDescriptor: Map<ModuleDescriptor, NotNullLazyValue<ResolverForModule>> = descriptorByModule.map { (module, descriptor) ->
descriptor to projectContext.storageManager.createLazyValue {
ResolverForModuleComputationTracker.getInstance(projectContext.project)?.onResolverComputed(module)
analyzerFacade(module).createResolverForModule(
module, descriptor, projectContext.withModule(descriptor), modulesContent(module),
platformParameters, targetEnvironment, this@ResolverForProjectImpl,
packagePartProviderFactory(module, modulesContent(module))
)
}
}.toMap()
override val allModules: Collection<M> by lazy {
(descriptorByModule.keys + delegateResolver.allModules).toSet()
@@ -156,15 +172,15 @@ interface ModuleInfo {
}
}
abstract class AnalyzerFacade<in P : PlatformAnalysisParameters> {
abstract class AnalyzerFacade {
companion object {
fun <P : PlatformAnalysisParameters, M : ModuleInfo> setupResolverForProject(
fun <M : ModuleInfo> setupResolverForProject(
debugName: String,
projectContext: ProjectContext,
modules: Collection<M>,
analyzerFacade: (M) -> AnalyzerFacade<P>,
analyzerFacade: (M) -> AnalyzerFacade,
modulesContent: (M) -> ModuleContent,
platformParameters: P,
platformParameters: PlatformAnalysisParameters,
languageSettingsProvider: LanguageSettingsProvider = LanguageSettingsProvider.Default,
targetEnvironment: TargetEnvironment = CompilerEnvironment,
builtIns: KotlinBuiltIns = DefaultBuiltIns.Instance,
@@ -176,9 +192,17 @@ abstract class AnalyzerFacade<in P : PlatformAnalysisParameters> {
): ResolverForProject<M> {
val storageManager = projectContext.storageManager
val resolverForProject = ResolverForProjectImpl(debugName, modules.keysToMap { module ->
ModuleDescriptorImpl(module.name, storageManager, builtIns, modulePlatforms(module), module.capabilities)
}, delegateResolver)
val resolverForProject = ResolverForProjectImpl(
projectContext,
analyzerFacade,
modulesContent,
platformParameters,
targetEnvironment,
packagePartProviderFactory,
debugName,
modules.keysToMap { module ->
ModuleDescriptorImpl(module.name, storageManager, builtIns, modulePlatforms(module), module.capabilities)
}, delegateResolver)
for (module in modules) {
val moduleDescriptor = resolverForProject.descriptorForModule(module)
@@ -188,37 +212,23 @@ abstract class AnalyzerFacade<in P : PlatformAnalysisParameters> {
modulePlatforms,
firstDependency,
resolverForProject))
}
for (module in modules) {
val descriptor = resolverForProject.descriptorForModule(module)
val content = modulesContent(module)
val computeResolverForModule = storageManager.createLazyValue {
ResolverForModuleComputationTracker.getInstance(projectContext.project)?.onResolverComputed(module)
analyzerFacade(module).createResolverForModule(
module, descriptor, projectContext.withModule(descriptor), modulesContent(module),
platformParameters, targetEnvironment, resolverForProject, languageSettingsProvider,
packagePartProviderFactory(module, content)
)
}
descriptor.initialize(
DelegatingPackageFragmentProvider(content, packageOracleFactory.createOracle(module), computeResolverForModule))
resolverForProject.resolverByModuleDescriptor[descriptor] = computeResolverForModule
moduleDescriptor.initialize(
DelegatingPackageFragmentProvider(resolverForProject, moduleDescriptor, content,
packageOracleFactory.createOracle(module)))
}
return resolverForProject
}
}
protected abstract fun <M : ModuleInfo> createResolverForModule(
abstract fun <M : ModuleInfo> createResolverForModule(
moduleInfo: M,
moduleDescriptor: ModuleDescriptorImpl,
moduleContext: ModuleContext,
moduleContent: ModuleContent,
platformParameters: P,
platformParameters: PlatformAnalysisParameters,
targetEnvironment: TargetEnvironment,
resolverForProject: ResolverForProject<M>,
languageSettingsProvider: LanguageSettingsProvider,
@@ -272,27 +282,31 @@ class LazyModuleDependencies<M: ModuleInfo>(
}
private class DelegatingPackageFragmentProvider(
private class DelegatingPackageFragmentProvider<M : ModuleInfo>(
private val resolverForProject: ResolverForProjectImpl<M>,
private val module: ModuleDescriptor,
moduleContent: ModuleContent,
private val packageOracle: PackageOracle,
private val resolverForModule: NotNullLazyValue<ResolverForModule>
private val packageOracle: PackageOracle
) : PackageFragmentProvider {
private val syntheticFilePackages = moduleContent.syntheticFiles.map { it.packageFqName }.toSet()
override fun getPackageFragments(fqName: FqName): List<PackageFragmentDescriptor> {
if (certainlyDoesNotExist(fqName)) return emptyList()
return resolverForModule().packageFragmentProvider.getPackageFragments(fqName)
return resolverForModuleCachedValue().packageFragmentProvider.getPackageFragments(fqName)
}
private val resolverForModuleCachedValue
get() = resolverForProject.resolverByModuleDescriptor[module]!!
override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean): Collection<FqName> {
if (certainlyDoesNotExist(fqName)) return emptyList()
return resolverForModule().packageFragmentProvider.getSubPackagesOf(fqName, nameFilter)
return resolverForModuleCachedValue().packageFragmentProvider.getSubPackagesOf(fqName, nameFilter)
}
private fun certainlyDoesNotExist(fqName: FqName): Boolean {
if (resolverForModule.isComputed()) return false // let this request get cached inside delegate
if (resolverForModuleCachedValue.isComputed()) return false // let this request get cached inside delegate
return !packageOracle.packageExists(fqName) && fqName !in syntheticFilePackages
}
@@ -46,7 +46,7 @@ import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragmen
* A facade that is used to analyze common (platform-independent) modules in multi-platform projects.
* See [TargetPlatform.Default]
*/
object DefaultAnalyzerFacade : AnalyzerFacade<PlatformAnalysisParameters>() {
object DefaultAnalyzerFacade : AnalyzerFacade() {
private class SourceModuleInfo(
override val name: Name,
override val capabilities: Map<ModuleDescriptor.Capability<*>, Any?>,
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfigu
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
object JsAnalyzerFacade : AnalyzerFacade<PlatformAnalysisParameters>() {
object JsAnalyzerFacade : AnalyzerFacade() {
override fun <M : ModuleInfo> createResolverForModule(
moduleInfo: M,
@@ -22,13 +22,12 @@ import org.jetbrains.kotlin.idea.caches.resolve.JsAnalyzerFacade
import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
object AnalyzerFacadeProvider {
//NOTE: it's convenient that JS backend doesn't have platform parameters (for now)
// otherwise we would be forced to add casts on the call site of setupResolverForProject
fun getAnalyzerFacade(targetPlatform: TargetPlatform): AnalyzerFacade<JvmPlatformParameters> {
fun getAnalyzerFacade(targetPlatform: TargetPlatform): AnalyzerFacade {
return when (targetPlatform) {
JvmPlatform -> JvmAnalyzerFacade
JsPlatform -> JsAnalyzerFacade