Load JVM built-ins in IDE from module dependencies
Fix built-ins for JVM platform and make them consistent with module's dependency on standard library. Changes don't affect non-JVM platforms. Previously all built-ins in IDE were loaded from classloader and were based on the same pre-serialized .kotlin_builtins files. This approach is generally not correct as built-in declarations differ for different platforms, but it had been working for a while without immediately observalble effects (see KT-33233 for more info). After changes in standard library JvmBuiltins started producing false errors (see KT-39728). To fix this, JVM built-ins in IDE now utilize the same technique as applied in CLI: using dependency on standard library as a module for built-ins instead of artificial module that considers only .kotlin_builtins. Change summary: - Provide JvmBuiltins with kind FROM_DEPENDENCIES for all modules with stdlib dependency in IDE - Add JvmBuiltinsPackageFragmentProvider to JVM-ish module resolvers (JVM and Composite with JVM platform) to support their use as built-ins module - Create KotlinBuiltInsMetadataIndex file index for tracking libraries containing .kotlin_builtins to support JvmBuiltinsPackageFragmentProvider - Create KotlinStdlibIndex file index for tracking kotlin-stdlib(-common), which looks for "Kotlin-Runtime-Component" manifest attribute - Add caching service to track LibraryInfo for kotlin-stdlib(-common) - Put LibraryInfo for kotlin-stdlib(-common) alongside SDKs due to the need to resolve that modules in BuiltInsCache - Update BuiltInsCache to separate JvmBuiltins by module's dependency on stdlib and JDK - Make platform of KotlinSDK common instead of JVM - Set built-ins module lazily in IDE ^KT-33233 Verification Pending
This commit is contained in:
@@ -125,8 +125,12 @@ fun StorageComponentContainer.configureJavaSpecificComponents(
|
||||
|
||||
useInstance(languageVersionSettings.getFlag(JvmAnalysisFlags.javaTypeEnhancementState))
|
||||
|
||||
if (useBuiltInsProvider) {
|
||||
useInstance((moduleContext.module.builtIns as JvmBuiltIns).customizer)
|
||||
val builtIns = moduleContext.module.builtIns
|
||||
if (useBuiltInsProvider && builtIns is JvmBuiltIns) {
|
||||
// TODO(dsavvinov): make sure that useBuiltInsProvider == true <=> builtIns is JvmBuiltIns
|
||||
// Currently, that's not the case at least in IDE unit-tests, because they do not set-up
|
||||
// dependency on SDK properly, see KT-43828
|
||||
useInstance(builtIns.customizer)
|
||||
useImpl<JvmBuiltInsPackageFragmentProvider>()
|
||||
}
|
||||
useImpl<OptionalAnnotationPackageFragmentProvider>()
|
||||
|
||||
+9
-6
@@ -17,8 +17,10 @@
|
||||
package org.jetbrains.kotlin.resolve.jvm
|
||||
|
||||
import org.jetbrains.kotlin.analyzer.*
|
||||
import org.jetbrains.kotlin.builtins.jvm.JvmBuiltInsPackageFragmentProvider
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.container.get
|
||||
import org.jetbrains.kotlin.container.tryGetService
|
||||
import org.jetbrains.kotlin.context.ModuleContext
|
||||
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
@@ -36,12 +38,14 @@ import org.jetbrains.kotlin.resolve.TargetEnvironment
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
|
||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
|
||||
class JvmPlatformParameters(
|
||||
val packagePartProviderFactory: (ModuleContent<*>) -> PackagePartProvider,
|
||||
val moduleByJavaClass: (JavaClass) -> ModuleInfo?,
|
||||
// params: referenced module info of target class, context module info of current resolver
|
||||
val resolverForReferencedModule: ((ModuleInfo, ModuleInfo) -> ResolverForModule?)? = null,
|
||||
val useBuiltinsProviderForModule: (ModuleInfo) -> Boolean
|
||||
) : PlatformAnalysisParameters
|
||||
|
||||
|
||||
@@ -111,17 +115,16 @@ class JvmResolverForModuleFactory(
|
||||
packagePartProvider,
|
||||
languageVersionSettings,
|
||||
sealedInheritorsProvider = sealedInheritorsProvider,
|
||||
useBuiltInsProvider = false // TODO: load built-ins from module dependencies in IDE
|
||||
useBuiltInsProvider = platformParameters.useBuiltinsProviderForModule(moduleInfo)
|
||||
)
|
||||
|
||||
val resolveSession = container.get<ResolveSession>()
|
||||
val javaDescriptorResolver = container.get<JavaDescriptorResolver>()
|
||||
|
||||
val providersForModule = arrayListOf(
|
||||
resolveSession.packageFragmentProvider,
|
||||
javaDescriptorResolver.packageFragmentProvider
|
||||
container.get<ResolveSession>().packageFragmentProvider,
|
||||
container.get<JavaDescriptorResolver>().packageFragmentProvider,
|
||||
)
|
||||
|
||||
providersForModule.addIfNotNull(container.tryGetService(JvmBuiltInsPackageFragmentProvider::class.java))
|
||||
|
||||
providersForModule +=
|
||||
PackageFragmentProviderExtension.getInstances(project)
|
||||
.mapNotNull {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.analyzer
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ModuleCapability
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
|
||||
val ModuleDescriptor.moduleInfo: ModuleInfo?
|
||||
@@ -23,3 +24,8 @@ internal fun collectAllExpectedByModules(entryModule: ModuleInfo): Set<ModuleInf
|
||||
|
||||
return expectedByModules
|
||||
}
|
||||
|
||||
val JDK_CAPABILITY = ModuleCapability<Boolean>("IsJdk")
|
||||
|
||||
val ModuleDescriptor.hasJdkCapability: Boolean
|
||||
get() = getCapability(JDK_CAPABILITY) == true
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm
|
||||
|
||||
import org.jetbrains.kotlin.analyzer.hasJdkCapability
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContextImpl
|
||||
@@ -115,6 +116,13 @@ class JvmIrCodegenFactory(private val phaseConfig: PhaseConfig) : CodegenFactory
|
||||
|
||||
val dependencies = psi2irContext.moduleDescriptor.allDependencyModules.map {
|
||||
val kotlinLibrary = (it.getCapability(KlibModuleOrigin.CAPABILITY) as? DeserializedKlibModuleOrigin)?.library
|
||||
if (it.hasJdkCapability) {
|
||||
// For IDE environment only, i.e. when compiling for debugger
|
||||
// Deserializer for built-ins module should exist because built-in types returned from SDK belong to that module,
|
||||
// but JDK's built-ins module might not be in current module's dependencies
|
||||
// We have to ensure that deserializer for built-ins module is created
|
||||
irLinker.deserializeIrModuleHeader(it.builtIns.builtInsModule, null)
|
||||
}
|
||||
irLinker.deserializeIrModuleHeader(it, kotlinLibrary)
|
||||
}
|
||||
val irProviders = listOf(irLinker)
|
||||
|
||||
+2
-2
@@ -20,7 +20,6 @@ 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
|
||||
@@ -44,7 +43,8 @@ fun createResolveSessionForFiles(
|
||||
TestModule(project, addBuiltIns)
|
||||
val platformParameters = JvmPlatformParameters(
|
||||
packagePartProviderFactory = { PackagePartProvider.Empty },
|
||||
moduleByJavaClass = { testModule }
|
||||
moduleByJavaClass = { testModule },
|
||||
useBuiltinsProviderForModule = { false }
|
||||
)
|
||||
|
||||
val resolverForProject = ResolverForSingleModuleProject(
|
||||
|
||||
+2
-1
@@ -88,7 +88,8 @@ class MultiModuleJavaAnalysisCustomTest : KtUsefulTestCase() {
|
||||
moduleByJavaClass = { javaClass ->
|
||||
val moduleName = javaClass.name.asString().toLowerCase().first().toString()
|
||||
modules.first { it._name == moduleName }
|
||||
}
|
||||
},
|
||||
useBuiltinsProviderForModule = { false }
|
||||
)
|
||||
|
||||
val resolverForProject = object : AbstractResolverForProject<TestModule>(
|
||||
|
||||
Reference in New Issue
Block a user