Skip to content

Commit 068e41d

Browse files
authored
Handle branches in anonymous function pattern matching (#534)
* Handle branches in anonymous function pattern matching * Handle canbuildfrom
1 parent ea602c7 commit 068e41d

File tree

3 files changed

+49
-7
lines changed

3 files changed

+49
-7
lines changed

Diff for: .gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
*.log
22

3+
# Build Server Protocol
4+
.bsp/
5+
36
# SBT specific
47
target/
58
project/boot/

Diff for: plugin/src/main/scala/scoverage/ScoveragePlugin.scala

+14-1
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,20 @@ class ScoverageInstrumentationComponent(
660660

661661
// handle function bodies. This AST node corresponds to the following Scala code: vparams => body
662662
case f: Function =>
663-
treeCopy.Function(tree, f.vparams, process(f.body))
663+
f.body match {
664+
case b: Match =>
665+
// anonymous function bodies with pattern matching needs to account for branches
666+
treeCopy.Function(
667+
tree,
668+
f.vparams,
669+
treeCopy.Match(
670+
b,
671+
b.selector,
672+
transformCases(b.cases, branch = true)
673+
)
674+
)
675+
case _ => treeCopy.Function(tree, f.vparams, process(f.body))
676+
}
664677

665678
case _: Ident => tree
666679

Diff for: plugin/src/test/scala/scoverage/PluginCoverageTest.scala

+32-6
Original file line numberDiff line numberDiff line change
@@ -130,15 +130,41 @@ class PluginCoverageTest extends FunSuite with MacroSupport {
130130
assert(!compiler.reporter.hasErrors)
131131
// should instrument:
132132
// the if clause,
133-
// thenp block,
134-
// thenp literal "1",
135-
// elsep block,
136-
// elsep literal "2",
133+
// then block,
134+
// then literal "1",
135+
// else block,
136+
// else literal "2",
137137
// case block "yes" literal
138138
// skip case block "yes" literal
139139
compiler.assertNMeasuredStatements(7)
140140
}
141141

142+
test(
143+
"scoverage should instrument anonymous function with pattern matching body"
144+
) {
145+
val compiler = ScoverageCompiler.default
146+
compiler.compileCodeSnippet(
147+
""" object A {
148+
| def foo(a: List[Option[Int]]) = a.map {
149+
| case Some(value) => value + 1
150+
| case None => 0
151+
| }
152+
|} """.stripMargin
153+
)
154+
assert(!compiler.reporter.hasErrors)
155+
// should instrument:
156+
// the def method entry,
157+
// case Some,
158+
// case block expression
159+
// case none,
160+
// case block literal "0"
161+
162+
// account for canbuildfrom statement
163+
val expectedStatementsCount =
164+
if (ScoverageCompiler.ShortScalaVersion < "2.13") 6 else 5
165+
compiler.assertNMeasuredStatements(expectedStatementsCount)
166+
}
167+
142168
// https://github.com/scoverage/sbt-scoverage/issues/16
143169
test(
144170
"scoverage should instrument for-loops but not the generated scaffolding"
@@ -246,9 +272,9 @@ class PluginCoverageTest extends FunSuite with MacroSupport {
246272

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

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

0 commit comments

Comments
 (0)