diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/analyzer/common/CommonResolverForModuleFactory.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/analyzer/common/CommonResolverForModuleFactory.kt index fa35d6d6241..920bcf89807 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/analyzer/common/CommonResolverForModuleFactory.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/analyzer/common/CommonResolverForModuleFactory.kt @@ -65,10 +65,14 @@ class CommonResolverForModuleFactory( override val name: Name, override val capabilities: Map, Any?>, private val dependencies: Iterable, + override val expectedBy: List, + private val modulesWhoseInternalsAreVisible: Collection, private val dependOnOldBuiltIns: Boolean ) : ModuleInfo { override fun dependencies() = listOf(this, *dependencies.toList().toTypedArray() ) + override fun modulesWhoseInternalsAreVisible(): Collection = modulesWhoseInternalsAreVisible + override fun dependencyOnBuiltIns(): ModuleInfo.DependencyOnBuiltIns = if (dependOnOldBuiltIns) ModuleInfo.DependencyOnBuiltIns.LAST else ModuleInfo.DependencyOnBuiltIns.NONE @@ -123,6 +127,8 @@ class CommonResolverForModuleFactory( moduleName, capabilities, dependenciesContainer?.moduleInfos?.toList().orEmpty(), + dependenciesContainer?.refinesModuleInfos.orEmpty(), + dependenciesContainer?.friendModuleInfos.orEmpty(), dependOnBuiltIns ) val project = files.firstOrNull()?.project ?: throw AssertionError("No files to analyze") @@ -150,7 +156,8 @@ class CommonResolverForModuleFactory( GlobalSearchScope.allScope(project), languageVersionSettings = multiplatformLanguageSettings, syntheticFiles = files, - dependencyModules = dependenciesContainer?.moduleInfos ?: emptyList() + knownDependencyModuleDescriptors = dependenciesContainer?.moduleInfos + ?.associateWith(dependenciesContainer::moduleDescriptorForModuleInfo).orEmpty() ) val moduleDescriptor = resolver.descriptorForModule(moduleInfo) @@ -167,7 +174,11 @@ class CommonResolverForModuleFactory( interface CommonDependenciesContainer { val moduleInfos: List + fun moduleDescriptorForModuleInfo(moduleInfo: ModuleInfo): ModuleDescriptor + fun packageFragmentProviderForModuleInfo(moduleInfo: ModuleInfo): PackageFragmentProvider? + val friendModuleInfos: List + val refinesModuleInfos: List } private fun createContainerToResolveCommonCode( diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2MetadataCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2MetadataCompilerArguments.kt index be7c3f83ac9..6770cf2daba 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2MetadataCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2MetadataCompilerArguments.kt @@ -40,4 +40,18 @@ class K2MetadataCompilerArguments : CommonCompilerArguments() { description = "Enable in JPS" ) var enabledInJps: Boolean by FreezableVar(false) + + @Argument( + value = "-Xfriend-paths", + valueDescription = "", + description = "Paths to output directories for friend modules (whose internals should be visible)" + ) + var friendPaths: Array? by FreezableVar(null) + + @Argument( + value = "-Xrefines-paths", + valueDescription = "", + description = "Paths to output directories for refined modules (whose expects this module can actualize)" + ) + var refinesPaths: Array? by FreezableVar(null) } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/config/K2MetadataConfigurationKeys.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/config/K2MetadataConfigurationKeys.kt new file mode 100644 index 00000000000..b0e98541238 --- /dev/null +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/config/K2MetadataConfigurationKeys.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.cli.jvm.config + +import org.jetbrains.kotlin.config.CompilerConfigurationKey + +object K2MetadataConfigurationKeys { + val FRIEND_PATHS = CompilerConfigurationKey.create>("friend module paths") + val REFINES_PATHS = CompilerConfigurationKey.create>("refined module paths") +} \ No newline at end of file diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/metadata/K2MetadataCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/metadata/K2MetadataCompiler.kt index 722e7ed5874..022cd8214f2 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/metadata/K2MetadataCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/metadata/K2MetadataCompiler.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.cli.common.messages.MessageUtil import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.cli.jvm.config.K2MetadataConfigurationKeys import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser import org.jetbrains.kotlin.codegen.CompilationException @@ -73,6 +74,10 @@ class K2MetadataCompiler : CLICompiler() { configuration.put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.allowKotlinPackage) + configuration.putIfNotNull(K2MetadataConfigurationKeys.FRIEND_PATHS, arguments.friendPaths?.toList()) + configuration.putIfNotNull(K2MetadataConfigurationKeys.REFINES_PATHS, arguments.refinesPaths?.toList()) + + val destination = arguments.destination if (destination != null) { if (destination.endsWith(".jar")) { diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/metadata/K2MetadataKlibSerializer.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/metadata/K2MetadataKlibSerializer.kt index c90a7eedb26..3dfe5094e16 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/metadata/K2MetadataKlibSerializer.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/metadata/K2MetadataKlibSerializer.kt @@ -5,7 +5,7 @@ package org.jetbrains.kotlin.cli.metadata -import org.jetbrains.kotlin.analyzer.ModuleInfo +import org.jetbrains.kotlin.analyzer.* import org.jetbrains.kotlin.analyzer.common.CommonDependenciesContainer import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataMonolithicSerializer @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot import org.jetbrains.kotlin.cli.jvm.config.JvmContentRoot +import org.jetbrains.kotlin.cli.jvm.config.K2MetadataConfigurationKeys import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.KotlinCompilerVersion @@ -112,6 +113,9 @@ private class KlibMetadataDependencyContainer( klibFiles.map { resolveSingleFileKlib(org.jetbrains.kotlin.konan.file.File(it.absolutePath)) } } + private val friendPaths = configuration.get(K2MetadataConfigurationKeys.FRIEND_PATHS).orEmpty().toSet() + private val refinesPaths = configuration.get(K2MetadataConfigurationKeys.REFINES_PATHS).orEmpty().toSet() + private val builtIns get() = DefaultBuiltIns.Instance @@ -147,7 +151,7 @@ private class KlibMetadataDependencyContainer( } } - override val moduleInfos: List = mutableListOf().apply { + private val moduleInfosImpl: List = mutableListOf().apply { addAll( moduleDescriptorsForKotlinLibraries.map { (kotlinLibrary, moduleDescriptor) -> KlibModuleInfo(moduleDescriptor.name, kotlinLibrary, this@apply) @@ -155,6 +159,28 @@ private class KlibMetadataDependencyContainer( ) } + override val moduleInfos: List get() = moduleInfosImpl + + override val friendModuleInfos: List = moduleInfosImpl.filter { + it.kotlinLibrary.libraryFile.absolutePath in friendPaths + } + + override val refinesModuleInfos: List = moduleInfosImpl.filter { + it.kotlinLibrary.libraryFile.absolutePath in refinesPaths + } + + override fun moduleDescriptorForModuleInfo(moduleInfo: ModuleInfo): ModuleDescriptor { + if (moduleInfo !in moduleInfos) + error("Unknown module info $moduleInfo") + moduleInfo as KlibModuleInfo + + // Ensure that the package fragment provider has been created and the module descriptor has been + // initialized with the package fragment provider: + packageFragmentProviderForModuleInfo(moduleInfo) + + return moduleDescriptorsForKotlinLibraries.getValue(moduleInfo.kotlinLibrary) + } + override fun packageFragmentProviderForModuleInfo( moduleInfo: ModuleInfo ): PackageFragmentProvider? { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AbstractResolverForProject.kt b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AbstractResolverForProject.kt index fb626c31908..93ed25ddf04 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AbstractResolverForProject.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AbstractResolverForProject.kt @@ -19,12 +19,12 @@ abstract class AbstractResolverForProject( private val debugName: String, protected val projectContext: ProjectContext, modules: Collection, - private val fallbackModificationTracker: ModificationTracker? = null, + protected val fallbackModificationTracker: ModificationTracker? = null, private val delegateResolver: ResolverForProject = EmptyResolverForProject(), private val packageOracleFactory: PackageOracleFactory = PackageOracleFactory.OptimisticFactory ) : ResolverForProject() { - private class ModuleData( + protected class ModuleData( val moduleDescriptor: ModuleDescriptorImpl, val modificationTracker: ModificationTracker? ) { @@ -37,7 +37,7 @@ abstract class AbstractResolverForProject( } // Protected by ("projectContext.storageManager.lock") - private val descriptorByModule = mutableMapOf() + protected val descriptorByModule = mutableMapOf() // Protected by ("projectContext.storageManager.lock") private val moduleInfoByDescriptor = mutableMapOf() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/ResolverForSingleModuleProject.kt b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/ResolverForSingleModuleProject.kt index ce680258fd8..e2c36115eb4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/ResolverForSingleModuleProject.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/ResolverForSingleModuleProject.kt @@ -26,17 +26,26 @@ class ResolverForSingleModuleProject( private val languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT, private val syntheticFiles: Collection = emptyList(), private val sdkDependency: M? = null, - dependencyModules: Iterable = emptyList() + knownDependencyModuleDescriptors: Map = emptyMap() ) : AbstractResolverForProject( debugName, projectContext, - listOf(module) + dependencyModules, + listOf(module) + knownDependencyModuleDescriptors.keys, null, EmptyResolverForProject(), PackageOracleFactory.OptimisticFactory ) { override fun sdkDependency(module: M): M? = sdkDependency + init { + knownDependencyModuleDescriptors.forEach { (module, descriptor) -> + descriptorByModule[module] = ModuleData( + descriptor as ModuleDescriptorImpl, + (module as? TrackableModuleInfo)?.createModificationTracker() ?: fallbackModificationTracker + ) + } + } + override fun modulesContent(module: M): ModuleContent = when (module) { this.module -> ModuleContent(module, syntheticFiles, searchScope) else -> ModuleContent(module, emptyList(), searchScope)