实现 Task 3.1 - C# 编译验证: - CSharpCompilerValidator: C# 编译验证器 - AutoFixEngine: 3 轮自动修复引擎 - ValidationPipeline: 验证流水线服务 - 集成到 ConversionService 功能: - 使用 Roslyn 进行实时编译验证 - 捕获编译错误和警告 - 自动修复第 1 轮:添加缺失的 using 语句 - 自动修复第 2 轮:类型映射修复 - 支持 1-3 轮验证迭代 测试覆盖 (新增 9 个测试): - CSharpCompilerValidatorTests: 3 个测试 - AutoFixEngineTests: 3 个测试 - ValidationPipelineTests: 3 个测试 总测试数:26 个,全部通过 ✅ Co-authored-by: monkeycode-ai <[email protected]>
200 lines
5.9 KiB
C#
200 lines
5.9 KiB
C#
using System.Text;
|
|
using CodePlay.Core.Interfaces;
|
|
using CodePlay.Core.Models;
|
|
using CodePlay.Core.Common;
|
|
|
|
namespace CodePlay.Core.Validators;
|
|
|
|
/// <summary>
|
|
/// 自动修复引擎
|
|
/// </summary>
|
|
public class AutoFixEngine
|
|
{
|
|
/// <summary>
|
|
/// 尝试修复编译错误
|
|
/// </summary>
|
|
public Task<FixResult> FixAsync(string code, List<CompilationError> errors, int round, CancellationToken cancellationToken = default)
|
|
{
|
|
var result = new FixResult
|
|
{
|
|
CanFix = false,
|
|
RemainingErrors = new List<CompilationError>()
|
|
};
|
|
|
|
if (errors == null || errors.Count == 0)
|
|
{
|
|
result.CanFix = true;
|
|
result.FixedCode = code;
|
|
result.FixDescription = "No errors to fix";
|
|
return Task.FromResult(result);
|
|
}
|
|
|
|
switch (round)
|
|
{
|
|
case 1:
|
|
result = FixRound1(code, errors);
|
|
break;
|
|
case 2:
|
|
result = FixRound2(code, errors);
|
|
break;
|
|
case 3:
|
|
result = FixRound3(code, errors);
|
|
break;
|
|
default:
|
|
result.RemainingErrors = errors;
|
|
break;
|
|
}
|
|
|
|
return Task.FromResult(result);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 第 1 轮:修复导入/using 语句
|
|
/// </summary>
|
|
private FixResult FixRound1(string code, List<CompilationError> errors)
|
|
{
|
|
var result = new FixResult
|
|
{
|
|
CanFix = false,
|
|
RemainingErrors = new List<CompilationError>(),
|
|
FixDescription = string.Empty
|
|
};
|
|
|
|
var needsSystemUsing = false;
|
|
var needsCollectionsUsing = false;
|
|
var needsLinqUsing = false;
|
|
|
|
foreach (var error in errors)
|
|
{
|
|
if (error.ErrorId == "CS0246" || error.ErrorId == "CS0103")
|
|
{
|
|
if (error.Message.Contains("Console"))
|
|
{
|
|
needsSystemUsing = true;
|
|
}
|
|
else if (error.Message.Contains("List") || error.Message.Contains("Dictionary"))
|
|
{
|
|
needsCollectionsUsing = true;
|
|
}
|
|
else if (error.Message.Contains("LINQ") || error.Message.Contains("var"))
|
|
{
|
|
needsLinqUsing = true;
|
|
}
|
|
else
|
|
{
|
|
result.RemainingErrors.Add(error);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
result.RemainingErrors.Add(error);
|
|
}
|
|
}
|
|
|
|
var fixedCode = code;
|
|
var fixDescription = new StringBuilder();
|
|
|
|
if (needsSystemUsing && !code.Contains("using System;"))
|
|
{
|
|
fixedCode = fixedCode.Insert(0, "using System;\n");
|
|
fixDescription.Append("Added using System; ");
|
|
}
|
|
|
|
if (needsCollectionsUsing && !code.Contains("using System.Collections.Generic;"))
|
|
{
|
|
fixedCode = fixedCode.Insert(0, "using System.Collections.Generic;\n");
|
|
fixDescription.Append("Added using System.Collections.Generic;");
|
|
}
|
|
|
|
if (needsLinqUsing && !code.Contains("using System.Linq;"))
|
|
{
|
|
fixedCode = fixedCode.Insert(0, "using System.Linq;\n");
|
|
fixDescription.Append("Added using System.Linq;");
|
|
}
|
|
|
|
if (fixDescription.Length > 0)
|
|
{
|
|
result.CanFix = true;
|
|
result.FixedCode = fixedCode;
|
|
result.FixDescription = fixDescription.ToString().Trim();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 第 2 轮:修复类型映射
|
|
/// </summary>
|
|
private FixResult FixRound2(string code, List<CompilationError> errors)
|
|
{
|
|
var result = new FixResult
|
|
{
|
|
CanFix = false,
|
|
RemainingErrors = new List<CompilationError>(),
|
|
FixDescription = string.Empty
|
|
};
|
|
|
|
var fixedCode = code;
|
|
var hasFixes = false;
|
|
var fixDescription = new StringBuilder();
|
|
|
|
foreach (var error in errors)
|
|
{
|
|
if (error.ErrorId == "CS0246")
|
|
{
|
|
if (error.Message.Contains("String"))
|
|
{
|
|
fixedCode = fixedCode.Replace("String", "string");
|
|
hasFixes = true;
|
|
fixDescription.Append("Mapped String to string; ");
|
|
}
|
|
else if (error.Message.Contains("ArrayList"))
|
|
{
|
|
fixedCode = fixedCode.Replace("ArrayList", "List<object>");
|
|
hasFixes = true;
|
|
fixDescription.Append("Mapped ArrayList to List<object>; ");
|
|
}
|
|
else if (error.Message.Contains("HashMap"))
|
|
{
|
|
fixedCode = fixedCode.Replace("HashMap", "Dictionary<object, object>");
|
|
hasFixes = true;
|
|
fixDescription.Append("Mapped HashMap to Dictionary;");
|
|
}
|
|
else
|
|
{
|
|
result.RemainingErrors.Add(error);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
result.RemainingErrors.Add(error);
|
|
}
|
|
}
|
|
|
|
if (hasFixes)
|
|
{
|
|
result.CanFix = true;
|
|
result.FixedCode = fixedCode;
|
|
result.FixDescription = fixDescription.ToString().Trim();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 第 3 轮:修复 API 调用
|
|
/// </summary>
|
|
private FixResult FixRound3(string code, List<CompilationError> errors)
|
|
{
|
|
var result = new FixResult
|
|
{
|
|
CanFix = false,
|
|
RemainingErrors = errors,
|
|
FixDescription = "Round 3 fixes not implemented in MVP"
|
|
};
|
|
|
|
// MVP 版本暂不实现复杂修复
|
|
return result;
|
|
}
|
|
}
|