0
# Core Library
1
2
The core library contains the fundamental classes that power solidity-coverage's instrumentation, data collection, and reporting capabilities. These classes work together to provide comprehensive coverage analysis for Solidity smart contracts.
3
4
## Capabilities
5
6
### Instrumenter
7
8
The core instrumentation engine that modifies Solidity source code to inject coverage tracking calls.
9
10
```javascript { .api }
11
/**
12
* Main instrumentation class that modifies Solidity source code
13
* Injects coverage tracking calls while preserving code functionality
14
*/
15
const Instrumenter = require('solidity-coverage/lib/instrumenter');
16
17
class Instrumenter {
18
/**
19
* Creates a new instrumenter instance
20
* @param config - Configuration options for instrumentation behavior
21
*/
22
constructor(config?: {
23
viaIR?: boolean; // Enable Solidity viaIR compilation mode
24
modifierWhitelist?: string[]; // Specific modifiers to measure
25
measureStatementCoverage?: boolean; // Enable statement coverage measurement
26
measureFunctionCoverage?: boolean; // Enable function coverage measurement
27
measureModifierCoverage?: boolean; // Enable modifier coverage measurement
28
measureBranchCoverage?: boolean; // Enable branch coverage measurement
29
measureLineCoverage?: boolean; // Enable line coverage measurement
30
});
31
32
/**
33
* Instruments Solidity source code for coverage tracking
34
* @param source - Solidity source code to instrument
35
* @param canonicalPath - Absolute path to the source file
36
* @returns Instrumentation result with modified source and mapping data
37
*/
38
instrument(source: string, canonicalPath: string): InstrumentationResult;
39
}
40
41
interface InstrumentationResult {
42
contract: string; // Instrumented Solidity source code
43
runnableLines: number[]; // Array of line numbers that can be executed
44
fnMap: object; // Function mapping data for coverage
45
branchMap: object; // Branch mapping data for coverage
46
statementMap: object; // Statement mapping data for coverage
47
}
48
```
49
50
**Usage Examples:**
51
52
```javascript
53
const Instrumenter = require('solidity-coverage/lib/instrumenter');
54
55
// Create instrumenter with custom configuration
56
const instrumenter = new Instrumenter({
57
measureStatementCoverage: true,
58
measureFunctionCoverage: true,
59
measureBranchCoverage: true,
60
viaIR: false
61
});
62
63
// Instrument contract source
64
const source = `
65
contract Token {
66
uint256 public totalSupply;
67
68
function transfer(address to, uint256 amount) public returns (bool) {
69
if (balances[msg.sender] >= amount) {
70
balances[msg.sender] -= amount;
71
balances[to] += amount;
72
return true;
73
}
74
return false;
75
}
76
}`;
77
78
const result = instrumenter.instrument(source, '/contracts/Token.sol');
79
console.log('Instrumented contract:', result.contract);
80
console.log('Runnable lines:', result.runnableLines);
81
```
82
83
### Coverage
84
85
Manages coverage data collection and generates Istanbul-compatible coverage reports.
86
87
```javascript { .api }
88
/**
89
* Coverage data management and report generation class
90
* Converts execution data into standardized coverage reports
91
*/
92
const Coverage = require('solidity-coverage/lib/coverage');
93
94
class Coverage {
95
/**
96
* Creates a new coverage instance
97
*/
98
constructor();
99
100
/**
101
* Adds contract instrumentation data to coverage tracking
102
* @param info - Instrumentation data from Instrumenter.instrument()
103
* @param contractPath - Canonical path to the contract file
104
*/
105
addContract(info: InstrumentationResult, contractPath: string): void;
106
107
/**
108
* Generates final coverage data from collected execution traces
109
* @param instrumentationData - Hit data collected during test execution
110
*/
111
generate(instrumentationData: object): void;
112
}
113
```
114
115
**Usage Examples:**
116
117
```javascript
118
const Coverage = require('solidity-coverage/lib/coverage');
119
120
// Create coverage instance
121
const coverage = new Coverage();
122
123
// Add instrumented contract data
124
coverage.addContract(instrumentationResult, '/contracts/Token.sol');
125
126
// Generate coverage report after tests complete
127
coverage.generate(executionData);
128
```
129
130
### DataCollector
131
132
Hooks into EVM execution to collect coverage hit data during test runs.
133
134
```javascript { .api }
135
/**
136
* EVM execution hook for collecting coverage data
137
* Tracks which lines, functions, and branches are executed
138
*/
139
const DataCollector = require('solidity-coverage/lib/collector');
140
141
class DataCollector {
142
/**
143
* Creates a new data collector instance
144
* @param instrumentationData - Hit map from instrumentation (optional)
145
* @param viaIR - Whether using viaIR compilation mode (optional)
146
*/
147
constructor(instrumentationData?: object, viaIR?: boolean);
148
149
/**
150
* EVM step callback that processes each instruction
151
* @param info - EVM execution step information
152
*/
153
step(info: EVMStepInfo): void;
154
}
155
156
interface EVMStepInfo {
157
pc: number; // Program counter
158
opcode: { // Current opcode information
159
name: string; // Opcode name (e.g., 'SSTORE', 'CALL')
160
};
161
stack: any[]; // EVM stack state
162
}
163
```
164
165
**Usage Examples:**
166
167
```javascript
168
const DataCollector = require('solidity-coverage/lib/collector');
169
170
// Create data collector with instrumentation data
171
const collector = new DataCollector(instrumentationData, false);
172
173
// Hook into EVM execution (typically done by the API)
174
provider._node._vm.evm.events.on('step', collector.step.bind(collector));
175
```
176
177
### ConfigValidator
178
179
Validates configuration objects to ensure proper setup.
180
181
```javascript { .api }
182
/**
183
* Configuration validation utility
184
* Ensures coverage configuration is valid and complete
185
*/
186
const ConfigValidator = require('solidity-coverage/lib/validator');
187
188
class ConfigValidator {
189
/**
190
* Creates a new validator instance
191
*/
192
constructor();
193
194
/**
195
* Validates a coverage configuration object
196
* @param config - Configuration object to validate
197
* @returns True if configuration is valid
198
* @throws Error with descriptive message if invalid
199
*/
200
validate(config: object): boolean;
201
}
202
```
203
204
**Valid Configuration Properties:**
205
206
The validator accepts these configuration properties:
207
- `client`, `cwd`, `host`, `port`, `abiOutputPath`, `matrixOutputPath`
208
- `matrixReporterPath`, `providerOptions`, `silent`, `autoLaunchServer`
209
- `istanbulFolder`, `measureStatementCoverage`, `measureFunctionCoverage`
210
- `measureModifierCoverage`, `measureLineCoverage`, `measureBranchCoverage`
211
- `onServerReady`, `onCompileComplete`, `onTestComplete`, `onIstanbulComplete`
212
- `skipFiles`, `istanbulReporter`, `modifierWhitelist`
213
214
**Usage Examples:**
215
216
```javascript
217
const ConfigValidator = require('solidity-coverage/lib/validator');
218
219
const validator = new ConfigValidator();
220
221
const config = {
222
skipFiles: ['contracts/mocks/'],
223
istanbulReporter: ['html', 'lcov'],
224
measureStatementCoverage: true,
225
measureFunctionCoverage: true
226
};
227
228
try {
229
const isValid = validator.validate(config);
230
console.log('Configuration is valid:', isValid);
231
} catch (error) {
232
console.error('Invalid configuration:', error.message);
233
}
234
```
235
236
### AbiUtils
237
238
Utilities for working with contract ABI data and generating human-readable reports.
239
240
```javascript { .api }
241
/**
242
* ABI analysis and comparison utilities
243
* Generates human-readable ABI information and diffs
244
*/
245
const AbiUtils = require('solidity-coverage/lib/abi');
246
247
class AbiUtils {
248
/**
249
* Compares two ABI objects and generates a unified diff
250
* @param original - Original ABI object (optional)
251
* @param current - Current ABI object (optional)
252
* @returns Diff result with statistics and unified diff lines
253
*/
254
diff(original?: object, current?: object): AbiDiffResult;
255
256
/**
257
* Converts contract ABI to human-readable function signatures
258
* @param contract - Contract object with ABI property
259
* @returns Array of human-readable function signature strings
260
*/
261
toHumanReadableFunctions(contract: {abi: any[]}): string[];
262
}
263
264
interface AbiDiffResult {
265
plus: number; // Number of additions
266
minus: number; // Number of deletions
267
unifiedDiff: string[]; // Array of diff lines
268
}
269
```
270
271
**Usage Examples:**
272
273
```javascript
274
const AbiUtils = require('solidity-coverage/lib/abi');
275
276
const abiUtils = new AbiUtils();
277
278
// Generate human-readable function signatures
279
const contract = {
280
abi: [
281
{
282
"name": "transfer",
283
"type": "function",
284
"inputs": [
285
{"name": "to", "type": "address"},
286
{"name": "amount", "type": "uint256"}
287
],
288
"outputs": [{"type": "bool"}]
289
}
290
]
291
};
292
293
const signatures = abiUtils.toHumanReadableFunctions(contract);
294
console.log('Function signatures:', signatures);
295
// Output: ['function transfer(address to, uint256 amount) returns (bool)']
296
297
// Compare ABI changes
298
const oldAbi = { /* previous ABI */ };
299
const newAbi = { /* current ABI */ };
300
const diff = abiUtils.diff(oldAbi, newAbi);
301
console.log(`ABI changes: +${diff.plus} -${diff.minus}`);
302
```
303
304
### UI Classes
305
306
User interface classes for different output formats and environments.
307
308
```javascript { .api }
309
/**
310
* Base UI class for coverage output formatting
311
*/
312
const UI = require('solidity-coverage/lib/ui');
313
314
class UI {
315
/**
316
* Creates a new UI instance
317
* @param log - Optional logging function
318
*/
319
constructor(log?: (message: string) => void);
320
321
/**
322
* Reports a message using the specified kind and arguments
323
* @param kind - Message type/template identifier
324
* @param args - Arguments for message formatting (optional)
325
*/
326
report(kind: string, args?: string[]): void;
327
328
/**
329
* Generates a formatted message string
330
* @param kind - Message type/template identifier
331
* @param args - Arguments for message formatting (optional)
332
* @returns Formatted message string
333
*/
334
generate(kind: string, args?: string[]): string;
335
}
336
337
/**
338
* Application-specific UI class with enhanced formatting
339
*/
340
class AppUI extends UI {
341
constructor(log?: (message: string) => void);
342
report(kind: string, args?: string[]): void;
343
generate(kind: string, args?: string[]): string;
344
}
345
346
/**
347
* Plugin-specific UI class for Hardhat integration
348
*/
349
class PluginUI extends UI {
350
constructor(log?: (message: string) => void);
351
352
flags: {
353
testfiles: string; // Test files flag description
354
testMatrix: string; // Test matrix flag description
355
abi: string; // ABI flag description
356
solcoverjs: string; // Config file flag description
357
temp: string; // Temp directory flag description
358
};
359
}
360
```
361
362
**Usage Examples:**
363
364
```javascript
365
const { UI, AppUI, PluginUI } = require('solidity-coverage/lib/ui');
366
367
// Basic UI usage
368
const ui = new UI(console.log);
369
ui.report('coverage-starts');
370
371
// Plugin UI with command flags
372
const pluginUI = new PluginUI();
373
console.log('Available flags:', pluginUI.flags);
374
```
375
376
## Integration Patterns
377
378
### Complete Workflow Example
379
380
```javascript
381
const API = require('solidity-coverage/api');
382
const Instrumenter = require('solidity-coverage/lib/instrumenter');
383
const Coverage = require('solidity-coverage/lib/coverage');
384
const DataCollector = require('solidity-coverage/lib/collector');
385
386
async function runCoverageAnalysis() {
387
// Initialize components
388
const instrumenter = new Instrumenter({ measureStatementCoverage: true });
389
const coverage = new Coverage();
390
391
// Instrument contracts
392
const targets = [{ source: contractSource, canonicalPath: '/contracts/Token.sol' }];
393
const instrumented = targets.map(target => ({
394
...target,
395
...instrumenter.instrument(target.source, target.canonicalPath)
396
}));
397
398
// Add contracts to coverage tracking
399
instrumented.forEach(target => {
400
coverage.addContract(target, target.canonicalPath);
401
});
402
403
// Set up data collection
404
const collector = new DataCollector(api.getInstrumentationData());
405
provider._node._vm.evm.events.on('step', collector.step.bind(collector));
406
407
// Run tests (instrumented contracts will be executed)
408
// ... test execution ...
409
410
// Generate coverage reports
411
coverage.generate(collector.data);
412
}
413
```
414
415
This comprehensive core library documentation covers all the fundamental classes that developers may need to access when building custom coverage solutions or integrating with solidity-coverage at a lower level than the high-level API.