aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/dotty-example/src/Main.scala3
-rw-r--r--examples/scalafmt-example/build/build.scala2
-rw-r--r--plugins/uber-jar/src/UberJar.scala2
-rw-r--r--stage1/Stage1Lib.scala69
-rw-r--r--stage2/BasicBuild.scala11
-rw-r--r--stage2/Lib.scala2
-rw-r--r--test/test.scala3
7 files changed, 78 insertions, 14 deletions
diff --git a/examples/dotty-example/src/Main.scala b/examples/dotty-example/src/Main.scala
index 1963b51..fdc2068 100644
--- a/examples/dotty-example/src/Main.scala
+++ b/examples/dotty-example/src/Main.scala
@@ -1,5 +1,6 @@
+package dotty_example
object Main extends Foo("Hello Dotty - trait parameters, yay"){
- def main(args: Array[String]) = {
+ def main(args: Array[String]): Unit = {
println(hello)
// Sanity check the classpath: this won't run if the dotty jar is not present.
diff --git a/examples/scalafmt-example/build/build.scala b/examples/scalafmt-example/build/build.scala
index a489616..b8a819b 100644
--- a/examples/scalafmt-example/build/build.scala
+++ b/examples/scalafmt-example/build/build.scala
@@ -1,7 +1,7 @@
import cbt._
import org.scalafmt.ScalafmtStyle
-class Build(val context: Context) extends BuildBuild with Scalafmt {
+class Build(val context: Context) extends BaseBuild with Scalafmt {
override def compile = {
scalafmt
super.compile
diff --git a/plugins/uber-jar/src/UberJar.scala b/plugins/uber-jar/src/UberJar.scala
index c6815b4..3783367 100644
--- a/plugins/uber-jar/src/UberJar.scala
+++ b/plugins/uber-jar/src/UberJar.scala
@@ -13,7 +13,7 @@ trait UberJar extends BaseBuild {
ExitCode.Success
}
- def uberJarMainClass: Option[String] = Some(runClass)
+ def uberJarMainClass: Option[String] = runClass
def uberJarName: String = projectName + ".jar"
diff --git a/stage1/Stage1Lib.scala b/stage1/Stage1Lib.scala
index c427b77..5e65018 100644
--- a/stage1/Stage1Lib.scala
+++ b/stage1/Stage1Lib.scala
@@ -8,7 +8,7 @@ import java.nio.file._
import java.nio.file.attribute.FileTime
import javax.tools._
import java.security._
-import java.util.{Set=>_,Map=>_,_}
+import java.util.{Set=>_,Map=>_,List=>_,_}
import java.util.concurrent.ConcurrentHashMap
import javax.xml.bind.annotation.adapters.HexBinaryAdapter
@@ -95,12 +95,6 @@ class Stage1Lib( val logger: Logger ) extends BaseLib{
// ========== compilation / execution ==========
- def runMainIfFound(cls: String, args: Seq[String], classLoader: ClassLoader ): ExitCode = {
- if( classLoader.canLoad(cls) ){
- runMain(cls, args, classLoader )
- } else ExitCode.Success
- }
-
def runMain( cls: String, args: Seq[String], classLoader: ClassLoader, fakeInstance: Boolean = false ): ExitCode = {
import java.lang.reflect.Modifier
logger.lib(s"Running $cls.main($args) with classLoader: " ++ classLoader.toString)
@@ -118,6 +112,67 @@ class Stage1Lib( val logger: Logger ) extends BaseLib{
}
}
+ /** shows an interactive dialogue in the shell asking the user to pick one of many choices */
+ def pickOne[T]( msg: String, choices: Seq[T] )( show: T => String ): Option[T] = {
+ if(choices.size == 0) None else if(choices.size == 1) Some(choices.head) else {
+ Option(System.console).map{
+ console =>
+ val indexedChoices: Map[Int, T] = choices.zipWithIndex.toMap.mapValues(_+1).map(_.swap)
+ System.err.println(
+ indexedChoices.map{ case (index,choice) => s"[${index}] "++show(choice)}.mkString("\n")
+ )
+ val range = s"1 - ${indexedChoices.size}"
+ System.err.println()
+ System.err.println( msg ++ " [" ++ range ++ "] " )
+ val answer = console.readLine()
+ val choice = try{
+ Some(Integer.parseInt(answer))
+ }catch{
+ case e:java.lang.NumberFormatException => None
+ }
+
+ choice.flatMap(indexedChoices.get).orElse{
+ System.err.println("Not in range "++range)
+ None
+ }
+ }.getOrElse{
+ System.err.println("Using '"++show(choices.head)++"' because System.console() == null. Use `cbt direct <task>` or see https://github.com/cvogt/cbt/issues/236")
+ None
+ }
+ }
+ }
+
+ /** interactively pick one main class */
+ def runClass( mainClasses: Seq[Class[_]] ): Option[Class[_]] = {
+ pickOne( "Which one do you want to run?", mainClasses )( _.toString )
+ }
+
+ def mainClasses( targetDirectory: File, classLoader : ClassLoader ): Seq[Class[_]] = {
+ val arrayClass = classOf[Array[String]]
+ val unitClass = classOf[Unit]
+
+ listFilesRecursive(targetDirectory)
+ .filter(_.isFile)
+ .map(_.getPath)
+ .collect{
+ // no $ to avoid inner classes
+ case path if !path.contains("$") && path.endsWith(".class") =>
+ classLoader.loadClass(
+ path
+ .stripSuffix(".class")
+ .stripPrefix(targetDirectory.getPath)
+ .stripPrefix(File.separator) // 1 for the slash
+ .replace(File.separator, ".")
+ )
+ }.filter(
+ _.getDeclaredMethods().exists( m =>
+ m.getName == "main"
+ && m.getParameterTypes.toList == List(arrayClass)
+ && m.getReturnType == unitClass
+ )
+ )
+ }
+
implicit class ClassLoaderExtensions(classLoader: ClassLoader){
def canLoad(className: String) = {
try{
diff --git a/stage2/BasicBuild.scala b/stage2/BasicBuild.scala
index bcc3646..98deddc 100644
--- a/stage2/BasicBuild.scala
+++ b/stage2/BasicBuild.scala
@@ -136,8 +136,15 @@ trait BaseBuild extends DependencyImplementation with BuildInterface with Trigge
)
}
- def runClass: String = "Main"
- def run: ExitCode = lib.runMainIfFound( runClass, context.args, classLoader(context.classLoaderCache) )
+
+ def mainClasses: Seq[Class[_]] = compile.toSeq.flatMap( lib.mainClasses( _, classLoader(classLoaderCache) ) )
+
+ def runClass: Option[String] = lib.runClass( mainClasses ).map( _.getName )
+
+ def run: ExitCode = runClass.map( lib.runMain( _, context.args, classLoader(context.classLoaderCache) ) ).getOrElse{
+ logger.task( "No main class found for " ++ projectDirectory.string )
+ ExitCode.Success
+ }
def clean = {
lib.clean(
diff --git a/stage2/Lib.scala b/stage2/Lib.scala
index 46fecf7..c18bf2e 100644
--- a/stage2/Lib.scala
+++ b/stage2/Lib.scala
@@ -201,7 +201,7 @@ final class Lib(logger: Logger) extends Stage1Lib(logger) with Scaffold{
def consoleOrFail(msg: String) = {
Option(System.console).getOrElse(
- throw new Exception(msg + ". java.io.Console == null. See https://github.com/cvogt/cbt/issues/236")
+ throw new Exception(msg + ". System.console() == null. See https://github.com/cvogt/cbt/issues/236")
)
}
diff --git a/test/test.scala b/test/test.scala
index dfc35d0..8845528 100644
--- a/test/test.scala
+++ b/test/test.scala
@@ -1,4 +1,5 @@
-import cbt._
+package cbt
+package test
import java.util.concurrent.ConcurrentHashMap
import java.io.File
import java.nio.file._