Store information is file was compiled with Kotlin in attributes (KT-10312)

- Add boolean attribute for all binary files in the project
- Stop using JarUserDataManager for full file indexing
- Store full header of files compiled with Kotlin in file UserData
This commit is contained in:
Nikolay Krasko
2016-01-11 18:10:53 +03:00
committed by Nikolay Krasko
parent 5431c6937f
commit adbf098166
12 changed files with 190 additions and 56 deletions
@@ -26,9 +26,9 @@ import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.updateSettings.impl.UpdateChecker;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.idea.caches.IDEKotlinBinaryClassCache;
import org.jetbrains.kotlin.idea.caches.JarUserDataManager;
import org.jetbrains.kotlin.idea.debugger.filter.DebuggerFiltersUtilKt;
import org.jetbrains.kotlin.idea.decompiler.classFile.HasCompiledKotlinInJar;
import org.jetbrains.kotlin.idea.framework.KotlinJavaScriptLibraryDetectionUtil;
import org.jetbrains.kotlin.utils.PathUtil;
@@ -53,7 +53,6 @@ public class PluginStartupComponent implements ApplicationComponent {
registerPathVariable();
JarUserDataManager.INSTANCE.register(KotlinJavaScriptLibraryDetectionUtil.HasKotlinJSMetadataInJar.INSTANCE);
JarUserDataManager.INSTANCE.register(HasCompiledKotlinInJar.INSTANCE);
DebuggerFiltersUtilKt.addKotlinStdlibDebugFilterIfNeeded();
@@ -20,6 +20,8 @@ import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.newvfs.FileAttribute
import com.intellij.util.containers.ContainerUtil
import com.intellij.util.io.DataInputOutputUtil
import java.io.DataInput
import java.io.DataOutput
class FileAttributeServiceImpl : FileAttributeService {
val attributes: MutableMap<String, FileAttribute> = ContainerUtil.newConcurrentMap()
@@ -28,29 +30,54 @@ class FileAttributeServiceImpl : FileAttributeService {
attributes[id] = FileAttribute(id, version, true)
}
override fun <T: Enum<T>> writeAttribute(id: String, file: VirtualFile, value: T): CachedAttributeData<T> {
override fun <T: Enum<T>> writeEnumAttribute(id: String, file: VirtualFile, value: T): CachedAttributeData<T> {
return write(file, id, value) { output, v ->
DataInputOutputUtil.writeINT(output, v.ordinal)
}
}
override fun <T: Enum<T>> readEnumAttribute(id: String, file: VirtualFile, klass: Class<T>): CachedAttributeData<T>? {
return read(file, id) { input ->
deserializeEnumValue(DataInputOutputUtil.readINT(input), klass)
}
}
override fun writeBooleanAttribute(id: String, file: VirtualFile, value: Boolean): CachedAttributeData<Boolean> {
return write(file, id, value) { output, v ->
DataInputOutputUtil.writeINT(output, if (v) 1 else 0)
}
}
override fun readBooleanAttribute(id: String, file: VirtualFile): CachedAttributeData<Boolean>? {
return read(file, id) { input ->
DataInputOutputUtil.readINT(input) > 0
}
}
private inline fun <T> write(file: VirtualFile, id: String, value: T, writeValueFun: (DataOutput, T) -> Unit): CachedAttributeData<T> {
val attribute = attributes[id] ?: throw IllegalArgumentException("Attribute with $id wasn't registered")
val data = CachedAttributeData(value, timeStamp = file.timeStamp)
attribute.writeAttribute(file).use {
DataInputOutputUtil.writeTIME(it, data.timeStamp)
DataInputOutputUtil.writeINT(it, data.value?.ordinal ?: -1)
writeValueFun(it, value)
}
return data
}
override fun <T: Enum<T>> readAttribute(id: String, file: VirtualFile, klass: Class<T>): CachedAttributeData<T>? {
private inline fun <T> read(file: VirtualFile, id: String, readValueFun: (DataInput) -> T): CachedAttributeData<T>? {
val attribute = attributes[id] ?: throw IllegalArgumentException("Attribute with $id wasn't registered")
val stream = attribute.readAttribute(file) ?: return null
return stream.use {
val timeStamp = DataInputOutputUtil.readTIME(it)
val intValue = DataInputOutputUtil.readINT(it)
val value = readValueFun(it)
if (file.timeStamp == timeStamp) {
CachedAttributeData(deserializeEnumValue(intValue, klass), timeStamp)
CachedAttributeData(value, timeStamp)
}
else {
null
@@ -60,7 +87,10 @@ class FileAttributeServiceImpl : FileAttributeService {
private fun <T: Enum<T>> deserializeEnumValue(i: Int, klass: Class<T>): T {
val method = klass.getMethod("values")
@Suppress("UNCHECKED_CAST")
val values = method.invoke(null) as Array<T>
return values[i]
}
}