Store computed library kind for jar in a file attribute

It should help to avoid visiting children of each jar in java projects
LibraryEffectiveKindProviderImpl has it's own in-memory cache
but it doesn't help when project is reopened

 #KT-25129 Fixed
 #KT-25034 Fixed
This commit is contained in:
Denis Zharkov
2018-07-20 12:03:32 +03:00
parent ad326f7875
commit 73acc86785
2 changed files with 72 additions and 24 deletions
@@ -24,6 +24,8 @@ import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.roots.libraries.PersistentLibraryKind
import com.intellij.openapi.util.io.JarUtil
import com.intellij.openapi.vfs.*
import org.jetbrains.kotlin.idea.vfilefinder.KnownLibraryKindForIndex
import org.jetbrains.kotlin.idea.vfilefinder.getLibraryKindForJar
import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
@@ -59,7 +61,11 @@ fun getLibraryPlatform(project: Project, library: Library): TargetPlatform {
fun detectLibraryKind(roots: Array<VirtualFile>): PersistentLibraryKind<*>? {
val jarFile = roots.firstOrNull() ?: return null
if (jarFile.fileSystem is JarFileSystem) {
return detectLibraryKindFromJarContents(jarFile)
return when (jarFile.getLibraryKindForJar()) {
KnownLibraryKindForIndex.COMMON -> CommonLibraryKind
KnownLibraryKindForIndex.JS -> JSLibraryKind
KnownLibraryKindForIndex.UNKNOWN -> null
}
}
return when (jarFile.extension) {
@@ -69,29 +75,6 @@ fun detectLibraryKind(roots: Array<VirtualFile>): PersistentLibraryKind<*>? {
}
}
private fun detectLibraryKindFromJarContents(jarRoot: VirtualFile): PersistentLibraryKind<*>? {
var result: PersistentLibraryKind<*>? = null
VfsUtil.visitChildrenRecursively(jarRoot, object : VirtualFileVisitor<PersistentLibraryKind<*>>() {
override fun visitFile(file: VirtualFile): Boolean =
when (file.extension) {
"class" -> false
"kjsm" -> {
result = JSLibraryKind
false
}
MetadataPackageFragment.METADATA_FILE_EXTENSION -> {
result = CommonLibraryKind
false
}
else -> true
}
})
return result
}
fun getLibraryJar(roots: Array<VirtualFile>, jarPattern: Pattern): VirtualFile? {
return roots.firstOrNull { jarPattern.matcher(it.name).matches() }
}
@@ -0,0 +1,65 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. 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.idea.vfilefinder
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileVisitor
import com.intellij.openapi.vfs.VirtualFileWithId
import com.intellij.psi.search.EverythingGlobalScope
import com.intellij.util.indexing.*
import com.intellij.util.io.DataExternalizer
import com.intellij.util.io.EnumDataDescriptor
import org.jetbrains.kotlin.idea.caches.FileAttributeService
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment
enum class KnownLibraryKindForIndex {
COMMON, JS, UNKNOWN
}
private val KOTLIN_LIBRARY_KIND_FILE_ATTRIBUTE: String = "kotlin-library-kind".apply {
ServiceManager.getService(FileAttributeService::class.java)?.register(this, 1)
}
fun VirtualFile.getLibraryKindForJar(): KnownLibraryKindForIndex {
if (this !is VirtualFileWithId) return detectLibraryKindFromJarContentsForIndex(this)
val service =
ServiceManager.getService(FileAttributeService::class.java)
?: return detectLibraryKindFromJarContentsForIndex(this)
service
.readEnumAttribute(KOTLIN_LIBRARY_KIND_FILE_ATTRIBUTE, this, KnownLibraryKindForIndex::class.java)
?.let { return it.value }
return detectLibraryKindFromJarContentsForIndex(this).also { newValue ->
service.writeEnumAttribute(KOTLIN_LIBRARY_KIND_FILE_ATTRIBUTE, this, newValue)
}
}
private fun detectLibraryKindFromJarContentsForIndex(jarRoot: VirtualFile): KnownLibraryKindForIndex {
var result: KnownLibraryKindForIndex? = null
VfsUtil.visitChildrenRecursively(jarRoot, object : VirtualFileVisitor<Unit>() {
override fun visitFile(file: VirtualFile): Boolean =
when (file.extension) {
"class" -> false
"kjsm" -> {
result = KnownLibraryKindForIndex.JS
false
}
MetadataPackageFragment.METADATA_FILE_EXTENSION -> {
result = KnownLibraryKindForIndex.COMMON
false
}
else -> true
}
})
return result ?: KnownLibraryKindForIndex.UNKNOWN
}