summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2018-01-14 03:31:06 -0800
committerLi Haoyi <haoyi.sg@gmail.com>2018-01-14 03:31:06 -0800
commit478bf87d3f140eaf2671663b5b3c1758354ec856 (patch)
treea8d61eccc5edba3479ce91ff7c3c3aaf57919fdb /core
parent708491342d8db05df6081c5e2edfe4037285f66e (diff)
downloadmill-478bf87d3f140eaf2671663b5b3c1758354ec856.tar.gz
mill-478bf87d3f140eaf2671663b5b3c1758354ec856.tar.bz2
mill-478bf87d3f140eaf2671663b5b3c1758354ec856.zip
Everything seems to compile with new, minimal `Discover` implementation...
Diffstat (limited to 'core')
-rw-r--r--core/src/main/scala/mill/define/Discover.scala44
-rw-r--r--core/src/main/scala/mill/define/Module.scala21
-rw-r--r--core/src/main/scala/mill/eval/Evaluator.scala10
-rw-r--r--core/src/main/scala/mill/main/MainRunner.scala9
-rw-r--r--core/src/main/scala/mill/main/ReplApplyHandler.scala24
-rw-r--r--core/src/main/scala/mill/main/Resolve.scala12
-rw-r--r--core/src/main/scala/mill/main/RunScript.scala40
-rw-r--r--core/src/test/scala/mill/main/MainTests.scala41
8 files changed, 147 insertions, 54 deletions
diff --git a/core/src/main/scala/mill/define/Discover.scala b/core/src/main/scala/mill/define/Discover.scala
new file mode 100644
index 00000000..a5bcd8c6
--- /dev/null
+++ b/core/src/main/scala/mill/define/Discover.scala
@@ -0,0 +1,44 @@
+package mill.define
+import language.experimental.macros
+import ammonite.main.Router.EntryPoint
+
+import scala.collection.mutable
+import scala.reflect.macros.blackbox
+
+case class Discover(value: Map[Class[_], Seq[EntryPoint[_]]])
+object Discover {
+ def apply[T]: Discover = macro applyImpl[T]
+
+ def applyImpl[T: c.WeakTypeTag](c: blackbox.Context): c.Expr[Discover] = {
+ import c.universe._
+ val seen = mutable.Set.empty[Type]
+ def rec(tpe: Type): Unit = {
+ println("Rec! " + tpe)
+ if (!seen(tpe)){
+ seen.add(tpe)
+ for{
+ m <- tpe.members
+ memberTpe = m.typeSignature
+ if memberTpe.resultType <:< typeOf[mill.define.Module] && memberTpe.paramLists.isEmpty
+ } rec(memberTpe.resultType)
+ }
+ }
+ rec(weakTypeOf[T])
+
+ val router = new ammonite.main.Router(c)
+ val mapping = for{
+ discoveredModuleType <- seen
+ val routes = router.getAllRoutesForClass(
+ discoveredModuleType.asInstanceOf[router.c.Type],
+ _.returnType <:< weakTypeOf[mill.define.Command[_]].asInstanceOf[router.c.Type]
+ ).map(_.asInstanceOf[c.Tree])
+ if routes.nonEmpty
+ } yield {
+ val lhs = q"classOf[${discoveredModuleType.typeSymbol.asClass}]"
+ val rhs = q"scala.Seq[ammonite.main.Router.EntryPoint[${discoveredModuleType.typeSymbol.asClass}]](..$routes)"
+ q"$lhs -> $rhs"
+ }
+
+ c.Expr[Discover](q"mill.define.Discover(scala.collection.immutable.Map(..$mapping))")
+ }
+}
diff --git a/core/src/main/scala/mill/define/Module.scala b/core/src/main/scala/mill/define/Module.scala
index f2ebe1f3..c9ce523c 100644
--- a/core/src/main/scala/mill/define/Module.scala
+++ b/core/src/main/scala/mill/define/Module.scala
@@ -25,7 +25,6 @@ object Module{
* the concrete instance.
*/
class Module(implicit ctx0: mill.define.Ctx, cmds: Module.Cmds) extends mill.moduledefs.Cacher{
- def commands: Seq[EntryPoint[Module]] = cmds.value
def traverse[T](f: Module => Seq[T]): Seq[T] = {
def rec(m: Module): Seq[T] = {
@@ -45,8 +44,8 @@ class Module(implicit ctx0: mill.define.Ctx, cmds: Module.Cmds) extends mill.mod
lazy val targets = segmentsToTargets.valuesIterator.toSet
lazy val segmentsToCommands = traverse{
- m => m.commands.map(e => m.ctx.segments ++ Seq(Segment.Label(e.name)) -> e)
- }.toMap
+ m => m.reflectNames[Command[_]].map(c => m.ctx.segments ++ Seq(Segment.Label(c)))
+ }.toSet
def ctx = ctx0
// Ensure we do not propagate the implicit parameters as implicits within
@@ -71,6 +70,22 @@ class Module(implicit ctx0: mill.define.Ctx, cmds: Module.Cmds) extends mill.mod
.filter(implicitly[ClassTag[T]].runtimeClass isAssignableFrom _.getReturnType)
.map(_.invoke(this).asInstanceOf[T])
}
+ def reflectNames[T: ClassTag] = {
+ this
+ .getClass
+ .getMethods
+ .filter(x => (x.getModifiers & Modifier.STATIC) == 0)
+ .filter(implicitly[ClassTag[T]].runtimeClass isAssignableFrom _.getReturnType)
+ .map(_.getName)
+ }
+ def reflectNestedObjects[T: ClassTag] = {
+ reflect[T] ++
+ this
+ .getClass
+ .getClasses
+ .filter(implicitly[ClassTag[T]].runtimeClass isAssignableFrom _)
+ .flatMap(c => c.getFields.find(_.getName == "MODULE$").map(_.get(c).asInstanceOf[T]))
+ }
}
trait TaskModule extends Module {
def defaultCommandName(): String
diff --git a/core/src/main/scala/mill/eval/Evaluator.scala b/core/src/main/scala/mill/eval/Evaluator.scala
index ee4ec27b..fbeb0c62 100644
--- a/core/src/main/scala/mill/eval/Evaluator.scala
+++ b/core/src/main/scala/mill/eval/Evaluator.scala
@@ -4,8 +4,9 @@ import java.net.URLClassLoader
import ammonite.ops._
import ammonite.runtime.SpecialClassLoader
-import mill.define.{Segment, Segments, NamedTask, Graph, Target, Task}
+import mill.define.{Graph, NamedTask, Segment, Segments, Target, Task}
import mill.util
+import mill.util.Ctx.Loader
import mill.util._
import mill.util.Strict.Agg
@@ -23,6 +24,9 @@ case class Labelled[T](target: NamedTask[T],
case _ => None
}
}
+object RootModuleLoader extends Loader[mill.Module] {
+ def make() = ???
+}
class Evaluator[T](val workspacePath: Path,
val basePath: Path,
val rootModule: mill.Module,
@@ -32,7 +36,7 @@ class Evaluator[T](val workspacePath: Path,
val workerCache = mutable.Map.empty[Ctx.Loader[_], Any]
-// workerCache(Discovered.Mapping) = rootModule
+ workerCache(RootModuleLoader) = rootModule
def evaluate(goals: Agg[Task[_]]): Evaluator.Results = {
mkdir(workspacePath)
@@ -43,7 +47,7 @@ class Evaluator[T](val workspacePath: Path,
val segments = t.ctx.segments
val (finalTaskOverrides, enclosing) = t match{
case t: Target[_] => rootModule.segmentsToTargets(segments).ctx.overrides -> t.ctx.enclosing
- case c: mill.define.Command[_] => rootModule.segmentsToCommands(segments).overrides -> c.ctx.enclosing
+ case c: mill.define.Command[_] => 0 -> c.ctx.enclosing
}
val additional =
if (finalTaskOverrides == t.ctx.overrides) Nil
diff --git a/core/src/main/scala/mill/main/MainRunner.scala b/core/src/main/scala/mill/main/MainRunner.scala
index 49fcfe2a..fd16161f 100644
--- a/core/src/main/scala/mill/main/MainRunner.scala
+++ b/core/src/main/scala/mill/main/MainRunner.scala
@@ -5,6 +5,7 @@ import ammonite.Main
import ammonite.interp.{Interpreter, Preprocessor}
import ammonite.ops.Path
import ammonite.util._
+import mill.define.Discover
import mill.eval.{Evaluator, PathRef}
import mill.util.PrintLogger
import upickle.Js
@@ -23,7 +24,7 @@ class MainRunner(config: ammonite.main.Cli.Config,
config, outprintStream, errPrintStream,
stdIn, outprintStream, errPrintStream
){
- var lastEvaluator: Option[(Seq[(Path, Long)], Evaluator[_])] = None
+ var lastEvaluator: Option[(Seq[(Path, Long)], Evaluator[_], Discover)] = None
override def runScript(scriptPath: Path, scriptArgs: List[String]) =
watchLoop(
@@ -47,9 +48,9 @@ class MainRunner(config: ammonite.main.Cli.Config,
result match{
case Res.Success(data) =>
- val (eval, evaluationWatches, res) = data
+ val (eval, discover, evaluationWatches, res) = data
- lastEvaluator = Some((interpWatched, eval))
+ lastEvaluator = Some((interpWatched, eval, discover))
(Res(res), interpWatched ++ evaluationWatches)
case _ => (result, interpWatched)
@@ -96,6 +97,8 @@ class MainRunner(config: ammonite.main.Cli.Config,
| // Stub to make sure Ammonite has something to call after it evaluates a script,
| // even if it does nothing...
| def $$main() = Iterator[String]()
+ |
+ | val millDiscover = mill.define.Discover[$wrapName]
|}
|
|sealed trait $wrapName extends mill.Module{
diff --git a/core/src/main/scala/mill/main/ReplApplyHandler.scala b/core/src/main/scala/mill/main/ReplApplyHandler.scala
index f7f44270..909f25f7 100644
--- a/core/src/main/scala/mill/main/ReplApplyHandler.scala
+++ b/core/src/main/scala/mill/main/ReplApplyHandler.scala
@@ -2,6 +2,7 @@ package mill.main
import mill.define.Applicative.ApplyHandler
+import mill.define.Segment.Label
import mill.define._
import mill.eval.{Evaluator, Result}
import mill.util.Strict.Agg
@@ -10,7 +11,8 @@ import scala.collection.mutable
object ReplApplyHandler{
def apply[T](colors: ammonite.util.Colors,
pprinter0: pprint.PPrinter,
- rootModule: mill.Module) = {
+ rootModule: mill.Module,
+ discover: Discover) = {
new ReplApplyHandler(
pprinter0,
new mill.eval.Evaluator(
@@ -24,11 +26,14 @@ object ReplApplyHandler{
System.err,
System.err
)
- )
+ ),
+ discover
)
}
}
-class ReplApplyHandler(pprinter0: pprint.PPrinter, evaluator: Evaluator[_]) extends ApplyHandler[Task] {
+class ReplApplyHandler(pprinter0: pprint.PPrinter,
+ evaluator: Evaluator[_],
+ discover: Discover) extends ApplyHandler[Task] {
// Evaluate classLoaderSig only once in the REPL to avoid busting caches
// as the user enters more REPL commands and changes the classpath
val classLoaderSig = Evaluator.classLoaderSig
@@ -75,11 +80,14 @@ class ReplApplyHandler(pprinter0: pprint.PPrinter, evaluator: Evaluator[_]) exte
Iterator(m.millModuleEnclosing, ":", m.millModuleLine.toString) ++
(if (m.reflect[mill.Module].isEmpty) Nil
else ctx.applyPrefixColor("\nChildren:").toString +: m.reflect[mill.Module].map("\n ." + _.ctx.segments.render)) ++
- (if (m.commands.isEmpty) Nil
- else ctx.applyPrefixColor("\nCommands:").toString +: m.commands.sortBy(_.name).map{c =>
- "\n ." + c.name + "(" +
- c.argSignatures.map(s => s.name + ": " + s.typeString).mkString(", ") +
- ")()"
+ (discover.value.get(m.getClass) match{
+ case None => Nil
+ case Some(commands) =>
+ ctx.applyPrefixColor("\nCommands:").toString +: commands.map{c =>
+ "\n ." + c.name + "(" +
+ c.argSignatures.map(s => s.name + ": " + s.typeString).mkString(", ") +
+ ")()"
+ }
}) ++
(if (m.reflect[Target[_]].isEmpty) Nil
else {
diff --git a/core/src/main/scala/mill/main/Resolve.scala b/core/src/main/scala/mill/main/Resolve.scala
index e50e0ca9..df3c250d 100644
--- a/core/src/main/scala/mill/main/Resolve.scala
+++ b/core/src/main/scala/mill/main/Resolve.scala
@@ -3,10 +3,12 @@ package mill.main
import mill.define._
import mill.define.TaskModule
import ammonite.main.Router
+import ammonite.main.Router.EntryPoint
object Resolve {
def resolve[T, V](remainingSelector: List[Segment],
obj: mill.Module,
+ discover: Discover,
rest: Seq[String],
remainingCrossSelectors: List[List[String]],
revSelectorsSoFar: List[Segment]): Either[String, Task[Any]] = {
@@ -21,8 +23,8 @@ object Resolve {
.map(Right(_))
def invokeCommand[V](target: mill.Module, name: String) = for{
- cmd <- target.commands.find(_.name == name)
- } yield cmd.invoke(target, ammonite.main.Scripts.groupArgs(rest.toList)) match {
+ cmd <- discover.value.get(target.getClass).toSeq.flatten.find(_.name == name)
+ } yield cmd.asInstanceOf[EntryPoint[mill.Module]].invoke(target, ammonite.main.Scripts.groupArgs(rest.toList)) match {
case Router.Result.Success(v) => Right(v)
case _ => Left(s"Command failed $last")
}
@@ -52,10 +54,10 @@ object Resolve {
val newRevSelectorsSoFar = head :: revSelectorsSoFar
head match{
case Segment.Label(singleLabel) =>
- obj.reflect[mill.Module].find{
+ obj.reflectNestedObjects[mill.Module].find{
_.ctx.segment == Segment.Label(singleLabel)
} match{
- case Some(child: mill.Module) => resolve(tail, child, rest, remainingCrossSelectors, newRevSelectorsSoFar)
+ case Some(child: mill.Module) => resolve(tail, child, discover, rest, remainingCrossSelectors, newRevSelectorsSoFar)
case None => Left("Cannot resolve module " + Segments(newRevSelectorsSoFar.reverse:_*).render)
}
@@ -63,7 +65,7 @@ object Resolve {
obj match{
case c: Cross[_] =>
c.itemMap.get(cross.toList) match{
- case Some(m: mill.Module) => resolve(tail, m, rest, remainingCrossSelectors, newRevSelectorsSoFar)
+ case Some(m: mill.Module) => resolve(tail, m, discover, rest, remainingCrossSelectors, newRevSelectorsSoFar)
case None => Left("Cannot resolve cross " + Segments(newRevSelectorsSoFar.reverse:_*).render)
}
diff --git a/core/src/main/scala/mill/main/RunScript.scala b/core/src/main/scala/mill/main/RunScript.scala
index acabcf0a..8ad144d3 100644
--- a/core/src/main/scala/mill/main/RunScript.scala
+++ b/core/src/main/scala/mill/main/RunScript.scala
@@ -7,8 +7,7 @@ import ammonite.ops.{Path, read}
import ammonite.util.Util.CodeSource
import ammonite.util.{Name, Res, Util}
import mill.{PathRef, define}
-import mill.define.Task
-import mill.define.Segment
+import mill.define.{Discover, Segment, Task}
import mill.eval.{Evaluator, Result}
import mill.util.{EitherOps, Logger}
import mill.util.Strict.Agg
@@ -24,15 +23,15 @@ object RunScript{
path: Path,
instantiateInterpreter: => Either[(Res.Failing, Seq[(Path, Long)]), ammonite.interp.Interpreter],
scriptArgs: Seq[String],
- lastEvaluator: Option[(Seq[(Path, Long)], Evaluator[_])],
+ lastEvaluator: Option[(Seq[(Path, Long)], Evaluator[_], Discover)],
log: Logger)
- : (Res[(Evaluator[_], Seq[(Path, Long)], Either[String, Seq[Js.Value]])], Seq[(Path, Long)]) = {
+ : (Res[(Evaluator[_], Discover, Seq[(Path, Long)], Either[String, Seq[Js.Value]])], Seq[(Path, Long)]) = {
val (evalRes, interpWatched) = lastEvaluator match{
- case Some((prevInterpWatchedSig, prevEvaluator))
+ case Some((prevInterpWatchedSig, prevEvaluator, prevDiscover))
if watchedSigUnchanged(prevInterpWatchedSig) =>
- (Res.Success(prevEvaluator), prevInterpWatchedSig)
+ (Res.Success(prevEvaluator -> prevDiscover), prevInterpWatchedSig)
case _ =>
instantiateInterpreter match{
@@ -40,15 +39,15 @@ object RunScript{
case Right(interp) =>
interp.watch(path)
val eval =
- for(mapping <- evaluateMapping(wd, path, interp))
- yield new Evaluator(wd / 'out, wd, mapping, log)
+ for((mapping, discover) <- evaluateMapping(wd, path, interp))
+ yield (new Evaluator(wd / 'out, wd, mapping, log), discover)
(eval, interp.watchedFiles)
}
}
val evaluated = for{
- evaluator <- evalRes
- (evalWatches, res) <- Res(evaluateTarget(evaluator, scriptArgs))
+ (evaluator, discover) <- evalRes
+ (evalWatches, res) <- Res(evaluateTarget(evaluator, discover, scriptArgs))
} yield {
val alreadyStale = evalWatches.exists(p => p.sig != new PathRef(p.path, p.quick).sig)
// If the file changed between the creation of the original
@@ -61,7 +60,7 @@ object RunScript{
if (alreadyStale) evalWatches.map(_.path -> util.Random.nextLong())
else evalWatches.map(p => p.path -> Interpreter.pathSignature(p.path))
- (evaluator, evaluationWatches, res.map(_.flatMap(_._2)))
+ (evaluator, discover, evaluationWatches, res.map(_.flatMap(_._2)))
}
(evaluated, interpWatched)
}
@@ -72,7 +71,7 @@ object RunScript{
def evaluateMapping(wd: Path,
path: Path,
- interp: ammonite.interp.Interpreter): Res[mill.Module] = {
+ interp: ammonite.interp.Interpreter): Res[(mill.Module, Discover)] = {
val (pkg, wrapper) = Util.pathToPackageWrapper(Seq(), path relativeTo wd)
@@ -98,7 +97,7 @@ object RunScript{
.evalClassloader
.loadClass(buildClsName)
- mapping <- try {
+ module <- try {
Util.withContextClassloader(interp.evalClassloader) {
Res.Success(
buildCls.getField("MODULE$")
@@ -109,11 +108,23 @@ object RunScript{
} catch {
case e: Throwable => Res.Exception(e, "")
}
+ discover <- try {
+ Util.withContextClassloader(interp.evalClassloader) {
+ Res.Success(
+ buildCls.getMethod("millDiscover")
+ .invoke(null)
+ .asInstanceOf[Discover]
+ )
+ }
+ } catch {
+ case e: Throwable => Res.Exception(e, "")
+ }
// _ <- Res(consistencyCheck(mapping))
- } yield mapping
+ } yield (module, discover)
}
def evaluateTarget[T](evaluator: Evaluator[_],
+ discover: Discover,
scriptArgs: Seq[String]) = {
for {
parsed <- ParseArgs(scriptArgs)
@@ -126,6 +137,7 @@ object RunScript{
}
mill.main.Resolve.resolve(
sel, evaluator.rootModule,
+ discover,
args, crossSelectors, Nil
)
}
diff --git a/core/src/test/scala/mill/main/MainTests.scala b/core/src/test/scala/mill/main/MainTests.scala
index a22cb5a6..62d87fce 100644
--- a/core/src/test/scala/mill/main/MainTests.scala
+++ b/core/src/test/scala/mill/main/MainTests.scala
@@ -1,19 +1,20 @@
package mill.main
import mill.Module
-import mill.define.{Segment, Task}
+import mill.define.{Discover, Segment, Task}
import mill.util.TestGraphs._
import mill.util.TestUtil.test
import utest._
object MainTests extends TestSuite{
def check[T](module: mill.Module,
+ discover: Discover,
selectorString: String,
expected: Either[String, Task[_]]) = {
val resolved = for{
selectors <- mill.main.ParseArgs(Seq(selectorString)).map(_._1.head)
val crossSelectors = selectors.map{case Segment.Cross(x) => x.toList.map(_.toString) case _ => Nil}
- task <- mill.main.Resolve.resolve(selectors, module, Nil, crossSelectors, Nil)
+ task <- mill.main.Resolve.resolve(selectors, module, discover, Nil, crossSelectors, Nil)
} yield task
assert(resolved == expected)
}
@@ -21,29 +22,29 @@ object MainTests extends TestSuite{
val graphs = new mill.util.TestGraphs()
import graphs._
'single - {
- 'pos - check(singleton, "single", Right(singleton.single))
- 'neg1 - check(singleton, "doesntExist", Left("Cannot resolve task doesntExist"))
- 'neg2 - check(singleton, "single.doesntExist", Left("Cannot resolve module single"))
- 'neg3 - check(singleton, "", Left("Selector cannot be empty"))
+ 'pos - check(singleton, Discover[singleton.type], "single", Right(singleton.single))
+ 'neg1 - check(singleton, Discover[singleton.type], "doesntExist", Left("Cannot resolve task doesntExist"))
+ 'neg2 - check(singleton, Discover[singleton.type], "single.doesntExist", Left("Cannot resolve module single"))
+ 'neg3 - check(singleton, Discover[singleton.type], "", Left("Selector cannot be empty"))
}
'nested - {
- 'pos1 - check(nestedModule, "single", Right(nestedModule.single))
- 'pos2 - check(nestedModule, "nested.single", Right(nestedModule.nested.single))
- 'pos3 - check(nestedModule, "classInstance.single", Right(nestedModule.classInstance.single))
- 'neg1 - check(nestedModule, "doesntExist", Left("Cannot resolve task doesntExist"))
- 'neg2 - check(nestedModule, "single.doesntExist", Left("Cannot resolve module single"))
- 'neg3 - check(nestedModule, "nested.doesntExist", Left("Cannot resolve task nested.doesntExist"))
- 'neg4 - check(nestedModule, "classInstance.doesntExist", Left("Cannot resolve task classInstance.doesntExist"))
+ 'pos1 - check(nestedModule, Discover[nestedModule.type], "single", Right(nestedModule.single))
+ 'pos2 - check(nestedModule, Discover[nestedModule.type], "nested.single", Right(nestedModule.nested.single))
+ 'pos3 - check(nestedModule, Discover[nestedModule.type], "classInstance.single", Right(nestedModule.classInstance.single))
+ 'neg1 - check(nestedModule, Discover[nestedModule.type], "doesntExist", Left("Cannot resolve task doesntExist"))
+ 'neg2 - check(nestedModule, Discover[nestedModule.type], "single.doesntExist", Left("Cannot resolve module single"))
+ 'neg3 - check(nestedModule, Discover[nestedModule.type], "nested.doesntExist", Left("Cannot resolve task nested.doesntExist"))
+ 'neg4 - check(nestedModule, Discover[nestedModule.type], "classInstance.doesntExist", Left("Cannot resolve task classInstance.doesntExist"))
}
'cross - {
'single - {
- 'pos1 - check(singleCross, "cross[210].suffix", Right(singleCross.cross("210").suffix))
- 'pos2 - check(singleCross, "cross[211].suffix", Right(singleCross.cross("211").suffix))
- 'neg1 - check(singleCross, "cross[210].doesntExist", Left("Cannot resolve task cross[210].doesntExist"))
- 'neg2 - check(singleCross, "cross[doesntExist].doesntExist", Left("Cannot resolve cross cross[doesntExist]"))
- 'neg2 - check(singleCross, "cross[doesntExist].suffix", Left("Cannot resolve cross cross[doesntExist]"))
+ 'pos1 - check(singleCross, Discover[singleCross.type], "cross[210].suffix", Right(singleCross.cross("210").suffix))
+ 'pos2 - check(singleCross, Discover[singleCross.type], "cross[211].suffix", Right(singleCross.cross("211").suffix))
+ 'neg1 - check(singleCross, Discover[singleCross.type], "cross[210].doesntExist", Left("Cannot resolve task cross[210].doesntExist"))
+ 'neg2 - check(singleCross, Discover[singleCross.type], "cross[doesntExist].doesntExist", Left("Cannot resolve cross cross[doesntExist]"))
+ 'neg2 - check(singleCross, Discover[singleCross.type], "cross[doesntExist].suffix", Left("Cannot resolve cross cross[doesntExist]"))
}
// 'double - {
//
@@ -62,11 +63,13 @@ object MainTests extends TestSuite{
'indirect - {
'pos1 - check(
indirectNestedCrosses,
+ Discover[indirectNestedCrosses.type],
"cross[210].cross2[js].suffix",
Right(indirectNestedCrosses.cross("210").cross2("js").suffix)
)
'pos2 - check(
indirectNestedCrosses,
+ Discover[indirectNestedCrosses.type],
"cross[211].cross2[jvm].suffix",
Right(indirectNestedCrosses.cross("211").cross2("jvm").suffix)
)
@@ -74,11 +77,13 @@ object MainTests extends TestSuite{
'direct - {
'pos1 - check(
nestedCrosses,
+ Discover[nestedCrosses.type],
"cross[210].cross2[js].suffix",
Right(nestedCrosses.cross("210").cross2("js").suffix)
)
'pos2 - check(
nestedCrosses,
+ Discover[nestedCrosses.type],
"cross[211].cross2[jvm].suffix",
Right(nestedCrosses.cross("211").cross2("jvm").suffix)
)