From 90802f2d7c32051d326dfe5d9e3f066aa6114dab Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Thu, 22 Feb 2018 16:10:18 +0300 Subject: [PATCH] Refactoring: remove ModuleResolverProvider, inline createModuleResolverProvider --- .../kotlin/analyzer/AnalyzerFacade.kt | 4 +- .../caches/resolve/ModuleDependencyMapper.kt | 115 ------------- .../caches/resolve/ProjectResolutionFacade.kt | 162 ++++++++++++------ 3 files changed, 117 insertions(+), 164 deletions(-) delete mode 100644 idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ModuleDependencyMapper.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt index 3ef7d72b057..d8ffca04a34 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt @@ -62,6 +62,7 @@ abstract class ResolverForProject { abstract val name: String abstract val allModules: Collection + abstract val builtIns: KotlinBuiltIns override fun toString() = name } @@ -77,6 +78,7 @@ class EmptyResolverForProject : ResolverForProject() { override fun descriptorForModule(moduleInfo: M) = diagnoseUnknownModuleInfo(listOf(moduleInfo)) override val allModules: Collection = listOf() override fun diagnoseUnknownModuleInfo(infos: List) = throw IllegalStateException("Should not be called for $infos") + override val builtIns get() = DefaultBuiltIns.Instance } class ResolverForProjectImpl( @@ -87,7 +89,7 @@ class ResolverForProjectImpl( private val modulesContent: (M) -> ModuleContent, private val platformParameters: PlatformAnalysisParameters, private val targetEnvironment: TargetEnvironment = CompilerEnvironment, - private val builtIns: KotlinBuiltIns = DefaultBuiltIns.Instance, + override val builtIns: KotlinBuiltIns = DefaultBuiltIns.Instance, private val delegateResolver: ResolverForProject = EmptyResolverForProject(), private val packagePartProviderFactory: (M, ModuleContent) -> PackagePartProvider = { _, _ -> PackagePartProvider.Empty }, private val firstDependency: M? = null, diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ModuleDependencyMapper.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ModuleDependencyMapper.kt deleted file mode 100644 index 000bd9f5f25..00000000000 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ModuleDependencyMapper.kt +++ /dev/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, - delegateResolver: ResolverForProject, - moduleFilter: (IdeaModuleInfo) -> Boolean, - allModules: Collection, - providedBuiltIns: KotlinBuiltIns?, // null means create new builtins based on SDK - dependencies: Collection, - 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, - val builtIns: KotlinBuiltIns, - val cacheDependencies: Collection -) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt index 816632f863a..b72754bf9fe 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt @@ -16,21 +16,30 @@ package org.jetbrains.kotlin.idea.caches.resolve +import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValuesManager import com.intellij.psi.util.PsiModificationTracker import com.intellij.util.containers.SLRUCache -import org.jetbrains.kotlin.analyzer.AnalysisResult -import org.jetbrains.kotlin.analyzer.EmptyResolverForProject -import org.jetbrains.kotlin.analyzer.ResolverForModule +import org.jetbrains.kotlin.analyzer.* +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.descriptors.ModuleDescriptor 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.KtFile import org.jetbrains.kotlin.resolve.CompositeBindingContext +import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult internal class ProjectResolutionFacade( @@ -41,7 +50,7 @@ internal class ProjectResolutionFacade( val settings: PlatformAnalysisSettings, val reuseDataFrom: ProjectResolutionFacade?, val moduleFilter: (IdeaModuleInfo) -> Boolean, - val dependencies: List, + dependencies: List, private val invalidateOnOOCB: Boolean, val syntheticFiles: Collection = listOf(), val allModules: Collection? = null // null means create resolvers for modules from idea model @@ -49,66 +58,115 @@ internal class ProjectResolutionFacade( private val cachedValue = CachedValuesManager.getManager(project).createCachedValue( { val resolverProvider = computeModuleResolverProvider() - CachedValueProvider.Result.create(resolverProvider, resolverProvider.cacheDependencies) + CachedValueProvider.Result.create(resolverProvider, resolverForProjectDependencies) }, /* trackValue = */ false ) - private fun computeModuleResolverProvider(): ModuleResolverProvider { - 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 + private val cachedResolverForProject: ResolverForProject 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( { - val resolverProvider = moduleResolverProvider + val resolverForProject = cachedResolverForProject val results = object : SLRUCache(2, 3) { override fun createValue(file: KtFile): PerFileAnalysisCache { return PerFileAnalysisCache( 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) }, false ) + private val resolverForProjectDependencies = dependencies + listOf(globalContext.exceptionTracker) + + private fun computeModuleResolverProvider(): ResolverForProject { + val delegateResolverForProject: ResolverForProject + 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): AnalysisResult { assert(elements.isNotEmpty()) { "elements collection should not be empty" } val slruCache = synchronized(analysisResults) { @@ -122,14 +180,22 @@ internal class ProjectResolutionFacade( } val withError = results.firstOrNull { it.isError() } val bindingContext = CompositeBindingContext.create(results.map { it.bindingContext }) - return if (withError != null) - AnalysisResult.internalError(bindingContext, withError.error) - else + if (withError != null) { + return AnalysisResult.internalError(bindingContext, withError.error) + } + //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 { 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) + } + } }