UNPKG

il2cpp-dump-analyzer-mcp

Version:

Agentic RAG system for analyzing IL2CPP dump.cs files from Unity games

377 lines 17.5 kB
"use strict"; /** * Find Design Patterns Tool Implementation * Detects common design patterns in IL2CPP code with confidence scoring */ Object.defineProperty(exports, "__esModule", { value: true }); exports.findDesignPatternsSchema = exports.FindDesignPatternsToolHandler = void 0; exports.createFindDesignPatternsTool = createFindDesignPatternsTool; const zod_1 = require("zod"); const base_tool_handler_1 = require("../base-tool-handler"); const parameter_validator_1 = require("../../utils/parameter-validator"); const mcp_response_formatter_1 = require("../../utils/mcp-response-formatter"); /** * Find Design Patterns Tool Handler * Detects common design patterns in IL2CPP code with confidence scoring */ class FindDesignPatternsToolHandler extends base_tool_handler_1.BaseAnalysisToolHandler { constructor(context) { super({ name: 'find_design_patterns', description: 'Detect common design patterns in IL2CPP code', enableParameterValidation: true, enableResponseFormatting: true }, context); } /** * Validate design patterns parameters */ async validateParameters(params) { const errors = []; const warnings = []; const adjustedValues = {}; // Validate pattern_types parameter const patternValidation = parameter_validator_1.ParameterValidator.validatePatternTypes(params.pattern_types); errors.push(...patternValidation.errors); warnings.push(...patternValidation.warnings); // Validate confidence_threshold parameter if (params.confidence_threshold !== undefined) { adjustedValues.confidence_threshold = parameter_validator_1.ParameterValidator.validateConfidence(params.confidence_threshold); if (adjustedValues.confidence_threshold !== params.confidence_threshold) { warnings.push(`Confidence threshold adjusted from ${params.confidence_threshold} to ${adjustedValues.confidence_threshold} (valid range: 0.1-1.0)`); } } else { adjustedValues.confidence_threshold = 0.7; } // Validate max_results_per_pattern parameter if (params.max_results_per_pattern !== undefined) { adjustedValues.max_results_per_pattern = parameter_validator_1.ParameterValidator.validateMaxResults(params.max_results_per_pattern, 50); if (adjustedValues.max_results_per_pattern !== params.max_results_per_pattern) { warnings.push(`max_results_per_pattern adjusted from ${params.max_results_per_pattern} to ${adjustedValues.max_results_per_pattern} (valid range: 1-50)`); } } else { adjustedValues.max_results_per_pattern = 10; } // Set defaults for optional boolean parameters if (params.include_partial_matches === undefined) { adjustedValues.include_partial_matches = true; } if (params.exclude_unity_patterns === undefined) { adjustedValues.exclude_unity_patterns = false; } return { isValid: errors.length === 0, errors, warnings, adjustedValues }; } /** * Execute design pattern detection */ async executeCore(params) { return await this.performAnalysis(async () => { this.context.logger.debug(`Detecting patterns: [${params.pattern_types.join(', ')}], confidence: ${params.confidence_threshold}`); // Step 1: Get all classes for analysis const filter = { type: 'class' }; if (params.namespace_scope) { filter.namespace = params.namespace_scope; } const allClassesResults = await this.context.vectorStore.searchWithFilter('', filter, 500); // Step 2: Initialize result const result = { detectedPatterns: {}, summary: { totalPatternsFound: 0, patternTypeCount: 0, averageConfidence: 0, architecturalInsights: [] }, metadata: { searchedPatterns: params.pattern_types, confidenceThreshold: params.confidence_threshold || 0.7, includePartialMatches: params.include_partial_matches || true, namespaceScope: params.namespace_scope, excludeUnityPatterns: params.exclude_unity_patterns || false, maxResultsPerPattern: params.max_results_per_pattern || 10, timestamp: new Date().toISOString() } }; // Step 3: Detect each pattern type for (const patternType of params.pattern_types) { try { this.context.logger.debug(`Detecting ${patternType} pattern...`); let matches = await this.detectPattern(patternType, allClassesResults, params); // Filter by confidence threshold matches = matches.filter(match => match.confidence >= (params.confidence_threshold || 0.7)); // Filter Unity patterns if excluded if (params.exclude_unity_patterns) { matches = matches.filter(match => !match.isUnitySpecific); } // Filter partial matches if not included if (!params.include_partial_matches) { matches = matches.filter(match => !match.isPartialMatch); } result.detectedPatterns[patternType] = matches.slice(0, params.max_results_per_pattern || 10); this.context.logger.debug(`Found ${matches.length} ${patternType} pattern matches`); } catch (patternError) { this.context.logger.error(`Error detecting ${patternType} pattern:`, patternError); result.detectedPatterns[patternType] = []; } } // Step 4: Calculate summary result.summary = this.calculatePatternSummary(result); return result; }); } /** * Detect a specific design pattern */ async detectPattern(patternType, classes, params) { switch (patternType) { case 'singleton': return this.detectSingleton(classes); case 'observer': return this.detectObserver(classes); case 'factory': return this.detectFactory(classes); case 'strategy': return this.detectStrategy(classes); case 'command': return this.detectCommand(classes); default: this.context.logger.warn(`Pattern detection not implemented for: ${patternType}`); return []; } } /** * Detect Singleton pattern */ async detectSingleton(classes) { const matches = []; for (const classDoc of classes) { const content = classDoc.pageContent.toLowerCase(); const className = classDoc.metadata.name; let confidence = 0; const evidence = []; const suggestions = []; // Check for static instance field const hasStaticInstance = content.includes('static') && (content.includes('instance') || content.includes(className.toLowerCase())); if (hasStaticInstance) { confidence += 0.4; evidence.push('Has static instance field'); } // Check for private constructor const hasPrivateConstructor = content.includes('private') && content.includes('constructor'); if (hasPrivateConstructor) { confidence += 0.3; evidence.push('Has private constructor'); } else { suggestions.push('Consider making constructor private'); } // Check for GetInstance method const hasGetInstanceMethod = content.includes('getinstance') || content.includes('get_instance'); if (hasGetInstanceMethod) { confidence += 0.3; evidence.push('Has GetInstance method'); } else if (confidence > 0.3) { suggestions.push('Add public static GetInstance() method'); } // Unity-specific check const isUnity = classDoc.metadata.isMonoBehaviour || (classDoc.metadata.namespace && classDoc.metadata.namespace.includes('Unity')); if (confidence >= 0.3) { matches.push({ className, fullName: classDoc.metadata.fullName, namespace: classDoc.metadata.namespace || '', confidence, evidence, implementation: confidence >= 0.8 ? 'full' : 'partial', isPartialMatch: confidence < 0.8, suggestions: suggestions.concat(confidence < 0.8 ? ['Ensure thread safety for multi-threaded environments'] : []), isUnitySpecific: isUnity }); } } return matches; } /** * Detect Observer pattern */ async detectObserver(classes) { const matches = []; for (const classDoc of classes) { const content = classDoc.pageContent.toLowerCase(); const className = classDoc.metadata.name; let confidence = 0; const evidence = []; // Check for event/delegate patterns if (content.includes('event') || content.includes('delegate')) { confidence += 0.4; evidence.push('Uses events or delegates'); } // Check for observer-like method names if (content.includes('notify') || content.includes('update') || content.includes('observe')) { confidence += 0.3; evidence.push('Has observer-pattern method names'); } // Check for list of observers if (content.includes('list') && (content.includes('observer') || content.includes('listener'))) { confidence += 0.3; evidence.push('Maintains list of observers'); } const isUnity = classDoc.metadata.isMonoBehaviour || (classDoc.metadata.namespace && classDoc.metadata.namespace.includes('Unity')); if (confidence >= 0.3) { matches.push({ className, fullName: classDoc.metadata.fullName, namespace: classDoc.metadata.namespace || '', confidence, evidence, implementation: confidence >= 0.8 ? 'full' : 'partial', isPartialMatch: confidence < 0.8, suggestions: ['Consider implementing IObserver interface', 'Add proper event handling'], isUnitySpecific: isUnity }); } } return matches; } /** * Detect Factory pattern */ async detectFactory(classes) { const matches = []; for (const classDoc of classes) { const content = classDoc.pageContent.toLowerCase(); const className = classDoc.metadata.name; let confidence = 0; const evidence = []; // Check for factory method names if (content.includes('create') || content.includes('make') || content.includes('build')) { confidence += 0.3; evidence.push('Has factory method names'); } // Check for factory in class name if (className.toLowerCase().includes('factory')) { confidence += 0.4; evidence.push('Class name indicates factory pattern'); } // Check for static creation methods if (content.includes('static') && (content.includes('create') || content.includes('make'))) { confidence += 0.3; evidence.push('Has static creation methods'); } const isUnity = classDoc.metadata.isMonoBehaviour || (classDoc.metadata.namespace && classDoc.metadata.namespace.includes('Unity')); if (confidence >= 0.3) { matches.push({ className, fullName: classDoc.metadata.fullName, namespace: classDoc.metadata.namespace || '', confidence, evidence, implementation: confidence >= 0.8 ? 'full' : 'partial', isPartialMatch: confidence < 0.8, suggestions: ['Consider implementing abstract factory interface'], isUnitySpecific: isUnity }); } } return matches; } /** * Detect Strategy pattern */ async detectStrategy(classes) { // Simplified strategy pattern detection return []; } /** * Detect Command pattern */ async detectCommand(classes) { // Simplified command pattern detection return []; } /** * Calculate pattern summary statistics */ calculatePatternSummary(result) { const allMatches = Object.values(result.detectedPatterns).flat(); const totalPatternsFound = allMatches.length; const patternTypeCount = Object.keys(result.detectedPatterns).filter(pattern => result.detectedPatterns[pattern].length > 0).length; const averageConfidence = totalPatternsFound > 0 ? allMatches.reduce((sum, match) => sum + match.confidence, 0) / totalPatternsFound : 0; const architecturalInsights = this.generateArchitecturalInsights(result.detectedPatterns); return { totalPatternsFound, patternTypeCount, averageConfidence, architecturalInsights }; } /** * Generate architectural insights based on detected patterns */ generateArchitecturalInsights(detectedPatterns) { const insights = []; if (detectedPatterns.singleton && detectedPatterns.singleton.length > 0) { insights.push('Codebase uses Singleton pattern for global state management'); } if (detectedPatterns.observer && detectedPatterns.observer.length > 0) { insights.push('Event-driven architecture detected with Observer pattern usage'); } if (detectedPatterns.factory && detectedPatterns.factory.length > 0) { insights.push('Object creation is abstracted using Factory patterns'); } if (insights.length === 0) { insights.push('No significant design patterns detected with the specified criteria'); insights.push('Consider lowering the confidence threshold or enabling partial matches'); insights.push('The codebase may use different architectural patterns not covered by this analysis'); } return insights; } /** * Format pattern detection results */ formatResponse(result, warnings = []) { let response = mcp_response_formatter_1.MCPResponseFormatter.formatPatternResults(result.detectedPatterns, result.summary, result.metadata); if (warnings.length > 0) { response = mcp_response_formatter_1.MCPResponseFormatter.addWarnings(response, warnings); } return mcp_response_formatter_1.MCPResponseFormatter.addExecutionTiming(response, this.startTime, this.config.name); } } exports.FindDesignPatternsToolHandler = FindDesignPatternsToolHandler; /** * Zod schema for find design patterns tool parameters */ exports.findDesignPatternsSchema = zod_1.z.object({ pattern_types: zod_1.z.array(zod_1.z.enum(["singleton", "observer", "factory", "strategy", "command", "state", "decorator", "adapter", "facade", "proxy", "builder", "template_method", "chain_of_responsibility", "mediator", "memento", "visitor", "flyweight", "composite", "bridge", "abstract_factory", "prototype", "iterator"])).describe("Array of design patterns to detect"), confidence_threshold: zod_1.z.number().optional().default(0.7).describe("Minimum confidence level (0.1-1.0)"), include_partial_matches: zod_1.z.boolean().optional().default(true).describe("Include partial pattern implementations"), namespace_scope: zod_1.z.string().optional().describe("Limit search to specific namespace pattern"), exclude_unity_patterns: zod_1.z.boolean().optional().default(false).describe("Exclude Unity-specific pattern implementations"), max_results_per_pattern: zod_1.z.number().optional().default(10).describe("Maximum results per pattern type (1-50)") }); /** * Factory function to create and register the find design patterns tool */ function createFindDesignPatternsTool(server, context) { const handler = new FindDesignPatternsToolHandler(context); server.tool("find_design_patterns", exports.findDesignPatternsSchema, async (params) => { return await handler.execute(params); }); return handler; } //# sourceMappingURL=find-design-patterns-tool.js.map