aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--stage1/Stage1Lib.scala54
-rw-r--r--stage2/BuildBuild.scala30
-rw-r--r--stage2/Scaffold.scala3
-rw-r--r--test/broken-build/build-class-with-wrong-arguments/build/build.scala3
-rw-r--r--test/broken-build/build-class-with-wrong-parent/build/build.scala (renamed from test/forgot-extend/build/build.scala)0
-rw-r--r--test/broken-build/empty-build-file/Main.scala (renamed from test/empty-build-file/Main.scala)0
-rw-r--r--test/broken-build/empty-build-file/build/build.scala (renamed from test/empty-build-file/build/build.scala)0
-rw-r--r--test/broken-build/no-build-file/Main.scala (renamed from test/no-build-file/Main.scala)0
-rw-r--r--test/broken-build/no-build-file/build/foo.scala (renamed from test/no-build-file/build/foo.scala)0
-rw-r--r--test/test.scala19
10 files changed, 71 insertions, 38 deletions
diff --git a/stage1/Stage1Lib.scala b/stage1/Stage1Lib.scala
index 505b298..79df450 100644
--- a/stage1/Stage1Lib.scala
+++ b/stage1/Stage1Lib.scala
@@ -146,35 +146,43 @@ class Stage1Lib( logger: Logger ) extends BaseLib{
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)
+ /** Given a directory corresponding to the root package, iterate
+ the names of all classes derived from the class files found */
+ def iterateClassNames( classesRootDirectory: File ): Seq[String] =
+ listFilesRecursive(classesRootDirectory)
.filter(_.isFile)
.map(_.getPath)
.collect{
// no $ to avoid inner classes
case path if !path.contains("$") && path.endsWith(".class") =>
- try{
- classLoader.loadClass(
- path
- .stripSuffix(".class")
- .stripPrefix(targetDirectory.getPath)
- .stripPrefix(File.separator) // 1 for the slash
- .replace(File.separator, ".")
- )
- } catch {
- case e: ClassNotFoundException => null
- case e: NoClassDefFoundError => null
- }
- }.filterNot(_ == null).filter(
- _.getDeclaredMethods().exists( m =>
- m.getName == "main"
- && m.getParameterTypes.toList == List(arrayClass)
- && m.getReturnType == unitClass
- )
+ path.stripSuffix(".class")
+ .stripPrefix(classesRootDirectory.getPath)
+ .stripPrefix(File.separator) // 1 for the slash
+ .replace(File.separator, ".")
+ }
+
+ /** ignoreMissingClasses allows ignoring other classes root directories which are subdirectories of this one */
+ def iterateClasses( classesRootDirectory: File, classLoader: ClassLoader, ignoreMissingClasses: Boolean ) =
+ iterateClassNames(classesRootDirectory).map{ name =>
+ try{
+ classLoader.loadClass(name)
+ } catch {
+ case e: ClassNotFoundException if ignoreMissingClasses => null
+ case e: NoClassDefFoundError if ignoreMissingClasses => null
+ }
+ }.filterNot(ignoreMissingClasses && _ == null)
+
+ def mainClasses( classesRootDirectory: File, classLoader: ClassLoader ): Seq[Class[_]] = {
+ val arrayClass = classOf[Array[String]]
+ val unitClass = classOf[Unit]
+
+ iterateClasses( classesRootDirectory, classLoader, true ).filter(
+ _.getDeclaredMethods().exists( m =>
+ m.getName == "main"
+ && m.getParameterTypes.toList == List(arrayClass)
+ && m.getReturnType == unitClass
)
+ )
}
implicit class ClassLoaderExtensions(classLoader: ClassLoader){
diff --git a/stage2/BuildBuild.scala b/stage2/BuildBuild.scala
index 798bd7d..2eebcbc 100644
--- a/stage2/BuildBuild.scala
+++ b/stage2/BuildBuild.scala
@@ -63,15 +63,29 @@ trait BuildBuildWithoutEssentials extends BaseBuild{
.invoke( null, ctx )
}
}.getOrElse{
- try{
- classLoader
- .loadClass(lib.buildClassName)
- .getConstructors.head
- .newInstance(managedContext)
- } catch {
- case e: ClassNotFoundException if e.getMessage == lib.buildClassName =>
- throw new Exception("You need to define a class Build in build.scala in: "+projectDirectory)
+ val buildClasses =
+ lib.iterateClasses( compileTarget, classLoader, false )
+ .filter(_.getSimpleName == lib.buildClassName)
+ .filter(classOf[BaseBuild] isAssignableFrom _)
+ if( buildClasses.size == 0 ){
+ throw new Exception(
+ s"You need to define a class ${lib.buildClassName} extending an appropriate super class in\n"
+ + (projectDirectory / lib.buildFileName) ++ "\nbut none found."
+ )
+ } else if( buildClasses.size > 1 ){
+ throw new Exception(
+ s"You need to define exactly one class ${lib.buildClassName} extending an appropriate build super class, but multiple found in " + projectDirectory + ":\n" + buildClasses.mkString("\n")
+ )
+ } else {
+ val buildClass = buildClasses.head
+ if( !buildClass.getConstructors.exists(_.getParameterTypes.toList == List(classOf[Context])) ){
+ throw new Exception(
+ s"Expected class ${lib.buildClassName}(val context: Context), but found different constructor in\n"
+ + projectDirectory ++ "\n"
+ + buildClass ++ "(" ++ buildClass.getConstructors.map(_.getParameterTypes.mkString(", ")).mkString("; ") + ")" )
}
+ buildClass.getConstructors.head.newInstance(managedContext)
+ }
}
}
)
diff --git a/stage2/Scaffold.scala b/stage2/Scaffold.scala
index b110258..68a966b 100644
--- a/stage2/Scaffold.scala
+++ b/stage2/Scaffold.scala
@@ -59,7 +59,8 @@ object Main{
def createBuild(
projectDirectory: File
): Unit = {
- createFile(projectDirectory, "build/build.scala", s"""import cbt._
+ createFile(projectDirectory, lib.buildDirectoryName++"/"++lib.buildFileName, s"""package cbt_build.${packageFromDirectory(projectDirectory)}
+import cbt._
class Build(val context: Context) extends BaseBuild{
override def dependencies =
super.dependencies ++ // don't forget super.dependencies here for scala-library, etc.
diff --git a/test/broken-build/build-class-with-wrong-arguments/build/build.scala b/test/broken-build/build-class-with-wrong-arguments/build/build.scala
new file mode 100644
index 0000000..cf040a1
--- /dev/null
+++ b/test/broken-build/build-class-with-wrong-arguments/build/build.scala
@@ -0,0 +1,3 @@
+package cbt_build.build_class_with_wrong_arguments
+import cbt._
+class Build(i: Int, val context: Context) extends BaseBuild
diff --git a/test/forgot-extend/build/build.scala b/test/broken-build/build-class-with-wrong-parent/build/build.scala
index 9181a5d..9181a5d 100644
--- a/test/forgot-extend/build/build.scala
+++ b/test/broken-build/build-class-with-wrong-parent/build/build.scala
diff --git a/test/empty-build-file/Main.scala b/test/broken-build/empty-build-file/Main.scala
index 19d4beb..19d4beb 100644
--- a/test/empty-build-file/Main.scala
+++ b/test/broken-build/empty-build-file/Main.scala
diff --git a/test/empty-build-file/build/build.scala b/test/broken-build/empty-build-file/build/build.scala
index e69de29..e69de29 100644
--- a/test/empty-build-file/build/build.scala
+++ b/test/broken-build/empty-build-file/build/build.scala
diff --git a/test/no-build-file/Main.scala b/test/broken-build/no-build-file/Main.scala
index 19d4beb..19d4beb 100644
--- a/test/no-build-file/Main.scala
+++ b/test/broken-build/no-build-file/Main.scala
diff --git a/test/no-build-file/build/foo.scala b/test/broken-build/no-build-file/build/foo.scala
index e69de29..e69de29 100644
--- a/test/no-build-file/build/foo.scala
+++ b/test/broken-build/no-build-file/build/foo.scala
diff --git a/test/test.scala b/test/test.scala
index 778fcda..d8714c0 100644
--- a/test/test.scala
+++ b/test/test.scala
@@ -240,21 +240,28 @@ object Main{
}
{
- val res = runCbt("forgot-extend", Seq("run"))
+ val res = runCbt("broken-build/build-class-with-wrong-arguments", Seq("run"))
assert(!res.exit0)
- assert(res.err contains s"${lib.buildClassName} cannot be cast to cbt.BuildInterface", res.err)
+ assert(res.err contains s"Expected class ${lib.buildClassName}(val context: Context), but found different constructor", res.err)
+ assert(res.err contains s"${lib.buildClassName}(int, interface cbt.Context)", res.err)
}
{
- val res = runCbt("no-build-file", Seq("run"))
+ val res = runCbt("broken-build/build-class-with-wrong-parent", Seq("run"))
assert(!res.exit0)
- assert(res.err contains s"No file ${lib.buildFileName} (lower case) found in", res.err)
+ assert(res.err contains s"You need to define a class ${lib.buildClassName} extending an appropriate super class", res.err)
}
{
- val res = runCbt("empty-build-file", Seq("run"))
+ val res = runCbt("broken-build/no-build-file", Seq("run"))
assert(!res.exit0)
- assert(res.err contains s"You need to define a class ${lib.buildClassName} in", res.err)
+ assert(res.err contains s"No file ${lib.buildFileName} (lower case) found", res.err)
+ }
+
+ {
+ val res = runCbt("broken-build/empty-build-file", Seq("run"))
+ assert(!res.exit0)
+ assert(res.err contains s"You need to define a class ${lib.buildClassName}", res.err)
}
{