using System.Text;
using CodePlay.Core.Interfaces;
using CodePlay.Core.Common;
namespace CodePlay.Core.Converters;
///
/// C# 代码生成器
///
public class CSharpCodeGenerator : ICodeGenerator
{
private readonly StringBuilder _output = new();
private int _indentLevel;
///
/// 从语法树生成 C# 代码
///
public string Generate(Interfaces.SyntaxTree syntaxTree)
{
_output.Clear();
_indentLevel = 0;
// 生成 using 指令
GenerateUsings(syntaxTree);
// 生成代码
GenerateNode(syntaxTree.Root);
return _output.ToString();
}
private void GenerateUsings(Interfaces.SyntaxTree tree)
{
_output.AppendLine("using System;");
_output.AppendLine("using System.Collections.Generic;");
_output.AppendLine();
}
private void GenerateNode(Interfaces.SyntaxNode node)
{
switch (node.Type)
{
case SyntaxNodeType.CompilationUnit:
GenerateCompilationUnit(node);
break;
case SyntaxNodeType.Namespace:
GenerateNamespace(node);
break;
case SyntaxNodeType.Class:
GenerateClass(node);
break;
case SyntaxNodeType.Method:
GenerateMethod(node);
break;
case SyntaxNodeType.Property:
GenerateProperty(node);
break;
case SyntaxNodeType.Field:
GenerateField(node);
break;
default:
GenerateDefault(node);
break;
}
}
private void GenerateCompilationUnit(Interfaces.SyntaxNode node)
{
foreach (var child in node.Children)
{
GenerateNode(child);
}
}
private void GenerateNamespace(Interfaces.SyntaxNode node)
{
var namespaceName = ExtractNamespaceName(node.Text);
_output.AppendLine($"namespace {namespaceName}");
_output.AppendLine("{");
_indentLevel++;
foreach (var child in node.Children)
{
if (child.Type != SyntaxNodeType.Unknown)
{
GenerateNode(child);
}
}
_indentLevel--;
_output.AppendLine("}");
_output.AppendLine();
}
private void GenerateClass(Interfaces.SyntaxNode node)
{
var classDeclaration = node.Text.Split('{')[0].Trim();
_output.AppendLine(Indent(classDeclaration));
_output.AppendLine(Indent("{"));
_indentLevel++;
foreach (var child in node.Children)
{
if (child.Type != SyntaxNodeType.Unknown && child.Type != SyntaxNodeType.CompilationUnit)
{
GenerateNode(child);
}
}
_indentLevel--;
_output.AppendLine(Indent("}"));
_output.AppendLine();
}
private void GenerateMethod(Interfaces.SyntaxNode node)
{
var methodSignature = ExtractMethodSignature(node.Text);
_output.AppendLine(Indent(methodSignature));
_output.AppendLine(Indent("{"));
_indentLevel++;
var methodBody = ExtractMethodBody(node.Text);
if (!string.IsNullOrWhiteSpace(methodBody))
{
var lines = methodBody.Split('\n');
foreach (var line in lines)
{
if (!string.IsNullOrWhiteSpace(line.Trim()))
{
_output.AppendLine(Indent(line.Trim()));
}
}
}
_indentLevel--;
_output.AppendLine(Indent("}"));
_output.AppendLine();
}
private void GenerateProperty(Interfaces.SyntaxNode node)
{
var propertyDeclaration = node.Text.Trim();
if (!string.IsNullOrWhiteSpace(propertyDeclaration))
{
_output.AppendLine(Indent(propertyDeclaration.EndsWith(";") ? propertyDeclaration : propertyDeclaration + ";"));
}
}
private void GenerateField(Interfaces.SyntaxNode node)
{
var fieldDeclaration = node.Text.Trim();
if (!string.IsNullOrWhiteSpace(fieldDeclaration))
{
_output.AppendLine(Indent(fieldDeclaration.EndsWith(";") ? fieldDeclaration : fieldDeclaration + ";"));
}
}
private void GenerateDefault(Interfaces.SyntaxNode node)
{
if (!string.IsNullOrWhiteSpace(node.Text) && node.Type != SyntaxNodeType.Comment)
{
var lines = node.Text.Split('\n');
foreach (var line in lines)
{
var trimmed = line.Trim();
if (!string.IsNullOrWhiteSpace(trimmed) &&
trimmed != "{" &&
trimmed != "}")
{
_output.AppendLine(Indent(trimmed));
}
}
}
foreach (var child in node.Children)
{
GenerateNode(child);
}
}
private string Indent(string text)
{
var indent = new string(' ', _indentLevel * 4);
return indent + text;
}
private string ExtractNamespaceName(string text)
{
if (text.StartsWith("namespace "))
{
var match = System.Text.RegularExpressions.Regex.Match(text, @"namespace\s+([\w.]+)");
return match.Success ? match.Groups[1].Value : "CodePlay.Converted";
}
return "CodePlay.Converted";
}
private string ExtractMethodSignature(string text)
{
var lines = text.Split('\n');
foreach (var line in lines)
{
var trimmed = line.Trim();
if (trimmed.Length > 0 &&
!trimmed.StartsWith("{") &&
!trimmed.StartsWith("}") &&
(trimmed.Contains("(") || trimmed.Contains("void") || trimmed.Contains("public") || trimmed.Contains("private")))
{
return trimmed.EndsWith("{") ? trimmed.Substring(0, trimmed.Length - 1).Trim() : trimmed;
}
}
return text;
}
private string ExtractMethodBody(string text)
{
var startIndex = text.IndexOf('{');
var endIndex = text.LastIndexOf('}');
if (startIndex >= 0 && endIndex > startIndex)
{
return text.Substring(startIndex + 1, endIndex - startIndex - 1).Trim();
}
return string.Empty;
}
}