From fb0e0e37679899bf19408fcf9c24de7a3e38f85b Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Wed, 14 Jun 2017 16:37:12 +0300 Subject: [PATCH] Introduce ScriptDependenciesFileAttribute to persist script dependencies --- .../idea/caches/FileAttributeService.kt | 8 +- .../script/ScriptDependenciesFileAttribute.kt | 89 +++++++++++++++++++ .../idea/caches/FileAttributeServiceImpl.kt | 8 +- 3 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesFileAttribute.kt diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/FileAttributeService.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/FileAttributeService.kt index 0ef4c383742..2640e3ace06 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/FileAttributeService.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/FileAttributeService.kt @@ -17,11 +17,13 @@ package org.jetbrains.kotlin.idea.caches import com.intellij.openapi.vfs.VirtualFile +import java.io.DataInput +import java.io.DataOutput data class CachedAttributeData(val value: T, val timeStamp: Long) interface FileAttributeService { - fun register(id: String, version: Int) {} + fun register(id: String, version: Int, fixedSize: Boolean = true) {} fun > writeEnumAttribute(id: String, file: VirtualFile, value: T): CachedAttributeData = CachedAttributeData(value, timeStamp = file.timeStamp) @@ -32,4 +34,8 @@ interface FileAttributeService { CachedAttributeData(value, timeStamp = file.timeStamp) fun readBooleanAttribute(id: String, file: VirtualFile): CachedAttributeData? = null + + fun write(file: VirtualFile, id: String, value: T, writeValueFun: (DataOutput, T) -> Unit): CachedAttributeData + + fun read(file: VirtualFile, id: String, readValueFun: (DataInput) -> T): CachedAttributeData? } 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 new file mode 100644 index 00000000000..a24d5894ecd --- /dev/null +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesFileAttribute.kt @@ -0,0 +1,89 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.core.script + +import com.intellij.openapi.components.service +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.VirtualFileWithId +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.caches.FileAttributeService +import java.io.DataInput +import java.io.DataOutput +import java.io.File +import kotlin.script.dependencies.KotlinScriptExternalDependencies + +// TODO_R: write nullable, write version +object ScriptDependenciesFileAttribute { + private val VERSION = 1 + private val ID = "kotlin-script-dependencies" + + private val fileAttributeService = service() + + init { + fileAttributeService.register(ID, VERSION, false) + } + + fun write(virtualFile: VirtualFile, dependencies: KotlinScriptExternalDependencies) { + if (virtualFile !is VirtualFileWithId) return + + fileAttributeService.write(virtualFile, ID, dependencies) { output, dep -> + with(dep) { + output.writeFileList(classpath) + output.writeStringList(imports) + // TODO: actually read/write nullable + output.writeString(javaHome ?: "") + output.writeFileList(scripts) + output.writeFileList(sources) + } + } + } + + fun read(virtualFile: VirtualFile): KotlinScriptExternalDependencies? { + if (virtualFile !is VirtualFileWithId) return null + + return fileAttributeService.read(virtualFile, ID) { input -> + SerializedScriptDependencies( + classpath = input.readFileList(), + imports = input.readStringList(), + javaHome = input.readString(), + scripts = input.readFileList(), + sources = input.readFileList() + ) + }?.value + } +} + +private fun DataInput.readStringList(): List = readSeq(this) { readString() } +private fun DataInput.readFileList() = readStringList().map { File(it) } +private fun DataInput.readString() = readUTF(this) + +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 class SerializedScriptDependencies( + override val classpath: Iterable, + override val imports: Iterable, + override val javaHome: String?, + override val scripts: Iterable, + override val sources: Iterable +) : KotlinScriptExternalDependencies \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/caches/FileAttributeServiceImpl.kt b/idea/src/org/jetbrains/kotlin/idea/caches/FileAttributeServiceImpl.kt index 22be215252a..983693c0bec 100644 --- a/idea/src/org/jetbrains/kotlin/idea/caches/FileAttributeServiceImpl.kt +++ b/idea/src/org/jetbrains/kotlin/idea/caches/FileAttributeServiceImpl.kt @@ -26,8 +26,8 @@ import java.io.DataOutput class FileAttributeServiceImpl : FileAttributeService { val attributes: MutableMap = ContainerUtil.newConcurrentMap() - override fun register(id: String, version: Int) { - attributes[id] = FileAttribute(id, version, true) + override fun register(id: String, version: Int, fixedSize: Boolean) { + attributes[id] = FileAttribute(id, version, fixedSize) } override fun > writeEnumAttribute(id: String, file: VirtualFile, value: T): CachedAttributeData { @@ -55,7 +55,7 @@ class FileAttributeServiceImpl : FileAttributeService { } } - private inline fun write(file: VirtualFile, id: String, value: T, writeValueFun: (DataOutput, T) -> Unit): CachedAttributeData { + override fun write(file: VirtualFile, id: String, value: T, writeValueFun: (DataOutput, T) -> Unit): CachedAttributeData { val attribute = attributes[id] ?: throw IllegalArgumentException("Attribute with $id wasn't registered") val data = CachedAttributeData(value, timeStamp = file.timeStamp) @@ -68,7 +68,7 @@ class FileAttributeServiceImpl : FileAttributeService { return data } - private inline fun read(file: VirtualFile, id: String, readValueFun: (DataInput) -> T): CachedAttributeData? { + override fun read(file: VirtualFile, id: String, readValueFun: (DataInput) -> T): CachedAttributeData? { val attribute = attributes[id] ?: throw IllegalArgumentException("Attribute with $id wasn't registered") val stream = attribute.readAttribute(file) ?: return null