UNPKG

agentsqripts

Version:

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

101 lines (88 loc) 3.68 kB
/** * @file Extract semantic blocks from JavaScript code using AST * @description Single responsibility: Main orchestrator for AST-based code block extraction */ const { parseAST } = require('../../../utils/astHelpers'); const walk = require('acorn-walk'); const createBlockFromNode = require('./createBlockFromNode'); const isReactComponent = require('./isReactComponent'); const extractFallbackBlocks = require('./extractFallbackBlocks'); /** * Extract semantic blocks from JavaScript code using AST * @param {string} content - File content * @param {string} filePath - File path for context * @returns {Array} Array of semantic code blocks */ function extractSemanticBlocks(content, filePath) { const blocks = []; try { // Parse with loose mode to handle various JS patterns const ast = parseAST(content, { allowImportExportEverywhere: true, allowAwaitOutsideFunction: true, locations: true, ranges: true }); // Extract different types of semantic blocks walk.simple(ast, { // Regular functions FunctionDeclaration(node) { blocks.push(createBlockFromNode(node, content, 'function', filePath)); }, // Arrow functions and function expressions assigned to variables VariableDeclarator(node) { if (node.init && (node.init.type === 'FunctionExpression' || node.init.type === 'ArrowFunctionExpression')) { blocks.push(createBlockFromNode(node, content, 'function', filePath)); } // Object methods pattern: const obj = { method() {} } else if (node.init && node.init.type === 'ObjectExpression') { node.init.properties.forEach(prop => { if (prop.value && (prop.value.type === 'FunctionExpression' || prop.value.type === 'ArrowFunctionExpression')) { blocks.push(createBlockFromNode(prop, content, 'method', filePath)); } }); } }, // Class declarations ClassDeclaration(node) { blocks.push(createBlockFromNode(node, content, 'class', filePath)); // Extract class methods separately for granular analysis node.body.body.forEach(method => { if (method.type === 'MethodDefinition') { blocks.push(createBlockFromNode(method, content, 'classMethod', filePath)); } }); }, // Object methods: obj.method = function() {} AssignmentExpression(node) { if (node.right && (node.right.type === 'FunctionExpression' || node.right.type === 'ArrowFunctionExpression')) { blocks.push(createBlockFromNode(node, content, 'function', filePath)); } }, // Export statements with functions ExportNamedDeclaration(node) { if (node.declaration) { if (node.declaration.type === 'FunctionDeclaration') { blocks.push(createBlockFromNode(node.declaration, content, 'function', filePath)); } else if (node.declaration.type === 'ClassDeclaration') { blocks.push(createBlockFromNode(node.declaration, content, 'class', filePath)); } } }, // React components (functional) CallExpression(node) { if (isReactComponent(node)) { blocks.push(createBlockFromNode(node, content, 'reactComponent', filePath)); } } }); } catch (error) { // If AST parsing fails, fall back to regex-based extraction for specific patterns blocks.push(...extractFallbackBlocks(content, filePath)); } return blocks; } module.exports = extractSemanticBlocks;