diff --git a/src/main/scala/sbt/BasicProjectTypes.scala b/src/main/scala/sbt/BasicProjectTypes.scala index d8340bf39..163a69af3 100644 --- a/src/main/scala/sbt/BasicProjectTypes.scala +++ b/src/main/scala/sbt/BasicProjectTypes.scala @@ -537,6 +537,8 @@ object Reflective trait ReflectiveLibraryDependencies extends ManagedProject { def excludeIDs: Iterable[ModuleID] = projectID :: Nil + /** Defines the library dependencies of this project. By default, this finds vals of type ModuleID defined on the project. + * This can be overridden to directly provide dependencies */ def libraryDependencies: Set[ModuleID] = reflectiveLibraryDependencies def reflectiveLibraryDependencies : Set[ModuleID] = Set[ModuleID](Reflective.reflectiveMappings[ModuleID](this).values.toList: _*) -- excludeIDs } diff --git a/src/main/scala/sbt/Run.scala b/src/main/scala/sbt/Run.scala index 5662e5d87..41a495801 100644 --- a/src/main/scala/sbt/Run.scala +++ b/src/main/scala/sbt/Run.scala @@ -90,7 +90,10 @@ object Run extends ScalaRun (new java.io.File(pathString)).toURI.toURL log.info("Running " + mainClass + " ...") log.debug(" Classpath:" + (classpathURLs ++ extraURLs).mkString("\n\t", "\n\t","")) - executeTrapExit( ObjectRunner.run(classpathURLs ++ extraURLs, mainClass, options.toList), log ) + def execute = + try { ObjectRunner.run(classpathURLs ++ extraURLs, mainClass, options.toList) } + catch { case e: java.lang.reflect.InvocationTargetException => throw e.getCause } + executeTrapExit( execute, log ) } } } diff --git a/src/main/scala/sbt/TestFramework.scala b/src/main/scala/sbt/TestFramework.scala index 7e6a59fb4..e5bbf1bb3 100644 --- a/src/main/scala/sbt/TestFramework.scala +++ b/src/main/scala/sbt/TestFramework.scala @@ -173,15 +173,24 @@ abstract class LazyTestFramework extends TestFramework * tests for this framework.*/ protected def testRunnerClassName: String + protected def bundledTestRunnerClassName: Option[String] = None + /** Creates an instance of the runner given by 'testRunnerClassName'.*/ final def testRunner(projectLoader: ClassLoader, listeners: Iterable[TestReportListener], log: Logger): TestRunner = { - val runnerClassName = testRunnerClassName val frameworkClasspath = FileUtilities.classLocation(getClass) val sbtURL = FileUtilities.sbtJar.toURI.toURL - val lazyLoader = new LazyFrameworkLoader(runnerClassName, Array(frameworkClasspath, sbtURL), projectLoader, getClass.getClassLoader) - val runnerClass = Class.forName(runnerClassName, true, lazyLoader).asSubclass(classOf[TestRunner]) - + val projectClasspath = projectLoader.asInstanceOf[java.net.URLClassLoader].getURLs + val loaderURLs = Array(frameworkClasspath, sbtURL) ++ projectClasspath + + def load(name: String): Option[Class[_]] = + { + val lazyLoader = new LazyFrameworkLoader(name, loaderURLs, projectLoader, getClass.getClassLoader) + try { Some(Class.forName(name, true, lazyLoader)) } + catch { case e: ClassNotFoundException => None } + } + val c = bundledTestRunnerClassName.flatMap(load).orElse(load(testRunnerClassName)) + val runnerClass = c.getOrElse(error("Could not find test runner")).asSubclass(classOf[TestRunner]) runnerClass.getConstructor(classOf[Logger], classOf[Seq[TestReportListener]], classOf[ClassLoader]).newInstance(log, listeners, projectLoader) } } @@ -196,6 +205,7 @@ object ScalaTestFramework extends LazyTestFramework def testSubClassType = ClassType.Class def testRunnerClassName = "sbt.impl.ScalaTestRunner" + override def bundledTestRunnerClassName = Some("org.scalatest.sbt.ScalaTestRunner") } /** The test framework definition for ScalaCheck.*/ object ScalaCheckFramework extends LazyTestFramework diff --git a/src/main/scala/sbt/TrapExit.scala b/src/main/scala/sbt/TrapExit.scala index c66b8f208..aef7cebb5 100644 --- a/src/main/scala/sbt/TrapExit.scala +++ b/src/main/scala/sbt/TrapExit.scala @@ -29,7 +29,7 @@ object TrapExit * the threads that were created by 'execute'.*/ val originalThreads = allThreads val code = new ExitCode - val customThreadGroup = new ExitThreadGroup(new ExitHandler(Thread.getDefaultUncaughtExceptionHandler, originalThreads, code)) + val customThreadGroup = new ExitThreadGroup(new ExitHandler(Thread.getDefaultUncaughtExceptionHandler, originalThreads, code, log)) val executionThread = new Thread(customThreadGroup, "run-main") { override def run() { execute } } val originalSecurityManager = System.getSecurityManager @@ -162,7 +162,7 @@ object TrapExit } /** An uncaught exception handler that delegates to the original uncaught exception handler except when * the cause was a call to System.exit (which generated a SecurityException)*/ - private final class ExitHandler(originalHandler: Thread.UncaughtExceptionHandler, originalThreads: Set[Thread], codeHolder: ExitCode) extends Thread.UncaughtExceptionHandler + private final class ExitHandler(originalHandler: Thread.UncaughtExceptionHandler, originalThreads: Set[Thread], codeHolder: ExitCode, log: Logger) extends Thread.UncaughtExceptionHandler { def uncaughtException(t: Thread, e: Throwable) { @@ -173,7 +173,9 @@ object TrapExit } catch { - case _ => originalHandler.uncaughtException(t, e) + case _ => + log.trace(e) + originalHandler.uncaughtException(t, e) } } } diff --git a/src/sbt-test/source-dependencies/added/test b/src/sbt-test/source-dependencies/added/test index 8938af326..5ba6a5af9 100644 --- a/src/sbt-test/source-dependencies/added/test +++ b/src/sbt-test/source-dependencies/added/test @@ -29,8 +29,6 @@ $ copy-file changes/A3.scala src/main/scala/A.scala # val x: String = B.y $ copy-file changes/B2.scala src/main/scala/B.scala [success] -$ pause -[success] > compile [failure]