Runtime support library for scoverage code coverage tool that collects coverage data during program execution when code has been instrumented by the scalac compiler plugin.
npx @tessl/cli install tessl/maven-org-scoverage--scalac-scoverage-runtime-2-11@1.4.0Scalac Scoverage Runtime is the runtime support library for scoverage, a code coverage tool for Scala. This library provides the essential instrumentation infrastructure that collects coverage data during program execution when code has been instrumented by the scalac-scoverage-plugin compiler plugin. It supports both JVM and JavaScript platforms through Scala.js.
libraryDependencies += "org.scoverage" %% "scalac-scoverage-runtime" % "1.4.11"<artifactId>scalac-scoverage-runtime_2.11</artifactId>import scoverage.Invoker
import scoverage.Platform._For JavaScript-specific functionality:
import scalajssupport.{File, FileWriter, Source}The runtime library is typically used automatically by instrumented code, but can also be used directly for coverage analysis:
import scoverage.Invoker
import scoverage.Platform._
// Record statement execution (called by instrumented code)
Invoker.invoked(statementId = 42, dataDir = "/path/to/coverage/data")
// Find measurement files for analysis
val dataDir = "/path/to/coverage/data"
val measurementFiles = Invoker.findMeasurementFiles(dataDir)
// Load invoked statement IDs from files
val invokedIds = Invoker.invoked(measurementFiles)
println(s"Covered statements: ${invokedIds.size}")The runtime library uses a cross-platform architecture with several key components:
scoverage.Platform provides unified interfaces across JVM and JavaScript with compile-time type resolutionscoverage.Invoker handles thread-safe recording of statement executions with per-thread measurement filesruntimeUUID) combined with thread ID to create unique measurement filesCore instrumentation runtime that records which statements have been executed during program execution.
object Invoker {
/**
* Records that a statement has been executed
* @param id the ID of the statement that was invoked
* @param dataDir the directory where measurement data is stored
* @param reportTestName whether to include test name information
*/
def invoked(id: Int, dataDir: String, reportTestName: Boolean = false): Unit
/**
* Gets the measurement file path for a given data directory
* @param dataDir the data directory as File
* @return measurement file for current thread
*/
def measurementFile(dataDir: File): File
/**
* Gets the measurement file path for a given data directory
* @param dataDir the data directory path as String
* @return measurement file for current thread
*/
def measurementFile(dataDir: String): File
/**
* Finds all measurement files in the given directory
* @param dataDir the directory to search as String
* @return array of measurement files
*/
def findMeasurementFiles(dataDir: String): Array[File]
/**
* Finds all measurement files in the given directory
* @param dataDir the directory to search as File
* @return array of measurement files
*/
def findMeasurementFiles(dataDir: File): Array[File]
/**
* Loads all invoked statement IDs from measurement files
* @param files sequence of measurement files to read
* @return set of statement IDs that were executed
* @note Each line may contain just the ID, or ID followed by test name (space-separated)
*/
def invoked(files: Seq[File]): Set[Int]
/**
* Utility method to identify calling ScalaTest suite
* @return name of calling test suite or empty string
*/
def getCallingScalaTest: String
}Provides unified cross-platform interfaces for file operations and concurrent data structures.
object Platform {
// JVM Platform (when compiling to JVM bytecode)
type ThreadSafeMap[A, B] = scala.collection.concurrent.TrieMap[A, B]
lazy val ThreadSafeMap: TrieMap.type = TrieMap
type File = java.io.File
type FileWriter = java.io.FileWriter
type FileFilter = java.io.FileFilter
lazy val Source: scala.io.Source.type = scala.io.Source
// JavaScript Platform (when compiling to JavaScript via Scala.js)
type ThreadSafeMap[A, B] = scala.collection.mutable.HashMap[A, B]
lazy val ThreadSafeMap: HashMap.type = HashMap
type File = scalajssupport.File
type FileWriter = scalajssupport.FileWriter
type FileFilter = scalajssupport.FileFilter
lazy val Source: scalajssupport.Source.type = scalajssupport.Source
}JavaScript-compatible file system abstractions that emulate Java I/O APIs for Scala.js environments.
// JavaScript File abstraction
class File(path: String) {
/**
* Creates a File with parent path and child name
* @param path parent directory path
* @param child child file/directory name
*/
def this(path: String, child: String)
/** Deletes the file or directory */
def delete(): Unit
/** Returns the absolute path */
def getAbsolutePath(): String
/** Returns the file name */
def getName(): String
/** Returns the file path */
def getPath(): String
/** Checks if this is a directory */
def isDirectory(): Boolean
/** Creates directory structure */
def mkdirs(): Unit
/** Lists all files in directory */
def listFiles(): Array[File]
/** Lists files matching filter */
def listFiles(filter: FileFilter): Array[File]
/** Reads entire file content as string */
def readFile(): String
}
object File {
/** Joins path components */
def pathJoin(path: String, child: String): String
/** Writes data to file */
def write(path: String, data: String, mode: String = "a"): Unit
}
// JavaScript FileWriter abstraction
class FileWriter(file: File, append: Boolean) {
/** Create FileWriter for file without append mode */
def this(file: File)
/** Create FileWriter for file path without append mode */
def this(file: String)
/** Create FileWriter for file path with append mode */
def this(file: String, append: Boolean)
/** Appends character sequence, returns this for chaining */
def append(csq: CharSequence): FileWriter
/** Closes the writer */
def close(): Unit
/** Flushes the writer */
def flush(): Unit
}
// JavaScript Source abstraction
object Source {
/** Creates source reader from file */
def fromFile(file: File): scala.io.Source
}
// File filtering interface
trait FileFilter {
/** Returns true if file should be included */
def accept(file: File): Boolean
}
// JavaScript File trait hierarchy
trait JsFile {
/** Deletes the file or directory */
def delete(): Unit
/** Returns the absolute path */
def getAbsolutePath(): String
/** Returns the file name */
def getName(): String
/** Returns the file path */
def getPath(): String
/** Checks if this is a directory */
def isDirectory(): Boolean
/** Creates directory structure */
def mkdirs(): Unit
/** Lists all files in directory */
def listFiles(): Array[File]
/** Lists files matching filter */
def listFiles(filter: FileFilter): Array[File]
/** Reads entire file content as string */
def readFile(): String
}
trait JsFileObject {
/** Writes data to file with mode (default append) */
def write(path: String, data: String, mode: String = "a"): Unit
/** Joins path components */
def pathJoin(path: String, child: String): String
/** Creates JsFile instance for path */
def apply(path: String): JsFile
}// Core platform types (resolved at compile time based on target platform)
type ThreadSafeMap[A, B] // TrieMap on JVM, HashMap on JS
type File // java.io.File on JVM, scalajssupport.File on JS
type FileWriter // java.io.FileWriter on JVM, scalajssupport.FileWriter on JS
type FileFilter // java.io.FileFilter on JVM, scalajssupport.FileFilter on JSThe library handles errors gracefully across both platforms:
false for isDirectory() if file doesn't exist)dataDirToIds.synchronized to guard against SI-7943invoked(files) method skips empty lines in measurement files using if (!line.isEmpty)java.util.concurrent.TrieMap for thread-safe collectionsThreadLocal storage for file writersscala.collection.mutable.HashMap (JavaScript is single-threaded)NodeFile, RhinoFile, PhantomFile)Packages (Rhino), callPhantom (PhantomJS), or defaults to Node.jsscoverage.measurements.<UUID>.<threadId>"123""123 MySuite" (when reportTestName = true)Recording coverage data (typically done by instrumented code):
import scoverage.Invoker
// Record that statement 123 was executed
Invoker.invoked(123, "/tmp/scoverage-data")
// Record with test name information
Invoker.invoked(456, "/tmp/scoverage-data", reportTestName = true)Analyzing coverage data:
import scoverage.Invoker
import scoverage.Platform._
val dataDir = "/tmp/scoverage-data"
// Find all measurement files
val files = Invoker.findMeasurementFiles(dataDir)
println(s"Found ${files.length} measurement files")
// Load executed statement IDs
val executedIds = Invoker.invoked(files.toSeq)
println(s"Total statements executed: ${executedIds.size}")
// Check if specific statement was executed
val statementId = 42
if (executedIds.contains(statementId)) {
println(s"Statement $statementId was executed")
}Cross-platform file operations:
import scoverage.Platform._
// This works on both JVM and JavaScript
val file = new File("/path/to/data", "measurements.txt")
val writer = new FileWriter(file, append = true)
writer.append("42\n")
writer.close()
// Read measurement data
val source = Source.fromFile(file)
val lines = source.getLines().toList
source.close()