vibe-code-build
Version:
Real-time code monitoring with teaching explanations, CLAUDE.md compliance checking, and interactive chat
267 lines (229 loc) • 9.34 kB
JavaScript
import chalk from 'chalk';
import { themeManager } from './theme-manager.js';
/**
* AI Code Analyzer - Detects and explains AI-generated code patterns
* Provides detailed explanations of what AI code does and why
*/
export class AICodeAnalyzer {
constructor() {
this.aiPatterns = {
// Common AI code generation patterns
errorHandling: {
pattern: /try\s*{[\s\S]*?}\s*catch\s*\((\w+)\)\s*{[\s\S]*?}/,
explain: 'AI added comprehensive error handling to prevent crashes'
},
asyncAwait: {
pattern: /async\s+(\w+)[\s\S]*?await\s+/,
explain: 'AI implemented asynchronous operations for better performance'
},
validation: {
pattern: /if\s*\(!?\w+(\.\w+)*\)\s*{[\s\S]*?(throw|return|console\.(error|warn))/,
explain: 'AI added input validation to ensure data integrity'
},
logging: {
pattern: /console\.(log|info|warn|error)\([^)]+\)/,
explain: 'AI added logging for debugging and monitoring'
},
typeChecking: {
pattern: /typeof\s+\w+\s*===?\s*['"][^'"]+['"]|instanceof\s+\w+/,
explain: 'AI added type checking for runtime safety'
},
nullChecks: {
pattern: /\w+\s*\?\.\w+|\w+\s*&&\s*\w+\.\w+|\w+\s*\|\|\s*['"\[\{]/,
explain: 'AI added null/undefined checks to prevent errors'
},
arrayMethods: {
pattern: /\.(map|filter|reduce|forEach|find|some|every)\(/,
explain: 'AI used modern array methods for cleaner, functional code'
},
destructuring: {
pattern: /const\s*{[^}]+}\s*=|const\s*\[[^\]]+\]\s*=/,
explain: 'AI used destructuring for cleaner variable extraction'
},
templateLiterals: {
pattern: /`[^`]*\$\{[^}]+\}[^`]*`/,
explain: 'AI used template literals for string formatting'
},
promises: {
pattern: /new\s+Promise\s*\(|\.then\s*\(|\.catch\s*\(/,
explain: 'AI implemented Promise-based asynchronous flow'
},
comments: {
pattern: /\/\/\s*[A-Z][\s\S]*?\n|\/\*[\s\S]*?\*\//,
explain: 'AI added helpful comments to explain the code'
}
};
this.codeQualityPatterns = {
modular: {
pattern: /export\s+(default\s+)?(?:class|function|const)|import\s+.*\s+from/,
explain: 'Code follows modular design principles'
},
defensive: {
pattern: /if\s*\([^)]*\)\s*{[\s\S]*?return[\s\S]*?}|guard|validate|check/i,
explain: 'Code includes defensive programming practices'
},
documented: {
pattern: /\/\*\*[\s\S]*?\*\/|@param|@returns|@throws/,
explain: 'Code includes JSDoc documentation'
},
tested: {
pattern: /describe\s*\(|it\s*\(|test\s*\(|expect\s*\(/,
explain: 'Code includes test cases'
}
};
}
analyzeAICode(context) {
const { diff, filename, type } = context;
const colors = themeManager.getColors();
if (!diff) return '';
const analysis = this.detectAIPatterns(diff);
if (analysis.patterns.length === 0) {
return this.fallbackAnalysis(context);
}
let output = colors.primary('\n🤖 AI Code Analysis:\n');
// Explain what the AI did
output += colors.secondary('\n📝 What the AI implemented:\n');
analysis.patterns.forEach(({ name, explanation, example }) => {
output += colors.muted(` • ${explanation}\n`);
if (example) {
output += colors.accent(` Example: ${this.truncateCode(example)}\n`);
}
});
// Explain why these patterns are good
if (analysis.quality.length > 0) {
output += colors.secondary('\n✨ Code quality improvements:\n');
analysis.quality.forEach(quality => {
output += colors.success(` • ${quality}\n`);
});
}
// Provide learning insights
output += colors.secondary('\n💡 Why this matters:\n');
output += this.explainBenefits(analysis.patterns);
// Suggest improvements if needed
const suggestions = this.suggestImprovements(diff);
if (suggestions.length > 0) {
output += colors.secondary('\n🎯 Potential improvements:\n');
suggestions.forEach(suggestion => {
output += colors.warning(` • ${suggestion}\n`);
});
}
return output;
}
detectAIPatterns(diff) {
const patterns = [];
const quality = [];
const addedLines = diff.split('\n')
.filter(line => line.startsWith('+') && !line.startsWith('+++'))
.map(line => line.substring(1))
.join('\n');
// Check for AI patterns
for (const [name, { pattern, explain }] of Object.entries(this.aiPatterns)) {
const match = addedLines.match(pattern);
if (match) {
patterns.push({
name,
explanation: explain,
example: match[0]
});
}
}
// Check code quality patterns
for (const [name, { pattern, explain }] of Object.entries(this.codeQualityPatterns)) {
if (pattern.test(addedLines)) {
quality.push(explain);
}
}
// Detect specific AI code generation patterns
if (this.looksLikeAIGenerated(addedLines)) {
patterns.push({
name: 'ai-generated',
explanation: 'This appears to be AI-generated code with consistent style and comprehensive handling'
});
}
return { patterns, quality };
}
looksLikeAIGenerated(code) {
// AI-generated code often has these characteristics
const indicators = [
code.includes('try {') && code.includes('} catch'), // Comprehensive error handling
code.match(/if\s*\([^)]+\)\s*{/g)?.length > 2, // Multiple validation checks
code.includes('console.log') || code.includes('console.error'), // Logging
code.match(/\/\/ [A-Z]/g)?.length > 1, // Multiple comments
code.includes('async') && code.includes('await'), // Modern async patterns
code.includes('const') && !code.includes('var'), // Modern JS syntax
code.match(/\?\./g)?.length > 0 // Optional chaining
];
const score = indicators.filter(Boolean).length;
return score >= 3;
}
explainBenefits(patterns) {
const colors = themeManager.getColors();
const benefits = [];
const hasErrorHandling = patterns.some(p => p.name === 'errorHandling');
const hasValidation = patterns.some(p => p.name === 'validation');
const hasAsync = patterns.some(p => p.name === 'asyncAwait');
const hasNullChecks = patterns.some(p => p.name === 'nullChecks');
if (hasErrorHandling) {
benefits.push('Error handling prevents app crashes and improves user experience');
}
if (hasValidation) {
benefits.push('Input validation prevents bugs and security vulnerabilities');
}
if (hasAsync) {
benefits.push('Async/await makes code more readable than callbacks or raw promises');
}
if (hasNullChecks) {
benefits.push('Null checks prevent "Cannot read property of undefined" errors');
}
if (benefits.length === 0) {
benefits.push('This code follows modern JavaScript best practices');
benefits.push('The implementation is robust and production-ready');
}
return benefits.map(b => colors.muted(` • ${b}`)).join('\n') + '\n';
}
suggestImprovements(diff) {
const suggestions = [];
const addedLines = diff.split('\n')
.filter(line => line.startsWith('+'))
.join('\n');
// Check for potential improvements
if (addedLines.includes('console.log') && !addedLines.includes('if')) {
suggestions.push('Consider adding environment checks for console.log statements');
}
if (addedLines.includes('catch(error)') && !addedLines.includes('console.error')) {
suggestions.push('Consider logging errors in catch blocks for debugging');
}
if (addedLines.match(/function\s+\w+\s*\(/g) && !addedLines.includes('/**')) {
suggestions.push('Consider adding JSDoc comments for better documentation');
}
if (addedLines.includes('setTimeout') || addedLines.includes('setInterval')) {
suggestions.push('Remember to clear timers to prevent memory leaks');
}
if (addedLines.length > 200 && !addedLines.includes('export')) {
suggestions.push('Consider breaking this into smaller, modular functions');
}
return suggestions;
}
fallbackAnalysis(context) {
const colors = themeManager.getColors();
const { diff, filename } = context;
const added = (diff.match(/^\+[^+]/gm) || []).length;
const removed = (diff.match(/^-[^-]/gm) || []).length;
let output = colors.primary(`\n📊 Code changes in ${filename}:\n`);
output += colors.muted(` Added ${added} lines, removed ${removed} lines\n`);
// Try to provide some generic insights
if (added > removed) {
output += colors.muted(` • New functionality has been added\n`);
} else if (removed > added) {
output += colors.muted(` • Code has been simplified or cleaned up\n`);
} else {
output += colors.muted(` • Code has been refactored\n`);
}
return output;
}
truncateCode(code, maxLength = 50) {
if (code.length <= maxLength) return code;
return code.substring(0, maxLength) + '...';
}
}
export const aiCodeAnalyzer = new AICodeAnalyzer();