aboutsummaryrefslogtreecommitdiff
path: root/stage2
diff options
context:
space:
mode:
Diffstat (limited to 'stage2')
-rw-r--r--stage2/BasicBuild.scala11
-rw-r--r--stage2/Lib.scala100
-rw-r--r--stage2/Stage2.scala8
-rw-r--r--stage2/ToolsStage2.scala5
4 files changed, 53 insertions, 71 deletions
diff --git a/stage2/BasicBuild.scala b/stage2/BasicBuild.scala
index f32d4d9..4ca39a7 100644
--- a/stage2/BasicBuild.scala
+++ b/stage2/BasicBuild.scala
@@ -186,9 +186,10 @@ trait BaseBuild extends BuildInterface with DependencyImplementation with Trigge
def run: ExitCode = run( context.args: _* )
def test: Any =
- Some(new lib.ReflectBuild(
- DirectoryDependency(projectDirectory++"/test").build
- ).callNullary(Some("run")))
+ lib.callReflective(
+ DirectoryDependency(projectDirectory++"/test").build,
+ Some("run")
+ )
def t = test
def rt = recursiveUnsafe(Some("test"))
@@ -221,13 +222,13 @@ trait BaseBuild extends BuildInterface with DependencyImplementation with Trigge
recursiveUnsafe(context.args.lift(1))
}
- def recursiveUnsafe(taskName: Option[String]): ExitCode = {
+ def recursiveUnsafe(code: Option[String]): ExitCode = {
recursiveSafe{
b =>
System.err.println(b.show)
lib.trapExitCode{ // FIXME: trapExitCode does not seem to work here
try{
- new lib.ReflectBuild(b).callNullary(taskName)
+ lib.callReflective(b,code)
ExitCode.Success
} catch {
case e: Throwable => println(e.getClass); throw e
diff --git a/stage2/Lib.scala b/stage2/Lib.scala
index b7d1686..9e1f824 100644
--- a/stage2/Lib.scala
+++ b/stage2/Lib.scala
@@ -108,7 +108,7 @@ final class Lib(val logger: Logger) extends Stage1Lib(logger){
}
// task reflection helpers
- def tasks(cls:Class[_]): Map[String, Method] =
+ def taskMethods(cls:Class[_]): Map[String, Method] =
Stream
.iterate(cls.asInstanceOf[Class[Any]])(_.getSuperclass)
.takeWhile(_ != null)
@@ -127,7 +127,7 @@ final class Lib(val logger: Logger) extends Stage1Lib(logger){
.map(m => NameTransformer.decode(m.getName) -> m)
).toMap
- def taskNames(cls: Class[_]): Seq[String] = tasks(cls).keys.toVector.sorted
+ def taskNames(cls: Class[_]): Seq[String] = taskMethods(cls).keys.toVector.sorted
def usage(buildClass: Class[_], show: String): String = {
val baseTasks = Seq(
@@ -151,65 +151,53 @@ final class Lib(val logger: Logger) extends Stage1Lib(logger){
) ++ "\n"
}
- class ReflectBuild[T:scala.reflect.ClassTag](build: BuildInterface) extends ReflectObject(build){
- def usage = lib.usage(build.getClass, build.show)
+ def callReflective[T <: AnyRef]( obj: T, code: Option[String] ): ExitCode = {
+ callInternal( obj, code.toSeq.flatMap(_.split("\\.").map( NameTransformer.encode )), Nil ) match {
+ case (obj, code, None) =>
+ val s = render(obj)
+ if(s.nonEmpty)
+ System.out.println(s)
+ code getOrElse ExitCode.Success
+ case (obj, code, Some(msg)) =>
+ if(msg.nonEmpty)
+ System.err.println(msg)
+ val s = render(obj)
+ if(s.nonEmpty)
+ System.err.println(s)
+ code getOrElse ExitCode.Failure
+ }
+ }
+
+ private def render[T]( obj: T ): String = {
+ obj match {
+ case Some(s) => render(s)
+ case None => ""
+ case d: Dependency => lib.usage(d.getClass, d.show())
+ case c: ClassPath => c.string
+ case t:ToolsStage2.type => "Available methods: " ++ lib.taskNames(t.getClass).mkString(" ")
+ case _ => obj.toString
+ }
}
- abstract class ReflectObject[T](obj: T){
- def usage: String
- def callNullary( taskName: Option[String] ): ExitCode = {
+
+ private def callInternal[T <: AnyRef]( obj: T, members: Seq[String], previous: Seq[String] ): (Option[Object], Option[ExitCode], Option[String]) = {
+ members.headOption.map{ taskName =>
logger.lib("Calling task " ++ taskName.toString)
- val ts = tasks(obj.getClass)
- taskName.map( NameTransformer.encode ).flatMap(ts.get).map{ method =>
- val result: Option[Any] = Option(method.invoke(obj)) // null in case of Unit
- result.flatMap{
- case v: Option[_] => v
- case other => Some(other)
- }.map{
- value =>
- // Try to render console representation. Probably not the best way to do this.
- scala.util.Try( value.getClass.getDeclaredMethod("toConsole") ) match {
- case scala.util.Success(toConsole) =>
- println(toConsole.invoke(value))
- ExitCode.Success
-
- case scala.util.Failure(e) if Option(e.getMessage).getOrElse("") contains "toConsole" =>
- value match {
- case code if code.getClass.getSimpleName == "ExitCode" =>
- // FIXME: ExitCode needs to be part of the compatibility interfaces
- ExitCode(Stage0Lib.get(code,"integer").asInstanceOf[Int])
- case b: BaseBuild =>
- val context = b.context.copy(args=b.context.args.drop(1))
- val task = b.context.args.lift(0)
- new ReflectBuild( b.copy(context=context) ).callNullary( task )
- case Seq(b: BaseBuild, bs @ _*) if bs.forall(_.isInstanceOf[BaseBuild]) =>
- (b +: bs)
- .map( _.asInstanceOf[BaseBuild] )
- .map{ b =>
- val task = b.context.args.lift(0)
- new ReflectBuild(
- b.copy( context = b.context.copy(args=b.context.args.drop(1)) )
- ).callNullary( task )
- }
- .head
- case other =>
- println( other.toString ) // no method .toConsole, using to String
- ExitCode.Success
- }
-
- case scala.util.Failure(e) =>
- throw e
+ taskMethods(obj.getClass).get(taskName).map{ method =>
+ Option(method.invoke(obj) /* null in case of Unit */ ).map{ result =>
+ result match {
+ case code if code.getClass.getSimpleName == "ExitCode" =>
+ // FIXME: ExitCode needs to be part of the compatibility interfaces
+ (None, Some(ExitCode(Stage0Lib.get(code,"integer").asInstanceOf[Int])), None)
+ case Seq(bs @ _*) if bs.forall(_.isInstanceOf[BaseBuild]) =>
+ bs.map( b => callInternal(b.asInstanceOf[BaseBuild], members.tail, previous :+ taskName) ).head
+ case _ => callInternal(result, members.tail, previous :+ taskName)
}
- }.getOrElse(ExitCode.Success)
+ }.getOrElse( (None, None, None) )
}.getOrElse{
- taskName.foreach{ n =>
- System.err.println(s"Method not found: $n")
- System.err.println("")
- }
- System.err.println(usage)
- taskName.map{ _ =>
- ExitCode.Failure
- }.getOrElse( ExitCode.Success )
+ ( Some(obj), None, Some("\nMethod not found: " ++ (previous :+ taskName).mkString(".") ++ "\n") )
}
+ }.getOrElse{
+ ( Some(obj), None, None )
}
}
diff --git a/stage2/Stage2.scala b/stage2/Stage2.scala
index 25cd0ae..93f0a77 100644
--- a/stage2/Stage2.scala
+++ b/stage2/Stage2.scala
@@ -41,10 +41,6 @@ object Stage2 extends Stage2Base{
val first = lib.loadRoot( context )
val build = first.finalBuild
- def call(build: BuildInterface): ExitCode = {
- new lib.ReflectBuild(build).callNullary(task)
- }
-
val res =
if (loop) {
// TODO: this should allow looping over task specific files, like test files as well
@@ -63,11 +59,11 @@ object Stage2 extends Stage2Base{
case file if triggerFiles.exists(file.toString startsWith _.toString) =>
val build = lib.loadRoot(context).finalBuild
logger.loop(s"Re-running $task for " ++ build.show)
- call(build)
+ lib.callReflective(build, task)
}
ExitCode.Success
} else {
- val code = call(build)
+ val code = lib.callReflective(build, task)
logger.stage2(s"Stage2 end")
code
}
diff --git a/stage2/ToolsStage2.scala b/stage2/ToolsStage2.scala
index e1c4a8e..c71f2b7 100644
--- a/stage2/ToolsStage2.scala
+++ b/stage2/ToolsStage2.scala
@@ -5,9 +5,6 @@ object ToolsStage2 extends Stage2Base{
val args = _args.args.dropWhile(Seq("tools","direct") contains _)
val lib = new Lib(_args.logger)
val toolsTasks = new ToolsTasks(lib, args, _args.cwd, _args.cache, _args.cbtHome, _args.stage2LastModified)(_args.classLoaderCache)
- new lib.ReflectObject(toolsTasks){
- def usage: String = "Available methods: " ++ lib.taskNames(toolsTasks.getClass).mkString(" ")
- }.callNullary(args.lift(0))
- ExitCode.Success
+ lib.callReflective(toolsTasks, args.lift(0))
}
}