using System.Text.RegularExpressions; namespace StellaOps.ElkSharp; public sealed record ElkSharpSourceProfile { public required string SourceName { get; init; } public int LineCount { get; init; } public int CharacterCount { get; init; } public int FunctionCount { get; init; } public int DefineClassCount { get; init; } public int CreateForClassCount { get; init; } public int InternConstantCount { get; init; } public int LayoutCommandCount { get; init; } public int RegisterAlgorithmCount { get; init; } } public static partial class ElkSharpSourceAnalyzer { [GeneratedRegex(@"(?m)^\s*function\s+[A-Za-z0-9_$]+\s*\(", RegexOptions.CultureInvariant)] private static partial Regex FunctionRegex(); [GeneratedRegex(@"defineClass\(", RegexOptions.CultureInvariant)] private static partial Regex DefineClassRegex(); [GeneratedRegex(@"createForClass\(", RegexOptions.CultureInvariant)] private static partial Regex CreateForClassRegex(); [GeneratedRegex(@"\$intern_", RegexOptions.CultureInvariant)] private static partial Regex InternConstantRegex(); [GeneratedRegex(@"cmd:\s*'layout'|layout_[0-9]+\(", RegexOptions.CultureInvariant)] private static partial Regex LayoutCommandRegex(); [GeneratedRegex(@"registerLayoutAlgorithms\(", RegexOptions.CultureInvariant)] private static partial Regex RegisterAlgorithmRegex(); public static ElkSharpSourceProfile Analyze(string sourceName, string sourceText) { ArgumentException.ThrowIfNullOrWhiteSpace(sourceName); ArgumentNullException.ThrowIfNull(sourceText); return new ElkSharpSourceProfile { SourceName = sourceName, LineCount = CountLines(sourceText), CharacterCount = sourceText.Length, FunctionCount = FunctionRegex().Matches(sourceText).Count, DefineClassCount = DefineClassRegex().Matches(sourceText).Count, CreateForClassCount = CreateForClassRegex().Matches(sourceText).Count, InternConstantCount = InternConstantRegex().Matches(sourceText).Count, LayoutCommandCount = LayoutCommandRegex().Matches(sourceText).Count, RegisterAlgorithmCount = RegisterAlgorithmRegex().Matches(sourceText).Count, }; } public static async Task AnalyzeFileAsync( string path, CancellationToken cancellationToken = default) { ArgumentException.ThrowIfNullOrWhiteSpace(path); var sourceText = await File.ReadAllTextAsync(path, cancellationToken); return Analyze(Path.GetFileName(path), sourceText); } private static int CountLines(string text) { if (text.Length == 0) { return 0; } var lines = 1; foreach (var character in text) { if (character == '\n') { ++lines; } } return lines; } }