Simplify jar-processor framework
This commit is contained in:
@@ -24,32 +24,42 @@ import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
|
||||
public object JarUserDataManager {
|
||||
val fileAttributeService: FileAttributeService? = ServiceManager.getService(javaClass<FileAttributeService>())
|
||||
|
||||
public fun register(collector: JarUserDataCollector<*>) {
|
||||
fileAttributeService?.register(collector.key.toString(), collector.version)
|
||||
enum class State {
|
||||
INIT,
|
||||
HAS_FILE,
|
||||
NO_FILE
|
||||
}
|
||||
|
||||
public fun <T: Enum<T>> getValue(collector: JarUserDataCollector<T>, file: VirtualFile): T? {
|
||||
val version = 1
|
||||
|
||||
val fileAttributeService: FileAttributeService? = ServiceManager.getService(javaClass<FileAttributeService>())
|
||||
|
||||
public fun register(counter: JarBooleanPropertyCounter) {
|
||||
fileAttributeService?.register(counter.key.toString(), version)
|
||||
}
|
||||
|
||||
public fun hasFileWithProperty(counter: JarBooleanPropertyCounter, file: VirtualFile): Boolean? {
|
||||
val jarFile = findJarRoot(file) ?: return null
|
||||
|
||||
val stored = jarFile.getUserData(collector.key)
|
||||
if (stored != null && jarFile.timeStamp == stored.second) {
|
||||
return stored.first
|
||||
val stored = jarFile.getUserData(counter.key)
|
||||
if (stored != null && jarFile.timeStamp == stored.timestamp) {
|
||||
return stored.hasFileWithProperty
|
||||
}
|
||||
|
||||
if (stored == null && fileAttributeService != null) {
|
||||
val savedData = fileAttributeService.readAttribute(collector.key.toString(), jarFile, collector.stateClass)
|
||||
val savedData = fileAttributeService.readAttribute(counter.key.toString(), jarFile, javaClass<State>())
|
||||
if (savedData != null && savedData.value != null) {
|
||||
jarFile.putUserData(collector.key, savedData.value to savedData.timeStamp)
|
||||
val hasFileWithProperty = savedData.value == State.HAS_FILE
|
||||
|
||||
jarFile.putUserData(counter.key, PropertyData(hasFileWithProperty, savedData.timeStamp))
|
||||
|
||||
if (jarFile.timeStamp == savedData.timeStamp) {
|
||||
return savedData.value
|
||||
return hasFileWithProperty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scheduleJarProcessing(collector, jarFile)
|
||||
scheduleJarProcessing(counter, jarFile)
|
||||
|
||||
return null
|
||||
}
|
||||
@@ -63,44 +73,35 @@ public object JarUserDataManager {
|
||||
return jarFile
|
||||
}
|
||||
|
||||
private fun <T: Enum<T>> scheduleJarProcessing(collector: JarUserDataCollector<T>, jarFile: VirtualFile) {
|
||||
if (jarFile.getUserData(collector.key) != null) return
|
||||
private fun scheduleJarProcessing(counter: JarBooleanPropertyCounter, jarFile: VirtualFile) {
|
||||
if (jarFile.getUserData(counter.key) != null) return
|
||||
|
||||
jarFile.putUserData(collector.key, collector.init to jarFile.timeStamp)
|
||||
jarFile.putUserData(counter.key, PropertyData(null, jarFile.timeStamp))
|
||||
|
||||
ApplicationManager.getApplication().executeOnPooledThread {
|
||||
runReadAction {
|
||||
var result = collector.notFoundState
|
||||
|
||||
VfsUtilCore.processFilesRecursively(jarFile) { file ->
|
||||
if (collector.process(file) == collector.stopState) {
|
||||
result = collector.stopState
|
||||
|
||||
// stop processing
|
||||
false
|
||||
}
|
||||
else {
|
||||
// continue processing
|
||||
true
|
||||
}
|
||||
val hasFileWithProperty = !VfsUtilCore.processFilesRecursively(jarFile) { file ->
|
||||
!counter.hasProperty(file)
|
||||
}
|
||||
|
||||
val savedData = fileAttributeService?.writeAttribute(collector.key.toString(), jarFile, result)
|
||||
jarFile.putUserData(collector.key, result to (savedData?.timeStamp ?: jarFile.timeStamp))
|
||||
val state = if (hasFileWithProperty) State.HAS_FILE else State.NO_FILE
|
||||
|
||||
val savedData = fileAttributeService?.writeAttribute(counter.key.toString(), jarFile, state)
|
||||
|
||||
jarFile.putUserData(
|
||||
counter.key,
|
||||
PropertyData(hasFileWithProperty, (savedData?.timeStamp ?: jarFile.timeStamp)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface JarUserDataCollector<State: Enum<State>> {
|
||||
val key: Key<Pair<State, Long>>
|
||||
val stateClass: Class<State>
|
||||
data class PropertyData(val hasFileWithProperty: Boolean?, val timestamp: Long)
|
||||
|
||||
val version: Int get() = 1
|
||||
abstract class JarBooleanPropertyCounter(keyName: String) {
|
||||
val key: Key<PropertyData> = Key.create<PropertyData>(keyName)
|
||||
|
||||
val init: State
|
||||
val stopState: State
|
||||
val notFoundState: State
|
||||
abstract fun hasProperty(file: VirtualFile): Boolean
|
||||
|
||||
fun process(file: VirtualFile): State
|
||||
override fun toString() = "Counter: $key"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,14 +17,9 @@
|
||||
package org.jetbrains.kotlin.idea.decompiler
|
||||
|
||||
import com.intellij.ide.highlighter.JavaClassFileType
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.impl.FilePropertyPusher
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.pom.java.LanguageLevel
|
||||
import com.intellij.psi.ClassFileViewProvider
|
||||
import com.intellij.util.messages.MessageBus
|
||||
import org.jetbrains.kotlin.idea.caches.JarUserDataManager
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass
|
||||
@@ -39,7 +34,7 @@ public fun isKotlinJvmCompiledFile(file: VirtualFile): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
if (JarUserDataManager.getValue(HasCompiledKotlinInJar, file) == HasCompiledKotlinInJar.JarKotlinState.NO_KOTLIN) {
|
||||
if (HasCompiledKotlinInJar.isInNoKotlinJar(file)) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -81,19 +76,9 @@ public fun isKotlinInternalCompiledFile(file: VirtualFile): Boolean {
|
||||
public fun isKotlinJavaScriptInternalCompiledFile(file: VirtualFile): Boolean =
|
||||
isKotlinJsMetaFile(file) && file.getNameWithoutExtension().contains('.')
|
||||
|
||||
public object HasCompiledKotlinInJar : JarUserDataManager.JarUserDataCollector<HasCompiledKotlinInJar.JarKotlinState> {
|
||||
public enum class JarKotlinState {
|
||||
HAS_KOTLIN,
|
||||
NO_KOTLIN,
|
||||
COUNTING
|
||||
}
|
||||
public object HasCompiledKotlinInJar : JarUserDataManager.JarBooleanPropertyCounter(HasCompiledKotlinInJar::class.simpleName!!) {
|
||||
override fun hasProperty(file: VirtualFile) = isKotlinJvmCompiledFile(file)
|
||||
|
||||
override val key = Key.create<Pair<HasCompiledKotlinInJar.JarKotlinState, Long>>(HasCompiledKotlinInJar::class.simpleName!!)
|
||||
override val stateClass = javaClass<JarKotlinState>()
|
||||
|
||||
override val init = JarKotlinState.COUNTING
|
||||
override val stopState = JarKotlinState.HAS_KOTLIN
|
||||
override val notFoundState = JarKotlinState.NO_KOTLIN
|
||||
|
||||
override fun process(file: VirtualFile) = if (isKotlinJvmCompiledFile(file)) JarKotlinState.HAS_KOTLIN else JarKotlinState.NO_KOTLIN
|
||||
fun isInNoKotlinJar(file: VirtualFile): Boolean =
|
||||
JarUserDataManager.hasFileWithProperty(HasCompiledKotlinInJar, file) == false
|
||||
}
|
||||
|
||||
+6
-26
@@ -38,12 +38,9 @@ public object KotlinJavaScriptLibraryDetectionUtil {
|
||||
if (JavaRuntimeDetectionUtil.getJavaRuntimeVersion(classesRoots) != null) return false
|
||||
|
||||
classesRoots.forEach { root ->
|
||||
val cachedResult = JarUserDataManager.getValue(HasKotlinJSMetadataInJar, root)
|
||||
|
||||
@suppress("NON_EXHAUSTIVE_WHEN")
|
||||
when (cachedResult) {
|
||||
HasKotlinJSMetadataInJar.JsMetadataState.HAS_JS_METADATA -> return true
|
||||
HasKotlinJSMetadataInJar.JsMetadataState.NO_JS_METADATA -> return false
|
||||
val hasMetadata = HasKotlinJSMetadataInJar.hasMetadataFromCache(root)
|
||||
if (hasMetadata != null) {
|
||||
return hasMetadata
|
||||
}
|
||||
|
||||
if (!VfsUtilCore.processFilesRecursively(root, { isJsFileWithMetadata(root) })) {
|
||||
@@ -59,26 +56,9 @@ public object KotlinJavaScriptLibraryDetectionUtil {
|
||||
JavaScript.EXTENSION == file.getExtension() &&
|
||||
KotlinJavascriptMetadataUtils.hasMetadata(String(file.contentsToByteArray(false)))
|
||||
|
||||
public object HasKotlinJSMetadataInJar : JarUserDataManager.JarUserDataCollector<HasKotlinJSMetadataInJar.JsMetadataState> {
|
||||
public enum class JsMetadataState {
|
||||
HAS_JS_METADATA,
|
||||
NO_JS_METADATA,
|
||||
COUNTING
|
||||
}
|
||||
public object HasKotlinJSMetadataInJar : JarUserDataManager.JarBooleanPropertyCounter(HasKotlinJSMetadataInJar::class.simpleName!!) {
|
||||
override fun hasProperty(file: VirtualFile) = KotlinJavaScriptLibraryDetectionUtil.isJsFileWithMetadata(file)
|
||||
|
||||
override val key = Key.create<Pair<HasKotlinJSMetadataInJar.JsMetadataState, Long>>(HasKotlinJSMetadataInJar::class.simpleName!!)
|
||||
override val stateClass = javaClass<JsMetadataState>()
|
||||
|
||||
override val init = JsMetadataState.COUNTING
|
||||
override val stopState = JsMetadataState.HAS_JS_METADATA
|
||||
override val notFoundState = JsMetadataState.NO_JS_METADATA
|
||||
|
||||
override fun process(file: VirtualFile): JsMetadataState {
|
||||
return if (KotlinJavaScriptLibraryDetectionUtil.isJsFileWithMetadata(file)) {
|
||||
JsMetadataState.HAS_JS_METADATA
|
||||
} else {
|
||||
JsMetadataState.NO_JS_METADATA
|
||||
}
|
||||
}
|
||||
fun hasMetadataFromCache(root: VirtualFile): Boolean? = JarUserDataManager.hasFileWithProperty(HasKotlinJSMetadataInJar, root)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user