feat: 实现 Java 完整解析器和不可转换语法处理 (Task 2.2, 2.8)

Task 2.2 - Java 完整解析器:
- JavaParser: 支持包声明、导入语句、类/接口/枚举提取
- 提取方法、字段、构造函数、参数
- 提取单行/多行注释和 JavaDoc 文档
- 10 个单元测试全部通过

Task 2.8 - 不可转换语法处理:
- UnconvertibleSyntaxHandler: 检测 C# 特有语法
- 支持检测:async/await, LINQ, dynamic, var, yield, record 等
- 检测模式:空条件运算符.?,空合并??, 字符串插值$等
- 转换可行性评估:置信度评分和努力程度估算
- 自动生成 TODO 注释标记
- 3 个单元测试通过

Task 4.2 - API 认证:
- AuthController: JWT 认证端点 (login, refresh, me)
- Program.cs: JWT Bearer 认证配置
- Swagger 集成认证支持

总计:39 个测试全部通过 
Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>
This commit is contained in:
monkeycode-ai
2026-06-03 09:21:55 +00:00
parent 529b9fe625
commit cca683f35c
8 changed files with 989 additions and 53 deletions
+196
View File
@@ -0,0 +1,196 @@
using CodePlay.Core.Parsers;
using CodePlay.Core.Common;
using CodePlay.Core.Interfaces;
using Xunit;
namespace CodePlay.Tests.Parsers;
public class JavaParserTests
{
private readonly JavaParser _parser;
public JavaParserTests()
{
_parser = new JavaParser();
}
[Fact]
public void SupportedLanguage_ShouldReturn_Java()
{
Assert.Equal(LanguageType.Java, _parser.SupportedLanguage);
}
[Fact]
public async Task ParseAsync_SimpleClass_ShouldParseSuccessfully()
{
var sourceCode = @"
package com.test;
import java.util.List;
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}";
var result = await _parser.ParseAsync(sourceCode);
Assert.NotNull(result);
Assert.Equal(LanguageType.Java, result.Language);
Assert.NotNull(result.Root);
Assert.NotEmpty(result.Root.Children);
}
[Fact]
public async Task ParseAsync_WithPackage_ShouldExtractPackage()
{
var sourceCode = @"
package com.example.demo;
public class Test { }";
var result = await _parser.ParseAsync(sourceCode);
Assert.NotNull(result);
Assert.Contains(result.Root.Children, n => n.Type == SyntaxNodeType.Namespace);
}
[Fact]
public async Task ParseAsync_WithImports_ShouldExtractImports()
{
var sourceCode = @"
import java.util.List;
import java.util.ArrayList;
import static java.lang.Math.PI;
public class Test { }";
var result = await _parser.ParseAsync(sourceCode);
Assert.NotNull(result);
Assert.Contains(result.Root.Children, n => n.Type == SyntaxNodeType.Field);
}
[Fact]
public async Task ParseAsync_WithComments_ShouldExtractComments()
{
var sourceCode = @"
// This is a single-line comment
/* This is a
multi-line comment */
public class Test {
/**
* This is JavaDoc
* @param name the name
*/
public void method(String name) { }
}";
var result = await _parser.ParseAsync(sourceCode);
Assert.NotNull(result);
Assert.NotEmpty(result.Comments);
Assert.NotEmpty(result.Documentation);
}
[Fact]
public async Task ParseAsync_WithMethods_ShouldExtractMethods()
{
var sourceCode = @"
public class Calculator {
public int add(int a, int b) {
return a + b;
}
private static String format(double value) {
return String.valueOf(value);
}
}";
var result = await _parser.ParseAsync(sourceCode);
Assert.NotNull(result);
var classNode = result.Root.Children.FirstOrDefault(n => n.Type == SyntaxNodeType.Class);
Assert.NotNull(classNode);
Assert.Contains(classNode.Children, n => n.Type == SyntaxNodeType.Method);
}
[Fact]
public async Task ParseAsync_WithFields_ShouldExtractFields()
{
var sourceCode = @"
public class Data {
private String name;
public static final int MAX_SIZE = 100;
protected List<String> items;
}";
var result = await _parser.ParseAsync(sourceCode);
Assert.NotNull(result);
var classNode = result.Root.Children.FirstOrDefault(n => n.Type == SyntaxNodeType.Class);
Assert.NotNull(classNode);
Assert.Contains(classNode.Children, n => n.Type == SyntaxNodeType.Field);
}
[Fact]
public async Task ParseAsync_WithGenericType_ShouldParseGenerics()
{
var sourceCode = @"
public class GenericClass<T extends Object> {
private List<T> items;
public <U> U convert(T item) {
return null;
}
}";
var result = await _parser.ParseAsync(sourceCode);
Assert.NotNull(result);
Assert.NotEmpty(result.Root.Children);
}
[Fact]
public async Task ParseAsync_WithInterface_ShouldExtractInterface()
{
var sourceCode = @"
public interface Service {
void execute();
String getName();
}";
var result = await _parser.ParseAsync(sourceCode);
Assert.NotNull(result);
Assert.Contains(result.Root.Children, n => n.Type == SyntaxNodeType.Interface);
}
[Fact]
public async Task ParseAsync_WithThrows_ShouldExtractThrows()
{
var sourceCode = @"
public class Test {
public void method() throws IOException, Exception {
throw new IOException();
}
}";
var result = await _parser.ParseAsync(sourceCode);
Assert.NotNull(result);
var methodNode = result.Root.Children
.FirstOrDefault(n => n.Type == SyntaxNodeType.Class)?
.Children.FirstOrDefault(n => n.Type == SyntaxNodeType.Method);
Assert.NotNull(methodNode);
}
}
@@ -0,0 +1,64 @@
using CodePlay.Core.Services;
using CodePlay.Core.Common;
using Xunit;
namespace CodePlay.Tests.Services;
public class UnconvertibleSyntaxHandlerTests
{
private readonly UnconvertibleSyntaxHandler _handler;
public UnconvertibleSyntaxHandlerTests()
{
_handler = new UnconvertibleSyntaxHandler();
}
[Fact]
public void DetectUnconvertibleSyntax_AsyncAwait_ShouldDetect()
{
var code = @"
public async Task<string> GetDataAsync()
{
var result = await httpClient.GetStringAsync(url);
return result;
}";
var issues = _handler.DetectUnconvertibleSyntax(code, LanguageType.CSharp, LanguageType.Java);
Assert.NotEmpty(issues);
Assert.Contains(issues, i => i.OriginalCode.Contains("async"));
Assert.Contains(issues, i => i.OriginalCode.Contains("await"));
}
[Fact]
public void DetectUnconvertibleSyntax_LINQ_ShouldDetect()
{
var code = @"
var result = source.Where(x => x > 0)
.Select(x => x * 2)
.ToList();";
var issues = _handler.DetectUnconvertibleSyntax(code, LanguageType.CSharp, LanguageType.Java);
Assert.NotEmpty(issues);
Assert.Contains(issues, i => i.Description.Contains("var") || i.Description.Contains("LINQ"));
}
[Fact]
public void AssessFeasibility_NoIssues_ShouldReturnHighConfidence()
{
var code = @"
public class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
}";
var feasibility = _handler.AssessFeasibility(code, LanguageType.CSharp, LanguageType.Java);
Assert.True(feasibility.IsFeasible);
Assert.True(feasibility.ConfidenceScore > 80);
}
}