Cleanup local Scripted plugin

This commit is contained in:
Dale Wijnand 2018-01-24 13:42:18 +00:00
parent 41249f707a
commit 8187a51d31
No known key found for this signature in database
GPG Key ID: 4F256E3D151DF5EF
2 changed files with 58 additions and 46 deletions

View File

@ -557,7 +557,6 @@ lazy val vscodePlugin = (project in file("vscode-sbt-scala"))
)
def scriptedTask: Def.Initialize[InputTask[Unit]] = Def.inputTask {
val result = scriptedSource(dir => (s: State) => Scripted.scriptedParser(dir)).parsed
// publishLocalBinAll.value // TODO: Restore scripted needing only binary jars.
publishAll.value
(sbtProj / Test / compile).value // make sure sbt.RunFromSourceMain is compiled
@ -567,21 +566,20 @@ def scriptedTask: Def.Initialize[InputTask[Unit]] = Def.inputTask {
(scalaInstance in scriptedSbtProj).value,
scriptedSource.value,
scriptedBufferLog.value,
result,
Def.setting(Scripted.scriptedParser(scriptedSource.value)).parsed,
scriptedPrescripted.value,
scriptedLaunchOpts.value
)
}
def scriptedUnpublishedTask: Def.Initialize[InputTask[Unit]] = Def.inputTask {
val result = scriptedSource(dir => (s: State) => Scripted.scriptedParser(dir)).parsed
Scripted.doScripted(
(sbtLaunchJar in bundledLauncherProj).value,
(fullClasspath in scriptedSbtProj in Test).value,
(scalaInstance in scriptedSbtProj).value,
scriptedSource.value,
scriptedBufferLog.value,
result,
Def.setting(Scripted.scriptedParser(scriptedSource.value)).parsed,
scriptedPrescripted.value,
scriptedLaunchOpts.value
)

View File

@ -1,13 +1,12 @@
import java.lang.reflect.InvocationTargetException
import sbt._
import Keys._
import Def.Initialize
import sbt.internal.inc.ScalaInstance
import sbt.internal.inc.classpath
import sbt.internal.inc.classpath.{ ClasspathUtilities, FilteredLoader }
import scala.language.reflectiveCalls
object ScriptedPlugin extends sbt.AutoPlugin {
object ScriptedPlugin extends AutoPlugin {
override def requires = plugins.JvmPlugin
object autoImport extends ScriptedKeys {
def scriptedPath = file("scripted")
}
@ -39,27 +38,31 @@ object Scripted {
val RepoOverrideTest = config("repoOverrideTest") extend Compile
import sbt.complete._
import DefaultParsers._
// Paging, 1-index based.
case class ScriptedTestPage(page: Int, total: Int)
final case class ScriptedTestPage(page: Int, total: Int)
// FIXME: Duplicated with ScriptedPlugin.scriptedParser, this can be
// avoided once we upgrade build.properties to 0.13.14
def scriptedParser(scriptedBase: File): Parser[Seq[String]] = {
import DefaultParsers._
val scriptedFiles: NameFilter = ("test": NameFilter) | "pending"
val pairs = (scriptedBase * AllPassFilter * AllPassFilter * scriptedFiles).get map {
(f: File) =>
val p = f.getParentFile
(p.getParentFile.getName, p.getName)
}
val pairMap = pairs.groupBy(_._1).mapValues(_.map(_._2).toSet);
val pairMap = pairs.groupBy(_._1).mapValues(_.map(_._2).toSet)
val id = charClass(c => !c.isWhitespace && c != '/').+.string
val groupP = token(id.examples(pairMap.keySet.toSet)) <~ token('/')
val groupP = token(id.examples(pairMap.keySet)) <~ token('/')
// A parser for page definitions
val pageP: Parser[ScriptedTestPage] = ("*" ~ NatBasic ~ "of" ~ NatBasic) map {
case _ ~ page ~ _ ~ total => ScriptedTestPage(page, total)
}
// Grabs the filenames from a given test group in the current page definition.
def pagedFilenames(group: String, page: ScriptedTestPage): Seq[String] = {
val files = pairMap(group).toSeq.sortBy(_.toLowerCase)
@ -69,9 +72,11 @@ object Scripted {
if (page.page == page.total) dropped
else dropped.take(pageSize)
}
def nameP(group: String) = {
token("*".id | id.examples(pairMap.getOrElse(group, Set.empty[String])))
}
val PagedIds: Parser[Seq[String]] =
for {
group <- groupP
@ -79,55 +84,64 @@ object Scripted {
files = pagedFilenames(group, page)
// TODO - Fail the parser if we don't have enough files for the given page size
//if !files.isEmpty
} yield files map (f => group + '/' + f)
} yield files map (f => s"$group/$f")
val testID = (for (group <- groupP; name <- nameP(group)) yield (group, name))
val testIdAsGroup = matched(testID) map (test => Seq(test))
//(token(Space) ~> matched(testID)).*
(token(Space) ~> (PagedIds | testIdAsGroup)).* map (_.flatten)
}
// Interface to cross class loader
type SbtScriptedRunner = {
def runInParallel(resourceBaseDirectory: File,
bufferLog: Boolean,
tests: Array[String],
bootProperties: File,
launchOpts: Array[String],
prescripted: java.util.List[File]): Unit
}
def doScripted(launcher: File,
scriptedSbtClasspath: Seq[Attributed[File]],
scriptedSbtInstance: ScalaInstance,
sourcePath: File,
bufferLog: Boolean,
args: Seq[String],
prescripted: File => Unit,
launchOpts: Seq[String]): Unit = {
def doScripted(
launcher: File,
scriptedSbtClasspath: Seq[Attributed[File]],
scriptedSbtInstance: ScalaInstance,
sourcePath: File,
bufferLog: Boolean,
args: Seq[String],
prescripted: File => Unit,
launchOpts: Seq[String],
): Unit = {
System.err.println(s"About to run tests: ${args.mkString("\n * ", "\n * ", "\n")}")
// Force Log4J to not use a thread context classloader otherwise it throws a CCE
sys.props(org.apache.logging.log4j.util.LoaderUtil.IGNORE_TCCL_PROPERTY) = "true"
val noJLine = new classpath.FilteredLoader(scriptedSbtInstance.loader, "jline." :: Nil)
val loader = classpath.ClasspathUtilities.toLoader(scriptedSbtClasspath.files, noJLine)
val noJLine = new FilteredLoader(scriptedSbtInstance.loader, "jline." :: Nil)
val loader = ClasspathUtilities.toLoader(scriptedSbtClasspath.files, noJLine)
val bridgeClass = Class.forName("sbt.scriptedtest.ScriptedRunner", true, loader)
// Interface to cross class loader
type SbtScriptedRunner = {
def runInParallel(
resourceBaseDirectory: File,
bufferLog: Boolean,
tests: Array[String],
bootProperties: File,
launchOpts: Array[String],
prescripted: java.util.List[File],
): Unit
}
val bridge = bridgeClass.getDeclaredConstructor().newInstance().asInstanceOf[SbtScriptedRunner]
try {
// Using java.util.List to encode File => Unit.
val callback = new java.util.AbstractList[File] {
override def add(x: File): Boolean = {
prescripted(x)
false
}
override def add(x: File): Boolean = { prescripted(x); false }
def get(x: Int): sbt.File = ???
def size(): Int = 0
}
bridge.runInParallel(sourcePath,
bufferLog,
args.toArray,
launcher,
launchOpts.toArray,
callback)
} catch { case ite: java.lang.reflect.InvocationTargetException => throw ite.getCause }
import scala.language.reflectiveCalls
bridge.runInParallel(
sourcePath,
bufferLog,
args.toArray,
launcher,
launchOpts.toArray,
callback,
)
} catch { case ite: InvocationTargetException => throw ite.getCause }
}
}