From 178dad3b4ee99c89e8f87a0ba0857f1c3c25ae4e Mon Sep 17 00:00:00 2001 From: Natalia Selezneva Date: Tue, 3 Apr 2018 16:09:08 +0300 Subject: [PATCH] Refactoring: introduce file attribute utils --- .../core/script/ModuleNameFileAttribute.kt | 33 +++---- .../script/ScriptDependenciesFileAttribute.kt | 87 +++++-------------- .../idea/core/util/FileAttributeUtils.kt | 75 ++++++++++++++++ 3 files changed, 107 insertions(+), 88 deletions(-) create mode 100644 idea/idea-core/src/org/jetbrains/kotlin/idea/core/util/FileAttributeUtils.kt diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ModuleNameFileAttribute.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ModuleNameFileAttribute.kt index c8dcdce437a..1192e9f7e68 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ModuleNameFileAttribute.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ModuleNameFileAttribute.kt @@ -6,26 +6,15 @@ package org.jetbrains.kotlin.idea.core.script import com.intellij.openapi.vfs.VirtualFile -import com.intellij.openapi.vfs.VirtualFileWithId -import com.intellij.openapi.vfs.newvfs.FileAttribute -import kotlin.reflect.KProperty +import org.jetbrains.kotlin.idea.core.util.fileAttribute +import org.jetbrains.kotlin.idea.core.util.readString +import org.jetbrains.kotlin.idea.core.util.writeString +import java.io.DataInputStream +import java.io.DataOutputStream -var VirtualFile.scriptRelatedModuleName: String? by ScratchModuleNameProperty() - -private val moduleNameAttribute = FileAttribute("kotlin-script-moduleName", 1, false) -private class ScratchModuleNameProperty { - - operator fun getValue(file: VirtualFile, property: KProperty<*>): String? { - if (file !is VirtualFileWithId) return null - - return moduleNameAttribute.readAttributeBytes(file)?.let { String(it) } - } - - operator fun setValue(file: VirtualFile, property: KProperty<*>, newValue: String?) { - if (file !is VirtualFileWithId) return - - if (newValue != null) { - moduleNameAttribute.writeAttributeBytes(file, newValue.toByteArray()) - } - } -} \ No newline at end of file +var VirtualFile.scriptRelatedModuleName: String? by fileAttribute( + name = "kotlin-script-moduleName", + version = 1, + read = DataInputStream::readString, + write = DataOutputStream::writeString +) \ No newline at end of file diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesFileAttribute.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesFileAttribute.kt index 3dfc6071235..16f12aa51ab 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesFileAttribute.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesFileAttribute.kt @@ -17,75 +17,30 @@ package org.jetbrains.kotlin.idea.core.script import com.intellij.openapi.vfs.VirtualFile -import com.intellij.openapi.vfs.VirtualFileWithId -import com.intellij.openapi.vfs.newvfs.FileAttribute -import com.intellij.util.io.DataInputOutputUtil.readSeq -import com.intellij.util.io.DataInputOutputUtil.writeSeq -import com.intellij.util.io.IOUtil.readUTF -import com.intellij.util.io.IOUtil.writeUTF +import org.jetbrains.kotlin.idea.core.util.* import java.io.DataInput import java.io.DataOutput -import java.io.File -import kotlin.reflect.KProperty import kotlin.script.experimental.dependencies.ScriptDependencies -var VirtualFile.scriptDependencies: ScriptDependencies? by ScriptDependenciesProperty() -private val scriptDependencies = FileAttribute("kotlin-script-dependencies", 4, false) - -private class ScriptDependenciesProperty { - - operator fun setValue(file: VirtualFile, property: KProperty<*>, newValue: ScriptDependencies?) { - if (file !is VirtualFileWithId) return - - val output = scriptDependencies.writeAttribute(file) - output.use { - it.writeNullable(newValue) { value -> - with(value) { - writeFileList(classpath) - writeStringList(imports) - writeNullable(javaHome, DataOutput::writeFile) - writeFileList(scripts) - writeFileList(sources) - - } - } +var VirtualFile.scriptDependencies: ScriptDependencies? by fileAttribute( + name = "kotlin-script-dependencies", + version = 3, + read = { + ScriptDependencies( + classpath = readFileList(), + imports = readStringList(), + javaHome = readNullable(DataInput::readFile), + scripts = readFileList(), + sources = readFileList() + ) + }, + write = { + with(it) { + writeFileList(classpath) + writeStringList(imports) + writeNullable(javaHome, DataOutput::writeFile) + writeFileList(scripts) + writeFileList(sources) } } - - operator fun getValue(file: VirtualFile, property: KProperty<*>): ScriptDependencies? { - if (file !is VirtualFileWithId) return null - - val input = scriptDependencies.readAttribute(file) - return input?.use { - it.readNullable { - ScriptDependencies( - classpath = readFileList(), - imports = readStringList(), - javaHome = readNullable(DataInput::readFile), - scripts = readFileList(), - sources = readFileList() - ) - } - } - } -} - -private fun DataInput.readStringList(): List = readSeq(this) { readString() } -private fun DataInput.readFileList() = readSeq(this) { readFile() } -private fun DataInput.readString() = readUTF(this) -private fun DataInput.readFile() = readUTF(this).let { File(it) } - -private fun DataOutput.writeFileList(iterable: Iterable) = writeSeq(this, iterable.toList()) { writeFile(it) } -private fun DataOutput.writeFile(it: File) = writeString(it.canonicalPath) -private fun DataOutput.writeString(string: String) = writeUTF(this, string) -private fun DataOutput.writeStringList(iterable: Iterable) = writeSeq(this, iterable.toList()) { writeString(it) } - -private fun DataOutput.writeNullable(nullable: T?, writeT: DataOutput.(T) -> Unit) { - writeBoolean(nullable != null) - nullable?.let { writeT(it) } -} - -private fun DataInput.readNullable(readT: DataInput.() -> T): T? { - val hasValue = readBoolean() - return if (hasValue) readT() else null -} \ No newline at end of file +) \ No newline at end of file diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/util/FileAttributeUtils.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/util/FileAttributeUtils.kt new file mode 100644 index 00000000000..db00c74031d --- /dev/null +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/util/FileAttributeUtils.kt @@ -0,0 +1,75 @@ +/* + * 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.core.util + +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.VirtualFileWithId +import com.intellij.openapi.vfs.newvfs.FileAttribute +import com.intellij.util.io.DataInputOutputUtil.readSeq +import com.intellij.util.io.DataInputOutputUtil.writeSeq +import com.intellij.util.io.IOUtil.readUTF +import com.intellij.util.io.IOUtil.writeUTF +import java.io.* +import kotlin.reflect.KProperty + +fun fileAttribute( + name: String, + version: Int, + read: DataInputStream.() -> T, + write: DataOutputStream.(T) -> Unit +): FileAttributeProperty { + return object : FileAttributeProperty(name, version) { + override fun readValue(input: DataInputStream): T = read(input) + override fun writeValue(output: DataOutputStream, value: T) = write(output, value) + } +} + +abstract class FileAttributeProperty(name: String, version: Int, private val default: T? = null) { + abstract fun readValue(input: DataInputStream): T + abstract fun writeValue(output: DataOutputStream, value: T) + + private val attribute = FileAttribute(name, version, false) + + operator fun setValue(file: VirtualFile, property: KProperty<*>, newValue: T?) { + if (file !is VirtualFileWithId) return + + attribute.writeAttribute(file).use { output -> + output.writeNullable(newValue) { value -> + writeValue(output, value) + } + } + } + + operator fun getValue(file: VirtualFile, property: KProperty<*>): T? { + if (file !is VirtualFileWithId) return null + + return attribute.readAttribute(file)?.use { input -> + input.readNullable { + readValue(input) + } + } ?: default + } +} + +fun DataInput.readStringList(): List = readSeq(this) { readString() } +fun DataInput.readFileList(): List = readSeq(this) { readFile() } +fun DataInput.readString(): String = readUTF(this) +fun DataInput.readFile() = readUTF(this).let { File(it) } + +fun DataOutput.writeFileList(iterable: Iterable) = writeSeq(this, iterable.toList()) { writeFile(it) } +fun DataOutput.writeFile(it: File) = writeString(it.canonicalPath) +fun DataOutput.writeString(string: String) = writeUTF(this, string) +fun DataOutput.writeStringList(iterable: Iterable) = writeSeq(this, iterable.toList()) { writeString(it) } + +fun DataOutput.writeNullable(nullable: T?, writeT: DataOutput.(T) -> Unit) { + writeBoolean(nullable != null) + nullable?.let { writeT(it) } +} + +fun DataInput.readNullable(readT: DataInput.() -> T): T? { + val hasValue = readBoolean() + return if (hasValue) readT() else null +} \ No newline at end of file