From 1db46095629ffaf2821807ddf1929dd7b90036c9 Mon Sep 17 00:00:00 2001 From: Semion Sidorenko Date: Wed, 3 Jun 2015 15:16:37 +0200 Subject: [PATCH 1/5] Add support for scala.js --- project/Scoverage.scala | 32 ++++-- project/plugins.sbt | 2 + .../scala/scoverage/ScoverageCompiler.scala | 2 +- .../src/main/scala/scalajssupport/File.scala | 73 ++++++++++++++ .../scala/scalajssupport/FileWriter.scala | 23 +++++ .../main/scala/scalajssupport/JsFile.scala | 32 ++++++ .../main/scala/scalajssupport/NodeFile.scala | 99 +++++++++++++++++++ .../scala/scalajssupport/PhantomFile.scala | 82 +++++++++++++++ .../main/scala/scalajssupport/RhinoFile.scala | 84 ++++++++++++++++ .../main/scala/scalajssupport/Source.scala | 16 +++ .../src/main/scala/scoverage/Platform.scala | 22 +++++ .../src/main/scala/scoverage/Platform.scala | 21 ++++ .../scoverage/InvokerConcurrencyTest.scala | 0 .../src/main/scala/scoverage/Invoker.scala | 14 +-- .../scoverage/InvokerMultiModuleTest.scala | 5 +- 15 files changed, 486 insertions(+), 21 deletions(-) create mode 100644 scalac-scoverage-runtime/js/src/main/scala/scalajssupport/File.scala create mode 100644 scalac-scoverage-runtime/js/src/main/scala/scalajssupport/FileWriter.scala create mode 100644 scalac-scoverage-runtime/js/src/main/scala/scalajssupport/JsFile.scala create mode 100644 scalac-scoverage-runtime/js/src/main/scala/scalajssupport/NodeFile.scala create mode 100644 scalac-scoverage-runtime/js/src/main/scala/scalajssupport/PhantomFile.scala create mode 100644 scalac-scoverage-runtime/js/src/main/scala/scalajssupport/RhinoFile.scala create mode 100644 scalac-scoverage-runtime/js/src/main/scala/scalajssupport/Source.scala create mode 100644 scalac-scoverage-runtime/js/src/main/scala/scoverage/Platform.scala create mode 100644 scalac-scoverage-runtime/jvm/src/main/scala/scoverage/Platform.scala rename scalac-scoverage-runtime/{ => jvm}/src/test/scala/scoverage/InvokerConcurrencyTest.scala (100%) rename scalac-scoverage-runtime/{ => shared}/src/main/scala/scoverage/Invoker.scala (88%) rename scalac-scoverage-runtime/{ => shared}/src/test/scala/scoverage/InvokerMultiModuleTest.scala (94%) diff --git a/project/Scoverage.scala b/project/Scoverage.scala index 7e8cf06b..c36bd38c 100644 --- a/project/Scoverage.scala +++ b/project/Scoverage.scala @@ -3,13 +3,17 @@ import sbt._ import sbtrelease.ReleasePlugin import sbtrelease.ReleasePlugin.ReleaseKeys import com.typesafe.sbt.pgp.PgpKeys +import org.scalajs.sbtplugin.cross.CrossProject +import org.scalajs.sbtplugin.cross.CrossType +import org.scalajs.sbtplugin.ScalaJSPlugin +import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport._ object Scoverage extends Build { val Org = "org.scoverage" val Scala = "2.11.7" val MockitoVersion = "1.9.5" - val ScalatestVersion = "2.2.2" + val ScalatestVersion = "3.0.0-M15" lazy val LocalTest = config("local") extend Test @@ -25,10 +29,7 @@ object Scoverage extends Build { resolvers := ("releases" at "https://oss.sonatype.org/service/local/staging/deploy/maven2") +: resolvers.value, concurrentRestrictions in Global += Tags.limit(Tags.Test, 1), javacOptions := Seq("-source", "1.6", "-target", "1.6"), - libraryDependencies ++= Seq( - "org.mockito" % "mockito-all" % MockitoVersion % "test", - "org.scalatest" %% "scalatest" % ScalatestVersion % "test" - ), + javaOptions += "-XX:MaxMetaspaceSize=2048m", publishTo <<= version { (v: String) => val nexus = "https://oss.sonatype.org/" @@ -70,17 +71,30 @@ object Scoverage extends Build { .settings(name := "scalac-scoverage") .settings(appSettings: _*) .settings(publishArtifact := false) - .aggregate(plugin, runtime) + .aggregate(plugin, runtime.jvm, runtime.js) - lazy val runtime = Project("scalac-scoverage-runtime", file("scalac-scoverage-runtime")) + lazy val runtime = CrossProject("scalac-scoverage-runtime", file("scalac-scoverage-runtime"), CrossType.Full) .settings(name := "scalac-scoverage-runtime") .settings(appSettings: _*) + .jvmSettings(libraryDependencies ++= Seq( + "org.mockito" % "mockito-all" % MockitoVersion % "test", + "org.scalatest" %% "scalatest" % ScalatestVersion % "test" + )) + .jsSettings( + libraryDependencies += "org.scalatest" %%% "scalatest" % ScalatestVersion, + scalaJSStage := FastOptStage + ) + + lazy val `scalac-scoverage-runtimeJVM` = runtime.jvm + lazy val `scalac-scoverage-runtimeJS` = runtime.js lazy val plugin = Project("scalac-scoverage-plugin", file("scalac-scoverage-plugin")) - .dependsOn(runtime % "test") + .dependsOn(`scalac-scoverage-runtimeJVM` % "test") .settings(name := "scalac-scoverage-plugin") .settings(appSettings: _*) .settings(libraryDependencies ++= Seq( + "org.mockito" % "mockito-all" % MockitoVersion % "test", + "org.scalatest" %% "scalatest" % ScalatestVersion % "test", "org.scala-lang" % "scala-reflect" % scalaVersion.value % "provided", "org.scala-lang" % "scala-compiler" % scalaVersion.value % "provided", "org.joda" % "joda-convert" % "1.6" % "test", @@ -96,4 +110,4 @@ object Scoverage extends Build { Nil } }) -} \ No newline at end of file +} diff --git a/project/plugins.sbt b/project/plugins.sbt index 33096ea7..dfb80729 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -5,3 +5,5 @@ addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "0.3.2") addSbtPlugin("com.typesafe.sbt" % "sbt-pgp" % "0.8.3") addSbtPlugin("com.github.gseitz" % "sbt-release" % "0.8.5") + +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.8") diff --git a/scalac-scoverage-plugin/src/test/scala/scoverage/ScoverageCompiler.scala b/scalac-scoverage-plugin/src/test/scala/scoverage/ScoverageCompiler.scala index f9f2247c..c09878f6 100644 --- a/scalac-scoverage-plugin/src/test/scala/scoverage/ScoverageCompiler.scala +++ b/scalac-scoverage-plugin/src/test/scala/scoverage/ScoverageCompiler.scala @@ -51,7 +51,7 @@ object ScoverageCompiler { dir } - private def runtimeClasses: File = new File("./scalac-scoverage-runtime/target/scala-2.11/classes") + private def runtimeClasses: File = new File("./scalac-scoverage-runtime/shared/target/scala-2.11/classes") private def findScalaJar(artifactId: String): File = findIvyJar("org.scala-lang", artifactId, ScalaVersion) diff --git a/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/File.scala b/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/File.scala new file mode 100644 index 00000000..c05169ad --- /dev/null +++ b/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/File.scala @@ -0,0 +1,73 @@ +package scalajssupport + +import scala.scalajs.js +import js.Dynamic.{ global => g } + +/** + * This wraps RhinoFile, NodeFile, or PhantomFile depending on which javascript + * environment is being used, and emulates a subset of the java.io.File API. + */ +class File(path: String) { + import File._ + + val _file = jsFile(path) + + def this(path: String, child: String) = { + this(File.pathJoin(path, child)) + } + + def delete(): Unit = { + _file.delete() + } + def getAbsolutePath(): String = { + _file.getAbsolutePath() + } + + def getName(): String = { + _file.getName() + } + + def getPath(): String = { + _file.getPath() + } + + def isDirectory(): Boolean = { + _file.isDirectory() + } + + def mkdirs(): Unit = { + _file.mkdirs() + } + + def listFiles(): Array[File] = { + _file.listFiles().toArray + } + + def listFiles(filter: FileFilter): Array[File] = { + _file.listFiles().filter(filter.accept).toArray + } + + def readFile(): String = { + _file.readFile() + } + + override def toString: String = { + getPath() + } +} + +object File { + val jsFile: JsFileObject = if (js.Dynamic.global.hasOwnProperty("Packages").asInstanceOf[Boolean]) + RhinoFile + else if (!js.Dynamic.global.hasOwnProperty("window").asInstanceOf[Boolean]) + NodeFile + else + PhantomFile + // Factorize this + + def pathJoin(path: String, child: String): String = + jsFile.pathJoin(path, child) + + def write(path: String, data: String, mode: String = "a") = + jsFile.write(path, data, mode) +} \ No newline at end of file diff --git a/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/FileWriter.scala b/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/FileWriter.scala new file mode 100644 index 00000000..60a8964e --- /dev/null +++ b/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/FileWriter.scala @@ -0,0 +1,23 @@ +package scalajssupport + +/** + * Emulates a subset of the java.io.FileWriter API required for scoverage to work. + */ +class FileWriter(file: File, append: Boolean) { + def this(file: File) = this(file, false) + def this(file: String) = this(new File(file), false) + def this(file: String, append: Boolean) = this(new File(file), append) + + def append(csq: CharSequence) = { + File.write(file.getPath, csq.toString) + this + } + + def close(): Unit = { + // do nothing as we don't open a FD to the file, as phantomJS does not use FDs + } + + override def finalize(): Unit = close() + + def flush() = {} +} diff --git a/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/JsFile.scala b/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/JsFile.scala new file mode 100644 index 00000000..4adb6f0e --- /dev/null +++ b/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/JsFile.scala @@ -0,0 +1,32 @@ +package scalajssupport + +trait JsFile { + def delete(): Unit + def getAbsolutePath(): String + + def getName(): String + + def getPath(): String + + def isDirectory(): Boolean + + def mkdirs(): Unit + + def listFiles(): Array[File] + + def listFiles(filter: FileFilter): Array[File] = { + listFiles().filter(filter.accept) + } + + def readFile(): String +} + +trait FileFilter { + def accept(file: File): Boolean +} + +trait JsFileObject { + def write(path: String, data: String, mode: String = "a") + def pathJoin(path: String, child: String): String + def apply(path: String): JsFile +} diff --git a/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/NodeFile.scala b/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/NodeFile.scala new file mode 100644 index 00000000..8be199bd --- /dev/null +++ b/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/NodeFile.scala @@ -0,0 +1,99 @@ +package scalajssupport + +import scala.scalajs.js + +class NodeFile(path: String) extends JsFile { + def this(path: String, child: String) = { + this(NodeFile.nodePath.join(path, child)) + } + + def delete(): Unit = { + if (isDirectory()) NodeFile.fs.rmdirSync(path) + else NodeFile.fs.unlinkSync(path) + } + + def getAbsolutePath(): String = { + NodeFile.fs.realpathSync(path) + } + + def getName(): String = { + NodeFile.nodePath.basename(path) + } + + def getPath(): String = { + path + } + + def isDirectory(): Boolean = { + try { + NodeFile.fs.lstatSync(path).isDirectory() + } catch { + // return false if the file does not exist + case e: Exception => false + } + } + + def mkdirs(): Unit = { + path.split("/").foldLeft("")((acc: String, x: String) => { + val new_acc = NodeFile.nodePath.join(acc, x) + try { + NodeFile.fs.mkdirSync(new_acc) + } catch { + case e: Exception => + } + new_acc + }) + } + + def listFiles(): Array[File] = { + val files = NodeFile.fs.readdirSync(path) + val filesArray = new Array[File](files.length) + for ((item, i) <- filesArray.zipWithIndex) { + filesArray(i) = new File(NodeFile.nodePath.join(this.getPath(), files(i))) + } + filesArray + } + + def readFile(): String = { + NodeFile.fs.readFileSync(path, js.Dynamic.literal(encoding = "utf-8")) + } + +} + +trait FSStats extends js.Object { + def isDirectory(): Boolean = js.native +} + +trait FS extends js.Object { + def closeSync(fd: Int): Unit = js.native + def lstatSync(path: String): FSStats = js.native + def mkdirSync(path: String): Unit = js.native + def openSync(path: String, flags: String): Int = js.native + def realpathSync(path: String): String = js.native + def readdirSync(path: String): js.Array[String] = js.native + def readFileSync(path: String, options: js.Dynamic): String = js.native + def rmdirSync(path: String): Unit = js.native + def unlinkSync(path: String): Unit = js.native + def writeFileSync(path: String, data: String, options: js.Dynamic = js.Dynamic.literal()): Unit = js.native +} + +trait NodePath extends js.Object { + def basename(path: String): String = js.native + def join(paths: String*): String = js.native +} + +private[scalajssupport] object NodeFile extends JsFileObject { + val fs: FS = js.Dynamic.global.require("fs").asInstanceOf[FS] + val nodePath: NodePath = js.Dynamic.global.require("path").asInstanceOf[NodePath] + def write(path: String, data: String, mode: String = "a") = { + fs.writeFileSync(path, data, js.Dynamic.literal(flag = mode)) + } + + def pathJoin(path: String, child: String) = { + nodePath.join(path, child) + } + + def apply(path: String) = { + new NodeFile(path) + } +} \ No newline at end of file diff --git a/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/PhantomFile.scala b/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/PhantomFile.scala new file mode 100644 index 00000000..173539a9 --- /dev/null +++ b/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/PhantomFile.scala @@ -0,0 +1,82 @@ +package scalajssupport + +import scala.scalajs.js +import scala.scalajs.js.JSON + +class PhantomFile(path: String) extends JsFile { + def this(path: String, child: String) = { + this(PhantomFile.pathJoin(path, child)) + } + + def delete(): Unit = { + if (isDirectory()) PhantomFile.removeDirectory(path) + else PhantomFile.remove(path) + } + + def getAbsolutePath(): String = { + PhantomFile.absolute(path) + } + + def getName(): String = { + path.split("\\" + PhantomFile.separator).last + } + + def getPath(): String = { + path + } + + def isDirectory(): Boolean = { + PhantomFile.isDirectory(path) + } + + def mkdirs(): Unit = { + PhantomFile.makeTree(path) + } + + def listFiles(): Array[File] = { + val files = PhantomFile.list(path) + val filesArray = new Array[File](files.length) + for ((item, i) <- filesArray.zipWithIndex) { + filesArray(i) = new File(PhantomFile.pathJoin(this.getPath(), files(i))) + } + filesArray + } + + def readFile(): String = { + PhantomFile.read(path) + } + +} + +private[scalajssupport] object PhantomFile extends JsFileObject { + def fsCallArray(method: String, args: js.Array[js.Any]): js.Dynamic = { + val d = js.Dynamic.global.callPhantom(js.Dynamic.literal( + action = "require.fs", + method = method, + args = args + )) + JSON.parse(d.asInstanceOf[String]) + } + + def fsCall(method: String, arg: js.Any = null): js.Dynamic = { + fsCallArray(method, js.Array(arg)) + + } + + def absolute(path: String): String = fsCall("absolute", path).asInstanceOf[String] + def isDirectory(path: String): Boolean = fsCall("isDirectory", path).asInstanceOf[Boolean] + def list(path: String): js.Array[String] = fsCall("list", path).asInstanceOf[js.Array[String]] + def makeTree(path: String): Boolean = fsCall("makeTree", path).asInstanceOf[Boolean] + def read(path: String): String = fsCall("read", path).asInstanceOf[String] + def remove(path: String): Boolean = fsCall("remove", path).asInstanceOf[Boolean] + def removeDirectory(path: String): Boolean = fsCall("removeDirectory", path).asInstanceOf[Boolean] + val separator: String = fsCall("separator").asInstanceOf[String] + def write(path: String, content: String, mode: String): Unit = fsCallArray("write", js.Array(path, content, mode)) + def pathJoin(path: String, child: String): String = { + return path + separator + child + } + + def apply(path: String) = { + new PhantomFile(path) + } +} \ No newline at end of file diff --git a/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/RhinoFile.scala b/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/RhinoFile.scala new file mode 100644 index 00000000..78724674 --- /dev/null +++ b/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/RhinoFile.scala @@ -0,0 +1,84 @@ +package scalajssupport + +import scala.scalajs.js +import scala.scalajs.js.annotation.JSName + +import js.Dynamic.{ global => g, newInstance => jsnew } + +@JSName("Packages.java.io.File") +class NativeRhinoFile(path: String, child: String) extends js.Object { + def this(path: String) = this("", path) + + def delete(): Unit = js.native + + def getAbsolutePath(): Any = js.native + + def getName(): Any = js.native + + def getPath(): Any = js.native + + def isDirectory(): Boolean = js.native + + def length(): js.Any = js.native + + def mkdirs(): Unit = js.native + + def listFiles(): js.Array[NativeRhinoFile] = js.native +} + +class RhinoFile(_file: NativeRhinoFile) extends JsFile { + def this(path: String) = this(new NativeRhinoFile(path)) + + def this(path: String, child: String) = { + this((new NativeRhinoFile(path, child))) + } + + def delete(): Unit = _file.delete() + + def getAbsolutePath(): String = "" + _file.getAbsolutePath() + + def getName(): String = "" + _file.getName() + + def getPath(): String = { + "" + _file.getPath() // Rhino bug: doesn't seem to actually returns a string, we have to convert it ourselves + } + + def isDirectory(): Boolean = _file.isDirectory() + + def mkdirs(): Unit = _file.mkdirs() + + def listFiles(): Array[File] = { + val files = _file.listFiles() + val filesArray = new Array[File](files.length) + for ((item, i) <- filesArray.zipWithIndex) { + filesArray(i) = new File("" + files(i).getAbsolutePath()) + } + filesArray + } + + def readFile(): String = { + val fis = jsnew(g.Packages.java.io.FileInputStream)(_file) + val data = g.Packages.java.lang.reflect.Array.newInstance( + g.Packages.java.lang.Byte.TYPE, _file.length() + ) + fis.read(data) + fis.close() + "" + jsnew(g.Packages.java.lang.String)(data) + } +} + +private[scalajssupport] object RhinoFile extends JsFileObject { + def write(path: String, data: String, mode: String) = { + val outputstream = jsnew(g.Packages.java.io.FileOutputStream)(path, mode == "a") + val jString = jsnew(g.Packages.java.lang.String)(data) + outputstream.write(jString.getBytes()) + } + + def pathJoin(path: String, child: String) = { + "" + (new NativeRhinoFile(path, child)).getPath() + } + + def apply(path: String) = { + new RhinoFile(path) + } +} \ No newline at end of file diff --git a/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/Source.scala b/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/Source.scala new file mode 100644 index 00000000..61025477 --- /dev/null +++ b/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/Source.scala @@ -0,0 +1,16 @@ +package scalajssupport + +import scala.io.{ Source => OrigSource } + +/** +* This implementation of Source loads the whole file in memory, which is not really efficient, but +* it is not a problem for scoverage operations. +*/ +object Source { + def fromFile(file: File) = { + new OrigSource { + + val iter = file.readFile.toCharArray.iterator + } + } +} \ No newline at end of file diff --git a/scalac-scoverage-runtime/js/src/main/scala/scoverage/Platform.scala b/scalac-scoverage-runtime/js/src/main/scala/scoverage/Platform.scala new file mode 100644 index 00000000..95a47a79 --- /dev/null +++ b/scalac-scoverage-runtime/js/src/main/scala/scoverage/Platform.scala @@ -0,0 +1,22 @@ +package scoverage + +import scala.collection.mutable.HashMap +import scala.collection.generic.{ CanBuildFrom, MutableMapFactory } +import scalajssupport.{ + File => SupportFile, + FileWriter => SupportFileWriter, + FileFilter => SupportFileFilter, + Source => SupportSource +} + +object Platform { + type ThreadSafeMap[A, B] = HashMap[A, B] + lazy val ThreadSafeMap = HashMap + + type File = SupportFile + type FileWriter = SupportFileWriter + type FileFilter = SupportFileFilter + + lazy val Source = SupportSource + +} \ No newline at end of file diff --git a/scalac-scoverage-runtime/jvm/src/main/scala/scoverage/Platform.scala b/scalac-scoverage-runtime/jvm/src/main/scala/scoverage/Platform.scala new file mode 100644 index 00000000..ec9f6f0d --- /dev/null +++ b/scalac-scoverage-runtime/jvm/src/main/scala/scoverage/Platform.scala @@ -0,0 +1,21 @@ +package scoverage + +import scala.collection.concurrent.TrieMap +import scala.collection.generic.{ CanBuildFrom, MutableMapFactory } +import java.io.{ + File => SupportFile, + FileWriter => SupportFileWriter, + FileFilter => SupportFileFilter +} +import scala.io.{ Source => SupportSource } + +object Platform { + type ThreadSafeMap[A, B] = TrieMap[A, B] + lazy val ThreadSafeMap = TrieMap + + type File = SupportFile + type FileWriter = SupportFileWriter + type FileFilter = SupportFileFilter + + lazy val Source = SupportSource +} \ No newline at end of file diff --git a/scalac-scoverage-runtime/src/test/scala/scoverage/InvokerConcurrencyTest.scala b/scalac-scoverage-runtime/jvm/src/test/scala/scoverage/InvokerConcurrencyTest.scala similarity index 100% rename from scalac-scoverage-runtime/src/test/scala/scoverage/InvokerConcurrencyTest.scala rename to scalac-scoverage-runtime/jvm/src/test/scala/scoverage/InvokerConcurrencyTest.scala diff --git a/scalac-scoverage-runtime/src/main/scala/scoverage/Invoker.scala b/scalac-scoverage-runtime/shared/src/main/scala/scoverage/Invoker.scala similarity index 88% rename from scalac-scoverage-runtime/src/main/scala/scoverage/Invoker.scala rename to scalac-scoverage-runtime/shared/src/main/scala/scoverage/Invoker.scala index bff28212..8f346e6e 100644 --- a/scalac-scoverage-runtime/src/main/scala/scoverage/Invoker.scala +++ b/scalac-scoverage-runtime/shared/src/main/scala/scoverage/Invoker.scala @@ -1,17 +1,14 @@ package scoverage -import java.io.{FileFilter, File, FileWriter} - import scala.collection.{mutable, Set} -import scala.collection.concurrent.TrieMap -import scala.io.Source +import scoverage.Platform._ /** @author Stephen Samuel */ object Invoker { private val MeasurementsPrefix = "scoverage.measurements." - private val threadFiles = new ThreadLocal[TrieMap[String, FileWriter]] - private val ids = TrieMap.empty[(String, Int), Any] + private val threadFiles = new ThreadLocal[ThreadSafeMap[String, FileWriter]] + private val ids = ThreadSafeMap.empty[(String, Int), Any] /** * We record that the given id has been invoked by appending its id to the coverage @@ -39,9 +36,8 @@ object Invoker { // and because file appends via FileWriter are not atomic on Windows. var files = threadFiles.get() if (files == null) - files = TrieMap.empty[String, FileWriter] + files = ThreadSafeMap.empty[String, FileWriter] threadFiles.set(files) - val writer = files.getOrElseUpdate(dataDir, new FileWriter(measurementFile(dataDir), true)) writer.append(id.toString + '\n').flush() @@ -62,7 +58,7 @@ object Invoker { val acc = mutable.Set[Int]() files.foreach { file => val reader = Source.fromFile(file) - for ( line <- reader.getLines() ) { + for (line <- reader.getLines()) { if (!line.isEmpty) { acc += line.toInt } diff --git a/scalac-scoverage-runtime/src/test/scala/scoverage/InvokerMultiModuleTest.scala b/scalac-scoverage-runtime/shared/src/test/scala/scoverage/InvokerMultiModuleTest.scala similarity index 94% rename from scalac-scoverage-runtime/src/test/scala/scoverage/InvokerMultiModuleTest.scala rename to scalac-scoverage-runtime/shared/src/test/scala/scoverage/InvokerMultiModuleTest.scala index 1f3e6f47..013153dd 100644 --- a/scalac-scoverage-runtime/src/test/scala/scoverage/InvokerMultiModuleTest.scala +++ b/scalac-scoverage-runtime/shared/src/test/scala/scoverage/InvokerMultiModuleTest.scala @@ -1,6 +1,6 @@ package scoverage -import java.io.File +import scoverage.Platform.File import org.scalatest.{BeforeAndAfter, FunSuite} @@ -11,7 +11,8 @@ class InvokerMultiModuleTest extends FunSuite with BeforeAndAfter { val measurementDir = Array( new File("target/invoker-test.measurement0"), - new File("target/invoker-test.measurement1")) + new File("target/invoker-test.measurement1") + ) before { deleteMeasurementFiles() From 8b901a16667cbe44a7e202febae058834bc3f340 Mon Sep 17 00:00:00 2001 From: Lukasz Stefaniak Date: Tue, 29 Mar 2016 14:02:21 +0200 Subject: [PATCH 2/5] Add -XX:MaxMetaspaceSize only to JVM projects --- project/Scoverage.scala | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/project/Scoverage.scala b/project/Scoverage.scala index c36bd38c..998d3eb9 100644 --- a/project/Scoverage.scala +++ b/project/Scoverage.scala @@ -29,7 +29,6 @@ object Scoverage extends Build { resolvers := ("releases" at "https://oss.sonatype.org/service/local/staging/deploy/maven2") +: resolvers.value, concurrentRestrictions in Global += Tags.limit(Tags.Test, 1), javacOptions := Seq("-source", "1.6", "-target", "1.6"), - javaOptions += "-XX:MaxMetaspaceSize=2048m", publishTo <<= version { (v: String) => val nexus = "https://oss.sonatype.org/" @@ -71,15 +70,19 @@ object Scoverage extends Build { .settings(name := "scalac-scoverage") .settings(appSettings: _*) .settings(publishArtifact := false) + .settings(javaOptions += "-XX:MaxMetaspaceSize=2048m") .aggregate(plugin, runtime.jvm, runtime.js) lazy val runtime = CrossProject("scalac-scoverage-runtime", file("scalac-scoverage-runtime"), CrossType.Full) .settings(name := "scalac-scoverage-runtime") .settings(appSettings: _*) - .jvmSettings(libraryDependencies ++= Seq( + .jvmSettings( + libraryDependencies ++= Seq( "org.mockito" % "mockito-all" % MockitoVersion % "test", "org.scalatest" %% "scalatest" % ScalatestVersion % "test" - )) + ), + javaOptions += "-XX:MaxMetaspaceSize=2048m" + ) .jsSettings( libraryDependencies += "org.scalatest" %%% "scalatest" % ScalatestVersion, scalaJSStage := FastOptStage @@ -92,6 +95,7 @@ object Scoverage extends Build { .dependsOn(`scalac-scoverage-runtimeJVM` % "test") .settings(name := "scalac-scoverage-plugin") .settings(appSettings: _*) + .settings(javaOptions += "-XX:MaxMetaspaceSize=2048m") .settings(libraryDependencies ++= Seq( "org.mockito" % "mockito-all" % MockitoVersion % "test", "org.scalatest" %% "scalatest" % ScalatestVersion % "test", From 16b8c0044ff04f34ce1dedf66f34404f30987ee2 Mon Sep 17 00:00:00 2001 From: Lukasz Stefaniak Date: Tue, 29 Mar 2016 16:34:00 +0200 Subject: [PATCH 3/5] Search for runtime classes in jvm for crossProject on jvm tests --- .../src/test/scala/scoverage/ScoverageCompiler.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scalac-scoverage-plugin/src/test/scala/scoverage/ScoverageCompiler.scala b/scalac-scoverage-plugin/src/test/scala/scoverage/ScoverageCompiler.scala index c09878f6..fc7cafd8 100644 --- a/scalac-scoverage-plugin/src/test/scala/scoverage/ScoverageCompiler.scala +++ b/scalac-scoverage-plugin/src/test/scala/scoverage/ScoverageCompiler.scala @@ -51,7 +51,7 @@ object ScoverageCompiler { dir } - private def runtimeClasses: File = new File("./scalac-scoverage-runtime/shared/target/scala-2.11/classes") + private def runtimeClasses: File = new File("./scalac-scoverage-runtime/jvm/target/scala-2.11/classes") private def findScalaJar(artifactId: String): File = findIvyJar("org.scala-lang", artifactId, ScalaVersion) From e8dff1fd6b7e97f0d1f0242a85e4c39214f3f94b Mon Sep 17 00:00:00 2001 From: Lukasz Stefaniak Date: Sun, 22 May 2016 00:02:06 +0200 Subject: [PATCH 4/5] Upgrade to scala.js 0.6.9 --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index dfb80729..671e05d3 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -6,4 +6,4 @@ addSbtPlugin("com.typesafe.sbt" % "sbt-pgp" % "0.8.3") addSbtPlugin("com.github.gseitz" % "sbt-release" % "0.8.5") -addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.8") +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.9") From dd36d9c28dbc6b720c3bfd73012349394d52467d Mon Sep 17 00:00:00 2001 From: Lukasz Stefaniak Date: Sun, 22 May 2016 00:02:18 +0200 Subject: [PATCH 5/5] Get rid of scala.js compilation warnings --- .../js/src/main/scala/scalajssupport/NodeFile.scala | 3 +++ .../js/src/main/scala/scalajssupport/RhinoFile.scala | 1 + 2 files changed, 4 insertions(+) diff --git a/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/NodeFile.scala b/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/NodeFile.scala index 8be199bd..7fb186ab 100644 --- a/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/NodeFile.scala +++ b/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/NodeFile.scala @@ -60,10 +60,12 @@ class NodeFile(path: String) extends JsFile { } +@js.native trait FSStats extends js.Object { def isDirectory(): Boolean = js.native } +@js.native trait FS extends js.Object { def closeSync(fd: Int): Unit = js.native def lstatSync(path: String): FSStats = js.native @@ -77,6 +79,7 @@ trait FS extends js.Object { def writeFileSync(path: String, data: String, options: js.Dynamic = js.Dynamic.literal()): Unit = js.native } +@js.native trait NodePath extends js.Object { def basename(path: String): String = js.native def join(paths: String*): String = js.native diff --git a/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/RhinoFile.scala b/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/RhinoFile.scala index 78724674..76ced8b4 100644 --- a/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/RhinoFile.scala +++ b/scalac-scoverage-runtime/js/src/main/scala/scalajssupport/RhinoFile.scala @@ -6,6 +6,7 @@ import scala.scalajs.js.annotation.JSName import js.Dynamic.{ global => g, newInstance => jsnew } @JSName("Packages.java.io.File") +@js.native class NativeRhinoFile(path: String, child: String) extends js.Object { def this(path: String) = this("", path)