UNPKG

il2cpp-dump-analyzer-mcp

Version:

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

325 lines 13.3 kB
"use strict"; /** * Find Cross References Tool Implementation * Analyzes cross-references and usage patterns in IL2CPP code */ Object.defineProperty(exports, "__esModule", { value: true }); exports.findCrossReferencesSchema = exports.FindCrossReferencesToolHandler = void 0; exports.createFindCrossReferencesTool = createFindCrossReferencesTool; const zod_1 = require("zod"); const base_tool_handler_1 = require("../base-tool-handler"); const parameter_validator_1 = require("../../utils/parameter-validator"); /** * Find Cross References Tool Handler * Analyzes cross-references and usage patterns in IL2CPP code */ class FindCrossReferencesToolHandler extends base_tool_handler_1.BaseAnalysisToolHandler { constructor(context) { super({ name: 'find_cross_references', description: 'Find cross-references and usage patterns in IL2CPP code', enableParameterValidation: true, enableResponseFormatting: true }, context); } /** * Validate cross references parameters */ async validateParameters(params) { const errors = []; const warnings = []; const adjustedValues = {}; // Validate target_name parameter if (!params.target_name || typeof params.target_name !== 'string') { errors.push('target_name is required and must be a string'); } else if (params.target_name.trim().length === 0) { errors.push('target_name cannot be empty'); } // Validate target_type parameter const targetTypeValidation = parameter_validator_1.ParameterValidator.validateTargetType(params.target_type); errors.push(...targetTypeValidation.errors); // Validate reference_type parameter if (params.reference_type) { const referenceTypeValidation = parameter_validator_1.ParameterValidator.validateReferenceType(params.reference_type); errors.push(...referenceTypeValidation.errors); } else { adjustedValues.reference_type = 'all'; } // Validate max_results parameter if (params.max_results !== undefined) { adjustedValues.max_results = parameter_validator_1.ParameterValidator.validateMaxResults(params.max_results, 200); if (adjustedValues.max_results !== params.max_results) { warnings.push(`max_results adjusted from ${params.max_results} to ${adjustedValues.max_results} (valid range: 1-200)`); } } else { adjustedValues.max_results = 50; } // Set defaults for optional boolean parameters if (params.include_nested === undefined) { adjustedValues.include_nested = true; } if (params.include_system_types === undefined) { adjustedValues.include_system_types = false; } return { isValid: errors.length === 0, errors, warnings, adjustedValues }; } /** * Execute cross references analysis */ async executeCore(params) { return await this.performAnalysis(async () => { // Step 1: Find the target entity const targetResults = await this.findTargetEntity(params.target_name, params.target_type); if (targetResults.length === 0) { return this.createNotFoundResult(params); } const target = targetResults[0]; this.context.logger.debug(`Searching for references to: ${target.metadata.fullName}`); // Step 2: Search for references const references = await this.searchForReferences(target, params); // Step 3: Build result const result = { target: { name: target.metadata.name, fullName: target.metadata.fullName, type: target.metadata.type, found: true }, references, summary: this.calculateSummary(references, params) }; this.context.logger.debug(`Found ${references.length} cross-references for ${target.metadata.name}`); return result; }); } /** * Find the target entity */ async findTargetEntity(targetName, targetType) { return await this.context.vectorStore.searchWithFilter(targetName, { type: targetType }, 1); } /** * Search for references to the target entity */ async searchForReferences(target, params) { const references = []; const maxResults = params.max_results || 50; // Generate search queries based on the target const searchQueries = this.generateSearchQueries(target); const foundReferences = new Map(); for (const query of searchQueries) { try { const searchResults = await this.context.vectorStore.similaritySearch(query, Math.min(maxResults * 2, 100)); for (const result of searchResults) { // Skip self-references if (result.metadata.fullName === target.metadata.fullName) { continue; } // Skip system types if not included if (!params.include_system_types && this.isSystemType(result.metadata.namespace)) { continue; } const reference = this.createCrossReference(result, target, query, params); if (reference && !foundReferences.has(reference.referencingEntity.fullName)) { foundReferences.set(reference.referencingEntity.fullName, reference); } } if (foundReferences.size >= maxResults) { break; } } catch (error) { this.context.logger.warn(`Search query failed: ${query}`, error); } } return Array.from(foundReferences.values()).slice(0, maxResults); } /** * Generate search queries for finding references */ generateSearchQueries(target) { const targetName = target.metadata.name; const targetFullName = target.metadata.fullName; return [ targetName, targetFullName, `: ${targetName}`, `<${targetName}>`, `${targetName}[]`, `${targetName}(`, `.${targetName}`, `new ${targetName}`, `typeof(${targetName})`, `${targetName}.` ]; } /** * Create a cross reference from a search result */ createCrossReference(result, target, query, params) { try { const referenceType = this.determineReferenceType(result, target, query); // Filter by reference type if specified if (params.reference_type !== 'all' && referenceType !== params.reference_type) { return null; } return { referencingEntity: { name: result.metadata.name, fullName: result.metadata.fullName, namespace: result.metadata.namespace || '', type: result.metadata.type, location: `${result.metadata.namespace || 'global'}.${result.metadata.name}` }, referenceType, context: this.extractContext(result.pageContent, target.metadata.name), confidence: this.calculateConfidence(result, target, query) }; } catch (error) { this.context.logger.warn('Failed to create cross reference', error); return null; } } /** * Determine the type of reference */ determineReferenceType(result, target, query) { if (query.includes('new ')) return 'instantiation'; if (query.includes(': ')) return 'inheritance'; if (query.includes('<') && query.includes('>')) return 'generic_parameter'; if (query.includes('[]')) return 'array_type'; if (query.includes('(')) return 'method_call'; if (query.includes('.')) return 'member_access'; return 'usage'; } /** * Extract context around the reference */ extractContext(content, targetName) { const lines = content.split('\n'); const targetLine = lines.find(line => line.includes(targetName)); return targetLine ? targetLine.trim() : ''; } /** * Calculate confidence score for the reference */ calculateConfidence(result, target, query) { let confidence = 0.5; // Base confidence // Increase confidence for exact matches if (result.pageContent.includes(target.metadata.fullName)) { confidence += 0.3; } // Increase confidence for specific query patterns if (query.includes('new ') || query.includes(': ')) { confidence += 0.2; } return Math.min(confidence, 1.0); } /** * Check if a namespace is a system type */ isSystemType(namespace) { if (!namespace) return false; const systemPrefixes = ['System', 'UnityEngine', 'Unity', 'Microsoft', 'Mono']; return systemPrefixes.some(prefix => namespace.startsWith(prefix)); } /** * Calculate summary statistics */ calculateSummary(references, params) { const referencesByType = {}; const namespaceCount = {}; references.forEach(ref => { // Count by reference type referencesByType[ref.referenceType] = (referencesByType[ref.referenceType] || 0) + 1; // Count by namespace const namespace = ref.referencingEntity.namespace || 'global'; namespaceCount[namespace] = (namespaceCount[namespace] || 0) + 1; }); const topReferencingNamespaces = Object.entries(namespaceCount) .sort(([, a], [, b]) => b - a) .slice(0, 5) .map(([namespace, count]) => ({ namespace, count })); return { totalReferences: references.length, referencesByType, topReferencingNamespaces, analysisMetadata: { searchedTarget: params.target_name, searchedType: params.target_type, referenceType: params.reference_type || 'all', maxResults: params.max_results || 50, includeNested: params.include_nested || true, includeSystemTypes: params.include_system_types || false, timestamp: new Date().toISOString() } }; } /** * Create result for when target is not found */ createNotFoundResult(params) { return { target: { name: params.target_name, fullName: params.target_name, type: params.target_type, found: false }, references: [], summary: { totalReferences: 0, referencesByType: {}, topReferencingNamespaces: [], analysisMetadata: { searchedTarget: params.target_name, searchedType: params.target_type, referenceType: params.reference_type || 'all', maxResults: params.max_results || 50, includeNested: params.include_nested || true, includeSystemTypes: params.include_system_types || false, timestamp: new Date().toISOString() } } }; } } exports.FindCrossReferencesToolHandler = FindCrossReferencesToolHandler; /** * Zod schema for find cross references tool parameters */ exports.findCrossReferencesSchema = zod_1.z.object({ target_name: zod_1.z.string().describe("Exact or partial name of the target entity to find references for"), target_type: zod_1.z.enum(["class", "interface", "enum", "method", "property", "field"]).describe("Type of entity to find references for"), reference_type: zod_1.z.enum(["usage", "inheritance", "implementation", "composition", "all"]).optional().default("all").describe("Type of references to find"), max_results: zod_1.z.number().optional().default(50).describe("Maximum number of references to return (1-200)"), include_nested: zod_1.z.boolean().optional().default(true).describe("Include references within nested types and inner classes"), include_system_types: zod_1.z.boolean().optional().default(false).describe("Include references from Unity/System types") }); /** * Factory function to create and register the find cross references tool */ function createFindCrossReferencesTool(server, context) { const handler = new FindCrossReferencesToolHandler(context); server.tool("find_cross_references", exports.findCrossReferencesSchema, async (params) => { return await handler.execute(params); }); return handler; } //# sourceMappingURL=find-cross-references-tool.js.map