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,211 @@
using CodePlay.Core.Interfaces;
using CodePlay.Core.Models;
using CodePlay.Core.Common;
namespace CodePlay.Core.Converters;
/// <summary>
/// Java 到 C# 转换策略
/// </summary>
public class JavaToCSharpStrategy : IConversionStrategy
{
/// <summary>
/// 源语言
/// </summary>
public LanguageType SourceLanguage => LanguageType.Java;
/// <summary>
/// 目标语言
/// </summary>
public LanguageType TargetLanguage => LanguageType.CSharp;
private readonly List<TypeMapping> _typeMappings = new();
public JavaToCSharpStrategy()
{
InitializeTypeMappings();
}
private void InitializeTypeMappings()
{
_typeMappings.AddRange(new[]
{
new TypeMapping("java.lang.String", "string"),
new TypeMapping("java.lang.Object", "object"),
new TypeMapping("java.lang.Integer", "int"),
new TypeMapping("java.lang.Long", "long"),
new TypeMapping("java.lang.Boolean", "bool"),
new TypeMapping("java.lang.Double", "double"),
new TypeMapping("java.lang.Float", "float"),
new TypeMapping("java.util.ArrayList", "List"),
new TypeMapping("java.util.List", "IEnumerable"),
new TypeMapping("java.util.HashMap", "Dictionary"),
new TypeMapping("java.util.Map", "IDictionary"),
new TypeMapping("java.util.stream.Stream", "IEnumerable"),
new TypeMapping("java.util.Arrays", "Array"),
new TypeMapping("java.time.LocalDateTime", "DateTime"),
new TypeMapping("java.time.Duration", "TimeSpan"),
new TypeMapping("java.lang.Exception", "Exception"),
new TypeMapping("java.lang.IllegalArgumentException", "ArgumentException"),
new TypeMapping("java.lang.IllegalStateException", "InvalidOperationException"),
new TypeMapping("java.lang.NullPointerException", "NullReferenceException"),
new TypeMapping("java.util.concurrent.CompletableFuture", "Task"),
new TypeMapping("System.out.println", "Console.WriteLine"),
new TypeMapping("public static void main", "static void Main"),
});
}
/// <summary>
/// 映射类型
/// </summary>
public string MapType(string sourceType)
{
var result = sourceType;
foreach (var mapping in _typeMappings)
{
result = result.Replace(mapping.SourceType, mapping.TargetType);
}
// Java 到 C# 的特定转换
result = result
.Replace("var ", "var ")
.Replace("final ", "")
.Replace(".size()", ".Count")
.Replace(".length", ".Length")
.Replace(".equals(", ".Equals(")
.Replace(".toString()", ".ToString()")
.Replace(".hashCode()", ".GetHashCode()");
return result;
}
/// <summary>
/// 转换语法节点
/// </summary>
public Interfaces.SyntaxNode ConvertNode(Interfaces.SyntaxNode node, ConversionContext context)
{
var newNode = new Interfaces.SyntaxNode
{
Type = node.Type,
Text = ConvertText(node.Text, context),
Metadata = new Dictionary<string, object?>(node.Metadata),
Parent = node.Parent,
Children = new List<Interfaces.SyntaxNode>(),
IsUnconvertible = node.IsUnconvertible,
TodoDescription = node.TodoDescription
};
foreach (var child in node.Children)
{
var convertedChild = ConvertNode(child, context);
convertedChild.Parent = newNode;
newNode.Children.Add(convertedChild);
}
// 检测不可转换的语法
CheckUnconvertibleSyntax(node.Text, context);
return newNode;
}
private string ConvertText(string text, ConversionContext context)
{
var result = text;
// package 转 namespace
if (result.StartsWith("package "))
{
result = result.Replace("package ", "namespace ")
.Replace(";", " {");
}
// import 转 using
if (result.StartsWith("import "))
{
result = result.Replace("import ", "using ")
.Replace(";", ";");
}
// 类型映射
result = MapType(result);
// Java 特定语法处理
result = result
.Replace("super.", "base.")
.Replace("System.out.println", "Console.WriteLine")
.Replace("@Override", "[Override]")
.Replace("extends", ":")
.Replace("implements", ":");
// 方法声明转换
result = System.Text.RegularExpressions.Regex.Replace(
result,
@"public\s+(\w+)\s+get(\w+)\(\)",
"public $1 Get$2 { get; }"
);
result = System.Text.RegularExpressions.Regex.Replace(
result,
@"public\s+void\s+set(\w+)\(\1\s+\w+\)",
"public void Set$1 { set; }"
);
return result;
}
private void CheckUnconvertibleSyntax(string text, ConversionContext context)
{
// 检测 Stream API
if (text.Contains(".stream(") || text.Contains("Stream."))
{
context.Issues.Add(new ConversionIssue
{
Type = IssueType.UnconvertibleSyntax,
Description = "Java Stream API 需要转换为 LINQ",
OriginalCode = text,
Suggestion = "使用 LINQ 替代:stream().filter() → .Where(), stream().map() → .Select()"
});
context.TodoItems.Add(new TodoItem
{
Description = "将 Stream API 转换为 LINQ",
OriginalSyntax = "Stream API",
WhyNotDirect = "Java Stream 和 LINQ 语法不同,需要手动调整",
RecommendedAlternative = "使用 .Where(), .Select(), .Aggregate() 等 LINQ 方法"
});
}
// 检测 CompletableFuture
if (text.Contains("CompletableFuture") || text.Contains("thenApply") || text.Contains("thenAccept"))
{
context.Issues.Add(new ConversionIssue
{
Type = IssueType.UnconvertibleSyntax,
Description = "CompletableFuture 需要转换为 async/await",
OriginalCode = text,
Suggestion = "使用 async/await 模式:completableFuture.thenApply() → await Task"
});
context.TodoItems.Add(new TodoItem
{
Description = "将 CompletableFuture 转换为 async/await",
OriginalSyntax = "CompletableFuture",
WhyNotDirect = "Java CompletableFuture 和 C# async/await 模式不同",
RecommendedAlternative = "使用 Task<T> 和 async/await 关键字"
});
}
// 检测接口默认方法
if (text.Contains("default ") && text.Contains(" interface "))
{
context.Logs.Add(new TransformationLog
{
Timestamp = DateTime.UtcNow,
Operation = "Warning",
Details = "Java 接口默认方法需要特殊处理",
Level = LogLevel.Warning
});
}
}
}