Guide to creating custom solution generators.
Overview
Solution generators create optimized code fixes for detected issues. Each generator handles specific issue types.
Base Class
abstract class BaseSolutionGenerator {
abstract name: string;
abstract generateSolutions(issue: Issue, context: AnalysisContext): Promise<Solution[]>;
protected generateTransformationBasedSolutions(
issue: Issue,
context: AnalysisContext,
strategies: TransformationStrategy[]
): Solution[];
}
Creating a Generator
// src/generators/my-solution-generator.ts
import { BaseSolutionGenerator, TransformationStrategy } from './base-generator';
import { Issue, Solution, AnalysisContext } from '../types';
export class MySolutionGenerator extends BaseSolutionGenerator {
name = 'My Solution Generator';
async generateSolutions(issue: Issue, context: AnalysisContext): Promise<Solution[]> {
const strategies: TransformationStrategy[] = [
{
name: 'my-optimization',
description: 'Apply custom optimization',
fitness: 85,
apply: (code, pattern, ctx) => this.applyOptimization(code, pattern)
}
];
return this.generateTransformationBasedSolutions(issue, context, strategies);
}
private applyOptimization(code: string, pattern: CodePattern) {
// Transform the code
const optimizedCode = code.replace(/pattern/, 'replacement');
return {
success: true,
code: optimizedCode,
description: 'Applied optimization',
transformationType: 'my-optimization',
preservedElements: ['variable names', 'function structure']
};
}
}
Registering Generator
// In CodeAnalyzer constructor
this.generators.set('my_issue_type', new MySolutionGenerator());
Transformation Strategy
interface TransformationStrategy {
name: string; // Strategy identifier
description: string; // Human-readable description
fitness: number; // Base fitness score (0-100)
apply: (
originalCode: string,
pattern: CodePattern,
context: AnalysisContext
) => TransformationResult;
}
interface TransformationResult {
success: boolean;
code: string;
description: string;
transformationType: string;
preservedElements: string[];
}
preservedElements should list the identifiers and structures your
transformation genuinely kept from the original — it determines the solution’s
risk rating, not just its documentation.
Code Pattern Analysis
interface CodePattern {
type: 'loop-with-calls' | 'chained-methods' | 'repeated-access' | 'nested-loop' | 'unknown';
loopVariable?: string;
iteratedCollection?: string;
repeatedCalls: string[];
originalStructure: string;
}
Framework information is not part of CodePattern. Detectors that determine a
framework record it on the issue under estimatedImpact.metrics.framework,
which is where framework-aware generators read it from.
Best Practices
- Preserve Original Structure - Keep variable names and code organization
- Expect Validation -
generateTransformationBasedSolutionsrunsisValidCode()on every result and silently skips comment-only output, so a strategy that returns explanation rather than code produces nothing - Provide Multiple Strategies - Offer different optimization approaches
- Calculate Accurate Fitness - Consider performance, complexity, maintainability
- Handle Edge Cases - Check for empty code, missing patterns