Skip to content

Commit 896d3a8

Browse files
committed
Merge pull request #133 from RichardBradley/issue-27
#27 use fully-qualified class names to avoid ambiguity in reports
2 parents 2d3b30c + 89dfbfc commit 896d3a8

14 files changed

+90
-64
lines changed

scalac-scoverage-plugin/src/main/scala/scoverage/Location.scala

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@ package scoverage
22

33
import scala.tools.nsc.Global
44

5+
/**
6+
* @param packageName the name of the enclosing package
7+
* @param className the name of the closest enclosing class
8+
* @param fullClassName the fully qualified name of the closest enclosing class
9+
*/
510
case class Location(packageName: String,
611
className: String,
7-
topLevelClass: String,
12+
fullClassName: String,
813
classType: ClassType,
914
method: String,
10-
sourcePath: String) extends java.io.Serializable {
11-
val fqn = (packageName + ".").replace("<empty>.", "") + className
12-
}
15+
sourcePath: String) extends java.io.Serializable
1316

1417
object Location {
1518

@@ -31,8 +34,10 @@ object Location {
3134
else ClassType.Class
3235
}
3336

34-
def topLevelClass(s: global.Symbol): String = {
35-
s.enclosingTopLevelClass.nameString
37+
def fullClassName(s: global.Symbol): String = {
38+
// anon functions are enclosed in proper classes.
39+
if (s.enclClass.isAnonymousFunction || s.enclClass.isAnonymousClass) fullClassName(s.owner)
40+
else s.enclClass.fullNameString
3641
}
3742

3843
def enclosingMethod(s: global.Symbol): String = {
@@ -51,7 +56,7 @@ object Location {
5156
Location(
5257
packageName(symbol),
5358
className(symbol),
54-
topLevelClass(symbol),
59+
fullClassName(symbol),
5560
classType(symbol),
5661
enclosingMethod(symbol),
5762
sourcePath(symbol))

scalac-scoverage-plugin/src/main/scala/scoverage/Serializer.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ object Serializer {
3333
<classType>
3434
{stmt.location.classType.toString}
3535
</classType>
36-
<topLevelClass>
37-
{stmt.location.topLevelClass}
38-
</topLevelClass>
36+
<fullClassName>
37+
{stmt.location.fullClassName}
38+
</fullClassName>
3939
<method>
4040
{stmt.location.method}
4141
</method>
@@ -93,7 +93,7 @@ object Serializer {
9393
val branch = (node \ "branch").text.toBoolean
9494
val _package = (node \ "package").text
9595
val _class = (node \ "class").text
96-
val topLevelClass = (node \ "topLevelClass").text
96+
val fullClassName = (node \ "fullClassName").text
9797
val method = (node \ "method").text
9898
val path = (node \ "path").text
9999
val treeName = (node \ "treeName").text
@@ -109,7 +109,7 @@ object Serializer {
109109
case _ => ClassType.Class
110110
}
111111
Statement(source,
112-
Location(_package, _class, topLevelClass, classType, method, path),
112+
Location(_package, _class, fullClassName, classType, method, path),
113113
id,
114114
start,
115115
end,

scalac-scoverage-plugin/src/main/scala/scoverage/coverage.scala

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ trait PackageBuilders {
6060

6161
trait ClassBuilders {
6262
def statements: Iterable[Statement]
63-
def classes = statements.groupBy(_.location.className).map(arg => MeasuredClass(arg._1, arg._2))
63+
def classes = statements.groupBy(_.location.fullClassName).map(arg => MeasuredClass(arg._1, arg._2))
6464
def classCount: Int = classes.size
6565
}
6666

@@ -74,12 +74,23 @@ case class MeasuredMethod(name: String, statements: Iterable[Statement]) extends
7474
override def ignoredStatements: Iterable[Statement] = Seq()
7575
}
7676

77-
case class MeasuredClass(name: String, statements: Iterable[Statement])
77+
case class MeasuredClass(fullClassName: String, statements: Iterable[Statement])
7878
extends CoverageMetrics with MethodBuilders {
79+
7980
def source: String = statements.head.source
80-
def simpleName = name.split('.').last
8181
def loc = statements.map(_.line).max
8282

83+
/**
84+
* The class name for display is the FQN minus the package,
85+
* for example "com.a.Foo.Bar.Baz" should display as "Foo.Bar.Baz"
86+
* and "com.a.Foo" should display as "Foo".
87+
*
88+
* This is used in the class lists in the package and overview pages.
89+
*/
90+
def displayClassName = statements.headOption.map(_.location).map { location =>
91+
location.fullClassName.stripPrefix(location.packageName + ".")
92+
}.getOrElse(fullClassName)
93+
8394
override def ignoredStatements: Iterable[Statement] = Seq()
8495
}
8596

scalac-scoverage-plugin/src/main/scala/scoverage/report/CoberturaXmlWriter.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class CoberturaXmlWriter(sourceDirectories: Seq[File], outputDir: File) extends
3939
}
4040

4141
def klass(klass: MeasuredClass): Node = {
42-
<class name={klass.name}
42+
<class name={klass.fullClassName}
4343
filename={relativeSource(klass.source).replace(File.separator, "/")}
4444
line-rate={format(klass.statementCoverage)}
4545
branch-rate={format(klass.branchCoverage)}

scalac-scoverage-plugin/src/main/scala/scoverage/report/ScoverageHtmlWriter.scala

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import scala.xml.Node
1111
class ScoverageHtmlWriter(sourceDirectories: Seq[File], outputDir: File) extends BaseReportWriter(sourceDirectories, outputDir) {
1212

1313
def this (sourceDirectory: File, outputDir: File) {
14-
this(Seq(sourceDirectory), outputDir);
14+
this(Seq(sourceDirectory), outputDir)
1515
}
1616

1717
def write(coverage: Coverage): Unit = {
@@ -193,7 +193,7 @@ class ScoverageHtmlWriter(sourceDirectories: Seq[File], outputDir: File) extends
193193
</tr>
194194
</thead>
195195
<tbody>
196-
{classes.toSeq.sortBy(_.simpleName) map classRow}
196+
{classes.toSeq.sortBy(_.fullClassName) map classRow}
197197
</tbody>
198198
</table>
199199
}
@@ -217,11 +217,10 @@ class ScoverageHtmlWriter(sourceDirectories: Seq[File], outputDir: File) extends
217217
val statement0f = Math.round(klass.statementCoveragePercent).toInt.toString
218218
val branch0f = Math.round(klass.branchCoveragePercent).toInt.toString
219219

220-
val simpleClassName = klass.name.split('.').last
221220
<tr>
222221
<td>
223222
<a href={filename}>
224-
{simpleClassName}
223+
{klass.displayClassName}
225224
</a>
226225
</td>
227226
<td>
@@ -331,7 +330,7 @@ class ScoverageHtmlWriter(sourceDirectories: Seq[File], outputDir: File) extends
331330
{coverage.risks(limit).map(klass =>
332331
<tr>
333332
<td>
334-
{klass.simpleName}
333+
{klass.displayClassName}
335334
</td>
336335
<td>
337336
{klass.loc.toString}

scalac-scoverage-plugin/src/main/scala/scoverage/report/ScoverageXmlReader.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ object ScoverageXmlReader {
2222
val pkg = node \ "@package"
2323
val classname = node \ "@class"
2424
val classType = node \ "@class-type"
25-
val topLevelClass = node \ "@top-level-class"
25+
val fullClassName = node \ "@full-class-name"
2626
val method = node \ "@method"
2727
val start = node \ "@start"
2828
val end = node \ "@end"
@@ -35,7 +35,7 @@ object ScoverageXmlReader {
3535

3636
val location = Location(pkg.text,
3737
classname.text,
38-
topLevelClass.text,
38+
fullClassName.text,
3939
ClassType fromString classType.text,
4040
method.text,
4141
source.text)

scalac-scoverage-plugin/src/main/scala/scoverage/report/ScoverageXmlWriter.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import scala.xml.{Node, PrettyPrinter}
1010
class ScoverageXmlWriter(sourceDirectories: Seq[File], outputDir: File, debug: Boolean) extends BaseReportWriter(sourceDirectories, outputDir) {
1111

1212
def this (sourceDir: File, outputDir: File, debug: Boolean) {
13-
this(Seq(sourceDir), outputDir, debug);
13+
this(Seq(sourceDir), outputDir, debug)
1414
}
1515

1616
def write(coverage: Coverage): Unit = {
@@ -37,7 +37,7 @@ class ScoverageXmlWriter(sourceDirectories: Seq[File], outputDir: File, debug: B
3737
<statement package={stmt.location.packageName}
3838
class={stmt.location.className}
3939
class-type={stmt.location.classType.toString}
40-
top-level-class={stmt.location.topLevelClass}
40+
full-class-name={stmt.location.fullClassName}
4141
source={stmt.source}
4242
method={stmt.location.method}
4343
start={stmt.start.toString}
@@ -54,7 +54,7 @@ class ScoverageXmlWriter(sourceDirectories: Seq[File], outputDir: File, debug: B
5454
<statement package={stmt.location.packageName}
5555
class={stmt.location.className}
5656
class-type={stmt.location.classType.toString}
57-
top-level-class={stmt.location.topLevelClass}
57+
full-class-name={stmt.location.fullClassName}
5858
source={stmt.source}
5959
method={stmt.location.method}
6060
start={stmt.start.toString}
@@ -79,7 +79,7 @@ class ScoverageXmlWriter(sourceDirectories: Seq[File], outputDir: File, debug: B
7979
}
8080

8181
private def klass(klass: MeasuredClass): Node = {
82-
<class name={klass.name}
82+
<class name={klass.fullClassName}
8383
filename={relativeSource(klass.source)}
8484
statement-count={klass.statementCount.toString}
8585
statements-invoked={klass.invokedStatementCount.toString}

scalac-scoverage-plugin/src/test/scala/scoverage/CoberturaXmlWriterTest.scala

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,29 +32,29 @@ class CoberturaXmlWriterTest extends FunSuite with BeforeAndAfter with OneInstan
3232

3333
val coverage = scoverage.Coverage()
3434
coverage
35-
.add(Statement(canonicalPath("a.scala"), Location("com.sksamuel.scoverage", "A", "A", ClassType.Object, "create", canonicalPath("a.scala")),
35+
.add(Statement(canonicalPath("a.scala"), Location("com.sksamuel.scoverage", "A", "com.sksamuel.scoverage.A", ClassType.Object, "create", canonicalPath("a.scala")),
3636
1, 2, 3, 12, "", "", "", false, 3))
3737
coverage
38-
.add(Statement(canonicalPath("a.scala"), Location("com.sksamuel.scoverage", "A", "A", ClassType.Object, "create2", canonicalPath("a.scala")),
38+
.add(Statement(canonicalPath("a.scala"), Location("com.sksamuel.scoverage", "A", "com.sksamuel.scoverage.A", ClassType.Object, "create2", canonicalPath("a.scala")),
3939
2, 2, 3, 16, "", "", "", false, 3))
4040
coverage
41-
.add(Statement(canonicalPath("b.scala"), Location("com.sksamuel.scoverage2", "B", "B", ClassType.Object, "retrieve", canonicalPath("b.scala")),
41+
.add(Statement(canonicalPath("b.scala"), Location("com.sksamuel.scoverage2", "B", "com.sksamuel.scoverage2.B", ClassType.Object, "retrieve", canonicalPath("b.scala")),
4242
3, 2, 3, 21, "", "", "", false, 0))
4343
coverage
4444
.add(Statement(canonicalPath("b.scala"),
4545
Location("com.sksamuel.scoverage2", "B", "B", ClassType.Object, "retrieve2", canonicalPath("b.scala")),
4646
4, 2, 3, 9, "", "", "", false, 3))
4747
coverage
48-
.add(Statement(canonicalPath("c.scala"), Location("com.sksamuel.scoverage3", "C", "C", ClassType.Object, "update", canonicalPath("c.scala")),
48+
.add(Statement(canonicalPath("c.scala"), Location("com.sksamuel.scoverage3", "C", "com.sksamuel.scoverage3.C", ClassType.Object, "update", canonicalPath("c.scala")),
4949
5, 2, 3, 66, "", "", "", true, 3))
5050
coverage
51-
.add(Statement(canonicalPath("c.scala"), Location("com.sksamuel.scoverage3", "C", "C", ClassType.Object, "update2", canonicalPath("c.scala")),
51+
.add(Statement(canonicalPath("c.scala"), Location("com.sksamuel.scoverage3", "C", "com.sksamuel.scoverage3.C", ClassType.Object, "update2", canonicalPath("c.scala")),
5252
6, 2, 3, 6, "", "", "", true, 3))
5353
coverage
54-
.add(Statement(canonicalPath("d.scala"), Location("com.sksamuel.scoverage4", "D", "D", ClassType.Object, "delete", canonicalPath("d.scala")),
54+
.add(Statement(canonicalPath("d.scala"), Location("com.sksamuel.scoverage4", "D", "com.sksamuel.scoverage4.D", ClassType.Object, "delete", canonicalPath("d.scala")),
5555
7, 2, 3, 4, "", "", "", false, 0))
5656
coverage
57-
.add(Statement(canonicalPath("d.scala"), Location("com.sksamuel.scoverage4", "D", "D", ClassType.Object, "delete2", canonicalPath("d.scala")),
57+
.add(Statement(canonicalPath("d.scala"), Location("com.sksamuel.scoverage4", "D", "com.sksamuel.scoverage4.D", ClassType.Object, "delete2", canonicalPath("d.scala")),
5858
8, 2, 3, 14, "", "", "", false, 0))
5959

6060
val writer = new CoberturaXmlWriter(sourceRoot, dir)
@@ -87,13 +87,13 @@ class CoberturaXmlWriterTest extends FunSuite with BeforeAndAfter with OneInstan
8787

8888
val coverage = Coverage()
8989
coverage
90-
.add(Statement(canonicalPath("a.scala"), Location("com.sksamuel.scoverage", "A", "A", ClassType.Object, "create", canonicalPath("a.scala")),
90+
.add(Statement(canonicalPath("a.scala"), Location("com.sksamuel.scoverage", "A", "com.sksamuel.scoverage.A", ClassType.Object, "create", canonicalPath("a.scala")),
9191
1, 2, 3, 12, "", "", "", false))
9292
coverage
93-
.add(Statement(canonicalPath("a.scala"), Location("com.sksamuel.scoverage", "A", "A", ClassType.Object, "create2", canonicalPath("a.scala")),
93+
.add(Statement(canonicalPath("a.scala"), Location("com.sksamuel.scoverage", "A", "com.sksamuel.scoverage.A", ClassType.Object, "create2", canonicalPath("a.scala")),
9494
2, 2, 3, 16, "", "", "", true))
9595
coverage
96-
.add(Statement(canonicalPath("a.scala"), Location("com.sksamuel.scoverage", "A", "A", ClassType.Object, "create3", canonicalPath("a.scala")),
96+
.add(Statement(canonicalPath("a.scala"), Location("com.sksamuel.scoverage", "A", "com.sksamuel.scoverage.A", ClassType.Object, "create3", canonicalPath("a.scala")),
9797
3, 3, 3, 20, "", "", "", true, 1))
9898

9999
val writer = new CoberturaXmlWriter(sourceRoot, dir)

scalac-scoverage-plugin/src/test/scala/scoverage/CoverageAggregatorTest.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class CoverageAggregatorTest extends FreeSpec with Matchers {
1818
val source = canonicalPath("com/scoverage/class.scala")
1919
val location = Location("com.scoverage.foo",
2020
"ServiceState",
21-
"Service",
21+
"com.scoverage.foo.Service.ServiceState",
2222
ClassType.Trait,
2323
"methlab",
2424
source)

0 commit comments

Comments
 (0)