sharplib/lib/CodeGenerator.cs

74 lines
2.3 KiB
C#

using System.Text;
using System.Collections.Generic;
using System;
using System.Linq;
namespace ser;
public abstract class CodeGenerator
{
protected StringBuilder _sb = new StringBuilder();
protected int _indent = 0;
protected TypeStructureAnalyzer _analyzer;
protected CodeGenConfig _config;
protected HashSet<Type> _generatedTypes = new(); // Track to avoid re-generating
public CodeGenerator( CodeGenConfig config )
{
_config = config;
_analyzer = new TypeStructureAnalyzer( config );
}
// Main entry point
public string Generate( Type type, string ns = "GeneratedCode" )
{
_sb.Clear();
WriteLine( "using System;" );
WriteLine( "using System.Collections.Generic;" );
WriteLine( "using System.Linq;" );
WriteLine( "" );
WriteLine( $"namespace {ns};" );
WriteLine( "" );
GenerateForType( type );
return _sb.ToString();
}
// Core generation logic - needs to be recursive for dependencies
protected virtual void GenerateForType( Type type )
{
if( type == null || !CanGenerateFor( type ) || _generatedTypes.Contains( type ) )
return;
_generatedTypes.Add( type );
var info = _analyzer.Get( type );
// Generate dependencies first
foreach( var member in info.Members )
{
GenerateForType( member.Type );
if( member.IsCollection && member.CollectionElementType != null )
{
GenerateForType( member.CollectionElementType );
}
}
// Generate the actual code
GenerateClassHeader( info );
BeginBlock();
GenerateClassBody( info );
EndBlock();
}
// Abstract methods to be implemented by specific generators
protected abstract void GenerateClassHeader( TypeStructureInfo info );
protected abstract void GenerateClassBody( TypeStructureInfo info );
protected abstract bool CanGenerateFor( Type type ); // Check if we should generate for this type
// Helper methods
protected void WriteLine( string line = "" ) => _sb.AppendLine( new string( '\t', _indent ) + line );
protected void BeginBlock() { WriteLine( "{" ); _indent++; }
protected void EndBlock() { _indent--; WriteLine( "}" ); }
protected string GetTypeName( Type t ) => t.IsGenericType
? $"{t.Name.Split( '`' )[0]}<{string.Join( ", ", t.GetGenericArguments().Select( GetTypeName ) )}>"
: t.Name; // Basic handling, needs improvement for full names/namespaces
}