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