@darrenjcoxon/vibeguard 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +58 -0
- package/dist/agent-report.d.ts +36 -0
- package/dist/agent-report.d.ts.map +1 -0
- package/dist/agent-report.js +329 -0
- package/dist/agent-report.js.map +1 -0
- package/dist/ai-summary.d.ts +55 -0
- package/dist/ai-summary.d.ts.map +1 -0
- package/dist/ai-summary.js +267 -0
- package/dist/ai-summary.js.map +1 -0
- package/dist/cli.d.ts +9 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +328 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/orchestrator.d.ts +63 -0
- package/dist/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator.js +331 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/scanners/complexity.d.ts +48 -0
- package/dist/scanners/complexity.d.ts.map +1 -0
- package/dist/scanners/complexity.js +512 -0
- package/dist/scanners/complexity.js.map +1 -0
- package/dist/scanners/eslint.d.ts +21 -0
- package/dist/scanners/eslint.d.ts.map +1 -0
- package/dist/scanners/eslint.js +196 -0
- package/dist/scanners/eslint.js.map +1 -0
- package/dist/scanners/gitleaks.d.ts +21 -0
- package/dist/scanners/gitleaks.d.ts.map +1 -0
- package/dist/scanners/gitleaks.js +158 -0
- package/dist/scanners/gitleaks.js.map +1 -0
- package/dist/scanners/index.d.ts +56 -0
- package/dist/scanners/index.d.ts.map +1 -0
- package/dist/scanners/index.js +71 -0
- package/dist/scanners/index.js.map +1 -0
- package/dist/scanners/npm-audit.d.ts +19 -0
- package/dist/scanners/npm-audit.d.ts.map +1 -0
- package/dist/scanners/npm-audit.js +176 -0
- package/dist/scanners/npm-audit.js.map +1 -0
- package/dist/scanners/semgrep.d.ts +22 -0
- package/dist/scanners/semgrep.d.ts.map +1 -0
- package/dist/scanners/semgrep.js +175 -0
- package/dist/scanners/semgrep.js.map +1 -0
- package/dist/types.d.ts +522 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +194 -0
- package/dist/types.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Complexity Scanner
|
|
3
|
+
*
|
|
4
|
+
* Analyzes code complexity using various metrics
|
|
5
|
+
*
|
|
6
|
+
* Improvements based on expert feedback:
|
|
7
|
+
* - Excludes test files by default
|
|
8
|
+
* - Excludes type definition files (.d.ts)
|
|
9
|
+
* - Raised thresholds to industry standards (High: 25+, Medium: 20+)
|
|
10
|
+
* - Better remediation advice with specific function names
|
|
11
|
+
* - Smarter detection that avoids type-only files
|
|
12
|
+
*/
|
|
13
|
+
import { readFileSync, readdirSync, statSync } from 'fs';
|
|
14
|
+
import { join, extname, relative, basename } from 'path';
|
|
15
|
+
import { generateFingerprint } from '../types.js';
|
|
16
|
+
const DEFAULT_CONFIG = {
|
|
17
|
+
highComplexityThreshold: 25,
|
|
18
|
+
mediumComplexityThreshold: 20,
|
|
19
|
+
maxFileLines: 500,
|
|
20
|
+
maxFunctionLines: 50,
|
|
21
|
+
excludeTestFiles: true,
|
|
22
|
+
excludeTypeFiles: true,
|
|
23
|
+
excludePatterns: [],
|
|
24
|
+
reportTodos: true,
|
|
25
|
+
reportDebugStatements: true
|
|
26
|
+
};
|
|
27
|
+
export class ComplexityScanner {
|
|
28
|
+
name = 'complexity';
|
|
29
|
+
categories = ['complexity', 'quality'];
|
|
30
|
+
config;
|
|
31
|
+
// Supported extensions
|
|
32
|
+
supportedExtensions = ['.js', '.jsx', '.ts', '.tsx', '.py', '.rb', '.php', '.java', '.cs', '.go'];
|
|
33
|
+
// Test file patterns
|
|
34
|
+
testPatterns = [
|
|
35
|
+
/\.test\.[jt]sx?$/,
|
|
36
|
+
/\.spec\.[jt]sx?$/,
|
|
37
|
+
/_test\.[jt]sx?$/,
|
|
38
|
+
/_spec\.[jt]sx?$/,
|
|
39
|
+
/\/__tests__\//,
|
|
40
|
+
/\/test\//,
|
|
41
|
+
/\/tests\//,
|
|
42
|
+
/\.stories\.[jt]sx?$/, // Storybook files
|
|
43
|
+
];
|
|
44
|
+
constructor(config = {}) {
|
|
45
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
46
|
+
}
|
|
47
|
+
async isAvailable() {
|
|
48
|
+
return true; // Built-in analysis, always available
|
|
49
|
+
}
|
|
50
|
+
async scan(target, config) {
|
|
51
|
+
const startTime = Date.now();
|
|
52
|
+
try {
|
|
53
|
+
const files = this.collectFiles(target.path, target);
|
|
54
|
+
const findings = [];
|
|
55
|
+
for (const file of files) {
|
|
56
|
+
const fileFindings = await this.analyzeFile(file, target.path);
|
|
57
|
+
findings.push(...fileFindings);
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
scanner: this.name,
|
|
61
|
+
success: true,
|
|
62
|
+
findings,
|
|
63
|
+
metrics: {
|
|
64
|
+
duration: Date.now() - startTime,
|
|
65
|
+
filesScanned: files.length
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
return {
|
|
71
|
+
scanner: this.name,
|
|
72
|
+
success: false,
|
|
73
|
+
error: error instanceof Error ? error.message : String(error),
|
|
74
|
+
findings: [],
|
|
75
|
+
metrics: { duration: Date.now() - startTime }
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
shouldExcludeFile(filePath) {
|
|
80
|
+
const fileName = basename(filePath);
|
|
81
|
+
// Exclude .d.ts type definition files
|
|
82
|
+
if (this.config.excludeTypeFiles && fileName.endsWith('.d.ts')) {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
// Exclude test files
|
|
86
|
+
if (this.config.excludeTestFiles) {
|
|
87
|
+
for (const pattern of this.testPatterns) {
|
|
88
|
+
if (pattern.test(filePath)) {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Check custom exclude patterns
|
|
94
|
+
for (const pattern of this.config.excludePatterns) {
|
|
95
|
+
if (filePath.includes(pattern)) {
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
isTypeOnlyFile(content, ext) {
|
|
102
|
+
if (!['.ts', '.tsx'].includes(ext))
|
|
103
|
+
return false;
|
|
104
|
+
// Check if file only contains type/interface definitions
|
|
105
|
+
const lines = content.split('\n').filter(l => l.trim() && !l.trim().startsWith('//') && !l.trim().startsWith('/*'));
|
|
106
|
+
const typeOnlyPatterns = [
|
|
107
|
+
/^export\s+(type|interface)\s+/,
|
|
108
|
+
/^(type|interface)\s+/,
|
|
109
|
+
/^import\s+.*from/,
|
|
110
|
+
/^export\s*\{/,
|
|
111
|
+
/^export\s+\*/,
|
|
112
|
+
];
|
|
113
|
+
let typeLines = 0;
|
|
114
|
+
for (const line of lines) {
|
|
115
|
+
const trimmed = line.trim();
|
|
116
|
+
if (typeOnlyPatterns.some(p => p.test(trimmed))) {
|
|
117
|
+
typeLines++;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// If >80% of meaningful lines are type definitions, it's a type-only file
|
|
121
|
+
return lines.length > 0 && (typeLines / lines.length) > 0.8;
|
|
122
|
+
}
|
|
123
|
+
collectFiles(dir, target) {
|
|
124
|
+
const files = [];
|
|
125
|
+
const excludePatterns = [
|
|
126
|
+
'node_modules', 'vendor', '.git', 'dist', 'build',
|
|
127
|
+
'__pycache__', '.venv', 'venv', 'coverage', '.next',
|
|
128
|
+
...(target.exclude || [])
|
|
129
|
+
];
|
|
130
|
+
const walk = (currentDir) => {
|
|
131
|
+
try {
|
|
132
|
+
const entries = readdirSync(currentDir);
|
|
133
|
+
for (const entry of entries) {
|
|
134
|
+
const fullPath = join(currentDir, entry);
|
|
135
|
+
// Skip excluded directories
|
|
136
|
+
if (excludePatterns.some(p => entry === p || fullPath.includes(`/${p}/`))) {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
const stat = statSync(fullPath);
|
|
141
|
+
if (stat.isDirectory()) {
|
|
142
|
+
walk(fullPath);
|
|
143
|
+
}
|
|
144
|
+
else if (stat.isFile()) {
|
|
145
|
+
const ext = extname(entry).toLowerCase();
|
|
146
|
+
if (this.supportedExtensions.includes(ext)) {
|
|
147
|
+
// Apply exclusion rules
|
|
148
|
+
if (!this.shouldExcludeFile(fullPath)) {
|
|
149
|
+
files.push(fullPath);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
// Skip files we can't stat
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
// Skip directories we can't read
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
walk(dir);
|
|
164
|
+
return files;
|
|
165
|
+
}
|
|
166
|
+
async analyzeFile(filePath, basePath) {
|
|
167
|
+
const findings = [];
|
|
168
|
+
const relativePath = relative(basePath, filePath);
|
|
169
|
+
try {
|
|
170
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
171
|
+
const lines = content.split('\n');
|
|
172
|
+
const ext = extname(filePath).toLowerCase();
|
|
173
|
+
// Skip type-only files (even if not .d.ts)
|
|
174
|
+
if (this.config.excludeTypeFiles && this.isTypeOnlyFile(content, ext)) {
|
|
175
|
+
return findings;
|
|
176
|
+
}
|
|
177
|
+
// Basic line metrics
|
|
178
|
+
const metrics = this.calculateLineMetrics(lines, ext);
|
|
179
|
+
// File too long
|
|
180
|
+
if (metrics.codeLines > this.config.maxFileLines) {
|
|
181
|
+
findings.push(this.createFinding({
|
|
182
|
+
file: relativePath,
|
|
183
|
+
title: 'File exceeds recommended length',
|
|
184
|
+
description: `This file has ${metrics.codeLines} lines of code (recommended max: ${this.config.maxFileLines}).`,
|
|
185
|
+
severity: metrics.codeLines > this.config.maxFileLines * 2 ? 'medium' : 'low',
|
|
186
|
+
category: 'complexity',
|
|
187
|
+
suggestion: `Consider splitting into smaller modules. Look for logical groupings of functions that could become separate files.`,
|
|
188
|
+
effort: 'medium'
|
|
189
|
+
}));
|
|
190
|
+
}
|
|
191
|
+
// Analyze functions for complexity
|
|
192
|
+
const functions = this.analyzeFunctions(content, ext, relativePath);
|
|
193
|
+
// Find high complexity functions
|
|
194
|
+
const complexFunctions = functions.filter(f => f.complexity >= this.config.mediumComplexityThreshold);
|
|
195
|
+
if (complexFunctions.length > 0) {
|
|
196
|
+
// Sort by complexity (highest first)
|
|
197
|
+
complexFunctions.sort((a, b) => b.complexity - a.complexity);
|
|
198
|
+
for (const func of complexFunctions) {
|
|
199
|
+
const isHigh = func.complexity >= this.config.highComplexityThreshold;
|
|
200
|
+
findings.push(this.createFinding({
|
|
201
|
+
file: relativePath,
|
|
202
|
+
line: func.line,
|
|
203
|
+
title: `High complexity: ${func.name}()`,
|
|
204
|
+
description: `Function "${func.name}" has cyclomatic complexity of ${func.complexity}${isHigh ? ' (very high)' : ''}.`,
|
|
205
|
+
severity: isHigh ? 'high' : 'medium',
|
|
206
|
+
category: 'complexity',
|
|
207
|
+
suggestion: this.generateComplexitySuggestion(func),
|
|
208
|
+
effort: isHigh ? 'medium' : 'easy'
|
|
209
|
+
}));
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
// Find long functions
|
|
213
|
+
const longFunctions = functions.filter(f => f.length > this.config.maxFunctionLines);
|
|
214
|
+
for (const func of longFunctions) {
|
|
215
|
+
// Don't double-report if already flagged for complexity
|
|
216
|
+
if (complexFunctions.some(cf => cf.name === func.name && cf.line === func.line)) {
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
findings.push(this.createFinding({
|
|
220
|
+
file: relativePath,
|
|
221
|
+
line: func.line,
|
|
222
|
+
title: `Long function: ${func.name}()`,
|
|
223
|
+
description: `Function "${func.name}" is ${func.length} lines (recommended max: ${this.config.maxFunctionLines}).`,
|
|
224
|
+
severity: func.length > this.config.maxFunctionLines * 2 ? 'medium' : 'low',
|
|
225
|
+
category: 'complexity',
|
|
226
|
+
suggestion: `Extract logical sections of "${func.name}" into helper functions with clear names.`,
|
|
227
|
+
effort: 'easy'
|
|
228
|
+
}));
|
|
229
|
+
}
|
|
230
|
+
// Check for potential issues (TODOs, debug statements)
|
|
231
|
+
if (this.config.reportTodos || this.config.reportDebugStatements) {
|
|
232
|
+
const codeSmells = this.detectCodeSmells(content, ext, relativePath);
|
|
233
|
+
findings.push(...codeSmells);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
// Skip files we can't read
|
|
238
|
+
}
|
|
239
|
+
return findings;
|
|
240
|
+
}
|
|
241
|
+
generateComplexitySuggestion(func) {
|
|
242
|
+
const suggestions = [];
|
|
243
|
+
if (func.complexity >= 30) {
|
|
244
|
+
suggestions.push(`"${func.name}" is very complex and should be refactored urgently.`);
|
|
245
|
+
suggestions.push(`Consider breaking it into 3-5 smaller functions.`);
|
|
246
|
+
}
|
|
247
|
+
else if (func.complexity >= 25) {
|
|
248
|
+
suggestions.push(`Extract conditional branches from "${func.name}" into separate functions.`);
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
suggestions.push(`Simplify "${func.name}" using early returns or by extracting helper functions.`);
|
|
252
|
+
}
|
|
253
|
+
suggestions.push(`Look for: nested if/else chains, long switch statements, or repeated patterns.`);
|
|
254
|
+
return suggestions.join(' ');
|
|
255
|
+
}
|
|
256
|
+
analyzeFunctions(content, ext, filePath) {
|
|
257
|
+
const functions = [];
|
|
258
|
+
const lines = content.split('\n');
|
|
259
|
+
// Function detection patterns for different languages
|
|
260
|
+
const functionPatterns = {
|
|
261
|
+
'.js': [
|
|
262
|
+
/function\s+(\w+)\s*\(/g,
|
|
263
|
+
/(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?function/g,
|
|
264
|
+
/(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?\([^)]*\)\s*=>/g,
|
|
265
|
+
/(\w+)\s*:\s*(?:async\s+)?function/g,
|
|
266
|
+
],
|
|
267
|
+
'.ts': [
|
|
268
|
+
/function\s+(\w+)\s*[<(]/g,
|
|
269
|
+
/(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?function/g,
|
|
270
|
+
/(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?\([^)]*\)(?:\s*:\s*[^=]+)?\s*=>/g,
|
|
271
|
+
/(?:public|private|protected)?\s*(?:async\s+)?(\w+)\s*\([^)]*\)(?:\s*:\s*[^{]+)?\s*\{/g,
|
|
272
|
+
],
|
|
273
|
+
'.py': [
|
|
274
|
+
/def\s+(\w+)\s*\(/g,
|
|
275
|
+
/async\s+def\s+(\w+)\s*\(/g,
|
|
276
|
+
]
|
|
277
|
+
};
|
|
278
|
+
const patterns = functionPatterns[ext] || functionPatterns['.js'] || [];
|
|
279
|
+
for (const pattern of patterns) {
|
|
280
|
+
let match;
|
|
281
|
+
while ((match = pattern.exec(content)) !== null) {
|
|
282
|
+
const funcName = match[1];
|
|
283
|
+
if (!funcName || funcName === 'function')
|
|
284
|
+
continue;
|
|
285
|
+
const startIndex = match.index;
|
|
286
|
+
const startLine = content.slice(0, startIndex).split('\n').length;
|
|
287
|
+
// Get function body
|
|
288
|
+
const funcBody = this.extractFunctionBody(content.slice(startIndex), ext);
|
|
289
|
+
const funcLength = funcBody.split('\n').length;
|
|
290
|
+
const funcComplexity = this.calculateFunctionComplexity(funcBody);
|
|
291
|
+
functions.push({
|
|
292
|
+
name: funcName,
|
|
293
|
+
line: startLine,
|
|
294
|
+
length: funcLength,
|
|
295
|
+
complexity: funcComplexity
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
pattern.lastIndex = 0;
|
|
299
|
+
}
|
|
300
|
+
return functions;
|
|
301
|
+
}
|
|
302
|
+
extractFunctionBody(content, ext) {
|
|
303
|
+
if (['.py', '.rb'].includes(ext)) {
|
|
304
|
+
// Indentation-based
|
|
305
|
+
const lines = content.split('\n');
|
|
306
|
+
if (lines.length < 2)
|
|
307
|
+
return content;
|
|
308
|
+
const firstLine = lines[1] || lines[0];
|
|
309
|
+
const baseIndent = (firstLine.match(/^\s*/)?.[0].length || 0);
|
|
310
|
+
let endLine = 1;
|
|
311
|
+
for (let i = 2; i < lines.length; i++) {
|
|
312
|
+
const line = lines[i];
|
|
313
|
+
if (!line.trim())
|
|
314
|
+
continue;
|
|
315
|
+
const indent = line.match(/^\s*/)?.[0].length || 0;
|
|
316
|
+
if (indent < baseIndent)
|
|
317
|
+
break;
|
|
318
|
+
endLine = i;
|
|
319
|
+
}
|
|
320
|
+
return lines.slice(0, endLine + 1).join('\n');
|
|
321
|
+
}
|
|
322
|
+
// Brace-based
|
|
323
|
+
let braceCount = 0;
|
|
324
|
+
let started = false;
|
|
325
|
+
let endIndex = content.length;
|
|
326
|
+
for (let i = 0; i < content.length; i++) {
|
|
327
|
+
const char = content[i];
|
|
328
|
+
if (char === '{') {
|
|
329
|
+
braceCount++;
|
|
330
|
+
started = true;
|
|
331
|
+
}
|
|
332
|
+
else if (char === '}') {
|
|
333
|
+
braceCount--;
|
|
334
|
+
if (started && braceCount === 0) {
|
|
335
|
+
endIndex = i + 1;
|
|
336
|
+
break;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
return content.slice(0, endIndex);
|
|
341
|
+
}
|
|
342
|
+
calculateFunctionComplexity(funcBody) {
|
|
343
|
+
let complexity = 1;
|
|
344
|
+
const patterns = [
|
|
345
|
+
/\bif\s*\(/g,
|
|
346
|
+
/\belse\s+if\s*\(/g,
|
|
347
|
+
/\bwhile\s*\(/g,
|
|
348
|
+
/\bfor\s*\(/g,
|
|
349
|
+
/\bfor\s+\w+\s+in\b/g, // Python for-in
|
|
350
|
+
/\bforeach\s*\(/gi,
|
|
351
|
+
/\bcase\s+[^:]+:/g,
|
|
352
|
+
/\bcatch\s*\(/g,
|
|
353
|
+
/\&\&/g,
|
|
354
|
+
/\|\|/g,
|
|
355
|
+
/\?\s*[^:]+\s*:/g, // Ternary
|
|
356
|
+
/\?\./g, // Optional chaining (reduce count)
|
|
357
|
+
];
|
|
358
|
+
for (const pattern of patterns) {
|
|
359
|
+
const matches = funcBody.match(pattern);
|
|
360
|
+
if (matches) {
|
|
361
|
+
// Optional chaining adds less complexity
|
|
362
|
+
if (pattern.source === '\\?\\.') {
|
|
363
|
+
complexity += Math.floor(matches.length / 3);
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
complexity += matches.length;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return complexity;
|
|
371
|
+
}
|
|
372
|
+
calculateLineMetrics(lines, ext) {
|
|
373
|
+
let codeLines = 0;
|
|
374
|
+
let commentLines = 0;
|
|
375
|
+
let blankLines = 0;
|
|
376
|
+
const commentPatterns = this.getCommentPatterns(ext);
|
|
377
|
+
let inBlockComment = false;
|
|
378
|
+
for (const line of lines) {
|
|
379
|
+
const trimmed = line.trim();
|
|
380
|
+
if (!trimmed) {
|
|
381
|
+
blankLines++;
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
if (commentPatterns.blockStart && trimmed.includes(commentPatterns.blockStart)) {
|
|
385
|
+
inBlockComment = true;
|
|
386
|
+
}
|
|
387
|
+
if (inBlockComment) {
|
|
388
|
+
commentLines++;
|
|
389
|
+
if (commentPatterns.blockEnd && trimmed.includes(commentPatterns.blockEnd)) {
|
|
390
|
+
inBlockComment = false;
|
|
391
|
+
}
|
|
392
|
+
continue;
|
|
393
|
+
}
|
|
394
|
+
if (commentPatterns.line && trimmed.startsWith(commentPatterns.line)) {
|
|
395
|
+
commentLines++;
|
|
396
|
+
continue;
|
|
397
|
+
}
|
|
398
|
+
codeLines++;
|
|
399
|
+
}
|
|
400
|
+
return { codeLines, commentLines, blankLines };
|
|
401
|
+
}
|
|
402
|
+
getCommentPatterns(ext) {
|
|
403
|
+
const patterns = {
|
|
404
|
+
'.js': { line: '//', blockStart: '/*', blockEnd: '*/' },
|
|
405
|
+
'.jsx': { line: '//', blockStart: '/*', blockEnd: '*/' },
|
|
406
|
+
'.ts': { line: '//', blockStart: '/*', blockEnd: '*/' },
|
|
407
|
+
'.tsx': { line: '//', blockStart: '/*', blockEnd: '*/' },
|
|
408
|
+
'.py': { line: '#', blockStart: '"""', blockEnd: '"""' },
|
|
409
|
+
'.rb': { line: '#', blockStart: '=begin', blockEnd: '=end' },
|
|
410
|
+
'.php': { line: '//', blockStart: '/*', blockEnd: '*/' },
|
|
411
|
+
'.java': { line: '//', blockStart: '/*', blockEnd: '*/' },
|
|
412
|
+
'.cs': { line: '//', blockStart: '/*', blockEnd: '*/' },
|
|
413
|
+
'.go': { line: '//', blockStart: '/*', blockEnd: '*/' }
|
|
414
|
+
};
|
|
415
|
+
return patterns[ext] || { line: '//' };
|
|
416
|
+
}
|
|
417
|
+
detectCodeSmells(content, ext, filePath) {
|
|
418
|
+
const findings = [];
|
|
419
|
+
const lines = content.split('\n');
|
|
420
|
+
// TODO/FIXME comments - consolidate into one finding
|
|
421
|
+
if (this.config.reportTodos) {
|
|
422
|
+
const todoPattern = /\b(TODO|FIXME|HACK|XXX|BUG)\b/gi;
|
|
423
|
+
const todoLines = [];
|
|
424
|
+
lines.forEach((line, index) => {
|
|
425
|
+
if (todoPattern.test(line)) {
|
|
426
|
+
todoLines.push(index + 1);
|
|
427
|
+
}
|
|
428
|
+
todoPattern.lastIndex = 0;
|
|
429
|
+
});
|
|
430
|
+
if (todoLines.length > 0) {
|
|
431
|
+
findings.push(this.createFinding({
|
|
432
|
+
file: filePath,
|
|
433
|
+
line: todoLines[0],
|
|
434
|
+
title: todoLines.length === 1
|
|
435
|
+
? 'TODO comment found'
|
|
436
|
+
: `${todoLines.length} TODO/FIXME comments`,
|
|
437
|
+
description: todoLines.length === 1
|
|
438
|
+
? `Line ${todoLines[0]}: "${lines[todoLines[0] - 1].trim().slice(0, 80)}"`
|
|
439
|
+
: `Found on lines: ${todoLines.slice(0, 5).join(', ')}${todoLines.length > 5 ? ` (+${todoLines.length - 5} more)` : ''}`,
|
|
440
|
+
severity: 'info',
|
|
441
|
+
category: 'quality',
|
|
442
|
+
suggestion: 'Track in issue tracker or address before merging.',
|
|
443
|
+
effort: 'trivial'
|
|
444
|
+
}));
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
// Debug statements - consolidate into one finding
|
|
448
|
+
if (this.config.reportDebugStatements) {
|
|
449
|
+
const debugPatterns = {
|
|
450
|
+
'.js': /console\.(log|debug)\(/,
|
|
451
|
+
'.jsx': /console\.(log|debug)\(/,
|
|
452
|
+
'.ts': /console\.(log|debug)\(/,
|
|
453
|
+
'.tsx': /console\.(log|debug)\(/,
|
|
454
|
+
'.py': /\bprint\s*\(/,
|
|
455
|
+
'.php': /var_dump\(|print_r\(/
|
|
456
|
+
};
|
|
457
|
+
const debugPattern = debugPatterns[ext];
|
|
458
|
+
if (debugPattern) {
|
|
459
|
+
let debugCount = 0;
|
|
460
|
+
let firstDebugLine = 0;
|
|
461
|
+
lines.forEach((line, index) => {
|
|
462
|
+
const trimmed = line.trim();
|
|
463
|
+
if (trimmed.startsWith('//') || trimmed.startsWith('#') || trimmed.startsWith('*')) {
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
if (debugPattern.test(line)) {
|
|
467
|
+
debugCount++;
|
|
468
|
+
if (firstDebugLine === 0)
|
|
469
|
+
firstDebugLine = index + 1;
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
if (debugCount > 0) {
|
|
473
|
+
findings.push(this.createFinding({
|
|
474
|
+
file: filePath,
|
|
475
|
+
line: firstDebugLine,
|
|
476
|
+
title: debugCount === 1
|
|
477
|
+
? 'Debug statement found'
|
|
478
|
+
: `${debugCount} debug statements`,
|
|
479
|
+
description: `Found ${debugCount} console.log/print statement${debugCount > 1 ? 's' : ''}.`,
|
|
480
|
+
severity: 'info',
|
|
481
|
+
category: 'quality',
|
|
482
|
+
suggestion: 'Remove or replace with proper logging before production.',
|
|
483
|
+
effort: 'trivial'
|
|
484
|
+
}));
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
return findings;
|
|
489
|
+
}
|
|
490
|
+
createFinding(params) {
|
|
491
|
+
const finding = {
|
|
492
|
+
id: `complexity-${params.file}-${params.line || 0}-${Date.now()}`,
|
|
493
|
+
source: this.name,
|
|
494
|
+
severity: params.severity,
|
|
495
|
+
category: params.category,
|
|
496
|
+
file: params.file,
|
|
497
|
+
line: params.line,
|
|
498
|
+
title: params.title,
|
|
499
|
+
description: params.description,
|
|
500
|
+
suggestion: params.suggestion,
|
|
501
|
+
fixAvailable: false,
|
|
502
|
+
autoFixable: false,
|
|
503
|
+
confidence: 'medium',
|
|
504
|
+
effort: params.effort,
|
|
505
|
+
fingerprint: ''
|
|
506
|
+
};
|
|
507
|
+
finding.fingerprint = generateFingerprint(finding);
|
|
508
|
+
return finding;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
export default ComplexityScanner;
|
|
512
|
+
//# sourceMappingURL=complexity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"complexity.js","sourceRoot":"","sources":["../../src/scanners/complexity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ESLint Scanner
|
|
3
|
+
*
|
|
4
|
+
* Code quality and style scanning for JavaScript/TypeScript projects
|
|
5
|
+
* Covers: quality, style, security (with security plugins)
|
|
6
|
+
*/
|
|
7
|
+
import { Scanner, ScanTarget, ScannerConfig, ScannerResult, FindingCategory } from '../types.js';
|
|
8
|
+
export declare class ESLintScanner implements Scanner {
|
|
9
|
+
name: string;
|
|
10
|
+
categories: FindingCategory[];
|
|
11
|
+
private securityRulePrefixes;
|
|
12
|
+
isAvailable(): Promise<boolean>;
|
|
13
|
+
scan(target: ScanTarget, config?: ScannerConfig): Promise<ScannerResult>;
|
|
14
|
+
private hasESLintConfig;
|
|
15
|
+
private runESLint;
|
|
16
|
+
private transformFindings;
|
|
17
|
+
private categorizeRule;
|
|
18
|
+
private mapSeverity;
|
|
19
|
+
}
|
|
20
|
+
export default ESLintScanner;
|
|
21
|
+
//# sourceMappingURL=eslint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eslint.d.ts","sourceRoot":"","sources":["../../src/scanners/eslint.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EACL,OAAO,EACP,UAAU,EACV,aAAa,EACb,aAAa,EAEb,eAAe,EAGhB,MAAM,aAAa,CAAC;AAgCrB,qBAAa,aAAc,YAAW,OAAO;IAC3C,IAAI,SAAY;IAChB,UAAU,EAAE,eAAe,EAAE,CAAoC;IAGjE,OAAO,CAAC,oBAAoB,CAO1B;IAEI,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAS/B,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAkD9E,OAAO,CAAC,eAAe;YAgBT,SAAS;IAkCvB,OAAO,CAAC,iBAAiB;IA6CzB,OAAO,CAAC,cAAc;IAwBtB,OAAO,CAAC,WAAW;CAcpB;AAED,eAAe,aAAa,CAAC"}
|