Skip to content

Commit acb5946

Browse files
committed
Reworked test compiler support
1 parent 6d1f17e commit acb5946

File tree

6 files changed

+240
-114
lines changed

6 files changed

+240
-114
lines changed

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,18 @@ object Location {
3232
else Option(s.owner.enclMethod.nameString).getOrElse("<none>")
3333
}
3434

35+
def sourcePath(symbol: global.Symbol): String = {
36+
Option(symbol.sourceFile).map(_.canonicalPath).getOrElse("<none>")
37+
}
38+
3539
Option(tree.symbol) map {
3640
symbol =>
3741
Location(
3842
symbol.enclosingPackage.fullName,
3943
className(symbol),
4044
classType(symbol),
4145
enclosingMethod(symbol),
42-
symbol.sourceFile.canonicalPath)
46+
sourcePath(symbol))
4347
}
4448
}
4549
}

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,16 @@ class ScoverageInstrumentationComponent(val global: Global)
8282
override def newPhase(prev: scala.tools.nsc.Phase): Phase = new Phase(prev) {
8383

8484
override def run(): Unit = {
85-
println(s"[info] [scoverage]: Cleaning datadir [${options.dataDir}]")
85+
println(s"[info] Cleaning datadir [${options.dataDir}]")
8686
IOUtils.clean(options.dataDir)
8787

88-
println("[info] [scoverage]: Begin instrumentation phase")
88+
println("[info] Beginning coverage instrumentation")
8989
super.run()
90-
println(s"[info] [scoverage]: Instrumentation completed [${coverage.statements.size} statements]")
90+
println(s"[info] Instrumentation completed [${coverage.statements.size} statements]")
9191

9292
IOUtils.serialize(coverage, IOUtils.coverageFile(options.dataDir))
93-
println(s"[info] [scoverage]: Wrote instrumentation file [${IOUtils.coverageFile(options.dataDir)}]")
94-
println(s"[info] [scoverage]: Writing measurements data to [${options.dataDir}]")
93+
println(s"[info] Wrote instrumentation file [${IOUtils.coverageFile(options.dataDir)}]")
94+
println(s"[info] Will write measurement data to [${options.dataDir}]")
9595
}
9696
}
9797

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package scoverage
2+
3+
import java.io.File
4+
5+
import org.scalatest.{FreeSpec, Matchers}
6+
7+
import scala.tools.nsc.Global
8+
import scala.tools.nsc.plugins.PluginComponent
9+
import scala.tools.nsc.transform.{Transform, TypingTransformers}
10+
11+
class LocationTest extends FreeSpec with Matchers {
12+
13+
val compiler = ScoverageCompiler.locationCompiler
14+
15+
"location function" - {
16+
"should ignore lambas" in {
17+
val loc = compiler.location("class Sammy")
18+
loc.get.className shouldBe ""
19+
}
20+
}
21+
}
22+
23+
class LocationCompiler(settings: scala.tools.nsc.Settings, reporter: scala.tools.nsc.reporters.Reporter)
24+
extends scala.tools.nsc.Global(settings, reporter) {
25+
26+
private var location: Option[Location] = None
27+
private val locationSetter = new LocationSetter(this)
28+
29+
def location(code: String): Option[Location] = {
30+
val files = writeCodeSnippetToTempFile(code)
31+
val command = new scala.tools.nsc.CompilerCommand(List(files.getAbsolutePath), settings)
32+
new Run().compile(command.files)
33+
location
34+
}
35+
36+
def writeCodeSnippetToTempFile(code: String): File = {
37+
val file = File.createTempFile("code_snippet", ".scala")
38+
org.apache.commons.io.FileUtils.write(file, code)
39+
file.deleteOnExit()
40+
file
41+
}
42+
43+
class LocationSetter(val global: Global) extends PluginComponent with TypingTransformers with Transform {
44+
45+
override val phaseName: String = "location-setter"
46+
override val runsAfter: List[String] = List("typer")
47+
override val runsBefore = List[String]("patmat")
48+
49+
override protected def newTransformer(unit: global.CompilationUnit): global.Transformer = new Transformer(unit)
50+
class Transformer(unit: global.CompilationUnit) extends TypingTransformer(unit) {
51+
52+
override def transform(tree: global.Tree) = {
53+
location = Location(global)(tree)
54+
tree
55+
}
56+
}
57+
}
58+
59+
override def computeInternalPhases() {
60+
val phs = List(
61+
syntaxAnalyzer -> "parse source into ASTs, perform simple desugaring",
62+
analyzer.namerFactory -> "resolve names, attach symbols to named trees",
63+
analyzer.packageObjects -> "load package objects",
64+
analyzer.typerFactory -> "the meat and potatoes: type the trees",
65+
locationSetter -> "sets locations",
66+
patmat -> "translate match expressions",
67+
superAccessors -> "add super accessors in traits and nested classes",
68+
extensionMethods -> "add extension methods for inline classes",
69+
pickler -> "serialize symbol tables",
70+
refChecks -> "reference/override checking, translate nested objects",
71+
uncurry -> "uncurry, translate function values to anonymous classes",
72+
tailCalls -> "replace tail calls by jumps",
73+
specializeTypes -> "@specialized-driven class and method specialization",
74+
explicitOuter -> "this refs to outer pointers, translate patterns",
75+
erasure -> "erase types, add interfaces for traits",
76+
postErasure -> "clean up erased inline classes",
77+
lazyVals -> "allocate bitmaps, translate lazy vals into lazified defs",
78+
lambdaLift -> "move nested functions to top level",
79+
constructors -> "move field definitions into constructors",
80+
mixer -> "mixin composition",
81+
cleanup -> "platform-specific cleanups, generate reflective calls",
82+
genicode -> "generate portable intermediate code",
83+
inliner -> "optimization: do inlining",
84+
inlineExceptionHandlers -> "optimization: inline exception handlers",
85+
closureElimination -> "optimization: eliminate uncalled closures",
86+
deadCode -> "optimization: eliminate dead code",
87+
terminal -> "The last phase in the compiler chain"
88+
)
89+
phs foreach (addToPhasesSet _).tupled
90+
}
91+
}

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

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,16 @@ class PluginASTSupportTest
88
extends FunSuite
99
with MockitoSugar
1010
with OneInstancePerTest
11-
with PluginSupport
1211
with BeforeAndAfterEachTestData {
1312

1413
override protected def afterEach(testData: TestData): Unit = {
15-
assert(!reporter.hasErrors)
14+
val compiler = ScoverageCompiler.default
15+
assert(!compiler.reporter.hasErrors)
1616
}
1717

1818
test("scoverage component should ignore basic macros") {
19-
compileCodeSnippet( """
19+
val compiler = ScoverageCompiler.default
20+
compiler.compileCodeSnippet( """
2021
| object MyMacro {
2122
| import scala.language.experimental.macros
2223
| import scala.reflect.macros.Context
@@ -28,11 +29,12 @@ class PluginASTSupportTest
2829
| }
2930
| }
3031
|} """.stripMargin)
31-
assert(!reporter.hasErrors)
32+
assert(!compiler.reporter.hasErrors)
3233
}
3334

3435
test("scoverage component should ignore complex macros #11") {
35-
compileCodeSnippet( """ object ComplexMacro {
36+
val compiler = ScoverageCompiler.default
37+
compiler.compileCodeSnippet( """ object ComplexMacro {
3638
|
3739
| import scala.language.experimental.macros
3840
| import scala.reflect.macros.Context
@@ -57,48 +59,51 @@ class PluginASTSupportTest
5759
| c.Expr[Unit](Block(treesWithSeparators.toList, Literal(Constant(()))))
5860
| }
5961
|} """.stripMargin)
60-
assert(!reporter.hasErrors)
62+
assert(!compiler.reporter.hasErrors)
6163
}
6264

6365

6466
// https://github.com/scoverage/scalac-scoverage-plugin/issues/32
6567
test("exhaustive warnings should not be generated for @unchecked") {
66-
compileCodeSnippet( """object PartialMatchObject {
68+
val compiler = ScoverageCompiler.default
69+
compiler.compileCodeSnippet( """object PartialMatchObject {
6770
| def partialMatchExample(s: Option[String]): Unit = {
6871
| (s: @unchecked) match {
6972
| case Some(str) => println(str)
7073
| }
7174
| }
7275
|} """.stripMargin)
73-
assert(!reporter.hasErrors)
74-
assert(!reporter.hasWarnings)
76+
assert(!compiler.reporter.hasErrors)
77+
assert(!compiler.reporter.hasWarnings)
7578
}
7679

7780
// https://github.com/skinny-framework/skinny-framework/issues/97
7881
test("macro range positions should not break plugin") {
79-
addToClassPath("org.slf4j", "slf4j-api", "1.7.7")
80-
addToClassPath("com.typesafe.scala-logging", "scala-logging-api_" + shortScalaVersion, "2.1.2")
81-
addToClassPath("com.typesafe.scala-logging", "scala-logging-slf4j_" + shortScalaVersion, "2.1.2")
82-
compileCodeSnippet( """import com.typesafe.scalalogging.slf4j.StrictLogging
82+
val compiler = ScoverageCompiler.default
83+
compiler.addToClassPath("org.slf4j", "slf4j-api", "1.7.7")
84+
compiler.addToClassPath("com.typesafe.scala-logging", "scala-logging-api_" + ScoverageCompiler.ShortScalaVersion, "2.1.2")
85+
compiler.addToClassPath("com.typesafe.scala-logging", "scala-logging-slf4j_" + ScoverageCompiler.ShortScalaVersion, "2.1.2")
86+
compiler.compileCodeSnippet( """import com.typesafe.scalalogging.slf4j.StrictLogging
8387
|
8488
|object MacroTest extends StrictLogging {
8589
| println("Hello")
8690
| logger.info("will break")
8791
|} """.stripMargin)
88-
assert(!reporter.hasErrors)
89-
assert(!reporter.hasWarnings)
92+
assert(!compiler.reporter.hasErrors)
93+
assert(!compiler.reporter.hasWarnings)
9094
}
9195

9296
// https://github.com/scoverage/scalac-scoverage-plugin/issues/45
9397
test("compile final vals in annotations") {
94-
compileCodeSnippet( """object Foo {
98+
val compiler = ScoverageCompiler.default
99+
compiler.compileCodeSnippet( """object Foo {
95100
| final val foo = 1L
96101
|}
97102
|@SerialVersionUID(value = Foo.foo)
98103
|class Bar
99104
|""".stripMargin)
100-
assert(!reporter.hasErrors)
101-
assert(!reporter.hasWarnings)
105+
assert(!compiler.reporter.hasErrors)
106+
assert(!compiler.reporter.hasWarnings)
102107
}
103108

104109
//test("type param with default arg supported") {

0 commit comments

Comments
 (0)