using System.Reflection; using System.Text.RegularExpressions; using NodePipeline.Engine.CodeGeneration.Abstractions; using NodePipeline.Engine.CodeGeneration.Abstractions.Models; namespace NodePipeline.Engine.Tests.CodeGeneratorTests.Fixtures; internal static class TestHelper { private const string NullString = "null"; internal static string ExtractMethod(string code, string methodName) { var pattern = $@"\b[\w\<\> \[\] \s\?]+?\s+{methodName}(\s*\<[^>]+\>)?\s*\([^)]*\)\s*(where[^{{\r\n]*)?\s*\{{"; var regex = new Regex(pattern); var match = regex.Match(code); if (!match.Success) return string.Empty; var braceStart = code.IndexOf('{', match.Index + match.Length - 1); if (braceStart == -1) return string.Empty; var braceCount = 1; var pos = braceStart + 1; while (pos < code.Length && braceCount > 0) { switch (code[pos]) { case '{': braceCount++; break; case '}': braceCount--; break; } pos++; } return braceCount != 0 ? string.Empty : code.Substring(braceStart, pos - braceStart); } internal static string ExtractSwitchCase(string methodCode, string caseLabel) { var caseIndex = methodCode.IndexOf(caseLabel, StringComparison.Ordinal); if (caseIndex == -1) return string.Empty; var switchStart = methodCode.LastIndexOf("switch", caseIndex, StringComparison.Ordinal); if (switchStart == -1) return string.Empty; var braceStart = methodCode.IndexOf('{', switchStart); if (braceStart == -1) return string.Empty; var braceCount = 1; var pos = braceStart + 1; while (pos < methodCode.Length && braceCount > 0) { switch (methodCode[pos]) { case '{': braceCount++; break; case '}': braceCount--; break; } pos++; } var switchBlock = methodCode.Substring(braceStart + 1, pos - braceStart - 2); // Extract the specific case block var caseStart = switchBlock.IndexOf(caseLabel, StringComparison.Ordinal); if (caseStart == -1) return string.Empty; var casePos = caseStart + caseLabel.Length; var nextCaseIndex = switchBlock.IndexOf("case ", casePos, StringComparison.Ordinal); var defaultCaseIndex = switchBlock.IndexOf("default:", casePos, StringComparison.Ordinal); int caseEnd; switch (nextCaseIndex) { case -1 when defaultCaseIndex == -1: caseEnd = switchBlock.Length; break; case -1: caseEnd = defaultCaseIndex; break; default: { caseEnd = defaultCaseIndex == -1 ? nextCaseIndex : Math.Min(nextCaseIndex, defaultCaseIndex); break; } } var caseBlock = switchBlock.Substring(caseStart, caseEnd - caseStart).Trim(); return caseBlock; } internal static NodeModelBuilder.NodesModel GetNodeModel(string factoryMethodName) { //TODO: add interface; var method = typeof(TestNodeModelFactory).GetMethod(factoryMethodName, BindingFlags.Static | BindingFlags.NonPublic, Type.EmptyTypes); if (method == null) throw new Exception($"Method {factoryMethodName} was not found in TestNodeModelFactory"); return method.Invoke(null, null) as NodeModelBuilder.NodesModel ?? throw new Exception("Method result is not NodeModelBuilder.NodesModel"); } internal static NodeDescriptor GetNodeDescriptorFromMockNode(Type mockNodeType) { //TODO: add interface; var method = mockNodeType.GetMethod("GetDescriptor", BindingFlags.Static | BindingFlags.NonPublic, Type.EmptyTypes); if (method == null) throw new Exception($"Method GetDescriptor was not found for type {mockNodeType.FullName}"); return method.Invoke(null, null) as NodeDescriptor ?? throw new Exception("Method result is not GetDescriptor"); } internal static string NumberToString(int? value) { return value?.ToString() ?? NullString; } internal static string NumberToString(decimal? value) { return value?.ToString() ?? NullString; } }