feat: 实现 Java → C# 转换器 (Task 2.5)

新增组件:
- 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>
This commit is contained in:
monkeycode-ai
2026-06-03 05:45:23 +00:00
parent 80b4718568
commit dd02c3a053
6 changed files with 858 additions and 0 deletions
@@ -0,0 +1,226 @@
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;
}
}