Skip to content
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
5 changes: 3 additions & 2 deletions jmf-rules.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# jacoco-method-filter — Default Rules & HowTo (Scala + Java)
# jacoco-method-filter — Default Rules & HowTo (Scala)
# [jmf:1.0.0]
#
# This file defines which methods should be annotated as *Generated so JaCoCo ignores them.
# One rule per line.
Expand Down Expand Up @@ -150,5 +151,5 @@
*#* synthetic name-contains:$anonfun$ id:scala-anonfun

# ─────────────────────────────────────────────────────────────────────────────
# DIRECT RULES
# PROJECT RULES
# ─────────────────────────────────────────────────────────────────────────────
83 changes: 61 additions & 22 deletions project/FilteredJacocoAgentPlugin.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// JacocoBaseKeysPlugin.scala | last modified in v1.0.0 + local changes

import JacocoBaseKeysPlugin.autoImport.*
import sbt.*
import sbt.Keys.*
import sbt.{ScopeFilter, inProjects as inP, *}

import scala.sys.process.*

/**
* JacocoAgentPlugin (no aggregation/merge)
Expand Down Expand Up @@ -70,6 +70,8 @@ object FilteredJacocoAgentPlugin extends AutoPlugin {
}
}

lazy val Jmf = config("jmf").extend(Compile)

// ---- commands
private lazy val jacocoCleanAllCmd = Command.command("jacocoCleanAll") { state =>
val targets = enabledUnder(state)
Expand All @@ -78,9 +80,25 @@ object FilteredJacocoAgentPlugin extends AutoPlugin {
}

private lazy val jacocoReportAllCmd = Command.command("jacocoReportAll") { state =>
val targets = enabledUnder(state)
if (targets.isEmpty) { println("[jacoco] nothing to report (no enabled modules under this aggregate)."); state }
else targets.foldLeft(state) { (st, ref) => Command.process(s"${ref.project}/jacocoReport", st) }
val e = Project.extract(state)
val current = e.currentRef
// your existing helper (enabled projects under current aggregate)
val under = enabledUnder(state)

// Also include current project if enabled
val selfEnabled =
e.getOpt(current / jacocoPluginEnabled).getOrElse(false)

val targets = (if (selfEnabled) current +: under else under).distinct

if (targets.isEmpty) {
println("[jacoco] nothing to report (no enabled modules here).");
state
} else {
targets.foldLeft(state) { (st, ref) =>
Command.process(s"${ref.project}/jacocoReport", st)
}
}
}

// ---- global defaults so keys exist everywhere (safe no-ops on projects without the plugin)
Expand Down Expand Up @@ -116,12 +134,12 @@ object FilteredJacocoAgentPlugin extends AutoPlugin {

// ---- coordinates
jacocoVersion := "0.8.12",
jmfCoreVersion := "0.1.7",
jmfCoreVersion := "1.0.0",
libraryDependencies ++= Seq(
// pull the agent with the runtime classifier (this is the actual -javaagent jar)
("org.jacoco" % "org.jacoco.agent" % jacocoVersion.value % Test).classifier("runtime"),
("org.jacoco" % "org.jacoco.cli" % jacocoVersion.value % Test).classifier("nodeps"),
"io.github.moranaapps" % "jacoco-method-filter-core_2.12" % jmfCoreVersion.value % Jmf.name,
"io.github.moranaapps" %% "jacoco-method-filter-core" % jmfCoreVersion.value % Jmf.name,
),
jacocoSetUserDirToBuildRoot := true,

Expand All @@ -138,7 +156,7 @@ object FilteredJacocoAgentPlugin extends AutoPlugin {
s"Report: $moduleId - scala:${scalaVersion.value}"
},

// --- JMF tool wiring
// --- JMF tool wiring
ivyConfigurations += Jmf,

jmfOutDir := target.value / "jmf",
Expand All @@ -149,15 +167,36 @@ object FilteredJacocoAgentPlugin extends AutoPlugin {

// the rewrite task (your code, lightly cleaned)
jmfRewrite := {
val log = streams.value.log
val enabled = jacocoPluginEnabled.value

// --- hoist all .value lookups BEFORE conditionals ---
// ensure classes exist (safe to always do; test would compile anyway)
val _ = (Compile / compile).value

val classesIn = (Compile / classDirectory).value
val rules = jmfRulesFile.value
val upd = (Jmf / update).value // hoisted
val log = streams.value.log
val outRoot = jmfOutDir.value
val mainCls = jmfCliMain.value
val dryRun = jmfDryRun.value
val workDir = baseDirectory.value
val classesIn = (Compile / classDirectory).value
val rulesFile = jmfRulesFile.value
val enabled = jacocoPluginEnabled.value

// Compile classpath (scala-stdlib, scopt, your module classes, etc.)
val compileCp: Seq[File] = Attributed.data((Compile / fullClasspath).value)

// Jmf-resolved jars (your jacoco-method-filter-core, etc.)
val jmfJars: Seq[File] = (Jmf / update).value.matching(artifactFilter(`type` = "jar")).distinct

// Final runtime CP
val cp: Seq[File] = (compileCp ++ jmfJars :+ (Compile / classDirectory).value).distinct
val cpStr = cp.distinct.map(_.getAbsolutePath).mkString(java.io.File.pathSeparator)

val javaBin = {
val h = sys.props.get("java.home").getOrElse("")
if (h.nonEmpty) new java.io.File(new java.io.File(h, "bin"), "java").getAbsolutePath else "java"
}
// ----------------------------------------------------

if (!enabled) classesIn
else if (!classesIn.exists) {
Expand All @@ -170,18 +209,17 @@ object FilteredJacocoAgentPlugin extends AutoPlugin {
val outDir = jmfOutDir.value / "classes-filtered"
IO.delete(outDir); IO.createDirectory(outDir)

val toolJars = upd.matching(artifactFilter(`type` = "jar")).distinct
log.info("[jmf] tool CP:\n" + toolJars.map(f => s" - ${f.getAbsolutePath}").mkString("\n"))
log.info("[jmf] runtime CP:\n" + cp.map(f => s" - ${f.getAbsolutePath}").mkString("\n"))

val cpStr = toolJars.mkString(java.io.File.pathSeparator)
val args = Seq("java","-cp", cpStr, jmfCliMain.value,
"--in", classesIn.getAbsolutePath,
"--out", outDir.getAbsolutePath,
"--rules", rules.getAbsolutePath) ++
(if (jmfDryRun.value) Seq("--dry-run") else Seq())
val args = Seq(
javaBin, "-cp", cpStr, jmfCliMain.value,
"--in", classesIn.getAbsolutePath,
"--out", outDir.getAbsolutePath,
"--rules", rules.getAbsolutePath
) ++ (if (jmfDryRun.value) Seq("--dry-run") else Seq())

log.info(s"[jmf] rewrite: ${args.mkString(" ")}")
val code = scala.sys.process.Process(args, baseDirectory.value).!
val code = scala.sys.process.Process(args, workDir).!
if (code != 0) sys.error(s"[jmf] rewriter failed ($code)")
outDir
}
Expand Down Expand Up @@ -333,3 +371,4 @@ object FilteredJacocoAgentPlugin extends AutoPlugin {
}
)
}

2 changes: 2 additions & 0 deletions project/JacocoBaseKeysPlugin.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// JacocoBaseKeysPlugin.scala | last modified in v1.0.0

import sbt._
import sbt.Keys._

Expand Down