From e38ca445951a53ebd3ab6a13ff1f89691bc18b32 Mon Sep 17 00:00:00 2001 From: Stanislav Erokhin Date: Sat, 28 Jan 2017 06:05:58 +0300 Subject: [PATCH] Create different KotlinBuiltIns for modules with different language feature settings. For sdkModule we create builtIns with default language feature settings. Also when we create sdkModuleResolverProvider we create builtIns cache. Then for every other module we get builtIns cached by value isAdditionalBuiltInsFeatureSupported. --- .../kotlin/analyzer/AnalyzerFacade.kt | 4 +- .../MultiModuleJavaAnalysisCustomTest.kt | 2 +- .../jetbrains/kotlin/platform/JvmBuiltIns.kt | 5 +- .../idea/caches/resolve/BuiltInsCache.kt | 86 +++++++++++++++++++ .../caches/resolve/KotlinCacheServiceImpl.kt | 34 +------- .../caches/resolve/ModuleDependencyMapper.kt | 38 +++++--- 6 files changed, 122 insertions(+), 47 deletions(-) create mode 100644 idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/BuiltInsCache.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt index 33b98f99957..0b8099b260e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt @@ -157,7 +157,7 @@ abstract class AnalyzerFacade { modulesContent: (M) -> ModuleContent, platformParameters: P, targetEnvironment: TargetEnvironment = CompilerEnvironment, - builtIns: KotlinBuiltIns = DefaultBuiltIns.Instance, + builtIns: (M) -> KotlinBuiltIns = { DefaultBuiltIns.Instance }, delegateResolver: ResolverForProject = EmptyResolverForProject(), packagePartProviderFactory: (M, ModuleContent) -> PackagePartProvider = { _, _ -> PackagePartProvider.Empty }, firstDependency: M? = null, @@ -170,7 +170,7 @@ abstract class AnalyzerFacade { modules.forEach { module -> descriptorByModule[module] = - ModuleDescriptorImpl(module.name, storageManager, builtIns, + ModuleDescriptorImpl(module.name, storageManager, builtIns(module), modulePlatforms(module), moduleSources(module), module.capabilities) } return ResolverForProjectImpl(debugName, descriptorByModule, delegateResolver) diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/MultiModuleJavaAnalysisCustomTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/MultiModuleJavaAnalysisCustomTest.kt index 5ca8c78d26d..667fdeda525 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/MultiModuleJavaAnalysisCustomTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/MultiModuleJavaAnalysisCustomTest.kt @@ -74,7 +74,7 @@ class MultiModuleJavaAnalysisCustomTest : KtUsefulTestCase() { val moduleName = javaClass.name.asString().toLowerCase().first().toString() modules.first { it._name == moduleName } }, - builtIns = builtIns, + builtIns = { builtIns }, modulePlatforms = { MultiTargetPlatform.Specific("JVM") } ) diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/platform/JvmBuiltIns.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/platform/JvmBuiltIns.kt index 7efb9b1db0f..c921bd1a581 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/platform/JvmBuiltIns.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/platform/JvmBuiltIns.kt @@ -44,7 +44,10 @@ class JvmBuiltIns @JvmOverloads constructor( JvmBuiltInsSettings( builtInsModule, storageManager, { ownerModuleDescriptor.sure { "JvmBuiltins has not been initialized properly" } }, - { isAdditionalBuiltInsFeatureSupported } + { + ownerModuleDescriptor.sure { "JvmBuiltins has not been initialized properly" } + isAdditionalBuiltInsFeatureSupported + } ) } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/BuiltInsCache.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/BuiltInsCache.kt new file mode 100644 index 00000000000..05d8ad8131e --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/BuiltInsCache.kt @@ -0,0 +1,86 @@ +/* + * Copyright 2010-2017 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.project.Project +import com.intellij.openapi.projectRoots.Sdk +import com.intellij.util.containers.SLRUCache +import org.jetbrains.kotlin.analyzer.LanguageSettingsProvider +import org.jetbrains.kotlin.analyzer.ModuleInfo +import org.jetbrains.kotlin.builtins.DefaultBuiltIns +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl +import org.jetbrains.kotlin.context.GlobalContextImpl +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.js.resolve.JsPlatform +import org.jetbrains.kotlin.platform.JvmBuiltIns +import org.jetbrains.kotlin.resolve.TargetPlatform +import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform + +class BuiltInsCache private constructor( + private val project: Project, + platform: TargetPlatform, + sdk: Sdk?, + sdkModuleDescriptor: ModuleDescriptor?, + sdkContext: GlobalContextImpl +) { + + private val cache: SLRUCache = object : SLRUCache(2, 2) { + override fun createValue(key: Boolean): KotlinBuiltIns { + val builtIns = calculateBuiltIns(platform, sdk, sdkContext) + + if (builtIns is JvmBuiltIns) { + builtIns.initialize(sdkModuleDescriptor!!, key) + } + return builtIns + } + } + + fun getBuiltIns(moduleInfo: ModuleInfo): KotlinBuiltIns { + val languageFeatureSettings = LanguageSettingsProvider.getInstance(project).getLanguageVersionSettings(moduleInfo) + return cache.get(languageFeatureSettings.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers)) + } + + companion object { + fun calculateBuiltIns(platform: TargetPlatform, sdk: Sdk?, sdkContext: GlobalContextImpl): KotlinBuiltIns = when { + platform is JsPlatform -> JsPlatform.builtIns + platform is JvmPlatform && sdk != null -> JvmBuiltIns(sdkContext.storageManager) + else -> DefaultBuiltIns.Instance + } + + fun createCacheAndInitializeBuiltIns( + project: Project, + platform: TargetPlatform, + sdk: Sdk?, + sdkModuleDescriptor: ModuleDescriptor?, + sdkBuiltIns: KotlinBuiltIns, + sdkContext: GlobalContextImpl + ): BuiltInsCache { + val builtInsCache = BuiltInsCache(project, platform, sdk, sdkModuleDescriptor, sdkContext) + + if (sdkBuiltIns is JvmBuiltIns) { + val isAdditionalBuiltInsFeatureSupported = LanguageVersionSettingsImpl.DEFAULT.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers) + sdkBuiltIns.initialize( + sdkModuleDescriptor!!, // sdk is not null for JvmBuiltIns because of calculateBuiltIns + isAdditionalBuiltInsFeatureSupported) + builtInsCache.cache.put(isAdditionalBuiltInsFeatureSupported, sdkBuiltIns) + } + return builtInsCache + } + } +} \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt index 6efbe1e7d06..68226bdc316 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt @@ -29,31 +29,23 @@ import com.intellij.psi.util.CachedValuesManager import com.intellij.psi.util.PsiModificationTracker import com.intellij.util.containers.SLRUCache import org.jetbrains.kotlin.analyzer.EmptyResolverForProject -import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.caches.resolve.KotlinCacheService -import org.jetbrains.kotlin.config.LanguageFeature -import org.jetbrains.kotlin.config.LanguageVersionSettings -import org.jetbrains.kotlin.container.get import org.jetbrains.kotlin.container.getService import org.jetbrains.kotlin.context.GlobalContext import org.jetbrains.kotlin.context.GlobalContextImpl import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesModificationTracker -import org.jetbrains.kotlin.idea.project.AnalyzerFacadeProvider import org.jetbrains.kotlin.idea.project.TargetPlatformDetector import org.jetbrains.kotlin.idea.project.outOfBlockModificationCount import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.util.ProjectRootsUtil -import org.jetbrains.kotlin.js.resolve.JsPlatform -import org.jetbrains.kotlin.platform.JvmBuiltIns import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.resolve.diagnostics.KotlinSuppressCache import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -import org.jetbrains.kotlin.script.KotlinScriptExternalDependencies import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.sumByLong import java.lang.AssertionError @@ -377,32 +369,12 @@ private fun globalResolveSessionProvider( val delegateResolverProvider = reuseDataFrom?.moduleResolverProvider val delegateResolverForProject = delegateResolverProvider?.resolverForProject ?: EmptyResolverForProject() - val reusedBuiltIns = delegateResolverProvider?.builtIns - val newBuiltIns: KotlinBuiltIns? = when { - reusedBuiltIns != null -> null - platform is JsPlatform -> JsPlatform.builtIns - platform is JvmPlatform && sdk != null -> JvmBuiltIns(globalContext.storageManager) - else -> DefaultBuiltIns.Instance - } - - val builtIns = reusedBuiltIns ?: newBuiltIns!! - val moduleResolverProvider = createModuleResolverProvider( + createModuleResolverProvider( debugName, project, globalContext, sdk, - AnalyzerFacadeProvider.getAnalyzerFacade(platform), + platform, syntheticFiles, delegateResolverForProject, moduleFilter, allModules, - builtIns, + delegateResolverProvider?.builtInsCache, dependencies ) - - if (newBuiltIns is JvmBuiltIns) { - val sdkInfo = SdkInfo(project, sdk!!) - newBuiltIns.initialize( - moduleResolverProvider.resolverForProject.descriptorForModule(sdkInfo), - moduleResolverProvider.resolverForProject.resolverForModule(sdkInfo) - .componentProvider.get() - .supportsFeature(LanguageFeature.AdditionalBuiltInsMembers)) - } - - moduleResolverProvider } 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 index 647401244ae..64b53ac1e2a 100644 --- 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 @@ -23,19 +23,20 @@ import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.roots.JdkOrderEntry import com.intellij.openapi.roots.LibraryOrderEntry import com.intellij.openapi.roots.ModuleRootManager -import org.jetbrains.kotlin.analyzer.AnalyzerFacade import org.jetbrains.kotlin.analyzer.ModuleContent +import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.analyzer.ResolverForProject import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.context.GlobalContextImpl import org.jetbrains.kotlin.context.withProject import org.jetbrains.kotlin.descriptors.SourceKind +import org.jetbrains.kotlin.idea.project.AnalyzerFacadeProvider import org.jetbrains.kotlin.idea.project.IdeaEnvironment import org.jetbrains.kotlin.idea.project.TargetPlatformDetector import org.jetbrains.kotlin.load.java.structure.JavaClass import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.resolve.MultiTargetPlatform +import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters fun createModuleResolverProvider( @@ -43,14 +44,21 @@ fun createModuleResolverProvider( project: Project, globalContext: GlobalContextImpl, sdk: Sdk?, - analyzerFacade: AnalyzerFacade, + platform: TargetPlatform, syntheticFiles: Collection, delegateResolver: ResolverForProject, moduleFilter: (IdeaModuleInfo) -> Boolean, allModules: Collection?, - builtIns: KotlinBuiltIns, + builtInsCache: BuiltInsCache?, // this cache is null only for SDK resolver provider dependencies: Collection ): ModuleResolverProvider { + var sdkBuiltIns: KotlinBuiltIns? = null + + val builtInsProvider: (ModuleInfo) -> KotlinBuiltIns = builtInsCache?.let { it::getBuiltIns } ?: run { + sdkBuiltIns = BuiltInsCache.calculateBuiltIns(platform, sdk, globalContext); + + { _: ModuleInfo -> sdkBuiltIns!! } + } val allModuleInfos = (allModules ?: collectAllModuleInfosFromIdeaModel(project)).toHashSet() @@ -71,10 +79,10 @@ fun createModuleResolverProvider( psiClass.getNullableModuleInfo() } - val resolverForProject = analyzerFacade.setupResolverForProject( + return AnalyzerFacadeProvider.getAnalyzerFacade(platform).setupResolverForProject( debugName, globalContext.withProject(project), modulesToCreateResolversFor, modulesContent, - jvmPlatformParameters, IdeaEnvironment, builtIns, - delegateResolver, { m, c -> IDEPackagePartProvider(c.moduleContentScope) }, + jvmPlatformParameters, IdeaEnvironment, builtInsProvider, + delegateResolver, { _, c -> IDEPackagePartProvider(c.moduleContentScope) }, sdk?.let { SdkInfo(project, it) }, modulePlatforms = { moduleInfo -> val module = (moduleInfo as? ModuleSourceInfo)?.module @@ -89,14 +97,19 @@ fun createModuleResolverProvider( } ) - return resolverForProject } val resolverForProject = createResolverForProject() + val newBuiltInsCache = builtInsCache ?: run { + val sdkModuleDescriptor = sdk?.let { resolverForProject.descriptorForModule(SdkInfo(project, it)) } + + BuiltInsCache.createCacheAndInitializeBuiltIns(project, platform, sdk, sdkModuleDescriptor, sdkBuiltIns!!, globalContext) + } + return ModuleResolverProviderImpl( resolverForProject, - builtIns, + newBuiltInsCache, dependencies + listOf(globalContext.exceptionTracker) ) } @@ -133,11 +146,12 @@ fun getAllProjectSdks(): Collection { interface ModuleResolverProvider { val resolverForProject: ResolverForProject - val builtIns: KotlinBuiltIns + val builtInsCache: BuiltInsCache val cacheDependencies: Collection } class ModuleResolverProviderImpl( override val resolverForProject: ResolverForProject, - override val builtIns: KotlinBuiltIns, - override val cacheDependencies: Collection) : ModuleResolverProvider + override val builtInsCache: BuiltInsCache, + override val cacheDependencies: Collection +) : ModuleResolverProvider