UNPKG

ds-sfcoe-ailabs

Version:

AI-powered code review tool with static analysis integration for comprehensive code quality assessment.

138 lines (137 loc) 5.28 kB
import { JS_PATTERNS, TEST_PATTERNS } from './constants.js'; import { FileUtils } from './fileUtils.js'; /** * Utility class for analyzing code content and detecting patterns * Provides methods for JavaScript anti-pattern detection, test framework validation, * and general code analysis across different file types * * @example * ```typescript * // Analyze JavaScript content for anti-patterns * const entries = CodeAnalysisUtils.analyzeJavaScriptContent('app.js', jsContent, new Set()); * * // Check for old test framework usage * const hasOldFramework = CodeAnalysisUtils.hasOldTestFramework(apexContent); * * // Extract class name from file path * const className = CodeAnalysisUtils.extractClassName('MyClass.cls'); * ``` */ export class CodeAnalysisUtils { /** * Check if content contains any JavaScript anti-patterns * * @param fileName - The name of the file being analyzed * @param content - The file content to analyze for JavaScript patterns * @param addedEntries - Set of already processed entry keys to avoid duplicates * @returns Array of table entries for JavaScript anti-patterns found * @example * ```typescript * const entries = CodeAnalysisUtils.analyzeJavaScriptContent('app.js', 'var x = 1;', new Set()); * console.log(entries.length); // Number of anti-patterns found * ``` */ static analyzeJavaScriptContent(fileName, content, addedEntries) { const entries = []; const shortFileName = FileUtils.getFileName(fileName); const className = FileUtils.removeExtension(shortFileName); for (const patternInfo of JS_PATTERNS) { if (content.includes(patternInfo.pattern)) { const entryKey = `${className}-${patternInfo.ruleId}`; if (!addedEntries.has(entryKey)) { entries.push({ className: shortFileName, lineNumber: 1, ruleType: patternInfo.ruleType, issue: patternInfo.issue, suggestedFix: patternInfo.suggestedFix, }); addedEntries.add(entryKey); } } } return entries; } /** * Check if file uses old test framework patterns * * @param content - The file content to analyze * @returns True if the file uses old test framework (no new framework patterns found) * @example * ```typescript * const hasOldFramework = CodeAnalysisUtils.hasOldTestFramework('Test.startTest();'); * console.log(hasOldFramework); // true * ``` */ static hasOldTestFramework(content) { return ![ TEST_PATTERNS.SOBJECT_MOCKER, TEST_PATTERNS.CLASS_MOCKER, TEST_PATTERNS.GENERATE_MOCK_SOBJECT, ].some((pattern) => content.includes(pattern)); } /** * Check if content contains specific pattern * * @param content - The content to search in * @param pattern - The pattern to search for * @returns True if the pattern is found in the content * @example * ```typescript * const hasPattern = CodeAnalysisUtils.containsPattern('var x = 1;', 'var'); * console.log(hasPattern); // true * ``` */ static containsPattern(content, pattern) { return content.includes(pattern); } /** * Extract class name from file path or content * * @param filePath - The file path to extract class name from * @returns The class name extracted from the file path (without extension) * @example * ```typescript * const className = CodeAnalysisUtils.extractClassName('/path/to/MyClass.cls'); * console.log(className); // 'MyClass' * ``` */ static extractClassName(filePath) { const fileName = FileUtils.getFileName(filePath); return FileUtils.removeExtension(fileName); } /** * Check if file is a test file based on filename or content * * @param filePath - The file path to check * @param content - Optional file content to check for test annotations * @returns True if the file is identified as a test file * @example * ```typescript * const isTest = CodeAnalysisUtils.isTestFile('MyTest.cls', '@isTest class MyTest {}'); * console.log(isTest); // true * ``` */ static isTestFile(filePath, content) { return FileUtils.isTestFile(filePath, content); } /** * Create entry key for deduplication * * @param fileName - The name of the file * @param ruleId - The rule identifier * @param lineNumber - Optional line number where the issue occurs * @returns A unique key string for deduplication purposes * @example * ```typescript * const key1 = CodeAnalysisUtils.createEntryKey('MyClass.cls', 'no-var'); * // Returns: 'MyClass.cls-no-var' * * const key2 = CodeAnalysisUtils.createEntryKey('MyClass.cls', 'no-var', 42); * // Returns: 'MyClass.cls-no-var-42' * ``` */ static createEntryKey(fileName, ruleId, lineNumber) { return `${fileName}-${ruleId}${lineNumber !== undefined ? `-${lineNumber}` : ''}`; } }