From 2b4d70fcf0c3f6b54f1e6043feea56d2e979f5c2 Mon Sep 17 00:00:00 2001 From: Dmitry Savvinov Date: Fri, 7 Jun 2019 18:08:37 +0300 Subject: [PATCH] [Resolve] Rewrite how built-ins are created Under COMPOSITE mode we don't have a globally known way to create built-ins, instead, we have to create them on per-module basis. So, in this commit we: 1. Use builtInsProvider: (ModuleInfo) -> KotlinBuiltIns instead of precomputed builtIns instance, in order to be able to calculate builtIns on per-module basis 2. Introduce new entity, called BuiltInsCache, which, roughly speaking, is a map of form ModuleInfo -> KotlinBuiltIns, to prevent creation of multiple builtInsInstances NB. Actually, it's of form BuiltInsCacheKey -> KotlinBuiltIns, because we shouldn't create new builtIns for each module. Also, currently, each platform has its own BuiltInsCacheKey implementation, because parameters by which built-ins are created, are a bit different across different platforms. Ideally, we should eliminate those differences and they use one concrete implementation as a key. --- .../common/CommonResolverForModuleFactory.kt | 5 +- .../kotlin/analyzer/AnalyzerFacade.kt | 8 +-- .../resolve/lazy/lazyResolveTestUtils.kt | 5 +- .../MultiModuleJavaAnalysisCustomTest.kt | 3 +- .../resolve/CommonPlatformKindResolution.kt | 7 ++- .../resolve/IdePlatformKindResolution.kt | 5 +- .../resolve/JsPlatformKindResolution.kt | 12 +++-- .../resolve/JvmPlatformKindResolution.kt | 19 +++++-- .../caches/resolve/KotlinCacheServiceImpl.kt | 53 ++++++++++++++++--- .../caches/resolve/ProjectResolutionFacade.kt | 47 ++++++++-------- .../ide/konan/NativePlatformKindResolution.kt | 26 +++++---- 11 files changed, 135 insertions(+), 55 deletions(-) diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/analyzer/common/CommonResolverForModuleFactory.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/analyzer/common/CommonResolverForModuleFactory.kt index 48835cfb73d..7ca87171a3c 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/analyzer/common/CommonResolverForModuleFactory.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/analyzer/common/CommonResolverForModuleFactory.kt @@ -20,6 +20,7 @@ import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.project.Project import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.analyzer.* +import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.container.StorageComponentContainer @@ -149,7 +150,9 @@ class CommonResolverForModuleFactory( CommonPlatforms.defaultCommonPlatform, shouldCheckExpectActual = false ) - } + }, + builtInsProvider = { DefaultBuiltIns.Instance }, + sdkDependency = { null } ) val moduleDescriptor = resolver.descriptorForModule(moduleInfo) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt index ed6927d0638..a158c235e61 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt @@ -58,7 +58,7 @@ abstract class ResolverForProject { abstract val name: String abstract val allModules: Collection - abstract val builtIns: KotlinBuiltIns + abstract val builtInsProvider: (M) -> KotlinBuiltIns override fun toString() = name @@ -83,7 +83,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 + override val builtInsProvider: (M) -> KotlinBuiltIns = { DefaultBuiltIns.Instance } } class ResolverForProjectImpl( @@ -94,7 +94,7 @@ class ResolverForProjectImpl( private val moduleLanguageSettingsProvider: LanguageSettingsProvider, private val resolverForModuleFactoryByPlatform: (TargetPlatform?) -> ResolverForModuleFactory, private val invalidateOnOOCB: Boolean, - override val builtIns: KotlinBuiltIns = DefaultBuiltIns.Instance, + override val builtInsProvider: (M) -> KotlinBuiltIns, private val delegateResolver: ResolverForProject = EmptyResolverForProject(), private val sdkDependency: (M) -> M?, private val packageOracleFactory: PackageOracleFactory = PackageOracleFactory.OptimisticFactory, @@ -251,7 +251,7 @@ class ResolverForProjectImpl( val moduleDescriptor = ModuleDescriptorImpl( module.name, projectContext.storageManager, - builtIns, + builtInsProvider(module), module.platform, module.capabilities, module.stableName diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/resolve/lazy/lazyResolveTestUtils.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/resolve/lazy/lazyResolveTestUtils.kt index 949ba993a75..69d3d65d6fe 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/resolve/lazy/lazyResolveTestUtils.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/resolve/lazy/lazyResolveTestUtils.kt @@ -20,6 +20,7 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.util.ModificationTracker import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.analyzer.* +import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.container.get import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.load.kotlin.PackagePartProvider @@ -53,7 +54,9 @@ fun createResolveSessionForFiles( moduleLanguageSettingsProvider = LanguageSettingsProvider.Default, resolverForModuleFactoryByPlatform = { JvmResolverForModuleFactory(platformParameters, CompilerEnvironment, JvmPlatforms.defaultJvmPlatform) - } + }, + builtInsProvider = { DefaultBuiltIns.Instance }, + sdkDependency = { null } ) return resolverForProject.resolverForModule(testModule).componentProvider.get() } diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/MultiModuleJavaAnalysisCustomTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/MultiModuleJavaAnalysisCustomTest.kt index e26bfb78744..d3f56106ca6 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/MultiModuleJavaAnalysisCustomTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/MultiModuleJavaAnalysisCustomTest.kt @@ -96,7 +96,8 @@ class MultiModuleJavaAnalysisCustomTest : KtUsefulTestCase() { resolverForModuleFactoryByPlatform = { JvmResolverForModuleFactory(platformParameters, CompilerEnvironment, JvmPlatforms.defaultJvmPlatform) }, - sdkDependency = { null } + sdkDependency = { null }, + builtInsProvider = { builtIns } ) builtIns.initialize( diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/CommonPlatformKindResolution.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/CommonPlatformKindResolution.kt index f2ad9ed55e0..8260628b5df 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/CommonPlatformKindResolution.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/CommonPlatformKindResolution.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.caches.resolve import com.intellij.openapi.roots.libraries.PersistentLibraryKind import com.intellij.openapi.vfs.VirtualFile +import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.analyzer.PlatformAnalysisParameters import org.jetbrains.kotlin.analyzer.ResolverForModuleFactory import org.jetbrains.kotlin.analyzer.common.CommonAnalysisParameters @@ -14,7 +15,7 @@ import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.context.ProjectContext -import org.jetbrains.kotlin.idea.caches.resolve.PlatformAnalysisSettings +import org.jetbrains.kotlin.idea.caches.resolve.BuiltInsCacheKey import org.jetbrains.kotlin.idea.framework.CommonLibraryKind import org.jetbrains.kotlin.platform.impl.CommonIdePlatformKind import org.jetbrains.kotlin.resolve.TargetEnvironment @@ -31,7 +32,9 @@ class CommonPlatformKindResolution : IdePlatformKindResolution { override val kind get() = CommonIdePlatformKind - override fun createBuiltIns(settings: PlatformAnalysisSettings, projectContext: ProjectContext): KotlinBuiltIns { + override fun getKeyForBuiltIns(moduleInfo: ModuleInfo): BuiltInsCacheKey = BuiltInsCacheKey.DefaultBuiltInsKey + + override fun createBuiltIns(moduleInfo: ModuleInfo, projectContext: ProjectContext): KotlinBuiltIns { return DefaultBuiltIns.Instance } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/IdePlatformKindResolution.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/IdePlatformKindResolution.kt index d3fee2cb34f..923a93792b0 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/IdePlatformKindResolution.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/IdePlatformKindResolution.kt @@ -30,7 +30,7 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentProvider import org.jetbrains.kotlin.extensions.ApplicationExtensionDescriptor import org.jetbrains.kotlin.idea.caches.project.LibraryInfo -import org.jetbrains.kotlin.idea.caches.resolve.PlatformAnalysisSettings +import org.jetbrains.kotlin.idea.caches.resolve.BuiltInsCacheKey import org.jetbrains.kotlin.platform.IdePlatformKind import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.resolve.TargetEnvironment @@ -39,7 +39,8 @@ import org.jetbrains.kotlin.storage.StorageManager interface IdePlatformKindResolution { val kind: IdePlatformKind<*> - fun createBuiltIns(settings: PlatformAnalysisSettings, projectContext: ProjectContext): KotlinBuiltIns + fun getKeyForBuiltIns(moduleInfo: ModuleInfo): BuiltInsCacheKey + fun createBuiltIns(moduleInfo: ModuleInfo, projectContext: ProjectContext): KotlinBuiltIns fun createResolverForModuleFactory( settings: PlatformAnalysisParameters, diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/JsPlatformKindResolution.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/JsPlatformKindResolution.kt index 16f24a6da7a..5d98bd6a16d 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/JsPlatformKindResolution.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/JsPlatformKindResolution.kt @@ -7,11 +7,13 @@ package org.jetbrains.kotlin.caches.resolve import com.intellij.openapi.roots.libraries.PersistentLibraryKind import com.intellij.openapi.vfs.VirtualFile +import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.analyzer.PlatformAnalysisParameters import org.jetbrains.kotlin.analyzer.ResolverForModuleFactory +import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.context.ProjectContext -import org.jetbrains.kotlin.idea.caches.resolve.PlatformAnalysisSettings +import org.jetbrains.kotlin.idea.caches.resolve.BuiltInsCacheKey import org.jetbrains.kotlin.idea.framework.JSLibraryKind import org.jetbrains.kotlin.js.resolve.JsResolverForModuleFactory import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices @@ -29,8 +31,12 @@ class JsPlatformKindResolution : IdePlatformKindResolution { override val kind get() = JsIdePlatformKind - override fun createBuiltIns(settings: PlatformAnalysisSettings, projectContext: ProjectContext): KotlinBuiltIns { - return JsPlatformAnalyzerServices.builtIns + override fun getKeyForBuiltIns(moduleInfo: ModuleInfo): BuiltInsCacheKey { + return BuiltInsCacheKey.DefaultBuiltInsKey + } + + override fun createBuiltIns(moduleInfo: ModuleInfo, projectContext: ProjectContext): KotlinBuiltIns { + return DefaultBuiltIns.Instance } override fun createResolverForModuleFactory( diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/JvmPlatformKindResolution.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/JvmPlatformKindResolution.kt index b17b12ca1fa..90468d7b2de 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/JvmPlatformKindResolution.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/JvmPlatformKindResolution.kt @@ -5,15 +5,18 @@ package org.jetbrains.kotlin.caches.resolve +import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.roots.libraries.PersistentLibraryKind import com.intellij.openapi.vfs.VirtualFile +import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.analyzer.PlatformAnalysisParameters import org.jetbrains.kotlin.analyzer.ResolverForModuleFactory import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns import org.jetbrains.kotlin.context.ProjectContext -import org.jetbrains.kotlin.idea.caches.resolve.PlatformAnalysisSettings +import org.jetbrains.kotlin.idea.caches.project.findSdkAcrossDependencies +import org.jetbrains.kotlin.idea.caches.resolve.BuiltInsCacheKey import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.platform.impl.JvmIdePlatformKind import org.jetbrains.kotlin.resolve.TargetEnvironment @@ -38,9 +41,19 @@ class JvmPlatformKindResolution : IdePlatformKindResolution { override val kind get() = JvmIdePlatformKind - override fun createBuiltIns(settings: PlatformAnalysisSettings, projectContext: ProjectContext): KotlinBuiltIns = - if (settings.sdk != null) + override fun getKeyForBuiltIns(moduleInfo: ModuleInfo): BuiltInsCacheKey { + val sdkInfo = moduleInfo.findSdkAcrossDependencies() + return if (sdkInfo != null) CacheKeyBySdk(sdkInfo.sdk) else BuiltInsCacheKey.DefaultBuiltInsKey + } + + override fun createBuiltIns(moduleInfo: ModuleInfo, projectContext: ProjectContext): KotlinBuiltIns { + val sdk = moduleInfo.findSdkAcrossDependencies() + + return if (sdk != null) JvmBuiltIns(projectContext.storageManager, JvmBuiltIns.Kind.FROM_CLASS_LOADER) else DefaultBuiltIns.Instance + } + + data class CacheKeyBySdk(val sdk: Sdk) : BuiltInsCacheKey } 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 4389aa6a515..53ac6a2e294 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 @@ -34,7 +34,10 @@ import org.jetbrains.kotlin.analyzer.ResolverForProject.Companion.resolverForMod import org.jetbrains.kotlin.analyzer.ResolverForProject.Companion.resolverForScriptDependenciesName import org.jetbrains.kotlin.analyzer.ResolverForProject.Companion.resolverForSdkName import org.jetbrains.kotlin.analyzer.ResolverForProject.Companion.resolverForSpecialInfoName +import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.caches.project.cacheByClass +import org.jetbrains.kotlin.caches.project.cacheInvalidatingOnRootModifications import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.isTypeRefinementEnabled @@ -62,6 +65,7 @@ import org.jetbrains.kotlin.resolve.diagnostics.KotlinSuppressCache import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.sumByLong +import java.util.concurrent.ConcurrentHashMap internal val LOG = Logger.getInstance(KotlinCacheService::class.java) @@ -175,7 +179,8 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { dependencies = dependenciesForScriptDependencies, moduleFilter = { it == dependenciesModuleInfo }, invalidateOnOOCB = true, - syntheticFiles = syntheticFiles + syntheticFiles = syntheticFiles, + builtInsCache = globalFacade.builtInsCache ) } @@ -191,7 +196,8 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { ProjectRootModificationTracker.getInstance(project) ), invalidateOnOOCB = false, - reuseDataFrom = null + reuseDataFrom = null, + builtInsCache = BuiltInsCache(project) ) private val librariesContext = sdkContext.contextWithCompositeExceptionTracker(project, resolverForLibrariesName) @@ -204,7 +210,8 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { dependencies = listOf( LibraryModificationTracker.getInstance(project), ProjectRootModificationTracker.getInstance(project) - ) + ), + builtInsCache = facadeForSdk.builtInsCache ) private val modulesContext = librariesContext.contextWithCompositeExceptionTracker(project, resolverForModulesName) @@ -217,7 +224,8 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { LibraryModificationTracker.getInstance(project), ProjectRootModificationTracker.getInstance(project) ), - invalidateOnOOCB = true + invalidateOnOOCB = true, + builtInsCache = facadeForLibraries.builtInsCache ) } @@ -288,7 +296,8 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { moduleFilter = moduleFilter, dependencies = dependenciesForSyntheticFileCache, invalidateOnOOCB = true, - allModules = allModules + allModules = allModules, + builtInsCache = reuseDataFrom?.builtInsCache ?: BuiltInsCache(project) ) } @@ -297,7 +306,10 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { val dependentModules = specialModuleInfo.getDependentModules() val modulesFacade = globalFacade(settings) val globalContext = - modulesFacade.globalContext.contextWithCompositeExceptionTracker(project, "facadeForSpecialModuleInfo (ModuleSourceInfo)") + modulesFacade.globalContext.contextWithCompositeExceptionTracker( + project, + "facadeForSpecialModuleInfo (ModuleSourceInfo)" + ) makeProjectResolutionFacade( "facadeForSpecialModuleInfo (ModuleSourceInfo)", globalContext, @@ -528,6 +540,35 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { } } +class BuiltInsCache(private val project: Project) { + private val innerCache + get() = project.cacheByClass( + BuiltInsCache::class.java, + ProjectRootModificationTracker.getInstance(project), + LibraryModificationTracker.getInstance(project) + ) { ConcurrentHashMap() } + + init { + innerCache[BuiltInsCacheKey.DefaultBuiltInsKey] = DefaultBuiltIns.Instance + } + + fun getOrPut(key: BuiltInsCacheKey, ifAbsent: (BuiltInsCacheKey) -> KotlinBuiltIns): KotlinBuiltIns { + return innerCache.computeIfAbsent(key, ifAbsent) + } + + operator fun get(key: BuiltInsCacheKey): KotlinBuiltIns? { + return innerCache[key] + } + + operator fun set(key: BuiltInsCacheKey, value: KotlinBuiltIns) { + innerCache[key] = value + } +} + +interface BuiltInsCacheKey { + object DefaultBuiltInsKey : BuiltInsCacheKey +} + fun IdeaModuleInfo.supportsAdditionalBuiltInsMembers(project: Project): Boolean { return IDELanguageSettingsProvider .getLanguageVersionSettings(this, project) 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 da7919b0042..0595088412e 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 @@ -65,6 +65,7 @@ internal class ProjectResolutionFacade( val moduleFilter: (IdeaModuleInfo) -> Boolean, dependencies: List, private val invalidateOnOOCB: Boolean, + val builtInsCache: BuiltInsCache, val syntheticFiles: Collection = listOf(), val allModules: Collection? = null // null means create resolvers for modules from idea model ) { @@ -104,18 +105,11 @@ internal class ProjectResolutionFacade( if (reuseDataFrom != null) { delegateResolverForProject = reuseDataFrom.cachedResolverForProject - delegateBuiltIns = delegateResolverForProject.builtIns } else { delegateResolverForProject = EmptyResolverForProject() - delegateBuiltIns = null } val projectContext = globalContext.withProject(project) - val builtIns = delegateBuiltIns ?: createBuiltIns( - settings, - projectContext - ) - val allModuleInfos = (allModules ?: getModuleInfosFromIdeaModel(project, (settings as? PlatformAnalysisSettingsImpl)?.platform)) .toMutableSet() @@ -165,7 +159,11 @@ internal class ProjectResolutionFacade( CompositeAnalyzerServices(modulePlatform.componentPlatforms.map { it.toTargetPlatform().findAnalyzerServices }) ) }, - builtIns = builtIns, + builtInsProvider = { module -> + require(module in modulesToCreateResolversFor) + val key = module.platform.idePlatformKind.resolution.getKeyForBuiltIns(module) + builtInsCache.getOrPut(key) { throw IllegalStateException("Can't find builtIns by key $key for module $module") } + }, delegateResolver = delegateResolverForProject, sdkDependency = { module -> if (settings is PlatformAnalysisSettingsImpl) @@ -178,13 +176,26 @@ internal class ProjectResolutionFacade( isReleaseCoroutines = settings.isReleaseCoroutines ) - if (delegateBuiltIns == null && builtIns is JvmBuiltIns) { - val sdkModuleDescriptor = (settings as PlatformAnalysisSettingsImpl).sdk!!.let { - resolverForProject.descriptorForModule( - SdkInfo(project, it) - ) + // Fill builtInsCache + modulesToCreateResolversFor.forEach { + val key = it.platform.idePlatformKind.resolution.getKeyForBuiltIns(it) + val cachedBuiltIns = builtInsCache[key] + if (cachedBuiltIns == null) { + // Note that we can't use .getOrPut, because we have to put builtIns into map *before* + // initialization + val builtIns = it.platform.idePlatformKind.resolution.createBuiltIns(it, projectContext) + builtInsCache[key] = builtIns + + if (builtIns is JvmBuiltIns) { + // SDK should be present, otherwise we wouldn't have created JvmBuiltIns in createBuiltIns + val sdk = it.findSdkAcrossDependencies()!! + val sdkDescriptor = resolverForProject.descriptorForModule(sdk) + + val isAdditionalBuiltInsFeaturesSupported = it.supportsAdditionalBuiltInsMembers(project) + + builtIns.initialize(sdkDescriptor, isAdditionalBuiltInsFeaturesSupported) + } } - builtIns.initialize(sdkModuleDescriptor, settings.isAdditionalBuiltInFeaturesSupported) } return resolverForProject @@ -230,12 +241,4 @@ internal class ProjectResolutionFacade( override fun toString(): String { return "$debugString@${Integer.toHexString(hashCode())}" } - - private companion object { - private fun createBuiltIns(settings: PlatformAnalysisSettings, projectContext: ProjectContext): KotlinBuiltIns { -// return settings.platform.idePlatformKind.resolution.createBuiltIns(settings, projectContext) -// TODO: what we do about built-ins? - return JvmPlatforms.defaultJvmPlatform.idePlatformKind.resolution.createBuiltIns(settings, projectContext) - } - } } diff --git a/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/NativePlatformKindResolution.kt b/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/NativePlatformKindResolution.kt index 874480a15e5..68fef8b471c 100644 --- a/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/NativePlatformKindResolution.kt +++ b/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/NativePlatformKindResolution.kt @@ -28,7 +28,9 @@ import org.jetbrains.kotlin.descriptors.konan.DeserializedKonanModuleOrigin import org.jetbrains.kotlin.ide.konan.analyzer.NativeResolverForModuleFactory import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo import org.jetbrains.kotlin.idea.caches.project.LibraryInfo +import org.jetbrains.kotlin.idea.caches.project.SdkInfo import org.jetbrains.kotlin.idea.caches.project.getModuleInfosFromIdeaModel +import org.jetbrains.kotlin.idea.caches.resolve.BuiltInsCacheKey import org.jetbrains.kotlin.idea.caches.resolve.PlatformAnalysisSettings import org.jetbrains.kotlin.idea.compiler.IDELanguageSettingsProvider import org.jetbrains.kotlin.konan.file.File @@ -39,6 +41,7 @@ import org.jetbrains.kotlin.platform.impl.NativeIdePlatformKind import org.jetbrains.kotlin.platform.konan.KonanPlatforms import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.storage.StorageManager +import org.jetbrains.kotlin.types.typeUtil.lazyClosure import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult class NativePlatformKindResolution : IdePlatformKindResolution { @@ -97,16 +100,20 @@ class NativePlatformKindResolution : IdePlatformKindResolution { override val kind get() = NativeIdePlatformKind - override fun createBuiltIns(settings: PlatformAnalysisSettings, projectContext: ProjectContext) = - createKotlinNativeBuiltIns(settings, projectContext) + override fun getKeyForBuiltIns(moduleInfo: ModuleInfo): BuiltInsCacheKey = NativeBuiltInsCacheKey + + override fun createBuiltIns(moduleInfo: ModuleInfo, projectContext: ProjectContext) = + createKotlinNativeBuiltIns(moduleInfo, projectContext) + + object NativeBuiltInsCacheKey : BuiltInsCacheKey } -private fun createKotlinNativeBuiltIns(settings: PlatformAnalysisSettings, projectContext: ProjectContext): KotlinBuiltIns { +private fun createKotlinNativeBuiltIns(moduleInfo: ModuleInfo, projectContext: ProjectContext): KotlinBuiltIns { val project = projectContext.project val storageManager = projectContext.storageManager - val stdlibInfo = findNativeStdlib(project) ?: return DefaultBuiltIns.Instance + val stdlibInfo = moduleInfo.findNativeStdlib(project) ?: return DefaultBuiltIns.Instance val konanLibrary = stdlibInfo.getCapability(NativeLibraryInfo.NATIVE_LIBRARY_CAPABILITY)!! val builtInsModule = KonanFactories.DefaultDescriptorFactory.createDescriptorAndNewBuiltIns( @@ -116,7 +123,7 @@ private fun createKotlinNativeBuiltIns(settings: PlatformAnalysisSettings, proje stdlibInfo.capabilities ) - val languageSettings = IDELanguageSettingsProvider.getLanguageVersionSettings(stdlibInfo, project, settings.isReleaseCoroutines) + val languageSettings = IDELanguageSettingsProvider.getLanguageVersionSettings(stdlibInfo, project, isReleaseCoroutines = false) val deserializationConfiguration = CompilerDeserializationConfiguration(languageSettings) val libraryProto = konanLibrary.moduleHeaderData @@ -147,11 +154,10 @@ private fun createKotlinNativeBuiltIns(settings: PlatformAnalysisSettings, proje return builtInsModule.builtIns } -// TODO: It depends on a random module's stdlib, propagate the actual module here. -private fun findNativeStdlib(project: Project): NativeLibraryInfo? = getModuleInfosFromIdeaModel(project, KonanPlatforms.defaultKonanPlatform) - .firstNotNullResult { it.asNativeStdlib() } - -private fun IdeaModuleInfo.asNativeStdlib(): NativeLibraryInfo? = if ((this as? NativeLibraryInfo)?.isStdlib == true) this else null +private fun ModuleInfo.findNativeStdlib(project: Project): NativeLibraryInfo? = + dependencies().lazyClosure { it.dependencies() } + .filterIsInstance() + .firstOrNull { it.isStdlib } class NativeLibraryInfo(project: Project, library: Library, root: File) : LibraryInfo(project, library) {