Skip to content

Commit

Permalink
Handle branches in anonymous function pattern matching (#534)
Browse files Browse the repository at this point in the history
* Handle branches in anonymous function pattern matching

* Handle canbuildfrom
  • Loading branch information
jrglee authored Feb 9, 2023
1 parent ea602c7 commit 068e41d
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 7 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
*.log

# Build Server Protocol
.bsp/

# SBT specific
target/
project/boot/
Expand Down
15 changes: 14 additions & 1 deletion plugin/src/main/scala/scoverage/ScoveragePlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,20 @@ class ScoverageInstrumentationComponent(

// handle function bodies. This AST node corresponds to the following Scala code: vparams => body
case f: Function =>
treeCopy.Function(tree, f.vparams, process(f.body))
f.body match {
case b: Match =>
// anonymous function bodies with pattern matching needs to account for branches
treeCopy.Function(
tree,
f.vparams,
treeCopy.Match(
b,
b.selector,
transformCases(b.cases, branch = true)
)
)
case _ => treeCopy.Function(tree, f.vparams, process(f.body))
}

case _: Ident => tree

Expand Down
38 changes: 32 additions & 6 deletions plugin/src/test/scala/scoverage/PluginCoverageTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -130,15 +130,41 @@ class PluginCoverageTest extends FunSuite with MacroSupport {
assert(!compiler.reporter.hasErrors)
// should instrument:
// the if clause,
// thenp block,
// thenp literal "1",
// elsep block,
// elsep literal "2",
// then block,
// then literal "1",
// else block,
// else literal "2",
// case block "yes" literal
// skip case block "yes" literal
compiler.assertNMeasuredStatements(7)
}

test(
"scoverage should instrument anonymous function with pattern matching body"
) {
val compiler = ScoverageCompiler.default
compiler.compileCodeSnippet(
""" object A {
| def foo(a: List[Option[Int]]) = a.map {
| case Some(value) => value + 1
| case None => 0
| }
|} """.stripMargin
)
assert(!compiler.reporter.hasErrors)
// should instrument:
// the def method entry,
// case Some,
// case block expression
// case none,
// case block literal "0"

// account for canbuildfrom statement
val expectedStatementsCount =
if (ScoverageCompiler.ShortScalaVersion < "2.13") 6 else 5
compiler.assertNMeasuredStatements(expectedStatementsCount)
}

// https://github.com/scoverage/sbt-scoverage/issues/16
test(
"scoverage should instrument for-loops but not the generated scaffolding"
Expand Down Expand Up @@ -246,9 +272,9 @@ class PluginCoverageTest extends FunSuite with MacroSupport {

assert(!compiler.reporter.hasErrors)
assert(!compiler.reporter.hasWarnings)
// should have 4 profiled statements: the outer apply, the true, the a < b, the false
// should have 7 profiled statements: the outer apply, and three pairs of case patterns & blocks
// we are testing that we don't instrument the tuple2 call used here
compiler.assertNMeasuredStatements(4)
compiler.assertNMeasuredStatements(7)
}

test("scoverage should instrument all case statements in an explicit match") {
Expand Down

0 comments on commit 068e41d

Please sign in to comment.