dd02c3a053
新增组件: - JavaToCSharpStrategy: Java 到 C# 转换策略 - JavaToCSharpConverter: Java 到 C# 转换器 - JavaParser: Java 简化解析器(基于文本处理) - CSharpCodeGenerator: C# 代码生成器 功能实现: - 18 种类型映射(Java → C#) - package → namespace 转换 - import → using 转换 - JavaDoc → XML Doc 转换 - Stream API 检测并添加 TODO - CompletableFuture 检测并添加 TODO 测试覆盖: - 添加 4 个 JavaToCSharpConverterTests 测试用例 - 总测试数 17 个,全部通过 Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>
227 lines
6.5 KiB
C#
227 lines
6.5 KiB
C#
using System.Text;
|
|
using CodePlay.Core.Interfaces;
|
|
using CodePlay.Core.Common;
|
|
|
|
namespace CodePlay.Core.Converters;
|
|
|
|
/// <summary>
|
|
/// C# 代码生成器
|
|
/// </summary>
|
|
public class CSharpCodeGenerator : ICodeGenerator
|
|
{
|
|
private readonly StringBuilder _output = new();
|
|
private int _indentLevel;
|
|
|
|
/// <summary>
|
|
/// 从语法树生成 C# 代码
|
|
/// </summary>
|
|
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;
|
|
}
|
|
}
|