UNPKG

agentsqripts

Version:

Comprehensive static code analysis toolkit for identifying technical debt, security vulnerabilities, performance issues, and code quality problems

116 lines (106 loc) 4.86 kB
/** * @file Barrel file detection for module organization analysis * @description Single responsibility: Identify files that primarily re-export other modules * * This module detects "barrel files" - files that exist solely to re-export other modules * for convenient importing. While barrel files serve legitimate organizational purposes, * excessive use can indicate architectural issues or unnecessary indirection. This analysis * helps identify optimization opportunities in module structure. * * Design rationale: * - Ratio-based detection balances legitimate barrels vs architectural issues * - Content analysis excludes comments and formatting for accurate assessment * - File path context prevents false positives on legitimate index files * - Conservative thresholds minimize false identification of utility modules */ /** * Identify barrel files using content ratio analysis with contextual filtering * * Technical function: Ratio-based barrel file detection with path-aware exclusions * * Implementation rationale: * - Export/import ratio analysis identifies primary file purpose * - Comment filtering ensures accurate code content assessment * - Path-based exclusions prevent false positives on legitimate index files * - Conservative thresholds (80% exports, <3 other lines) balance precision and recall * * Barrel file characteristics: * - High ratio of export/import statements to other code * - Minimal business logic or implementation details * - Primary purpose is module aggregation and re-export * - Common patterns: export * from, export { } from, module.exports = require() * * Detection algorithm: * - Filter out comments and empty lines for accurate analysis * - Count export/import statements vs other meaningful code lines * - Apply ratio threshold (>80% exports) with absolute limit (<3 other lines) * - Exclude legitimate organizational files (index.js in lib directories) * * Legitimate barrel file patterns: * - Public API aggregation in library index files * - Feature module consolidation for clean imports * - Framework adapter pattern implementations * - Plugin or extension registration modules * * Problematic barrel file indicators: * - Deep nesting of barrel files creating import chains * - Single-export barrels that don't provide aggregation value * - Circular dependencies introduced through barrel indirection * - Performance impact from unnecessary module resolution * * Path exclusion strategy: * - index.js files in lib/ directories often serve legitimate aggregation purposes * - Non-JavaScript files excluded to prevent type errors * - Main entry points identified by conventional naming patterns * - Allow-list approach for known architectural patterns * * @param {string} content - File content to analyze for barrel characteristics * @param {string} filePath - File path for contextual exclusion logic * @returns {boolean} True if file appears to be primarily a barrel/re-export file * @example * const isBarrel = isBarrelFile(` * export { UserService } from './user.js'; * export { AuthService } from './auth.js'; * export { DataService } from './data.js'; * `, 'src/services/index.js'); * // Returns: true (100% exports, minimal other code) */ function isBarrelFile(content, filePath) { if (!content || typeof content !== 'string') return false; // Skip non-JS files and certain patterns if (!filePath.match(/\.(js|ts|jsx|tsx)$/)) return false; if (filePath.includes('index.') && filePath.includes('/lib/')) return false; // Main exports const allLines = content.split('\n'); const lines = []; for (let i = 0; i < allLines.length; i++) { const trimmed = allLines[i].trim(); if (trimmed.length > 0 && !trimmed.startsWith('//') && !trimmed.startsWith('/*')) { lines.push(trimmed); } } if (lines.length === 0) return false; // Count export/import lines vs other code let exportImportLines = 0; let otherCodeLines = 0; for (let i = 0; i < lines.length; i++) { let line = lines[i]; // Remove block comments if (line.includes('/*') && line.includes('*/')) { line = line.replace(/\/\*.*?\*\//g, '').trim(); } if (!line) continue; if (line.startsWith('export') || line.startsWith('import') || line.startsWith('const') && line.includes('require(') || line.startsWith('module.exports')) { exportImportLines++; } else if (!line.startsWith('//') && line !== '{' && line !== '}' && line !== ';') { otherCodeLines++; } } // File is a barrel if it's mostly exports/imports with minimal other code const totalLines = exportImportLines + otherCodeLines; return totalLines > 0 && (exportImportLines / totalLines) > 0.8 && otherCodeLines < 3; } module.exports = { isBarrelFile };