summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.sbt3
-rw-r--r--core/src/test/scala/mill/TestMain.scala152
-rw-r--r--scalaplugin/src/main/scala/mill/scalaplugin/Subproject.scala32
3 files changed, 102 insertions, 85 deletions
diff --git a/build.sbt b/build.sbt
index f8c85428..e88b5a90 100644
--- a/build.sbt
+++ b/build.sbt
@@ -39,7 +39,8 @@ lazy val core = project
"com.lihaoyi" %% "pprint" % "0.5.3",
"com.lihaoyi" % "ammonite" % "1.0.3" cross CrossVersion.full,
"com.typesafe.play" %% "play-json" % "2.6.6",
- "org.scala-sbt" %% "zinc" % "1.0.3"
+ "org.scala-sbt" %% "zinc" % "1.0.3",
+ "org.scala-sbt" % "test-interface" % "1.0"
)
)
diff --git a/core/src/test/scala/mill/TestMain.scala b/core/src/test/scala/mill/TestMain.scala
index d0ebfc9d..c8fb3148 100644
--- a/core/src/test/scala/mill/TestMain.scala
+++ b/core/src/test/scala/mill/TestMain.scala
@@ -1,100 +1,86 @@
package mill
-import ammonite.ops._
-import java.io.File
+import java.io.FileInputStream
-import coursier._
-import sbt.internal.inc.{FreshCompilerCache, ScalaInstance, ZincUtil}
-import sbt.internal.util.{ConsoleOut, MainAppender}
-import sbt.util.LogExchange
-import xsbti.api.{ClassLike, DependencyContext}
-import xsbti.compile._
+import ammonite.ops._
+import java.lang.annotation.Annotation
+import java.util.zip.ZipInputStream
-import scalaz.concurrent.Task
+import sbt.testing._
object TestMain {
- def main(args: Array[String]): Unit = {
- val scalaVersion = "2.12.4"
- val start = Resolution(
- Set(
- Dependency(Module("org.scala-lang", "scala-reflect"), scalaVersion),
- Dependency(Module("org.scala-lang", "scala-compiler"), scalaVersion),
- Dependency(Module("org.scala-lang", "scala-reflect"), scalaVersion),
- Dependency(Module("org.scala-sbt", "compiler-bridge_2.12"), "1.0.3"),
- Dependency(Module("com.lihaoyi", "sourcecode_2.12"), "0.1.4"),
- Dependency(Module("com.lihaoyi", "pprint_2.12"), "0.5.3"),
- Dependency(Module("com.lihaoyi", "ammonite_2.12.4"), "1.0.3"),
- Dependency(Module("com.typesafe.play", "play-json_2.12"), "2.6.6"),
- Dependency(Module("org.scala-sbt", "zinc_2.12"), "1.0.3")
- )
- )
- val repositories = Seq(
- Cache.ivy2Local,
- MavenRepository("https://repo1.maven.org/maven2")
- )
-
- val fetch = Fetch.from(repositories, Cache.fetch())
- val resolution = start.process.run(fetch).unsafePerformSync
+ def listClassFiles(base: Path): Iterator[String] = {
+ if (base.isDir) ls.rec(base).toIterator.filter(_.ext == "class").map(_.relativeTo(base).toString)
+ else {
+ val zip = new ZipInputStream(new FileInputStream(base.toIO))
+ Iterator.continually(zip.getNextEntry).takeWhile(_ != null).map(_.getName).filter(_.endsWith(".class"))
+ }
+ }
+ def runTests(framework: Framework,
+ targets: Seq[Path]) = {
- val localArtifacts: Seq[File] = Task.gatherUnordered(
- resolution.artifacts.map(Cache.file(_).run)
- ).unsafePerformSync.flatMap(_.toOption)
+ val fingerprints = framework.fingerprints()
+ val testClasses = targets.flatMap { base =>
+ listClassFiles(base).flatMap { path =>
+ val cls = Class.forName(path.stripSuffix(".class").replace('/', '.'))
+ fingerprints.find {
+ case f: SubclassFingerprint =>
+ Class.forName(f.superclassName()).isAssignableFrom(cls)
+ case f: AnnotatedFingerprint =>
+ cls.isAnnotationPresent(
+ Class.forName(f.annotationName()).asInstanceOf[Class[Annotation]]
+ )
+ }.map { f => (cls, f) }
+ }
+ }
+ testClasses
+ }
+ def main(args: Array[String]): Unit = {
- pprint.log(localArtifacts)
- def grepJar(s: String) = localArtifacts.find(_.toString.endsWith(s)).get
+ val framework = Class.forName("mill.UTestFramework")
+ .newInstance()
+ .asInstanceOf[sbt.testing.Framework]
- val scalac = ZincUtil.scalaCompiler(
- new ScalaInstance(
- version = scalaVersion,
- loader = getClass.getClassLoader,
- libraryJar = grepJar(s"scala-library-$scalaVersion.jar"),
- compilerJar = grepJar(s"scala-compiler-$scalaVersion.jar"),
- allJars = localArtifacts.toArray,
- explicitActual = None
- ),
- grepJar("compiler-bridge_2.12-1.0.3.jar")
+ val testClasses = runTests(
+ framework,
+ Seq(pwd/'core/'target/"scala-2.12"/"test-classes")
)
- val outputDir = pwd/'target/'zinc
- mkdir(outputDir)
- val scalaFiles = ls.rec(pwd/'src/'main/'scala/'mill).filter(_.ext == "scala").map(_.toIO).toArray
+ pprint.log(testClasses)
- pprint.log(scalaFiles)
- scalac.apply(
- sources = scalaFiles,
- changes = new DependencyChanges {
- def isEmpty = true
- def modifiedBinaries() = Array[File]()
- def modifiedClasses() = Array[String]()
- },
- classpath = localArtifacts.toArray,
- singleOutput = outputDir.toIO,
- options = Array(),
- callback = new xsbti.AnalysisCallback {
- def startSource(source: File) = ()
- def apiPhaseCompleted() = ()
- def enabled() = true
- def binaryDependency(onBinaryEntry: File, onBinaryClassName: String, fromClassName: String, fromSourceFile: File, context: DependencyContext) = ()
- def generatedNonLocalClass(source: File, classFile: File, binaryClassName: String, srcClassName: String) = ()
- def problem(what: String, pos: xsbti.Position, msg: String, severity: xsbti.Severity, reported: Boolean) = ()
- def dependencyPhaseCompleted() = ()
- def classDependency(onClassName: String, sourceClassName: String, context: DependencyContext) = ()
- def generatedLocalClass(source: File, classFile: File) = ()
- def api(sourceFile: File, classApi: ClassLike) = ()
+ val runner = framework.runner(Array(), Array(), getClass.getClassLoader)
+ println(runner)
- def mainClass(sourceFile: File, className: String) = ()
- def usedName(className: String, name: String, useScopes: java.util.EnumSet[xsbti.UseScope]) = ()
- },
- maximumErrors = 10,
- cache = new FreshCompilerCache(),
- log = {
- val console = ConsoleOut.systemOut
- val consoleAppender = MainAppender.defaultScreen(console)
- val l = LogExchange.logger("Hello")
- LogExchange.unbindLoggerAppenders("Hello")
- LogExchange.bindLoggerAppenders("Hello", (consoleAppender -> sbt.util.Level.Warn) :: Nil)
- l
+ val tasks = runner.tasks(
+ for((cls, fingerprint) <- testClasses.toArray)
+ yield {
+ new TaskDef(cls.getName.stripSuffix("$"), fingerprint, true, Array())
}
)
+ for(t <- tasks){
+ t.execute(
+ new EventHandler {
+ def handle(event: Event) = ()
+ },
+ Array(
+ new Logger {
+ def debug(msg: String) = println(msg)
+
+ def error(msg: String) = println(msg)
+
+ def ansiCodesSupported() = true
+
+ def warn(msg: String) = println(msg)
+
+ def trace(t: Throwable) = println(t)
+
+ def info(msg: String) = println(msg)
+ })
+ )
+ }
+ val doneMsg = runner.done()
+ if (doneMsg.trim.nonEmpty){
+ println(doneMsg)
+ }
}
}
diff --git a/scalaplugin/src/main/scala/mill/scalaplugin/Subproject.scala b/scalaplugin/src/main/scala/mill/scalaplugin/Subproject.scala
index 59538a69..f30e74d2 100644
--- a/scalaplugin/src/main/scala/mill/scalaplugin/Subproject.scala
+++ b/scalaplugin/src/main/scala/mill/scalaplugin/Subproject.scala
@@ -2,8 +2,10 @@ package mill
package scalaplugin
import java.io.File
+import java.lang.annotation.Annotation
+import java.net.URLClassLoader
-import ammonite.ops.{Path, ls, mkdir, pwd}
+import ammonite.ops.{Path, ls, mkdir, pwd, up}
import coursier.{Cache, Dependency, Fetch, MavenRepository, Module, Repository, Resolution}
import mill.define.Task
import mill.define.Task.Cacher
@@ -12,11 +14,39 @@ import mill.util.Args
import play.api.libs.json._
import sbt.internal.inc.{FreshCompilerCache, ScalaInstance, ZincUtil}
import sbt.internal.util.{ConsoleOut, MainAppender}
+import sbt.testing.{AnnotatedFingerprint, SubclassFingerprint}
import sbt.util.LogExchange
import xsbti.api.{ClassLike, DependencyContext}
import xsbti.compile.DependencyChanges
+
+
object Subproject{
+ def runTests(frameworkName: String,
+ testClassloader: URLClassLoader) = {
+ val framework = Class.forName(frameworkName)
+ .newInstance()
+ .asInstanceOf[sbt.testing.Framework]
+
+ val fingerprints = framework.fingerprints()
+ val testClasses = for{
+ url <- testClassloader.getURLs
+ path <- ls.rec(ammonite.ops.Path(url.getFile)).toIterator
+ if path.ext == "class"
+ className = (path/up/path.last.stripSuffix(".class")).segments.mkString(".")
+ cls = testClassloader.loadClass(className)
+ if fingerprints.exists{
+ case f: SubclassFingerprint =>
+ cls.isAssignableFrom(cls)
+ case f: AnnotatedFingerprint =>
+ cls.isAnnotationPresent(
+ Class.forName(f.annotationName()).asInstanceOf[Class[Annotation]]
+ )
+ }
+ } yield cls
+
+
+ }
def compileScala(scalaVersion: String,
sources: PathRef,
compileClasspath: Seq[PathRef],