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