agentsqripts
Version:
Comprehensive static code analysis toolkit for identifying technical debt, security vulnerabilities, performance issues, and code quality problems
253 lines (234 loc) • 10.9 kB
JavaScript
/**
* @file Execution context detector for context-aware scalability analysis and targeted guidance
* @description Single responsibility: Detect execution context to provide appropriate scalability recommendations
*
* This detector analyzes code patterns, imports, and structure to determine the execution
* context (CLI tool, web server, library, etc.) enabling context-appropriate scalability
* analysis. Different execution contexts have different scalability requirements and acceptable
* patterns, making context detection essential for accurate analysis and relevant recommendations.
*
* Design rationale:
* - Context-aware analysis prevents inappropriate scalability warnings for different application types
* - Pattern-based detection efficiently identifies execution context through code characteristics
* - Multi-factor analysis considers imports, patterns, and file structure for accurate classification
* - Flexible detection supports diverse JavaScript application architectures and frameworks
* - Context information enables targeted recommendations for specific deployment scenarios
*
* Context detection scope:
* - CLI tool detection: Command-line utilities with different scalability requirements
* - Web server identification: Express, Koa, and other web framework applications
* - Library module detection: Reusable modules with library-specific patterns
* - Background service identification: Worker processes and background job handlers
* - Batch processing detection: Data processing scripts with different performance characteristics
*/
/**
* Detects the execution context of a file
* @param {string} content - File content
* @param {string} filePath - Path to the file
* @returns {Object} Context information
*/
function detectExecutionContext(content, filePath) {
const context = {
type: 'unknown',
confidence: 0,
indicators: [],
isCLI: false,
isServer: false,
isLibrary: false,
isTest: false,
isFrontend: false
};
// Weighted scoring system for context detection
let cliScore = 0;
let serverScore = 0;
let libraryScore = 0;
let testScore = 0;
let frontendScore = 0;
// CLI indicators
if (content.startsWith('#!/usr/bin/env node')) {
cliScore += 8;
context.indicators.push('shebang');
}
if (filePath.includes('/bin/') || filePath.includes('\\bin\\')) {
cliScore += 6;
context.indicators.push('bin directory');
}
if (content.includes('process.exit')) {
cliScore += 4;
context.indicators.push('process.exit');
}
if (content.includes('process.argv')) {
cliScore += 3;
context.indicators.push('process.argv');
}
if (content.includes('commander') || content.includes('yargs')) {
cliScore += 3;
context.indicators.push('CLI argument parser');
}
if (filePath.includes('/cli/') || filePath.includes('\\cli\\')) {
cliScore += 5;
context.indicators.push('cli directory');
}
// Frontend/React indicators (check BEFORE server to avoid conflicts)
if (content.includes('import React') || content.includes('from \'react\'') || content.includes('from "react"')) {
frontendScore += 8;
context.indicators.push('React imports');
}
if (content.includes('useState') || content.includes('useEffect') || content.includes('Component')) {
frontendScore += 6;
context.indicators.push('React hooks/components');
}
if (content.includes('BrowserRouter') || content.includes('Routes') || content.includes('Route')) {
frontendScore += 5;
context.indicators.push('React Router');
}
if (filePath.includes('/client/') || filePath.includes('/frontend/') || filePath.includes('/src/components/')) {
frontendScore += 4;
context.indicators.push('frontend directory');
}
if (content.includes('JSX') || content.includes('jsx') || filePath.endsWith('.jsx') || filePath.endsWith('.tsx')) {
frontendScore += 3;
context.indicators.push('JSX/TSX');
}
// Server indicators
if (content.includes('app.listen') || content.includes('server.listen')) {
serverScore += 8;
context.indicators.push('server.listen');
}
if (content.includes('express()') || content.includes('fastify()')) {
serverScore += 6;
context.indicators.push('web framework');
}
if (content.includes('req.') && content.includes('res.')) {
serverScore += 5;
context.indicators.push('request/response handling');
}
if (content.includes('middleware') || content.includes('router')) {
serverScore += 4;
context.indicators.push('middleware/routing');
}
if (content.includes('cors') || content.includes('helmet')) {
serverScore += 3;
context.indicators.push('web security middleware');
}
// Server filename indicators (ONLY if not frontend)
if (frontendScore === 0 && (filePath.includes('server.js') || filePath.includes('/server/app.js') || filePath.includes('/api/index.js'))) {
serverScore += 3;
context.indicators.push('server filename');
}
if (filePath.includes('/routes/') || filePath.includes('/api/')) {
serverScore += 4;
context.indicators.push('server directory');
}
// Library indicators
if (content.includes('module.exports') && !content.includes('#!/usr/bin/env')) {
libraryScore += 3;
context.indicators.push('module.exports');
}
if (filePath.includes('/lib/') || filePath.includes('\\lib\\')) {
libraryScore += 4;
context.indicators.push('lib directory');
}
if (content.includes('function ') && !content.includes('main(') && !content.includes('process.exit')) {
libraryScore += 2;
context.indicators.push('function definitions');
}
// Test indicators
if (filePath.includes('test') || filePath.includes('spec') || filePath.includes('__tests__')) {
testScore += 6;
context.indicators.push('test file path');
}
if (content.includes('describe(') || content.includes('it(') || content.includes('test(')) {
testScore += 5;
context.indicators.push('test functions');
}
if (content.includes('expect(') || content.includes('assert')) {
testScore += 3;
context.indicators.push('test assertions');
}
// Determine primary context
const scores = { cli: cliScore, server: serverScore, library: libraryScore, test: testScore, frontend: frontendScore };
const maxScore = Math.max(cliScore, serverScore, libraryScore, testScore, frontendScore);
if (maxScore === 0) {
context.type = 'unknown';
context.confidence = 0;
} else if (testScore === maxScore) {
context.type = 'test';
context.isTest = true;
context.confidence = Math.min(testScore / 10, 1);
} else if (frontendScore === maxScore) {
context.type = 'frontend';
context.isFrontend = true;
context.confidence = Math.min(frontendScore / 15, 1);
} else if (cliScore === maxScore) {
context.type = 'cli';
context.isCLI = true;
context.confidence = Math.min(cliScore / 15, 1);
} else if (serverScore === maxScore) {
context.type = 'server';
context.isServer = true;
context.confidence = Math.min(serverScore / 15, 1);
} else {
context.type = 'library';
context.isLibrary = true;
context.confidence = Math.min(libraryScore / 10, 1);
}
context.scores = scores;
return context;
}
/**
* Gets scalability concerns relevant to the execution context
* @param {Object} context - Context information from detectExecutionContext
* @returns {Object} Context-specific scalability guidance
*/
function getContextualScalabilityConcerns(context) {
const concerns = {
blockingOperations: { severity: 'LOW', relevant: false },
memoryGrowth: { severity: 'LOW', relevant: false },
cpuIntensiveOperations: { severity: 'LOW', relevant: false },
databaseConnections: { severity: 'LOW', relevant: false }
};
switch (context.type) {
case 'server':
concerns.blockingOperations = { severity: 'HIGH', relevant: true, reason: 'Blocks event loop, hurts concurrent users' };
concerns.memoryGrowth = { severity: 'HIGH', relevant: true, reason: 'Can cause OOM crashes under load' };
concerns.cpuIntensiveOperations = { severity: 'HIGH', relevant: true, reason: 'Blocks event loop, causes timeouts' };
concerns.databaseConnections = { severity: 'HIGH', relevant: true, reason: 'Connection exhaustion under load' };
break;
case 'frontend':
concerns.blockingOperations = { severity: 'LOW', relevant: false, reason: 'Frontend code runs in browser context' };
concerns.memoryGrowth = { severity: 'MEDIUM', relevant: true, reason: 'Memory leaks affect user experience' };
concerns.cpuIntensiveOperations = { severity: 'MEDIUM', relevant: true, reason: 'Can cause UI freezing and poor UX' };
concerns.databaseConnections = { severity: 'LOW', relevant: false, reason: 'Frontend typically uses APIs not direct DB' };
break;
case 'cli':
concerns.blockingOperations = { severity: 'LOW', relevant: false, reason: 'CLI tools run once and exit' };
concerns.memoryGrowth = { severity: 'MEDIUM', relevant: true, reason: 'May hit memory limits on large datasets' };
concerns.cpuIntensiveOperations = { severity: 'LOW', relevant: false, reason: 'Expected for analysis tools' };
concerns.databaseConnections = { severity: 'MEDIUM', relevant: true, reason: 'Should clean up connections' };
break;
case 'library':
concerns.blockingOperations = { severity: 'MEDIUM', relevant: true, reason: 'Depends on usage context' };
concerns.memoryGrowth = { severity: 'MEDIUM', relevant: true, reason: 'Could affect consumers' };
concerns.cpuIntensiveOperations = { severity: 'MEDIUM', relevant: true, reason: 'May block consumers' };
concerns.databaseConnections = { severity: 'MEDIUM', relevant: true, reason: 'Consumer may not handle properly' };
break;
case 'test':
concerns.blockingOperations = { severity: 'LOW', relevant: false, reason: 'Tests run in isolation' };
concerns.memoryGrowth = { severity: 'LOW', relevant: false, reason: 'Test scope is limited' };
concerns.cpuIntensiveOperations = { severity: 'LOW', relevant: false, reason: 'Tests need thorough validation' };
concerns.databaseConnections = { severity: 'MEDIUM', relevant: true, reason: 'Should clean up after tests' };
break;
default:
// Unknown context - be conservative
concerns.blockingOperations = { severity: 'MEDIUM', relevant: true, reason: 'Context unclear' };
concerns.memoryGrowth = { severity: 'MEDIUM', relevant: true, reason: 'Context unclear' };
concerns.cpuIntensiveOperations = { severity: 'MEDIUM', relevant: true, reason: 'Context unclear' };
concerns.databaseConnections = { severity: 'MEDIUM', relevant: true, reason: 'Context unclear' };
}
return concerns;
}
module.exports = {
detectExecutionContext,
getContextualScalabilityConcerns
};