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.

172 lines 5.31 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.checkChangeFrequency = checkChangeFrequency; const child_process_1 = require("child_process"); const util_1 = require("util"); const execAsync = (0, util_1.promisify)(child_process_1.exec); async function checkChangeFrequency() { return await analyzeChangePatterns(); } async function analyzeChangePatterns() { try { return await collectAllChangeIssues(); } catch (error) { warnAboutAnalysisFailure(); return []; } } async function collectAllChangeIssues() { const frequentFiles = await findFrequentlyChangedFiles(); const cohesiveChanges = await findCohesiveChanges(); return [...frequentFiles, ...cohesiveChanges]; } function warnAboutAnalysisFailure() { console.warn('Warning: Could not analyze git history for change frequency'); } async function findFrequentlyChangedFiles() { try { const changeData = await getFileChangeData(); return analyzeFileChangeFrequency(changeData); } catch (error) { return []; } } async function getFileChangeData() { const { stdout } = await execAsync('git log -100 --name-only --pretty=format: | sort | uniq -c | sort -nr'); return stdout.trim().split('\n').filter(line => line.trim()); } function analyzeFileChangeFrequency(lines) { const issues = []; for (const line of lines) { const changeInfo = parseChangeCountLine(line); if (changeInfo && shouldReportFile(changeInfo)) { issues.push(createFrequencyWarning(changeInfo)); } } return issues; } function parseChangeCountLine(line) { const match = line.trim().match(/^(\d+)\s+(.+)$/); if (match) { return { count: parseInt(match[1]), fileName: match[2] }; } return null; } function shouldReportFile(changeInfo) { return changeInfo.fileName.startsWith('src/') && changeInfo.fileName.endsWith('.ts') && changeInfo.count >= 5; } function createFrequencyWarning(changeInfo) { return `${changeInfo.fileName} changed ${changeInfo.count} times in last 100 commits`; } async function findCohesiveChanges() { try { const commitData = await getCommitData(); return analyzeCohesiveChanges(commitData); } catch (error) { return []; } } async function getCommitData() { const { stdout } = await execAsync('git log -100 --name-only --pretty=format:"%H" | awk "NF"'); const lines = stdout.trim().split('\n'); return parseCommitData(lines); } function parseCommitData(lines) { const parser = createCommitParser(); return processLines(lines, parser); } function createCommitParser() { return { commitData: [], currentCommit: '', currentFiles: [] }; } function processLines(lines, parser) { for (const line of lines) { processLine(line, parser); } parser.commitData.push(...saveCurrentCommit(parser.currentCommit, parser.currentFiles)); return parser.commitData; } function processLine(line, parser) { if (isCommitHash(line)) { parser.commitData.push(...saveCurrentCommit(parser.currentCommit, parser.currentFiles)); parser.currentCommit = line; parser.currentFiles = []; } else if (isRelevantFile(line)) { parser.currentFiles.push(line); } } function isCommitHash(line) { return line.match(/^[a-f0-9]{40}$/) !== null; } function isRelevantFile(line) { return line.startsWith('src/') && line.endsWith('.ts'); } function saveCurrentCommit(commit, files) { if (commit && files.length > 0) { return [{ commit, files }]; } return []; } function analyzeCohesiveChanges(commitData) { const filePairs = findFrequentFilePairs(commitData); const issues = []; for (const [files, count] of filePairs) { if (count >= 3) { issues.push(createCohesionWarning(files, count)); } } return issues; } function createCohesionWarning(files, count) { return `[${files.join(', ')}] change together ${count} times`; } function findFrequentFilePairs(commitData) { const pairCounts = countFilePairs(commitData); return convertPairCountsToMap(pairCounts); } function countFilePairs(commitData) { const pairCounts = new Map(); for (const commit of commitData) { if (commit.files.length >= 2) { const pairs = generateFilePairs(commit.files); recordPairs(pairs, pairCounts); } } return pairCounts; } function generateFilePairs(files) { const sortedFiles = files.sort(); const pairs = []; for (let i = 0; i < sortedFiles.length; i++) { for (let j = i + 1; j < sortedFiles.length; j++) { pairs.push(`${sortedFiles[i]}|${sortedFiles[j]}`); } } return pairs; } function recordPairs(pairs, pairCounts) { for (const pairKey of pairs) { pairCounts.set(pairKey, (pairCounts.get(pairKey) || 0) + 1); } } function convertPairCountsToMap(pairCounts) { const result = new Map(); for (const [pairKey, count] of pairCounts) { const files = pairKey.split('|'); result.set(files, count); } return result; } //# sourceMappingURL=change-frequency-checker.js.map