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:
+3
@@ -104,6 +104,9 @@ public class K2JVMCompilerArguments extends CommonCompilerArguments {
|
||||
@Argument(value = "Xadd-compiler-builtins", description = "Add definitions of built-in declarations to the compilation classpath (useful with -no-stdlib)")
|
||||
public boolean addCompilerBuiltIns;
|
||||
|
||||
@Argument(value = "Xload-builtins-from-dependencies", description = "Load definitions of built-in declarations from module dependencies, instead of from the compiler")
|
||||
public boolean loadBuiltInsFromDependencies;
|
||||
|
||||
@Argument(value = "Xinterface-compatibility", description = "Generate DefaultImpls classes for interfaces in JVM target bytecode version 1.8 for binary compatibility with 1.6")
|
||||
public boolean interfaceCompatibility;
|
||||
|
||||
|
||||
@@ -334,6 +334,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
configuration.put(CLIConfigurationKeys.REPORT_PERF, arguments.reportPerf)
|
||||
configuration.put(JVMConfigurationKeys.USE_SINGLE_MODULE, arguments.singleModule)
|
||||
configuration.put(JVMConfigurationKeys.ADD_BUILT_INS_FROM_COMPILER_TO_DEPENDENCIES, arguments.addCompilerBuiltIns)
|
||||
configuration.put(JVMConfigurationKeys.CREATE_BUILT_INS_FROM_MODULE_DEPENDENCIES, arguments.loadBuiltInsFromDependencies)
|
||||
|
||||
arguments.declarationsOutputPath?.let { configuration.put(JVMConfigurationKeys.DECLARATIONS_JSON_PATH, it) }
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
+26
-16
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,13 +23,14 @@ import org.jetbrains.kotlin.descriptors.impl.*
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.DescriptorFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.util.createFunctionType
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.storage.getValue
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.createDynamicType
|
||||
@@ -38,9 +39,11 @@ import org.jetbrains.kotlin.types.isDynamic
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
import java.util.*
|
||||
|
||||
class DynamicCallableDescriptors(builtIns: KotlinBuiltIns) {
|
||||
class DynamicCallableDescriptors(storageManager: StorageManager, builtIns: KotlinBuiltIns) {
|
||||
|
||||
val dynamicType = createDynamicType(builtIns)
|
||||
val dynamicType by storageManager.createLazyValue {
|
||||
createDynamicType(builtIns)
|
||||
}
|
||||
|
||||
fun createDynamicDescriptorScope(call: Call, owner: DeclarationDescriptor) = object : MemberScopeImpl() {
|
||||
override fun printScopeStructure(p: Printer) {
|
||||
|
||||
+2
@@ -10,6 +10,8 @@ where advanced options include:
|
||||
-Xdump-declarations-to <path> Path to JSON file to dump Java to Kotlin declaration mappings
|
||||
-Xsingle-module Combine modules for source files and binary dependencies into a single module
|
||||
-Xadd-compiler-builtins Add definitions of built-in declarations to the compilation classpath (useful with -no-stdlib)
|
||||
-Xload-builtins-from-dependencies
|
||||
Load definitions of built-in declarations from module dependencies, instead of from the compiler
|
||||
-Xinterface-compatibility Generate DefaultImpls classes for interfaces in JVM target bytecode version 1.8 for binary compatibility with 1.6
|
||||
-Xno-inline Disable method inlining
|
||||
-Xrepeat <count> Repeat compilation (for performance analysis)
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ class JvmBuiltInClassDescriptorFactory(
|
||||
) : ClassDescriptorFactory {
|
||||
private val cloneable by storageManager.createLazyValue {
|
||||
ClassDescriptorImpl(
|
||||
moduleDescriptor.getPackage(KOTLIN_FQ_NAME).fragments.filterIsInstance<BuiltInsPackageFragment>().single(),
|
||||
moduleDescriptor.getPackage(KOTLIN_FQ_NAME).fragments.filterIsInstance<BuiltInsPackageFragment>().first(),
|
||||
CLONEABLE_NAME, Modality.ABSTRACT, ClassKind.INTERFACE, listOf(moduleDescriptor.builtIns.anyType),
|
||||
SourceElement.NO_SOURCE
|
||||
).apply {
|
||||
|
||||
@@ -26,7 +26,10 @@ import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.storage.getValue
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
|
||||
class JvmBuiltIns(storageManager: StorageManager) : KotlinBuiltIns(storageManager) {
|
||||
class JvmBuiltIns @JvmOverloads constructor(
|
||||
storageManager: StorageManager,
|
||||
loadBuiltInsFromCurrentClassLoader: Boolean = true
|
||||
) : KotlinBuiltIns(storageManager) {
|
||||
// Module containing JDK classes or having them among dependencies
|
||||
private var ownerModuleDescriptor: ModuleDescriptor? = null
|
||||
private var isAdditionalBuiltInsFeatureSupported: Boolean = true
|
||||
@@ -46,7 +49,9 @@ class JvmBuiltIns(storageManager: StorageManager) : KotlinBuiltIns(storageManage
|
||||
}
|
||||
|
||||
init {
|
||||
createBuiltInsModule()
|
||||
if (loadBuiltInsFromCurrentClassLoader) {
|
||||
createBuiltInsModule()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getPlatformDependentDeclarationFilter(): PlatformDependentDeclarationFilter = settings
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.builtins;
|
||||
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -23,13 +24,16 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.functions.BuiltInFictitiousFunctionClassFactory;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.*;
|
||||
import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl;
|
||||
import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl;
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
||||
import org.jetbrains.kotlin.name.ClassId;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.scopes.ChainedMemberScope;
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
|
||||
import org.jetbrains.kotlin.serialization.deserialization.AdditionalClassPartsProvider;
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ClassDescriptorFactory;
|
||||
@@ -42,7 +46,6 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
|
||||
import static kotlin.collections.CollectionsKt.single;
|
||||
import static kotlin.collections.SetsKt.setOf;
|
||||
import static org.jetbrains.kotlin.builtins.PrimitiveType.*;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.getFqName;
|
||||
@@ -137,6 +140,22 @@ public abstract class KotlinBuiltIns {
|
||||
builtInsModule.initialize(packageFragmentProvider);
|
||||
builtInsModule.setDependencies(builtInsModule);
|
||||
}
|
||||
|
||||
public void setBuiltInsModule(@NotNull final ModuleDescriptorImpl module) {
|
||||
storageManager.compute(new Function0<Void>() {
|
||||
@Override
|
||||
public Void invoke() {
|
||||
if (builtInsModule != null) {
|
||||
throw new AssertionError(
|
||||
"Built-ins module is already set: " + builtInsModule + " (attempting to reset to " + module + ")"
|
||||
);
|
||||
}
|
||||
builtInsModule = module;
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected AdditionalClassPartsProvider getAdditionalClassPartsProvider() {
|
||||
return AdditionalClassPartsProvider.None.INSTANCE;
|
||||
@@ -153,14 +172,39 @@ public abstract class KotlinBuiltIns {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PackageFragmentDescriptor createPackage(
|
||||
private PackageFragmentDescriptor createPackage(
|
||||
@NotNull PackageFragmentProvider fragmentProvider,
|
||||
@NotNull Map<FqName, PackageFragmentDescriptor> packageNameToPackageFragment,
|
||||
@NotNull FqName packageFqName
|
||||
@NotNull final FqName packageFqName
|
||||
) {
|
||||
PackageFragmentDescriptor packageFragment = single(fragmentProvider.getPackageFragments(packageFqName));
|
||||
packageNameToPackageFragment.put(packageFqName, packageFragment);
|
||||
return packageFragment;
|
||||
final List<PackageFragmentDescriptor> packageFragments = fragmentProvider.getPackageFragments(packageFqName);
|
||||
|
||||
PackageFragmentDescriptor result =
|
||||
packageFragments.isEmpty()
|
||||
? new EmptyPackageFragmentDescriptor(builtInsModule, packageFqName)
|
||||
: packageFragments.size() == 1
|
||||
? packageFragments.iterator().next()
|
||||
: new PackageFragmentDescriptorImpl(builtInsModule, packageFqName) {
|
||||
@NotNull
|
||||
@Override
|
||||
public MemberScope getMemberScope() {
|
||||
return new ChainedMemberScope(
|
||||
"built-in package " + packageFqName,
|
||||
CollectionsKt.map(
|
||||
packageFragments,
|
||||
new Function1<PackageFragmentDescriptor, MemberScope>() {
|
||||
@Override
|
||||
public MemberScope invoke(PackageFragmentDescriptor descriptor) {
|
||||
return descriptor.getMemberScope();
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
packageNameToPackageFragment.put(packageFqName, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -354,7 +398,9 @@ public abstract class KotlinBuiltIns {
|
||||
@NotNull
|
||||
private static ClassDescriptor getBuiltInClassByName(@NotNull Name simpleName, @NotNull PackageFragmentDescriptor packageFragment) {
|
||||
ClassDescriptor classDescriptor = getBuiltInClassByNameNullable(simpleName, packageFragment);
|
||||
assert classDescriptor != null : "Built-in class " + simpleName + " is not found";
|
||||
if (classDescriptor == null) {
|
||||
throw new AssertionError("Built-in class " + packageFragment.getFqName().child(simpleName).asString() + " is not found");
|
||||
}
|
||||
return classDescriptor;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -80,7 +80,7 @@ class BuiltInFictitiousFunctionClassFactory(
|
||||
val packageFqName = classId.packageFqName
|
||||
val (kind, arity) = parseClassName(className, packageFqName) ?: return null
|
||||
|
||||
val containingPackageFragment = module.getPackage(packageFqName).fragments.filterIsInstance<BuiltInsPackageFragment>().single()
|
||||
val containingPackageFragment = module.getPackage(packageFqName).fragments.filterIsInstance<BuiltInsPackageFragment>().first()
|
||||
|
||||
return FunctionClassDescriptor(storageManager, containingPackageFragment, kind, arity)
|
||||
}
|
||||
|
||||
+1
-1
@@ -131,7 +131,7 @@ class FunctionClassDescriptor(
|
||||
// For KFunction{n}, add corresponding numbered Function{n} class, e.g. Function2 for KFunction2
|
||||
if (functionKind == Kind.KFunction) {
|
||||
val packageView = containingDeclaration.containingDeclaration.getPackage(BUILT_INS_PACKAGE_FQ_NAME)
|
||||
val kotlinPackageFragment = packageView.fragments.filterIsInstance<BuiltInsPackageFragment>().single()
|
||||
val kotlinPackageFragment = packageView.fragments.filterIsInstance<BuiltInsPackageFragment>().first()
|
||||
|
||||
add(kotlinPackageFragment, Kind.Function.numberedClassName(arity))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user