Skip to content

Use SBT settings to control scoverage #182

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 1 commit into from Sep 27, 2016
Merged
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
115 changes: 53 additions & 62 deletions src/main/scala/scoverage/ScoverageSbtPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,8 @@ object ScoverageSbtPlugin extends AutoPlugin {
override def requires: JvmPlugin.type = plugins.JvmPlugin
override def trigger: PluginTrigger = allRequirements

override lazy val projectSettings = Seq(
override def globalSettings: Seq[Def.Setting[_]] = super.globalSettings ++ Seq(
coverageEnabled := false,
commands += Command.command("coverage", "enable compiled code with instrumentation", "")(toggleCoverage(true)),
commands += Command.command("coverageOff", "disable compiled code with instrumentation", "")(toggleCoverage(false)),
coverageReport <<= coverageReport0,
coverageAggregate <<= coverageAggregate0,
ivyConfigurations := ivyConfigurations.value :+ ScoveragePluginConfig,
coverageScalacPluginVersion := DefaultScoverageVersion,
libraryDependencies ++= {
if (coverageEnabled.value) Seq(
OrgScoverage %% (ScalacRuntimeArtifact + optionalScalaJsSuffix(libraryDependencies.value)) % coverageScalacPluginVersion.value,
OrgScoverage %% ScalacPluginArtifact % coverageScalacPluginVersion.value % ScoveragePluginConfig.name
) else Nil
},
scalacOptions in(Compile, compile) ++= scoverageScalacOptions.value,
aggregate in coverageAggregate := false,
coverageExcludedPackages := "",
coverageExcludedFiles := "",
coverageMinimum := 0, // default is no minimum
Expand All @@ -49,22 +35,60 @@ object ScoverageSbtPlugin extends AutoPlugin {
coverageOutputCobertura := true,
coverageOutputDebug := false,
coverageCleanSubprojectFiles := true,
coverageOutputTeamCity := false
coverageOutputTeamCity := false,
coverageScalacPluginVersion := DefaultScoverageVersion
)

override def buildSettings: Seq[Setting[_]] = super.buildSettings ++
addCommandAlias("coverage", ";set coverageEnabled in ThisBuild := true") ++
addCommandAlias("coverageOn", ";set coverageEnabled in ThisBuild := true") ++
addCommandAlias("coverageOff", ";set coverageEnabled in ThisBuild := false")

override def projectSettings: Seq[Setting[_]] = Seq(
ivyConfigurations += ScoveragePluginConfig,
coverageReport <<= coverageReport0,
coverageAggregate <<= coverageAggregate0
) ++ coverageSettings ++ scalacSettings

private lazy val coverageSettings = Seq(
libraryDependencies ++= {
if (coverageEnabled.value)
Seq(
// We only add for "compile"" because of macros. This setting could be optimed to just "test" if the handling
// of macro coverage was improved.
OrgScoverage %% (scalacRuntime(libraryDependencies.value)) % coverageScalacPluginVersion.value,
// We don't want to instrument the test code itself, nor add to a pom when published with coverage enabled.
OrgScoverage %% ScalacPluginArtifact % coverageScalacPluginVersion.value % ScoveragePluginConfig.name
)
else
Nil
}
)

private lazy val scalacSettings = Seq(
scalacOptions in(Compile, compile) ++= {
if (coverageEnabled.value) {
val scoverageDeps: Seq[File] = update.value matching configurationFilter(ScoveragePluginConfig.name)
val pluginPath: File = scoverageDeps.find(_.getAbsolutePath.contains(ScalacPluginArtifact)) match {
case None => throw new Exception(s"Fatal: $ScalacPluginArtifact not in libraryDependencies")
case Some(pluginPath) => pluginPath
}
Seq(
Some(s"-Xplugin:${pluginPath.getAbsolutePath}"),
Some(s"-P:scoverage:dataDir:${crossTarget.value.getAbsolutePath}/scoverage-data"),
Option(coverageExcludedPackages.value.trim).filter(_.nonEmpty).map(v => s"-P:scoverage:excludedPackages:$v"),
Option(coverageExcludedFiles.value.trim).filter(_.nonEmpty).map(v => s"-P:scoverage:excludedFiles:$v"),
// rangepos is broken in some releases of scala so option to turn it off
if (coverageHighlighting.value) Some("-Yrangepos") else None
).flatten
} else {
Nil
}
}
)

/**
* The "coverage" command enables or disables instrumentation for all projects
* in the build.
*/
private def toggleCoverage(status: Boolean): State => State = { state =>
val extracted = Project.extract(state)
val currentProjRef = extracted.currentRef
val newSettings = extracted.structure.allProjectRefs.flatMap(proj =>
Seq(coverageEnabled in proj := status)
)
val appendSettings = Load.transformSettings(Load.projectScope(currentProjRef), currentProjRef.build, extracted.rootProject, newSettings)
val newSessionSettings = extracted.session.appendRaw(appendSettings)
SessionSettings.reapply(newSessionSettings, state)
private def scalacRuntime(deps: Seq[ModuleID]): String = {
ScalacRuntimeArtifact + optionalScalaJsSuffix(deps)
}

// returns "_sjs$sjsVersion" for Scala.js projects or "" otherwise
Expand Down Expand Up @@ -130,39 +154,6 @@ object ScoverageSbtPlugin extends AutoPlugin {
}
}

private lazy val scoverageScalacOptions = Def.task {
update.value
.matching(configurationFilter(ScoveragePluginConfig.name))
.find(_.getAbsolutePath.contains(ScalacPluginArtifact))
.fold[Seq[String]](Nil)(pluginPath =>
scalaArgs(coverageEnabled.value,
pluginPath,
crossTarget.value,
coverageExcludedPackages.value,
coverageExcludedFiles.value,
coverageHighlighting.value))
}

private def scalaArgs(coverageEnabled: Boolean,
pluginPath: File,
target: File,
excludedPackages: String,
excludedFiles: String,
coverageHighlighting: Boolean) = {
if (coverageEnabled) {
Seq(
Some(s"-Xplugin:${pluginPath.getAbsolutePath}"),
Some(s"-P:scoverage:dataDir:${target.getAbsolutePath}/scoverage-data"),
Option(excludedPackages.trim).filter(_.nonEmpty).map(v => s"-P:scoverage:excludedPackages:$v"),
Option(excludedFiles.trim).filter(_.nonEmpty).map(v => s"-P:scoverage:excludedFiles:$v"),
// rangepos is broken in some releases of scala so option to turn it off
if (coverageHighlighting) Some("-Yrangepos") else None
).flatten
} else {
Nil
}
}

private def writeReports(crossTarget: File,
compileSourceDirectories: Seq[File],
coverage: Coverage,
Expand Down