UNPKG

agentsqripts

Version:

Comprehensive static code analysis toolkit for identifying technical debt, security vulnerabilities, performance issues, and code quality problems

165 lines (142 loc) 5.12 kB
/** * @file Contextual performance scorer * @description Provides context-aware scoring for performance issues */ /** * Calculate contextual effort score based on issue characteristics * @param {Object} issue - Performance issue object * @param {string} fileContent - Full file content for context * @returns {number} Contextual effort score (1-5) */ function calculateContextualEffort(issue, fileContent) { let baseEffort = issue.effort || 3; let multiplier = 1; // Check if issue is in a hot path (common function names, event handlers) const hotPathPatterns = [ /render/i, /update/i, /handle/i, /process/i, /calculate/i, /validate/i, /onScroll/i, /onChange/i, /onInput/i ]; const surroundingCode = getSurroundingCode(fileContent, issue.line, 10); const isHotPath = hotPathPatterns.some(pattern => pattern.test(surroundingCode)); if (isHotPath) { multiplier *= 1.5; // Increase effort for hot path issues } // Check if inside a loop or recursive function if (surroundingCode.includes('while') || surroundingCode.includes('for') || surroundingCode.includes('forEach') || surroundingCode.includes('map')) { multiplier *= 1.2; } // Adjust for issue type specifics switch (issue.type) { case 'o_n_squared': // Check approximate data size if (surroundingCode.includes('.length > 1000') || surroundingCode.includes('large')) { multiplier *= 1.3; } break; case 'memory_leak': // Memory leaks in constructors or initialization are worse if (surroundingCode.includes('constructor') || surroundingCode.includes('init')) { multiplier *= 1.4; } break; case 'react_render_issue': // Render issues in frequently updated components are worse if (surroundingCode.includes('interval') || surroundingCode.includes('animation')) { multiplier *= 1.3; } break; } return Math.min(5, Math.round(baseEffort * multiplier)); } /** * Calculate contextual impact score based on issue characteristics * @param {Object} issue - Performance issue object * @param {string} fileContent - Full file content for context * @returns {string} Contextual impact description */ function calculateContextualImpact(issue, fileContent) { const surroundingCode = getSurroundingCode(fileContent, issue.line, 20); switch (issue.type) { case 'o_n_squared': // Estimate data size from context if (surroundingCode.includes('users') || surroundingCode.includes('items') || surroundingCode.includes('records') || surroundingCode.includes('data')) { return '40-80% reduction for large datasets (1000+ items)'; } else if (surroundingCode.includes('config') || surroundingCode.includes('settings') || surroundingCode.includes('options')) { return '10-20% reduction for small datasets'; } break; case 'promise_in_loop': // Check loop size indicators if (surroundingCode.match(/\.length|count|size/)) { return '50-70% faster with Promise.all for 10+ items'; } break; case 'repeated_dom_query': // Check frequency of updates if (surroundingCode.includes('animation') || surroundingCode.includes('interval')) { return '60-90% DOM performance gain in animations'; } else { return '20-40% DOM performance improvement'; } break; } return issue.impact; // Fallback to default impact } /** * Get surrounding code context * @param {string} content - File content * @param {number} lineNumber - Target line number * @param {number} radius - Lines before/after to include * @returns {string} Surrounding code */ function getSurroundingCode(content, lineNumber, radius = 10) { const lines = content.split('\n'); const start = Math.max(0, lineNumber - radius - 1); const end = Math.min(lines.length, lineNumber + radius); return lines.slice(start, end).join('\n'); } /** * Calculate priority score for issue ordering * @param {Object} issue - Performance issue * @param {string} fileContent - File content * @returns {number} Priority score (higher = more important) */ function calculatePriorityScore(issue, fileContent) { let score = 0; // Severity weights const severityWeights = { 'HIGH': 100, 'MEDIUM': 50, 'LOW': 10 }; score += severityWeights[issue.severity] || 50; // Add effort consideration (lower effort = higher priority for quick wins) const contextualEffort = calculateContextualEffort(issue, fileContent); score += (6 - contextualEffort) * 10; // Hot path bonus const surroundingCode = getSurroundingCode(fileContent, issue.line, 10); if (/render|update|handle|process/.test(surroundingCode)) { score += 25; } // Framework-specific issues get priority if (issue.category === 'Framework') { score += 20; } return score; } module.exports = { calculateContextualEffort, calculateContextualImpact, calculatePriorityScore, getSurroundingCode };