intellify
Version:
Detect JavaScript & TypeScript errors and make codes more optimized.
272 lines (219 loc) ⢠9.81 kB
JavaScript
import chalk from 'chalk';
import boxen from 'boxen';
import path from 'path';
import util from 'util';
function safeInspect(obj, depth = 2) {
return util.inspect(obj, {
depth: depth,
colors: false,
maxArrayLength: 10,
breakLength: 80
});
}
function formatBytes(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
export function displayResults(results, stats) {
try {
console.log(chalk.blue.bold('\n⨠Analysis Complete āØ'));
try {
let statsText = `${chalk.white.bold('š Files:')} ${chalk.white(stats.filesAnalyzed)}\n`;
statsText += `${chalk.white.bold('š Lines:')} ${chalk.white(stats.linesOfCode.toLocaleString())}\n`;
statsText += `${chalk.white.bold('š¾ Size:')} ${chalk.white(formatBytes(stats.totalSize))}`;
if (Object.keys(stats.fileTypes).length > 0) {
statsText += `\n\n${chalk.white.bold('š¼ File Types:')}`;
const sortedTypes = Object.entries(stats.fileTypes)
.sort((a, b) => b[1] - a[1])
.slice(0, 4);
sortedTypes.forEach(([ext, count]) => {
const percent = Math.round((count / stats.filesAnalyzed) * 100);
statsText += `\n ${chalk.white(ext.padEnd(5))} ${chalk.white(count + ' files')} ${chalk.gray(`(${percent}%)`)}`;
});
}
console.log(boxen(statsText, {
title: 'Codebase Stats',
titleAlignment: 'center',
padding: 1,
margin: {top:1, bottom:1},
borderStyle: 'round',
borderColor: 'cyan'
}));
} catch (error) {
console.error('[ERROR] Failed to display stats:', error.message);
}
try {
console.log(chalk.magenta.bold('\nš Issues Found'));
const syntaxErrorsCount = results.syntaxErrors?.length || 0;
const unusedPackagesCount = results.unusedPackages?.length || 0;
const unusedVariablesCount = results.unusedVariables?.length || 0;
const commentsCount = results.comments?.length || 0;
const totalIssues = syntaxErrorsCount + unusedPackagesCount + unusedVariablesCount + commentsCount;
if (totalIssues > 0) {
const barWidth = 40;
const syntaxErrorsWidth = Math.round((syntaxErrorsCount / totalIssues) * barWidth) || 0;
const unusedPackagesWidth = Math.round((unusedPackagesCount / totalIssues) * barWidth) || 0;
const unusedVariablesWidth = Math.round((unusedVariablesCount / totalIssues) * barWidth) || 0;
const commentsWidth = Math.round((commentsCount / totalIssues) * barWidth) || 0;
console.log(
chalk.red('ā'.repeat(syntaxErrorsWidth)) +
chalk.yellow('ā'.repeat(unusedPackagesWidth)) +
chalk.magenta('ā'.repeat(unusedVariablesWidth)) +
chalk.green('ā'.repeat(commentsWidth))
);
console.log(
chalk.red(`Syntax Errors: ${syntaxErrorsCount} `) +
chalk.yellow(`Unused Packages: ${unusedPackagesCount} `) +
chalk.magenta(`Unused Variables: ${unusedVariablesCount} `) +
chalk.green(`Comments: ${commentsCount}`)
);
} else {
console.log(chalk.green('No issues found! Your codebase is clean. ā
'));
}
} catch (error) {
console.error('[ERROR] Failed to display issues summary:', error.message);
}
try {
if (results.analyzedFiles?.length > 0) {
let filesTable = `${chalk.white.bold('Filename'.padEnd(20))} ${chalk.white.bold('Type'.padEnd(8))} ${chalk.white.bold('Size'.padEnd(10))} ${chalk.white.bold('Lines'.padEnd(10))}\n`;
filesTable += chalk.gray('ā'.repeat(50)) + '\n';
const topFiles = [...results.analyzedFiles]
.sort((a, b) => b.size - a.size)
.slice(0, 10);
topFiles.forEach(file => {
const filename = file.name.length > 19 ? file.name.substring(0, 16) + '...' : file.name;
filesTable +=
`${chalk.white(filename.padEnd(20))} ` +
`${chalk.yellow(file.type.padEnd(8))} ` +
`${chalk.cyan(formatBytes(file.size).padEnd(10))} ` +
`${chalk.green(file.lines.toString().padEnd(10))}\n`;
});
console.log(boxen(filesTable, {
title: 'Analyzed Files (Top by size)',
titleAlignment: 'center',
padding: 1,
margin: {top:1, bottom:1},
borderStyle: 'round',
borderColor: 'blue'
}));
}
} catch (error) {
console.error('[ERROR] Failed to display analyzed files:', error.message);
}
try {
if (results.syntaxErrors?.length > 0) {
console.log(chalk.red.bold('\nš„ Syntax Errors:'));
results.syntaxErrors.forEach(error => {
console.log(chalk.red(` ⢠${path.basename(error.file)} (line ${error.line}): ${error.message}`));
});
}
} catch (error) {
console.error('[ERROR] Failed to display syntax errors:', error.message);
}
try {
if (results.unusedPackages?.length > 0) {
console.log(chalk.yellow.bold('\nš¦ Unused Packages:'));
results.unusedPackages.forEach(pkg => {
console.log(chalk.yellow(` ⢠${pkg.name} (${pkg.type})`));
});
}
} catch (error) {
console.error('[ERROR] Failed to display unused packages:', error.message);
}
try {
if (results.unusedVariables?.length > 0) {
console.log(chalk.magenta.bold('\nš Unused Items:'));
const unusedByType = {
variable: [],
import: [],
require: [],
other: []
};
results.unusedVariables.forEach(item => {
if (item.type === 'variable') {
unusedByType.variable.push(item);
} else if (item.type === 'import') {
unusedByType.import.push(item);
} else if (item.type === 'require') {
unusedByType.require.push(item);
} else {
unusedByType.other.push(item);
}
});
if (unusedByType.variable.length > 0) {
console.log(chalk.magenta(' Variables:'));
unusedByType.variable.slice(0, 5).forEach(variable => {
console.log(chalk.magenta(` ⢠${variable.name} in ${path.basename(variable.file)} (line ${variable.line})`));
});
if (unusedByType.variable.length > 5) {
console.log(chalk.magenta(` ... and ${unusedByType.variable.length - 5} more variables`));
}
}
if (unusedByType.import.length > 0) {
console.log(chalk.magenta('\n ES6 Imports:'));
unusedByType.import.slice(0, 5).forEach(item => {
console.log(chalk.magenta(` ⢠${item.name} from '${item.source}' in ${path.basename(item.file)} (line ${item.line})`));
});
if (unusedByType.import.length > 5) {
console.log(chalk.magenta(` ... and ${unusedByType.import.length - 5} more imports`));
}
}
if (unusedByType.require.length > 0) {
console.log(chalk.magenta('\n CommonJS Requires:'));
unusedByType.require.slice(0, 5).forEach(item => {
console.log(chalk.magenta(` ⢠${item.name} from '${item.source}' in ${path.basename(item.file)} (line ${item.line})`));
});
if (unusedByType.require.length > 5) {
console.log(chalk.magenta(` ... and ${unusedByType.require.length - 5} more requires`));
}
}
if (unusedByType.other.length > 0) {
console.log(chalk.magenta('\n Other:'));
unusedByType.other.slice(0, 5).forEach(item => {
console.log(chalk.magenta(` ⢠${item.name} in ${path.basename(item.file)} (line ${item.line})`));
});
if (unusedByType.other.length > 5) {
console.log(chalk.magenta(` ... and ${unusedByType.other.length - 5} more`));
}
}
}
} catch (error) {
console.error('[ERROR] Failed to display unused variables:', error.message);
}
try {
if (results.comments?.length > 0) {
console.log(chalk.green.bold('\nš¬ Comment Lines:'));
console.log(chalk.green(` Found ${results.comments.length} comments across all files`));
const commentsByFile = {};
results.comments.forEach(comment => {
const filename = path.basename(comment.file);
if (!commentsByFile[filename]) {
commentsByFile[filename] = 0;
}
commentsByFile[filename]++;
});
const topCommentFiles = Object.entries(commentsByFile)
.sort((a, b) => b[1] - a[1])
.slice(0, 5);
if (topCommentFiles.length > 0) {
console.log(chalk.green(' Top files with comments:'));
topCommentFiles.forEach(([filename, count]) => {
console.log(chalk.green(` ⢠${filename}: ${count} comments`));
});
}
}
} catch (error) {
console.error('[ERROR] Failed to display comments:', error.message);
}
console.log();
} catch (error) {
console.error('[CRITICAL] displayResults function failed:', error);
console.log('\n⨠Analysis Complete āØ');
console.log('An error occurred while displaying detailed results.');
console.log('An error occurred while analyzing the project.');
}
}
export default displayResults;