58 lines
2.2 KiB
C#
58 lines
2.2 KiB
C#
namespace gregExtractor.Services;
|
|
|
|
public sealed class RegexCoverageScanner : ICoverageScanner
|
|
{
|
|
private static readonly Regex PatchRegex = new(
|
|
@"\[HarmonyPatch\(typeof\(([^)]+)\),\s*nameof\(([^)]+)\)\)\]",
|
|
RegexOptions.Compiled | RegexOptions.CultureInvariant);
|
|
|
|
private readonly Dictionary<string, HashSet<string>> _matches = new(StringComparer.Ordinal);
|
|
|
|
public IReadOnlyDictionary<string, IReadOnlyCollection<string>> LastScanMatches => _matches
|
|
.ToDictionary(static x => x.Key, static x => (IReadOnlyCollection<string>)x.Value.ToArray(), StringComparer.Ordinal);
|
|
|
|
public HashSet<string> ScanImplementedPatches(string[] sourceDirs, IProgress<string>? progress)
|
|
{
|
|
_matches.Clear();
|
|
|
|
var keys = new HashSet<string>(StringComparer.Ordinal);
|
|
foreach (string dir in sourceDirs.Where(Directory.Exists))
|
|
{
|
|
foreach (string file in Directory.EnumerateFiles(dir, "*.cs", SearchOption.AllDirectories))
|
|
{
|
|
progress?.Report($"Regex scanning {file}");
|
|
string code = File.ReadAllText(file);
|
|
|
|
foreach (Match match in PatchRegex.Matches(code))
|
|
{
|
|
string typeName = match.Groups[1].Value.Replace("global::", string.Empty).Trim();
|
|
string methodExpr = match.Groups[2].Value.Trim();
|
|
int dotIndex = methodExpr.LastIndexOf('.');
|
|
string methodName = dotIndex >= 0 ? methodExpr[(dotIndex + 1)..].Trim() : methodExpr;
|
|
|
|
if (string.IsNullOrWhiteSpace(typeName) || string.IsNullOrWhiteSpace(methodName))
|
|
continue;
|
|
|
|
string key = NormalizeKey($"{typeName}::{methodName}");
|
|
keys.Add(key);
|
|
|
|
if (!_matches.TryGetValue(key, out HashSet<string>? files))
|
|
{
|
|
files = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
|
_matches[key] = files;
|
|
}
|
|
|
|
files.Add(file);
|
|
}
|
|
}
|
|
}
|
|
|
|
return keys;
|
|
}
|
|
|
|
private static string NormalizeKey(string key)
|
|
{
|
|
return key.Replace(" ", string.Empty);
|
|
}
|
|
}
|