Skip to content

Commit

Permalink
Support file and package exclusions for Scala 3.4.2+
Browse files Browse the repository at this point in the history
  • Loading branch information
jozic authored and ckipp01 committed Jul 1, 2024
1 parent e1df4f7 commit 76a39fb
Show file tree
Hide file tree
Showing 11 changed files with 126 additions and 26 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,7 @@ coverageExcludedFiles := ".*\\/two\\/GoodCoverage;.*\\/three\\/.*"

Note: The `.scala` file extension needs to be omitted from the filename, if one is given.

Note: These two options only work for Scala2. Right now Scala3 does not support
a way to exclude packages or files from being instrumented.
Note: These two options only work for Scala2 and Scala 3.4.2+.

You can also mark sections of code with comments like:

Expand All @@ -104,6 +103,8 @@ You can also mark sections of code with comments like:
Any code between two such comments will not be instrumented or included in the
coverage report.

Note: Comments exclusion works only for Scala2.

### Minimum coverage

Based on minimum coverage, you can fail the build with the following keys:
Expand Down
69 changes: 49 additions & 20 deletions src/main/scala/scoverage/ScoverageSbtPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,28 @@ object ScoverageSbtPlugin extends AutoPlugin {
private def isScala2(scalaVersion: String) =
CrossVersion
.partialVersion(scalaVersion)
.collect { case (2, _) =>
true
.exists {
case (2, _) => true
case _ => false
}
.getOrElse(false)

private def isScala3SupportingScoverage(scalaVersion: String) =
CrossVersion
.partialVersion(scalaVersion)
.collect {
.exists {
case (3, minor) if minor >= 2 => true
case _ => false
}

private def isScala3SupportingFilePackageExclusion(scalaVersion: String) = {
def patch = scalaVersion.split('.').drop(2).headOption
CrossVersion
.partialVersion(scalaVersion)
.exists {
case (3, minor) if minor >= 4 && patch.exists(_ >= "2") => true
case _ => false
}
.getOrElse(false)
}

private lazy val coverageSettings = Seq(
libraryDependencies ++= {
Expand Down Expand Up @@ -114,6 +124,18 @@ object ScoverageSbtPlugin extends AutoPlugin {

implicit val log = streams.value.log

val excludedPackages =
Option(coverageExcludedPackages.value.trim).filter(_.nonEmpty)
val excludedFiles = Option(coverageExcludedFiles.value.trim)
.filter(_.nonEmpty)
.map(v =>
// On windows, replace unix file separators with windows file
// separators. Note that we need to replace / with \\ because
// the plugin treats this string as a regular expression and
// backslashes must be escaped in regular expressions.
if (isWindows) v.replace("/", """\\""") else v
)

val updateReport = update.value
if (coverageEnabled.value && isScala2(scalaVersion.value)) {
val scoverageDeps: Seq[File] =
Expand Down Expand Up @@ -156,19 +178,8 @@ object ScoverageSbtPlugin extends AutoPlugin {
Some(
s"-P:scoverage:sourceRoot:${coverageSourceRoot.value.getAbsolutePath}"
),
Option(coverageExcludedPackages.value.trim)
.filter(_.nonEmpty)
.map(v => s"-P:scoverage:excludedPackages:$v"),
Option(coverageExcludedFiles.value.trim)
.filter(_.nonEmpty)
.map(v =>
// On windows, replace unix file separators with windows file
// separators. Note that we need to replace / with \\ because
// the plugin treats this string as a regular expression and
// backslashes must be escaped in regular expressions.
if (isWindows) v.replace("/", """\\""") else v
)
.map(v => s"-P:scoverage:excludedFiles:$v"),
excludedPackages.map(v => s"-P:scoverage:excludedPackages:$v"),
excludedFiles.map(v => s"-P:scoverage:excludedFiles:$v"),
Some("-P:scoverage:reportTestName"),
// rangepos is broken in some releases of scala so option to turn it off
if (coverageHighlighting.value) Some("-Yrangepos") else None
Expand All @@ -177,8 +188,26 @@ object ScoverageSbtPlugin extends AutoPlugin {
coverageEnabled.value && isScala3SupportingScoverage(scalaVersion.value)
) {
Seq(
s"-coverage-out:${coverageDataDir.value.getAbsolutePath()}/scoverage-data"
)
Some(
s"-coverage-out:${coverageDataDir.value.getAbsolutePath()}/scoverage-data"
),
excludedPackages
.collect {
case v
if isScala3SupportingFilePackageExclusion(
scalaVersion.value
) =>
s"-coverage-exclude-classlikes:$v"
},
excludedFiles
.collect {
case v
if isScala3SupportingFilePackageExclusion(
scalaVersion.value
) =>
s"-coverage-exclude-files:$v"
}
).flatten
} else if (coverageEnabled.value && !isScala2(scalaVersion.value)) {
log.warn(
"coverage in Scala 3 needs at least 3.2.x. Please update your Scala version and try again."
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
version := "0.1"

scalaVersion := "3.2.0-RC1"
scalaVersion := "3.4.2"

libraryDependencies += "org.scalameta" %% "munit" % "0.7.29" % Test

Expand Down
4 changes: 1 addition & 3 deletions src/sbt-test/scoverage/scala3-coverage-excluded-files/test
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,4 @@
> test
> coverageReport
# There should be no directory for the excluded files
#-$ exists target/scala-3.2.0-RC1/scoverage-report/two
# But right now there is, because Scala3 does not support excluding files
$ exists target/scala-3.2.0-RC1/scoverage-report/two
-$ exists target/scala-3.4.2/scoverage-report/two
13 changes: 13 additions & 0 deletions src/sbt-test/scoverage/scala3-coverage-excluded-packages/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
version := "0.1"

scalaVersion := "3.4.2"

libraryDependencies += "org.scalameta" %% "munit" % "0.7.29" % Test

coverageExcludedPackages := "two\\..*"

resolvers ++= {
if (sys.props.get("plugin.version").exists(_.endsWith("-SNAPSHOT")))
Seq(Resolver.sonatypeRepo("snapshots"))
else Seq.empty
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sbt.version=1.9.9
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
val pluginVersion = sys.props.getOrElse(
"plugin.version",
throw new RuntimeException(
"""|The system property 'plugin.version' is not defined.
|Specify this property using the scriptedLaunchOpts -D.""".stripMargin
)
)

addSbtPlugin("org.scoverage" % "sbt-scoverage" % pluginVersion)

resolvers ++= {
if (pluginVersion.endsWith("-SNAPSHOT"))
Seq(Resolver.sonatypeRepo("snapshots"))
else
Seq.empty
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
object GoodCoverage {

def sum(num1: Int, num2: Int) = {
if (0 == num1) num2 else if (0 == num2) num1 else num1 + num2
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package two

object GoodCoverage {

def sum(num1: Int, num2: Int) = {
if (0 == num1) num2 else if (0 == num2) num1 else num1 + num2
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import munit.FunSuite

/** Created by tbarke001c on 7/8/14.
*/
class GoodCoverageSpec extends FunSuite {

test("GoodCoverage should sum two numbers") {
assertEquals(GoodCoverage.sum(1, 2), 3)
assertEquals(GoodCoverage.sum(0, 3), 3)
assertEquals(GoodCoverage.sum(3, 0), 3)
}

test("two.GoodCoverage should sum two numbers") {
assertEquals(two.GoodCoverage.sum(1, 2), 3)
assertEquals(two.GoodCoverage.sum(0, 3), 3)
assertEquals(two.GoodCoverage.sum(3, 0), 3)
}

}
7 changes: 7 additions & 0 deletions src/sbt-test/scoverage/scala3-coverage-excluded-packages/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# run scoverage using the coverage task
> clean
> coverage
> test
> coverageReport
# There should be no directory for the excluded package
-$ exists target/scala-3.4.2/scoverage-report/two

0 comments on commit 76a39fb

Please sign in to comment.