Skip to content

Commit 206a784

Browse files
committed
Scala 3 support; Scoverage v2.0.7
1 parent 3021528 commit 206a784

7 files changed

+140
-60
lines changed

build.gradle

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ repositories {
1111
group 'org.scoverage'
1212
description = 'gradle-scoverage is a Gradle plugin for calculating code coverage using Scoverage'
1313
if (project.version == 'unspecified') {
14-
version = '7.0.0-SNAPSHOT'
14+
version = '8.0.0-SNAPSHOT'
1515
}
1616
ext {
1717
website = 'http://scoverage.org'
@@ -46,7 +46,8 @@ targetCompatibility = '1.8'
4646

4747

4848
dependencies {
49-
compileOnly "org.scoverage:scalac-scoverage-plugin_2.13:1.4.2"
49+
compileOnly "org.scoverage:scalac-scoverage-plugin_2.13.8:2.0.5"
50+
compileOnly "org.scoverage:scalac-scoverage-reporter_2.13:2.0.5"
5051
implementation group: 'commons-io', name: 'commons-io', version: '2.6'
5152

5253
testImplementation 'junit:junit:4.12'
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package org.scoverage
2+
3+
class ScalaVersion {
4+
final String primaryVersion
5+
final Optional<String> secondaryVersion
6+
final Integer majorVersion
7+
final String scalacScoverageVersion
8+
final String scalacScoveragePluginVersion
9+
final String scalacScoverageRuntimeVersion
10+
11+
ScalaVersion(primaryVersion) {
12+
this(primaryVersion, Optional.empty())
13+
}
14+
15+
ScalaVersion(String primaryVersion, Optional<String> secondaryVersion) {
16+
this.primaryVersion = primaryVersion
17+
this.secondaryVersion = secondaryVersion
18+
19+
this.majorVersion = primaryVersion.substring(0, primaryVersion.indexOf('.')).toInteger()
20+
this.scalacScoverageVersion = this.majorVersion < 3
21+
? primaryVersion.substring(0, primaryVersion.lastIndexOf('.'))
22+
: this.majorVersion.toString()
23+
this.scalacScoveragePluginVersion = secondaryVersion.orElse(primaryVersion)
24+
this.scalacScoverageRuntimeVersion = scalacScoveragePluginVersion.substring(0, scalacScoveragePluginVersion.lastIndexOf('.'))
25+
}
26+
27+
@Override
28+
String toString() {
29+
return majorVersion < 3 ? primaryVersion : "$primaryVersion (${secondaryVersion.get()})"
30+
}
31+
}

src/main/groovy/org/scoverage/ScoverageAggregate.groovy

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import org.gradle.api.tasks.Nested
1010
import org.gradle.api.tasks.OutputDirectory
1111
import org.gradle.api.tasks.PathSensitive
1212
import org.gradle.api.tasks.TaskAction
13-
import scoverage.report.CoverageAggregator
13+
import scoverage.reporter.CoverageAggregator
1414

1515
import static org.gradle.api.tasks.PathSensitivity.RELATIVE
1616

@@ -57,7 +57,8 @@ class ScoverageAggregate extends DefaultTask {
5757

5858
def dirs = []
5959
dirs.addAll(dirsToAggregateFrom.get())
60-
def coverage = CoverageAggregator.aggregate(dirs.unique() as File[])
60+
def sourceRoot = getProject().getRootDir()
61+
def coverage = CoverageAggregator.aggregate(dirs.unique() as File[], sourceRoot)
6162

6263
if (coverage.nonEmpty()) {
6364
new ScoverageWriter(project.logger).write(

src/main/groovy/org/scoverage/ScoverageExtension.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class ScoverageExtension {
5555
project.plugins.apply(ScalaPlugin.class)
5656

5757
scoverageVersion = project.objects.property(String)
58-
scoverageVersion.set('1.4.11')
58+
scoverageVersion.set('2.0.7')
5959

6060
scoverageScalaVersion = project.objects.property(String)
6161

src/main/groovy/org/scoverage/ScoveragePlugin.groovy

Lines changed: 74 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,12 @@ class ScoveragePlugin implements Plugin<PluginAware> {
5151
project.logger.info("Project ${project.name} already has the scoverage plugin")
5252
return
5353
}
54-
project.logger.info("Applying scoverage plugin to $project.name")
5554

55+
project.logger.info("Applying scoverage plugin to $project.name")
5656
def extension = project.extensions.create('scoverage', ScoverageExtension, project)
57+
58+
def scalaVersion = resolveScalaVersions(project)
59+
5760
if (!project.configurations.asMap[CONFIGURATION_NAME]) {
5861
project.configurations.create(CONFIGURATION_NAME) {
5962
visible = false
@@ -62,23 +65,27 @@ class ScoveragePlugin implements Plugin<PluginAware> {
6265
}
6366

6467
project.afterEvaluate {
65-
def scalaFullVersion = resolveScalaVersion(project)
66-
def scalaBinaryVersion = scalaFullVersion.substring(0, scalaFullVersion.lastIndexOf('.'))
6768
def scoverageVersion = project.extensions.scoverage.scoverageVersion.get()
69+
project.logger.info("Using scoverage scalac plugin $scoverageVersion for scala $scalaVersion")
6870

69-
project.logger.info("Using scoverage scalac plugin $scoverageVersion for scala $scalaFullVersion")
71+
def scalacScoverageVersion = scalaVersion.scalacScoverageVersion
72+
def scalacScoveragePluginVersion = scalaVersion.scalacScoveragePluginVersion
73+
def scalacScoverageRuntimeVersion = scalaVersion.scalacScoverageRuntimeVersion
7074

7175
project.dependencies {
72-
scoverage("org.scoverage:scalac-scoverage-plugin_$scalaFullVersion:$scoverageVersion")
73-
scoverage("org.scoverage:scalac-scoverage-runtime_$scalaBinaryVersion:$scoverageVersion")
76+
scoverage("org.scoverage:scalac-scoverage-domain_$scalacScoverageVersion:$scoverageVersion")
77+
scoverage("org.scoverage:scalac-scoverage-reporter_$scalacScoverageVersion:$scoverageVersion")
78+
scoverage("org.scoverage:scalac-scoverage-serializer_$scalacScoverageVersion:$scoverageVersion")
79+
scoverage("org.scoverage:scalac-scoverage-runtime_$scalacScoverageRuntimeVersion:$scoverageVersion")
80+
scoverage("org.scoverage:scalac-scoverage-plugin_$scalacScoveragePluginVersion:$scoverageVersion")
7481
}
7582
}
7683
}
7784

78-
createTasks(project, extension)
85+
createTasks(project, extension, scalaVersion)
7986
}
8087

81-
private void createTasks(Project project, ScoverageExtension extension) {
88+
private void createTasks(Project project, ScoverageExtension extension, ScalaVersion scalaVersion) {
8289

8390
ScoverageRunner scoverageRunner = new ScoverageRunner(project.configurations.scoverage)
8491

@@ -162,32 +169,43 @@ class ScoveragePlugin implements Plugin<PluginAware> {
162169
if (existingParameters) {
163170
parameters.addAll(existingParameters)
164171
}
165-
parameters.add("-P:scoverage:dataDir:${extension.dataDir.get().absolutePath}".toString())
166-
if (extension.excludedPackages.get()) {
167-
def packages = extension.excludedPackages.get().join(';')
168-
parameters.add("-P:scoverage:excludedPackages:$packages".toString())
169-
}
170-
if (extension.excludedFiles.get()) {
171-
def packages = extension.excludedFiles.get().join(';')
172-
parameters.add("-P:scoverage:excludedFiles:$packages".toString())
173-
}
174-
if (extension.highlighting.get()) {
175-
parameters.add('-Yrangepos')
176-
}
177-
scalaCompileOptions.additionalParameters = parameters
178-
// the compile task creates a store of measured statements
179-
outputs.file(new File(extension.dataDir.get(), 'scoverage.coverage'))
180-
181-
dependsOn project.configurations[CONFIGURATION_NAME]
182-
doFirst {
183-
/*
184-
It is crucial that this would run in `doFirst`, as this resolves the (dependencies of the)
185-
configuration, which we do not want to do at configuration time (but only at execution time).
186-
*/
187-
def pluginFile = project.configurations[CONFIGURATION_NAME].find {
188-
it.name.startsWith("scalac-scoverage-plugin")
172+
173+
if (scalaVersion.majorVersion < 3) {
174+
parameters.add("-P:scoverage:dataDir:${extension.dataDir.get().absolutePath}".toString())
175+
parameters.add("-P:scoverage:sourceRoot:${extension.project.getRootDir().absolutePath}".toString())
176+
if (extension.excludedPackages.get()) {
177+
def packages = extension.excludedPackages.get().join(';')
178+
parameters.add("-P:scoverage:excludedPackages:$packages".toString())
179+
}
180+
if (extension.excludedFiles.get()) {
181+
def packages = extension.excludedFiles.get().join(';')
182+
parameters.add("-P:scoverage:excludedFiles:$packages".toString())
183+
}
184+
if (extension.highlighting.get()) {
185+
parameters.add('-Yrangepos')
186+
}
187+
scalaCompileOptions.additionalParameters = parameters
188+
// the compile task creates a store of measured statements
189+
outputs.file(new File(extension.dataDir.get(), 'scoverage.coverage'))
190+
191+
dependsOn project.configurations[CONFIGURATION_NAME]
192+
doFirst {
193+
/*
194+
It is crucial that this would run in `doFirst`, as this resolves the (dependencies of the)
195+
configuration, which we do not want to do at configuration time (but only at execution time).
196+
*/
197+
def pluginFiles = project.configurations[CONFIGURATION_NAME].findAll {
198+
it.name.startsWith("scalac-scoverage-plugin") ||
199+
it.name.startsWith("scalac-scoverage-domain") ||
200+
it.name.startsWith("scalac-scoverage-serializer")
201+
}.collect {
202+
it.absolutePath
203+
}
204+
scalaCompileOptions.additionalParameters.add('-Xplugin:' + pluginFiles.join(":"))
189205
}
190-
scalaCompileOptions.additionalParameters.add('-Xplugin:' + pluginFile.absolutePath)
206+
} else {
207+
parameters.add("-coverage-out:${extension.dataDir.get().absolutePath}".toString())
208+
scalaCompileOptions.additionalParameters = parameters
191209
}
192210
}
193211

@@ -364,27 +382,41 @@ class ScoveragePlugin implements Plugin<PluginAware> {
364382
}
365383
}
366384

367-
private String resolveScalaVersion(Project project) {
368-
385+
private ScalaVersion resolveScalaVersions(Project project) {
369386
def scalaVersionProperty = project.extensions.scoverage.scoverageScalaVersion
370387
if (scalaVersionProperty.isPresent()) {
371388
def configuredScalaVersion = scalaVersionProperty.get()
372389
project.logger.info("Using configured Scala version: $configuredScalaVersion")
373-
return configuredScalaVersion
390+
return new ScalaVersion(configuredScalaVersion)
374391
} else {
375392
project.logger.info("No Scala version configured. Detecting scala library...")
376393
def components = project.configurations.compileClasspath.incoming.resolutionResult.getAllComponents()
394+
395+
def scala3Library = components.find {
396+
it.moduleVersion.group == "org.scala-lang" && it.moduleVersion.name == "scala3-library_3"
397+
}
377398
def scalaLibrary = components.find {
378399
it.moduleVersion.group == "org.scala-lang" && it.moduleVersion.name == "scala-library"
379400
}
401+
402+
// Scala 3
403+
if (scala3Library != null) {
404+
def scala3Version = scala3Library.moduleVersion.version
405+
def scala2Version = scalaLibrary.moduleVersion.version
406+
project.logger.info("Detected scala 3 library in compilation classpath. Scala 3 version: $scala3Version; using Scala 2 library: $scala2Version")
407+
return new ScalaVersion(scala3Version, Optional.of(scala2Version))
408+
}
409+
410+
// Scala 2
380411
if (scalaLibrary != null) {
381-
def scalaVersion = scalaLibrary.moduleVersion.version
382-
project.logger.info("Detected scala library in compilation classpath. Scala version: $scalaVersion")
383-
return scalaVersion
384-
} else {
385-
project.logger.info("No scala library detected. Using default Scala version: $DEFAULT_SCALA_VERSION")
386-
return DEFAULT_SCALA_VERSION
412+
def scala2Version = scalaLibrary.moduleVersion.version
413+
project.logger.info("Detected scala library in compilation classpath. Scala version: $scala2Version")
414+
return new ScalaVersion(scala2Version)
387415
}
416+
417+
// No Scala library was found, using default Scala version
418+
project.logger.info("No scala library detected. Using default Scala version: $DEFAULT_SCALA_VERSION")
419+
return new ScalaVersion(DEFAULT_SCALA_VERSION)
388420
}
389421
}
390422

src/main/groovy/org/scoverage/ScoverageReport.groovy

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import org.gradle.api.tasks.Nested
1111
import org.gradle.api.tasks.OutputDirectory
1212
import org.gradle.api.tasks.PathSensitive
1313
import org.gradle.api.tasks.TaskAction
14-
import scoverage.report.CoverageAggregator
14+
import scoverage.reporter.CoverageAggregator
1515

1616
import static org.gradle.api.tasks.PathSensitivity.RELATIVE
1717

@@ -50,7 +50,8 @@ class ScoverageReport extends DefaultTask {
5050
reportDir.get().delete()
5151
reportDir.get().mkdirs()
5252

53-
def coverage = CoverageAggregator.aggregate([dataDir.get()] as File[])
53+
def sourceRoot = getProject().getRootDir()
54+
def coverage = CoverageAggregator.aggregate([dataDir.get()] as File[], sourceRoot)
5455

5556
if (coverage.isEmpty()) {
5657
project.logger.info("[scoverage] Could not find coverage file, skipping...")

src/main/groovy/org/scoverage/ScoverageWriter.java

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
import scala.Some;
66
import scala.collection.immutable.Seq;
77
import scala.collection.mutable.Buffer;
8-
import scoverage.Constants;
9-
import scoverage.Coverage;
10-
import scoverage.report.CoberturaXmlWriter;
11-
import scoverage.report.ScoverageHtmlWriter;
12-
import scoverage.report.ScoverageXmlWriter;
8+
import scoverage.domain.Constants;
9+
import scoverage.domain.Coverage;
10+
import scoverage.reporter.CoberturaXmlWriter;
11+
import scoverage.reporter.ScoverageHtmlWriter;
12+
import scoverage.reporter.ScoverageXmlWriter;
1313
import scala.collection.JavaConverters;
1414

1515
import java.io.File;
@@ -65,11 +65,17 @@ public void write(Set<File> sourceDirs,
6565
if (coverageOutputCobertura) {
6666
Constructor<CoberturaXmlWriter> cst;
6767
try {
68-
cst = CoberturaXmlWriter.class.getConstructor(Class.forName("scala.collection.immutable.Seq"), File.class);
68+
cst = CoberturaXmlWriter.class.getConstructor(
69+
Class.forName("scala.collection.immutable.Seq"),
70+
File.class,
71+
Class.forName("scala.Option"));
6972
} catch (NoSuchMethodException | ClassNotFoundException e) {
70-
cst = CoberturaXmlWriter.class.getConstructor(Class.forName("scala.collection.Seq"), File.class);
73+
cst = CoberturaXmlWriter.class.getConstructor(
74+
Class.forName("scala.collection.Seq"),
75+
File.class,
76+
Class.forName("scala.Option"));
7177
}
72-
CoberturaXmlWriter writer = cst.newInstance(sourceDirsSeq, reportDir);
78+
CoberturaXmlWriter writer = cst.newInstance(sourceDirsSeq, reportDir, new Some<>(sourceEncoding));
7379
writer.write(coverage);
7480
logger.info("[scoverage] Written Cobertura XML report to " +
7581
reportDir.getAbsolutePath() +
@@ -80,11 +86,19 @@ public void write(Set<File> sourceDirs,
8086
if (coverageOutputXML) {
8187
Constructor<ScoverageXmlWriter> cst;
8288
try {
83-
cst = ScoverageXmlWriter.class.getConstructor(Class.forName("scala.collection.immutable.Seq"), File.class, boolean.class);
89+
cst = ScoverageXmlWriter.class.getConstructor(
90+
Class.forName("scala.collection.immutable.Seq"),
91+
File.class,
92+
boolean.class,
93+
Class.forName("scala.Option"));
8494
} catch (NoSuchMethodException | ClassNotFoundException e) {
85-
cst = ScoverageXmlWriter.class.getConstructor(Class.forName("scala.collection.Seq"), File.class, boolean.class);
95+
cst = ScoverageXmlWriter.class.getConstructor(
96+
Class.forName("scala.collection.Seq"),
97+
File.class,
98+
boolean.class,
99+
Class.forName("scala.Option"));
86100
}
87-
ScoverageXmlWriter writer = cst.newInstance(sourceDirsSeq, reportDir, false);
101+
ScoverageXmlWriter writer = cst.newInstance(sourceDirsSeq, reportDir, false, new Some<>(sourceEncoding));
88102
writer.write(coverage);
89103
logger.info("[scoverage] Written XML report to " +
90104
reportDir.getAbsolutePath() +

0 commit comments

Comments
 (0)