[Editor] Bump JVM version to 17
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
plugins {
|
||||
id 'org.jetbrains.kotlin.jvm' version '1.4.10'
|
||||
id 'org.openjfx.javafxplugin' version '0.0.8'
|
||||
id 'org.jetbrains.kotlin.jvm' version "$kotlinJvmVersion"
|
||||
id 'org.openjfx.javafxplugin' version "$javaFxPluginVersion"
|
||||
id 'org.springframework.boot' version "$springBootVersion"
|
||||
id 'io.spring.dependency-management' version "$springDependencyManagementVersion"
|
||||
id 'idea'
|
||||
@@ -24,11 +24,11 @@ javafx {
|
||||
}
|
||||
|
||||
compileKotlin {
|
||||
kotlinOptions.jvmTarget = "14"
|
||||
kotlinOptions.jvmTarget = "17"
|
||||
}
|
||||
|
||||
compileTestKotlin {
|
||||
kotlinOptions.jvmTarget = "14"
|
||||
kotlinOptions.jvmTarget = "17"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -2,7 +2,14 @@ package com.bartlomiejpluta.base.editor.code.build.compiler
|
||||
|
||||
import com.bartlomiejpluta.base.editor.file.model.FileSystemNode
|
||||
import java.io.File
|
||||
import java.io.PrintStream
|
||||
|
||||
interface Compiler {
|
||||
fun compile(sourceDirectories: Array<FileSystemNode>, targetDirectory: File, classPath: Array<File> = emptyArray())
|
||||
fun compile(
|
||||
sourceDirectories: Array<FileSystemNode>,
|
||||
targetDirectory: File,
|
||||
classPath: Array<File> = emptyArray(),
|
||||
stdout: PrintStream,
|
||||
stderr: PrintStream
|
||||
)
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
package com.bartlomiejpluta.base.editor.code.build.compiler
|
||||
|
||||
import com.bartlomiejpluta.base.editor.code.build.exception.BuildException
|
||||
import com.bartlomiejpluta.base.editor.common.logs.enumeration.Severity
|
||||
import com.bartlomiejpluta.base.editor.common.logs.model.Location
|
||||
import com.bartlomiejpluta.base.editor.event.AppendBuildLogsEvent
|
||||
import com.bartlomiejpluta.base.editor.file.model.FileSystemNode
|
||||
import com.bartlomiejpluta.base.editor.file.model.FileType
|
||||
import com.bartlomiejpluta.base.editor.project.context.ProjectContext
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.context.annotation.Primary
|
||||
import org.springframework.stereotype.Component
|
||||
import tornadofx.FX
|
||||
import java.io.File
|
||||
import java.io.PrintStream
|
||||
import java.io.PrintWriter
|
||||
import javax.tools.Diagnostic
|
||||
import javax.tools.DiagnosticCollector
|
||||
import javax.tools.JavaFileObject
|
||||
@@ -20,8 +20,17 @@ import javax.tools.ToolProvider
|
||||
class JDKCompiler : Compiler {
|
||||
private val compiler = ToolProvider.getSystemJavaCompiler()
|
||||
|
||||
override fun compile(sourceDirectories: Array<FileSystemNode>, targetDirectory: File, classPath: Array<File>) {
|
||||
val classpath = classPath.joinToString(";") { it.absolutePath }
|
||||
@Autowired
|
||||
private lateinit var projectContext: ProjectContext
|
||||
|
||||
override fun compile(
|
||||
sourceDirectories: Array<FileSystemNode>,
|
||||
targetDirectory: File,
|
||||
classPath: Array<File>,
|
||||
stdout: PrintStream,
|
||||
stderr: PrintStream
|
||||
) {
|
||||
val classpath = classPath.joinToString(":") { it.absolutePath }
|
||||
val options = listOf("-g", "-d", targetDirectory.absolutePath, "-classpath", classpath)
|
||||
|
||||
val collector = DiagnosticCollector<JavaFileObject>()
|
||||
@@ -33,32 +42,33 @@ class JDKCompiler : Compiler {
|
||||
.map { it.file }
|
||||
.let { manager.getJavaFileObjects(*it.toTypedArray()) }
|
||||
|
||||
val task = compiler.getTask(null, manager, collector, options, null, sources)
|
||||
val task = compiler.getTask(PrintWriter(stdout), manager, collector, options, null, sources)
|
||||
|
||||
val success = task.call()
|
||||
|
||||
collector.diagnostics.forEach(this::fireDiagnosticEvent)
|
||||
collector.diagnostics.forEach(compilationError(stdout, stderr))
|
||||
|
||||
if (!success) {
|
||||
throw BuildException()
|
||||
}
|
||||
}
|
||||
|
||||
private fun fireDiagnosticEvent(diagnostic: Diagnostic<out JavaFileObject>) {
|
||||
val severity = when (diagnostic.kind!!) {
|
||||
Diagnostic.Kind.ERROR -> Severity.ERROR
|
||||
Diagnostic.Kind.WARNING -> Severity.WARNING
|
||||
Diagnostic.Kind.MANDATORY_WARNING -> Severity.WARNING
|
||||
Diagnostic.Kind.NOTE -> Severity.NOTE
|
||||
Diagnostic.Kind.OTHER -> Severity.INFO
|
||||
private fun compilationError(stdout: PrintStream, stderr: PrintStream): (Diagnostic<out JavaFileObject>) -> Unit {
|
||||
|
||||
return { d ->
|
||||
val stream = when (d.kind!!) {
|
||||
Diagnostic.Kind.ERROR -> stderr
|
||||
Diagnostic.Kind.WARNING -> stderr
|
||||
Diagnostic.Kind.MANDATORY_WARNING -> stderr
|
||||
Diagnostic.Kind.NOTE -> stdout
|
||||
Diagnostic.Kind.OTHER -> stdout
|
||||
}
|
||||
|
||||
val source =
|
||||
projectContext.project?.let { File(d.source.name).toRelativeString(it.codeFSNode.file) } ?: d.source.name
|
||||
|
||||
stream.println("[$TAG] $source:${d.lineNumber},${d.columnNumber}: ${d.getMessage(null)}")
|
||||
}
|
||||
|
||||
val location = diagnostic.source?.let {
|
||||
Location(diagnostic.source.name, diagnostic.lineNumber, diagnostic.columnNumber)
|
||||
}
|
||||
|
||||
|
||||
FX.eventbus.fire(AppendBuildLogsEvent(severity, diagnostic.getMessage(null), location, TAG))
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -2,23 +2,26 @@ package com.bartlomiejpluta.base.editor.code.build.compiler
|
||||
|
||||
import com.bartlomiejpluta.base.editor.code.build.exception.BuildException
|
||||
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.model.Location
|
||||
import com.bartlomiejpluta.base.editor.event.AppendBuildLogsEvent
|
||||
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.janino.CompilerFactory
|
||||
import org.springframework.stereotype.Component
|
||||
import tornadofx.FX.Companion.eventbus
|
||||
import java.io.File
|
||||
import java.io.PrintStream
|
||||
|
||||
@Component
|
||||
class JaninoCompiler : Compiler {
|
||||
private val compilerFactory = CompilerFactory()
|
||||
|
||||
override fun compile(sourceDirectories: Array<FileSystemNode>, targetDirectory: File, classPath: Array<File>) = try {
|
||||
tryToCompile(sourceDirectories, targetDirectory, classPath)
|
||||
override fun compile(
|
||||
sourceDirectories: Array<FileSystemNode>,
|
||||
targetDirectory: File,
|
||||
classPath: Array<File>,
|
||||
stdout: PrintStream,
|
||||
stderr: PrintStream
|
||||
) = try {
|
||||
tryToCompile(sourceDirectories, targetDirectory, classPath, stdout)
|
||||
|
||||
/* Because Janino parser does not provide error handler for parsers:
|
||||
*
|
||||
@@ -31,14 +34,16 @@ class JaninoCompiler : Compiler {
|
||||
* as BuildException
|
||||
*/
|
||||
} catch (e: CompileException) {
|
||||
val locationIndex = e.location?.toString()?.length?.plus(2) ?: 0
|
||||
val message = e.message?.substring(locationIndex)
|
||||
val location = Location(e.location.fileName, e.location.lineNumber.toLong(), e.location.columnNumber.toLong())
|
||||
|
||||
throw BuildException(Severity.ERROR, TAG, location, message, e)
|
||||
stderr.println("[$TAG] ${e.message}")
|
||||
throw BuildException()
|
||||
}
|
||||
|
||||
private fun tryToCompile(sourceDirectories: Array<FileSystemNode>, targetDirectory: File, classPath: Array<File>) {
|
||||
private fun tryToCompile(
|
||||
sourceDirectories: Array<FileSystemNode>,
|
||||
targetDirectory: File,
|
||||
classPath: Array<File>,
|
||||
stdout: PrintStream
|
||||
) {
|
||||
val compilationUnits = sourceDirectories.flatMap(FileSystemNode::allChildren)
|
||||
.filter { it.type == FileType.FILE }
|
||||
.map(::FileNodeResourceAdapter)
|
||||
@@ -50,8 +55,7 @@ class JaninoCompiler : Compiler {
|
||||
setClassPath(classPath)
|
||||
|
||||
setWarningHandler { handle, message, loc ->
|
||||
val location = Location(loc.fileName, loc.lineNumber.toLong(), loc.columnNumber.toLong())
|
||||
eventbus.fire(AppendBuildLogsEvent(Severity.WARNING, "$message ($handle)", location, TAG))
|
||||
stdout.println("[$TAG] $message:$loc ($handle)")
|
||||
}
|
||||
|
||||
compile(compilationUnits)
|
||||
|
||||
@@ -2,7 +2,8 @@ package com.bartlomiejpluta.base.editor.code.build.database
|
||||
|
||||
import com.bartlomiejpluta.base.editor.project.model.Project
|
||||
import java.io.File
|
||||
import java.io.PrintStream
|
||||
|
||||
interface DatabaseAssembler {
|
||||
fun assembly(project: Project, targetJar: File)
|
||||
fun assembly(project: Project, targetJar: File, stdout: PrintStream, stderr: PrintStream)
|
||||
}
|
||||
@@ -2,12 +2,12 @@ package com.bartlomiejpluta.base.editor.code.build.database
|
||||
|
||||
import com.bartlomiejpluta.base.editor.code.build.exception.BuildException
|
||||
import com.bartlomiejpluta.base.editor.code.build.packager.JarPackager
|
||||
import com.bartlomiejpluta.base.editor.common.logs.enumeration.Severity
|
||||
import com.bartlomiejpluta.base.editor.database.service.DatabaseService
|
||||
import com.bartlomiejpluta.base.editor.project.model.Project
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.stereotype.Component
|
||||
import java.io.File
|
||||
import java.io.PrintStream
|
||||
|
||||
@Component
|
||||
class H2DatabaseAssembler : DatabaseAssembler {
|
||||
@@ -18,11 +18,12 @@ class H2DatabaseAssembler : DatabaseAssembler {
|
||||
@Autowired
|
||||
private lateinit var packager: JarPackager
|
||||
|
||||
override fun assembly(project: Project, targetJar: File) {
|
||||
override fun assembly(project: Project, targetJar: File, stdout: PrintStream, stderr: PrintStream) {
|
||||
try {
|
||||
tryToAssembly(project, targetJar)
|
||||
} catch (e: Exception) {
|
||||
throw BuildException(Severity.ERROR, TAG, e.message, e)
|
||||
stderr.println("[$TAG] ${e.message}")
|
||||
throw BuildException()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,3 @@
|
||||
package com.bartlomiejpluta.base.editor.code.build.exception
|
||||
|
||||
import com.bartlomiejpluta.base.editor.common.logs.enumeration.Severity
|
||||
import com.bartlomiejpluta.base.editor.common.logs.model.Location
|
||||
|
||||
class BuildException(
|
||||
val severity: Severity?,
|
||||
val tag: String?,
|
||||
val location: Location?,
|
||||
message: String?,
|
||||
override val cause: Throwable?
|
||||
) : Exception() {
|
||||
constructor(severity: Severity?, tag: String?, message: String?, cause: Throwable?)
|
||||
: this(severity, tag, null, message, cause)
|
||||
|
||||
constructor() : this(null, null, null, null, null)
|
||||
|
||||
override val message = message ?: ""
|
||||
}
|
||||
class BuildException : Exception()
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.bartlomiejpluta.base.editor.code.build.game
|
||||
|
||||
import com.bartlomiejpluta.base.editor.code.build.exception.BuildException
|
||||
import com.bartlomiejpluta.base.editor.common.logs.enumeration.Severity
|
||||
import org.springframework.stereotype.Component
|
||||
import java.io.File
|
||||
import java.io.PrintStream
|
||||
|
||||
/* TODO
|
||||
* There is an idea to have a different GameEngine providers for different OS (Windows, Mac OS X, Linux etc.)
|
||||
@@ -17,18 +17,19 @@ import java.io.File
|
||||
@Component
|
||||
class DefaultGameEngineProvider : GameEngineProvider {
|
||||
|
||||
override fun provideBaseGameEngine(targetJar: File) {
|
||||
override fun provideBaseGameEngine(targetJar: File, stdout: PrintStream, stderr: PrintStream) {
|
||||
try {
|
||||
tryToProvide(targetJar)
|
||||
} catch (e: Exception) {
|
||||
throw BuildException(Severity.ERROR, TAG, e.message, e)
|
||||
stderr.println("[$TAG] ${e.message}")
|
||||
throw BuildException()
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryToProvide(targetJar: File) {
|
||||
javaClass.getResourceAsStream(GAME_ENGINE_JAR).use { ris ->
|
||||
targetJar.outputStream().use { fos ->
|
||||
ris.copyTo(fos)
|
||||
ris?.copyTo(fos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package com.bartlomiejpluta.base.editor.code.build.game
|
||||
|
||||
import java.io.File
|
||||
import java.io.PrintStream
|
||||
|
||||
interface GameEngineProvider {
|
||||
fun provideBaseGameEngine(targetJar: File)
|
||||
fun provideBaseGameEngine(targetJar: File, stdout: PrintStream, stderr: PrintStream)
|
||||
}
|
||||
@@ -2,8 +2,10 @@ package com.bartlomiejpluta.base.editor.code.build.pipeline
|
||||
|
||||
import javafx.beans.property.BooleanProperty
|
||||
import javafx.concurrent.Task
|
||||
import java.io.OutputStream
|
||||
|
||||
interface BuildPipelineService {
|
||||
fun initStreams(stdout: OutputStream, stderr: OutputStream)
|
||||
val isRunningProperty: BooleanProperty
|
||||
fun build(): Task<Boolean>
|
||||
fun clean()
|
||||
|
||||
@@ -8,8 +8,6 @@ import com.bartlomiejpluta.base.editor.code.build.generator.CodeGenerator
|
||||
import com.bartlomiejpluta.base.editor.code.build.packager.JarPackager
|
||||
import com.bartlomiejpluta.base.editor.code.build.project.ProjectAssembler
|
||||
import com.bartlomiejpluta.base.editor.code.dependency.DependenciesProvider
|
||||
import com.bartlomiejpluta.base.editor.common.logs.enumeration.Severity
|
||||
import com.bartlomiejpluta.base.editor.event.AppendBuildLogsEvent
|
||||
import com.bartlomiejpluta.base.editor.event.ClearBuildLogsEvent
|
||||
import com.bartlomiejpluta.base.editor.file.model.FileSystemNode
|
||||
import com.bartlomiejpluta.base.editor.project.context.ProjectContext
|
||||
@@ -19,6 +17,8 @@ import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.stereotype.Component
|
||||
import tornadofx.*
|
||||
import tornadofx.FX.Companion.eventbus
|
||||
import java.io.OutputStream
|
||||
import java.io.PrintStream
|
||||
|
||||
@Component
|
||||
class DefaultBuildPipelineService : BuildPipelineService {
|
||||
@@ -50,6 +50,18 @@ class DefaultBuildPipelineService : BuildPipelineService {
|
||||
private val latchProperty = SimpleObjectProperty<Latch?>()
|
||||
private var latch by latchProperty
|
||||
|
||||
private lateinit var stdout: OutputStream
|
||||
private lateinit var stderr: OutputStream
|
||||
private lateinit var out: PrintStream
|
||||
private lateinit var err: PrintStream
|
||||
|
||||
override fun initStreams(stdout: OutputStream, stderr: OutputStream) {
|
||||
this.stdout = stdout
|
||||
this.stderr = stderr
|
||||
this.out = PrintStream(stdout)
|
||||
this.err = PrintStream(stderr)
|
||||
}
|
||||
|
||||
override val isRunningProperty = false.toProperty()
|
||||
private var isRunning by isRunningProperty
|
||||
|
||||
@@ -70,18 +82,18 @@ class DefaultBuildPipelineService : BuildPipelineService {
|
||||
|
||||
latch = Latch()
|
||||
|
||||
val startTime = System.currentTimeMillis()
|
||||
|
||||
try {
|
||||
projectContext.project?.let(this@DefaultBuildPipelineService::runPipeline)
|
||||
out.println("Build completed")
|
||||
return@runAsync true
|
||||
} catch (e: BuildException) {
|
||||
e.severity?.let {
|
||||
val event = AppendBuildLogsEvent(it, e.message, e.location, e.tag)
|
||||
eventbus.fire(event)
|
||||
}
|
||||
|
||||
eventbus.fire(AppendBuildLogsEvent(Severity.ERROR, "Build failed", tag = TAG))
|
||||
err.println("Build failed")
|
||||
} finally {
|
||||
latch?.release()
|
||||
val buildingTime = (System.currentTimeMillis() - startTime) / 1000.0
|
||||
out.println("Finished in [${buildingTime}s]")
|
||||
}
|
||||
|
||||
false
|
||||
@@ -92,35 +104,33 @@ class DefaultBuildPipelineService : BuildPipelineService {
|
||||
prepareBuildDirectory(project)
|
||||
|
||||
val outputFile = project.buildOutputJarFile
|
||||
val startTime = System.currentTimeMillis()
|
||||
|
||||
eventbus.fire(AppendBuildLogsEvent(Severity.INFO, "Providing compile-time dependencies...", tag = TAG))
|
||||
out.println("Providing compile-time dependencies...")
|
||||
val dependencies = dependenciesProvider.provideDependenciesTo(project.buildDependenciesDirectory)
|
||||
|
||||
eventbus.fire(AppendBuildLogsEvent(Severity.INFO, "Generating sources...", tag = TAG))
|
||||
out.println("Generating sources...")
|
||||
generators.forEach(CodeGenerator::generate)
|
||||
|
||||
eventbus.fire(AppendBuildLogsEvent(Severity.INFO, "Compiling sources...", tag = TAG))
|
||||
out.println("Compiling sources...")
|
||||
compiler.compile(
|
||||
arrayOf(project.codeFSNode, FileSystemNode(project.buildGeneratedCodeDirectory)),
|
||||
project.buildClassesDirectory,
|
||||
dependencies.toTypedArray()
|
||||
dependencies.toTypedArray(),
|
||||
out,
|
||||
err
|
||||
)
|
||||
|
||||
eventbus.fire(AppendBuildLogsEvent(Severity.INFO, "Assembling game engine...", tag = TAG))
|
||||
engineProvider.provideBaseGameEngine(outputFile)
|
||||
out.println("Assembling game engine...")
|
||||
engineProvider.provideBaseGameEngine(outputFile, out, err)
|
||||
|
||||
eventbus.fire(AppendBuildLogsEvent(Severity.INFO, "Assembling compiled classes...", tag = TAG))
|
||||
out.println("Linking compilation units...")
|
||||
packager.pack(project.buildClassesDirectory, outputFile, "BOOT-INF/classes")
|
||||
|
||||
eventbus.fire(AppendBuildLogsEvent(Severity.INFO, "Assembling project assets...", tag = TAG))
|
||||
projectAssembler.assembly(project, outputFile)
|
||||
out.println("Assembling project assets...")
|
||||
projectAssembler.assembly(project, outputFile, out, err)
|
||||
|
||||
eventbus.fire(AppendBuildLogsEvent(Severity.INFO, "Assembling database...", tag = TAG))
|
||||
databaseAssembler.assembly(project, outputFile)
|
||||
|
||||
val buildingTime = (System.currentTimeMillis() - startTime) / 1000.0
|
||||
eventbus.fire(AppendBuildLogsEvent(Severity.INFO, "Build done [${buildingTime}s]", tag = TAG))
|
||||
out.println("Assembling database...")
|
||||
databaseAssembler.assembly(project, outputFile, out, err)
|
||||
}
|
||||
|
||||
private fun prepareBuildDirectory(project: Project) {
|
||||
@@ -129,14 +139,11 @@ class DefaultBuildPipelineService : BuildPipelineService {
|
||||
project.buildClassesDirectory.mkdirs()
|
||||
project.buildOutDirectory.mkdirs()
|
||||
project.buildDependenciesDirectory.mkdirs()
|
||||
project.buildGeneratedCodeDirectory.mkdirs()
|
||||
}
|
||||
|
||||
override fun clean() {
|
||||
projectContext.project?.apply { buildDirectory.deleteRecursively() }
|
||||
eventbus.fire(AppendBuildLogsEvent(Severity.INFO, "Cleaning done", tag = TAG))
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "Build"
|
||||
out.println("Cleaning done")
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,11 @@ package com.bartlomiejpluta.base.editor.code.build.project
|
||||
|
||||
import com.bartlomiejpluta.base.editor.code.build.exception.BuildException
|
||||
import com.bartlomiejpluta.base.editor.code.build.packager.JarPackager
|
||||
import com.bartlomiejpluta.base.editor.common.logs.enumeration.Severity
|
||||
import com.bartlomiejpluta.base.editor.project.model.Project
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.stereotype.Component
|
||||
import java.io.File
|
||||
import java.io.PrintStream
|
||||
|
||||
@Component
|
||||
class DefaultProjectAssembler : ProjectAssembler {
|
||||
@@ -14,11 +14,12 @@ class DefaultProjectAssembler : ProjectAssembler {
|
||||
@Autowired
|
||||
private lateinit var packager: JarPackager
|
||||
|
||||
override fun assembly(project: Project, targetJar: File) {
|
||||
override fun assembly(project: Project, targetJar: File, stdout: PrintStream, stderr: PrintStream) {
|
||||
try {
|
||||
tryToAssembly(project, targetJar)
|
||||
} catch (e: Exception) {
|
||||
throw BuildException(Severity.ERROR, TAG, e.message, e)
|
||||
stderr.println("[$TAG] ${e.message}")
|
||||
throw BuildException()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@ package com.bartlomiejpluta.base.editor.code.build.project
|
||||
|
||||
import com.bartlomiejpluta.base.editor.project.model.Project
|
||||
import java.io.File
|
||||
import java.io.PrintStream
|
||||
|
||||
interface ProjectAssembler {
|
||||
fun assembly(project: Project, targetJar: File)
|
||||
fun assembly(project: Project, targetJar: File, stdout: PrintStream, stderr: PrintStream)
|
||||
}
|
||||
@@ -1,52 +1,31 @@
|
||||
package com.bartlomiejpluta.base.editor.code.view.build
|
||||
|
||||
import com.bartlomiejpluta.base.editor.code.build.pipeline.BuildPipelineService
|
||||
import com.bartlomiejpluta.base.editor.common.logs.component.LogsPane
|
||||
import com.bartlomiejpluta.base.editor.common.logs.model.Location
|
||||
import com.bartlomiejpluta.base.editor.event.AppendBuildLogsEvent
|
||||
import com.bartlomiejpluta.base.editor.event.ClearBuildLogsEvent
|
||||
import com.bartlomiejpluta.base.editor.main.controller.MainController
|
||||
import com.bartlomiejpluta.base.editor.project.context.ProjectContext
|
||||
import org.kordamp.ikonli.javafx.FontIcon
|
||||
import tornadofx.*
|
||||
import java.io.File
|
||||
import kotlin.math.max
|
||||
|
||||
class BuildLogsView : View() {
|
||||
private val projectContext: ProjectContext by di()
|
||||
private val mainController: MainController by di()
|
||||
private val pipelineService: BuildPipelineService by di()
|
||||
|
||||
private val followCaret = true.toProperty()
|
||||
|
||||
private val buildLogs = LogsPane(this::locationClick)
|
||||
private val logsPane = LogsPane()
|
||||
|
||||
init {
|
||||
subscribe<AppendBuildLogsEvent> { event ->
|
||||
buildLogs.appendEntry(event.message, event.severity, followCaret.value, event.location, event.tag)
|
||||
}
|
||||
|
||||
subscribe<ClearBuildLogsEvent> {
|
||||
buildLogs.clear()
|
||||
logsPane.clear()
|
||||
}
|
||||
}
|
||||
|
||||
private fun locationClick(location: Location) {
|
||||
projectContext.project?.codeFSNode?.findByFile(File(location.sourceName))?.let {
|
||||
mainController.openScript(it, max(1, location.lineNumber.toInt()), 1)
|
||||
}
|
||||
pipelineService.initStreams(logsPane.stdout, logsPane.stderr)
|
||||
}
|
||||
|
||||
override val root = borderpane {
|
||||
left = vbox {
|
||||
button(graphic = FontIcon("fa-trash")) {
|
||||
action { buildLogs.clear() }
|
||||
}
|
||||
|
||||
togglebutton {
|
||||
followCaret.bind(selectedProperty())
|
||||
graphic = FontIcon("fa-angle-double-down")
|
||||
action { logsPane.clear() }
|
||||
}
|
||||
}
|
||||
|
||||
center = buildLogs
|
||||
center = logsPane
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
package com.bartlomiejpluta.base.editor.common.logs.component
|
||||
|
||||
import com.bartlomiejpluta.base.editor.common.logs.enumeration.Severity
|
||||
import com.bartlomiejpluta.base.editor.common.logs.model.Location
|
||||
import com.bartlomiejpluta.base.editor.common.logs.style.LogsPaneStyle
|
||||
import com.bartlomiejpluta.base.editor.common.logs.stylesheet.LogsPaneStylesheet
|
||||
import javafx.scene.layout.StackPane
|
||||
import org.fxmisc.flowless.VirtualizedScrollPane
|
||||
import org.fxmisc.richtext.StyledTextArea
|
||||
import tornadofx.addClass
|
||||
import tornadofx.runLater
|
||||
import java.io.OutputStream
|
||||
|
||||
class LogsPane(private val locationClick: (location: Location) -> Unit = {}) : StackPane() {
|
||||
class LogsPane : StackPane() {
|
||||
private val editor = StyledTextArea("logs-pane",
|
||||
{ text, style -> text.addClass(style) },
|
||||
LogsPaneStyle.NO_STYLE,
|
||||
LogsPaneStyle.DEFAULT,
|
||||
{ text, style -> style.apply(text) }
|
||||
).apply { isEditable = false }
|
||||
|
||||
@@ -20,27 +20,25 @@ class LogsPane(private val locationClick: (location: Location) -> Unit = {}) : S
|
||||
children += VirtualizedScrollPane(editor)
|
||||
}
|
||||
|
||||
fun appendEntry(
|
||||
message: String,
|
||||
severity: Severity,
|
||||
follow: Boolean,
|
||||
location: Location? = null,
|
||||
tag: String? = null
|
||||
) {
|
||||
val locationRef = LogsPaneStyle(location = location, onClick = locationClick)
|
||||
val severityStyle = LogsPaneStyle(severity = severity)
|
||||
|
||||
tag?.let { editor.insert(editor.length, "[$it] ", severityStyle) }
|
||||
editor.insert(editor.length, location?.toString() ?: "", locationRef)
|
||||
editor.insert(editor.length, (location?.let { ": " } ?: "") + message, LogsPaneStyle(severity = severity))
|
||||
editor.insert(editor.length, "\n", LogsPaneStyle.NO_STYLE)
|
||||
|
||||
if (follow) {
|
||||
editor.requestFollowCaret()
|
||||
}
|
||||
}
|
||||
|
||||
fun clear() = editor.clear()
|
||||
|
||||
override fun getUserAgentStylesheet(): String = LogsPaneStylesheet().base64URL.toExternalForm()
|
||||
|
||||
val stdout = object : OutputStream() {
|
||||
override fun write(b: Int) {
|
||||
runLater {
|
||||
editor.insert(editor.length, (b.toChar()).toString(), LogsPaneStyle.DEFAULT)
|
||||
editor.requestFollowCaret()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val stderr = object : OutputStream() {
|
||||
override fun write(b: Int) {
|
||||
runLater {
|
||||
editor.insert(editor.length, (b.toChar()).toString(), LogsPaneStyle.ERROR)
|
||||
editor.requestFollowCaret()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package com.bartlomiejpluta.base.editor.common.logs.enumeration
|
||||
|
||||
enum class Severity {
|
||||
INFO,
|
||||
NOTE,
|
||||
WARNING,
|
||||
ERROR
|
||||
}
|
||||
@@ -1,43 +1,13 @@
|
||||
package com.bartlomiejpluta.base.editor.common.logs.style
|
||||
|
||||
import com.bartlomiejpluta.base.editor.common.logs.enumeration.Severity
|
||||
import com.bartlomiejpluta.base.editor.common.logs.model.Location
|
||||
import javafx.scene.Cursor
|
||||
import javafx.scene.paint.Color
|
||||
import javafx.scene.text.Text
|
||||
|
||||
class LogsPaneStyle(
|
||||
private val location: Location? = null,
|
||||
private val severity: Severity? = null,
|
||||
private val onClick: (Location) -> Unit = {}
|
||||
) {
|
||||
enum class LogsPaneStyle(private val color: Color?) {
|
||||
DEFAULT(null),
|
||||
ERROR(Color.RED);
|
||||
|
||||
fun apply(text: Text) = when {
|
||||
severity != null -> message(text, severity)
|
||||
location != null -> location(text, location)
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
|
||||
private fun message(text: Text, severity: Severity) {
|
||||
text.fill = when (severity) {
|
||||
Severity.WARNING -> Color.ORANGE
|
||||
Severity.ERROR -> Color.RED
|
||||
Severity.NOTE -> Color.DARKGRAY
|
||||
Severity.INFO -> text.fill
|
||||
}
|
||||
}
|
||||
|
||||
private fun location(text: Text, location: Location) {
|
||||
text.cursor = Cursor.HAND
|
||||
text.fill = Color.BLUE
|
||||
text.isUnderline = true
|
||||
text.setOnMouseClicked {
|
||||
onClick(location)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val NO_STYLE = LogsPaneStyle()
|
||||
fun apply(text: Text) {
|
||||
text.fill = color ?: text.fill
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package com.bartlomiejpluta.base.editor.event
|
||||
|
||||
import com.bartlomiejpluta.base.editor.common.logs.enumeration.Severity
|
||||
import com.bartlomiejpluta.base.editor.common.logs.model.Location
|
||||
import tornadofx.EventBus
|
||||
import tornadofx.FXEvent
|
||||
|
||||
data class AppendBuildLogsEvent(
|
||||
val severity: Severity,
|
||||
val message: String,
|
||||
val location: Location? = null,
|
||||
val tag: String? = null
|
||||
) : FXEvent(EventBus.RunOn.ApplicationThread)
|
||||
@@ -1,8 +0,0 @@
|
||||
package com.bartlomiejpluta.base.editor.event
|
||||
|
||||
import com.bartlomiejpluta.base.editor.common.logs.enumeration.Severity
|
||||
import tornadofx.EventBus
|
||||
import tornadofx.FXEvent
|
||||
|
||||
data class AppendProcessLogsEvent(val severity: Severity, val message: String) :
|
||||
FXEvent(EventBus.RunOn.ApplicationThread)
|
||||
@@ -8,8 +8,6 @@ import com.bartlomiejpluta.base.editor.code.viewmodel.CodeVM
|
||||
import com.bartlomiejpluta.base.editor.database.view.list.TablesListView
|
||||
import com.bartlomiejpluta.base.editor.database.view.query.QueryResultFragment
|
||||
import com.bartlomiejpluta.base.editor.database.viewmodel.QueryVM
|
||||
import com.bartlomiejpluta.base.editor.event.AppendBuildLogsEvent
|
||||
import com.bartlomiejpluta.base.editor.event.AppendProcessLogsEvent
|
||||
import com.bartlomiejpluta.base.editor.event.SelectMainViewTabEvent
|
||||
import com.bartlomiejpluta.base.editor.main.component.EditorTab
|
||||
import com.bartlomiejpluta.base.editor.main.controller.MainController
|
||||
@@ -94,14 +92,6 @@ class MainView : View("BASE Game Editor") {
|
||||
}.let { titleProperty.bind(it) }
|
||||
}
|
||||
|
||||
subscribe<AppendBuildLogsEvent> {
|
||||
buildLogItem.expanded = true
|
||||
}
|
||||
|
||||
subscribe<AppendProcessLogsEvent> {
|
||||
processLogItem.expanded = true
|
||||
}
|
||||
|
||||
subscribe<SelectMainViewTabEvent> { event ->
|
||||
openTabs[event.targetScope]?.let {
|
||||
tabPane.selectionModel.select(it)
|
||||
|
||||
@@ -2,8 +2,10 @@ package com.bartlomiejpluta.base.editor.process.runner.app
|
||||
|
||||
import javafx.beans.binding.BooleanExpression
|
||||
import javafx.beans.property.ObjectProperty
|
||||
import java.io.OutputStream
|
||||
|
||||
interface ApplicationRunner {
|
||||
fun initStreams(stdout: OutputStream, stderr: OutputStream)
|
||||
val isRunningProperty: BooleanExpression
|
||||
val processProperty: ObjectProperty<Process>
|
||||
fun run()
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package com.bartlomiejpluta.base.editor.process.runner.app
|
||||
|
||||
import com.bartlomiejpluta.base.editor.code.build.pipeline.BuildPipelineService
|
||||
import com.bartlomiejpluta.base.editor.common.logs.enumeration.Severity
|
||||
import com.bartlomiejpluta.base.editor.event.AppendProcessLogsEvent
|
||||
import com.bartlomiejpluta.base.editor.event.ClearProcessLogsEvent
|
||||
import com.bartlomiejpluta.base.editor.process.runner.jar.JarRunner
|
||||
import com.bartlomiejpluta.base.editor.project.context.ProjectContext
|
||||
@@ -10,8 +8,14 @@ import com.bartlomiejpluta.base.editor.project.model.Project
|
||||
import javafx.beans.property.SimpleObjectProperty
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.stereotype.Component
|
||||
import tornadofx.*
|
||||
import tornadofx.FX.Companion.eventbus
|
||||
import tornadofx.getValue
|
||||
import tornadofx.runAsync
|
||||
import tornadofx.setValue
|
||||
import tornadofx.toProperty
|
||||
import java.io.IOException
|
||||
import java.io.OutputStream
|
||||
import java.io.PrintStream
|
||||
|
||||
@Component
|
||||
class DefaultApplicationRunner : ApplicationRunner {
|
||||
@@ -25,12 +29,25 @@ class DefaultApplicationRunner : ApplicationRunner {
|
||||
@Autowired
|
||||
private lateinit var jarRunner: JarRunner
|
||||
|
||||
override val isRunningProperty = false.toProperty()
|
||||
private var isRunning by isRunningProperty
|
||||
private lateinit var stdout: OutputStream
|
||||
private lateinit var stderr: OutputStream
|
||||
private lateinit var out: PrintStream
|
||||
private lateinit var err: PrintStream
|
||||
|
||||
override val isRunningProperty = false.toProperty()
|
||||
|
||||
private var isRunning by isRunningProperty
|
||||
override val processProperty = SimpleObjectProperty<Process>()
|
||||
|
||||
private var process by processProperty
|
||||
|
||||
override fun initStreams(stdout: OutputStream, stderr: OutputStream) {
|
||||
this.stdout = stdout
|
||||
this.stderr = stderr
|
||||
this.out = PrintStream(stdout)
|
||||
this.err = PrintStream(stderr)
|
||||
}
|
||||
|
||||
override fun run() {
|
||||
projectContext.project?.let { project ->
|
||||
if (process != null) {
|
||||
@@ -65,19 +82,16 @@ class DefaultApplicationRunner : ApplicationRunner {
|
||||
process = builder.start()
|
||||
|
||||
runAsync {
|
||||
process.inputStream.bufferedReader().forEachLine {
|
||||
eventbus.fire(AppendProcessLogsEvent(Severity.INFO, it))
|
||||
}
|
||||
}
|
||||
|
||||
runAsync {
|
||||
process.errorStream.bufferedReader().forEachLine {
|
||||
eventbus.fire(AppendProcessLogsEvent(Severity.ERROR, it))
|
||||
try {
|
||||
process.inputStream.transferTo(stdout)
|
||||
process.errorStream.transferTo(stderr)
|
||||
} catch (e: IOException) {
|
||||
// Ignore stream termination exception
|
||||
}
|
||||
}
|
||||
|
||||
process.onExit().thenApply {
|
||||
eventbus.fire(AppendProcessLogsEvent(Severity.INFO, "\nProcess exited with code ${it.exitValue()}"))
|
||||
out.println("\nProcess exited with code ${it.exitValue()}")
|
||||
process = null
|
||||
isRunning = false
|
||||
}
|
||||
|
||||
@@ -1,38 +1,32 @@
|
||||
package com.bartlomiejpluta.base.editor.process.view
|
||||
|
||||
import com.bartlomiejpluta.base.editor.common.logs.component.LogsPane
|
||||
import com.bartlomiejpluta.base.editor.event.AppendProcessLogsEvent
|
||||
import com.bartlomiejpluta.base.editor.event.ClearProcessLogsEvent
|
||||
import com.bartlomiejpluta.base.editor.process.runner.app.ApplicationRunner
|
||||
import org.kordamp.ikonli.javafx.FontIcon
|
||||
import tornadofx.*
|
||||
|
||||
|
||||
class ProcessLogsView : View() {
|
||||
private val buildLogs = LogsPane()
|
||||
private val followCaret = true.toProperty()
|
||||
private val logsPane = LogsPane()
|
||||
|
||||
private val applicationRunner: ApplicationRunner by di()
|
||||
|
||||
init {
|
||||
subscribe<AppendProcessLogsEvent> { event ->
|
||||
buildLogs.appendEntry(event.message, event.severity, followCaret.value)
|
||||
subscribe<ClearProcessLogsEvent> {
|
||||
logsPane.clear()
|
||||
}
|
||||
|
||||
subscribe<ClearProcessLogsEvent> {
|
||||
buildLogs.clear()
|
||||
}
|
||||
applicationRunner.initStreams(logsPane.stdout, logsPane.stderr)
|
||||
}
|
||||
|
||||
override val root = borderpane {
|
||||
left = vbox {
|
||||
button(graphic = FontIcon("fa-trash")) {
|
||||
action { buildLogs.clear() }
|
||||
}
|
||||
|
||||
togglebutton {
|
||||
followCaret.bind(selectedProperty())
|
||||
graphic = FontIcon("fa-angle-double-down")
|
||||
action { logsPane.clear() }
|
||||
}
|
||||
}
|
||||
|
||||
center = buildLogs
|
||||
center = logsPane
|
||||
}
|
||||
}
|
||||
@@ -176,7 +176,7 @@ class Project {
|
||||
const val FONTS_DIR = "fonts"
|
||||
const val WIDGETS_DIR = "widgets"
|
||||
const val AUDIO_DIR = "audio"
|
||||
const val CODE_DIR = "code"
|
||||
const val CODE_DIR = "src/main/java"
|
||||
const val BUILD_DIR = "build"
|
||||
const val BUILD_CLASSES_DIR = "$BUILD_DIR/classes"
|
||||
const val BUILD_OUT_DIR = "$BUILD_DIR/out"
|
||||
|
||||
@@ -42,7 +42,6 @@ configurations {
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
bootJar {
|
||||
|
||||
@@ -5,7 +5,9 @@ slf4jVersion=1.7.30
|
||||
lombokVersion=1.18.22
|
||||
jomlVersion=1.10.0
|
||||
guavaVersion=29.0-jre
|
||||
kotlinJvmVersion=1.6.0-M1
|
||||
javaFxVersion=15.0.1
|
||||
javaFxPluginVersion=0.0.10
|
||||
tornadoFxVersion=2.0.0-SNAPSHOT
|
||||
ikonliVersion=12.2.0
|
||||
protobufPluginVersion=0.8.14
|
||||
|
||||
Reference in New Issue
Block a user