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:
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user