CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-scoverage--scalac-scoverage-plugin

Comprehensive code coverage tool for Scala providing statement and branch coverage through compiler plugin instrumentation and report generation

Pending
Overview
Eval results
Files

plugin.mddocs/

Compiler Plugin

The Scalac Scoverage Plugin is a Scala compiler plugin that instruments source code during compilation to enable coverage measurement. It adds instrumentation calls to statements and branches, allowing runtime collection of coverage data during test execution.

Capabilities

Main Plugin Class

The core compiler plugin that integrates with the Scala compiler.

/**
 * Main Scoverage compiler plugin class
 * @param global The Scala compiler's Global object
 */
class ScoveragePlugin(val global: Global) extends Plugin {
  /** Plugin name identifier */
  val name: String
  
  /** Human-readable plugin description */
  val description: String
  
  /** List of plugin components that perform the instrumentation */
  val components: List[PluginComponent]
  
  /** Initialize plugin with command-line options */
  def init(opts: List[String], error: String => Unit): Boolean
  
  /** Help text for plugin options */
  val optionsHelp: Option[String]
}

Plugin Configuration

Configuration options for controlling plugin behavior.

/**
 * Configuration options for the Scoverage plugin
 * @param excludedPackages Regex patterns for packages to exclude from instrumentation
 * @param excludedFiles Regex patterns for files to exclude from instrumentation
 * @param excludedSymbols Regex patterns for symbols to exclude from instrumentation
 * @param dataDir Directory where coverage data files are written
 * @param reportTestName Whether to include test names in coverage reports
 * @param sourceRoot Root directory for source files
 */
case class ScoverageOptions(
  excludedPackages: Seq[String],
  excludedFiles: Seq[String],
  excludedSymbols: Seq[String],
  dataDir: String,
  reportTestName: Boolean,
  sourceRoot: String
)

object ScoverageOptions {
  /** Create default options */
  def default(): ScoverageOptions
  
  /** Parse command-line options into ScoverageOptions */
  def parse(scalacOptions: List[String], errFn: String => Unit, base: ScoverageOptions): ScoverageOptions
  
  /** Process phase options for before/after phase configuration */
  def processPhaseOptions(opts: List[String]): (Option[String], Option[String])
  
  /** Help text for all available options */
  val help: Option[String]
}

Usage Examples:

import scoverage.ScoverageOptions

// Create custom configuration
val options = ScoverageOptions(
  excludedPackages = Seq(".*\\.test\\..*", ".*\\.generated\\..*"),
  excludedFiles = Seq(".*DatabaseMigrations.*"),
  excludedSymbols = Seq(".*Logger.*"),
  dataDir = "target/scoverage-data",  
  reportTestName = true,
  sourceRoot = "src/main/scala"
)

// Parse from compiler options
val opts = List(
  "-P:scoverage:dataDir:target/scoverage-data",
  "-P:scoverage:excludedPackages:.*\\.test\\..*",
  "-P:scoverage:reportTestName:true"
)
val parsed = ScoverageOptions.parse(opts, println, ScoverageOptions.default())

Coverage Filtering

Control which code gets instrumented for coverage measurement.

/**
 * Base trait for filtering what code should be included in coverage
 */
trait CoverageFilter {
  /** Check if a class should be included in coverage */
  def isClassIncluded(className: String): Boolean
  
  /** Check if a source file should be included in coverage */
  def isFileIncluded(file: SourceFile): Boolean
  
  /** Check if a specific line position should be included */
  def isLineIncluded(position: Position): Boolean
  
  /** Check if a symbol should be included in coverage */
  def isSymbolIncluded(symbolName: String): Boolean
  
  /** Get line number ranges that are excluded from coverage */
  def getExcludedLineNumbers(sourceFile: SourceFile): List[Range]
}

/**
 * Filter that includes all code (no exclusions)
 */
object AllCoverageFilter extends CoverageFilter

/**
 * Regex-based filter for excluding code from coverage
 * @param excludedPackages Regex patterns for package exclusion
 * @param excludedFiles Regex patterns for file exclusion  
 * @param excludedSymbols Regex patterns for symbol exclusion
 * @param reporter Compiler reporter for error handling
 */
class RegexCoverageFilter(
  excludedPackages: Seq[String],
  excludedFiles: Seq[String],
  excludedSymbols: Seq[String],
  reporter: Reporter
) extends CoverageFilter

Usage Examples:

import scoverage.{RegexCoverageFilter, AllCoverageFilter}

// Create filter with exclusions
val filter = new RegexCoverageFilter(
  excludedPackages = Seq(".*\\.test\\..*", ".*\\.generated\\..*"),
  excludedFiles = Seq(".*Migration.*\\.scala"),
  excludedSymbols = Seq(".*Logger.*", ".*Debug.*"),
  reporter = global.reporter
)

// Check if class should be covered
val shouldCover = filter.isClassIncluded("com.example.service.UserService")

// Use no-exclusion filter
val allFilter = AllCoverageFilter

Instrumentation Component

The component that performs the actual code instrumentation.

/**
 * Compiler plugin component that performs code instrumentation
 * @param global The Scala compiler's Global object  
 * @param extraAfterPhase Optional phase to run after
 * @param extraBeforePhase Optional phase to run before
 */
class ScoverageInstrumentationComponent(
  val global: Global,
  extraAfterPhase: Option[String],
  extraBeforePhase: Option[String]
) extends PluginComponent with TypingTransformers with Transform {

  /** Phase name for the instrumentation */
  val phaseName: String
  
  /** Phases this component must run after */
  val runsAfter: List[String]
  
  /** Phases this component must run before */
  val runsBefore: List[String]
  
  /** Configure options for this component */
  def setOptions(options: ScoverageOptions): Unit
  
  /** Create new phase instance */
  def newPhase(prev: scala.tools.nsc.Phase): Phase
}

Location Utilities

Utilities for extracting location information from compiler AST nodes.

/**
 * Utilities for extracting location information from compiler trees
 */
object Location {
  /**
   * Create location extractor function for a specific compiler instance
   * @param global The compiler's Global object
   * @returns Function to extract Location from compiler Tree nodes
   */
  def fromGlobal(global: Global): global.Tree => Option[scoverage.domain.Location]
}

Compiler Plugin Usage

Command Line Options

The plugin accepts several command-line options via the -P:scoverage: prefix:

  • -P:scoverage:dataDir:<path> - Directory for coverage data files
  • -P:scoverage:excludedPackages:<regex> - Semicolon-separated regexes for package exclusion
  • -P:scoverage:excludedFiles:<regex> - Semicolon-separated regexes for file exclusion
  • -P:scoverage:excludedSymbols:<regex> - Semicolon-separated regexes for symbol exclusion
  • -P:scoverage:reportTestName:<boolean> - Include test names in coverage data
  • -P:scoverage:sourceRoot:<path> - Root directory for source files

SBT Integration

// project/plugins.sbt
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.3.0")

// build.sbt  
scoverageExcludedPackages := ".*\\.test\\..*;.*\\.generated\\..*"
scoverageExcludedFiles := ".*DatabaseMigrations.*"
scoverageMinimumCoverage := 80.0
scoverageFailOnMinimumCoverage := true

Manual Configuration

// Add to scalacOptions
scalacOptions ++= Seq(
  "-Xplugin:/path/to/scalac-scoverage-plugin.jar",
  "-P:scoverage:dataDir:target/scoverage-data",
  "-P:scoverage:excludedPackages:.*\\.test\\..*;.*\\.generated\\..*",
  "-P:scoverage:reportTestName:true",
  "-P:scoverage:sourceRoot:src/main/scala"
)

Exclusion Comments

Code can be excluded from coverage using special comments:

// $COVERAGE-OFF$
def debugOnlyMethod(): Unit = {
  println("This won't be covered")
}
// $COVERAGE-ON$

def normalMethod(): Unit = {
  // This will be covered normally
  println("Normal method")
}

Error Handling

  • PluginInitException: Thrown when plugin fails to initialize with provided options
  • InstrumentationException: Thrown when code instrumentation fails due to unsupported constructs
  • ConfigurationException: Thrown when invalid configuration options are provided
  • FileSystemException: Thrown when unable to create coverage data directory or write coverage files

Install with Tessl CLI

npx tessl i tessl/maven-org-scoverage--scalac-scoverage-plugin

docs

aggregation.md

cobertura-reports.md

coverage-model.md

html-reports.md

index.md

io-utils.md

plugin.md

runtime.md

serialization.md

xml-reports.md

tile.json