0
# Compiler Plugin
1
2
The Scalac Scoverage Plugin is a Scala compiler plugin that instruments source code during compilation to enable coverage measurement. It adds instrumentation calls to statements and branches, allowing runtime collection of coverage data during test execution.
3
4
## Capabilities
5
6
### Main Plugin Class
7
8
The core compiler plugin that integrates with the Scala compiler.
9
10
```scala { .api }
11
/**
12
* Main Scoverage compiler plugin class
13
* @param global The Scala compiler's Global object
14
*/
15
class ScoveragePlugin(val global: Global) extends Plugin {
16
/** Plugin name identifier */
17
val name: String
18
19
/** Human-readable plugin description */
20
val description: String
21
22
/** List of plugin components that perform the instrumentation */
23
val components: List[PluginComponent]
24
25
/** Initialize plugin with command-line options */
26
def init(opts: List[String], error: String => Unit): Boolean
27
28
/** Help text for plugin options */
29
val optionsHelp: Option[String]
30
}
31
```
32
33
### Plugin Configuration
34
35
Configuration options for controlling plugin behavior.
36
37
```scala { .api }
38
/**
39
* Configuration options for the Scoverage plugin
40
* @param excludedPackages Regex patterns for packages to exclude from instrumentation
41
* @param excludedFiles Regex patterns for files to exclude from instrumentation
42
* @param excludedSymbols Regex patterns for symbols to exclude from instrumentation
43
* @param dataDir Directory where coverage data files are written
44
* @param reportTestName Whether to include test names in coverage reports
45
* @param sourceRoot Root directory for source files
46
*/
47
case class ScoverageOptions(
48
excludedPackages: Seq[String],
49
excludedFiles: Seq[String],
50
excludedSymbols: Seq[String],
51
dataDir: String,
52
reportTestName: Boolean,
53
sourceRoot: String
54
)
55
56
object ScoverageOptions {
57
/** Create default options */
58
def default(): ScoverageOptions
59
60
/** Parse command-line options into ScoverageOptions */
61
def parse(scalacOptions: List[String], errFn: String => Unit, base: ScoverageOptions): ScoverageOptions
62
63
/** Process phase options for before/after phase configuration */
64
def processPhaseOptions(opts: List[String]): (Option[String], Option[String])
65
66
/** Help text for all available options */
67
val help: Option[String]
68
}
69
```
70
71
**Usage Examples:**
72
73
```scala
74
import scoverage.ScoverageOptions
75
76
// Create custom configuration
77
val options = ScoverageOptions(
78
excludedPackages = Seq(".*\\.test\\..*", ".*\\.generated\\..*"),
79
excludedFiles = Seq(".*DatabaseMigrations.*"),
80
excludedSymbols = Seq(".*Logger.*"),
81
dataDir = "target/scoverage-data",
82
reportTestName = true,
83
sourceRoot = "src/main/scala"
84
)
85
86
// Parse from compiler options
87
val opts = List(
88
"-P:scoverage:dataDir:target/scoverage-data",
89
"-P:scoverage:excludedPackages:.*\\.test\\..*",
90
"-P:scoverage:reportTestName:true"
91
)
92
val parsed = ScoverageOptions.parse(opts, println, ScoverageOptions.default())
93
```
94
95
### Coverage Filtering
96
97
Control which code gets instrumented for coverage measurement.
98
99
```scala { .api }
100
/**
101
* Base trait for filtering what code should be included in coverage
102
*/
103
trait CoverageFilter {
104
/** Check if a class should be included in coverage */
105
def isClassIncluded(className: String): Boolean
106
107
/** Check if a source file should be included in coverage */
108
def isFileIncluded(file: SourceFile): Boolean
109
110
/** Check if a specific line position should be included */
111
def isLineIncluded(position: Position): Boolean
112
113
/** Check if a symbol should be included in coverage */
114
def isSymbolIncluded(symbolName: String): Boolean
115
116
/** Get line number ranges that are excluded from coverage */
117
def getExcludedLineNumbers(sourceFile: SourceFile): List[Range]
118
}
119
120
/**
121
* Filter that includes all code (no exclusions)
122
*/
123
object AllCoverageFilter extends CoverageFilter
124
125
/**
126
* Regex-based filter for excluding code from coverage
127
* @param excludedPackages Regex patterns for package exclusion
128
* @param excludedFiles Regex patterns for file exclusion
129
* @param excludedSymbols Regex patterns for symbol exclusion
130
* @param reporter Compiler reporter for error handling
131
*/
132
class RegexCoverageFilter(
133
excludedPackages: Seq[String],
134
excludedFiles: Seq[String],
135
excludedSymbols: Seq[String],
136
reporter: Reporter
137
) extends CoverageFilter
138
```
139
140
**Usage Examples:**
141
142
```scala
143
import scoverage.{RegexCoverageFilter, AllCoverageFilter}
144
145
// Create filter with exclusions
146
val filter = new RegexCoverageFilter(
147
excludedPackages = Seq(".*\\.test\\..*", ".*\\.generated\\..*"),
148
excludedFiles = Seq(".*Migration.*\\.scala"),
149
excludedSymbols = Seq(".*Logger.*", ".*Debug.*"),
150
reporter = global.reporter
151
)
152
153
// Check if class should be covered
154
val shouldCover = filter.isClassIncluded("com.example.service.UserService")
155
156
// Use no-exclusion filter
157
val allFilter = AllCoverageFilter
158
```
159
160
### Instrumentation Component
161
162
The component that performs the actual code instrumentation.
163
164
```scala { .api }
165
/**
166
* Compiler plugin component that performs code instrumentation
167
* @param global The Scala compiler's Global object
168
* @param extraAfterPhase Optional phase to run after
169
* @param extraBeforePhase Optional phase to run before
170
*/
171
class ScoverageInstrumentationComponent(
172
val global: Global,
173
extraAfterPhase: Option[String],
174
extraBeforePhase: Option[String]
175
) extends PluginComponent with TypingTransformers with Transform {
176
177
/** Phase name for the instrumentation */
178
val phaseName: String
179
180
/** Phases this component must run after */
181
val runsAfter: List[String]
182
183
/** Phases this component must run before */
184
val runsBefore: List[String]
185
186
/** Configure options for this component */
187
def setOptions(options: ScoverageOptions): Unit
188
189
/** Create new phase instance */
190
def newPhase(prev: scala.tools.nsc.Phase): Phase
191
}
192
```
193
194
### Location Utilities
195
196
Utilities for extracting location information from compiler AST nodes.
197
198
```scala { .api }
199
/**
200
* Utilities for extracting location information from compiler trees
201
*/
202
object Location {
203
/**
204
* Create location extractor function for a specific compiler instance
205
* @param global The compiler's Global object
206
* @returns Function to extract Location from compiler Tree nodes
207
*/
208
def fromGlobal(global: Global): global.Tree => Option[scoverage.domain.Location]
209
}
210
```
211
212
## Compiler Plugin Usage
213
214
### Command Line Options
215
216
The plugin accepts several command-line options via the `-P:scoverage:` prefix:
217
218
- `-P:scoverage:dataDir:<path>` - Directory for coverage data files
219
- `-P:scoverage:excludedPackages:<regex>` - Semicolon-separated regexes for package exclusion
220
- `-P:scoverage:excludedFiles:<regex>` - Semicolon-separated regexes for file exclusion
221
- `-P:scoverage:excludedSymbols:<regex>` - Semicolon-separated regexes for symbol exclusion
222
- `-P:scoverage:reportTestName:<boolean>` - Include test names in coverage data
223
- `-P:scoverage:sourceRoot:<path>` - Root directory for source files
224
225
### SBT Integration
226
227
```scala
228
// project/plugins.sbt
229
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.3.0")
230
231
// build.sbt
232
scoverageExcludedPackages := ".*\\.test\\..*;.*\\.generated\\..*"
233
scoverageExcludedFiles := ".*DatabaseMigrations.*"
234
scoverageMinimumCoverage := 80.0
235
scoverageFailOnMinimumCoverage := true
236
```
237
238
### Manual Configuration
239
240
```scala
241
// Add to scalacOptions
242
scalacOptions ++= Seq(
243
"-Xplugin:/path/to/scalac-scoverage-plugin.jar",
244
"-P:scoverage:dataDir:target/scoverage-data",
245
"-P:scoverage:excludedPackages:.*\\.test\\..*;.*\\.generated\\..*",
246
"-P:scoverage:reportTestName:true",
247
"-P:scoverage:sourceRoot:src/main/scala"
248
)
249
```
250
251
### Exclusion Comments
252
253
Code can be excluded from coverage using special comments:
254
255
```scala
256
// $COVERAGE-OFF$
257
def debugOnlyMethod(): Unit = {
258
println("This won't be covered")
259
}
260
// $COVERAGE-ON$
261
262
def normalMethod(): Unit = {
263
// This will be covered normally
264
println("Normal method")
265
}
266
```
267
268
## Error Handling
269
270
- **PluginInitException**: Thrown when plugin fails to initialize with provided options
271
- **InstrumentationException**: Thrown when code instrumentation fails due to unsupported constructs
272
- **ConfigurationException**: Thrown when invalid configuration options are provided
273
- **FileSystemException**: Thrown when unable to create coverage data directory or write coverage files