0
# Output Formatting
1
2
Multiple formatter functions for different output formats and integration needs. Solhint provides various formatters to present linting results in different formats suitable for human reading, CI/CD integration, and tool consumption.
3
4
## Capabilities
5
6
### Stylish Formatter
7
8
Default human-readable formatter with colors and clear structure (default formatter).
9
10
```javascript { .api }
11
/**
12
* Default human-readable formatter with colors and clear structure
13
* @param {Array<Reporter>} reports - Array of Reporter instances
14
* @returns {string} Formatted output string with colors and styling
15
*/
16
function stylish(reports);
17
```
18
19
**Usage Examples:**
20
21
```javascript
22
const stylish = require('solhint/lib/formatters/stylish');
23
24
const reports = [/* Reporter instances */];
25
const output = stylish(reports);
26
console.log(output);
27
28
// CLI usage
29
// solhint contracts/*.sol (uses stylish by default)
30
// solhint -f stylish contracts/*.sol
31
```
32
33
**Output Format:**
34
```
35
contracts/Token.sol
36
10:5 error Explicitly mark visibility in function func-visibility
37
15:8 warning Line length exceeds 120 characters max-line-length
38
39
✖ 2 problems (1 error, 1 warning)
40
```
41
42
### JSON Formatter
43
44
Machine-readable JSON output for programmatic consumption and CI/CD integration.
45
46
```javascript { .api }
47
/**
48
* Machine-readable JSON output for programmatic consumption
49
* @param {Array<Reporter>} reports - Array of Reporter instances
50
* @returns {string} JSON string containing structured results
51
*/
52
function json(reports);
53
```
54
55
**Usage Examples:**
56
57
```javascript
58
const json = require('solhint/lib/formatters/json');
59
60
const output = json(reports);
61
const results = JSON.parse(output);
62
63
// Process results programmatically
64
results.forEach(file => {
65
console.log(`File: ${file.filePath}`);
66
console.log(`Errors: ${file.errorCount}`);
67
file.messages.forEach(msg => {
68
console.log(` ${msg.line}:${msg.column} ${msg.message}`);
69
});
70
});
71
72
// CLI usage
73
// solhint -f json contracts/*.sol > results.json
74
```
75
76
**Output Format:**
77
```json
78
[
79
{
80
"filePath": "contracts/Token.sol",
81
"messages": [
82
{
83
"line": 10,
84
"column": 5,
85
"severity": 2,
86
"message": "Explicitly mark visibility in function",
87
"ruleId": "func-visibility"
88
}
89
],
90
"errorCount": 1,
91
"warningCount": 0
92
}
93
]
94
```
95
96
### Table Formatter
97
98
Tabular output format for clear columnar presentation of results.
99
100
```javascript { .api }
101
/**
102
* Tabular output format for clear columnar presentation
103
* @param {Array<Reporter>} reports - Array of Reporter instances
104
* @returns {string} Table-formatted output string
105
*/
106
function table(reports);
107
```
108
109
**Usage Examples:**
110
111
```javascript
112
const table = require('solhint/lib/formatters/table');
113
114
const output = table(reports);
115
console.log(output);
116
117
// CLI usage
118
// solhint -f table contracts/*.sol
119
```
120
121
**Output Format:**
122
```
123
┌─────────────────────┬──────┬────────┬──────────┬─────────────────────────────────────┬───────────────────┐
124
│ File │ Line │ Column │ Severity │ Message │ Rule ID │
125
├─────────────────────┼──────┼────────┼──────────┼─────────────────────────────────────┼───────────────────┤
126
│ contracts/Token.sol │ 10 │ 5 │ error │ Explicitly mark visibility │ func-visibility │
127
│ contracts/Token.sol │ 15 │ 8 │ warning │ Line length exceeds 120 characters │ max-line-length │
128
└─────────────────────┴──────┴────────┴──────────┴─────────────────────────────────────┴───────────────────┘
129
```
130
131
### Compact Formatter
132
133
Compact single-line format for each issue, suitable for grep and simple parsing.
134
135
```javascript { .api }
136
/**
137
* Compact single-line format for each issue
138
* @param {Array<Reporter>} reports - Array of Reporter instances
139
* @returns {string} Compact formatted output string
140
*/
141
function compact(reports);
142
```
143
144
**Usage Examples:**
145
146
```javascript
147
const compact = require('solhint/lib/formatters/compact');
148
149
const output = compact(reports);
150
console.log(output);
151
152
// CLI usage
153
// solhint -f compact contracts/*.sol
154
```
155
156
**Output Format:**
157
```
158
contracts/Token.sol: line 10, col 5, Error - Explicitly mark visibility in function (func-visibility)
159
contracts/Token.sol: line 15, col 8, Warning - Line length exceeds 120 characters (max-line-length)
160
```
161
162
### Unix Formatter
163
164
Unix-style format compatible with editors and IDEs that parse compiler output.
165
166
```javascript { .api }
167
/**
168
* Unix-style format compatible with editors and IDEs
169
* @param {Array<Reporter>} reports - Array of Reporter instances
170
* @returns {string} Unix-formatted output string
171
*/
172
function unix(reports);
173
```
174
175
**Usage Examples:**
176
177
```javascript
178
const unix = require('solhint/lib/formatters/unix');
179
180
const output = unix(reports);
181
console.log(output);
182
183
// CLI usage
184
// solhint -f unix contracts/*.sol
185
```
186
187
**Output Format:**
188
```
189
contracts/Token.sol:10:5: Explicitly mark visibility in function [func-visibility]
190
contracts/Token.sol:15:8: Line length exceeds 120 characters [max-line-length]
191
```
192
193
### TAP Formatter
194
195
Test Anything Protocol (TAP) format for integration with TAP-consuming test runners.
196
197
```javascript { .api }
198
/**
199
* Test Anything Protocol (TAP) format for test runners
200
* @param {Array<Reporter>} reports - Array of Reporter instances
201
* @returns {string} TAP-formatted output string
202
*/
203
function tap(reports);
204
```
205
206
**Usage Examples:**
207
208
```javascript
209
const tap = require('solhint/lib/formatters/tap');
210
211
const output = tap(reports);
212
console.log(output);
213
214
// CLI usage
215
// solhint -f tap contracts/*.sol
216
```
217
218
**Output Format:**
219
```
220
TAP version 13
221
1..2
222
not ok 1 - contracts/Token.sol:10:5: Explicitly mark visibility in function (func-visibility)
223
not ok 2 - contracts/Token.sol:15:8: Line length exceeds 120 characters (max-line-length)
224
```
225
226
### SARIF Formatter
227
228
Static Analysis Results Interchange Format (SARIF) for security tooling and CI/CD integration.
229
230
```javascript { .api }
231
/**
232
* Static Analysis Results Interchange Format (SARIF) for security tooling
233
* @param {Array<Reporter>} reports - Array of Reporter instances
234
* @returns {string} SARIF JSON formatted output string
235
*/
236
function sarif(reports);
237
```
238
239
**Usage Examples:**
240
241
```javascript
242
const sarif = require('solhint/lib/formatters/sarif');
243
244
const output = sarif(reports);
245
const sarifData = JSON.parse(output);
246
247
// Process SARIF data
248
console.log('Tool:', sarifData.runs[0].tool.driver.name);
249
console.log('Results:', sarifData.runs[0].results.length);
250
251
// CLI usage
252
// solhint -f sarif contracts/*.sol > results.sarif
253
```
254
255
**Output Format:**
256
```json
257
{
258
"version": "2.1.0",
259
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
260
"runs": [
261
{
262
"tool": {
263
"driver": {
264
"name": "solhint",
265
"version": "6.0.1",
266
"rules": [
267
{
268
"id": "func-visibility",
269
"shortDescription": {
270
"text": "Explicitly mark visibility in function"
271
}
272
}
273
]
274
}
275
},
276
"results": [
277
{
278
"ruleId": "func-visibility",
279
"level": "error",
280
"message": {
281
"text": "Explicitly mark visibility in function"
282
},
283
"locations": [
284
{
285
"physicalLocation": {
286
"artifactLocation": {
287
"uri": "contracts/Token.sol"
288
},
289
"region": {
290
"startLine": 10,
291
"startColumn": 5
292
}
293
}
294
}
295
]
296
}
297
]
298
}
299
]
300
}
301
```
302
303
## Formatter Usage Patterns
304
305
### Programmatic Usage
306
307
```javascript
308
const { processPath } = require('solhint');
309
const stylish = require('solhint/lib/formatters/stylish');
310
const json = require('solhint/lib/formatters/json');
311
312
// Process files
313
const reports = processPath('contracts/**/*.sol');
314
315
// Format for human reading
316
const humanOutput = stylish(reports);
317
console.log(humanOutput);
318
319
// Format for tools
320
const jsonOutput = json(reports);
321
fs.writeFileSync('lint-results.json', jsonOutput);
322
```
323
324
### CLI Usage
325
326
```bash
327
# Default formatter (stylish)
328
solhint contracts/*.sol
329
330
# Specific formatter
331
solhint -f json contracts/*.sol
332
333
# Save formatted output
334
solhint -f sarif contracts/*.sol > security-report.sarif
335
solhint -f json contracts/*.sol > lint-results.json
336
```
337
338
### CI/CD Integration
339
340
```yaml
341
# GitHub Actions example
342
- name: Run Solhint
343
run: |
344
solhint -f json 'contracts/**/*.sol' > lint-results.json
345
346
- name: Process Results
347
run: |
348
node -e "
349
const results = JSON.parse(require('fs').readFileSync('lint-results.json'));
350
const errors = results.reduce((sum, file) => sum + file.errorCount, 0);
351
if (errors > 0) process.exit(1);
352
"
353
```
354
355
### Custom Formatter Integration
356
357
```javascript
358
// Create custom formatter wrapper
359
function customFormatter(reports) {
360
const jsonResults = json(reports);
361
const data = JSON.parse(jsonResults);
362
363
// Custom processing
364
return data.map(file => ({
365
file: file.filePath,
366
issues: file.messages.length,
367
critical: file.messages.filter(m => m.severity === 2).length
368
}));
369
}
370
371
const reports = processPath('contracts/**/*.sol');
372
const customOutput = customFormatter(reports);
373
console.log(JSON.stringify(customOutput, null, 2));
374
```
375
376
## Output Format Comparison
377
378
| Formatter | Use Case | Machine Readable | Colors | Structure |
379
|-----------|----------|------------------|--------|-----------|
380
| stylish | Development, terminal output | No | Yes | Human-friendly |
381
| json | CI/CD, programmatic processing | Yes | No | Structured data |
382
| table | Reports, documentation | No | No | Tabular |
383
| compact | Grep, simple parsing | Partial | No | One-line |
384
| unix | Editor integration | Partial | No | Standard format |
385
| tap | Test runners | Yes | No | TAP protocol |
386
| sarif | Security tools, compliance | Yes | No | Industry standard |
387
388
## Error Handling in Formatters
389
390
Formatters handle various edge cases:
391
392
- Empty report arrays
393
- Files with no issues
394
- Missing file paths
395
- Invalid severity levels
396
- Unicode characters in messages
397
- Very long file paths or messages
398
399
```javascript
400
// Example error handling
401
function safeFormat(formatter, reports) {
402
try {
403
return formatter(reports || []);
404
} catch (error) {
405
console.error('Formatter error:', error.message);
406
return 'Error formatting results';
407
}
408
}
409
```
410
411
## Performance Considerations
412
413
- JSON and SARIF formatters handle large result sets efficiently
414
- Stylish formatter is optimized for terminal display
415
- Table formatter may be slow with very wide tables
416
- Consider streaming for very large outputs in custom integrations