Detect K/N library kind if library is a ZIP file (native-specific part)

Issue #KT-26730 Fixed
This commit is contained in:
Dmitriy Dolovov
2018-09-11 10:48:36 +03:00
parent 0d0929922a
commit 324ec7aff8
5 changed files with 98 additions and 56 deletions
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.ide.konan
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiFileFactory
import com.intellij.psi.SingleRootFileViewProvider
@@ -25,6 +25,8 @@ import org.jetbrains.kotlin.idea.decompiler.textBuilder.LoggingErrorReporter
import org.jetbrains.kotlin.konan.file.File
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
@@ -98,16 +100,31 @@ private fun KonanLibrary.createPackageFragmentProvider(
internal object CachingIdeMetadataReaderImpl : MetadataReader {
override fun loadSerializedModule(libraryLayout: KonanLibraryLayout): KonanProtoBuf.LinkDataLibrary =
cache.getCachedModuleHeader(libraryLayout.moduleHeaderFile.virtualFile)
cache.getCachedModuleHeader(libraryLayout.getVirtualFile(libraryLayout.moduleHeaderFile))
override fun loadSerializedPackageFragment(
libraryLayout: KonanLibraryLayout,
packageFqName: String
): KonanProtoBuf.LinkDataPackageFragment =
cache.getCachedPackageFragment(libraryLayout.packageFragmentFile(packageFqName).virtualFile)
cache.getCachedPackageFragment(libraryLayout.getVirtualFile(libraryLayout.packageFragmentFile(packageFqName)))
private val File.virtualFile: VirtualFile
get() = LocalFileSystem.getInstance().refreshAndFindFileByPath(path) ?: error("File not found: $path")
private fun KonanLibraryLayout.getVirtualFile(file: File): VirtualFile {
val source = this.source
return when (source) {
is KonanLibraryFile -> asJarFileSystemFile(source.klibFile, file)
is KonanLibraryDir -> asLocalFile(file)
}
}
private fun asJarFileSystemFile(jarFile: File, localFile: File): VirtualFile {
val fullPath = jarFile.absolutePath + "!" + localFile.absolutePath
return StandardFileSystems.jar().findFileByPath(fullPath) ?: error("File not found: $fullPath")
}
private fun asLocalFile(localFile: File): VirtualFile {
val fullPath = localFile.absolutePath
return StandardFileSystems.local().findFileByPath(fullPath) ?: error("File not found: $fullPath")
}
private val cache
get() = KotlinNativeLoadingMetadataCache.getInstance()
@@ -9,6 +9,8 @@ import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.ApplicationComponent
import com.intellij.openapi.vfs.*
import com.intellij.util.containers.ContainerUtil.createConcurrentSoftValueMap
import org.jetbrains.kotlin.konan.library.KLIB_METADATA_FILE_EXTENSION
import org.jetbrains.kotlin.konan.library.KLIB_MODULE_METADATA_FILE_NAME
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
import org.jetbrains.kotlin.serialization.konan.parseModuleHeader
import org.jetbrains.kotlin.serialization.konan.parsePackageFragment
@@ -25,12 +27,12 @@ class KotlinNativeLoadingMetadataCache : ApplicationComponent {
private val moduleHeaderCache = createConcurrentSoftValueMap<VirtualFile, KonanProtoBuf.LinkDataLibrary>()
fun getCachedPackageFragment(virtualFile: VirtualFile): KonanProtoBuf.LinkDataPackageFragment =
packageFragmentCache.computeIfAbsent(virtualFile) {
packageFragmentCache.computeIfAbsent(virtualFile.surePackageMetadataFile) {
parsePackageFragment(virtualFile.contentsToByteArray(false))
}
fun getCachedModuleHeader(virtualFile: VirtualFile): KonanProtoBuf.LinkDataLibrary =
moduleHeaderCache.computeIfAbsent(virtualFile) {
moduleHeaderCache.computeIfAbsent(virtualFile.sureModuleHeaderFile) {
parseModuleHeader(virtualFile.contentsToByteArray(false))
}
@@ -45,7 +47,21 @@ class KotlinNativeLoadingMetadataCache : ApplicationComponent {
}
private fun invalidateCaches(virtualFile: VirtualFile) {
packageFragmentCache.remove(virtualFile)
moduleHeaderCache.remove(virtualFile)
when {
virtualFile.isPackageMetadataFile -> packageFragmentCache.remove(virtualFile)
virtualFile.isModuleHeaderFile -> moduleHeaderCache.remove(virtualFile)
}
}
private val VirtualFile.surePackageMetadataFile
get() = if (isPackageMetadataFile) this else error("Not a package metadata file: $this")
private val VirtualFile.isPackageMetadataFile
get() = extension == KLIB_METADATA_FILE_EXTENSION
private val VirtualFile.sureModuleHeaderFile
get() = if (isModuleHeaderFile) this else error("Not a module header file: $this")
private val VirtualFile.isModuleHeaderFile
get() = name == KLIB_MODULE_METADATA_FILE_NAME
}