Skip to content

Commit c1f2022

Browse files
committed
Port coverage filter options
- Add `-coverage-exclude-packages` option that excludes packages and classes from generating coverage - Add `-coverage-exclude-files` option that excludes files from generating coverage
1 parent 7f410aa commit c1f2022

File tree

2 files changed

+27
-2
lines changed

2 files changed

+27
-2
lines changed

compiler/src/dotty/tools/dotc/config/ScalaSettings.scala

+2
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ trait CommonScalaSettings:
127127

128128
/* Coverage settings */
129129
val coverageOutputDir = PathSetting("-coverage-out", "Destination for coverage classfiles and instrumentation data.", "", aliases = List("--coverage-out"))
130+
val coverageExcludePackages: Setting[List[String]] = MultiStringSetting("-coverage-exclude-packages", "packages", "Semicolon separated list of regexes for packages to exclude from coverage.", aliases = List("--coverage-exclude-packages"))
131+
val coverageExcludeFiles: Setting[List[String]] = MultiStringSetting("-coverage-exclude-files", "files", "Semicolon separated list of regexes for files to exclude from coverage.", aliases = List("--coverage-exclude-files"))
130132

131133
/* Other settings */
132134
val encoding: Setting[String] = StringSetting("-encoding", "encoding", "Specify character encoding used by source files.", Properties.sourceEncoding, aliases = List("--encoding"))

compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala

+25-2
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@ import core.Constants.Constant
1313
import core.NameOps.isContextFunction
1414
import core.StdNames.nme
1515
import core.Types.*
16+
import core.Decorators.*
1617
import coverage.*
1718
import typer.LiftCoverage
1819
import util.{SourcePosition, SourceFile}
1920
import util.Spans.Span
2021
import localopt.StringInterpolatorOpt
2122
import inlines.Inlines
23+
import scala.util.matching.Regex
2224

2325
/** Implements code coverage by inserting calls to scala.runtime.coverage.Invoker
2426
* ("instruments" the source code).
@@ -58,6 +60,18 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
5860

5961
Serializer.serialize(coverage, outputPath, ctx.settings.sourceroot.value)
6062

63+
private def isClassIncluded(sym: Symbol)(using Context): Boolean =
64+
val excludedClassNamePatterns = ctx.settings.coverageExcludePackages.value.map(_.r.pattern)
65+
excludedClassNamePatterns.isEmpty || !excludedClassNamePatterns.exists(
66+
_.matcher(sym.fullName.toText(ctx.printerFn(ctx)).show).nn.matches
67+
)
68+
69+
private def isFileIncluded(file: SourceFile)(using Context): Boolean =
70+
val excludedFilePatterns = ctx.settings.coverageExcludeFiles.value.map(_.r.pattern)
71+
excludedFilePatterns.isEmpty || !excludedFilePatterns.exists(
72+
_.matcher(file.path.replace(".scala", "")).nn.matches
73+
)
74+
6175
override protected def newTransformer(using Context) =
6276
CoverageTransformer(ctx.settings.coverageOutputDir.value)
6377

@@ -269,8 +283,17 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
269283
transformDefDef(tree)
270284

271285
case tree: PackageDef =>
272-
// only transform the statements of the package
273-
cpy.PackageDef(tree)(tree.pid, transform(tree.stats))
286+
if (isFileIncluded(tree.srcPos.sourcePos.source) && isClassIncluded(tree.symbol))
287+
// only transform the statements of the package
288+
cpy.PackageDef(tree)(tree.pid, transform(tree.stats))
289+
else
290+
tree
291+
292+
case tree: TypeDef =>
293+
if (isFileIncluded(tree.srcPos.sourcePos.source) && isClassIncluded(tree.symbol))
294+
super.transform(tree)
295+
else
296+
tree
274297

275298
case tree: Assign =>
276299
// only transform the rhs

0 commit comments

Comments
 (0)