using CodePlay.Core.Common; using CodePlay.Core.Models; namespace CodePlay.Core.Services; /// /// 不可转换语法处理器 /// 识别和标记无法直接转换的语法结构 /// public class UnconvertibleSyntaxHandler { private static readonly HashSet CSharpUnconvertibleKeywords = new() { "async", "await", "dynamic", "var", "yield", "unsafe", "fixed", "checked", "unchecked", "nameof", "is", "record", "init", "with", "not", "and", "or" }; private static readonly HashSet CSharpUnconvertiblePatterns = new() { "LINQ", @"\bawait\s+\w+\b", @"\basync\s+\w+", @"\bvar\s+\w+\s*=\s*new\b", @"\busing\s+\w+\s*=", @"\?\.", // 空条件运算符 @"\?\?", // 空合并运算符 @"\$\{", // 字符串插值 @"\brecord\s+\w+", @"\binit\s*{", @"\bwith\s*{", @"\bdelegate\s*\(", @"\bevent\s+", @"\bref\s+\w+", @"\bout\s+\w+", @"\bin\b" // C# 9 pattern }; /// /// 检测 C# 代码中的不可转换语法 /// public List DetectUnconvertibleSyntax(string sourceCode, LanguageType sourceLanguage, LanguageType targetLanguage) { var issues = new List(); var lines = sourceCode.Split('\n'); for (int i = 0; i < lines.Length; i++) { var line = lines[i]; var lineNumber = i + 1; // 检查关键词 foreach (var keyword in CSharpUnconvertibleKeywords.Where(k => k != "switch")) { if (System.Text.RegularExpressions.Regex.IsMatch(line, $@"\b{keyword}\b")) { issues.Add(new ConversionIssue { Type = IssueType.UnconvertibleSyntax.ToString(), Severity = IssueSeverity.Medium.ToString(), LineNumber = lineNumber, Description = $"C# keyword '{keyword}' cannot be directly converted to {targetLanguage}", Suggestion = GetSuggestion(keyword, targetLanguage), OriginalCode = line.Trim(), Language = sourceLanguage.ToName() }); } } // 检查模式 foreach (var pattern in CSharpUnconvertiblePatterns) { if (pattern.StartsWith(@"\") && System.Text.RegularExpressions.Regex.IsMatch(line, pattern)) { issues.Add(new ConversionIssue { Type = IssueType.UnconvertibleSyntax.ToString(), Severity = IssueSeverity.Medium.ToString(), LineNumber = lineNumber, Description = $"Pattern '{pattern}' cannot be directly converted to {targetLanguage}", Suggestion = GetPatternSuggestion(pattern, targetLanguage), OriginalCode = line.Trim(), Language = sourceLanguage.ToName() }); } else if (!pattern.StartsWith(@"\") && line.Contains(pattern)) { issues.Add(new ConversionIssue { Type = IssueType.UnconvertibleSyntax.ToString(), Severity = IssueSeverity.Medium.ToString(), LineNumber = lineNumber, Description = $"Pattern containing '{pattern}' cannot be directly converted to {targetLanguage}", Suggestion = GetPatternSuggestion(pattern, targetLanguage), OriginalCode = line.Trim(), Language = sourceLanguage.ToName() }); } } } return issues; } /// /// 获取关键词的转换建议 /// private string GetSuggestion(string keyword, LanguageType targetLanguage) { return keyword switch { "async" => $"Use CompletableFuture (Java) or std::future (C++) for asynchronous operations", "await" => $"Use .join() (Java) or .get() (C++) to wait for async results", "dynamic" => $"Use Object (Java) with explicit casting, or templates (C++)", "var" => $"Use explicit type declaration in {targetLanguage}", "yield" => $"Implement Iterator pattern with hasNext()/next() (Java) or begin()/end() (C++)", "unsafe" => $"Use JNI (Java) or native pointers with caution (C++)", "fixed" => $"Use pinned memory or GC.KeepAlive (Java: Unsafe class)", "nameof" => $"Use reflection or manual string literals", "record" => $"Generate immutable class with final fields and getter methods", "init" => $"Use constructor or builder pattern", "with" => $"Use copy constructor or builder pattern", "not" => $"Use ! operator or Objects.isNull() (Java)", "and" => $"Use && operator", "or" => $"Use || operator", _ => $"Manual refactoring required" }; } /// /// 获取模式的转换建议 /// private string GetPatternSuggestion(string pattern, LanguageType targetLanguage) { return pattern switch { @"\bLINQ\b" => "Convert to Stream API (Java) or STL algorithms (C++)", @"\basync\s+\w+" => "Use CompletableFuture (Java) or std::async (C++)", @"\bvar\s+\w+\s*=\s*new\b" => "Replace with explicit type declaration", @"\busing\s+\w+\s*=" => "Use try-with-resources (Java) or RAII pattern (C++)", @"\?\." => "Add explicit null checks before method/property access", @"\?\?" => "Use Objects.requireNonNullElse (Java) or ternary operator", @"\$\{" => $"Use String.format() (Java) or std::format (C++)", @"\brecord\s+\w+" => "Convert to immutable class with equals/hashCode/toString", @"\bdelegate\s*\(" => "Convert to functional interface (Java) or std::function (C++)", @"\bevent\s+" => "Implement observer pattern with add/remove methods", @"\bref\s+\w+" => "Pass by reference using pointers (C++) or mutable wrapper (Java)", @"\bout\s+\w+" => "Return tuple or use holder class", _ => "Manual refactoring required" }; } /// /// 生成 TODO 注释标记 /// public string GenerateTodoComment(ConversionIssue issue) { return $""" // TODO [CONVERSION]: {issue.Description} // Original: {issue.OriginalCode} // Suggestion: {issue.Suggestion ?? "Manual refactoring required"} // Severity: {issue.Severity} """; } /// /// 评估转换可行性 /// public ConversionFeasibility AssessFeasibility(string sourceCode, LanguageType sourceLanguage, LanguageType targetLanguage) { var issues = DetectUnconvertibleSyntax(sourceCode, sourceLanguage, targetLanguage); var highSeverity = issues.Count(i => i.Severity == "High"); var mediumSeverity = issues.Count(i => i.Severity == "Medium"); var lowSeverity = issues.Count(i => i.Severity == "Low"); var feasibility = new ConversionFeasibility { IsFeasible = highSeverity == 0 && mediumSeverity < 5, ConfidenceScore = CalculateConfidenceScore(issues), EstimatedManualEffort = CalculateEstimatedEffort(issues), CriticalIssues = issues.Where(i => i.Severity == "High").ToList(), AllIssues = issues }; return feasibility; } private int CalculateConfidenceScore(List issues) { var baseScore = 100; baseScore -= issues.Count(i => i.Severity == "High") * 20; baseScore -= issues.Count(i => i.Severity == "Medium") * 5; baseScore -= issues.Count(i => i.Severity == "Low") * 2; return Math.Max(0, Math.Min(100, baseScore)); } private string CalculateEstimatedEffort(List issues) { var totalScore = issues.Sum(i => i.Severity switch { nameof(IssueSeverity.High) => 4, nameof(IssueSeverity.Medium) => 2, nameof(IssueSeverity.Low) => 1, _ => 1 }); return totalScore switch { 0 => "No manual effort required", <= 3 => "Minimal (< 15 minutes)", <= 10 => "Low (15-30 minutes)", <= 20 => "Moderate (30-60 minutes)", > 20 => "High (> 1 hour)" }; } } /// /// 转换可行性评估结果 /// public class ConversionFeasibility { public bool IsFeasible { get; set; } public int ConfidenceScore { get; set; } // 0-100 public string EstimatedManualEffort { get; set; } = string.Empty; public List CriticalIssues { get; set; } = new(); public List AllIssues { get; set; } = new(); }