Support friend internal visibility in K2Metadata compiler (KT-37264)
Add and handle the friend paths and refines paths compiler arguments; Reuse klib dependency module descriptors in the resolver for project; Issue #KT-37264
This commit is contained in:
+12
-1
@@ -65,10 +65,14 @@ class CommonResolverForModuleFactory(
|
|||||||
override val name: Name,
|
override val name: Name,
|
||||||
override val capabilities: Map<ModuleDescriptor.Capability<*>, Any?>,
|
override val capabilities: Map<ModuleDescriptor.Capability<*>, Any?>,
|
||||||
private val dependencies: Iterable<ModuleInfo>,
|
private val dependencies: Iterable<ModuleInfo>,
|
||||||
|
override val expectedBy: List<ModuleInfo>,
|
||||||
|
private val modulesWhoseInternalsAreVisible: Collection<ModuleInfo>,
|
||||||
private val dependOnOldBuiltIns: Boolean
|
private val dependOnOldBuiltIns: Boolean
|
||||||
) : ModuleInfo {
|
) : ModuleInfo {
|
||||||
override fun dependencies() = listOf(this, *dependencies.toList().toTypedArray() )
|
override fun dependencies() = listOf(this, *dependencies.toList().toTypedArray() )
|
||||||
|
|
||||||
|
override fun modulesWhoseInternalsAreVisible(): Collection<ModuleInfo> = modulesWhoseInternalsAreVisible
|
||||||
|
|
||||||
override fun dependencyOnBuiltIns(): ModuleInfo.DependencyOnBuiltIns =
|
override fun dependencyOnBuiltIns(): ModuleInfo.DependencyOnBuiltIns =
|
||||||
if (dependOnOldBuiltIns) ModuleInfo.DependencyOnBuiltIns.LAST else ModuleInfo.DependencyOnBuiltIns.NONE
|
if (dependOnOldBuiltIns) ModuleInfo.DependencyOnBuiltIns.LAST else ModuleInfo.DependencyOnBuiltIns.NONE
|
||||||
|
|
||||||
@@ -123,6 +127,8 @@ class CommonResolverForModuleFactory(
|
|||||||
moduleName,
|
moduleName,
|
||||||
capabilities,
|
capabilities,
|
||||||
dependenciesContainer?.moduleInfos?.toList().orEmpty(),
|
dependenciesContainer?.moduleInfos?.toList().orEmpty(),
|
||||||
|
dependenciesContainer?.refinesModuleInfos.orEmpty(),
|
||||||
|
dependenciesContainer?.friendModuleInfos.orEmpty(),
|
||||||
dependOnBuiltIns
|
dependOnBuiltIns
|
||||||
)
|
)
|
||||||
val project = files.firstOrNull()?.project ?: throw AssertionError("No files to analyze")
|
val project = files.firstOrNull()?.project ?: throw AssertionError("No files to analyze")
|
||||||
@@ -150,7 +156,8 @@ class CommonResolverForModuleFactory(
|
|||||||
GlobalSearchScope.allScope(project),
|
GlobalSearchScope.allScope(project),
|
||||||
languageVersionSettings = multiplatformLanguageSettings,
|
languageVersionSettings = multiplatformLanguageSettings,
|
||||||
syntheticFiles = files,
|
syntheticFiles = files,
|
||||||
dependencyModules = dependenciesContainer?.moduleInfos ?: emptyList()
|
knownDependencyModuleDescriptors = dependenciesContainer?.moduleInfos
|
||||||
|
?.associateWith(dependenciesContainer::moduleDescriptorForModuleInfo).orEmpty()
|
||||||
)
|
)
|
||||||
|
|
||||||
val moduleDescriptor = resolver.descriptorForModule(moduleInfo)
|
val moduleDescriptor = resolver.descriptorForModule(moduleInfo)
|
||||||
@@ -167,7 +174,11 @@ class CommonResolverForModuleFactory(
|
|||||||
interface CommonDependenciesContainer {
|
interface CommonDependenciesContainer {
|
||||||
val moduleInfos: List<ModuleInfo>
|
val moduleInfos: List<ModuleInfo>
|
||||||
|
|
||||||
|
fun moduleDescriptorForModuleInfo(moduleInfo: ModuleInfo): ModuleDescriptor
|
||||||
|
|
||||||
fun packageFragmentProviderForModuleInfo(moduleInfo: ModuleInfo): PackageFragmentProvider?
|
fun packageFragmentProviderForModuleInfo(moduleInfo: ModuleInfo): PackageFragmentProvider?
|
||||||
|
val friendModuleInfos: List<ModuleInfo>
|
||||||
|
val refinesModuleInfos: List<ModuleInfo>
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createContainerToResolveCommonCode(
|
private fun createContainerToResolveCommonCode(
|
||||||
|
|||||||
+14
@@ -40,4 +40,18 @@ class K2MetadataCompilerArguments : CommonCompilerArguments() {
|
|||||||
description = "Enable in JPS"
|
description = "Enable in JPS"
|
||||||
)
|
)
|
||||||
var enabledInJps: Boolean by FreezableVar(false)
|
var enabledInJps: Boolean by FreezableVar(false)
|
||||||
|
|
||||||
|
@Argument(
|
||||||
|
value = "-Xfriend-paths",
|
||||||
|
valueDescription = "<path>",
|
||||||
|
description = "Paths to output directories for friend modules (whose internals should be visible)"
|
||||||
|
)
|
||||||
|
var friendPaths: Array<String>? by FreezableVar(null)
|
||||||
|
|
||||||
|
@Argument(
|
||||||
|
value = "-Xrefines-paths",
|
||||||
|
valueDescription = "<path>",
|
||||||
|
description = "Paths to output directories for refined modules (whose expects this module can actualize)"
|
||||||
|
)
|
||||||
|
var refinesPaths: Array<String>? by FreezableVar(null)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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<List<String>>("friend module paths")
|
||||||
|
val REFINES_PATHS = CompilerConfigurationKey.create<List<String>>("refined module paths")
|
||||||
|
}
|
||||||
@@ -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.common.messages.OutputMessageUtil
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
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.config.addJvmClasspathRoots
|
||||||
import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser
|
import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser
|
||||||
import org.jetbrains.kotlin.codegen.CompilationException
|
import org.jetbrains.kotlin.codegen.CompilationException
|
||||||
@@ -73,6 +74,10 @@ class K2MetadataCompiler : CLICompiler<K2MetadataCompilerArguments>() {
|
|||||||
|
|
||||||
configuration.put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.allowKotlinPackage)
|
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
|
val destination = arguments.destination
|
||||||
if (destination != null) {
|
if (destination != null) {
|
||||||
if (destination.endsWith(".jar")) {
|
if (destination.endsWith(".jar")) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.cli.metadata
|
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.CommonDependenciesContainer
|
||||||
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
|
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataMonolithicSerializer
|
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.compiler.KotlinCoreEnvironment
|
||||||
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
|
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
|
||||||
import org.jetbrains.kotlin.cli.jvm.config.JvmContentRoot
|
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.CommonConfigurationKeys
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.config.KotlinCompilerVersion
|
import org.jetbrains.kotlin.config.KotlinCompilerVersion
|
||||||
@@ -112,6 +113,9 @@ private class KlibMetadataDependencyContainer(
|
|||||||
klibFiles.map { resolveSingleFileKlib(org.jetbrains.kotlin.konan.file.File(it.absolutePath)) }
|
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
|
private val builtIns
|
||||||
get() = DefaultBuiltIns.Instance
|
get() = DefaultBuiltIns.Instance
|
||||||
|
|
||||||
@@ -147,7 +151,7 @@ private class KlibMetadataDependencyContainer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override val moduleInfos: List<ModuleInfo> = mutableListOf<KlibModuleInfo>().apply {
|
private val moduleInfosImpl: List<KlibModuleInfo> = mutableListOf<KlibModuleInfo>().apply {
|
||||||
addAll(
|
addAll(
|
||||||
moduleDescriptorsForKotlinLibraries.map { (kotlinLibrary, moduleDescriptor) ->
|
moduleDescriptorsForKotlinLibraries.map { (kotlinLibrary, moduleDescriptor) ->
|
||||||
KlibModuleInfo(moduleDescriptor.name, kotlinLibrary, this@apply)
|
KlibModuleInfo(moduleDescriptor.name, kotlinLibrary, this@apply)
|
||||||
@@ -155,6 +159,28 @@ private class KlibMetadataDependencyContainer(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val moduleInfos: List<ModuleInfo> get() = moduleInfosImpl
|
||||||
|
|
||||||
|
override val friendModuleInfos: List<ModuleInfo> = moduleInfosImpl.filter {
|
||||||
|
it.kotlinLibrary.libraryFile.absolutePath in friendPaths
|
||||||
|
}
|
||||||
|
|
||||||
|
override val refinesModuleInfos: List<ModuleInfo> = 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(
|
override fun packageFragmentProviderForModuleInfo(
|
||||||
moduleInfo: ModuleInfo
|
moduleInfo: ModuleInfo
|
||||||
): PackageFragmentProvider? {
|
): PackageFragmentProvider? {
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ abstract class AbstractResolverForProject<M : ModuleInfo>(
|
|||||||
private val debugName: String,
|
private val debugName: String,
|
||||||
protected val projectContext: ProjectContext,
|
protected val projectContext: ProjectContext,
|
||||||
modules: Collection<M>,
|
modules: Collection<M>,
|
||||||
private val fallbackModificationTracker: ModificationTracker? = null,
|
protected val fallbackModificationTracker: ModificationTracker? = null,
|
||||||
private val delegateResolver: ResolverForProject<M> = EmptyResolverForProject(),
|
private val delegateResolver: ResolverForProject<M> = EmptyResolverForProject(),
|
||||||
private val packageOracleFactory: PackageOracleFactory = PackageOracleFactory.OptimisticFactory
|
private val packageOracleFactory: PackageOracleFactory = PackageOracleFactory.OptimisticFactory
|
||||||
) : ResolverForProject<M>() {
|
) : ResolverForProject<M>() {
|
||||||
|
|
||||||
private class ModuleData(
|
protected class ModuleData(
|
||||||
val moduleDescriptor: ModuleDescriptorImpl,
|
val moduleDescriptor: ModuleDescriptorImpl,
|
||||||
val modificationTracker: ModificationTracker?
|
val modificationTracker: ModificationTracker?
|
||||||
) {
|
) {
|
||||||
@@ -37,7 +37,7 @@ abstract class AbstractResolverForProject<M : ModuleInfo>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Protected by ("projectContext.storageManager.lock")
|
// Protected by ("projectContext.storageManager.lock")
|
||||||
private val descriptorByModule = mutableMapOf<M, ModuleData>()
|
protected val descriptorByModule = mutableMapOf<M, ModuleData>()
|
||||||
|
|
||||||
// Protected by ("projectContext.storageManager.lock")
|
// Protected by ("projectContext.storageManager.lock")
|
||||||
private val moduleInfoByDescriptor = mutableMapOf<ModuleDescriptorImpl, M>()
|
private val moduleInfoByDescriptor = mutableMapOf<ModuleDescriptorImpl, M>()
|
||||||
|
|||||||
+11
-2
@@ -26,17 +26,26 @@ class ResolverForSingleModuleProject<M : ModuleInfo>(
|
|||||||
private val languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
|
private val languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
|
||||||
private val syntheticFiles: Collection<KtFile> = emptyList(),
|
private val syntheticFiles: Collection<KtFile> = emptyList(),
|
||||||
private val sdkDependency: M? = null,
|
private val sdkDependency: M? = null,
|
||||||
dependencyModules: Iterable<M> = emptyList()
|
knownDependencyModuleDescriptors: Map<M, ModuleDescriptor> = emptyMap()
|
||||||
) : AbstractResolverForProject<M>(
|
) : AbstractResolverForProject<M>(
|
||||||
debugName,
|
debugName,
|
||||||
projectContext,
|
projectContext,
|
||||||
listOf(module) + dependencyModules,
|
listOf(module) + knownDependencyModuleDescriptors.keys,
|
||||||
null,
|
null,
|
||||||
EmptyResolverForProject(),
|
EmptyResolverForProject(),
|
||||||
PackageOracleFactory.OptimisticFactory
|
PackageOracleFactory.OptimisticFactory
|
||||||
) {
|
) {
|
||||||
override fun sdkDependency(module: M): M? = sdkDependency
|
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<M> = when (module) {
|
override fun modulesContent(module: M): ModuleContent<M> = when (module) {
|
||||||
this.module -> ModuleContent(module, syntheticFiles, searchScope)
|
this.module -> ModuleContent(module, syntheticFiles, searchScope)
|
||||||
else -> ModuleContent(module, emptyList(), searchScope)
|
else -> ModuleContent(module, emptyList(), searchScope)
|
||||||
|
|||||||
Reference in New Issue
Block a user