UNPKG

il2cpp-dump-analyzer-mcp

Version:

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

270 lines 11.9 kB
"use strict"; /** * Analyze Dependencies Tool Implementation * Performs comprehensive dependency analysis for IL2CPP classes */ Object.defineProperty(exports, "__esModule", { value: true }); exports.analyzeDependenciesSchema = exports.AnalyzeDependenciesToolHandler = void 0; exports.createAnalyzeDependenciesTool = createAnalyzeDependenciesTool; 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"); /** * Analyze Dependencies Tool Handler * Performs comprehensive dependency mapping and analysis for IL2CPP classes */ class AnalyzeDependenciesToolHandler extends base_tool_handler_1.BaseAnalysisToolHandler { constructor(context) { super({ name: 'analyze_dependencies', description: 'Analyze class dependencies and relationships', enableParameterValidation: true, enableResponseFormatting: true }, context); } /** * Validate dependency analysis parameters */ async validateParameters(params) { const errors = []; const warnings = []; const adjustedValues = {}; // Validate class_name parameter const classNameValidation = parameter_validator_1.ParameterValidator.validateClassName(params.class_name); errors.push(...classNameValidation.errors); warnings.push(...classNameValidation.warnings); // Validate analysis_type parameter const validAnalysisTypes = ['incoming', 'outgoing', 'bidirectional', 'circular']; if (params.analysis_type && !validAnalysisTypes.includes(params.analysis_type)) { errors.push(`analysis_type must be one of: ${validAnalysisTypes.join(', ')}`); } else if (!params.analysis_type) { adjustedValues.analysis_type = 'bidirectional'; } // Validate depth parameter if (params.depth !== undefined) { adjustedValues.depth = parameter_validator_1.ParameterValidator.validateDepth(params.depth); if (adjustedValues.depth !== params.depth) { warnings.push(`Depth adjusted from ${params.depth} to ${adjustedValues.depth} (valid range: 1-5)`); } } else { adjustedValues.depth = 3; } // Validate include_system_types parameter if (params.include_system_types === undefined) { adjustedValues.include_system_types = false; } return { isValid: errors.length === 0, errors, warnings, adjustedValues }; } /** * Execute dependency analysis */ async executeCore(params) { return await this.performAnalysis(async () => { // Step 1: Find the target class const classResults = await this.context.vectorStore.searchWithFilter(params.class_name, { type: 'class' }, 1); if (classResults.length === 0) { throw new Error(`Class '${params.class_name}' not found in the IL2CPP dump.`); } const targetClass = classResults[0]; const targetClassName = targetClass.metadata.name; const targetFullName = targetClass.metadata.fullName; this.context.logger.debug(`Analyzing dependencies for class: ${targetClassName} (${targetFullName})`); // Step 2: Initialize analysis result const result = { targetClass: { name: targetClassName, fullName: targetFullName, namespace: targetClass.metadata.namespace || '' }, incomingDependencies: [], outgoingDependencies: [], circularDependencies: [], metrics: { totalIncoming: 0, totalOutgoing: 0, systemTypeCount: 0, userTypeCount: 0, couplingScore: 0, maxDepthReached: 0 }, analysisMetadata: { analysisType: params.analysis_type || 'bidirectional', requestedDepth: params.depth || 3, actualDepth: params.depth || 3, includeSystemTypes: params.include_system_types || false, timestamp: new Date().toISOString() } }; // Step 3: Analyze dependencies based on type if (params.analysis_type === 'outgoing' || params.analysis_type === 'bidirectional') { result.outgoingDependencies = await this.analyzeOutgoingDependencies(targetClass, params.depth || 3, params.include_system_types || false); } if (params.analysis_type === 'incoming' || params.analysis_type === 'bidirectional') { result.incomingDependencies = await this.analyzeIncomingDependencies(targetClassName, params.depth || 3, params.include_system_types || false); } if (params.analysis_type === 'circular') { result.circularDependencies = await this.detectCircularDependencies(targetClassName, params.depth || 3); } // Step 4: Calculate metrics result.metrics = this.calculateDependencyMetrics(result); return result; }); } /** * Analyze outgoing dependencies (what this class depends on) */ async analyzeOutgoingDependencies(targetClass, depth, includeSystemTypes) { const dependencies = []; const visited = new Set(); // Helper function to check if a type is a system type const isSystemType = (typeName) => { if (!typeName) return false; const systemPrefixes = ['System.', 'UnityEngine.', 'Unity.', 'Microsoft.', 'Mono.']; return systemPrefixes.some(prefix => typeName.startsWith(prefix)); }; // Helper function to extract type name from complex type strings const extractTypeName = (typeStr) => { if (!typeStr) return ''; return typeStr.replace(/[<>\[\]]/g, '').split(',')[0].trim(); }; // Analyze inheritance dependencies if (targetClass.metadata.baseClass) { const baseClassName = extractTypeName(targetClass.metadata.baseClass); if (!isSystemType(baseClassName) || includeSystemTypes) { dependencies.push({ name: baseClassName, fullName: baseClassName, namespace: '', type: 'class', relationship: 'inheritance', depth: 1, isSystemType: isSystemType(baseClassName) }); } } // Analyze interface dependencies if (targetClass.metadata.interfaces) { targetClass.metadata.interfaces.forEach((iface) => { const ifaceName = extractTypeName(iface); if (!isSystemType(ifaceName) || includeSystemTypes) { dependencies.push({ name: ifaceName, fullName: ifaceName, namespace: '', type: 'interface', relationship: 'interface', depth: 1, isSystemType: isSystemType(ifaceName) }); } }); } // Analyze field type dependencies if (targetClass.metadata.fields) { targetClass.metadata.fields.forEach((field) => { const fieldTypeName = extractTypeName(field.type); if (!isSystemType(fieldTypeName) || includeSystemTypes) { dependencies.push({ name: fieldTypeName, fullName: fieldTypeName, namespace: '', type: 'class', relationship: 'field', depth: 1, isSystemType: isSystemType(fieldTypeName) }); } }); } return dependencies; } /** * Analyze incoming dependencies (what depends on this class) */ async analyzeIncomingDependencies(targetClassName, depth, includeSystemTypes) { const dependencies = []; // Search for classes that inherit from this class const inheritanceResults = await this.context.vectorStore.searchWithFilter(targetClassName, { baseClass: targetClassName }, 50); inheritanceResults.forEach(doc => { dependencies.push({ name: doc.metadata.name, fullName: doc.metadata.fullName, namespace: doc.metadata.namespace || '', type: 'class', relationship: 'inheritance', depth: 1, isSystemType: false }); }); return dependencies; } /** * Detect circular dependencies */ async detectCircularDependencies(targetClassName, depth) { // Simplified circular dependency detection // In a full implementation, this would traverse the dependency graph return []; } /** * Calculate dependency metrics */ calculateDependencyMetrics(result) { const totalIncoming = result.incomingDependencies.length; const totalOutgoing = result.outgoingDependencies.length; const allDeps = [...result.incomingDependencies, ...result.outgoingDependencies]; const systemTypeCount = allDeps.filter(dep => dep.isSystemType).length; const userTypeCount = allDeps.filter(dep => !dep.isSystemType).length; // Simple coupling score calculation const couplingScore = Math.min((totalIncoming + totalOutgoing) / 10, 1.0); const maxDepthReached = Math.max(...allDeps.map(dep => dep.depth), 0); return { totalIncoming, totalOutgoing, systemTypeCount, userTypeCount, couplingScore, maxDepthReached }; } /** * Handle class not found error specifically */ handleError(error, params) { if (error.message && error.message.includes('not found')) { return mcp_response_formatter_1.MCPResponseFormatter.formatNotFoundResponse(params?.class_name || 'unknown', 'Class'); } return super.handleError(error, params); } } exports.AnalyzeDependenciesToolHandler = AnalyzeDependenciesToolHandler; /** * Zod schema for analyze dependencies tool parameters */ exports.analyzeDependenciesSchema = zod_1.z.object({ class_name: zod_1.z.string().describe("Target class to analyze dependencies for"), analysis_type: zod_1.z.enum(["incoming", "outgoing", "bidirectional", "circular"]).optional().default("bidirectional").describe("Type of dependency analysis to perform"), depth: zod_1.z.number().optional().default(3).describe("How deep to traverse dependency chains (1-5)"), include_system_types: zod_1.z.boolean().optional().default(false).describe("Include Unity/System dependencies in analysis") }); /** * Factory function to create and register the analyze dependencies tool */ function createAnalyzeDependenciesTool(server, context) { const handler = new AnalyzeDependenciesToolHandler(context); server.tool("analyze_dependencies", exports.analyzeDependenciesSchema, async (params) => { return await handler.execute(params); }); return handler; } //# sourceMappingURL=analyze-dependencies-tool.js.map