From 30d753f43b28afe49cc803a3cc1d25956d6d7e52 Mon Sep 17 00:00:00 2001 From: Nikolay Tatarinov <5min4eq.unity@gmail.com> Date: Mon, 26 Feb 2018 08:35:41 +0300 Subject: make scala.js work with multi-module projects (#165) --- scalajslib/src/mill/scalajslib/ScalaJSModule.scala | 25 +++--- .../resources/multi-module/client/src/Lib.scala | 8 ++ .../resources/multi-module/client/src/Main.scala | 6 ++ .../multi-module/client/test/src/MainTests.scala | 26 ++++++ .../multi-module/shared/src/shared/Utils.scala | 5 ++ .../src/mill/scalajslib/HelloJSWorldTests.scala | 19 +---- .../src/mill/scalajslib/MultiModuleTests.scala | 99 ++++++++++++++++++++++ .../test/src/mill/scalajslib/ScalaJsUtils.scala | 23 +++++ 8 files changed, 178 insertions(+), 33 deletions(-) create mode 100644 scalajslib/test/resources/multi-module/client/src/Lib.scala create mode 100644 scalajslib/test/resources/multi-module/client/src/Main.scala create mode 100644 scalajslib/test/resources/multi-module/client/test/src/MainTests.scala create mode 100644 scalajslib/test/resources/multi-module/shared/src/shared/Utils.scala create mode 100644 scalajslib/test/src/mill/scalajslib/MultiModuleTests.scala create mode 100644 scalajslib/test/src/mill/scalajslib/ScalaJsUtils.scala (limited to 'scalajslib') diff --git a/scalajslib/src/mill/scalajslib/ScalaJSModule.scala b/scalajslib/src/mill/scalajslib/ScalaJSModule.scala index ab67cd95..6fc3e964 100644 --- a/scalajslib/src/mill/scalajslib/ScalaJSModule.scala +++ b/scalajslib/src/mill/scalajslib/ScalaJSModule.scala @@ -1,7 +1,7 @@ package mill package scalajslib -import ammonite.ops.{Path, ls, mkdir, rm} +import ammonite.ops.{Path, exists, ls, mkdir, rm} import coursier.Cache import coursier.maven.MavenRepository import mill.eval.PathRef @@ -69,7 +69,6 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => link( ScalaJSBridge.scalaJSBridge(), toolsClasspath(), - Seq(compile()), runClasspath(), mainClass(), FastOpt @@ -80,7 +79,6 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => link( ScalaJSBridge.scalaJSBridge(), toolsClasspath(), - Seq(compile()), runClasspath(), mainClass(), FullOpt @@ -106,7 +104,6 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => val linkedFile = link( ScalaJSBridge.scalaJSBridge(), toolsClasspath(), - Seq(compile()), runClasspath(), Some(mainClass), FastOpt @@ -120,8 +117,7 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => def link(worker: ScalaJSWorker, toolsClasspath: Agg[PathRef], - input: Seq[CompilationResult], - libraries: Agg[PathRef], + runClasspath: Agg[PathRef], mainClass: Option[String], mode: OptimizeMode)(implicit ctx: Ctx.Dest): PathRef = { val outputPath = ctx.dest / "out.js" @@ -129,16 +125,16 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => mkdir(ctx.dest) rm(outputPath) - val inputFiles = Agg.from(for { - compiled <- input - file <- ls.rec(compiled.classes.path) - if file.ext == "sjsir" - } yield file) - val inputLibraries = libraries.map(_.path).filter(_.ext == "jar") + val classpath = runClasspath.map(_.path) + val sjsirFiles = classpath + .filter(path => exists(path) && path.isDir) + .flatMap(ls.rec) + .filter(_.ext == "sjsir") + val libraries = classpath.filter(_.ext == "jar") worker.link( toolsClasspath.map(_.path), - inputFiles, - inputLibraries, + sjsirFiles, + libraries, outputPath.toIO, mainClass, mode == FullOpt @@ -182,7 +178,6 @@ trait TestScalaJSModule extends ScalaJSModule with TestModule { link( ScalaJSBridge.scalaJSBridge(), toolsClasspath(), - compile() +: upstreamCompileOutput(), scalaJSTestDeps() ++ runClasspath(), None, FastOpt diff --git a/scalajslib/test/resources/multi-module/client/src/Lib.scala b/scalajslib/test/resources/multi-module/client/src/Lib.scala new file mode 100644 index 00000000..183f19f6 --- /dev/null +++ b/scalajslib/test/resources/multi-module/client/src/Lib.scala @@ -0,0 +1,8 @@ +import shared.Utils + +object Lib { + def parse(s:String): Seq[String] = s.split(":").toSeq + def addTwice(a: Int, b: Int) = Utils.add(a,b) + Utils.add(a,b) + def vmName = sys.props("java.vm.name") + +} diff --git a/scalajslib/test/resources/multi-module/client/src/Main.scala b/scalajslib/test/resources/multi-module/client/src/Main.scala new file mode 100644 index 00000000..ed4a9b99 --- /dev/null +++ b/scalajslib/test/resources/multi-module/client/src/Main.scala @@ -0,0 +1,6 @@ +import shared.Utils + +object Main extends App { + val result = Utils.add(1, 2) + println(s"Hello from ${Lib.vmName}, result is: ${result}") +} diff --git a/scalajslib/test/resources/multi-module/client/test/src/MainTests.scala b/scalajslib/test/resources/multi-module/client/test/src/MainTests.scala new file mode 100644 index 00000000..66670233 --- /dev/null +++ b/scalajslib/test/resources/multi-module/client/test/src/MainTests.scala @@ -0,0 +1,26 @@ +import utest._ +import shared.Utils + +object MainTests extends TestSuite { + def tests: Tests = Tests { + 'Lib - { + 'addTwice - { + assert( + Lib.addTwice(1, 2) == 6 + ) + } + 'parse - { + assert( + Lib.parse("hello:world") == Seq("hello", "world") + ) + } + } + 'shared - { + 'add - { + assert( + Utils.add(1, 2) == 3 + ) + } + } + } +} diff --git a/scalajslib/test/resources/multi-module/shared/src/shared/Utils.scala b/scalajslib/test/resources/multi-module/shared/src/shared/Utils.scala new file mode 100644 index 00000000..fad61a31 --- /dev/null +++ b/scalajslib/test/resources/multi-module/shared/src/shared/Utils.scala @@ -0,0 +1,5 @@ +package shared + +object Utils { + def add(a: Int, b: Int) = a + b +} diff --git a/scalajslib/test/src/mill/scalajslib/HelloJSWorldTests.scala b/scalajslib/test/src/mill/scalajslib/HelloJSWorldTests.scala index 189e9634..d2cfc4da 100644 --- a/scalajslib/test/src/mill/scalajslib/HelloJSWorldTests.scala +++ b/scalajslib/test/src/mill/scalajslib/HelloJSWorldTests.scala @@ -1,8 +1,6 @@ package mill.scalajslib -import java.io.{FileReader, StringWriter} import java.util.jar.JarFile -import javax.script.{ScriptContext, ScriptEngineManager} import ammonite.ops._ import mill._ @@ -85,21 +83,6 @@ object HelloJSWorldTests extends TestSuite { val mainObject = helloWorldEvaluator.outPath / 'src / "Main.scala" - class Console { - val out = new StringWriter() - def log(s: String): Unit = out.append(s) - } - - def runJS(path: Path): String = { - val engineManager = new ScriptEngineManager(null) - val engine = engineManager.getEngineByName("nashorn") - val console = new Console - val bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE) - bindings.put("console", console) - engine.eval(new FileReader(path.toIO)) - console.out.toString - } - def tests: Tests = Tests { prepareWorkspace() 'compile - { @@ -136,7 +119,7 @@ object HelloJSWorldTests extends TestSuite { case FastOpt => HelloJSWorld.helloJsWorld(scalaVersion, scalaJSVersion).fastOpt } val Right((result, evalCount)) = helloWorldEvaluator(task) - val output = runJS(result.path) + val output = ScalaJsUtils.runJS(result.path) assert(output == "Hello Scala.js") } diff --git a/scalajslib/test/src/mill/scalajslib/MultiModuleTests.scala b/scalajslib/test/src/mill/scalajslib/MultiModuleTests.scala new file mode 100644 index 00000000..0f2df335 --- /dev/null +++ b/scalajslib/test/src/mill/scalajslib/MultiModuleTests.scala @@ -0,0 +1,99 @@ +package mill.scalajslib + +import ammonite.ops._ +import mill._ +import mill.define.Discover +import mill.eval.Evaluator +import mill.util._ +import mill.scalalib._ +import utest._ + +object MultiModuleTests extends TestSuite { + val workspacePath = TestUtil.getOutPathStatic() / "multi-module" + val sourcePath = pwd / 'scalajslib / 'test / 'resources / "multi-module" + + object MultiModule extends TestUtil.BaseModule { + trait BaseModule extends ScalaJSModule { + def scalaVersion = "2.12.4" + def scalaJSVersion = "0.6.22" + } + + object client extends BaseModule { + override def millSourcePath = workspacePath / 'client + override def moduleDeps = Seq(shared) + override def mainClass = Some("Main") + object test extends Tests { + def testFrameworks = Seq("utest.runner.Framework") + override def ivyDeps = Agg(ivy"com.lihaoyi::utest::0.6.3") + } + } + + object shared extends BaseModule { + override def millSourcePath = workspacePath / 'shared + } + + override def millDiscover = Discover[this.type] + } + + val evaluator = TestEvaluator.static(MultiModule) + + def tests: Tests = Tests { + prepareWorkspace() + + def checkOpt(mode: OptimizeMode) = { + val task = mode match { + case FullOpt => MultiModule.client.fullOpt + case FastOpt => MultiModule.client.fastOpt + } + val Right((linked, evalCount)) = evaluator(task) + + val runOutput = ScalaJsUtils.runJS(linked.path) + assert( + evalCount > 0, + runOutput == "Hello from Scala.js, result is: 3" + ) + } + + 'fastOpt - checkOpt(FastOpt) + 'fullOpt - checkOpt(FullOpt) + + 'test - { + val Right(((_, testResults), evalCount)) = evaluator(MultiModule.client.test.test()) + + assert( + evalCount > 0, + testResults.size == 3, + testResults.forall(_.status == "Success") + ) + } + + def checkRun(mainClass: Option[String] = None) = { + val command = mainClass match { + case Some(main) => MultiModule.client.runMain(main) + case None => MultiModule.client.run() + } + val Right((_, evalCount)) = evaluator(command) + + val paths = Evaluator.resolveDestPaths( + evaluator.outPath, + command.ctx.segments + ) + val log = read(paths.log) + assert( + evalCount > 0, + log.contains("node"), + log.contains("Hello from Scala.js, result is: 3") + ) + } + + 'run - checkRun() + 'runMain - checkRun(mainClass = Some("Main")) + } + + def prepareWorkspace(): Unit = { + rm(workspacePath) + mkdir(workspacePath / up) + cp(sourcePath, workspacePath) + } + +} diff --git a/scalajslib/test/src/mill/scalajslib/ScalaJsUtils.scala b/scalajslib/test/src/mill/scalajslib/ScalaJsUtils.scala new file mode 100644 index 00000000..859d2d56 --- /dev/null +++ b/scalajslib/test/src/mill/scalajslib/ScalaJsUtils.scala @@ -0,0 +1,23 @@ +package mill.scalajslib + +import java.io.{FileReader, StringWriter} +import javax.script.{ScriptContext, ScriptEngineManager} + +import ammonite.ops.Path + +object ScalaJsUtils { + def runJS(path: Path): String = { + val engineManager = new ScriptEngineManager(null) + val engine = engineManager.getEngineByName("nashorn") + val console = new Console + val bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE) + bindings.put("console", console) + engine.eval(new FileReader(path.toIO)) + console.out.toString + } +} + +class Console { + val out = new StringWriter() + def log(s: String): Unit = out.append(s) +} -- cgit v1.2.3