Support injecting custom module into KotlinBuiltIns

Provide a command-line option to load built-ins from the module and its
dependencies instead of looking for them in kotlin-compiler.jar; built-ins must
be found this way, or an error will be reported (or, most likely at this
moment, an exception will be thrown).

Note that this does not affect whether built-ins (loaded from one place or the
other) are added to the _dependencies_ of the module, this is controlled by
another option. The option added in this commit only makes the KotlinBuiltIns
instance which is used via ModuleDescriptor throughout the compiler front-end
(and also injected in a bunch of places) a sort of "helper" which always goes
to that same module to find descriptors for built-in classes
This commit is contained in:
Alexander Udalov
2016-11-07 19:01:42 +03:00
parent 7898e2447d
commit 8c65379711
12 changed files with 121 additions and 32 deletions
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.config;
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl;
import org.jetbrains.kotlin.incremental.components.SourceRetentionAnnotationHandler;
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents;
import org.jetbrains.kotlin.modules.Module;
@@ -58,9 +59,23 @@ public class JVMConfigurationKeys {
public static final CompilerConfigurationKey<Boolean> USE_SINGLE_MODULE =
CompilerConfigurationKey.create("combine modules for source files and binary dependencies into a single module");
/**
* Controls whether the module depends on an additional "built-ins" module, which contains binary metadata of built-in definitions.
* By default, that metadata is loaded from kotlin-compiler.jar.
* However, it can be also loaded directly from the module, see {@link CREATE_BUILT_INS_FROM_MODULE_DEPENDENCIES}
*/
public static final CompilerConfigurationKey<Boolean> ADD_BUILT_INS_FROM_COMPILER_TO_DEPENDENCIES =
CompilerConfigurationKey.create("add built-ins from the compiler jar to the dependencies of the module being resolved");
/**
* Controls whether an instance of KotlinBuiltIns which is passed to {@link ModuleDescriptorImpl}'s constructor and ends up being used
* everywhere in the compiler front-end is loaded directly from the module (from its sources and/or its binaries), as opposed to
* from kotlin-compiler.jar
*/
public static final CompilerConfigurationKey<Boolean> CREATE_BUILT_INS_FROM_MODULE_DEPENDENCIES =
CompilerConfigurationKey.create("create built-ins from resources found in the module dependencies");
public static final CompilerConfigurationKey<JvmTarget> JVM_TARGET =
CompilerConfigurationKey.create("JVM bytecode target version");
@@ -128,5 +128,9 @@ fun createContainerForTopDownAnalyzerForJvm(
fun ComponentProvider.initJvmBuiltInsForTopDownAnalysis(module: ModuleDescriptor, languageVersionSettings: LanguageVersionSettings) {
get<JvmBuiltIns>().initialize(module, languageVersionSettings.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers))
get<JvmBuiltIns>().initialize(module, languageVersionSettings)
}
internal fun JvmBuiltIns.initialize(module: ModuleDescriptor, languageVersionSettings: LanguageVersionSettings) {
initialize(module, languageVersionSettings.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers))
}
@@ -40,6 +40,7 @@ import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDependenciesImpl
import org.jetbrains.kotlin.frontend.java.di.createContainerForTopDownAnalyzerForJvm
import org.jetbrains.kotlin.frontend.java.di.initJvmBuiltInsForTopDownAnalysis
import org.jetbrains.kotlin.frontend.java.di.initialize
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.load.java.lazy.ModuleClassResolver
import org.jetbrains.kotlin.load.java.structure.JavaClass
@@ -60,7 +61,6 @@ import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.utils.addToStdlib.check
import java.util.*
object TopDownAnalyzerFacadeForJVM {
@@ -99,7 +99,8 @@ object TopDownAnalyzerFacadeForJVM {
declarationProviderFactory: (StorageManager, Collection<KtFile>) -> DeclarationProviderFactory,
sourceModuleSearchScope: GlobalSearchScope = newModuleSearchScope(project, files)
): ComponentProvider {
val moduleContext = createModuleContext(project, configuration)
val createBuiltInsFromModule = configuration.getBoolean(JVMConfigurationKeys.CREATE_BUILT_INS_FROM_MODULE_DEPENDENCIES)
val moduleContext = createModuleContext(project, configuration, createBuiltInsFromModule)
val storageManager = moduleContext.storageManager
val module = moduleContext.module
@@ -116,6 +117,14 @@ object TopDownAnalyzerFacadeForJVM {
val languageVersionSettings =
configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, LanguageVersionSettingsImpl.DEFAULT)
val optionalBuiltInsModule =
if (configuration.getBoolean(JVMConfigurationKeys.ADD_BUILT_INS_FROM_COMPILER_TO_DEPENDENCIES)) {
if (createBuiltInsFromModule)
JvmBuiltIns(storageManager).apply { initialize(module, languageVersionSettings) }.builtInsModule
else module.builtIns.builtInsModule
}
else null
val dependencyModule = if (separateModules) {
val dependenciesContext = ContextForNewModule(
moduleContext, Name.special("<dependencies of ${configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)}>"),
@@ -132,12 +141,7 @@ object TopDownAnalyzerFacadeForJVM {
moduleClassResolver.compiledCodeResolver = dependenciesContainer.get<JavaDescriptorResolver>()
dependenciesContext.setDependencies(listOfNotNull(
dependenciesContext.module,
dependenciesContext.module.builtIns.builtInsModule.check {
configuration.getBoolean(JVMConfigurationKeys.ADD_BUILT_INS_FROM_COMPILER_TO_DEPENDENCIES)
}
))
dependenciesContext.setDependencies(listOfNotNull(dependenciesContext.module, optionalBuiltInsModule))
dependenciesContext.initializeModuleContents(CompositePackageFragmentProvider(listOf(
moduleClassResolver.compiledCodeResolver.packageFragmentProvider,
dependenciesContainer.get<JvmBuiltInsPackageFragmentProvider>()
@@ -181,9 +185,7 @@ object TopDownAnalyzerFacadeForJVM {
// TODO: remove dependencyModule from friends
module.setDependencies(ModuleDependenciesImpl(
listOfNotNull(module, dependencyModule, module.builtIns.builtInsModule.check {
configuration.getBoolean(JVMConfigurationKeys.ADD_BUILT_INS_FROM_COMPILER_TO_DEPENDENCIES)
}),
listOfNotNull(module, dependencyModule, optionalBuiltInsModule),
if (dependencyModule != null) setOf(dependencyModule) else emptySet()
))
module.initialize(CompositePackageFragmentProvider(
@@ -225,15 +227,23 @@ object TopDownAnalyzerFacadeForJVM {
}
fun createContextWithSealedModule(project: Project, configuration: CompilerConfiguration): MutableModuleContext =
createModuleContext(project, configuration).apply {
createModuleContext(project, configuration, false).apply {
setDependencies(module, module.builtIns.builtInsModule)
}
private fun createModuleContext(project: Project, configuration: CompilerConfiguration): MutableModuleContext {
private fun createModuleContext(
project: Project,
configuration: CompilerConfiguration,
createBuiltInsFromModule: Boolean
): MutableModuleContext {
val projectContext = ProjectContext(project)
val builtIns = JvmBuiltIns(projectContext.storageManager, !createBuiltInsFromModule)
return ContextForNewModule(
projectContext, Name.special("<${configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)}>"),
JvmBuiltIns(projectContext.storageManager)
)
projectContext, Name.special("<${configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)}>"), builtIns
).apply {
if (createBuiltInsFromModule) {
builtIns.builtInsModule = module
}
}
}
}