Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 103 additions & 2 deletions src/GitHub.Exports/Models/DiffUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Text.RegularExpressions;
using System.Diagnostics.CodeAnalysis;
using GitHub.Extensions;
using System.Linq;

#pragma warning disable CA1034 // Nested types should not be visible

Expand Down Expand Up @@ -57,8 +58,10 @@ public static IEnumerable<DiffChunk> ParseFragment(string diff)
chunk.Lines.Add(new DiffLine
{
Type = type,
OldLineNumber = type != DiffChangeType.Add ? oldLine : -1,
NewLineNumber = type != DiffChangeType.Delete ? newLine : -1,
//OldLineNumber = type != DiffChangeType.Add ? oldLine : -1,
//NewLineNumber = type != DiffChangeType.Delete ? newLine : -1,
OldLineNumber = oldLine,
NewLineNumber = newLine,
DiffLineNumber = diffLine,
Content = line,
});
Expand Down Expand Up @@ -92,12 +95,36 @@ public static IEnumerable<DiffChunk> ParseFragment(string diff)
}

public static DiffLine Match(IEnumerable<DiffChunk> diff, IList<DiffLine> target)
{
var diffLine = MatchLine(diff, target);
if (diffLine != null)
{
return diffLine;
}

diffLine = MatchLineIgnoreComments(diff, target);
if (diffLine != null)
{
return diffLine;
}

diffLine = MatchChunk(diff, target);
if (diffLine != null)
{
return diffLine;
}

return null;
}

public static DiffLine MatchChunk(IEnumerable<DiffChunk> diff, IList<DiffLine> target)
{
if (target.Count == 0)
{
return null; // no lines to match
}

int j = 0;
foreach (var source in diff)
{
var matches = 0;
Expand All @@ -122,6 +149,80 @@ public static DiffLine Match(IEnumerable<DiffChunk> diff, IList<DiffLine> target
return null;
}

public static DiffLine MatchLine(IEnumerable<DiffChunk> chunks1, IList<DiffLine> targetLines)
{
var targetLine = targetLines.FirstOrDefault();
if (targetLine == null)
{
return null;
}

foreach (var chunk in chunks1)
{
foreach (var line in chunk.Lines)
{
if (targetLine.OldLineNumber == line.OldLineNumber)
{
if(targetLine.Content == line.Content)
{
return line;
}
}
}
}

return null;
}

public static DiffLine MatchLineIgnoreComments(IEnumerable<DiffChunk> chunks1, IList<DiffLine> targetLines)
{
var ignoreChars = new[] { ' ', '\t', '/' };

var targetLine = targetLines.FirstOrDefault();
if (targetLine == null)
{
return null;
}

foreach (var chunk in chunks1)
{
bool loose = false;
foreach (var line in chunk.Lines)
{
if (targetLine.OldLineNumber == line.OldLineNumber || loose)
{
var targetContent = targetLine.Content;
var lineContent = line.Content;
if (targetContent == lineContent)
{
return line;
}

targetContent = GetSignificantContent(targetContent, ignoreChars);
lineContent = GetSignificantContent(lineContent, ignoreChars);
if (targetContent == lineContent)
{
if (line.Type == DiffChangeType.Delete)
{
loose = true;
}
else
{
return line;
}
}
}
}
}

return null;
}

static string GetSignificantContent(string content, char[] ignoreChars)
{
return content.Substring(1).TrimStart(ignoreChars);
}

/// Here are some alternative implementations we tried:
/// https://gist.github.com/shana/200e4719d4f571caab9dbf5921fa5276
/// Scanning with `text.IndexOf('\n', index)` appears to the the best compromise for average .diff files.
Expand Down
Loading