Compare commits

...

7 Commits

Author SHA1 Message Date
Simon Ogorodnik
4e1f65a417 Support forward declarations for Native via hack-ing into built-ins 2018-09-13 22:15:17 +03:00
Simon Ogorodnik
ed25d6a948 Create Native specific LibraryInfo
This LibraryInfo contains KonanLibrary and provides correct
capabilities to ModuleDescriptor
2018-09-13 22:13:58 +03:00
Simon Ogorodnik
8a7ad0dba1 Add function to get typed capability from ModuleInfo 2018-09-13 22:12:09 +03:00
Simon Ogorodnik
faa9647555 Add factory function to create platform specific LibraryInfo's 2018-09-13 22:04:52 +03:00
Simon Ogorodnik
64ceaf7921 Do not throw exception on not-found serialized class from knm 2018-09-12 20:53:09 +03:00
Simon Ogorodnik
ee412e6fd0 Support free-form .knm package part names 2018-09-11 20:24:10 +03:00
Simon Ogorodnik
f0381ad4fa Support for split-packages in Kotlin Native
See JetBrains/kotlin-native#2034
2018-09-11 20:23:41 +03:00
19 changed files with 279 additions and 162 deletions

View File

@@ -502,4 +502,7 @@ private object DiagnoseUnknownModuleInfoReporter {
private fun errorInSpecialModuleInfoResolver(message: String): Nothing = throw AssertionError(message)
private fun otherError(message: String): Nothing = throw AssertionError(message)
}
}
@Suppress("UNCHECKED_CAST")
fun <T> ModuleInfo.getCapability(capability: ModuleDescriptor.Capability<T>) = capabilities[capability] as? T

View File

@@ -16,12 +16,15 @@
package org.jetbrains.kotlin.caches.resolve
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.roots.libraries.PersistentLibraryKind
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.analyzer.ResolverForModuleFactory
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.context.ProjectContext
import org.jetbrains.kotlin.extensions.ApplicationExtensionDescriptor
import org.jetbrains.kotlin.idea.caches.project.LibraryInfo
import org.jetbrains.kotlin.idea.caches.resolve.PlatformAnalysisSettings
import org.jetbrains.kotlin.platform.IdePlatformKind
@@ -36,6 +39,10 @@ interface IdePlatformKindResolution {
val libraryKind: PersistentLibraryKind<*>?
fun createLibraryInfo(project: Project, library: Library): List<LibraryInfo> {
return listOf(LibraryInfo(project, library))
}
companion object : ApplicationExtensionDescriptor<IdePlatformKindResolution>(
"org.jetbrains.kotlin.idePlatformKindResolution", IdePlatformKindResolution::class.java
) {

View File

@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.analyzer.CombinedModuleInfo
import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.analyzer.TrackableModuleInfo
import org.jetbrains.kotlin.caches.project.LibraryModuleInfo
import org.jetbrains.kotlin.caches.resolve.resolution
import org.jetbrains.kotlin.config.KotlinSourceRootType
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.idea.configuration.BuildSystemType
@@ -40,6 +41,7 @@ import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope
import org.jetbrains.kotlin.idea.util.isInSourceContentWithoutInjected
import org.jetbrains.kotlin.idea.util.rootManager
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.idePlatformKind
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.jvm.GlobalSearchScopeWithModuleSources
import org.jetbrains.kotlin.utils.addIfNotNull
@@ -86,7 +88,7 @@ private fun orderEntryToModuleInfo(project: Project, orderEntry: OrderEntry, for
}
is LibraryOrderEntry -> {
val library = orderEntry.library ?: return listOf()
listOfNotNull(LibraryInfo(project, library))
createLibraryInfo(project, library)
}
is JdkOrderEntry -> {
val sdk = orderEntry.jdk ?: return listOf()
@@ -98,6 +100,11 @@ private fun orderEntryToModuleInfo(project: Project, orderEntry: OrderEntry, for
}
}
fun createLibraryInfo(project: Project, library: Library): List<LibraryInfo> {
return getLibraryPlatform(project, library).idePlatformKind.resolution.createLibraryInfo(project, library)
}
private fun OrderEntry.acceptAsDependency(forProduction: Boolean): Boolean {
return this !is ExportableOrderEntry
|| !forProduction
@@ -256,7 +263,7 @@ private class ModuleTestSourceScope(module: Module) : ModuleSourceScope(module)
override fun toString() = "ModuleTestSourceScope($module)"
}
class LibraryInfo(val project: Project, val library: Library) : IdeaModuleInfo, LibraryModuleInfo, BinaryModuleInfo {
open class LibraryInfo(val project: Project, val library: Library) : IdeaModuleInfo, LibraryModuleInfo, BinaryModuleInfo {
override val moduleOrigin: ModuleOrigin
get() = ModuleOrigin.LIBRARY
@@ -271,11 +278,8 @@ class LibraryInfo(val project: Project, val library: Library) : IdeaModuleInfo,
val (libraries, sdks) = LibraryDependenciesCache.getInstance(project).getLibrariesAndSdksUsedWith(library)
sdks.mapTo(result) { SdkInfo(project, it) }
libraries.filter { it is LibraryEx && !it.isDisposed }.mapTo(result) {
LibraryInfo(
project,
it
)
libraries.filter { it is LibraryEx && !it.isDisposed }.flatMapTo(result) {
createLibraryInfo(project, it)
}
return result.toList()
@@ -285,7 +289,7 @@ class LibraryInfo(val project: Project, val library: Library) : IdeaModuleInfo,
get() = getLibraryPlatform(project, library)
override val sourcesModuleInfo: SourceForBinaryModuleInfo
get() = LibrarySourceInfo(project, library)
get() = LibrarySourceInfo(project, library, this)
override fun getLibraryRoots(): Collection<String> =
library.getFiles(OrderRootType.CLASSES).mapNotNull(PathUtil::getLocalPath)
@@ -300,7 +304,7 @@ class LibraryInfo(val project: Project, val library: Library) : IdeaModuleInfo,
override fun hashCode(): Int = 43 * library.hashCode()
}
data class LibrarySourceInfo(val project: Project, val library: Library) : IdeaModuleInfo, SourceForBinaryModuleInfo {
data class LibrarySourceInfo(val project: Project, val library: Library, override val binariesModuleInfo: BinaryModuleInfo) : IdeaModuleInfo, SourceForBinaryModuleInfo {
override val name: Name = Name.special("<sources for library ${library.name}>")
@@ -311,12 +315,9 @@ data class LibrarySourceInfo(val project: Project, val library: Library) : IdeaM
), project)
override fun modulesWhoseInternalsAreVisible(): Collection<ModuleInfo> {
return listOf(LibraryInfo(project, library))
return createLibraryInfo(project, library)
}
override val binariesModuleInfo: BinaryModuleInfo
get() = LibraryInfo(project, library)
override fun toString() = "LibrarySourceInfo(libraryName=${library.name})"
}

View File

@@ -217,7 +217,7 @@ private inline fun <T> collectInfosByVirtualFile(
}
projectFileIndex.getOrderEntriesForFile(virtualFile).forEach {
it.toIdeaModuleInfo(project, virtualFile, treatAsLibrarySource)?.let(onOccurrence)
it.toIdeaModuleInfo(project, virtualFile, treatAsLibrarySource).map(onOccurrence)
}
val isBinary = virtualFile.fileType.isKotlinBinary()
@@ -262,23 +262,23 @@ private fun OrderEntry.toIdeaModuleInfo(
project: Project,
virtualFile: VirtualFile,
treatAsLibrarySource: Boolean = false
): IdeaModuleInfo? {
if (this is ModuleOrderEntry) return null
if (!isValid) return null
): List<IdeaModuleInfo> {
if (this is ModuleOrderEntry) return emptyList()
if (!isValid) return emptyList()
when (this) {
is LibraryOrderEntry -> {
val library = library ?: return null
val library = library ?: return emptyList()
if (ProjectRootsUtil.isLibraryClassFile(project, virtualFile) && !treatAsLibrarySource) {
return LibraryInfo(project, library)
return createLibraryInfo(project, library)
} else if (ProjectRootsUtil.isLibraryFile(project, virtualFile) || treatAsLibrarySource) {
return LibrarySourceInfo(project, library)
return createLibraryInfo(project, library).map { it.sourcesModuleInfo }
}
}
is JdkOrderEntry -> {
return SdkInfo(project, jdk ?: return null)
return listOf(SdkInfo(project, jdk ?: return emptyList()))
}
else -> return null
else -> return emptyList()
}
return null
return emptyList()
}

View File

@@ -60,7 +60,7 @@ private fun collectModuleInfosFromIdeaModel(
return IdeaModelInfosCache(
moduleSourceInfos = ideaModules.flatMap(Module::correspondingModuleInfos),
libraryInfos = ideaLibraries.map { LibraryInfo(project, it) },
libraryInfos = ideaLibraries.flatMap { createLibraryInfo(project, it) },
sdkInfos = (sdksFromModulesDependencies + getAllProjectSdks()).filterNotNull().toSet().map { SdkInfo(project, it) }
)
}

View File

@@ -23,13 +23,13 @@ import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.idea.caches.project.LibraryInfo
import org.jetbrains.kotlin.idea.decompiler.textBuilder.LoggingErrorReporter
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.util.KonanFactories.DefaultPackageFragmentsFactory
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.KonanLibraryLayout
import org.jetbrains.kotlin.konan.library.KonanLibrarySource.KonanLibraryDir
import org.jetbrains.kotlin.konan.library.KonanLibrarySource.KonanLibraryFile
import org.jetbrains.kotlin.konan.library.MetadataReader
import org.jetbrains.kotlin.konan.library.createKonanLibrary
import org.jetbrains.kotlin.konan.util.KonanFactories.DefaultPackageFragmentsFactory
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
@@ -50,28 +50,7 @@ fun createFileStub(project: Project, text: String): PsiFileStub<*> {
fun createLoggingErrorReporter(log: Logger) = LoggingErrorReporter(log)
fun LibraryInfo.createPackageFragmentProviderForLibraryModule(
storageManager: StorageManager,
languageVersionSettings: LanguageVersionSettings,
moduleDescriptor: ModuleDescriptor
): List<PackageFragmentProvider> {
if (this.platform != KonanPlatform) return emptyList()
val libraryRoots = this.getLibraryRoots()
return libraryRoots.mapNotNull { libraryRoot -> File(libraryRoot).takeIf { it.exists } }.map { libraryRoot ->
val konanLibrary =
createKonanLibrary(
libraryRoot,
KOTLIN_NATIVE_CURRENT_ABI_VERSION,
metadataReader = CachingIdeMetadataReaderImpl
)
konanLibrary.createPackageFragmentProvider(storageManager, languageVersionSettings, moduleDescriptor)
}
}
private fun KonanLibrary.createPackageFragmentProvider(
fun KonanLibrary.createPackageFragmentProvider(
storageManager: StorageManager,
languageVersionSettings: LanguageVersionSettings,
moduleDescriptor: ModuleDescriptor
@@ -104,9 +83,10 @@ internal object CachingIdeMetadataReaderImpl : MetadataReader {
override fun loadSerializedPackageFragment(
libraryLayout: KonanLibraryLayout,
packageFqName: String
packageFqName: String,
partName: String
): KonanProtoBuf.LinkDataPackageFragment =
cache.getCachedPackageFragment(libraryLayout.getVirtualFile(libraryLayout.packageFragmentFile(packageFqName)))
cache.getCachedPackageFragment(libraryLayout.getVirtualFile(libraryLayout.packageFragmentFile(packageFqName, partName)))
private fun KonanLibraryLayout.getVirtualFile(file: File): VirtualFile {
val source = this.source

View File

@@ -5,31 +5,50 @@
package org.jetbrains.kotlin.ide.konan
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.OrderRootType
import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.roots.libraries.PersistentLibraryKind
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.util.PathUtil
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.caches.resolve.IdePlatformKindResolution
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.context.ProjectContext
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
import org.jetbrains.kotlin.descriptors.konan.DeserializedKonanModuleOrigin
import org.jetbrains.kotlin.ide.konan.analyzer.NativeAnalyzerFacade
import org.jetbrains.kotlin.idea.caches.project.LibraryInfo
import org.jetbrains.kotlin.idea.caches.project.getModuleInfosFromIdeaModel
import org.jetbrains.kotlin.idea.caches.resolve.PlatformAnalysisSettings
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.library.KLIB_FILE_EXTENSION
import org.jetbrains.kotlin.konan.library.KLIB_METADATA_FILE_EXTENSION
import org.jetbrains.kotlin.konan.library.KONAN_STDLIB_NAME
import org.jetbrains.kotlin.konan.library.createKonanLibrary
import org.jetbrains.kotlin.konan.util.KonanFactories.DefaultDeserializedDescriptorFactory
import org.jetbrains.kotlin.konan.library.*
import org.jetbrains.kotlin.resolve.ImplicitIntegerCoercion
import org.jetbrains.kotlin.resolve.konan.platform.KonanPlatform
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.konan.util.KonanFactories
class NativePlatformKindResolution : IdePlatformKindResolution {
override fun createLibraryInfo(project: Project, library: Library): List<LibraryInfo> {
return library.getFiles(OrderRootType.CLASSES)
.mapNotNull { file -> PathUtil.getLocalPath(file) }
.map { path -> File(path) }
.filter { file -> file.exists }
.map { file -> NativeLibraryInfo(project, library, file) }
}
override fun isLibraryFileForPlatform(virtualFile: VirtualFile): Boolean {
return if (virtualFile.isDirectory) {
virtualFile.findChild("linkdata")?.takeIf { it.isDirectory }
?.children?.any { it.extension == KLIB_METADATA_FILE_EXTENSION } == true
val dir = virtualFile.findChild("linkdata") ?: return false
// False means we hit .knm file
!VfsUtil.processFilesRecursively(dir) {
it.extension != KLIB_METADATA_FILE_EXTENSION
}
} else {
virtualFile.extension == KLIB_FILE_EXTENSION
}
@@ -73,13 +92,45 @@ private fun createKotlinNativeBuiltIns(projectContext: ProjectContext): KotlinBu
metadataReader = CachingIdeMetadataReaderImpl
)
val builtInsModule = DefaultDeserializedDescriptorFactory.createDescriptorAndNewBuiltIns(
library,
LanguageVersionSettingsImpl.DEFAULT,
projectContext.storageManager,
// This is to preserve "capabilities" from the original IntelliJ LibraryInfo:
customCapabilities = libraryInfo.capabilities
val libraryProto = library.moduleHeaderData
val moduleName = Name.special(libraryProto.moduleName)
val moduleOrigin = DeserializedKonanModuleOrigin(library)
val storageManager = projectContext.storageManager
val descriptorFactory = KonanFactories.DefaultDescriptorFactory
val builtInsModule = descriptorFactory.createDescriptorAndNewBuiltIns(
moduleName,
storageManager,
moduleOrigin,
libraryInfo.capabilities
)
val deserializationConfiguration = CompilerDeserializationConfiguration(LanguageVersionSettingsImpl.DEFAULT)
val provider = KonanFactories.DefaultPackageFragmentsFactory.createPackageFragmentProvider(
library,
null,
libraryProto.packageFragmentNameList,
storageManager,
builtInsModule,
deserializationConfiguration
)
builtInsModule.initialize(
CompositePackageFragmentProvider(
listOf(
provider,
KonanFactories.DefaultPackageFragmentsFactory.createForwardDeclarationHackPackagePartProvider(
storageManager,
builtInsModule
)
)
)
)
builtInsModule.setDependencies(listOf(builtInsModule))
return builtInsModule.builtIns
@@ -87,3 +138,27 @@ private fun createKotlinNativeBuiltIns(projectContext: ProjectContext): KotlinBu
return DefaultBuiltIns.Instance
}
class NativeLibraryInfo(project: Project, library: Library, private val root: File) : LibraryInfo(project, library) {
private val nativeLibrary = createKonanLibrary(
root,
KOTLIN_NATIVE_CURRENT_ABI_VERSION,
metadataReader = CachingIdeMetadataReaderImpl
)
override fun getLibraryRoots(): Collection<String> {
return listOf(root.absolutePath)
}
override val capabilities: Map<ModuleDescriptor.Capability<*>, Any?>
get() = super.capabilities +
mapOf(
ImplicitIntegerCoercion.MODULE_CAPABILITY to nativeLibrary.isInterop,
NATIVE_LIBRARY_CAPABILITY to nativeLibrary
)
companion object {
val NATIVE_LIBRARY_CAPABILITY = ModuleDescriptor.Capability<KonanLibrary>("KonanLibrary")
}
}

View File

@@ -13,8 +13,8 @@ import org.jetbrains.kotlin.context.ModuleContext
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.frontend.di.createContainerForLazyResolve
import org.jetbrains.kotlin.ide.konan.createPackageFragmentProviderForLibraryModule
import org.jetbrains.kotlin.idea.caches.project.LibraryInfo
import org.jetbrains.kotlin.ide.konan.NativeLibraryInfo
import org.jetbrains.kotlin.ide.konan.createPackageFragmentProvider
import org.jetbrains.kotlin.resolve.BindingTraceContext
import org.jetbrains.kotlin.resolve.TargetEnvironment
import org.jetbrains.kotlin.resolve.TargetPlatform
@@ -60,14 +60,16 @@ object NativeAnalyzerFacade : ResolverForModuleFactory() {
val moduleInfo = moduleContent.moduleInfo
if (moduleInfo is LibraryInfo) {
val libPackageFragmentProviders = moduleInfo.createPackageFragmentProviderForLibraryModule(
moduleContext.storageManager,
languageVersionSettings,
moduleDescriptor
)
fragmentProviders.addAll(libPackageFragmentProviders)
//TODO: Forward declarations?
val konanLibrary = moduleInfo.getCapability(NativeLibraryInfo.NATIVE_LIBRARY_CAPABILITY)
if (konanLibrary != null) {
val libPackageFragmentProvider =
konanLibrary.createPackageFragmentProvider(
moduleContext.storageManager,
languageVersionSettings,
moduleDescriptor
)
fragmentProviders.add(libPackageFragmentProvider)
}
return ResolverForModule(CompositePackageFragmentProvider(fragmentProviders), container)

View File

@@ -101,10 +101,10 @@ sealed class FileWithMetadata {
open class Compatible(
val proto: KonanProtoBuf.LinkDataPackageFragment,
serializerProtocol: SerializerExtensionProtocol
serializerProtocol: SerializerExtensionProtocol // TODO: Is it required?
) : FileWithMetadata() {
val nameResolver = NameResolverImpl(proto.stringTable, proto.nameTable)
val packageFqName = FqName(nameResolver.getPackageFqName(proto.`package`.getExtension(serializerProtocol.packageFqName)))
val packageFqName = FqName(proto.fqName)
open val classesToDecompile: List<ProtoBuf.Class> =
proto.classes.classesList.filter { proto ->

View File

@@ -44,7 +44,8 @@ interface KonanLibrary {
val dataFlowGraph: ByteArray?
val moduleHeaderData: KonanProtoBuf.LinkDataLibrary
fun packageMetadata(packageFqName: String): KonanProtoBuf.LinkDataPackageFragment
fun packageMetadataParts(fqName: String): Set<String>
fun packageMetadata(packageFqName: String, partName: String): KonanProtoBuf.LinkDataPackageFragment
}
val KonanLibrary.uniqueName

View File

@@ -35,11 +35,11 @@ interface KonanLibraryLayout {
val moduleHeaderFile get() = File(linkdataDir, KLIB_MODULE_METADATA_FILE_NAME)
val dataFlowGraphFile get() = File(linkdataDir, "module_data_flow_graph")
fun packageFragmentFile(packageFqName: String) =
File(
linkdataDir,
if (packageFqName == "") "root_package.$KLIB_METADATA_FILE_EXTENSION" else "package_$packageFqName.$KLIB_METADATA_FILE_EXTENSION"
)
fun packageFragmentsDir(packageFqName: String) =
File(linkdataDir, if (packageFqName == "") "root_package" else "package_$packageFqName")
fun packageFragmentFile(packageFqName: String, partName: String) =
File(packageFragmentsDir(packageFqName), "$partName$KLIB_METADATA_FILE_EXTENSION_WITH_DOT")
}
sealed class KonanLibrarySource {

View File

@@ -9,5 +9,9 @@ import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
interface MetadataReader {
fun loadSerializedModule(libraryLayout: KonanLibraryLayout): KonanProtoBuf.LinkDataLibrary
fun loadSerializedPackageFragment(libraryLayout: KonanLibraryLayout, packageFqName: String): KonanProtoBuf.LinkDataPackageFragment
fun loadSerializedPackageFragment(
libraryLayout: KonanLibraryLayout,
packageFqName: String,
partName: String
): KonanProtoBuf.LinkDataPackageFragment
}

View File

@@ -18,7 +18,10 @@ object DefaultMetadataReaderImpl : MetadataReader {
override fun loadSerializedPackageFragment(
libraryLayout: KonanLibraryLayout,
packageFqName: String
packageFqName: String,
partName: String
): KonanProtoBuf.LinkDataPackageFragment =
parsePackageFragment(libraryLayout.packageFragmentFile(packageFqName).readBytes())
parsePackageFragment(
libraryLayout.packageFragmentFile(packageFqName, partName).readBytes()
)
}

View File

@@ -6,10 +6,7 @@
package org.jetbrains.kotlin.konan.library.impl
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.library.KLIB_PROPERTY_ABI_VERSION
import org.jetbrains.kotlin.konan.library.KLIB_PROPERTY_LINKED_OPTS
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.MetadataReader
import org.jetbrains.kotlin.konan.library.*
import org.jetbrains.kotlin.konan.properties.Properties
import org.jetbrains.kotlin.konan.properties.loadProperties
import org.jetbrains.kotlin.konan.properties.propertyList
@@ -65,7 +62,25 @@ internal class KonanLibraryImpl(
override val moduleHeaderData: KonanProtoBuf.LinkDataLibrary by lazy { layout.inPlace { metadataReader.loadSerializedModule(it) } }
override fun packageMetadata(packageFqName: String) = layout.inPlace { metadataReader.loadSerializedPackageFragment(it, packageFqName) }
override fun packageMetadata(packageFqName: String, partName: String) =
layout.inPlace { metadataReader.loadSerializedPackageFragment(it, packageFqName, partName) }
override fun packageMetadataParts(fqName: String): Set<String> =
layout.inPlace { inPlaceLayout ->
val fileList =
inPlaceLayout.packageFragmentsDir(fqName)
.listFiles
.mapNotNull {
it.name
.substringBeforeLast(KLIB_METADATA_FILE_EXTENSION_WITH_DOT, missingDelimiterValue = "")
.takeIf { it.isNotEmpty() }
}
fileList.toSortedSet().also {
require(it.size == fileList.size) { "Duplicated names: ${fileList.groupingBy { it }.eachCount().filter { (_, count) -> count > 1 }}" }
}
}
override fun toString() = "$libraryName[default=$isDefault]"
}

View File

@@ -23,8 +23,9 @@ class KonanClassDataFinder(
val nameList = proto.classNameList
val index = nameList.indexOfFirst { nameResolver.getClassId(it) == classId }
if (index == -1)
error("Could not find serialized class $classId")
if (index == -1) {
return null
}
val foundClass = proto.getClasses(index) ?: error("Could not find data for serialized class $classId")

View File

@@ -5,9 +5,8 @@
package org.jetbrains.kotlin.serialization.konan
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.resolver.PackageAccessedHandler
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
@@ -37,4 +36,9 @@ interface KonanDeserializedPackageFragmentsFactory {
moduleDescriptor: ModuleDescriptor,
configuration: DeserializationConfiguration
): PackageFragmentProvider
fun createForwardDeclarationHackPackagePartProvider(
storageManager: StorageManager,
module: ModuleDescriptorImpl
): PackageFragmentProviderImpl
}

View File

@@ -24,7 +24,8 @@ class KonanPackageFragment(
private val library: KonanLibrary,
private val packageAccessedHandler: PackageAccessedHandler?,
storageManager: StorageManager,
module: ModuleDescriptor
module: ModuleDescriptor,
partName: String
) : DeserializedPackageFragment(fqName, storageManager, module) {
lateinit var components: DeserializationComponents
@@ -35,7 +36,7 @@ class KonanPackageFragment(
// The proto field is lazy so that we can load only needed
// packages from the library.
private val protoForNames: KonanProtoBuf.LinkDataPackageFragment by lazy { library.packageMetadata(fqName.asString()) }
private val protoForNames: KonanProtoBuf.LinkDataPackageFragment by lazy { library.packageMetadata(fqName.asString(), partName) }
val proto: KonanProtoBuf.LinkDataPackageFragment
get() = protoForNames.also { packageAccessedHandler?.markPackageAccessed(fqName) }

View File

@@ -6,9 +6,12 @@
package org.jetbrains.kotlin.serialization.konan.impl
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.exportForwardDeclarations
import org.jetbrains.kotlin.konan.library.isInterop
@@ -16,6 +19,7 @@ import org.jetbrains.kotlin.konan.library.packageFqName
import org.jetbrains.kotlin.konan.library.resolver.PackageAccessedHandler
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl
import org.jetbrains.kotlin.serialization.deserialization.*
@@ -23,7 +27,9 @@ import org.jetbrains.kotlin.serialization.konan.KonanDeserializedPackageFragment
import org.jetbrains.kotlin.serialization.konan.KonanPackageFragment
import org.jetbrains.kotlin.serialization.konan.KonanSerializerProtocol
import org.jetbrains.kotlin.serialization.konan.NullFlexibleTypeDeserializer
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.storage.getValue
import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
@@ -36,8 +42,12 @@ internal object KonanDeserializedPackageFragmentsFactoryImpl : KonanDeserialized
moduleDescriptor: ModuleDescriptor,
packageAccessedHandler: PackageAccessedHandler?,
storageManager: StorageManager
) = packageFragmentNames.map {
KonanPackageFragment(FqName(it), library, packageAccessedHandler, storageManager, moduleDescriptor)
) = packageFragmentNames.flatMap {
val fqName = FqName(it)
val parts = library.packageMetadataParts(it)
parts.map { partName ->
KonanPackageFragment(fqName, library, packageAccessedHandler, storageManager, moduleDescriptor, partName)
}
}
override fun createSyntheticPackageFragments(
@@ -118,6 +128,29 @@ internal object KonanDeserializedPackageFragmentsFactoryImpl : KonanDeserialized
return provider
}
override fun createForwardDeclarationHackPackagePartProvider(
storageManager: StorageManager,
module: ModuleDescriptorImpl
): PackageFragmentProviderImpl {
fun createPackage(fqName: FqName, supertypeName: String, classKind: ClassKind) =
ForwardDeclarationsPackageFragmentDescriptor(
storageManager,
module,
fqName,
Name.identifier(supertypeName),
classKind
)
val packageFragmentProvider = PackageFragmentProviderImpl(
listOf(
createPackage(ForwardDeclarationsFqNames.cNamesStructs, "COpaque", ClassKind.CLASS),
createPackage(ForwardDeclarationsFqNames.objCNamesClasses, "ObjCObjectBase", ClassKind.CLASS),
createPackage(ForwardDeclarationsFqNames.objCNamesProtocols, "ObjCObject", ClassKind.INTERFACE)
)
)
return packageFragmentProvider
}
}
/**
@@ -189,3 +222,52 @@ class ClassifierAliasingPackageFragmentDescriptor(
override fun getMemberScope(): MemberScope = memberScope
}
/**
* Package fragment which creates descriptors for forward declarations on demand.
*/
private class ForwardDeclarationsPackageFragmentDescriptor(
storageManager: StorageManager,
module: ModuleDescriptor,
fqName: FqName,
supertypeName: Name,
classKind: ClassKind
) : PackageFragmentDescriptorImpl(module, fqName) {
private val memberScope = object : MemberScopeImpl() {
private val declarations = storageManager.createMemoizedFunction(this::createDeclaration)
private val supertype by storageManager.createLazyValue {
val descriptor = builtIns.builtInsModule.getPackage(ForwardDeclarationsFqNames.packageName)
.memberScope
.getContributedClassifier(supertypeName, NoLookupLocation.FROM_BACKEND) as ClassDescriptor
descriptor.defaultType
}
private fun createDeclaration(name: Name): ClassDescriptor {
return ClassDescriptorImpl(
this@ForwardDeclarationsPackageFragmentDescriptor,
name,
Modality.FINAL,
classKind,
listOf(supertype),
SourceElement.NO_SOURCE,
false,
LockBasedStorageManager.NO_LOCKS
).apply {
this.initialize(MemberScope.Empty, emptySet(), null)
}
}
override fun getContributedClassifier(name: Name, location: LookupLocation) = declarations(name)
override fun printScopeStructure(p: Printer) {
p.println(this::class.java.simpleName, "{}")
}
}
override fun getMemberScope(): MemberScope = memberScope
}

View File

@@ -85,22 +85,8 @@ class KonanResolvedModuleDescriptorsFactoryImpl(
val name = Name.special("<forward declarations>")
val module = createDescriptorOptionalBuiltsIns(name, storageManager, builtIns, SyntheticModulesOrigin)
fun createPackage(fqName: FqName, supertypeName: String, classKind: ClassKind) =
ForwardDeclarationsPackageFragmentDescriptor(
storageManager,
module,
fqName,
Name.identifier(supertypeName),
classKind
)
val packageFragmentProvider = PackageFragmentProviderImpl(
listOf(
createPackage(ForwardDeclarationsFqNames.cNamesStructs, "COpaque", ClassKind.CLASS),
createPackage(ForwardDeclarationsFqNames.objCNamesClasses, "ObjCObjectBase", ClassKind.CLASS),
createPackage(ForwardDeclarationsFqNames.objCNamesProtocols, "ObjCObject", ClassKind.INTERFACE)
)
)
val packageFragmentProvider =
moduleDescriptorFactory.packageFragmentsFactory.createForwardDeclarationHackPackagePartProvider(storageManager, module)
module.initialize(packageFragmentProvider)
module.setDependencies(module)
@@ -144,54 +130,6 @@ class KonanResolvedModuleDescriptorsFactoryImpl(
)
}
/**
* Package fragment which creates descriptors for forward declarations on demand.
*/
private class ForwardDeclarationsPackageFragmentDescriptor(
storageManager: StorageManager,
module: ModuleDescriptor,
fqName: FqName,
supertypeName: Name,
classKind: ClassKind
) : PackageFragmentDescriptorImpl(module, fqName) {
private val memberScope = object : MemberScopeImpl() {
private val declarations = storageManager.createMemoizedFunction(this::createDeclaration)
private val supertype by storageManager.createLazyValue {
val descriptor = builtIns.builtInsModule.getPackage(ForwardDeclarationsFqNames.packageName)
.memberScope
.getContributedClassifier(supertypeName, NoLookupLocation.FROM_BACKEND) as ClassDescriptor
descriptor.defaultType
}
private fun createDeclaration(name: Name): ClassDescriptor {
return ClassDescriptorImpl(
this@ForwardDeclarationsPackageFragmentDescriptor,
name,
Modality.FINAL,
classKind,
listOf(supertype),
SourceElement.NO_SOURCE,
false,
LockBasedStorageManager.NO_LOCKS
).apply {
this.initialize(MemberScope.Empty, emptySet(), null)
}
}
override fun getContributedClassifier(name: Name, location: LookupLocation) = declarations(name)
override fun printScopeStructure(p: Printer) {
p.println(this::class.java.simpleName, "{}")
}
}
override fun getMemberScope(): MemberScope = memberScope
}
// FIXME(ddol): decouple and move interop-specific logic back to Kotlin/Native.
internal object ForwardDeclarationsFqNames {