il2cpp-dump-analyzer-mcp
Version:
Agentic RAG system for analyzing IL2CPP dump.cs files from Unity games
325 lines • 13.3 kB
JavaScript
;
/**
* 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