mirror of
https://github.com/ethauvin/kobalt.git
synced 2025-04-26 16:28:12 -07:00
Modify commands to report errors to the IDEA plug-in.
This commit is contained in:
parent
806ca59f97
commit
ce435adf25
7 changed files with 68 additions and 33 deletions
|
@ -17,7 +17,7 @@ interface ICommand {
|
||||||
*/
|
*/
|
||||||
fun run(sender: ICommandSender, received: JsonObject)
|
fun run(sender: ICommandSender, received: JsonObject)
|
||||||
|
|
||||||
fun toCommandData(data: String) = CommandData(name, data)
|
fun toCommandData(data: String, error: String? = null) = CommandData(name, data, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.beust.kobalt.internal.remote
|
package com.beust.kobalt.internal.remote
|
||||||
|
|
||||||
import com.beust.kobalt.misc.log
|
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import com.beust.kobalt.api.Kobalt
|
||||||
import com.beust.kobalt.api.PluginTask
|
import com.beust.kobalt.api.PluginTask
|
||||||
import com.beust.kobalt.api.Project
|
import com.beust.kobalt.api.Project
|
||||||
import com.beust.kobalt.app.*
|
import com.beust.kobalt.app.*
|
||||||
|
import com.beust.kobalt.app.remote.DependencyData
|
||||||
import com.beust.kobalt.app.remote.KobaltClient
|
import com.beust.kobalt.app.remote.KobaltClient
|
||||||
import com.beust.kobalt.app.remote.KobaltServer
|
import com.beust.kobalt.app.remote.KobaltServer
|
||||||
import com.beust.kobalt.internal.KobaltSettings
|
import com.beust.kobalt.internal.KobaltSettings
|
||||||
|
@ -65,6 +66,7 @@ private class Main @Inject constructor(
|
||||||
val pluginInfo: PluginInfo,
|
val pluginInfo: PluginInfo,
|
||||||
val projectGenerator: ProjectGenerator,
|
val projectGenerator: ProjectGenerator,
|
||||||
val depFactory: DepFactory,
|
val depFactory: DepFactory,
|
||||||
|
val dependencyData: DependencyData,
|
||||||
val resolveDependency: ResolveDependency) {
|
val resolveDependency: ResolveDependency) {
|
||||||
|
|
||||||
data class RunInfo(val jc: JCommander, val args: Args)
|
data class RunInfo(val jc: JCommander, val args: Args)
|
||||||
|
@ -88,7 +90,7 @@ private class Main @Inject constructor(
|
||||||
return pluginClassLoader
|
return pluginClassLoader
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun run(jc: JCommander, args: Args, argv: Array<String>): Int {
|
fun run(jc: JCommander, args: Args, argv: Array<String>): Int {
|
||||||
//
|
//
|
||||||
// Install plug-ins requested from the command line
|
// Install plug-ins requested from the command line
|
||||||
//
|
//
|
||||||
|
@ -101,6 +103,9 @@ private class Main @Inject constructor(
|
||||||
//
|
//
|
||||||
pluginInfo.plugins.forEach { Plugins.addPluginInstance(it) }
|
pluginInfo.plugins.forEach { Plugins.addPluginInstance(it) }
|
||||||
|
|
||||||
|
// val data = dependencyData.dependenciesDataFor(homeDir("kotlin/klaxon/kobalt/src/Build.kt"), Args())
|
||||||
|
// println("Data: $data")
|
||||||
|
|
||||||
// --listTemplates
|
// --listTemplates
|
||||||
if (args.listTemplates) {
|
if (args.listTemplates) {
|
||||||
Templates().list(pluginInfo)
|
Templates().list(pluginInfo)
|
||||||
|
@ -174,8 +179,14 @@ private class Main @Inject constructor(
|
||||||
if (!buildFile.exists()) {
|
if (!buildFile.exists()) {
|
||||||
error(buildFile.path.toFile().path + " does not exist")
|
error(buildFile.path.toFile().path + " does not exist")
|
||||||
} else {
|
} else {
|
||||||
val allProjects = buildFileCompilerFactory.create(listOf(buildFile), pluginInfo)
|
val findProjectResult = buildFileCompilerFactory.create(listOf(buildFile), pluginInfo)
|
||||||
.compileBuildFiles(args)
|
.compileBuildFiles(args)
|
||||||
|
if (! findProjectResult.taskResult.success) {
|
||||||
|
throw KobaltException("Couldn't compile build file: "
|
||||||
|
+ findProjectResult.taskResult.errorMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
val allProjects = findProjectResult.projects
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now that we have projects, add all the repos from repo contributors that need a Project
|
// Now that we have projects, add all the repos from repo contributors that need a Project
|
||||||
|
|
|
@ -2,8 +2,8 @@ package com.beust.kobalt.app
|
||||||
|
|
||||||
import com.beust.kobalt.Args
|
import com.beust.kobalt.Args
|
||||||
import com.beust.kobalt.Constants
|
import com.beust.kobalt.Constants
|
||||||
import com.beust.kobalt.KobaltException
|
|
||||||
import com.beust.kobalt.Plugins
|
import com.beust.kobalt.Plugins
|
||||||
|
import com.beust.kobalt.TaskResult
|
||||||
import com.beust.kobalt.api.Kobalt
|
import com.beust.kobalt.api.Kobalt
|
||||||
import com.beust.kobalt.api.KobaltContext
|
import com.beust.kobalt.api.KobaltContext
|
||||||
import com.beust.kobalt.api.PluginProperties
|
import com.beust.kobalt.api.PluginProperties
|
||||||
|
@ -39,7 +39,7 @@ public class BuildFileCompiler @Inject constructor(@Assisted("buildFiles") val b
|
||||||
|
|
||||||
private val SCRIPT_JAR = "buildScript.jar"
|
private val SCRIPT_JAR = "buildScript.jar"
|
||||||
|
|
||||||
fun compileBuildFiles(args: Args): List<Project> {
|
fun compileBuildFiles(args: Args): FindProjectResult {
|
||||||
//
|
//
|
||||||
// Create the KobaltContext
|
// Create the KobaltContext
|
||||||
//
|
//
|
||||||
|
@ -54,16 +54,21 @@ public class BuildFileCompiler @Inject constructor(@Assisted("buildFiles") val b
|
||||||
//
|
//
|
||||||
// Find all the projects in the build file, possibly compiling them
|
// Find all the projects in the build file, possibly compiling them
|
||||||
//
|
//
|
||||||
val allProjects = findProjects(context)
|
val projectResult = findProjects(context)
|
||||||
plugins.applyPlugins(context, allProjects)
|
if (projectResult.taskResult.success) {
|
||||||
|
plugins.applyPlugins(context, projectResult.projects)
|
||||||
|
}
|
||||||
|
|
||||||
return allProjects
|
return projectResult
|
||||||
}
|
}
|
||||||
|
|
||||||
val parsedBuildFiles = arrayListOf<ParsedBuildFile>()
|
val parsedBuildFiles = arrayListOf<ParsedBuildFile>()
|
||||||
|
|
||||||
private fun findProjects(context: KobaltContext): List<Project> {
|
class FindProjectResult(val projects: List<Project>, val taskResult: TaskResult)
|
||||||
val result = arrayListOf<Project>()
|
|
||||||
|
private fun findProjects(context: KobaltContext): FindProjectResult {
|
||||||
|
var errorTaskResult: TaskResult? = null
|
||||||
|
val projects = arrayListOf<Project>()
|
||||||
buildFiles.forEach { buildFile ->
|
buildFiles.forEach { buildFile ->
|
||||||
val parsedBuildFile = parseBuildFile(context, buildFile)
|
val parsedBuildFile = parseBuildFile(context, buildFile)
|
||||||
parsedBuildFiles.add(parsedBuildFile)
|
parsedBuildFiles.add(parsedBuildFile)
|
||||||
|
@ -83,35 +88,39 @@ public class BuildFileCompiler @Inject constructor(@Assisted("buildFiles") val b
|
||||||
// compile it, jar it in buildScript.jar and run it
|
// compile it, jar it in buildScript.jar and run it
|
||||||
val modifiedBuildFile = KFiles.createTempFile(".kt")
|
val modifiedBuildFile = KFiles.createTempFile(".kt")
|
||||||
KFiles.saveFile(modifiedBuildFile, parsedBuildFile.buildScriptCode)
|
KFiles.saveFile(modifiedBuildFile, parsedBuildFile.buildScriptCode)
|
||||||
maybeCompileBuildFile(context, BuildFile(Paths.get(modifiedBuildFile.path),
|
val taskResult = maybeCompileBuildFile(context, BuildFile(Paths.get(modifiedBuildFile.path),
|
||||||
"Modified ${Constants.BUILD_FILE_NAME}", buildFile.realPath),
|
"Modified ${Constants.BUILD_FILE_NAME}", buildFile.realPath),
|
||||||
buildScriptJarFile, pluginUrls)
|
buildScriptJarFile, pluginUrls)
|
||||||
val projects = buildScriptUtil.runBuildScriptJarFile(buildScriptJarFile, pluginUrls, context)
|
if (taskResult.success) {
|
||||||
result.addAll(projects)
|
projects.addAll(buildScriptUtil.runBuildScriptJarFile(buildScriptJarFile, pluginUrls, context))
|
||||||
|
} else {
|
||||||
|
if (errorTaskResult == null) {
|
||||||
|
errorTaskResult = taskResult
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result
|
return FindProjectResult(projects, if (errorTaskResult != null) errorTaskResult!! else TaskResult())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun maybeCompileBuildFile(context: KobaltContext, buildFile: BuildFile, buildScriptJarFile: File,
|
private fun maybeCompileBuildFile(context: KobaltContext, buildFile: BuildFile, buildScriptJarFile: File,
|
||||||
pluginUrls: List<URL>) {
|
pluginUrls: List<URL>) : TaskResult {
|
||||||
log(2, "Running build file ${buildFile.name} jar: $buildScriptJarFile")
|
log(2, "Running build file ${buildFile.name} jar: $buildScriptJarFile")
|
||||||
|
|
||||||
if (buildScriptUtil.isUpToDate(buildFile, buildScriptJarFile)) {
|
if (buildScriptUtil.isUpToDate(buildFile, buildScriptJarFile)) {
|
||||||
log(2, "Build file is up to date")
|
log(2, "Build file is up to date")
|
||||||
|
return TaskResult()
|
||||||
} else {
|
} else {
|
||||||
log(2, "Need to recompile ${buildFile.name}")
|
log(2, "Need to recompile ${buildFile.name}")
|
||||||
|
|
||||||
buildScriptJarFile.delete()
|
buildScriptJarFile.delete()
|
||||||
kotlinCompilePrivate {
|
val result = kotlinCompilePrivate {
|
||||||
classpath(files.kobaltJar)
|
classpath(files.kobaltJar)
|
||||||
classpath(pluginUrls.map { it.file })
|
classpath(pluginUrls.map { it.file })
|
||||||
sourceFiles(listOf(buildFile.path.toFile().absolutePath))
|
sourceFiles(listOf(buildFile.path.toFile().absolutePath))
|
||||||
output = buildScriptJarFile
|
output = buildScriptJarFile
|
||||||
}.compile(context = context)
|
}.compile(context = context)
|
||||||
|
|
||||||
if (! buildScriptJarFile.exists()) {
|
return result
|
||||||
throw KobaltException("Could not compile ${buildFile.name}")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,11 +31,11 @@ class DependencyData @Inject constructor(val executors: KobaltExecutors, val dep
|
||||||
|
|
||||||
val buildFile = BuildFile(Paths.get(buildFilePath), "GetDependenciesCommand")
|
val buildFile = BuildFile(Paths.get(buildFilePath), "GetDependenciesCommand")
|
||||||
val buildFileCompiler = buildFileCompilerFactory.create(listOf(buildFile), pluginInfo)
|
val buildFileCompiler = buildFileCompilerFactory.create(listOf(buildFile), pluginInfo)
|
||||||
val projects = buildFileCompiler.compileBuildFiles(args)
|
val projectResult = buildFileCompiler.compileBuildFiles(args)
|
||||||
val pluginUrls = buildFileCompiler.parsedBuildFiles.flatMap { it.pluginUrls }
|
val pluginUrls = buildFileCompiler.parsedBuildFiles.flatMap { it.pluginUrls }
|
||||||
|
|
||||||
val pluginDependencies = pluginUrls.map { File(it.toURI()) }.map { FileDependency(it.absolutePath) }
|
val pluginDependencies = pluginUrls.map { File(it.toURI()) }.map { FileDependency(it.absolutePath) }
|
||||||
projects.forEach { project ->
|
projectResult.projects.forEach { project ->
|
||||||
val compileDependencies = pluginDependencies.map { toDependencyData(it, "compile") } +
|
val compileDependencies = pluginDependencies.map { toDependencyData(it, "compile") } +
|
||||||
allDeps(project.compileDependencies).map { toDependencyData(it, "compile") } +
|
allDeps(project.compileDependencies).map { toDependencyData(it, "compile") } +
|
||||||
allDeps(project.compileProvidedDependencies).map { toDependencyData(it, "compile") }
|
allDeps(project.compileProvidedDependencies).map { toDependencyData(it, "compile") }
|
||||||
|
@ -57,7 +57,7 @@ class DependencyData @Inject constructor(val executors: KobaltExecutors, val dep
|
||||||
compileDependencies, testDependencies,
|
compileDependencies, testDependencies,
|
||||||
sources.second.toSet(), tests.second.toSet(), sources.first.toSet(), tests.first.toSet()))
|
sources.second.toSet(), tests.second.toSet(), sources.first.toSet(), tests.first.toSet()))
|
||||||
}
|
}
|
||||||
return GetDependenciesData(projectDatas)
|
return GetDependenciesData(projectDatas, projectResult.taskResult.errorMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
/////
|
/////
|
||||||
|
@ -72,5 +72,5 @@ class DependencyData @Inject constructor(val executors: KobaltExecutors, val dep
|
||||||
val testDependencies: List<DependencyData>, val sourceDirs: Set<String>, val testDirs: Set<String>,
|
val testDependencies: List<DependencyData>, val sourceDirs: Set<String>, val testDirs: Set<String>,
|
||||||
val sourceResourceDirs: Set<String>, val testResourceDirs: Set<String>)
|
val sourceResourceDirs: Set<String>, val testResourceDirs: Set<String>)
|
||||||
|
|
||||||
class GetDependenciesData(val projects: List<ProjectData>)
|
class GetDependenciesData(val projects: List<ProjectData>, val errorMessage: String?)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,8 @@ class GetDependenciesCommand @Inject constructor(val args: Args, val dependencyD
|
||||||
|
|
||||||
override fun run(sender: ICommandSender, received: JsonObject) {
|
override fun run(sender: ICommandSender, received: JsonObject) {
|
||||||
val buildFile = received.get("buildFile").asString
|
val buildFile = received.get("buildFile").asString
|
||||||
val data = toCommandData(Gson().toJson(dependencyData.dependenciesDataFor(buildFile, args)))
|
val dd = dependencyData.dependenciesDataFor(buildFile, args)
|
||||||
|
val data = toCommandData(Gson().toJson(dd), dd.errorMessage)
|
||||||
sender.sendData(data)
|
sender.sendData(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -14,7 +14,10 @@ import com.beust.kobalt.misc.log
|
||||||
import org.jetbrains.kotlin.cli.common.CLICompiler
|
import org.jetbrains.kotlin.cli.common.CLICompiler
|
||||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||||
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
||||||
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.PrintStream
|
||||||
|
import java.nio.charset.Charset
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
@ -64,8 +67,7 @@ class KotlinCompiler @Inject constructor(
|
||||||
allArgs.add("-no-stdlib")
|
allArgs.add("-no-stdlib")
|
||||||
}
|
}
|
||||||
|
|
||||||
val success = invokeCompiler(projectName ?: "kobalt-" + Random().nextInt(), cp, allArgs)
|
return invokeCompiler(projectName ?: "kobalt-" + Random().nextInt(), cp, allArgs)
|
||||||
return TaskResult(success)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -78,10 +80,10 @@ class KotlinCompiler @Inject constructor(
|
||||||
* There are plenty of ways in which this method can break but this will be immediately
|
* There are plenty of ways in which this method can break but this will be immediately
|
||||||
* apparent if it happens.
|
* apparent if it happens.
|
||||||
*/
|
*/
|
||||||
private fun invokeCompiler(projectName: String, cp: List<File>, args: List<String>): Boolean {
|
private fun invokeCompiler(projectName: String, cp: List<File>, args: List<String>): TaskResult {
|
||||||
val allArgs = listOf("-module-name", "project-" + projectName) + args
|
val allArgs = listOf("-module-name", "project-" + projectName) + args
|
||||||
log(2, "Calling kotlinc " + allArgs.joinToString(" "))
|
log(2, "Calling kotlinc " + allArgs.joinToString(" "))
|
||||||
val result : Boolean =
|
val result : TaskResult =
|
||||||
if (true) {
|
if (true) {
|
||||||
val classLoader = ParentLastClassLoader(cp.map { it.toURI().toURL() })
|
val classLoader = ParentLastClassLoader(cp.map { it.toURI().toURL() })
|
||||||
val compiler = classLoader.loadClass("org.jetbrains.kotlin.cli.common.CLICompiler")
|
val compiler = classLoader.loadClass("org.jetbrains.kotlin.cli.common.CLICompiler")
|
||||||
|
@ -89,13 +91,26 @@ class KotlinCompiler @Inject constructor(
|
||||||
it.name == "doMainNoExit" && it.parameterTypes.size == 2
|
it.name == "doMainNoExit" && it.parameterTypes.size == 2
|
||||||
}[0]
|
}[0]
|
||||||
val kCompiler = classLoader.loadClass("org.jetbrains.kotlin.cli.jvm.K2JVMCompiler")
|
val kCompiler = classLoader.loadClass("org.jetbrains.kotlin.cli.jvm.K2JVMCompiler")
|
||||||
val compilerInstance = kCompiler.newInstance()
|
|
||||||
val exitCode = compilerMain.invoke(null, compilerInstance, allArgs.toTypedArray())
|
//
|
||||||
|
// In order to capture the error stream, I need to invoke CLICompiler.exec(), which
|
||||||
|
// is the first method that accepts a PrintStream for the errors in parameter
|
||||||
|
//
|
||||||
|
val baos = ByteArrayOutputStream()
|
||||||
|
val ps = PrintStream(baos)
|
||||||
|
val execMethod = compiler.declaredMethods.filter {
|
||||||
|
it.name == "exec" && it.parameterTypes.size == 2
|
||||||
|
}[0]
|
||||||
|
val exitCode = execMethod.invoke(kCompiler.newInstance(), ps, allArgs.toTypedArray())
|
||||||
|
val errorString = baos.toString(Charset.defaultCharset().toString())
|
||||||
|
|
||||||
|
// The return value is an enum
|
||||||
val nameMethod = exitCode.javaClass.getMethod("name")
|
val nameMethod = exitCode.javaClass.getMethod("name")
|
||||||
"OK" == nameMethod.invoke(exitCode).toString()
|
val success = "OK" == nameMethod.invoke(exitCode).toString()
|
||||||
|
TaskResult(success, errorString)
|
||||||
} else {
|
} else {
|
||||||
val exitCode = CLICompiler.doMainNoExit(K2JVMCompiler(), allArgs.toTypedArray())
|
val exitCode = CLICompiler.doMainNoExit(K2JVMCompiler(), allArgs.toTypedArray())
|
||||||
exitCode == ExitCode.OK
|
TaskResult(exitCode == ExitCode.OK)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue