Fast check of Kotlin/Native KLIBs by virtual files

This commit is contained in:
Dmitriy Dolovov
2019-12-24 17:29:25 +07:00
parent 98e9642a1e
commit 59e84e826b
3 changed files with 28 additions and 28 deletions
@@ -19,12 +19,17 @@ import org.jetbrains.kotlin.ide.konan.decompiler.KotlinNativeLoadingMetadataCach
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.idea.decompiler.textBuilder.LoggingErrorReporter
import org.jetbrains.kotlin.library.KLIB_FILE_EXTENSION
import org.jetbrains.kotlin.library.KLIB_MANIFEST_FILE_NAME
import org.jetbrains.kotlin.library.KLIB_PROPERTY_UNIQUE_NAME
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.impl.KotlinLibraryImpl
import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf
import org.jetbrains.kotlin.library.metadata.PackageAccessHandler
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
import java.io.IOException
import java.util.*
import org.jetbrains.kotlin.konan.file.File as KFile
fun createFileStub(project: Project, text: String): PsiFileStub<*> {
@@ -76,3 +81,21 @@ internal object CachingIdeKonanLibraryMetadataLoader : PackageAccessHandler {
get() = (this as KotlinLibraryImpl).base.access.layout.isZipped
}
internal val VirtualFile.isKonanLibraryRoot: Boolean
get() {
// The virtual file for a library packed in a ZIP file will have path like "/some/path/to/the/file.klib!/",
// and therefore will be recognized by VFS as a directory (isDirectory == true).
// So, first, let's check the extension.
val extension = extension
if (!extension.isNullOrEmpty() && extension != KLIB_FILE_EXTENSION) return false
val manifestFile = findChild(KLIB_MANIFEST_FILE_NAME)?.takeIf { !it.isDirectory } ?: return false
val manifestProperties = try {
manifestFile.inputStream.use { Properties().apply { load(it) } }
} catch (_: IOException) {
return false
}
return manifestProperties.containsKey(KLIB_PROPERTY_UNIQUE_NAME)
}
@@ -10,10 +10,7 @@ import com.intellij.openapi.roots.libraries.DummyLibraryProperties
import com.intellij.openapi.roots.libraries.LibraryType
import com.intellij.openapi.roots.libraries.ui.LibraryEditorComponent
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.util.PathUtil
import org.jetbrains.kotlin.idea.KotlinIcons
import org.jetbrains.kotlin.konan.library.lite.LiteKonanLibraryFacade
import java.io.File
import javax.swing.Icon
import javax.swing.JComponent
@@ -25,13 +22,10 @@ object NativeLibraryType : LibraryType<DummyLibraryProperties>(NativeLibraryKind
// Library type is determined by `KotlinGradleLibraryDataService` for every library dependency imported from Gradle to IDE.
// However this does not work for libraries that are to be just created during project build, e.g. C-interop Kotlin/Native KLIBs.
// The code below helps to perform postponed detection of Kotlin/Native libraries.
override fun detect(classesRoots: List<VirtualFile>): DummyLibraryProperties? {
val path = classesRoots.firstOrNull()?.let { PathUtil.getLocalPath(it) } ?: return null
return if (LiteKonanLibraryFacade.getLibraryProvider().getLibrary(File(path)) != null)
override fun detect(classesRoots: List<VirtualFile>): DummyLibraryProperties? =
if (classesRoots.firstOrNull()?.isKonanLibraryRoot == true)
DummyLibraryProperties.INSTANCE!!
else null
}
override fun getIcon(properties: DummyLibraryProperties?): Icon = KotlinIcons.NATIVE
}
@@ -9,7 +9,6 @@ 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.analyzer.ModuleInfo
@@ -41,8 +40,9 @@ import org.jetbrains.kotlin.idea.compiler.IDELanguageSettingsProvider
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.library.KONAN_STDLIB_NAME
import org.jetbrains.kotlin.konan.library.KonanFactories
import org.jetbrains.kotlin.library.*
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.impl.createKotlinLibrary
import org.jetbrains.kotlin.library.isInterop
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.impl.NativeIdePlatformKind
import org.jetbrains.kotlin.platform.konan.KonanPlatforms
@@ -100,24 +100,7 @@ class NativePlatformKindResolution : IdePlatformKindResolution {
)
}
override fun isLibraryFileForPlatform(virtualFile: VirtualFile): Boolean {
return when {
// The virtual file for a library packed in a ZIP file will have path like "/some/path/to/the/file.klib!/",
// and therefore will be recognized by VFS as a directory (isDirectory == true).
// So, first, let's check the extension.
virtualFile.extension == KLIB_FILE_EXTENSION -> true
virtualFile.isDirectory -> {
val linkdataDir = virtualFile.findChild("linkdata") ?: return false
// False means we hit .knm file
!VfsUtil.processFilesRecursively(linkdataDir) {
it.extension != KLIB_METADATA_FILE_EXTENSION
}
}
else -> false
}
}
override fun isLibraryFileForPlatform(virtualFile: VirtualFile): Boolean = virtualFile.isKonanLibraryRoot
override fun createResolverForModuleFactory(
settings: PlatformAnalysisParameters,