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