agentsqripts
Version:
Comprehensive static code analysis toolkit for identifying technical debt, security vulnerabilities, performance issues, and code quality problems
144 lines (122 loc) • 4.43 kB
JavaScript
/**
* @file Shared detailed formatter for CLI tools
* @description Provides consistent detailed output formatting across all analysis tools
*/
const path = require('path');
/**
* Create a detailed formatter function with customizable configuration
* @param {Object} config - Formatter configuration
* @param {string} config.title - Title for the detailed output
* @param {Function} config.formatSummary - Function to format summary
* @param {string} config.filesField - Field name for files array
* @param {string} config.issuesField - Field name for issues array
* @param {Function} config.formatIssue - Function to format individual issues
* @param {Function} [config.formatFile] - Optional function to format file info
* @returns {Function} Detailed formatter function
*/
function createDetailedFormatter(config) {
const {
title,
formatSummary,
filesField,
issuesField,
formatIssue,
formatFile
} = config;
return function formatDetailed(results, options = {}) {
let output = '';
// Add summary if available
if (formatSummary) {
output += formatSummary(results, options);
}
// Add detailed section title
if (title) {
output += `\n${title}\n${'='.repeat(title.length)}\n\n`;
}
// Process files if available
if (results[filesField] && Array.isArray(results[filesField])) {
const files = results[filesField];
const maxFiles = options.maxFiles || Infinity; // No display limit by default
files.slice(0, maxFiles).forEach((fileData, index) => {
// Format file header
if (formatFile) {
output += formatFile(fileData, index);
} else {
output += `📄 ${path.relative('.', fileData.file || fileData.filePath)}\n`;
}
// Format issues for this file
if (fileData[issuesField] && Array.isArray(fileData[issuesField])) {
fileData[issuesField].forEach((issue) => {
const formatted = formatIssue(issue);
if (Array.isArray(formatted)) {
formatted.forEach(line => output += line + '\n');
} else {
output += formatted + '\n';
}
});
}
output += '\n';
});
// Show truncation message if needed
if (files.length > maxFiles) {
output += `... and ${files.length - maxFiles} more files (use JSON output for complete details)\n`;
}
}
// Handle single file analysis
else if (results[issuesField] && Array.isArray(results[issuesField])) {
results[issuesField].forEach((issue) => {
const formatted = formatIssue(issue);
if (Array.isArray(formatted)) {
formatted.forEach(line => output += line + '\n');
} else {
output += formatted + '\n';
}
output += '\n';
});
}
return output;
};
}
/**
* Common issue formatter with severity and category icons
* @param {Object} issue - Issue object
* @param {Object} icons - Icon mapping for severity/category
* @returns {Array<string>} Formatted lines
*/
function formatIssueWithIcons(issue, icons = {}) {
const severityIcons = icons.severity || {
'CRITICAL': '🚨',
'HIGH': '🔥',
'MEDIUM': '⚡',
'LOW': '💡'
};
const categoryIcons = icons.category || {};
const severityIcon = severityIcons[issue.severity] || '📌';
const categoryIcon = categoryIcons[issue.category] || '';
const lines = [];
// Main issue line
const mainLine = ` ${severityIcon} ${categoryIcon} ${issue.type || issue.message}`;
if (issue.line) {
lines.push(`${mainLine} (Line ${issue.line})`);
} else {
lines.push(mainLine);
}
// Additional details
if (issue.details || issue.summary) {
lines.push(` 📝 ${issue.details || issue.summary}`);
}
if (issue.recommendation || issue.fix) {
lines.push(` 💡 ${issue.recommendation || issue.fix}`);
}
if (issue.effort !== undefined || issue.impact) {
const effortText = issue.effort ? `Effort: ${issue.effort}/3` : '';
const impactText = issue.impact ? `Impact: ${issue.impact}` : '';
const separator = effortText && impactText ? ' | ' : '';
lines.push(` ⚙️ ${effortText}${separator}${impactText}`);
}
return lines;
}
module.exports = {
createDetailedFormatter,
formatIssueWithIcons
};