The Code Quality scanner performs fast AST-based analysis to identify upgrade friction hotspots. It measures complexity metrics that correlate with difficult migrations and maintenance burden.
Metrics Collected
Function-Level Metrics
| Metric | Description | Why It Matters |
|---|---|---|
| Cyclomatic complexity | Number of decision points | High complexity = harder to test and upgrade |
| Function length | Lines per function | Long functions often need refactoring |
| Parameter count | Arguments per function | Many parameters suggest refactoring needed |
| Nesting depth | Maximum indentation level | Deep nesting is harder to understand |
File-Level Metrics
| Metric | Description | Why It Matters |
|---|---|---|
| File size | Lines of code | Large files are upgrade bottlenecks |
| Export count | Number of exports | Many exports = high coupling |
| Import count | Number of imports | Many imports = high dependencies |
| Circular dependencies | Files that import each other | Circular imports complicate upgrades |
Project-Level Metrics
| Metric | Description |
|---|---|
| "God files" | Files exceeding complexity thresholds |
| Dead code estimate | Potentially unused exports |
| Test coverage gaps | Files without corresponding tests |
Thresholds
| Metric | 🟢 Healthy | 🟡 Warning | 🔴 Critical |
|---|---|---|---|
| Cyclomatic complexity | <10 | 10–20 | >20 |
| Function length | <50 lines | 50–100 lines | >100 lines |
| Nesting depth | <4 levels | 4–6 levels | >6 levels |
| File size | <300 lines | 300–500 lines | >500 lines |
| Parameters | <4 | 4–6 | >6 |
Use Cases
Pre-Upgrade Assessment
Identify files that will be hardest to upgrade:
vg scan --format json | jq '.codeQuality.godFiles | sort_by(-.complexity)'
Refactoring Prioritization
Rank files by complexity for refactoring sprints:
vg scan --format json | jq '.codeQuality | {avgComplexity, godFiles: (.godFiles | length)}'
Code Review Focus
During upgrades, focus review effort on high-complexity files.
Example Output
{
"codeQuality": {
"summary": {
"filesAnalyzed": 245,
"functionsAnalyzed": 1203,
"healthScore": 72
},
"averages": {
"cyclomaticComplexity": 8.3,
"functionLength": 32,
"nestingDepth": 2.8,
"parametersPerFunction": 2.1
},
"maximums": {
"cyclomaticComplexity": 45,
"functionLength": 287,
"nestingDepth": 7
},
"circularDependencies": [
{
"cycle": ["src/auth/index.ts", "src/api/middleware.ts", "src/auth/index.ts"],
"severity": "high"
}
],
"godFiles": [
{
"path": "src/legacy/megaModule.ts",
"complexity": 45,
"lines": 892,
"functions": 34,
"recommendations": [
"Consider splitting into multiple modules",
"Extract pure utility functions"
]
},
{
"path": "src/api/handlers.ts",
"complexity": 32,
"lines": 456,
"functions": 22
}
],
"deadCodeEstimate": {
"unusedExports": 12,
"files": ["src/utils/deprecated.ts", "src/legacy/old-api.ts"]
}
}
}
Configuration
Customize thresholds in config:
// vibgrate.config.ts
const config: VibgrateConfig = {
scanners: {
codeQuality: {
enabled: true,
thresholds: {
cyclomaticComplexity: { warning: 15, critical: 25 },
functionLength: { warning: 75, critical: 150 },
nestingDepth: { warning: 5, critical: 8 },
},
exclude: ['**/*.test.ts', '**/*.spec.ts'],
},
},
};