diff --git a/api/build.gradle b/api/build.gradle index 58300c56..19ebdde7 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -11,9 +11,4 @@ repositories { dependencies { implementation "org.joml:joml:${jomlVersion}" -} - -task relayDependencies(type: Copy) { - from configurations.runtimeClasspath - into file("build/dependencies") } \ No newline at end of file diff --git a/editor/build.gradle b/editor/build.gradle index aa617105..5e5afe61 100644 --- a/editor/build.gradle +++ b/editor/build.gradle @@ -32,7 +32,9 @@ compileTestKotlin { } dependencies { + implementation project(":api") implementation project(":proto") + implementation "org.jetbrains.kotlin:kotlin-stdlib" implementation "no.tornado:tornadofx:${tornadoFxVersion}" implementation platform("org.kordamp.ikonli:ikonli-bom:${ikonliVersion}") @@ -55,14 +57,15 @@ task provideGameEngine(type: Copy) { into file("build/resources/main/engine") } -task provideApiDependencies(type: Copy) { - dependsOn(":api:relayDependencies") +task provideAPIWithDependences(type: Copy) { + dependsOn(":api:build") - from project(':api').file('build/dependencies') + from project(':api').file('build/libs') + from project(':api').configurations.runtimeClasspath into file("build/resources/main/dependencies") } -task provideApi(type: Copy) { +task provideAPISources(type: Copy) { from project(':api').file('src/main/java') into file('build/resources/main/api') @@ -81,6 +84,6 @@ task provideApi(type: Copy) { processResources { dependsOn(provideGameEngine) - dependsOn(provideApiDependencies) - dependsOn(provideApi) + dependsOn(provideAPIWithDependences) + dependsOn(provideAPISources) } \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/compiler/JDKCompiler.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/compiler/JDKCompiler.kt new file mode 100644 index 00000000..280c083c --- /dev/null +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/compiler/JDKCompiler.kt @@ -0,0 +1,66 @@ +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 org.springframework.context.annotation.Primary +import org.springframework.stereotype.Component +import tornadofx.FX +import java.io.File +import java.util.* +import javax.tools.Diagnostic +import javax.tools.DiagnosticCollector +import javax.tools.JavaFileObject +import javax.tools.ToolProvider + +@Primary +@Component +class JDKCompiler : Compiler { + private val compiler = ToolProvider.getSystemJavaCompiler() + + override fun compile(sourceDirectory: FileSystemNode, targetDirectory: File, classPath: Array) { + val classpath = classPath.joinToString(";") { it.absolutePath } + val options = listOf("-g", "-d", targetDirectory.absolutePath, "-classpath", classpath) + + val collector = DiagnosticCollector() + + val manager = compiler.getStandardFileManager(collector, null, null) + val sources = sourceDirectory.allChildren + .filter { it.type == FileType.FILE } + .mapNotNull { it as? FileSystemNode } + .map { it.file } + .let { manager.getJavaFileObjects(*it.toTypedArray()) } + + val task = compiler.getTask(null, manager, collector, options, null, sources) + + val success = task.call() + + collector.diagnostics.forEach(this::fireDiagnosticEvent) + + if (!success) { + throw BuildException() + } + } + + private fun fireDiagnosticEvent(diagnostic: Diagnostic) { + 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 + } + + val location = Location(diagnostic.source.name, diagnostic.lineNumber, diagnostic.columnNumber) + + + FX.eventbus.fire(AppendBuildLogsEvent(severity, diagnostic.getMessage(null), location, TAG)) + } + + companion object { + private const val TAG = "Compiler" + } +} \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/compiler/JaninoCompiler.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/compiler/JaninoCompiler.kt index 2ea11a14..fb8b9e61 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/compiler/JaninoCompiler.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/compiler/JaninoCompiler.kt @@ -1,16 +1,14 @@ 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.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.commons.compiler.util.resource.Resource import org.codehaus.janino.CompilerFactory -import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Component import tornadofx.FX.Companion.eventbus import java.io.File @@ -19,9 +17,6 @@ import java.io.File class JaninoCompiler : Compiler { private val compilerFactory = CompilerFactory() - @Autowired - private lateinit var apiProvider: APIProvider - override fun compile(sourceDirectory: FileSystemNode, targetDirectory: File, classPath: Array) = try { tryToCompile(sourceDirectory, targetDirectory, classPath) @@ -38,32 +33,32 @@ class JaninoCompiler : Compiler { } 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, "Compiler", e.location, message, e) + throw BuildException(Severity.ERROR, TAG, location, message, e) } private fun tryToCompile(sourceDirectory: FileSystemNode, targetDirectory: File, classPath: Array) { - val compilationUnits = prepareCompilationUnits(sourceDirectory) + val compilationUnits = sourceDirectory.allChildren + .filter { it.type == FileType.FILE } + .map(::FileNodeResourceAdapter) + .toTypedArray() compilerFactory.newCompiler().apply { setDestinationDirectory(targetDirectory, false) setClassPath(classPath) - setWarningHandler { handle, message, location -> - eventbus.fire(AppendBuildLogsEvent(Severity.WARNING, "$message ($handle)", location, "Compiler")) + setWarningHandler { handle, message, loc -> + val location = Location(loc.fileName, loc.lineNumber.toLong(), loc.columnNumber.toLong()) + eventbus.fire(AppendBuildLogsEvent(Severity.WARNING, "$message ($handle)", location, TAG)) } compile(compilationUnits) } } - private fun prepareCompilationUnits(sourceDirectory: FileSystemNode): Array { - val sources = sourceDirectory.allChildren - val api = apiProvider.apiNode.allChildren - return (sources + api) - .filter { it.type == FileType.FILE } - .map(::FileNodeResourceAdapter) - .toTypedArray() + companion object { + private const val TAG = "Compiler" } } diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/exception/BuildException.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/exception/BuildException.kt index a62ce85f..c67b0ff4 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/exception/BuildException.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/exception/BuildException.kt @@ -1,17 +1,19 @@ package com.bartlomiejpluta.base.editor.code.build.exception import com.bartlomiejpluta.base.editor.common.logs.enumeration.Severity -import org.codehaus.commons.compiler.Location +import com.bartlomiejpluta.base.editor.common.logs.model.Location class BuildException( - val severity: Severity, - val tag: String, + val severity: Severity?, + val tag: String?, val location: Location?, message: String?, - override val cause: Throwable + override val cause: Throwable? ) : Exception() { - constructor(severity: Severity, tag: String, message: String?, cause: Throwable) + 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 ?: "" } \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/game/DefaultGameEngineProvider.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/game/DefaultGameEngineProvider.kt index 97447378..5cc044e2 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/game/DefaultGameEngineProvider.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/game/DefaultGameEngineProvider.kt @@ -21,7 +21,7 @@ class DefaultGameEngineProvider : GameEngineProvider { try { tryToProvide(targetJar) } catch (e: Exception) { - throw BuildException(Severity.ERROR, "Engine Provider", e.message, e) + throw BuildException(Severity.ERROR, TAG, e.message, e) } } @@ -35,5 +35,6 @@ class DefaultGameEngineProvider : GameEngineProvider { companion object { private const val GAME_ENGINE_JAR = "/engine/engine.jar" + private const val TAG = "Engine Provider" } } \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/pipeline/BuildPipelineService.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/pipeline/BuildPipelineService.kt index 6ba456e1..deb24d95 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/pipeline/BuildPipelineService.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/pipeline/BuildPipelineService.kt @@ -5,6 +5,6 @@ import javafx.concurrent.Task interface BuildPipelineService { val isRunningProperty: BooleanProperty - fun build(): Task + fun build(): Task fun clean() } \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/pipeline/DefaultBuildPipelineService.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/pipeline/DefaultBuildPipelineService.kt index 76162341..ec1edcf5 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/pipeline/DefaultBuildPipelineService.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/pipeline/DefaultBuildPipelineService.kt @@ -56,21 +56,26 @@ class DefaultBuildPipelineService : BuildPipelineService { override fun build() = runAsync { latch?.locked?.takeIf { it }?.let { cancel() - return@runAsync + return@runAsync false } latch = Latch() try { projectContext.project?.let(this@DefaultBuildPipelineService::runPipeline) + return@runAsync true } catch (e: BuildException) { - val event = AppendBuildLogsEvent(e.severity, e.message, e.location, e.tag) - eventbus.fire(event) + 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)) } finally { latch?.release() } - Unit + false } private fun runPipeline(project: Project) { diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/project/DefaultProjectAssembler.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/project/DefaultProjectAssembler.kt index 39bc8c54..105c637a 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/project/DefaultProjectAssembler.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/project/DefaultProjectAssembler.kt @@ -18,7 +18,7 @@ class DefaultProjectAssembler : ProjectAssembler { try { tryToAssembly(project, targetJar) } catch (e: Exception) { - throw BuildException(Severity.ERROR, "Project Assembler", e.message, e) + throw BuildException(Severity.ERROR, TAG, e.message, e) } } @@ -29,4 +29,8 @@ class DefaultProjectAssembler : ProjectAssembler { packager.pack(project.entitySetsDirectory, targetJar, "BOOT-INF/classes/project/entsets") packager.copy(project.projectFile, targetJar, "BOOT-INF/classes/project") } + + companion object { + private const val TAG = "Project Assembler" + } } \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/view/build/BuildLogsView.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/view/build/BuildLogsView.kt index ee18eab7..2ec4f886 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/view/build/BuildLogsView.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/view/build/BuildLogsView.kt @@ -1,14 +1,15 @@ package com.bartlomiejpluta.base.editor.code.view.build 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.codehaus.commons.compiler.Location 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() @@ -29,8 +30,8 @@ class BuildLogsView : View() { } private fun locationClick(location: Location) { - projectContext.project?.codeFSNode?.findByFile(File(location.fileName))?.let { - mainController.openScript(it, location.lineNumber, 1) + projectContext.project?.codeFSNode?.findByFile(File(location.sourceName))?.let { + mainController.openScript(it, max(1, location.lineNumber.toInt()), 1) } } diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/common/logs/component/LogsPane.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/common/logs/component/LogsPane.kt index 3a1a6790..0e181bde 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/common/logs/component/LogsPane.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/common/logs/component/LogsPane.kt @@ -1,10 +1,10 @@ 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.codehaus.commons.compiler.Location import org.fxmisc.flowless.VirtualizedScrollPane import org.fxmisc.richtext.StyledTextArea import tornadofx.addClass diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/common/logs/enumeration/Severity.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/common/logs/enumeration/Severity.kt index b7408f85..34e7d11d 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/common/logs/enumeration/Severity.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/common/logs/enumeration/Severity.kt @@ -2,6 +2,7 @@ package com.bartlomiejpluta.base.editor.common.logs.enumeration enum class Severity { INFO, + NOTE, WARNING, ERROR } \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/common/logs/model/Location.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/common/logs/model/Location.kt new file mode 100644 index 00000000..2df065a6 --- /dev/null +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/common/logs/model/Location.kt @@ -0,0 +1,5 @@ +package com.bartlomiejpluta.base.editor.common.logs.model + +data class Location(val sourceName: String, val lineNumber: Long, val columnNumber: Long) { + override fun toString() = if(lineNumber < 1) sourceName else "$sourceName:$lineNumber,$columnNumber" +} \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/common/logs/style/LogsPaneStyle.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/common/logs/style/LogsPaneStyle.kt index d7022205..a386b642 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/common/logs/style/LogsPaneStyle.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/common/logs/style/LogsPaneStyle.kt @@ -1,10 +1,10 @@ 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 -import org.codehaus.commons.compiler.Location class LogsPaneStyle( private val location: Location? = null, @@ -23,6 +23,7 @@ class LogsPaneStyle( text.fill = when (severity) { Severity.WARNING -> Color.ORANGE Severity.ERROR -> Color.RED + Severity.NOTE -> Color.DARKGRAY Severity.INFO -> text.fill } } diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/event/AppendBuildLogsEvent.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/event/AppendBuildLogsEvent.kt index 455e73a8..d4df6a71 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/event/AppendBuildLogsEvent.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/event/AppendBuildLogsEvent.kt @@ -1,7 +1,7 @@ package com.bartlomiejpluta.base.editor.event import com.bartlomiejpluta.base.editor.common.logs.enumeration.Severity -import org.codehaus.commons.compiler.Location +import com.bartlomiejpluta.base.editor.common.logs.model.Location import tornadofx.EventBus import tornadofx.FXEvent diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/process/runner/app/DefaultApplicationRunner.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/process/runner/app/DefaultApplicationRunner.kt index 013c0e05..d3bb4f03 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/process/runner/app/DefaultApplicationRunner.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/process/runner/app/DefaultApplicationRunner.kt @@ -8,7 +8,6 @@ import com.bartlomiejpluta.base.editor.process.runner.jar.JarRunner import com.bartlomiejpluta.base.editor.project.context.ProjectContext import com.bartlomiejpluta.base.editor.project.model.Project import javafx.beans.property.SimpleObjectProperty -import javafx.event.EventHandler import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Component import tornadofx.* @@ -43,7 +42,14 @@ class DefaultApplicationRunner : ApplicationRunner { if (project.buildOutputJarFile.exists() && project.buildOutputJarFile.isFile) { runApplication(project) } else { - pipelineService.build().onSucceeded = EventHandler { runApplication(project) } + val build = pipelineService.build() + build.setOnSucceeded { + if (build.value) { + runApplication(project) + } else { + isRunning = false + } + } } } } diff --git a/editor/src/main/resources/java_templates/game_runner.ftl b/editor/src/main/resources/java_templates/game_runner.ftl index b4ed7d66..30f77366 100644 --- a/editor/src/main/resources/java_templates/game_runner.ftl +++ b/editor/src/main/resources/java_templates/game_runner.ftl @@ -1,7 +1,7 @@ package ${package}; -import com.bartlomiejpluta.base.api.runner.GameRunner; -import com.bartlomiejpluta.base.api.context.Context; +import com.bartlomiejpluta.base.api.game.runner.GameRunner; +import com.bartlomiejpluta.base.api.game.context.Context; public class ${className} implements GameRunner {