[Editor] Create ResourceFileNode

This commit is contained in:
2021-03-01 10:59:51 +01:00
parent 965775774c
commit a270414a28
7 changed files with 129 additions and 30 deletions

View File

@@ -59,6 +59,18 @@ task provideGameEngine(type: Copy) {
task provideApi(type: Copy) { task provideApi(type: Copy) {
from project(':api').file('src/main/java') from project(':api').file('src/main/java')
into file('build/resources/main/api') into file('build/resources/main/api')
doLast {
def apiDir = file('build/resources/main/api')
def apiIndex = file('build/resources/main/api.idx')
def buffer = new StringBuilder()
fileTree(apiDir).matching { include "**/*.java" }.each {
buffer.append(apiDir.relativePath(it)).append("\n")
}
apiIndex.write(buffer.toString())
}
} }
processResources { processResources {

View File

@@ -0,0 +1,21 @@
package com.bartlomiejpluta.base.editor.code.api
import com.bartlomiejpluta.base.editor.file.model.FileNode
import com.bartlomiejpluta.base.editor.file.model.ResourceFileNode
import org.springframework.beans.factory.annotation.Value
import org.springframework.core.io.Resource
import org.springframework.stereotype.Component
import java.io.BufferedReader
@Component
class APIProvider {
@Value("classpath:api.idx")
private lateinit var apiIndex: Resource
val apiNode: FileNode by lazy { loadNode() }
private fun loadNode() = ResourceFileNode.root("api").apply {
apiIndex.inputStream.bufferedReader().use(BufferedReader::readLines).forEach(this::createNode)
}
}

View File

@@ -1,15 +1,16 @@
package com.bartlomiejpluta.base.editor.code.build.compiler package com.bartlomiejpluta.base.editor.code.build.compiler
import com.bartlomiejpluta.base.editor.code.api.APIProvider
import com.bartlomiejpluta.base.editor.code.build.exception.BuildException import com.bartlomiejpluta.base.editor.code.build.exception.BuildException
import com.bartlomiejpluta.base.editor.code.build.model.ClasspathResource import com.bartlomiejpluta.base.editor.code.build.model.FileNodeResourceAdapter
import com.bartlomiejpluta.base.editor.common.logs.enumeration.Severity import com.bartlomiejpluta.base.editor.common.logs.enumeration.Severity
import com.bartlomiejpluta.base.editor.event.AppendBuildLogsEvent import com.bartlomiejpluta.base.editor.event.AppendBuildLogsEvent
import com.bartlomiejpluta.base.editor.file.model.FileSystemNode import com.bartlomiejpluta.base.editor.file.model.FileSystemNode
import com.bartlomiejpluta.base.editor.file.model.FileType
import org.codehaus.commons.compiler.CompileException import org.codehaus.commons.compiler.CompileException
import org.codehaus.commons.compiler.util.resource.FileResource
import org.codehaus.commons.compiler.util.resource.Resource import org.codehaus.commons.compiler.util.resource.Resource
import org.codehaus.janino.CompilerFactory import org.codehaus.janino.CompilerFactory
import org.springframework.beans.factory.annotation.Value import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component import org.springframework.stereotype.Component
import tornadofx.FX.Companion.eventbus import tornadofx.FX.Companion.eventbus
import java.io.File import java.io.File
@@ -18,8 +19,8 @@ import java.io.File
class JaninoCompiler : Compiler { class JaninoCompiler : Compiler {
private val compilerFactory = CompilerFactory() private val compilerFactory = CompilerFactory()
@Value("classpath:api/**/*.java") @Autowired
private lateinit var apiFiles: Array<org.springframework.core.io.Resource> private lateinit var apiProvider: APIProvider
override fun compile(sourceDirectory: FileSystemNode, targetDirectory: File) = try { override fun compile(sourceDirectory: FileSystemNode, targetDirectory: File) = try {
tryToCompile(sourceDirectory, targetDirectory) tryToCompile(sourceDirectory, targetDirectory)
@@ -56,17 +57,11 @@ class JaninoCompiler : Compiler {
} }
private fun prepareCompilationUnits(sourceDirectory: FileSystemNode): Array<Resource> { private fun prepareCompilationUnits(sourceDirectory: FileSystemNode): Array<Resource> {
val sources = sourceDirectory val sources = sourceDirectory.allChildren
.allChildren val api = apiProvider.apiNode.allChildren
.map(FileSystemNode::file) return (sources + api)
.filter(File::isFile) .filter { it.type == FileType.FILE }
.map(::FileResource) .map(::FileNodeResourceAdapter)
.toTypedArray<Resource>()
val api = apiFiles
.map(::ClasspathResource)
.toTypedArray() .toTypedArray()
return sources + api
} }
} }

View File

@@ -0,0 +1,10 @@
package com.bartlomiejpluta.base.editor.code.build.model
import com.bartlomiejpluta.base.editor.file.model.FileNode
import org.codehaus.commons.compiler.util.resource.Resource
class FileNodeResourceAdapter(private val fileNode: FileNode) : Resource {
override fun open() = fileNode.inputStream()
override fun getFileName() = fileNode.absolutePath
override fun lastModified() = fileNode.lastModified
}

View File

@@ -1,5 +1,6 @@
package com.bartlomiejpluta.base.editor.file.model package com.bartlomiejpluta.base.editor.file.model
import javafx.beans.value.ObservableLongValue
import javafx.beans.value.ObservableValue import javafx.beans.value.ObservableValue
import java.io.InputStream import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream
@@ -19,7 +20,11 @@ interface FileNode {
val parent: FileNode? val parent: FileNode?
val children: Iterable<FileNode> val children: Iterable<FileNode>
val allChildren: Iterable<FileNode> val allChildren: List<FileNode>
get() = children + children.flatMap { it.allChildren }
val lastModifiedProperty: ObservableLongValue
val lastModified: Long
fun delete() fun delete()
fun rename(name: String) fun rename(name: String)
@@ -29,7 +34,7 @@ interface FileNode {
fun inputStream(): InputStream fun inputStream(): InputStream
fun outputStream(): OutputStream fun outputStream(): OutputStream
fun writeBytes(array: ByteArray)
fun writeText(text: String, charset: Charset = Charsets.UTF_8) = writeBytes(text.toByteArray(charset))
fun readText(charset: Charset = Charsets.UTF_8) = inputStream().reader(charset).readText() fun readText(charset: Charset = Charsets.UTF_8) = inputStream().reader(charset).readText()
fun writeText(text: String, charset: Charset = Charsets.UTF_8) = writeBytes(text.toByteArray(charset))
fun writeBytes(array: ByteArray) = outputStream().use { it.write(array) }
} }

View File

@@ -1,12 +1,12 @@
package com.bartlomiejpluta.base.editor.file.model package com.bartlomiejpluta.base.editor.file.model
import javafx.beans.binding.Bindings.createLongBinding
import javafx.beans.binding.Bindings.createStringBinding import javafx.beans.binding.Bindings.createStringBinding
import tornadofx.getValue import tornadofx.getValue
import tornadofx.observableListOf import tornadofx.observableListOf
import tornadofx.setValue import tornadofx.setValue
import tornadofx.toProperty import tornadofx.toProperty
import java.io.File import java.io.File
import java.io.FileOutputStream
import java.nio.file.Path import java.nio.file.Path
class FileSystemNode(file: File, override val parent: FileSystemNode? = null) : FileNode { class FileSystemNode(file: File, override val parent: FileSystemNode? = null) : FileNode {
@@ -30,8 +30,9 @@ class FileSystemNode(file: File, override val parent: FileSystemNode? = null) :
} }
override val children = observableListOf<FileSystemNode>() override val children = observableListOf<FileSystemNode>()
override val allChildren: List<FileSystemNode>
get() = children + children.flatMap { it.allChildren } override val lastModifiedProperty = createLongBinding({ fileProperty.value.lastModified() }, fileProperty)
override val lastModified by lastModifiedProperty
init { init {
refreshChildren() refreshChildren()
@@ -78,7 +79,7 @@ class FileSystemNode(file: File, override val parent: FileSystemNode? = null) :
else -> file.createNewFile() else -> file.createNewFile()
} }
when (val child = findChild(file)) { when (val child = parent.children.firstOrNull { it.name == file.name }) {
null -> FileSystemNode(file, parent).also { parent.children += it } null -> FileSystemNode(file, parent).also { parent.children += it }
else -> child else -> child
} }
@@ -89,11 +90,5 @@ class FileSystemNode(file: File, override val parent: FileSystemNode? = null) :
override fun outputStream() = file.outputStream() override fun outputStream() = file.outputStream()
override fun writeBytes(array: ByteArray): Unit = FileOutputStream(file).use { it.write(array) } fun findByFile(file: File) = allChildren.firstOrNull { it.absolutePath == file.absolutePath }
private fun findChild(file: File): FileSystemNode? {
return children.firstOrNull { it.file.name == file.name }
}
fun findByFile(file: File) = allChildren.firstOrNull { it.file.equals(file) }
} }

View File

@@ -0,0 +1,61 @@
package com.bartlomiejpluta.base.editor.file.model
import javafx.beans.property.StringProperty
import org.springframework.core.io.ClassPathResource
import org.springframework.core.io.Resource
import tornadofx.getValue
import tornadofx.observableListOf
import tornadofx.toProperty
import java.nio.file.Path
class ResourceFileNode private constructor(
private val resource: Resource? = null,
override val parent: ResourceFileNode? = null,
override val type: FileType = FileType.FILE,
name: String? = null
) : FileNode {
override val nameProperty = (resource?.filename ?: name ?: "").toProperty()
override val name by nameProperty
override val extensionProperty = (resource?.filename?.substringAfter(".") ?: "").toProperty()
override val extension by extensionProperty
override val absolutePathProperty: StringProperty =
((parent?.absolutePath ?: "") + "/${nameProperty.value}").toProperty()
override val absolutePath by absolutePathProperty
override val children = observableListOf<ResourceFileNode>()
override val lastModifiedProperty = (resource?.lastModified() ?: 0L).toProperty()
override val lastModified by lastModifiedProperty
override fun createNode(path: String): ResourceFileNode {
val segments = Path.of(path.replace("..", "."))
return segments.foldIndexed(this) { index, parent, segment ->
when (val child = parent.children.firstOrNull { it.name == segment.toString() }) {
null -> when (index < segments.count() - 1) {
true -> directory(segment.toString(), parent)
false -> resource(ClassPathResource("$absolutePath/$path"), parent)
}.also { parent.children += it }
else -> child
}
}
}
override fun inputStream() = resource
?.inputStream
?: throw IllegalStateException("Attempt to open input stream of resource directory")
override fun delete() = throw UnsupportedOperationException()
override fun rename(name: String) = throw UnsupportedOperationException()
override fun refresh() = throw UnsupportedOperationException()
override fun outputStream() = throw UnsupportedOperationException()
companion object {
fun resource(resource: Resource, parent: ResourceFileNode) = ResourceFileNode(resource, parent)
fun directory(name: String, parent: ResourceFileNode) = ResourceFileNode(null, parent, FileType.DIRECTORY, name)
fun root(name: String) = ResourceFileNode(null, null, FileType.DIRECTORY, name)
}
}