Initial commit to new repository

This commit is contained in:
2026-04-03 18:22:19 +09:00
commit 4458bb0f52
7672 changed files with 452440 additions and 0 deletions

View File

@@ -0,0 +1,99 @@
namespace AxCopilot.Services;
/// <summary>
/// 라인 기반 텍스트 diff 서비스. 두 텍스트의 변경 사항을 비교합니다.
/// </summary>
public static class DiffService
{
public enum DiffType { Equal, Added, Removed }
public record DiffLine(DiffType Type, int? OldLineNo, int? NewLineNo, string Content);
/// <summary>두 텍스트를 라인 단위로 비교하여 diff 결과를 반환합니다.</summary>
public static List<DiffLine> ComputeDiff(string oldText, string newText)
{
var oldLines = (oldText ?? "").Split('\n');
var newLines = (newText ?? "").Split('\n');
var result = new List<DiffLine>();
// LCS (Longest Common Subsequence) 기반 간단 diff
var lcs = ComputeLcs(oldLines, newLines);
int oi = 0, ni = 0, li = 0;
while (oi < oldLines.Length || ni < newLines.Length)
{
if (li < lcs.Count && oi < oldLines.Length && ni < newLines.Length &&
oldLines[oi].TrimEnd('\r') == lcs[li] && newLines[ni].TrimEnd('\r') == lcs[li])
{
result.Add(new DiffLine(DiffType.Equal, oi + 1, ni + 1, oldLines[oi].TrimEnd('\r')));
oi++; ni++; li++;
}
else if (li < lcs.Count && oi < oldLines.Length &&
oldLines[oi].TrimEnd('\r') != lcs[li])
{
result.Add(new DiffLine(DiffType.Removed, oi + 1, null, oldLines[oi].TrimEnd('\r')));
oi++;
}
else if (ni < newLines.Length &&
(li >= lcs.Count || newLines[ni].TrimEnd('\r') != lcs[li]))
{
result.Add(new DiffLine(DiffType.Added, null, ni + 1, newLines[ni].TrimEnd('\r')));
ni++;
}
else
{
// 나머지 처리
if (oi < oldLines.Length)
{
result.Add(new DiffLine(DiffType.Removed, oi + 1, null, oldLines[oi].TrimEnd('\r')));
oi++;
}
if (ni < newLines.Length)
{
result.Add(new DiffLine(DiffType.Added, null, ni + 1, newLines[ni].TrimEnd('\r')));
ni++;
}
}
}
return result;
}
private static List<string> ComputeLcs(string[] a, string[] b)
{
int m = a.Length, n = b.Length;
var dp = new int[m + 1, n + 1];
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++)
dp[i, j] = a[i - 1].TrimEnd('\r') == b[j - 1].TrimEnd('\r')
? dp[i - 1, j - 1] + 1
: Math.Max(dp[i - 1, j], dp[i, j - 1]);
// 역추적
var lcs = new List<string>();
int x = m, y = n;
while (x > 0 && y > 0)
{
if (a[x - 1].TrimEnd('\r') == b[y - 1].TrimEnd('\r'))
{
lcs.Add(a[x - 1].TrimEnd('\r'));
x--; y--;
}
else if (dp[x - 1, y] > dp[x, y - 1])
x--;
else
y--;
}
lcs.Reverse();
return lcs;
}
/// <summary>diff 결과를 통계 요약 문자열로 반환합니다.</summary>
public static string GetSummary(List<DiffLine> diff)
{
int added = diff.Count(d => d.Type == DiffType.Added);
int removed = diff.Count(d => d.Type == DiffType.Removed);
return $"+{added} -{removed} 라인 변경";
}
}