UNPKG

sicua

Version:

A tool for analyzing project structure and dependencies

287 lines (286 loc) 10.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ErrorHandler = exports.ErrorCategory = exports.ErrorSeverity = void 0; /** * Error severity levels */ var ErrorSeverity; (function (ErrorSeverity) { ErrorSeverity["LOW"] = "low"; ErrorSeverity["MEDIUM"] = "medium"; ErrorSeverity["HIGH"] = "high"; ErrorSeverity["CRITICAL"] = "critical"; })(ErrorSeverity || (exports.ErrorSeverity = ErrorSeverity = {})); /** * Error categories for function analysis */ var ErrorCategory; (function (ErrorCategory) { ErrorCategory["PARSING"] = "parsing"; ErrorCategory["TYPE_RESOLUTION"] = "type_resolution"; ErrorCategory["AST_TRAVERSAL"] = "ast_traversal"; ErrorCategory["FILE_ACCESS"] = "file_access"; ErrorCategory["FUNCTION_EXTRACTION"] = "function_extraction"; ErrorCategory["CLASSIFICATION"] = "classification"; ErrorCategory["DEPENDENCY_ANALYSIS"] = "dependency_analysis"; })(ErrorCategory || (exports.ErrorCategory = ErrorCategory = {})); /** * Utility class for structured error handling in function analysis */ class ErrorHandler { constructor(config = {}) { this.errors = []; this.defaultFallbacks = { functionName: "Unknown Function", returnType: "unknown", params: [], body: "// Error parsing function body", dependencies: [], calledFunctions: [], isAsync: false, }; this.config = { logErrors: true, throwOnCritical: false, maxErrorsPerFile: 50, includeStackTrace: false, enableRecovery: true, ...config, }; } /** * Safely executes a function with error handling and fallback */ safeExecute(operation, fallbackValue, context, category = ErrorCategory.PARSING, severity = ErrorSeverity.MEDIUM, filePath, functionName) { try { return operation(); } catch (error) { this.handleError(error, context, category, severity, filePath, functionName); return fallbackValue; } } /** * Safely extracts function name with fallback */ safeFunctionName(node, extractor, filePath) { return this.safeExecute(() => extractor(node), this.defaultFallbacks.functionName, "function name extraction", ErrorCategory.FUNCTION_EXTRACTION, ErrorSeverity.LOW, filePath); } /** * Safely extracts return type with fallback */ safeReturnType(node, extractor, filePath, functionName) { return this.safeExecute(() => extractor(node), this.defaultFallbacks.returnType, "return type extraction", ErrorCategory.TYPE_RESOLUTION, ErrorSeverity.LOW, filePath, functionName); } /** * Safely extracts parameters with fallback */ safeParameters(node, extractor, filePath, functionName) { return this.safeExecute(() => extractor(node), this.defaultFallbacks.params, "parameter extraction", ErrorCategory.FUNCTION_EXTRACTION, ErrorSeverity.LOW, filePath, functionName); } /** * Safely extracts function body with fallback */ safeFunctionBody(node, extractor, filePath, functionName) { return this.safeExecute(() => extractor(node), this.defaultFallbacks.body, "function body extraction", ErrorCategory.FUNCTION_EXTRACTION, ErrorSeverity.MEDIUM, filePath, functionName); } /** * Safely extracts dependencies with fallback */ safeDependencies(node, extractor, filePath, functionName) { return this.safeExecute(() => extractor(node), this.defaultFallbacks.dependencies, "dependency extraction", ErrorCategory.DEPENDENCY_ANALYSIS, ErrorSeverity.LOW, filePath, functionName); } /** * Safely extracts called functions with fallback */ safeCalledFunctions(node, extractor, filePath, functionName) { return this.safeExecute(() => extractor(node), this.defaultFallbacks.calledFunctions, "called functions extraction", ErrorCategory.FUNCTION_EXTRACTION, ErrorSeverity.LOW, filePath, functionName); } /** * Safely detects async status with fallback */ safeAsyncDetection(node, detector, filePath, functionName) { return this.safeExecute(() => detector(node), this.defaultFallbacks.isAsync, "async detection", ErrorCategory.FUNCTION_EXTRACTION, ErrorSeverity.LOW, filePath, functionName); } /** * Safely performs classification with fallback */ safeClassification(node, classifier, fallbackValue, filePath, functionName) { return this.safeExecute(() => classifier(node), fallbackValue, "function classification", ErrorCategory.CLASSIFICATION, ErrorSeverity.MEDIUM, filePath, functionName); } /** * Safely traverses AST with error recovery */ safeASTTraversal(node, traverser, fallbackValue, filePath) { return this.safeExecute(() => traverser(node), fallbackValue, "AST traversal", ErrorCategory.AST_TRAVERSAL, ErrorSeverity.HIGH, filePath); } /** * Handles file access errors */ handleFileError(filePath, operation, error) { this.handleError(error, `File ${operation}: ${filePath}`, ErrorCategory.FILE_ACCESS, ErrorSeverity.HIGH, filePath); } /** * Core error handling method */ handleError(error, context, category, severity, filePath, functionName) { const analysisError = { category, severity, message: this.extractErrorMessage(error), context, filePath, functionName, nodeKind: this.extractNodeKind(error), stackTrace: this.config.includeStackTrace ? this.extractStackTrace(error) : undefined, timestamp: new Date(), recoverable: this.config.enableRecovery && severity !== ErrorSeverity.CRITICAL, }; this.errors.push(analysisError); // Log error if configured if (this.config.logErrors) { this.logError(analysisError); } // Check if we should throw on critical errors if (this.config.throwOnCritical && severity === ErrorSeverity.CRITICAL) { throw new Error(`Critical error in ${context}: ${analysisError.message}`); } // Check if we've exceeded max errors per file if (filePath && this.getErrorCountForFile(filePath) > this.config.maxErrorsPerFile) { console.warn(`Max errors exceeded for file: ${filePath}. Some errors may be suppressed.`); } } /** * Extracts error message from various error types */ extractErrorMessage(error) { if (error instanceof Error) { return error.message; } if (typeof error === "string") { return error; } if (error && typeof error === "object" && "message" in error) { return String(error.message); } return "Unknown error occurred"; } /** * Extracts stack trace from error */ extractStackTrace(error) { if (error instanceof Error && error.stack) { return error.stack; } return undefined; } /** * Attempts to extract TypeScript node kind from error context */ extractNodeKind(error) { if (error instanceof Error && error.message.includes("SyntaxKind")) { const match = error.message.match(/SyntaxKind\.(\w+)/); return match ? match[1] : undefined; } return undefined; } /** * Logs error with appropriate level */ logError(error) { const prefix = `[${error.severity.toUpperCase()}] ${error.category}:`; const message = `${prefix} ${error.message} (${error.context})`; const location = error.filePath ? ` in ${error.filePath}` : ""; const functionContext = error.functionName ? ` at function ${error.functionName}` : ""; const fullMessage = `${message}${location}${functionContext}`; switch (error.severity) { case ErrorSeverity.CRITICAL: console.error(fullMessage); break; case ErrorSeverity.HIGH: console.error(fullMessage); break; case ErrorSeverity.MEDIUM: console.warn(fullMessage); break; case ErrorSeverity.LOW: console.log(fullMessage); break; } if (error.stackTrace && error.severity === ErrorSeverity.CRITICAL) { console.error("Stack trace:", error.stackTrace); } } /** * Gets error count for a specific file */ getErrorCountForFile(filePath) { return this.errors.filter((error) => error.filePath === filePath).length; } /** * Gets all errors */ getErrors() { return [...this.errors]; } /** * Gets errors by category */ getErrorsByCategory(category) { return this.errors.filter((error) => error.category === category); } /** * Gets errors by severity */ getErrorsBySeverity(severity) { return this.errors.filter((error) => error.severity === severity); } /** * Gets errors for a specific file */ getErrorsForFile(filePath) { return this.errors.filter((error) => error.filePath === filePath); } /** * Clears all errors */ clearErrors() { this.errors = []; } /** * Gets error summary statistics */ getErrorSummary() { const bySeverity = Object.values(ErrorSeverity).reduce((acc, severity) => { acc[severity] = this.getErrorsBySeverity(severity).length; return acc; }, {}); const byCategory = Object.values(ErrorCategory).reduce((acc, category) => { acc[category] = this.getErrorsByCategory(category).length; return acc; }, {}); const filesWithErrors = new Set(this.errors .filter((error) => error.filePath) .map((error) => error.filePath)).size; return { total: this.errors.length, bySeverity, byCategory, filesWithErrors, }; } /** * Checks if analysis can continue based on error state */ canContinueAnalysis() { const criticalErrors = this.getErrorsBySeverity(ErrorSeverity.CRITICAL).length; const highErrors = this.getErrorsBySeverity(ErrorSeverity.HIGH).length; return criticalErrors === 0 && highErrors < 10; // Configurable threshold } } exports.ErrorHandler = ErrorHandler;