Built from main at 1d902a0 on 2026-11-14

Scala

Recognised by .scala sources and the build tools: sbt (*.sbt), Mill (build.mill, build.sc) and scala-cli (project.scala). .sc scripts (Ammonite, Mill) are Scala's once the project is; .sbt files name no language of their own. The build's target/, out/ and .scala-build/ directories are build trees and are never read.

The tools run tasks, and one command may run several: sbt coverage test coverageReport, sbt "scalafixAll --check", sbt "; core/test; Test/scalafmtCheck" (a scope and a cross-building + are dropped; ++3.3.5 only switches the Scala version), mill __.fix --check + __.compile (a selector whose last segment is the task), scala-cli test . (also as the scala runner since Scala 3.5). Every rule below is about the task, however it is run.

The compiled-language checks that need a C-family compiler (hardening, build types, extensions, sanitizers) do not apply, and nor do type checking (Scala is statically typed), fuzz and mutation testing (no fuzzer or mutation tool for Scala is known) and dependency management (sbt, Mill and scala-cli lock nothing).

tests-run

munit, ScalaTest, specs2, utest, ZIO Test or ScalaCheck suites under src/test/scala (or Mill's test/src), recognised by their import or the suite they extend, run by sbt test (testOnly, testQuick), mill __.test or scala-cli test.

coverage

scoverage, which instruments statements and branches: sbt coverage test coverageReport (or coverageAggregate), or Mill's __.scoverage.xmlReport (htmlReport, consoleReport). sbt-jacoco (sbt jacoco) counts lines and branches too.

platform-matrix

The toolchains are the JDK versions (the JVM profile's: java-version, the JDK images, coursier's jvm input) and the Scala versions a job switches to (sbt ++3.3.5 test, scala-cli --scala 3.3.5, -S 3.3.5, a scala-version input), or cross-builds (sbt +test, mill __.test) with the versions the build names (crossScalaVersions := Seq("2.13.16", "3.3.5") in an .sbt file, Mill's Cross[Module](https://github.com/cpp-best-practices/project_validator/blob/1d902a0c4c2dce7e7f12c7435bbe07a6a70f2422/docs/ecosystems/"2.13.16", "3.3.5")). A job naming both runs each Scala version on each JDK (JDK 21 / Scala 3.3.5); one that switches to no Scala version builds the version its build names, and counts its JDKs.

compiler-warnings

-deprecation, -feature and -Xlint (Scala 2) or -Wunused/-Wall (Scala 3) in scalacOptions (in the sbt or Mill build, or scala-cli's //> using options), or sbt-tpolecat, which sets them all.

warnings-as-errors

-Werror (or -Xfatal-warnings) in scalacOptions, or sbt-tpolecat's CI mode (SBT_TPOLECAT_CI=true in CI, or tpolecatDefaultOptionsMode := CiMode).

code-formatting

scalafmt, which refuses to run without a .scalafmt.conf naming its version: sbt scalafmtCheckAll (scalafmtCheck, scalafmtSbtCheck), scalafmt --check (--test, --list), Mill's __.checkFormat (checkFormatAll) or scala-cli fmt --check, each failing on a file it would change; scalafmtAll, scalafmt, __.reformat and plain scala-cli fmt rewrite.

static-analysis

scalafix with the rules .scalafix.conf names: sbt "scalafixAll --check" (or scalafix), Mill's __.fix --check.

security-scanning

semgrep or GitLab SAST; CodeQL does not analyse Scala.

dependency-audit

sbt-dependency-check (sbt dependencyCheck, dependencyCheckAggregate), snyk or GitLab Dependency Scanning; osv-scanner and trivy read no sbt build.

committed-artifacts

sbt's target/, Mill's out/, scala-cli's .scala-build/.

vcs-ignore

The build tool's output directory (target/, out/ or .scala-build/); .bsp/, .bloop/ and .metals/ are worth ignoring too.

function-limits

lizard parses Scala, so CI runs it with a length limit.