il2cpp-dump-analyzer-mcp
Version:
Agentic RAG system for analyzing IL2CPP dump.cs files from Unity games
215 lines • 9.59 kB
JavaScript
;
/**
* C# Method Stub Generator for IL2CPP methods
* Generates C# method stubs from IL2CPP method definitions with proper signatures and documentation
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.MethodStubGenerator = void 0;
const types_1 = require("./types");
const base_generator_1 = require("./base-generator");
/**
* Generator for C# method stubs from IL2CPP method definitions
*/
class MethodStubGenerator extends base_generator_1.BaseGenerator {
/**
* Validate the generation request for method stub generation
* @param request Code generation request
* @returns Validation result
*/
async validateRequest(request) {
const errors = [];
const warnings = [];
// Check if request type is correct
if (request.type !== types_1.GenerationType.METHOD_STUB) {
errors.push({
type: types_1.GenerationErrorType.VALIDATION_ERROR,
message: `Invalid generation type: expected ${types_1.GenerationType.METHOD_STUB}, got ${request.type}`,
code: 'INVALID_GENERATION_TYPE',
context: 'MethodStubGenerator.validateRequest'
});
}
// Check if source is an IL2CPP method
const source = request.source;
if (!source || typeof source !== 'object') {
errors.push({
type: types_1.GenerationErrorType.VALIDATION_ERROR,
message: 'Source entity is required and must be an object',
code: 'INVALID_SOURCE_ENTITY',
context: 'MethodStubGenerator.validateRequest'
});
}
else {
// Check for required method properties
const requiredProps = ['name', 'returnType', 'parameters'];
for (const prop of requiredProps) {
if (!(prop in source)) {
errors.push({
type: types_1.GenerationErrorType.VALIDATION_ERROR,
message: `Source entity missing required property: ${prop}`,
code: 'MISSING_REQUIRED_PROPERTY',
context: 'MethodStubGenerator.validateRequest'
});
}
}
// Check if parameters is an array
if (source.parameters && !Array.isArray(source.parameters)) {
errors.push({
type: types_1.GenerationErrorType.VALIDATION_ERROR,
message: 'Source entity parameters must be an array',
code: 'INVALID_PARAMETERS_TYPE',
context: 'MethodStubGenerator.validateRequest'
});
}
// Check if attributes is an array
if (source.attributes && !Array.isArray(source.attributes)) {
errors.push({
type: types_1.GenerationErrorType.VALIDATION_ERROR,
message: 'Source entity attributes must be an array',
code: 'INVALID_ATTRIBUTES_TYPE',
context: 'MethodStubGenerator.validateRequest'
});
}
}
// Check target language
if (request.target.language !== 'csharp') {
errors.push({
type: types_1.GenerationErrorType.VALIDATION_ERROR,
message: `Unsupported target language: ${request.target.language}`,
code: 'UNSUPPORTED_LANGUAGE',
context: 'MethodStubGenerator.validateRequest'
});
}
// Warnings for potential issues
if (source && source.name && !/^[A-Z][a-zA-Z0-9]*$/.test(source.name)) {
warnings.push('Method name should follow PascalCase convention');
}
return {
isValid: errors.length === 0,
errors: errors.map(err => ({
message: err.message,
line: 1,
column: 1,
severity: 'error'
})),
warnings
};
}
/**
* Parse the IL2CPP method source entity
* @param request Code generation request
* @returns Parsed method data
*/
async parseSourceEntity(request) {
const source = request.source;
const usings = new Set();
// Add basic using statements
usings.add('using System;');
// Add using statements based on return type
const returnUsings = this.context.typeResolver.getUsingsForType(source.returnType);
returnUsings.forEach(using => usings.add(using));
// Add using statements based on parameter types
for (const param of source.parameters || []) {
const paramUsings = this.context.typeResolver.getUsingsForType(param.type);
paramUsings.forEach(using => usings.add(using));
}
// Add additional using statements from options
for (const additionalUsing of request.options.additionalUsings) {
usings.add(`using ${additionalUsing};`);
}
return {
name: source.name,
returnType: source.returnType,
parameters: source.parameters || [],
isPublic: source.isPublic ?? true,
isStatic: source.isStatic ?? false,
isVirtual: source.isVirtual ?? false,
isAbstract: source.isAbstract ?? false,
isOverride: source.isOverride ?? false,
attributes: source.attributes || [],
rva: source.rva,
offset: source.offset,
usings
};
}
/**
* Generate C# method stub code from parsed method data
* @param parsedEntity Parsed method data
* @param options Generation options
* @returns Generated C# code
*/
async generateCode(parsedEntity, options) {
let code = '';
// Add XML documentation if requested
if (options.includeDocumentation) {
code += '/// <summary>\n';
code += `/// ${parsedEntity.name} method stub\n`;
code += `/// RVA: ${parsedEntity.rva}, Offset: ${parsedEntity.offset}\n`;
code += '/// </summary>\n';
// Add parameter documentation
for (const param of parsedEntity.parameters) {
const resolvedParamType = this.context.typeResolver.resolveType(param.type);
code += `/// <param name="${param.name}">Parameter of type ${resolvedParamType}</param>\n`;
}
// Add return documentation
if (parsedEntity.returnType !== 'System.Void') {
const resolvedReturnType = this.context.typeResolver.resolveType(parsedEntity.returnType);
code += `/// <returns>Returns value of type ${resolvedReturnType}</returns>\n`;
}
}
// Add attributes if requested
if (options.includeUnityAttributes && parsedEntity.attributes.length > 0) {
for (const attribute of parsedEntity.attributes) {
code += `[${attribute}]\n`;
}
}
// Add method signature
const accessModifier = parsedEntity.isPublic ? 'public' : 'private';
const staticModifier = parsedEntity.isStatic ? 'static ' : '';
const virtualModifier = parsedEntity.isVirtual ? 'virtual ' : '';
const overrideModifier = parsedEntity.isOverride ? 'override ' : '';
const abstractModifier = parsedEntity.isAbstract ? 'abstract ' : '';
const resolvedReturnType = this.context.typeResolver.resolveType(parsedEntity.returnType);
code += `${accessModifier} ${staticModifier}${virtualModifier}${overrideModifier}${abstractModifier}${resolvedReturnType} ${parsedEntity.name}(`;
// Add parameters
const parameters = parsedEntity.parameters.map(param => {
const resolvedParamType = this.context.typeResolver.resolveType(param.type);
return `${resolvedParamType} ${param.name}`;
});
code += parameters.join(', ');
code += ')';
// Add method body or semicolon for abstract methods
if (parsedEntity.isAbstract) {
code += ';\n';
}
else {
code += '\n{\n';
if (options.includeErrorHandling && parsedEntity.returnType !== 'System.Void') {
// Add try-catch block for error handling
code += ' try\n';
code += ' {\n';
code += ' // TODO: Implement method\n';
code += ' throw new System.NotImplementedException();\n';
code += ' }\n';
code += ' catch (System.Exception ex)\n';
code += ' {\n';
code += ' // Log error or handle as appropriate\n';
code += ' throw;\n';
code += ' }\n';
}
else if (parsedEntity.returnType === 'System.Void') {
// Void method - just add TODO comment
code += ' // TODO: Implement method\n';
}
else {
// Non-void method without error handling
code += ' // TODO: Implement method\n';
code += ' throw new System.NotImplementedException();\n';
}
code += '}\n';
}
// Format the code according to style options
return this.formatCode(code, options.codeStyle);
}
}
exports.MethodStubGenerator = MethodStubGenerator;
//# sourceMappingURL=method-stub-generator.js.map