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
JavaScript
;
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