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 capabilities: Map<ModuleDescriptor.Capability<*>, Any?>,
|
||||
private val dependencies: Iterable<ModuleInfo>,
|
||||
override val expectedBy: List<ModuleInfo>,
|
||||
private val modulesWhoseInternalsAreVisible: Collection<ModuleInfo>,
|
||||
private val dependOnOldBuiltIns: Boolean
|
||||
) : ModuleInfo {
|
||||
override fun dependencies() = listOf(this, *dependencies.toList().toTypedArray() )
|
||||
|
||||
override fun modulesWhoseInternalsAreVisible(): Collection<ModuleInfo> = 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<ModuleInfo>
|
||||
|
||||
fun moduleDescriptorForModuleInfo(moduleInfo: ModuleInfo): ModuleDescriptor
|
||||
|
||||
fun packageFragmentProviderForModuleInfo(moduleInfo: ModuleInfo): PackageFragmentProvider?
|
||||
val friendModuleInfos: List<ModuleInfo>
|
||||
val refinesModuleInfos: List<ModuleInfo>
|
||||
}
|
||||
|
||||
private fun createContainerToResolveCommonCode(
|
||||
|
||||
+14
@@ -40,4 +40,18 @@ class K2MetadataCompilerArguments : CommonCompilerArguments() {
|
||||
description = "Enable in JPS"
|
||||
)
|
||||
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.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<K2MetadataCompilerArguments>() {
|
||||
|
||||
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")) {
|
||||
|
||||
@@ -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<ModuleInfo> = mutableListOf<KlibModuleInfo>().apply {
|
||||
private val moduleInfosImpl: List<KlibModuleInfo> = mutableListOf<KlibModuleInfo>().apply {
|
||||
addAll(
|
||||
moduleDescriptorsForKotlinLibraries.map { (kotlinLibrary, moduleDescriptor) ->
|
||||
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(
|
||||
moduleInfo: ModuleInfo
|
||||
): PackageFragmentProvider? {
|
||||
|
||||
@@ -19,12 +19,12 @@ abstract class AbstractResolverForProject<M : ModuleInfo>(
|
||||
private val debugName: String,
|
||||
protected val projectContext: ProjectContext,
|
||||
modules: Collection<M>,
|
||||
private val fallbackModificationTracker: ModificationTracker? = null,
|
||||
protected val fallbackModificationTracker: ModificationTracker? = null,
|
||||
private val delegateResolver: ResolverForProject<M> = EmptyResolverForProject(),
|
||||
private val packageOracleFactory: PackageOracleFactory = PackageOracleFactory.OptimisticFactory
|
||||
) : ResolverForProject<M>() {
|
||||
|
||||
private class ModuleData(
|
||||
protected class ModuleData(
|
||||
val moduleDescriptor: ModuleDescriptorImpl,
|
||||
val modificationTracker: ModificationTracker?
|
||||
) {
|
||||
@@ -37,7 +37,7 @@ abstract class AbstractResolverForProject<M : ModuleInfo>(
|
||||
}
|
||||
|
||||
// Protected by ("projectContext.storageManager.lock")
|
||||
private val descriptorByModule = mutableMapOf<M, ModuleData>()
|
||||
protected val descriptorByModule = mutableMapOf<M, ModuleData>()
|
||||
|
||||
// Protected by ("projectContext.storageManager.lock")
|
||||
private val moduleInfoByDescriptor = mutableMapOf<ModuleDescriptorImpl, M>()
|
||||
|
||||
+11
-2
@@ -26,17 +26,26 @@ class ResolverForSingleModuleProject<M : ModuleInfo>(
|
||||
private val languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
|
||||
private val syntheticFiles: Collection<KtFile> = emptyList(),
|
||||
private val sdkDependency: M? = null,
|
||||
dependencyModules: Iterable<M> = emptyList()
|
||||
knownDependencyModuleDescriptors: Map<M, ModuleDescriptor> = emptyMap()
|
||||
) : AbstractResolverForProject<M>(
|
||||
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<M> = when (module) {
|
||||
this.module -> ModuleContent(module, syntheticFiles, searchScope)
|
||||
else -> ModuleContent(module, emptyList(), searchScope)
|
||||
|
||||
Reference in New Issue
Block a user