Skip to content

fix: ignore lazy definition generated from by-name implicits #536

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,14 @@ lazy val plugin =
sharedSettings
)
.settings(
Test / unmanagedSourceDirectories += (Test / sourceDirectory).value / "scala-2.12+"
Test / unmanagedSourceDirectories += (Test / sourceDirectory).value / "scala-2.12+",
Test / unmanagedSourceDirectories ++= {
val sourceDir = (Test / sourceDirectory).value
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, n)) if n >= 13 => Seq(sourceDir / "scala-2.13+")
case _ => Seq.empty
}
}
)
.dependsOn(domain, reporter % "test->compile", serializer, buildInfo % Test)

Expand Down
8 changes: 8 additions & 0 deletions plugin/src/main/scala/scoverage/ScoveragePlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,14 @@ class ScoverageInstrumentationComponent(
*/
case s: Select if s.symbol.isLazy => tree

// Generated by compiler for lazy definitions involving
// by-name implicit parameters. More on that here:
// https://docs.scala-lang.org/sips/byname-implicits.html
//
// final <synthetic> val lazyDefns$1: LazyDefns$1 = new LazyDefns$1();
// lazyDefns$1.rec$1()
case s: Select if s.symbol.isSynthetic => tree

case s: Select =>
instrument(
treeCopy.Select(s, traverseApplication(s.qualifier), s.name),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package scoverage

import munit.FunSuite

class Scala213PluginCoverageTest extends FunSuite with MacroSupport {

test(
"scoverage should ignore synthetic lazy definitions generated by compiler from by-name implicits"
) {
val compiler = ScoverageCompiler.noPositionValidation
compiler.compileCodeSnippet(
"""
|object test {
|
| trait Foo {
| def next: Foo
| }
|
| object Foo {
| implicit def foo(implicit rec: => Foo): Foo =
| new Foo { def next = rec }
| }
|
| val foo = implicitly[Foo]
|
|}
|
""".stripMargin
)
assert(!compiler.reporter.hasErrors)
assert(!compiler.reporter.hasWarnings)
}
}
15 changes: 11 additions & 4 deletions plugin/src/test/scala/scoverage/ScoverageCompiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,17 @@ private[scoverage] object ScoverageCompiler {

def default: ScoverageCompiler = {
val reporter = new scala.tools.nsc.reporters.ConsoleReporter(settings)
new ScoverageCompiler(settings, reporter)
new ScoverageCompiler(settings, reporter, validatePositions = true)
}

def noPositionValidation: ScoverageCompiler = {
val reporter = new scala.tools.nsc.reporters.ConsoleReporter(settings)
new ScoverageCompiler(settings, reporter, validatePositions = false)
}

def defaultJS: ScoverageCompiler = {
val reporter = new scala.tools.nsc.reporters.ConsoleReporter(jsSettings)
new ScoverageCompiler(jsSettings, reporter)
new ScoverageCompiler(jsSettings, reporter, validatePositions = true)
}

def locationCompiler: LocationCompiler = {
Expand Down Expand Up @@ -152,7 +157,8 @@ private[scoverage] object ScoverageCompiler {

class ScoverageCompiler(
settings: scala.tools.nsc.Settings,
rep: scala.tools.nsc.reporters.Reporter
rep: scala.tools.nsc.reporters.Reporter,
validatePositions: Boolean
) extends scala.tools.nsc.Global(settings, rep) {

def addToClassPath(file: File): Unit = {
Expand Down Expand Up @@ -268,7 +274,8 @@ class ScoverageCompiler(

override def computeInternalPhases(): Unit = {
super.computeInternalPhases()
addToPhasesSet(validator, "scoverage validator")
if (validatePositions)
addToPhasesSet(validator, "scoverage validator")
addToPhasesSet(
instrumentationComponent,
"scoverage instrumentationComponent"
Expand Down