ds-sfcoe-ailabs
Version:
AI-powered code review tool with static analysis integration for comprehensive code quality assessment.
224 lines (223 loc) • 8.19 kB
JavaScript
import { FileUtils } from './fileUtils.js';
import { CodeAnalysisUtils } from './codeAnalysisUtils.js';
import { RuleUtils } from './ruleUtils.js';
import { DOCUSIGN_SPECIFIC_ISSUES } from './constants.js';
/**
* Utility class for Docusign-specific code analysis rules
*
* Provides specialized rule checking for DocuSign's coding standards
* including test framework validation, performance patterns, and
* transaction logging requirements.
*
* @example
* ```typescript
* const issues = DocuSignRuleUtils.getDocuSignIssuesForFile(
* 'MyClass.cls',
* 'public class MyClass { ... }',
* true
* );
* console.log(issues.length); // Number of DocuSign-specific issues found
* ```
*/
export class DocuSignRuleUtils {
/**
* Check if file uses old test framework
*
* @param content - The file content to analyze
* @returns True if the file uses old test framework patterns
* @example
* ```typescript
* const hasOldFramework = DocuSignRuleUtils.hasOldTestFramework(apexContent);
* if (hasOldFramework) {
* console.log('File uses deprecated test framework');
* }
* ```
*/
static hasOldTestFramework(content) {
return CodeAnalysisUtils.hasOldTestFramework(content);
}
/**
* Check if file uses Schema.getGlobalDescribe()
*
* @param content - The file content to analyze
* @returns Array of Docusign issues found related to Schema.getGlobalDescribe() usage
* @example
* ```typescript
* const issues = DocuSignRuleUtils.hasGlobalDescribeUsage(apexContent);
* issues.forEach(issue => {
* console.log(`Line ${issue.lineNumber}: ${issue.issue}`);
* });
* ```
*/
static hasGlobalDescribeUsage(content) {
const issues = [];
if (content?.toLowerCase().includes('getglobaldescribe()')) {
const lines = content.split('\n');
for (let i = 0; i < lines.length; i++) {
if (lines[i]?.toLocaleLowerCase().includes('getglobaldescribe()')) {
issues.push({
lineNumber: i + 1,
ruleType: DOCUSIGN_SPECIFIC_ISSUES.GLOBAL_DESCRIBE_USAGE.ruleType,
issue: DOCUSIGN_SPECIFIC_ISSUES.GLOBAL_DESCRIBE_USAGE.issue,
});
}
}
}
return issues;
}
/**
* Check if an Apex class references TransactionLogger
*
* @param content - The file content to analyze
* @returns True if the content references TransactionLogger
* @example
* ```typescript
* const hasLogger = DocuSignRuleUtils.hasTransactionLoggerReference(apexContent);
* if (!hasLogger) {
* console.log('TransactionLogger reference missing');
* }
* ```
*/
static hasTransactionLoggerReference(content) {
if (!content)
return false;
// Check for TransactionLogger references
const transactionLoggerPatterns = [
/= new TransactionLogger\(\)/i,
/=new TransactionLogger\(\)/i,
];
return transactionLoggerPatterns.some((pattern) => pattern.test(content));
}
/**
* Check if an Apex class is a new file and missing TransactionLogger reference
*
* @param filePath - The path of the file being analyzed
* @param content - The content of the file to analyze
* @param isNewFile - Whether this is a new file (added in commit)
* @returns Array of Docusign issues if TransactionLogger is missing from new Apex class
* @example
* ```typescript
* const issues = DocuSignRuleUtils.checkTransactionLoggerInNewApexClass(
* 'MyController.cls',
* apexContent,
* true
* );
* if (issues.length > 0) {
* console.log('New Apex class missing TransactionLogger');
* }
* ```
*/
static checkTransactionLoggerInNewApexClass(filePath, content, isNewFile) {
const issues = [];
// Only check new Apex classes
if (!isNewFile || !FileUtils.isApexFile(filePath)) {
return issues;
}
// Skip test files and interfaces
if (FileUtils.isTestFile(filePath, content) ||
content.includes('interface ') ||
content.includes(' interface ')) {
return issues;
}
// Check if the file contains a class definition
const classDefinitionRegex = /\b(public|private|global)?\s*class\s+\w+/i;
if (!classDefinitionRegex.test(content)) {
return issues;
}
// Check if TransactionLogger is referenced
if (!this.hasTransactionLoggerReference(content)) {
issues.push({
lineNumber: 1,
ruleType: DOCUSIGN_SPECIFIC_ISSUES.TRANSACTION_LOGGER_MISSING.ruleType,
issue: DOCUSIGN_SPECIFIC_ISSUES.TRANSACTION_LOGGER_MISSING.issue,
});
}
return issues;
}
/**
* Get Docusign issues for a specific file
*
* @param filePath - The path of the file being analyzed
* @param content - The content of the file to analyze
* @param isNewFile - Whether this is a new file (optional, defaults to false)
* @returns Array of Docusign-specific issues found in the file
* @example
* ```typescript
* const issues = DocuSignRuleUtils.getDocuSignIssuesForFile(
* 'MyClass.cls',
* apexContent,
* true
* );
* console.log(`Found ${issues.length} DocuSign-specific issues`);
* ```
*/
static getDocuSignIssuesForFile(filePath, content, isNewFile = false) {
const issues = [];
// Test framework check
if (FileUtils.isTestFile(filePath, content) &&
this.hasOldTestFramework(content)) {
issues.push({
lineNumber: 1,
ruleType: DOCUSIGN_SPECIFIC_ISSUES.TEST_FRAMEWORK.ruleType,
issue: DOCUSIGN_SPECIFIC_ISSUES.TEST_FRAMEWORK.issue,
});
}
// Schema.getGlobalDescribe check
issues.push(...this.hasGlobalDescribeUsage(content));
// TransactionLogger check for new Apex classes
issues.push(...this.checkTransactionLoggerInNewApexClass(filePath, content, isNewFile));
return issues;
}
/**
* Create JavaScript-specific table entries for common issues
*
* @param fileName - The name of the JavaScript file being analyzed
* @param content - The content of the file to analyze
* @param addedEntries - Set of already processed entry keys to avoid duplicates
* @returns Array of table entries for JavaScript-specific issues found
* @example
* ```typescript
* const entries = DocuSignRuleUtils.createJavaScriptTableEntries(
* 'app.js',
* jsContent,
* new Set()
* );
* console.log(`Created ${entries.length} table entries`);
* ```
*/
static createJavaScriptTableEntries(fileName, content, addedEntries) {
return CodeAnalysisUtils.analyzeJavaScriptContent(fileName, content, addedEntries);
}
/**
* Extract rule type from hint ruleId
*
* @param ruleId - The rule identifier to extract type from
* @returns The rule type category
* @example
* ```typescript
* const ruleType = DocuSignRuleUtils.extractRuleType('SF_SOQL_IN_LOOP');
* console.log(ruleType); // 'SOQL_IN_LOOP'
* ```
*/
static extractRuleType(ruleId) {
return RuleUtils.extractRuleType(ruleId);
}
/**
* Get suggested fix for JavaScript rules
*
* @param ruleId - The rule identifier to get fix for
* @param message - The rule message for context
* @returns Suggested fix description for the rule
* @example
* ```typescript
* const fix = DocuSignRuleUtils.getSuggestedFixForJavaScript(
* 'no-unused-vars',
* 'Variable is declared but never used'
* );
* console.log(fix); // Suggested fix for the rule
* ```
*/
static getSuggestedFixForJavaScript(ruleId, message) {
return RuleUtils.getSuggestedFix(ruleId, message);
}
}