AnalyzerFacade: resolvers for modules are created lazily

This commit is contained in:
Pavel V. Talanov
2015-06-15 21:53:19 +03:00
parent 96199ecc1f
commit f454b7d15e
@@ -23,12 +23,15 @@ import org.jetbrains.kotlin.context.ProjectContext
import org.jetbrains.kotlin.context.withModule import org.jetbrains.kotlin.context.withModule
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.ModuleParameters import org.jetbrains.kotlin.descriptors.ModuleParameters
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.LazyModuleDependencies import org.jetbrains.kotlin.descriptors.impl.LazyModuleDependencies
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.JetFile import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.resolve.lazy.ResolveSession import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.storage.StorageManager
import java.util.ArrayList import java.util.ArrayList
import java.util.HashMap import java.util.HashMap
import kotlin.properties.Delegates import kotlin.properties.Delegates
@@ -56,7 +59,7 @@ public class ResolverForProjectImpl<M : ModuleInfo, R : ResolverForModule>(
val descriptorByModule: Map<M, ModuleDescriptorImpl>, val descriptorByModule: Map<M, ModuleDescriptorImpl>,
val delegateResolver: ResolverForProject<M, R> = EmptyResolverForProject() val delegateResolver: ResolverForProject<M, R> = EmptyResolverForProject()
) : ResolverForProject<M, R> { ) : ResolverForProject<M, R> {
val resolverByModuleDescriptor: MutableMap<ModuleDescriptor, R> = HashMap() val resolverByModuleDescriptor: MutableMap<ModuleDescriptor, () -> R> = HashMap()
override val allModules: Collection<M> by Delegates.lazy { override val allModules: Collection<M> by Delegates.lazy {
(descriptorByModule.keySet() + delegateResolver.allModules).toSet() (descriptorByModule.keySet() + delegateResolver.allModules).toSet()
@@ -69,7 +72,8 @@ public class ResolverForProjectImpl<M : ModuleInfo, R : ResolverForModule>(
} }
override fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): R { override fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): R {
return resolverByModuleDescriptor[descriptor] ?: return delegateResolver.resolverForModuleDescriptor(descriptor) val computation = resolverByModuleDescriptor[descriptor] ?: return delegateResolver.resolverForModuleDescriptor(descriptor)
return computation()
} }
override fun descriptorForModule(moduleInfo: M): ModuleDescriptorImpl { override fun descriptorForModule(moduleInfo: M): ModuleDescriptorImpl {
@@ -127,11 +131,12 @@ public trait AnalyzerFacade<A : ResolverForModule, in P : PlatformAnalysisParame
delegateResolver: ResolverForProject<M, A> = EmptyResolverForProject() delegateResolver: ResolverForProject<M, A> = EmptyResolverForProject()
): ResolverForProject<M, A> { ): ResolverForProject<M, A> {
val storageManager = projectContext.storageManager
fun createResolverForProject(): ResolverForProjectImpl<M, A> { fun createResolverForProject(): ResolverForProjectImpl<M, A> {
val descriptorByModule = HashMap<M, ModuleDescriptorImpl>() val descriptorByModule = HashMap<M, ModuleDescriptorImpl>()
modules.forEach { modules.forEach {
module -> module ->
descriptorByModule[module] = ModuleDescriptorImpl(module.name, projectContext.storageManager, moduleParameters) descriptorByModule[module] = ModuleDescriptorImpl(module.name, storageManager, moduleParameters)
} }
return ResolverForProjectImpl(descriptorByModule, delegateResolver) return ResolverForProjectImpl(descriptorByModule, delegateResolver)
} }
@@ -153,7 +158,7 @@ public trait AnalyzerFacade<A : ResolverForModule, in P : PlatformAnalysisParame
modules.forEach { modules.forEach {
module -> module ->
resolverForProject.descriptorForModule(module).setDependencies( resolverForProject.descriptorForModule(module).setDependencies(
LazyModuleDependencies(projectContext.storageManager) { computeDependencyDescriptors(module) } LazyModuleDependencies(storageManager) { computeDependencyDescriptors(module) }
) )
} }
} }
@@ -176,12 +181,15 @@ public trait AnalyzerFacade<A : ResolverForModule, in P : PlatformAnalysisParame
modules.forEach { modules.forEach {
module -> module ->
val descriptor = resolverForProject.descriptorForModule(module) val descriptor = resolverForProject.descriptorForModule(module)
val resolverForModule = createResolverForModule( val computeResolverForModule = storageManager.createLazyValue {
module, descriptor, projectContext.withModule(descriptor), createResolverForModule(
modulesContent(module), platformParameters, resolverForProject module, descriptor, projectContext.withModule(descriptor),
) modulesContent(module), platformParameters, resolverForProject
descriptor.initialize(resolverForModule.packageFragmentProvider) )
resolverForProject.resolverByModuleDescriptor[descriptor] = resolverForModule }
descriptor.initialize(DelegatingPackageFragmentProvider { computeResolverForModule().packageFragmentProvider })
resolverForProject.resolverByModuleDescriptor[descriptor] = computeResolverForModule
} }
} }
@@ -199,3 +207,17 @@ public trait AnalyzerFacade<A : ResolverForModule, in P : PlatformAnalysisParame
public val moduleParameters: ModuleParameters public val moduleParameters: ModuleParameters
} }
//NOTE: relies on delegate to be lazily computed and cached
private class DelegatingPackageFragmentProvider(
private val delegate: () -> PackageFragmentProvider
) : PackageFragmentProvider {
override fun getPackageFragments(fqName: FqName): List<PackageFragmentDescriptor> {
return delegate().getPackageFragments(fqName)
}
override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean): Collection<FqName> {
return delegate().getSubPackagesOf(fqName, nameFilter)
}
}