diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/builtins/jvm/JvmBuiltIns.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/builtins/jvm/JvmBuiltIns.kt index 987b33ae4ac..67306bf3b4f 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/builtins/jvm/JvmBuiltIns.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/builtins/jvm/JvmBuiltIns.kt @@ -53,25 +53,35 @@ class JvmBuiltIns(storageManager: StorageManager, kind: Kind) : KotlinBuiltIns(s FALLBACK, } - // Module containing JDK classes or having them among dependencies - private var ownerModuleDescriptor: ModuleDescriptor? = null - private var isAdditionalBuiltInsFeatureSupported: Boolean = true + class Settings( + // Module containing JDK classes or having them among dependencies + val ownerModuleDescriptor: ModuleDescriptor, + val isAdditionalBuiltInsFeatureSupported: Boolean, + ) + + private var settingsComputation: (() -> Settings)? = null + + fun setPostponedSettingsComputation(computation: () -> Settings) { + assert(settingsComputation == null) { "JvmBuiltins repeated initialization" } + settingsComputation = computation + } fun initialize(moduleDescriptor: ModuleDescriptor, isAdditionalBuiltInsFeatureSupported: Boolean) { - assert(ownerModuleDescriptor == null) { "JvmBuiltins repeated initialization" } - this.ownerModuleDescriptor = moduleDescriptor - this.isAdditionalBuiltInsFeatureSupported = isAdditionalBuiltInsFeatureSupported + setPostponedSettingsComputation { + Settings(moduleDescriptor, isAdditionalBuiltInsFeatureSupported) + } } val customizer: JvmBuiltInsCustomizer by storageManager.createLazyValue { JvmBuiltInsCustomizer( - builtInsModule, storageManager, - { ownerModuleDescriptor.sure { "JvmBuiltins has not been initialized properly" } }, - { - ownerModuleDescriptor.sure { "JvmBuiltins has not been initialized properly" } - isAdditionalBuiltInsFeatureSupported - } - ) + builtInsModule, storageManager + ) { + settingsComputation + .sure { "JvmBuiltins instance has not been initialized properly" } + .invoke().also { + settingsComputation = null + } + } } init { diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/builtins/jvm/JvmBuiltInsCustomizer.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/builtins/jvm/JvmBuiltInsCustomizer.kt index 13d8b1998a5..386b4a3720d 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/builtins/jvm/JvmBuiltInsCustomizer.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/builtins/jvm/JvmBuiltInsCustomizer.kt @@ -50,19 +50,17 @@ import java.util.* class JvmBuiltInsCustomizer( private val moduleDescriptor: ModuleDescriptor, storageManager: StorageManager, - deferredOwnerModuleDescriptor: () -> ModuleDescriptor, - isAdditionalBuiltInsFeatureSupported: () -> Boolean + settingsComputation: () -> JvmBuiltIns.Settings, ) : AdditionalClassPartsProvider, PlatformDependentDeclarationFilter { private val j2kClassMapper = JavaToKotlinClassMapper - private val ownerModuleDescriptor: ModuleDescriptor by lazy(deferredOwnerModuleDescriptor) - private val isAdditionalBuiltInsFeatureSupported: Boolean by lazy(isAdditionalBuiltInsFeatureSupported) + private val settings by storageManager.createLazyValue(settingsComputation) private val mockSerializableType = storageManager.createMockJavaIoSerializableType() private val cloneableType by storageManager.createLazyValue { - ownerModuleDescriptor.findNonGenericClassAcrossDependencies( + settings.ownerModuleDescriptor.findNonGenericClassAcrossDependencies( JvmBuiltInClassDescriptorFactory.CLONEABLE_CLASS_ID, - NotFoundClasses(storageManager, ownerModuleDescriptor) + NotFoundClasses(storageManager, settings.ownerModuleDescriptor) ).defaultType } @@ -119,7 +117,7 @@ class JvmBuiltInsCustomizer( ) } - if (!isAdditionalBuiltInsFeatureSupported) return emptyList() + if (!settings.isAdditionalBuiltInsFeatureSupported) return emptyList() return getAdditionalFunctions(classDescriptor) { it.getContributedFunctions(name, NoLookupLocation.FROM_BUILTINS) @@ -158,7 +156,7 @@ class JvmBuiltInsCustomizer( } override fun getFunctionsNames(classDescriptor: ClassDescriptor): Set { - if (!isAdditionalBuiltInsFeatureSupported) return emptySet() + if (!settings.isAdditionalBuiltInsFeatureSupported) return emptySet() // NB: It's just an approximation that could be calculated relatively fast // More precise computation would look like `getAdditionalFunctions` (and the measurements show that it would be rather slow) return classDescriptor.getJavaAnalogue()?.unsubstitutedMemberScope?.getFunctionNames() ?: emptySet() @@ -270,11 +268,11 @@ class JvmBuiltInsCustomizer( if (!fqName.isSafe) return null val javaAnalogueFqName = JavaToKotlinClassMap.mapKotlinToJava(fqName)?.asSingleFqName() ?: return null - return ownerModuleDescriptor.resolveClassByFqName(javaAnalogueFqName, NoLookupLocation.FROM_BUILTINS) as? LazyJavaClassDescriptor + return settings.ownerModuleDescriptor.resolveClassByFqName(javaAnalogueFqName, NoLookupLocation.FROM_BUILTINS) as? LazyJavaClassDescriptor } override fun getConstructors(classDescriptor: ClassDescriptor): Collection { - if (classDescriptor.kind != ClassKind.CLASS || !isAdditionalBuiltInsFeatureSupported) return emptyList() + if (classDescriptor.kind != ClassKind.CLASS || !settings.isAdditionalBuiltInsFeatureSupported) return emptyList() val javaAnalogueDescriptor = classDescriptor.getJavaAnalogue() ?: return emptyList() @@ -317,7 +315,7 @@ class JvmBuiltInsCustomizer( val javaAnalogueClassDescriptor = classDescriptor.getJavaAnalogue() ?: return true if (!functionDescriptor.annotations.hasAnnotation(PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME)) return true - if (!isAdditionalBuiltInsFeatureSupported) return false + if (!settings.isAdditionalBuiltInsFeatureSupported) return false val jvmDescriptor = functionDescriptor.computeJvmDescriptor() return javaAnalogueClassDescriptor 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 74b023e01cb..1e193ce59b4 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 @@ -14,6 +14,7 @@ import com.intellij.util.PathUtil import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.analyzer.PlatformAnalysisParameters import org.jetbrains.kotlin.analyzer.ResolverForModuleFactory +import org.jetbrains.kotlin.analyzer.ResolverForProject import org.jetbrains.kotlin.analyzer.common.CommonAnalysisParameters import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory import org.jetbrains.kotlin.builtins.DefaultBuiltIns @@ -22,6 +23,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentProvider +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.resolve.BuiltInsCacheKey @@ -53,7 +55,12 @@ class CommonPlatformKindResolution : IdePlatformKindResolution { override fun getKeyForBuiltIns(moduleInfo: ModuleInfo, sdkInfo: SdkInfo?): BuiltInsCacheKey = BuiltInsCacheKey.DefaultBuiltInsKey - override fun createBuiltIns(moduleInfo: ModuleInfo, projectContext: ProjectContext, sdkDependency: SdkInfo?): KotlinBuiltIns { + override fun createBuiltIns( + moduleInfo: IdeaModuleInfo, + projectContext: ProjectContext, + resolverForProject: ResolverForProject, + sdkDependency: SdkInfo? + ): 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 5026d5e1968..3e0e51e0144 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 @@ -23,12 +23,14 @@ 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.ResolverForProject import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.context.ProjectContext 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.IdeaModuleInfo import org.jetbrains.kotlin.idea.caches.project.LibraryInfo import org.jetbrains.kotlin.idea.caches.project.SdkInfo import org.jetbrains.kotlin.idea.caches.resolve.BuiltInsCacheKey @@ -41,7 +43,12 @@ interface IdePlatformKindResolution { val kind: IdePlatformKind<*> fun getKeyForBuiltIns(moduleInfo: ModuleInfo, sdkInfo: SdkInfo?): BuiltInsCacheKey - fun createBuiltIns(moduleInfo: ModuleInfo, projectContext: ProjectContext, sdkDependency: SdkInfo?): KotlinBuiltIns + fun createBuiltIns( + moduleInfo: IdeaModuleInfo, + projectContext: ProjectContext, + resolverForProject: ResolverForProject, + sdkDependency: SdkInfo? + ): KotlinBuiltIns fun createResolverForModuleFactory( settings: PlatformAnalysisParameters, @@ -88,4 +95,4 @@ interface IdePlatformKindResolution { } val IdePlatformKind<*>.resolution: IdePlatformKindResolution - get() = IdePlatformKindResolution.getResolution(this) \ No newline at end of file + get() = IdePlatformKindResolution.getResolution(this) 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 be7bbd93739..28a99bcefb2 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 @@ -14,12 +14,14 @@ import com.intellij.util.PathUtil import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.analyzer.PlatformAnalysisParameters import org.jetbrains.kotlin.analyzer.ResolverForModuleFactory +import org.jetbrains.kotlin.analyzer.ResolverForProject import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentProvider +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.resolve.BuiltInsCacheKey @@ -53,7 +55,12 @@ class JsPlatformKindResolution : IdePlatformKindResolution { return BuiltInsCacheKey.DefaultBuiltInsKey } - override fun createBuiltIns(moduleInfo: ModuleInfo, projectContext: ProjectContext, sdkDependency: SdkInfo?): KotlinBuiltIns { + override fun createBuiltIns( + moduleInfo: IdeaModuleInfo, + projectContext: ProjectContext, + resolverForProject: ResolverForProject, + sdkDependency: SdkInfo? + ): KotlinBuiltIns { return DefaultBuiltIns.Instance } 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 4c0d94ca12e..7494a075a35 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 @@ -13,13 +13,16 @@ 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.ResolverForProject 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.project.IdeaModuleInfo import org.jetbrains.kotlin.idea.caches.project.LibraryInfo import org.jetbrains.kotlin.idea.caches.project.SdkInfo import org.jetbrains.kotlin.idea.caches.resolve.BuiltInsCacheKey +import org.jetbrains.kotlin.idea.caches.resolve.supportsAdditionalBuiltInsMembers import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.platform.impl.JvmIdePlatformKind import org.jetbrains.kotlin.platform.jvm.JvmPlatforms @@ -52,9 +55,23 @@ class JvmPlatformKindResolution : IdePlatformKindResolution { return if (sdkInfo != null) CacheKeyBySdk(sdkInfo.sdk) else BuiltInsCacheKey.DefaultBuiltInsKey } - override fun createBuiltIns(moduleInfo: ModuleInfo, projectContext: ProjectContext, sdkDependency: SdkInfo?): KotlinBuiltIns { + override fun createBuiltIns( + moduleInfo: IdeaModuleInfo, + projectContext: ProjectContext, + resolverForProject: ResolverForProject, + sdkDependency: SdkInfo? + ): KotlinBuiltIns { return if (sdkDependency != null) - JvmBuiltIns(projectContext.storageManager, JvmBuiltIns.Kind.FROM_CLASS_LOADER) + JvmBuiltIns(projectContext.storageManager, JvmBuiltIns.Kind.FROM_CLASS_LOADER).apply { + setPostponedSettingsComputation { + // SDK should be present, otherwise we wouldn't have created JvmBuiltIns in createBuiltIns + val sdkDescriptor = resolverForProject.descriptorForModule(sdkDependency) + + val isAdditionalBuiltInsFeaturesSupported = + moduleInfo.supportsAdditionalBuiltInsMembers(projectContext.project) + JvmBuiltIns.Settings(sdkDescriptor, isAdditionalBuiltInsFeaturesSupported) + } + } else DefaultBuiltIns.Instance } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IdeaResolverForProject.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IdeaResolverForProject.kt index 10e7d6de911..1aa494cd018 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IdeaResolverForProject.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IdeaResolverForProject.kt @@ -10,7 +10,6 @@ import com.intellij.openapi.util.ModificationTracker import org.jetbrains.kotlin.analyzer.* import org.jetbrains.kotlin.analyzer.common.CommonAnalysisParameters import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns import org.jetbrains.kotlin.caches.resolve.CompositeAnalyzerServices import org.jetbrains.kotlin.caches.resolve.CompositeResolverForModuleFactory import org.jetbrains.kotlin.caches.resolve.KotlinCacheService @@ -145,21 +144,12 @@ class IdeaResolverForProject( val cachedBuiltIns = cache[key] if (cachedBuiltIns != null) return@compute cachedBuiltIns - // Note #1: we can't use .getOrPut, because we have to put builtIns into map *before* initialization - // Note #2: it's OK to put not-initialized built-ins into public map, because access to [cache] is guarded by storageManager.lock - val newBuiltIns = module.platform.idePlatformKind.resolution.createBuiltIns(module, projectContextFromSdkResolver, sdk) - cache[key] = newBuiltIns - - if (newBuiltIns is JvmBuiltIns) { - // SDK should be present, otherwise we wouldn't have created JvmBuiltIns in createBuiltIns - val sdkDescriptor = resolverForSdk.descriptorForModule(sdk!!) - - val isAdditionalBuiltInsFeaturesSupported = module.supportsAdditionalBuiltInsMembers(projectContextFromSdkResolver.project) - - newBuiltIns.initialize(sdkDescriptor, isAdditionalBuiltInsFeaturesSupported) - } - - return@compute newBuiltIns + module.platform.idePlatformKind.resolution + .createBuiltIns(module, projectContextFromSdkResolver, resolverForSdk, sdk) + .also { + // TODO: MemoizedFunction should be used here instead, but for proper we also need a module (for LV settings) that is not contained in the key + cache[key] = it + } } } 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 cf4c833f7f5..7152af66d0b 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 @@ -14,6 +14,7 @@ import com.intellij.util.PathUtil import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.analyzer.PlatformAnalysisParameters import org.jetbrains.kotlin.analyzer.ResolverForModuleFactory +import org.jetbrains.kotlin.analyzer.ResolverForProject import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.functions.functionInterfacePackageFragmentProvider @@ -28,6 +29,7 @@ import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin import org.jetbrains.kotlin.descriptors.konan.KlibModuleOrigin 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.lazyClosure @@ -94,8 +96,12 @@ class NativePlatformKindResolution : IdePlatformKindResolution { override fun getKeyForBuiltIns(moduleInfo: ModuleInfo, sdkInfo: SdkInfo?): BuiltInsCacheKey = NativeBuiltInsCacheKey - override fun createBuiltIns(moduleInfo: ModuleInfo, projectContext: ProjectContext, sdkDependency: SdkInfo?) = - createKotlinNativeBuiltIns(moduleInfo, projectContext) + override fun createBuiltIns( + moduleInfo: IdeaModuleInfo, + projectContext: ProjectContext, + resolverForProject: ResolverForProject, + sdkDependency: SdkInfo? + ) = createKotlinNativeBuiltIns(moduleInfo, projectContext) private fun createKotlinNativeBuiltIns(moduleInfo: ModuleInfo, projectContext: ProjectContext): KotlinBuiltIns { val stdlibInfo = moduleInfo.findNativeStdlib() ?: return DefaultBuiltIns.Instance