UNPKG

ds-sfcoe-ailabs

Version:

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

130 lines (129 loc) 4.39 kB
import * as path from 'node:path'; import { TEST_PATTERNS, LAST_EXTENSION_REGEX } from './constants.js'; /** * File utility functions for common operations */ export class FileUtils { /** * Extract filename from a file path * * @param filePath - The file path to extract the filename from * @returns The filename (including extension) or the original path if no path separators * @example * ```typescript * const fileName = FileUtils.getFileName('/path/to/file.js'); * console.log(fileName); // 'file.js' * ``` */ static getFileName(filePath) { return filePath.split('/').pop() ?? filePath; } /** * Get file extension from a file path * * @param filePath - The file path to extract the extension from * @returns The file extension in lowercase (including the dot) * @example * ```typescript * const extension = FileUtils.getFileExtension('file.js'); * console.log(extension); // '.js' * ``` */ static getFileExtension(filePath) { return path.extname(filePath).toLowerCase(); } /** * Check if a file is a JavaScript/TypeScript file * * @param filePath - The file path to check * @returns True if the file is a JavaScript/TypeScript file * @example * ```typescript * const isJs = FileUtils.isJavaScriptFile('app.js'); * console.log(isJs); // true * ``` */ static isJavaScriptFile(filePath) { const extension = this.getFileExtension(filePath); return /\.(js|ts|mjs|cjs)$/i.test(extension); } /** * Check if a file is an Apex file * * @param filePath - The file path to check * @returns True if the file is an Apex class or trigger file * @example * ```typescript * const isApex = FileUtils.isApexFile('MyClass.cls'); * console.log(isApex); // true * ``` */ static isApexFile(filePath) { const extension = this.getFileExtension(filePath); return extension === '.cls' || extension === '.trigger'; } /** * Check if a file is a test file based on filename or content * * @param filePath - The file path to check * @param content - Optional file content to analyze for test annotations * @returns True if the file is identified as a test file * @example * ```typescript * const isTest = FileUtils.isTestFile('MyTest.cls', 'public class MyTest { @isTest void test() {} }'); * console.log(isTest); // true * ``` */ static isTestFile(filePath, content) { const fileName = this.getFileName(filePath); const isTestFileName = fileName .toLowerCase() .includes(TEST_PATTERNS.TEST_FILE_PATTERN); const hasTestAnnotation = content?.includes(TEST_PATTERNS.APEX_TEST_ANNOTATION) ?? false; return isTestFileName || hasTestAnnotation; } /** * Normalize file path for consistent comparison * * @param filePath - The file path to normalize * @returns The normalized file path with forward slashes * @example * ```typescript * const normalized = FileUtils.normalizePath('src\\file.js'); * console.log(normalized); // 'src/file.js' * ``` */ static normalizePath(filePath) { return path.normalize(filePath); } /** * Create a unique entry key for deduplication * * @param fileName - The name of the file * @param ruleId - The rule identifier * @param lineNumber - The line number where the issue occurs * @returns A unique string key for the entry * @example * ```typescript * const key = FileUtils.createEntryKey('file.js', 'no-unused-vars', 42); * console.log(key); // 'file.js-no-unused-vars-42' * ``` */ static createEntryKey(fileName, ruleId, lineNumber) { return `${fileName}-${ruleId}-${lineNumber}`; } /** * Remove file extension from filename * * @param fileName - The filename to process * @returns The filename without its extension * @example * ```typescript * const nameWithoutExt = FileUtils.removeExtension('file.js'); * console.log(nameWithoutExt); // 'file' * ``` */ static removeExtension(fileName) { return fileName.replace(LAST_EXTENSION_REGEX, ''); } }