Fix exceptions caused by cyclic dependency between ModuleDescriptor and JvmBuiltIns
^KT-39105 Fixed ^KT-42001 Fixed See also EA-216604 and EA-211562
This commit is contained in:
@@ -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 {
|
||||
|
||||
+9
-11
@@ -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<Name> {
|
||||
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<ClassConstructorDescriptor> {
|
||||
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
|
||||
|
||||
+8
-1
@@ -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<IdeaModuleInfo>,
|
||||
sdkDependency: SdkInfo?
|
||||
): KotlinBuiltIns {
|
||||
return DefaultBuiltIns.Instance
|
||||
}
|
||||
|
||||
|
||||
+9
-2
@@ -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<IdeaModuleInfo>,
|
||||
sdkDependency: SdkInfo?
|
||||
): KotlinBuiltIns
|
||||
|
||||
fun createResolverForModuleFactory(
|
||||
settings: PlatformAnalysisParameters,
|
||||
@@ -88,4 +95,4 @@ interface IdePlatformKindResolution {
|
||||
}
|
||||
|
||||
val IdePlatformKind<*>.resolution: IdePlatformKindResolution
|
||||
get() = IdePlatformKindResolution.getResolution(this)
|
||||
get() = IdePlatformKindResolution.getResolution(this)
|
||||
|
||||
+8
-1
@@ -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<IdeaModuleInfo>,
|
||||
sdkDependency: SdkInfo?
|
||||
): KotlinBuiltIns {
|
||||
return DefaultBuiltIns.Instance
|
||||
}
|
||||
|
||||
|
||||
+19
-2
@@ -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<IdeaModuleInfo>,
|
||||
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
|
||||
}
|
||||
|
||||
+6
-16
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<IdeaModuleInfo>,
|
||||
sdkDependency: SdkInfo?
|
||||
) = createKotlinNativeBuiltIns(moduleInfo, projectContext)
|
||||
|
||||
private fun createKotlinNativeBuiltIns(moduleInfo: ModuleInfo, projectContext: ProjectContext): KotlinBuiltIns {
|
||||
val stdlibInfo = moduleInfo.findNativeStdlib() ?: return DefaultBuiltIns.Instance
|
||||
|
||||
Reference in New Issue
Block a user