0
# Analysis Reporters
1
2
Specialized analysis modules for different code quality metrics and linting integration. Reporters provide the core analysis functionality for complexity calculation, JSHint integration, and ESLint integration.
3
4
## Capabilities
5
6
### Complexity Reporter
7
8
Analyzes JavaScript source code to calculate complexity metrics including cyclomatic complexity, Halstead metrics, and maintainability indices.
9
10
```javascript { .api }
11
/**
12
* Analyze JavaScript source code complexity metrics
13
* @param {String} source - JavaScript source code to analyze
14
* @param {Object} options - Analysis options and configuration
15
* @param {Object} reportInfo - File information object for context
16
* @returns {Object} Complexity analysis report with detailed metrics
17
*/
18
function process(source, options, reportInfo);
19
```
20
21
**Parameters:**
22
23
- `source` (String): JavaScript source code to analyze
24
- `options` (Object): Analysis options and configuration
25
- `reportInfo` (Object): File information object containing file metadata
26
27
**Returns:** Object - Comprehensive complexity analysis report
28
29
**Report Structure:**
30
31
```javascript { .api }
32
interface ComplexityReport {
33
/** Cyclomatic complexity score */
34
cyclomatic: number;
35
36
/** Source lines of code metrics */
37
sloc: {
38
/** Physical lines of code (including comments and whitespace) */
39
physical: number;
40
/** Logical lines of code (executable statements) */
41
logical: number;
42
};
43
44
/** Halstead complexity metrics */
45
halstead: {
46
/** Operator analysis */
47
operators: {
48
distinct: number; // Number of unique operators
49
total: number; // Total operator count
50
identifiers: string[]; // List of operators found
51
};
52
/** Operand analysis */
53
operands: {
54
distinct: number; // Number of unique operands
55
total: number; // Total operand count
56
identifiers: string[]; // List of operands found
57
};
58
length: number; // Program length (N = N1 + N2)
59
vocabulary: number; // Program vocabulary (n = n1 + n2)
60
difficulty: number; // Programming difficulty
61
volume: number; // Program volume
62
effort: number; // Programming effort
63
bugs: number; // Estimated bugs
64
time: number; // Estimated programming time (seconds)
65
};
66
67
/** Maintainability index (0-100, higher is better) */
68
maintainability: number;
69
70
/** Function parameter count analysis */
71
params: number;
72
73
/** Additional complexity metrics */
74
// ... other complexity measurements
75
}
76
```
77
78
**Usage Examples:**
79
80
```javascript
81
const complexityReporter = require('plato/lib/reporters/complexity');
82
83
// Analyze source code
84
const sourceCode = `
85
function calculateSum(a, b, c) {
86
if (a > 0) {
87
return a + b + c;
88
} else {
89
return b + c;
90
}
91
}
92
`;
93
94
const reportInfo = {
95
file: 'calculator.js',
96
fileShort: 'calculator.js'
97
};
98
99
const complexityReport = complexityReporter.process(sourceCode, {}, reportInfo);
100
101
console.log('Cyclomatic Complexity:', complexityReport.cyclomatic);
102
console.log('Maintainability Index:', complexityReport.maintainability);
103
console.log('Physical SLOC:', complexityReport.sloc.physical);
104
console.log('Logical SLOC:', complexityReport.sloc.logical);
105
console.log('Halstead Volume:', complexityReport.halstead.volume);
106
```
107
108
### JSHint Reporter
109
110
Integrates JSHint linting analysis to identify potential issues and coding standard violations in JavaScript code.
111
112
```javascript { .api }
113
/**
114
* Run JSHint analysis on JavaScript source code
115
* @param {String} source - JavaScript source code to analyze
116
* @param {Object} options - JSHint configuration options
117
* @returns {Object} JSHint analysis report with messages and metadata
118
*/
119
function process(source, options);
120
```
121
122
**Parameters:**
123
124
- `source` (String): JavaScript source code to analyze
125
- `options` (Object): JSHint configuration options and rules
126
127
**Returns:** Object - JSHint analysis report
128
129
**Report Structure:**
130
131
```javascript { .api }
132
interface JSHintReport {
133
/** Array of JSHint messages */
134
messages: Array<{
135
/** Message severity level */
136
severity: 'error' | 'warning' | 'info';
137
/** Line number where issue occurs */
138
line: number;
139
/** Column number where issue occurs */
140
column: number;
141
/** Human-readable message describing the issue */
142
message: string;
143
/** Source code evidence showing the problematic line */
144
evidence: string;
145
/** JSHint rule identifier */
146
reason?: string;
147
/** Character position in source */
148
character?: number;
149
}>;
150
}
151
```
152
153
**Usage Examples:**
154
155
```javascript
156
const jshintReporter = require('plato/lib/reporters/jshint');
157
158
// Analyze with JSHint
159
const sourceCode = `
160
function badCode() {
161
var unused = 1;
162
undeclaredVar = 2;
163
return "missing semicolon"
164
}
165
`;
166
167
const jshintOptions = {
168
undef: true, // Require variable declarations
169
unused: true, // Warn about unused variables
170
asi: false // Require semicolons
171
};
172
173
const jshintReport = jshintReporter.process(sourceCode, jshintOptions);
174
175
jshintReport.messages.forEach(msg => {
176
console.log(`${msg.severity} at line ${msg.line}: ${msg.message}`);
177
console.log(`Evidence: ${msg.evidence}`);
178
});
179
180
// Example output:
181
// error at line 3: 'unused' is defined but never used.
182
// error at line 4: 'undeclaredVar' is not defined.
183
// error at line 5: Missing semicolon.
184
```
185
186
### ESLint Reporter
187
188
Integrates ESLint analysis for modern JavaScript linting with configurable rules and comprehensive error reporting.
189
190
```javascript { .api }
191
/**
192
* Run ESLint analysis on JavaScript source code
193
* @param {String} source - JavaScript source code to analyze
194
* @param {Object} options - ESLint configuration options and rules
195
* @returns {Object} ESLint analysis report with messages and metadata
196
*/
197
function process(source, options);
198
```
199
200
**Parameters:**
201
202
- `source` (String): JavaScript source code to analyze
203
- `options` (Object): ESLint configuration options, rules, and environment settings
204
205
**Returns:** Object - ESLint analysis report
206
207
**Report Structure:**
208
209
```javascript { .api }
210
interface ESLintReport {
211
/** Array of ESLint messages */
212
messages: Array<{
213
/** Message severity level */
214
severity: 'error' | 'warning';
215
/** Line number where issue occurs */
216
line: number;
217
/** Column number where issue occurs */
218
column: number;
219
/** Human-readable message describing the issue */
220
message: string;
221
/** ESLint rule identifier that triggered the message */
222
ruleId: string;
223
/** End line number for multi-line issues */
224
endLine?: number;
225
/** End column number for multi-line issues */
226
endColumn?: number;
227
/** Node type that triggered the rule */
228
nodeType?: string;
229
/** Source code excerpt */
230
source?: string;
231
}>;
232
}
233
```
234
235
**Usage Examples:**
236
237
```javascript
238
const eslintReporter = require('plato/lib/reporters/eslint');
239
240
// Analyze with ESLint
241
const sourceCode = `
242
const unusedVar = 1;
243
244
function inconsistentQuotes() {
245
console.log("double quotes");
246
console.log('single quotes');
247
return `template literal`;
248
}
249
250
if(true){
251
console.log("no spacing");
252
}
253
`;
254
255
const eslintOptions = {
256
env: {
257
es6: true,
258
node: true
259
},
260
rules: {
261
'no-unused-vars': 'error',
262
'quotes': ['error', 'single'],
263
'space-before-blocks': 'error',
264
'keyword-spacing': 'error'
265
}
266
};
267
268
const eslintReport = eslintReporter.process(sourceCode, eslintOptions);
269
270
eslintReport.messages.forEach(msg => {
271
console.log(`${msg.severity}: ${msg.message} (${msg.ruleId})`);
272
console.log(` at line ${msg.line}, column ${msg.column}`);
273
});
274
275
// Example output:
276
// error: 'unusedVar' is defined but never used. (no-unused-vars)
277
// at line 2, column 7
278
// error: Strings must use single quote. (quotes)
279
// at line 5, column 15
280
```
281
282
## Integration with Main Analysis
283
284
The reporters integrate seamlessly with Plato's main analysis workflow:
285
286
### Reporter Configuration
287
288
```javascript
289
const plato = require('plato');
290
291
// Configure analysis with multiple reporters
292
plato.inspect(['src/**/*.js'], 'reports', {
293
// JSHint configuration
294
jshint: {
295
node: true,
296
browser: true,
297
camelcase: true,
298
curly: true,
299
immed: true,
300
indent: 2,
301
latedef: true,
302
newcap: true,
303
nonew: true,
304
quotmark: 'single',
305
undef: true,
306
unused: true,
307
strict: true,
308
maxparams: 4,
309
maxdepth: 3,
310
maxcomplexity: 10
311
},
312
313
// ESLint configuration
314
eslint: {
315
env: {
316
node: true,
317
es6: true
318
},
319
extends: ['eslint:recommended'],
320
rules: {
321
'no-console': 'warn',
322
'no-unused-vars': 'error',
323
'quotes': ['error', 'single'],
324
'semi': ['error', 'always']
325
}
326
}
327
}, function(reports) {
328
reports.forEach(report => {
329
console.log(`\n--- ${report.info.file} ---`);
330
331
// Complexity metrics
332
console.log(`Complexity: ${report.complexity.cyclomatic}`);
333
console.log(`Maintainability: ${report.complexity.maintainability}`);
334
335
// JSHint results
336
if (report.jshint && report.jshint.messages.length > 0) {
337
console.log(`JSHint issues: ${report.jshint.messages.length}`);
338
}
339
340
// ESLint results
341
if (report.eslint && report.eslint.messages.length > 0) {
342
console.log(`ESLint issues: ${report.eslint.messages.length}`);
343
}
344
});
345
});
346
```
347
348
### Custom Reporter Integration
349
350
```javascript
351
// Example of using reporters independently
352
const complexityReporter = require('plato/lib/reporters/complexity');
353
const jshintReporter = require('plato/lib/reporters/jshint');
354
const eslintReporter = require('plato/lib/reporters/eslint');
355
const fs = require('fs');
356
357
function analyzeFile(filePath) {
358
const source = fs.readFileSync(filePath, 'utf8');
359
const reportInfo = { file: filePath };
360
361
// Run all analyses
362
const complexity = complexityReporter.process(source, {}, reportInfo);
363
const jshint = jshintReporter.process(source, { undef: true, unused: true });
364
const eslint = eslintReporter.process(source, {
365
rules: { 'no-unused-vars': 'error' }
366
});
367
368
return {
369
file: filePath,
370
complexity,
371
jshint,
372
eslint
373
};
374
}
375
376
// Analyze specific file
377
const analysis = analyzeFile('src/app.js');
378
console.log('Analysis complete:', analysis);
379
```
380
381
## Reporter Output Integration
382
383
Reporter outputs are combined into the final analysis reports:
384
385
### Combined Report Structure
386
387
```javascript
388
// Final report structure combining all reporters
389
const combinedReport = {
390
info: {
391
file: 'src/app.js',
392
fileShort: 'app.js',
393
// ... other file info
394
},
395
396
// From complexity reporter
397
complexity: {
398
cyclomatic: 8,
399
maintainability: 75.2,
400
sloc: { physical: 120, logical: 95 },
401
halstead: { /* ... */ }
402
},
403
404
// From JSHint reporter (if enabled)
405
jshint: {
406
messages: [
407
{ severity: 'error', line: 15, message: 'Undefined variable' }
408
]
409
},
410
411
// From ESLint reporter (if enabled)
412
eslint: {
413
messages: [
414
{ severity: 'warning', line: 20, ruleId: 'no-console', message: 'Unexpected console statement.' }
415
]
416
}
417
};
418
```
419
420
## Error Handling
421
422
Reporters handle various error scenarios gracefully:
423
424
### Source Code Parsing Errors
425
426
```javascript
427
// Reporters handle malformed JavaScript
428
const malformedCode = `
429
function broken() {
430
if (condition { // Missing closing parenthesis
431
return true;
432
}
433
`;
434
435
try {
436
const report = complexityReporter.process(malformedCode, {}, { file: 'broken.js' });
437
// Report may contain partial analysis or error information
438
} catch (error) {
439
console.error('Analysis failed:', error.message);
440
}
441
```
442
443
### Configuration Errors
444
445
```javascript
446
// Reporters validate configuration options
447
const invalidConfig = {
448
rules: {
449
'nonexistent-rule': 'error'
450
}
451
};
452
453
const report = eslintReporter.process(sourceCode, invalidConfig);
454
// Report will include configuration error messages
455
```
456
457
Each reporter is designed to provide useful information even when encountering errors, ensuring that the overall analysis process can continue and provide valuable insights about code quality.