/** * 质量保证系统 * 为AI自动生成打下基石 */ class QualityAssurance { constructor() { this.validators = { syntax: this.validateSyntax.bind(this), types: this.validateTypes.bind(this), imports: this.validateImports.bind(this), business: this.validateBusinessLogic.bind(this), performance: this.validatePerformance.bind(this), security: this.validateSecurity.bind(this) }; this.fixers = { syntax: this.fixSyntaxErrors.bind(this), types: this.fixTypeErrors.bind(this), imports: this.fixImportErrors.bind(this), business: this.fixBusinessLogicErrors.bind(this) }; this.metrics = { complexity: this.calculateComplexity.bind(this), maintainability: this.calculateMaintainability.bind(this), testability: this.calculateTestability.bind(this), performance: this.calculatePerformance.bind(this) }; } /** * 执行完整的质量检查 */ async performQualityCheck(code, context = {}) { const results = { overall: 'pass', validations: {}, fixes: {}, metrics: {}, recommendations: [], errors: [], warnings: [] }; console.log('🛡️ 开始质量检查...'); // 执行所有验证 for (const [type, validator] of Object.entries(this.validators)) { try { console.log(` 🔍 执行${type}验证...`); const validation = await validator(code, context); results.validations[type] = validation; if (validation.errors.length > 0) { results.errors.push(...validation.errors); results.overall = 'fail'; } if (validation.warnings.length > 0) { results.warnings.push(...validation.warnings); } console.log(` ✅ ${type}验证完成: ${validation.errors.length}个错误, ${validation.warnings.length}个警告`); } catch (error) { console.error(` ❌ ${type}验证失败:`, error.message); results.errors.push({ type, message: error.message, stack: error.stack }); results.overall = 'fail'; } } // 计算质量指标 for (const [type, calculator] of Object.entries(this.metrics)) { try { results.metrics[type] = calculator(code, context); } catch (error) { console.error(` ❌ ${type}指标计算失败:`, error.message); } } // 生成建议 results.recommendations = this.generateRecommendations(results); console.log(`🎯 质量检查完成: ${results.overall.toUpperCase()}`); return results; } /** * 自动修复代码问题 */ async autoFix(code, qualityResults) { let fixedCode = code; const fixes = []; console.log('🔧 开始自动修复...'); // 修复语法错误 if (qualityResults.validations.syntax?.errors.length > 0) { const syntaxFixes = await this.fixers.syntax(fixedCode, qualityResults.validations.syntax); fixedCode = syntaxFixes.code; fixes.push(...syntaxFixes.fixes); } // 修复类型错误 if (qualityResults.validations.types?.errors.length > 0) { const typeFixes = await this.fixers.types(fixedCode, qualityResults.validations.types); fixedCode = typeFixes.code; fixes.push(...typeFixes.fixes); } // 修复导入错误 if (qualityResults.validations.imports?.errors.length > 0) { const importFixes = await this.fixers.imports(fixedCode, qualityResults.validations.imports); fixedCode = importFixes.code; fixes.push(...importFixes.fixes); } // 修复业务逻辑错误 if (qualityResults.validations.business?.errors.length > 0) { const businessFixes = await this.fixers.business(fixedCode, qualityResults.validations.business); fixedCode = businessFixes.code; fixes.push(...businessFixes.fixes); } console.log(`✅ 自动修复完成: ${fixes.length}个修复`); return { code: fixedCode, fixes, summary: { totalFixes: fixes.length, fixedTypes: [...new Set(fixes.map(f => f.type))] } }; } /** * 验证语法 */ async validateSyntax(code, context) { const errors = []; const warnings = []; // 检查方括号错误 const bracketErrors = this.findBracketErrors(code); errors.push(...bracketErrors); // 检查重复前缀 const prefixErrors = this.findPrefixErrors(code); errors.push(...prefixErrors); // 检查语法错误 const syntaxErrors = this.findSyntaxErrors(code); errors.push(...syntaxErrors); // 检查代码风格 const styleWarnings = this.findStyleWarnings(code); warnings.push(...styleWarnings); return { errors, warnings }; } /** * 验证类型 */ async validateTypes(code, context) { const errors = []; const warnings = []; // 检查类型声明 const typeErrors = this.findTypeErrors(code); errors.push(...typeErrors); // 检查类型使用 const usageWarnings = this.findTypeUsageWarnings(code); warnings.push(...usageWarnings); return { errors, warnings }; } /** * 验证导入 */ async validateImports(code, context) { const errors = []; const warnings = []; // 检查缺失的导入 const missingImports = this.findMissingImports(code); errors.push(...missingImports); // 检查未使用的导入 const unusedImports = this.findUnusedImports(code); warnings.push(...unusedImports); return { errors, warnings }; } /** * 验证业务逻辑 */ async validateBusinessLogic(code, context) { const errors = []; const warnings = []; // 检查业务逻辑完整性 const businessErrors = this.findBusinessLogicErrors(code); errors.push(...businessErrors); // 检查业务规则 const ruleWarnings = this.findBusinessRuleWarnings(code); warnings.push(...ruleWarnings); return { errors, warnings }; } /** * 验证性能 */ async validatePerformance(code, context) { const errors = []; const warnings = []; // 检查性能问题 const performanceIssues = this.findPerformanceIssues(code); warnings.push(...performanceIssues); return { errors, warnings }; } /** * 验证安全性 */ async validateSecurity(code, context) { const errors = []; const warnings = []; // 检查安全问题 const securityIssues = this.findSecurityIssues(code); errors.push(...securityIssues); return { errors, warnings }; } // 错误检测方法 findBracketErrors(code) { const errors = []; const lines = code.split('\n'); lines.forEach((line, index) => { if (line.includes(']') && !line.includes('[')) { // 检查是否是函数调用中的方括号错误 if (line.match(/\w+\]/)) { errors.push({ type: 'syntax', message: '方括号错误: 应该是圆括号', line: index + 1, code: line.trim(), severity: 'error' }); } } }); return errors; } findPrefixErrors(code) { const errors = []; const lines = code.split('\n'); lines.forEach((line, index) => { if (line.includes('BusinessBusinessException')) { errors.push({ type: 'syntax', message: '重复的Business前缀', line: index + 1, code: line.trim(), severity: 'error' }); } }); return errors; } findSyntaxErrors(code) { const errors = []; const lines = code.split('\n'); lines.forEach((line, index) => { // 检查等号错误 if (line.includes('====')) { errors.push({ type: 'syntax', message: '重复的等号', line: index + 1, code: line.trim(), severity: 'error' }); } // 检查括号不匹配 const openParens = (line.match(/\(/g) || []).length; const closeParens = (line.match(/\)/g) || []).length; const openBrackets = (line.match(/\[/g) || []).length; const closeBrackets = (line.match(/\]/g) || []).length; if (openParens !== closeParens) { errors.push({ type: 'syntax', message: '括号不匹配', line: index + 1, code: line.trim(), severity: 'error' }); } if (openBrackets !== closeBrackets) { errors.push({ type: 'syntax', message: '方括号不匹配', line: index + 1, code: line.trim(), severity: 'error' }); } }); return errors; } findStyleWarnings(code) { const warnings = []; const lines = code.split('\n'); lines.forEach((line, index) => { // 检查行长度 if (line.length > 120) { warnings.push({ type: 'style', message: '行长度超过120字符', line: index + 1, code: line.trim(), severity: 'warning' }); } // 检查尾随空格 if (line.endsWith(' ')) { warnings.push({ type: 'style', message: '尾随空格', line: index + 1, code: line.trim(), severity: 'warning' }); } }); return warnings; } findTypeErrors(code) { const errors = []; // 类型错误检测逻辑 return errors; } findTypeUsageWarnings(code) { const warnings = []; // 类型使用警告检测逻辑 return warnings; } findMissingImports(code) { const errors = []; const lines = code.split('\n'); // 检查使用的类是否已导入 const usedClasses = this.extractUsedClasses(code); const importedClasses = this.extractImportedClasses(code); usedClasses.forEach(className => { if (!importedClasses.includes(className)) { errors.push({ type: 'import', message: `缺失导入: ${className}`, line: -1, code: '', severity: 'error' }); } }); return errors; } findUnusedImports(code) { const warnings = []; // 未使用导入检测逻辑 return warnings; } findBusinessLogicErrors(code) { const errors = []; // 业务逻辑错误检测逻辑 return errors; } findBusinessRuleWarnings(code) { const warnings = []; // 业务规则警告检测逻辑 return warnings; } findPerformanceIssues(code) { const warnings = []; // 性能问题检测逻辑 return warnings; } findSecurityIssues(code) { const errors = []; // 安全问题检测逻辑 return errors; } // 修复方法 async fixSyntaxErrors(code, validation) { let fixedCode = code; const fixes = []; validation.errors.forEach(error => { if (error.message.includes('方括号错误')) { fixedCode = fixedCode.replace(/(\w+)\]/g, '$1)'); fixes.push({ type: 'syntax', description: '修复方括号错误', line: error.line }); } if (error.message.includes('重复的Business前缀')) { fixedCode = fixedCode.replace(/BusinessBusinessException/g, 'BusinessException'); fixes.push({ type: 'syntax', description: '修复重复的Business前缀', line: error.line }); } if (error.message.includes('重复的等号')) { fixedCode = fixedCode.replace(/====/g, '==='); fixes.push({ type: 'syntax', description: '修复重复的等号', line: error.line }); } }); return { code: fixedCode, fixes }; } async fixTypeErrors(code, validation) { let fixedCode = code; const fixes = []; // 类型错误修复逻辑 return { code: fixedCode, fixes }; } async fixImportErrors(code, validation) { let fixedCode = code; const fixes = []; // 导入错误修复逻辑 return { code: fixedCode, fixes }; } async fixBusinessLogicErrors(code, validation) { let fixedCode = code; const fixes = []; // 业务逻辑错误修复逻辑 return { code: fixedCode, fixes }; } // 指标计算方法 calculateComplexity(code, context) { const lines = code.split('\n'); const methods = (code.match(/function\s+\w+/g) || []).length; const conditions = (code.match(/if\s*\(|else\s*if\s*\(|switch\s*\(/g) || []).length; const loops = (code.match(/for\s*\(|while\s*\(|foreach\s*\(/g) || []).length; return { lines: lines.length, methods, conditions, loops, cyclomatic: methods + conditions + loops + 1 }; } calculateMaintainability(code, context) { const complexity = this.calculateComplexity(code, context); const maintainabilityIndex = Math.max(0, 171 - 5.2 * Math.log(complexity.lines) - 0.23 * complexity.cyclomatic); return { index: maintainabilityIndex, rating: maintainabilityIndex > 80 ? 'A' : maintainabilityIndex > 60 ? 'B' : maintainabilityIndex > 40 ? 'C' : 'D' }; } calculateTestability(code, context) { const methods = (code.match(/function\s+\w+/g) || []).length; const dependencies = (code.match(/this\.\w+Service/g) || []).length; return { methods, dependencies, testabilityScore: Math.max(0, 100 - dependencies * 10) }; } calculatePerformance(code, context) { const loops = (code.match(/for\s*\(|while\s*\(|foreach\s*\(/g) || []).length; const asyncCalls = (code.match(/await\s+/g) || []).length; return { loops, asyncCalls, performanceScore: Math.max(0, 100 - loops * 5 - asyncCalls * 2) }; } // 辅助方法 extractUsedClasses(code) { const classes = []; const matches = code.match(/([A-Z][a-zA-Z0-9_]*)/g); if (matches) { classes.push(...matches); } return [...new Set(classes)]; } extractImportedClasses(code) { const imports = []; const matches = code.match(/import\s*\{\s*([^}]+)\s*\}\s*from/g); if (matches) { matches.forEach(match => { const importMatch = match.match(/import\s*\{\s*([^}]+)\s*\}\s*from/); if (importMatch) { const classNames = importMatch[1].split(',').map(name => name.trim()); imports.push(...classNames); } }); } return imports; } generateRecommendations(results) { const recommendations = []; if (results.errors.length > 0) { recommendations.push({ type: 'error', message: '修复所有语法错误以提高代码质量', priority: 'high' }); } if (results.warnings.length > 10) { recommendations.push({ type: 'warning', message: '减少警告数量以提高代码质量', priority: 'medium' }); } if (results.metrics.complexity?.cyclomatic > 10) { recommendations.push({ type: 'complexity', message: '降低代码复杂度以提高可维护性', priority: 'medium' }); } return recommendations; } } module.exports = QualityAssurance;