Skip to content

Commit 37a7a34

Browse files
committed
#32 fixed match warnings by instrumenting selector as a tree
1 parent d0a849b commit 37a7a34

File tree

3 files changed

+43
-11
lines changed

3 files changed

+43
-11
lines changed

src/main/scala/scoverage/plugin.scala

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ class ScoverageInstrumentationComponent(val global: Global)
169169
})
170170
}
171171

172-
def instrument(tree: Tree, branch: Boolean = false) = {
172+
def instrument(tree: Tree, branch: Boolean = false): Tree = {
173173
safeSource(tree) match {
174174
case None =>
175175
println(s"[warn] Could not instrument [${tree.getClass.getSimpleName}/${tree.symbol}]. No position.")
@@ -436,14 +436,21 @@ class ScoverageInstrumentationComponent(val global: Global)
436436
case l: Literal => instrument(l)
437437

438438
// pattern match clauses will be instrumented per case
439-
case m@Match(clause: Tree, cases: List[CaseDef]) =>
439+
case m@Match(selector: Tree, cases: List[CaseDef]) =>
440440
// we can be fairly sure this was generated as part of a for loop
441-
if (m.selector.toString().contains("check$")
442-
&& m.selector.tpe.annotations.mkString == "unchecked"
443-
&& m.cases.last.toString == "case _ => false") // todo check these assumptions for 2.11
444-
treeCopy.Match(tree, instrument(clause), transformCases(cases.dropRight(1)) ++ cases.takeRight(1))
445-
else
446-
treeCopy.Match(tree, instrument(clause), transformCases(cases))
441+
if (selector.toString().contains("check$")
442+
&& selector.tpe.annotations.mkString == "unchecked"
443+
&& m.cases.last.toString == "case _ => false") {
444+
// todo check these assumptions for 2.11
445+
treeCopy.Match(tree, instrument(selector), transformCases(cases.dropRight(1)) ++ cases.takeRight(1))
446+
} else {
447+
// import scala.reflect.runtime.universe.{reify, showRaw}
448+
// val _selector = reify {
449+
// Match(Annotated(Apply(Select(New(Ident(scala.unchecked)), nme.CONSTRUCTOR), List()),
450+
// Ident(newTermName("name")))
451+
// }
452+
instrument(treeCopy.Match(tree, process(selector), transformCases(cases)))
453+
}
447454

448455
// a synthetic object is a generated object, such as case class companion
449456
case m: ModuleDef if m.symbol.isSynthetic => super.transform(tree)
@@ -582,4 +589,3 @@ class ScoverageInstrumentationComponent(val global: Global)
582589
}
583590
}
584591

585-

src/test/scala/scoverage/PluginASTSupportTest.scala

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,20 @@ class PluginASTSupportTest
6565
assert(!reporter.hasErrors)
6666
}
6767

68-
// test("scoverage supports skinny #23") {
68+
69+
// https://github.com/scoverage/scalac-scoverage-plugin/issues/32
70+
test("exhaustive warnings should not be generated for @unchecked") {
71+
compileCodeSnippet( """object PartialMatchObject {
72+
| def partialMatchExample(s: Option[String]): Unit = {
73+
| (s: @unchecked) match {
74+
| case Some(str) => println(str)
75+
| }
76+
| }
77+
|} """.stripMargin)
78+
assert(!reporter.hasWarnings)
79+
}
80+
81+
// test("scoverage supports skinny #23") {
6982
// addToClassPath("org.joda", "joda-convert", "1.3.1")
7083
// addToClassPath("joda-time", "joda-time", "2.3")
7184
// addToClassPath("org.scalikejdbc", "scalikejdbc_2.10", "1.7.5")

src/test/scala/scoverage/PluginCoverageTest.scala

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,24 @@ class PluginCoverageTest
3333
assertNMeasuredStatements(3)
3434
}
3535

36-
36+
test("scoverage should instrument selectors in match") {
37+
compileCodeSnippet( """ trait A {
38+
| def foo(a:String) = (if (a == "hello") 1 else 2) match {
39+
| case any => "yes"
40+
| }
41+
|} """.stripMargin)
42+
assert(!reporter.hasErrors)
43+
// should instrument the method call, the if clause, thenp, thenp literal, elsep, elsep literal, case block,
44+
// case block literal
45+
assertNMeasuredStatements(8)
46+
}
3747

3848
// https://github.com/scoverage/sbt-scoverage/issues/16
3949
test("scoverage should instrument for-loops but not the generated default case") {
4050
compileCodeSnippet( """ trait A {
4151
| def print1(list: List[String]) = for (string: String <- list) println(string)
4252
|} """.stripMargin)
53+
assert(!reporter.hasErrors)
4354
// should have one statement for the withFilter invoke, one of the match selector,
4455
// one of the case block, one for the case string RHS value, one for the foreach block.
4556
assertNMeasuredStatements(5)
@@ -53,7 +64,9 @@ class PluginCoverageTest
5364
| case _ => 3
5465
| }
5566
|} """.stripMargin)
67+
assert(!reporter.hasErrors)
5668
// should have one statement for each literal, one for each case block, and one for the selector.
5769
assertNMeasuredStatements(7)
5870
}
71+
5972
}

0 commit comments

Comments
 (0)