agentsqripts
Version:
Comprehensive static code analysis toolkit for identifying technical debt, security vulnerabilities, performance issues, and code quality problems
96 lines (79 loc) • 3.08 kB
JavaScript
/**
* @file Duplicate grouping logic
* @description Responsible for grouping duplicate and similar blocks
*/
const { calculateSimilarity } = require('./similarityCalculator');
const { calculateEstimatedSavings } = require('./savingsCalculator');
const { WET_CODE_CONFIG, WET_PATTERNS } = require('./wetCodeConfig');
/**
* Groups duplicate and similar blocks
* @param {Array} allBlocks - All blocks from all files
* @returns {Array} Grouped duplicates with metadata
*/
function groupDuplicateBlocks(allBlocks) {
const groups = [];
const processed = new Set();
for (let i = 0; i < allBlocks.length; i++) {
if (processed.has(i)) continue;
const currentBlock = allBlocks[i];
const group = {
type: 'exact_duplicate',
blocks: [currentBlock],
similarity: 1.0,
pattern: WET_PATTERNS['exact_duplicate'],
hash: currentBlock.hash,
complexity: currentBlock.complexity,
deduplicationOpportunity: 'HIGH'
};
// Find exact duplicates first
for (let j = i + 1; j < allBlocks.length; j++) {
if (processed.has(j)) continue;
const otherBlock = allBlocks[j];
if (currentBlock.hash === otherBlock.hash &&
currentBlock.content === otherBlock.content) {
group.blocks.push(otherBlock);
processed.add(j);
}
}
// If no exact duplicates, look for similar blocks
if (group.blocks.length === 1) {
for (let j = i + 1; j < allBlocks.length; j++) {
if (processed.has(j)) continue;
const otherBlock = allBlocks[j];
const similarity = calculateSimilarity(currentBlock.content, otherBlock.content);
if (similarity >= WET_CODE_CONFIG.minSimilarityThreshold) {
if (group.blocks.length === 1) {
// Convert to similar logic group
group.type = 'similar_logic';
group.pattern = WET_PATTERNS['similar_logic'];
group.similarity = similarity;
}
group.blocks.push(otherBlock);
processed.add(j);
}
}
}
// Only include groups with multiple blocks or high complexity single blocks
if (group.blocks.length > 1 ||
(group.blocks.length === 1 && currentBlock.complexity >= WET_CODE_CONFIG.minComplexityScore)) {
// Determine deduplication opportunity
if (group.blocks.length > 1) {
const filesInvolved = new Set(group.blocks.map(b => b.file)).size;
group.deduplicationOpportunity = filesInvolved > 2 ? 'HIGH' :
group.blocks.length > 3 ? 'HIGH' : 'MEDIUM';
group.estimatedSavings = calculateEstimatedSavings(group);
}
groups.push(group);
}
processed.add(i);
}
return groups.sort((a, b) => {
// Sort by impact: more blocks and higher complexity first
const scoreA = a.blocks.length * a.complexity;
const scoreB = b.blocks.length * b.complexity;
return scoreB - scoreA;
});
}
module.exports = {
groupDuplicateBlocks
};