UNPKG

refakts

Version:

TypeScript refactoring tool built for AI coding agents to perform precise refactoring operations via command line instead of requiring complete code regeneration.

213 lines 7.47 kB
#!/usr/bin/env node "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const child_process_1 = require("child_process"); const util_1 = require("util"); const comment_detector_1 = require("./comment-detector"); const file_size_checker_1 = require("./file-size-checker"); const git_diff_checker_1 = require("./git-diff-checker"); const change_frequency_checker_1 = require("./change-frequency-checker"); const quality_reporter_1 = require("./quality-reporter"); const cli_generator_1 = require("../cli-generator"); const execAsync = (0, util_1.promisify)(child_process_1.exec); async function runDuplicationCheck() { try { await execAsync('npx jscpd src --threshold 10 --reporters console --silent'); return { hasIssues: false }; } catch (error) { return processDuplicationError(error); } } function processDuplicationError(error) { if (error.stdout && error.stdout.includes('duplications found')) { return { hasIssues: true, message: '👧🏻💬 Code duplication detected. Look for missing abstractions - similar code patterns indicate shared concepts that should be extracted into reusable functions or classes.' }; } return { hasIssues: false }; } async function runComplexityCheck() { try { const { stdout } = await execAsync('npx complexity-report --format json src'); return processComplexityReport(stdout); } catch (error) { return { hasIssues: false }; } } function processComplexityReport(stdout) { const report = JSON.parse(stdout); const issues = analyzeComplexity(report); const messages = createComplexityMessages(issues); return { hasIssues: issues.hasComplexFunctions || issues.hasManyParams, message: messages.join('\n') }; } function analyzeComplexity(report) { const issues = { hasComplexFunctions: false, hasManyParams: false }; for (const file of report.reports || []) { checkFileComplexity(file, issues); } return issues; } function checkFileComplexity(file, issues) { for (const func of file.functions || []) { if (func.complexity && func.complexity.cyclomatic > 5) { issues.hasComplexFunctions = true; } if (func.params && func.params > 2) { issues.hasManyParams = true; } } } function createComplexityMessages(issues) { const messages = []; if (issues.hasComplexFunctions) { messages.push('👧🏻💬 High cyclomatic complexity detected. Break down complex functions into smaller, single-purpose methods.'); } if (issues.hasManyParams) { messages.push('👧🏻💬 Functions with more than 2 parameters detected. Consider using parameter objects to group related parameters.'); } return messages; } async function collectQualityIssues() { const reporter = new quality_reporter_1.QualityReporter(); await addAllIssues(reporter); return [reporter.generateReport()]; } async function addAllIssues(reporter) { await addDuplicationIssues(reporter); await addComplexityIssues(reporter); addCommentIssues(reporter); addFileSizeIssues(reporter); addFunctionSizeIssues(reporter); await addUnusedMethodIssues(reporter); await addDiffSizeIssues(reporter); await addChangeFrequencyIssues(reporter); addIncompleteRefactoringReminder(reporter); } async function addDuplicationIssues(reporter) { const dupResult = await runDuplicationCheck(); if (dupResult.hasIssues && dupResult.message) { reporter.addIssue({ type: 'duplication', message: dupResult.message }); } } async function addComplexityIssues(reporter) { const complexityResult = await runComplexityCheck(); if (complexityResult.hasIssues && complexityResult.message) { reporter.addIssue({ type: 'complexity', message: complexityResult.message }); } } function addCommentIssues(reporter) { const comments = (0, comment_detector_1.findComments)('src'); if (comments.length > 0) { reporter.addIssue({ type: 'comment', message: 'Comments found in codebase' }); } } function addFileSizeIssues(reporter) { const fileSizes = (0, file_size_checker_1.checkFileSizes)('src'); for (const issue of fileSizes) { reporter.addIssue({ type: 'fileSize', severity: issue.severity, message: `${issue.file} has ${issue.lines} lines` }); } } function addFunctionSizeIssues(reporter) { const functionSizes = (0, file_size_checker_1.checkFunctionSizes)('src'); for (const issue of functionSizes) { reporter.addIssue({ type: 'functionSize', severity: issue.severity, message: `Function '${issue.function}' in ${issue.file} has ${issue.lines} lines` }); } } async function addUnusedMethodIssues(reporter) { try { const unusedMembers = await getUnusedClassMembers(); addUnusedMemberIssues(unusedMembers, reporter); } catch (error) { } } async function getUnusedClassMembers() { const { stdout } = await execAsync('npx knip --include classMembers --reporter json'); const results = JSON.parse(stdout); return results.issues?.classMembers || []; } function addUnusedMemberIssues(unusedMembers, reporter) { for (const member of unusedMembers) { reporter.addIssue({ type: 'unusedMethod', severity: 'critical', message: `Unused method '${member.name}' in ${member.file}` }); } } async function addDiffSizeIssues(reporter) { const diffResult = await (0, git_diff_checker_1.checkGitDiffSize)(); if (diffResult.message) { reporter.addIssue({ type: 'diffSize', message: diffResult.message.replace('👧🏻💬 ', '') }); } } async function addChangeFrequencyIssues(reporter) { const changeIssues = await (0, change_frequency_checker_1.checkChangeFrequency)(); processChangeIssues(changeIssues, reporter); } function processChangeIssues(changeIssues, reporter) { for (const issue of changeIssues) { const issueType = classifyChangeIssue(issue); reporter.addIssue({ type: issueType, message: issue }); } } function classifyChangeIssue(issue) { return issue.includes('change together') ? 'cohesiveChange' : 'changeFrequency'; } function addIncompleteRefactoringReminder(reporter) { const incompleteRefactorings = (0, cli_generator_1.getIncompleteRefactorings)(); if (incompleteRefactorings.length > 0) { const refactoringList = incompleteRefactorings.join(', '); reporter.addIssue({ type: 'incompleteRefactoring', message: `Consider if any incomplete refactorings should be marked complete: ${refactoringList}` }); } } function reportResults(messages) { if (messages.length === 1 && messages[0].includes('✅ All quality checks passed')) { console.log(messages[0]); process.exit(0); } else { console.log(messages[0]); process.exit(1); } } async function main() { const messages = await collectQualityIssues(); reportResults(messages); } if (require.main === module) { main().catch(console.error); } //# sourceMappingURL=quality-check.js.map