/// <summary> /// Use a combination of file reading and reflection to get fields and source code for all recipes /// </summary> public List <(string id, string title, string description, string source)> GetRecipeSources(string sourcePath) { sourcePath = Path.GetFullPath(sourcePath); if (!File.Exists(Path.Combine(sourcePath, "IRecipe.cs"))) { throw new ArgumentException("IRecipe.cs can not be found in the given source colder"); } var sources = new List <(string id, string title, string description, string source)>(); string[] projectCsFiles = Directory.GetFiles(sourcePath, "*.cs", SearchOption.AllDirectories); foreach (string csFilePath in projectCsFiles) { string sourceCode = File.ReadAllText(csFilePath); // ensure the source code is not from this file if (Path.GetFileName(csFilePath) == "Chef.cs") { continue; } // ensure the start of the recipe is in the file string recipeStart = ": IRecipe"; if (!sourceCode.Contains(recipeStart)) { continue; } // isolate individual recipes from files with multiple recipes string[] sourceCodeByClass = sourceCode.Split( separator: new string[] { recipeStart }, options: StringSplitOptions.RemoveEmptyEntries) .Skip(1) .ToArray(); foreach (string singleClassSourceCode in sourceCodeByClass) { // ensure functions are at the correct indentation level int executionMethodCount = Regex.Matches(singleClassSourceCode, ExecutionMethod).Count; string indentedMethod = "\n " + ExecutionMethod; int indentedMethodCount = Regex.Matches(singleClassSourceCode, indentedMethod).Count; if (executionMethodCount != indentedMethodCount) { throw new InvalidOperationException($"recipe structure error in: {csFilePath}"); } // read the file's source code for primary recipe components string id = GetRecipeID(singleClassSourceCode); IRecipe recipe = Locate.GetRecipe(id); string source = $"var plt = new ScottPlot.Plot({Width}, {Height});\n\n" + GetRecipeSource(singleClassSourceCode, csFilePath) + "\n\n" + $"plt.SaveFig(\"{id}{Ext}\");"; sources.Add((recipe.ID, recipe.Title, recipe.Description, source)); } } return(sources); }
/// <summary> /// Use a combination of file reading and reflection to get fields and source code for all recipes /// </summary> public static RecipeSource[] GetRecipeSources(string sourcePath, int width, int height) { sourcePath = Path.GetFullPath(sourcePath); if (!File.Exists(Path.Combine(sourcePath, "IRecipe.cs"))) { throw new ArgumentException($"IRecipe.cs not be found in: {sourcePath}"); } List <RecipeSource> sources = new(); string[] projectCsFiles = Directory.GetFiles(sourcePath, "*.cs", SearchOption.AllDirectories); foreach (string csFilePath in projectCsFiles) { string sourceCode = File.ReadAllText(csFilePath); // ensure the source code is not from this file if (Path.GetFileName(csFilePath) == "Chef.cs") { continue; } // ensure the start of the recipe is in the file string recipeStart = ": IRecipe"; if (!sourceCode.Contains(recipeStart)) { continue; } // isolate individual recipes from files with multiple recipes string[] sourceCodeByClass = sourceCode.Split( separator: new string[] { recipeStart }, options: StringSplitOptions.RemoveEmptyEntries) .Skip(1) .ToArray(); foreach (string singleClassSourceCode in sourceCodeByClass) { // ensure functions are at the correct indentation level int executionMethodCount = Regex.Matches(singleClassSourceCode, ExecutionMethod).Count; string indentedMethod = "\n " + ExecutionMethod; int indentedMethodCount = Regex.Matches(singleClassSourceCode, indentedMethod).Count; if (executionMethodCount != indentedMethodCount) { throw new InvalidOperationException($"Source code parsing error in: {csFilePath}\n\n" + "This is typically caused by an error in indentation and whitespace before '{ExecutionMethod}'.\n\n" + "Ensure cookbook classes are standalone classes not encased by another class."); } // read the file's source code for primary recipe components string id = GetRecipeID(singleClassSourceCode); if (string.IsNullOrWhiteSpace(id)) { continue; } IRecipe recipe = Locate.GetRecipe(id); string source = $"var plt = new ScottPlot.Plot({width}, {height});\n\n" + GetRecipeSource(singleClassSourceCode, csFilePath) + "\n\n" + $"plt.SaveFig(\"{id}.png\");"; sources.Add(new RecipeSource(recipe, source)); } } return(sources.ToArray()); }