Refactoring: remove ModuleResolverProvider, inline createModuleResolverProvider

This commit is contained in:
Nikolay Krasko
2018-02-22 16:10:18 +03:00
parent de68607d5f
commit 90802f2d7c
3 changed files with 117 additions and 164 deletions
@@ -62,6 +62,7 @@ abstract class ResolverForProject<M : ModuleInfo> {
abstract val name: String abstract val name: String
abstract val allModules: Collection<M> abstract val allModules: Collection<M>
abstract val builtIns: KotlinBuiltIns
override fun toString() = name override fun toString() = name
} }
@@ -77,6 +78,7 @@ class EmptyResolverForProject<M : ModuleInfo> : ResolverForProject<M>() {
override fun descriptorForModule(moduleInfo: M) = diagnoseUnknownModuleInfo(listOf(moduleInfo)) override fun descriptorForModule(moduleInfo: M) = diagnoseUnknownModuleInfo(listOf(moduleInfo))
override val allModules: Collection<M> = listOf() override val allModules: Collection<M> = listOf()
override fun diagnoseUnknownModuleInfo(infos: List<ModuleInfo>) = throw IllegalStateException("Should not be called for $infos") override fun diagnoseUnknownModuleInfo(infos: List<ModuleInfo>) = throw IllegalStateException("Should not be called for $infos")
override val builtIns get() = DefaultBuiltIns.Instance
} }
class ResolverForProjectImpl<M : ModuleInfo>( class ResolverForProjectImpl<M : ModuleInfo>(
@@ -87,7 +89,7 @@ class ResolverForProjectImpl<M : ModuleInfo>(
private val modulesContent: (M) -> ModuleContent, private val modulesContent: (M) -> ModuleContent,
private val platformParameters: PlatformAnalysisParameters, private val platformParameters: PlatformAnalysisParameters,
private val targetEnvironment: TargetEnvironment = CompilerEnvironment, private val targetEnvironment: TargetEnvironment = CompilerEnvironment,
private val builtIns: KotlinBuiltIns = DefaultBuiltIns.Instance, override val builtIns: KotlinBuiltIns = DefaultBuiltIns.Instance,
private val delegateResolver: ResolverForProject<M> = EmptyResolverForProject(), private val delegateResolver: ResolverForProject<M> = EmptyResolverForProject(),
private val packagePartProviderFactory: (M, ModuleContent) -> PackagePartProvider = { _, _ -> PackagePartProvider.Empty }, private val packagePartProviderFactory: (M, ModuleContent) -> PackagePartProvider = { _, _ -> PackagePartProvider.Empty },
private val firstDependency: M? = null, private val firstDependency: M? = null,
@@ -1,115 +0,0 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.caches.resolve
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analyzer.ModuleContent
import org.jetbrains.kotlin.analyzer.ResolverForProject
import org.jetbrains.kotlin.analyzer.ResolverForProjectImpl
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.caches.resolve.IdePlatformSupport
import org.jetbrains.kotlin.context.GlobalContextImpl
import org.jetbrains.kotlin.context.withProject
import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo
import org.jetbrains.kotlin.idea.caches.project.SdkInfo
import org.jetbrains.kotlin.idea.caches.project.getModuleInfo
import org.jetbrains.kotlin.idea.caches.project.getNullableModuleInfo
import org.jetbrains.kotlin.idea.compiler.IDELanguageSettingsProvider
import org.jetbrains.kotlin.idea.project.IdeaEnvironment
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
import org.jetbrains.kotlin.platform.JvmBuiltIns
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
fun createModuleResolverProvider(
debugName: String,
project: Project,
globalContext: GlobalContextImpl,
analysisSettings: PlatformAnalysisSettings,
syntheticFiles: Collection<KtFile>,
delegateResolver: ResolverForProject<IdeaModuleInfo>,
moduleFilter: (IdeaModuleInfo) -> Boolean,
allModules: Collection<IdeaModuleInfo>,
providedBuiltIns: KotlinBuiltIns?, // null means create new builtins based on SDK
dependencies: Collection<Any>,
invalidateOnOOCB: Boolean = true
): ModuleResolverProvider {
val builtIns = providedBuiltIns ?: createBuiltIns(analysisSettings, globalContext)
val allModuleInfos = allModules.toMutableSet()
val syntheticFilesByModule = syntheticFiles.groupBy(KtFile::getModuleInfo)
val syntheticFilesModules = syntheticFilesByModule.keys
allModuleInfos.addAll(syntheticFilesModules)
val modulesToCreateResolversFor = allModuleInfos.filter(moduleFilter)
val modulesContent = { module: IdeaModuleInfo ->
ModuleContent(syntheticFilesByModule[module] ?: listOf(), module.contentScope())
}
val jvmPlatformParameters = JvmPlatformParameters { javaClass: JavaClass ->
val psiClass = (javaClass as JavaClassImpl).psi
psiClass.getNullableModuleInfo()
}
val resolverForProject = ResolverForProjectImpl(
debugName, globalContext.withProject(project), modulesToCreateResolversFor,
{ module ->
val platform = module.platform ?: analysisSettings.platform
IdePlatformSupport.facades[platform] ?: throw UnsupportedOperationException("Unsupported platform $platform")
},
modulesContent, jvmPlatformParameters,
IdeaEnvironment, builtIns,
delegateResolver, { _, c -> IDEPackagePartProvider(c.moduleContentScope) },
analysisSettings.sdk?.let { SdkInfo(project, it) },
modulePlatforms = { module -> module.platform?.multiTargetPlatform },
packageOracleFactory = ServiceManager.getService(project, IdePackageOracleFactory::class.java),
languageSettingsProvider = IDELanguageSettingsProvider,
invalidateOnOOCB = invalidateOnOOCB
)
if (providedBuiltIns == null && builtIns is JvmBuiltIns) {
val sdkModuleDescriptor = analysisSettings.sdk!!.let { resolverForProject.descriptorForModule(
SdkInfo(
project,
it
)
) }
builtIns.initialize(sdkModuleDescriptor, analysisSettings.isAdditionalBuiltInFeaturesSupported)
}
return ModuleResolverProvider(
resolverForProject,
builtIns,
dependencies + listOf(globalContext.exceptionTracker)
)
}
private fun createBuiltIns(settings: PlatformAnalysisSettings, sdkContext: GlobalContextImpl): KotlinBuiltIns {
val supportInstance = IdePlatformSupport.platformSupport[settings.platform] ?: return DefaultBuiltIns.Instance
return supportInstance.createBuiltIns(settings, sdkContext)
}
class ModuleResolverProvider(
val resolverForProject: ResolverForProject<IdeaModuleInfo>,
val builtIns: KotlinBuiltIns,
val cacheDependencies: Collection<Any>
)
@@ -16,21 +16,30 @@
package org.jetbrains.kotlin.idea.caches.resolve package org.jetbrains.kotlin.idea.caches.resolve
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager import com.intellij.psi.util.CachedValuesManager
import com.intellij.psi.util.PsiModificationTracker import com.intellij.psi.util.PsiModificationTracker
import com.intellij.util.containers.SLRUCache import com.intellij.util.containers.SLRUCache
import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.analyzer.*
import org.jetbrains.kotlin.analyzer.EmptyResolverForProject import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.analyzer.ResolverForModule import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.caches.resolve.IdePlatformSupport
import org.jetbrains.kotlin.context.GlobalContextImpl import org.jetbrains.kotlin.context.GlobalContextImpl
import org.jetbrains.kotlin.context.withProject
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.idea.caches.project.* import org.jetbrains.kotlin.idea.caches.project.*
import org.jetbrains.kotlin.idea.compiler.IDELanguageSettingsProvider
import org.jetbrains.kotlin.idea.project.IdeaEnvironment
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
import org.jetbrains.kotlin.platform.JvmBuiltIns
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.CompositeBindingContext import org.jetbrains.kotlin.resolve.CompositeBindingContext
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
internal class ProjectResolutionFacade( internal class ProjectResolutionFacade(
@@ -41,7 +50,7 @@ internal class ProjectResolutionFacade(
val settings: PlatformAnalysisSettings, val settings: PlatformAnalysisSettings,
val reuseDataFrom: ProjectResolutionFacade?, val reuseDataFrom: ProjectResolutionFacade?,
val moduleFilter: (IdeaModuleInfo) -> Boolean, val moduleFilter: (IdeaModuleInfo) -> Boolean,
val dependencies: List<Any>, dependencies: List<Any>,
private val invalidateOnOOCB: Boolean, private val invalidateOnOOCB: Boolean,
val syntheticFiles: Collection<KtFile> = listOf(), val syntheticFiles: Collection<KtFile> = listOf(),
val allModules: Collection<IdeaModuleInfo>? = null // null means create resolvers for modules from idea model val allModules: Collection<IdeaModuleInfo>? = null // null means create resolvers for modules from idea model
@@ -49,66 +58,115 @@ internal class ProjectResolutionFacade(
private val cachedValue = CachedValuesManager.getManager(project).createCachedValue( private val cachedValue = CachedValuesManager.getManager(project).createCachedValue(
{ {
val resolverProvider = computeModuleResolverProvider() val resolverProvider = computeModuleResolverProvider()
CachedValueProvider.Result.create(resolverProvider, resolverProvider.cacheDependencies) CachedValueProvider.Result.create(resolverProvider, resolverForProjectDependencies)
}, },
/* trackValue = */ false /* trackValue = */ false
) )
private fun computeModuleResolverProvider(): ModuleResolverProvider { private val cachedResolverForProject: ResolverForProject<IdeaModuleInfo>
val delegateResolverProvider = reuseDataFrom?.moduleResolverProvider
val delegateResolverForProject = delegateResolverProvider?.resolverForProject ?: EmptyResolverForProject()
return createModuleResolverProvider(
resolverDebugName,
project,
globalContext,
settings,
syntheticFiles = syntheticFiles,
delegateResolver = delegateResolverForProject,
moduleFilter = moduleFilter,
allModules = allModules ?: collectAllModuleInfosFromIdeaModel(project),
providedBuiltIns = delegateResolverProvider?.builtIns,
dependencies = dependencies,
invalidateOnOOCB = invalidateOnOOCB
)
}
private val moduleResolverProvider: ModuleResolverProvider
get() = globalContext.storageManager.compute { cachedValue.value } get() = globalContext.storageManager.compute { cachedValue.value }
private val resolverForProject get() = moduleResolverProvider.resolverForProject
fun resolverForModuleInfo(moduleInfo: IdeaModuleInfo) = resolverForProject.resolverForModule(moduleInfo)
fun resolverForElement(element: PsiElement): ResolverForModule {
val infos = element.getModuleInfos()
return infos.asIterable().firstNotNullResult { resolverForProject.tryGetResolverForModule(it) }
?: resolverForProject.tryGetResolverForModule(NotUnderContentRootModuleInfo)
?: resolverForProject.diagnoseUnknownModuleInfo(infos.toList())
}
fun resolverForDescriptor(moduleDescriptor: ModuleDescriptor) = resolverForProject.resolverForModuleDescriptor(moduleDescriptor)
fun findModuleDescriptor(ideaModuleInfo: IdeaModuleInfo): ModuleDescriptor {
return resolverForProject.descriptorForModule(ideaModuleInfo)
}
private val analysisResults = CachedValuesManager.getManager(project).createCachedValue( private val analysisResults = CachedValuesManager.getManager(project).createCachedValue(
{ {
val resolverProvider = moduleResolverProvider val resolverForProject = cachedResolverForProject
val results = object : SLRUCache<KtFile, PerFileAnalysisCache>(2, 3) { val results = object : SLRUCache<KtFile, PerFileAnalysisCache>(2, 3) {
override fun createValue(file: KtFile): PerFileAnalysisCache { override fun createValue(file: KtFile): PerFileAnalysisCache {
return PerFileAnalysisCache( return PerFileAnalysisCache(
file, file,
resolverProvider.resolverForProject.resolverForModule(file.getModuleInfo()).componentProvider resolverForProject.resolverForModule(file.getModuleInfo()).componentProvider
) )
} }
} }
val allDependencies = resolverProvider.cacheDependencies + listOf(PsiModificationTracker.MODIFICATION_COUNT) val allDependencies = resolverForProjectDependencies + listOf(PsiModificationTracker.MODIFICATION_COUNT)
CachedValueProvider.Result.create(results, allDependencies) CachedValueProvider.Result.create(results, allDependencies)
}, false }, false
) )
private val resolverForProjectDependencies = dependencies + listOf(globalContext.exceptionTracker)
private fun computeModuleResolverProvider(): ResolverForProject<IdeaModuleInfo> {
val delegateResolverForProject: ResolverForProject<IdeaModuleInfo>
val delegateBuiltIns: KotlinBuiltIns?
if (reuseDataFrom != null) {
delegateResolverForProject = reuseDataFrom.cachedResolverForProject
delegateBuiltIns = delegateResolverForProject.builtIns
} else {
delegateResolverForProject = EmptyResolverForProject()
delegateBuiltIns = null
}
val builtIns = delegateBuiltIns ?: createBuiltIns(
settings,
globalContext
)
val allModuleInfos = (allModules ?: collectAllModuleInfosFromIdeaModel(project)).toMutableSet()
val syntheticFilesByModule = syntheticFiles.groupBy(KtFile::getModuleInfo)
val syntheticFilesModules = syntheticFilesByModule.keys
allModuleInfos.addAll(syntheticFilesModules)
val modulesToCreateResolversFor = allModuleInfos.filter(moduleFilter)
val modulesContentFactory = { module: IdeaModuleInfo ->
ModuleContent(syntheticFilesByModule[module] ?: listOf(), module.contentScope())
}
val jvmPlatformParameters = JvmPlatformParameters { javaClass: JavaClass ->
val psiClass = (javaClass as JavaClassImpl).psi
psiClass.getNullableModuleInfo()
}
val resolverForProject = ResolverForProjectImpl(
resolverDebugName,
globalContext.withProject(project),
modulesToCreateResolversFor,
{ module ->
val platform = module.platform ?: settings.platform
IdePlatformSupport.facades[platform] ?: throw UnsupportedOperationException("Unsupported platform $platform")
},
modulesContentFactory,
jvmPlatformParameters,
IdeaEnvironment,
builtIns,
delegateResolverForProject,
packagePartProviderFactory = { _, c -> IDEPackagePartProvider(c.moduleContentScope) },
firstDependency = settings.sdk?.let { SdkInfo(project, it) },
modulePlatforms = { module -> module.platform?.multiTargetPlatform },
packageOracleFactory = ServiceManager.getService(project, IdePackageOracleFactory::class.java),
languageSettingsProvider = IDELanguageSettingsProvider,
invalidateOnOOCB = invalidateOnOOCB
)
if (delegateBuiltIns == null && builtIns is JvmBuiltIns) {
val sdkModuleDescriptor = settings.sdk!!.let {
resolverForProject.descriptorForModule(
SdkInfo(project, it)
)
}
builtIns.initialize(sdkModuleDescriptor, settings.isAdditionalBuiltInFeaturesSupported)
}
return resolverForProject
}
fun resolverForModuleInfo(moduleInfo: IdeaModuleInfo) = cachedResolverForProject.resolverForModule(moduleInfo)
fun resolverForElement(element: PsiElement): ResolverForModule {
val infos = element.getModuleInfos()
return infos.asIterable().firstNotNullResult { cachedResolverForProject.tryGetResolverForModule(it) }
?: cachedResolverForProject.tryGetResolverForModule(NotUnderContentRootModuleInfo)
?: cachedResolverForProject.diagnoseUnknownModuleInfo(infos.toList())
}
fun resolverForDescriptor(moduleDescriptor: ModuleDescriptor) = cachedResolverForProject.resolverForModuleDescriptor(moduleDescriptor)
fun findModuleDescriptor(ideaModuleInfo: IdeaModuleInfo): ModuleDescriptor {
return cachedResolverForProject.descriptorForModule(ideaModuleInfo)
}
fun getAnalysisResultsForElements(elements: Collection<KtElement>): AnalysisResult { fun getAnalysisResultsForElements(elements: Collection<KtElement>): AnalysisResult {
assert(elements.isNotEmpty()) { "elements collection should not be empty" } assert(elements.isNotEmpty()) { "elements collection should not be empty" }
val slruCache = synchronized(analysisResults) { val slruCache = synchronized(analysisResults) {
@@ -122,14 +180,22 @@ internal class ProjectResolutionFacade(
} }
val withError = results.firstOrNull { it.isError() } val withError = results.firstOrNull { it.isError() }
val bindingContext = CompositeBindingContext.create(results.map { it.bindingContext }) val bindingContext = CompositeBindingContext.create(results.map { it.bindingContext })
return if (withError != null) if (withError != null) {
AnalysisResult.internalError(bindingContext, withError.error) return AnalysisResult.internalError(bindingContext, withError.error)
else }
//TODO: (module refactoring) several elements are passed here in debugger //TODO: (module refactoring) several elements are passed here in debugger
AnalysisResult.success(bindingContext, findModuleDescriptor(elements.first().getModuleInfo())) return AnalysisResult.success(bindingContext, findModuleDescriptor(elements.first().getModuleInfo()))
} }
override fun toString(): String { override fun toString(): String {
return "$debugString@${Integer.toHexString(hashCode())}" return "$debugString@${Integer.toHexString(hashCode())}"
} }
companion object {
private fun createBuiltIns(settings: PlatformAnalysisSettings, sdkContext: GlobalContextImpl): KotlinBuiltIns {
val supportInstance = IdePlatformSupport.platformSupport[settings.platform] ?: return DefaultBuiltIns.Instance
return supportInstance.createBuiltIns(settings, sdkContext)
}
}
} }