From 35f8177ca508b65df7f698d963c957968c3a243c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thyge=20Sk=C3=B8dt=20Steffensen?= <31892312+thygesteffensen@users.noreply.github.com> Date: Thu, 2 Nov 2023 09:31:14 +0100 Subject: [PATCH 01/10] feat: Extract Plugin documentation version 1 --- .editorconfig | 4 + ...tensions.Manifest.ManifestEnricherTool.sln | 7 ++ .../AssemblyInfo.cs | 9 ++ .../CustomAssemblyResolver.cs | 36 ++++++ .../DocumentLogic.cs | 74 ++++++++++++ .../EAVFW.Extensions.Docs.Extracter.csproj | 17 +++ .../IDocumentLogic.cs | 15 +++ .../PluginDocumentation.cs | 34 ++++++ .../PluginInfo.cs | 28 +++++ .../XmlDocumentationHelper.cs | 65 ++++++++++ .../XmlMemberElement.cs | 12 ++ .../Commands/DocumentCommand.cs | 111 ++++++++++++++++++ ...sions.Manifest.ManifestEnricherTool.csproj | 5 +- .../Program.cs | 4 + .../Properties/launchSettings.json | 6 +- 15 files changed, 424 insertions(+), 3 deletions(-) create mode 100644 .editorconfig create mode 100644 src/EAVFW.Extensions.Docs.Extracter/AssemblyInfo.cs create mode 100644 src/EAVFW.Extensions.Docs.Extracter/CustomAssemblyResolver.cs create mode 100644 src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs create mode 100644 src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj create mode 100644 src/EAVFW.Extensions.Docs.Extracter/IDocumentLogic.cs create mode 100644 src/EAVFW.Extensions.Docs.Extracter/PluginDocumentation.cs create mode 100644 src/EAVFW.Extensions.Docs.Extracter/PluginInfo.cs create mode 100644 src/EAVFW.Extensions.Docs.Extracter/XmlDocumentationHelper.cs create mode 100644 src/EAVFW.Extensions.Docs.Extracter/XmlMemberElement.cs create mode 100644 src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..5b462cc --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +root = true + +[*] +insert_final_newline = true diff --git a/EAVFW.Extensions.Manifest.ManifestEnricherTool.sln b/EAVFW.Extensions.Manifest.ManifestEnricherTool.sln index 3120658..283985b 100644 --- a/EAVFW.Extensions.Manifest.ManifestEnricherTool.sln +++ b/EAVFW.Extensions.Manifest.ManifestEnricherTool.sln @@ -44,6 +44,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EAVFramework", "external\EA EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EAVFW.Extensions.Manifest.SDK", "external\EAVFramework\sdk\EAVFW.Extensions.Manifest.SDK.csproj", "{3BEF0769-ABD1-4D34-8004-C98DE9FB0339}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EAVFW.Extensions.Docs.Extracter", "src\EAVFW.Extensions.Docs.Extracter\EAVFW.Extensions.Docs.Extracter.csproj", "{432042AB-6A78-4ED7-B8AC-73B047F6630F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -64,6 +66,10 @@ Global {2F30C24A-421A-4309-9F07-99668EA70C25}.Debug|Any CPU.Build.0 = Debug|Any CPU {3BEF0769-ABD1-4D34-8004-C98DE9FB0339}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3BEF0769-ABD1-4D34-8004-C98DE9FB0339}.Debug|Any CPU.Build.0 = Debug|Any CPU + {432042AB-6A78-4ED7-B8AC-73B047F6630F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {432042AB-6A78-4ED7-B8AC-73B047F6630F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {432042AB-6A78-4ED7-B8AC-73B047F6630F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {432042AB-6A78-4ED7-B8AC-73B047F6630F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -75,6 +81,7 @@ Global {79505337-2855-4CC7-8FD3-D5AF31B18278} = {CAE8FBC9-BDC3-4F45-81E1-57506D609011} {2F30C24A-421A-4309-9F07-99668EA70C25} = {CAE8FBC9-BDC3-4F45-81E1-57506D609011} {3BEF0769-ABD1-4D34-8004-C98DE9FB0339} = {CAE8FBC9-BDC3-4F45-81E1-57506D609011} + {432042AB-6A78-4ED7-B8AC-73B047F6630F} = {0D61C87C-0809-4CD7-9200-D78AD11A1E22} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {036D5D82-DDA4-4600-B190-739D512F1062} diff --git a/src/EAVFW.Extensions.Docs.Extracter/AssemblyInfo.cs b/src/EAVFW.Extensions.Docs.Extracter/AssemblyInfo.cs new file mode 100644 index 0000000..d76edcc --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Extracter/AssemblyInfo.cs @@ -0,0 +1,9 @@ +namespace EAVFW.Extensions.Docs.Extracter +{ + public class AssemblyInfo + { + public string Name { get; set; } = ""; + public string Version { get; set; } = ""; + public string Path { get; set; } + } +} diff --git a/src/EAVFW.Extensions.Docs.Extracter/CustomAssemblyResolver.cs b/src/EAVFW.Extensions.Docs.Extracter/CustomAssemblyResolver.cs new file mode 100644 index 0000000..a2922f3 --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Extracter/CustomAssemblyResolver.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace EAVFW.Extensions.Docs.Extracter +{ + public static class CustomAssemblyResolver + { + public static Dictionary Dictionary { get; set; } = new(); + + public static Assembly? CustomAssemblyResolverEventHandler(object? sender, ResolveEventArgs args) + { + // Ignore missing resources + if (args.Name.Contains(".resources")) + return null; + + // check for assemblies already loaded + var assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName == args.Name); + if (assembly != null) + return assembly; + + if (!Dictionary.TryGetValue(args.Name.Split(',').First(), out var assemblyInfo)) + return null; + + try + { + return Assembly.LoadFrom(assemblyInfo.Path); + } + catch (Exception) + { + return null; + } + } + } +} diff --git a/src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs b/src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs new file mode 100644 index 0000000..32535de --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.Loader; +using EAVFramework.Plugins; + +namespace EAVFW.Extensions.Docs.Extracter +{ + public class DocumentLogic : IDocumentLogic + { + private static Dictionary BuildAssemblyDictionary(IEnumerable binDirectories) + { + var dictionary = new Dictionary(); + + foreach (var directory in binDirectories) + { + var dlls = Directory.GetFiles(directory, "*.dll"); + foreach (var dll in dlls) + { + var assemblyName = AssemblyName.GetAssemblyName(dll); + + dictionary.TryAdd(assemblyName.Name!, new AssemblyInfo + { + Name = assemblyName.Name!, + Version = assemblyName.Version!.ToString(), + Path = dll + }); + } + } + + return dictionary; + } + + /// + public IEnumerable ExtractPluginDocumentation(PluginInfo pluginInfo) + { + var subDirectories = pluginInfo.RootPath.EnumerateDirectories("*", SearchOption.AllDirectories); + + var directoriesWithBin = + from d in subDirectories + where d.FullName.EndsWith($"bin/{pluginInfo.Configuration}/{pluginInfo.Framework}") + select d.FullName; + + CustomAssemblyResolver.Dictionary = BuildAssemblyDictionary(directoriesWithBin.AsQueryable()); + + var currentDomain = AppDomain.CurrentDomain; + currentDomain.AssemblyResolve += CustomAssemblyResolver.CustomAssemblyResolverEventHandler; + + var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(pluginInfo.AssemblyPath.FullName); + + var implementingTypes = assembly.GetTypes() + .Where(t => typeof(IPlugin).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract); + + var plugins = + from implementingType in implementingTypes + let pluginRegistrations = implementingType.GetCustomAttributes() + let interface2 = implementingType.GetInterfaces() + .FirstOrDefault(i => i.GenericTypeArguments.Length == 2) + select new PluginDocumentation + { + PluginRegistrations = pluginRegistrations, + Name = implementingType.Name, + Summary = implementingType.GetDocumentation(), + Context = interface2.GetGenericArguments().First(), + Entity = interface2.GetGenericArguments().Last() + }; + + return plugins; + } + } +} diff --git a/src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj b/src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj new file mode 100644 index 0000000..f7d8b2d --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj @@ -0,0 +1,17 @@ + + + + 9.0 + net6.0 + enable + + + + + + + + + + + diff --git a/src/EAVFW.Extensions.Docs.Extracter/IDocumentLogic.cs b/src/EAVFW.Extensions.Docs.Extracter/IDocumentLogic.cs new file mode 100644 index 0000000..eb39f45 --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Extracter/IDocumentLogic.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace EAVFW.Extensions.Docs.Extracter +{ + public interface IDocumentLogic + { + /// + /// Extract plugin metadata and summary from given Assembly using the DLL and .xml documentation files + /// created during a build. + /// + /// Remember to enable GenerateDocumentationFile for the project. + /// + IEnumerable ExtractPluginDocumentation(PluginInfo pluginInfo); + } +} diff --git a/src/EAVFW.Extensions.Docs.Extracter/PluginDocumentation.cs b/src/EAVFW.Extensions.Docs.Extracter/PluginDocumentation.cs new file mode 100644 index 0000000..b1830f2 --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Extracter/PluginDocumentation.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json.Serialization; +using EAVFramework.Plugins; + +namespace EAVFW.Extensions.Docs.Extracter +{ + public class PluginDocumentation + { + [JsonIgnore] + public IEnumerable PluginRegistrations { get; set; } = + Array.Empty(); + + public string? Name { get; set; } + + [JsonIgnore] + public Type? Context { get; set; } + [JsonIgnore] + public Type? Entity { get; set; } + public string Summary { get; set; } = ""; + + + public override string ToString() + { + var summary = Summary?.Split("\n").Select(x => x.Trim()).ToArray() ?? Array.Empty(); + return $"Plugin: {Name} on {Entity.Name}\n* " + + string.Join("\n* ", PluginRegistrations.Select(x => $"{x.Operation} on {x.Execution} as {x.Order}")) + + '\n' + + string.Join('\n', summary) + + "\n\n"; + } + } +} diff --git a/src/EAVFW.Extensions.Docs.Extracter/PluginInfo.cs b/src/EAVFW.Extensions.Docs.Extracter/PluginInfo.cs new file mode 100644 index 0000000..f26bf60 --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Extracter/PluginInfo.cs @@ -0,0 +1,28 @@ +using System; +using System.IO; + +namespace EAVFW.Extensions.Docs.Extracter +{ + public struct PluginInfo + { + public PluginInfo(DirectoryInfo rootPath, FileInfo assemblyPath, string configuration, string framework) + { + RootPath = !rootPath.Exists + ? throw new ArgumentException($"Directory {nameof(rootPath)} does not exists") + : rootPath; + AssemblyPath = !assemblyPath.Exists + ? throw new ArgumentException($"File {nameof(assemblyPath)} does not exists") + : assemblyPath; + + Configuration = string.IsNullOrWhiteSpace(configuration) + ? throw new ArgumentNullException(configuration) + : configuration; + Framework = string.IsNullOrWhiteSpace(framework) ? throw new ArgumentNullException(framework) : framework; + } + + public DirectoryInfo RootPath { get; } + public FileInfo AssemblyPath { get; } + public string Configuration { get; } + public string Framework { get; } + } +} diff --git a/src/EAVFW.Extensions.Docs.Extracter/XmlDocumentationHelper.cs b/src/EAVFW.Extensions.Docs.Extracter/XmlDocumentationHelper.cs new file mode 100644 index 0000000..e8f7565 --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Extracter/XmlDocumentationHelper.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Xml; +using System.Xml.Serialization; + +namespace EAVFW.Extensions.Docs.Extracter +{ + public static class XmlDocumentationHelper + { + private static readonly Dictionary LoadedXmlDocumentation = new(); + private static readonly HashSet LoadedAssemblies = new(); + + public static string? GetDocumentation(this Type type) + { + LoadXmlDocumentation(type.Assembly); + + var key = $"T:{type.FullName}"; + LoadedXmlDocumentation.TryGetValue(key, out var docs); + return docs; + } + + private static void LoadXmlDocumentation(Assembly assembly) + { + if (LoadedAssemblies.Contains(assembly)) + return; // Already loaded + + var directoryPath = Path.GetDirectoryName(assembly.Location); + if (string.IsNullOrEmpty(directoryPath)) + return; + + var xmlFilePath = Path.Combine(directoryPath, assembly.GetName().Name + ".xml"); + + if (!File.Exists(xmlFilePath)) return; + + using var xmlReader = XmlReader.Create(new StringReader(File.ReadAllText(xmlFilePath))); + + + var started = false; + var name = ""; + while (xmlReader.Read()) + { + if (xmlReader.Name == "member") + { + started = true; + name = xmlReader.GetAttribute("name"); + continue; + } + + if (xmlReader is { Name: "member", NodeType: XmlNodeType.EndElement } && started) + { + name = ""; + started = false; + continue; + } + + if (xmlReader.Name == "summary" && !string.IsNullOrWhiteSpace(name)) + LoadedXmlDocumentation[name] = xmlReader.ReadInnerXml(); + } + + LoadedAssemblies.Add(assembly); + } + } +} diff --git a/src/EAVFW.Extensions.Docs.Extracter/XmlMemberElement.cs b/src/EAVFW.Extensions.Docs.Extracter/XmlMemberElement.cs new file mode 100644 index 0000000..ce53ecf --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Extracter/XmlMemberElement.cs @@ -0,0 +1,12 @@ +using System.Xml.Serialization; + +namespace EAVFW.Extensions.Docs.Extracter +{ + [XmlRoot("member")] + public class XmlMemberElement + { + [XmlAttribute("name")] public string Name { get; set; } + + [XmlElement("summary")] public string Summary { get; set; } + } +} diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs new file mode 100644 index 0000000..b392f03 --- /dev/null +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Parsing; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text.Json; +using System.Threading.Tasks; +using EAVFW.Extensions.Docs.Extracter; + +namespace EAVFW.Extensions.Manifest.ManifestEnricherTool.Commands +{ + public class DocumentCommand : Command + { + private readonly IDocumentLogic documentLogic; + + + [Alias("-a")] + [Alias("--assembly")] + [Description("Path for the assembly")] + public FileInfo AssemblyPathOption { get; set; } + + [Alias("-p")] + [Alias("--probing-path")] + [Description("Path to probe for dependent assemblies")] + public DirectoryInfo RootPathOption { get; set; } + + [Alias("-c")] + [Alias("--configuration")] + [Description("Configuration for the built assembly")] + public string ConfigurationOption { get; set; } + + [Alias("-f")] + [Alias("--framework")] + [Description("Framework confugraiton for the built assembly")] + public string FrameworkOption { get; set; } + + + public DocumentCommand(IDocumentLogic documentLogic) : base("docs", "Generate documentation") + { + this.documentLogic = documentLogic ?? throw new ArgumentNullException(nameof(documentLogic)); + Handler = COmmandExtensions.Create(this, Array.Empty(), Run); + } + + private async Task Run(ParseResult parseResult, IConsole console) + { + if (IsMissingOptions(out var missing)) + { + Console.WriteLine("The following options are missed: " + string.Join(", ", missing)); + return 126; + } + + if (!RootPathOption.Exists) + { + Console.WriteLine("Probing path does not exists"); + return 1; + } + + if (!AssemblyPathOption.Exists) + { + Console.WriteLine("Assembly does not exists"); + return 1; + } + + var plugins = documentLogic + .ExtractPluginDocumentation(new PluginInfo(RootPathOption, AssemblyPathOption, ConfigurationOption, FrameworkOption)) + .ToArray(); + + var jsonString = JsonSerializer.Serialize(plugins, new JsonSerializerOptions + { + WriteIndented = true + }); + await File.WriteAllTextAsync("docs.json", jsonString); + + var groups = plugins.GroupBy(x => x.Entity!.Name); + + Console.WriteLine("# Plugins "); + foreach (var group in groups) + { + Console.WriteLine($"## {group.FirstOrDefault()?.Entity?.Name}"); + foreach (var pluginDocumentation in group) + { + Console.WriteLine(pluginDocumentation.ToString()); + } + } + + + return 0; + } + + private bool IsMissingOptions(out List missing) + { + missing = new List(); + + if (AssemblyPathOption == null) + missing.Add(nameof(AssemblyPathOption)); + + if (RootPathOption == null) + missing.Add(nameof(RootPathOption)); + + if (string.IsNullOrWhiteSpace(ConfigurationOption)) + missing.Add(nameof(ConfigurationOption)); + + if (string.IsNullOrWhiteSpace(FrameworkOption)) + missing.Add(nameof(FrameworkOption)); + + return false; + } + } +} diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj index 265b1f6..bf75144 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj @@ -48,4 +48,7 @@ - \ No newline at end of file + + + + diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Program.cs b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Program.cs index d71f536..81bfd86 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Program.cs +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Program.cs @@ -9,6 +9,7 @@ using Microsoft.Extensions.Logging; using System.CommandLine; using System.Threading.Tasks; +using EAVFW.Extensions.Docs.Extracter; using EAVFW.Extensions.Manifest.ManifestEnricherTool.Commands.Gzip; namespace EAVFW.Extensions.Manifest.ManifestEnricherTool @@ -28,11 +29,14 @@ static IServiceCollection ConfigureServices(IServiceCollection serviceCollection .AddManifestSDK() .AddSingleton(); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); serviceCollection.AddGPT(); serviceCollection.AddHttpClient(); diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json index aed73ed..7c30d12 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json @@ -3,7 +3,9 @@ "EAVFW.Extensions.Manifest.ManifestEnricherTool": { "commandName": "Project", "workingDirectory": "/Users/thyge/dev/playground", - "commandLineArgs": "binary --unzip 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" + "commandLineArgs": "docs -c Release -f net6.0 -a \"/Users/thyge/dev/hafnia/Letter of Indemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/Letter of Indemnity\"" +// "commandLineArgs": "binary --unzip 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" +// "commandLineArgs": "binary --unzip 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" // "commandLineArgs": "binary --unzip --pretty-print 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" // "commandLineArgs": "binary --unzip --pretty-print --output myjsonfile.json 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" // "commandLineArgs": "binary --zip {\"actions\":{\"CreateLOIDataRequestMessageAction\":{\"input\":{\"loirequest\":\"a4dd227a-efab-4cb5-3e2a-08dbcaf45591\",\"recipients\":[\"1504bf2f-cf6e-49c9-df39-08dbcaf6aa88\"]},\"status\":\"Succeded\",\"body\":\"a4dd227a-efab-4cb5-3e2a-08dbcaf45591\",\"failedReason\":null}},\"triggers\":{\"Trigger\":{\"time\":\"2023-10-12T07:41:42.311509+00:00\",\"body\":{\"entityName\":\"LetterofindemnityRequests\",\"recordId\":\"a4dd227a-efab-4cb5-3e2a-08dbcaf45591\",\"data\":{\"recipients\":[\"1504bf2f-cf6e-49c9-df39-08dbcaf6aa88\"]}}}}}" @@ -24,4 +26,4 @@ //"commandLineArgs": "--path C:\\dev\\hafnia\\loi\\src\\Hafnia.Models\\manifest.json --customizationprefix hafnia" } } -} \ No newline at end of file +} From af5f52b7682668494ecafc708c29661d155c8c19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thyge=20Sk=C3=B8dt=20Steffensen?= <31892312+thygesteffensen@users.noreply.github.com> Date: Wed, 8 Nov 2023 16:45:03 +0100 Subject: [PATCH 02/10] feat: Working version with Wizards --- .gitignore | 1 + ....ManifestEnricherTool.sln.DotSettings.user | 4 + .../DocumentLogic.cs | 121 +++++++++++++++--- .../IDocumentLogic.cs | 11 ++ .../{ => Plugin}/AssemblyInfo.cs | 0 .../{ => Plugin}/PluginDocumentation.cs | 0 .../{ => Plugin}/PluginInfo.cs | 0 .../{ => Plugin}/XmlDocumentationHelper.cs | 1 - .../{ => Plugin}/XmlMemberElement.cs | 0 .../Wizard/Wizards.cs | 101 +++++++++++++++ .../Commands/DocumentCommand.cs | 54 +++++++- ...sions.Manifest.ManifestEnricherTool.csproj | 2 +- .../Properties/launchSettings.json | 3 +- .../EAVFW.Extensions.Manifest.Tests.csproj | 1 + 14 files changed, 277 insertions(+), 22 deletions(-) create mode 100644 EAVFW.Extensions.Manifest.ManifestEnricherTool.sln.DotSettings.user rename src/EAVFW.Extensions.Docs.Extracter/{ => Plugin}/AssemblyInfo.cs (100%) rename src/EAVFW.Extensions.Docs.Extracter/{ => Plugin}/PluginDocumentation.cs (100%) rename src/EAVFW.Extensions.Docs.Extracter/{ => Plugin}/PluginInfo.cs (100%) rename src/EAVFW.Extensions.Docs.Extracter/{ => Plugin}/XmlDocumentationHelper.cs (98%) rename src/EAVFW.Extensions.Docs.Extracter/{ => Plugin}/XmlMemberElement.cs (100%) create mode 100644 src/EAVFW.Extensions.Docs.Extracter/Wizard/Wizards.cs diff --git a/.gitignore b/.gitignore index 5cb0f51..b4016f0 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ node_modules /.github/workflows/package-lock.json /artifacts *.csproj.user +.idea diff --git a/EAVFW.Extensions.Manifest.ManifestEnricherTool.sln.DotSettings.user b/EAVFW.Extensions.Manifest.ManifestEnricherTool.sln.DotSettings.user new file mode 100644 index 0000000..6f09b90 --- /dev/null +++ b/EAVFW.Extensions.Manifest.ManifestEnricherTool.sln.DotSettings.user @@ -0,0 +1,4 @@ + + <SessionState ContinuousTestingMode="0" IsActive="True" Name="ZipAndUnZipTests" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <Solution /> +</SessionState> \ No newline at end of file diff --git a/src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs b/src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs index 32535de..ebefaec 100644 --- a/src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs +++ b/src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs @@ -1,10 +1,11 @@ using System; using System.Collections.Generic; -using System.Diagnostics.Contracts; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.Loader; +using System.Text.Json; +using System.Text.Json.Serialization; using EAVFramework.Plugins; namespace EAVFW.Extensions.Docs.Extracter @@ -36,6 +37,30 @@ private static Dictionary BuildAssemblyDictionary(IEnumera /// public IEnumerable ExtractPluginDocumentation(PluginInfo pluginInfo) + { + var assembly = LoadAssembly(pluginInfo); + + var implementingTypes = assembly.GetTypes() + .Where(t => typeof(IPlugin).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract); + + var plugins = + from implementingType in implementingTypes + let pluginRegistrations = implementingType.GetCustomAttributes() + let _interface = implementingType.GetInterfaces() + .FirstOrDefault(i => i.GenericTypeArguments.Length == 2) + select new PluginDocumentation + { + PluginRegistrations = pluginRegistrations, + Name = implementingType.Name, + Summary = implementingType.GetDocumentation(), + Context = _interface.GetGenericArguments().First(), + Entity = _interface.GetGenericArguments().Last() + }; + + return plugins; + } + + private static Assembly LoadAssembly(PluginInfo pluginInfo) { var subDirectories = pluginInfo.RootPath.EnumerateDirectories("*", SearchOption.AllDirectories); @@ -50,25 +75,89 @@ where d.FullName.EndsWith($"bin/{pluginInfo.Configuration}/{pluginInfo.Framework currentDomain.AssemblyResolve += CustomAssemblyResolver.CustomAssemblyResolverEventHandler; var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(pluginInfo.AssemblyPath.FullName); + return assembly; + } - var implementingTypes = assembly.GetTypes() - .Where(t => typeof(IPlugin).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract); + /// + public IEnumerable ExtractWizardDocumentation(FileInfo manifestFile, PluginInfo pluginInfo) + { + var assembly = LoadAssembly(pluginInfo); - var plugins = - from implementingType in implementingTypes - let pluginRegistrations = implementingType.GetCustomAttributes() - let interface2 = implementingType.GetInterfaces() - .FirstOrDefault(i => i.GenericTypeArguments.Length == 2) - select new PluginDocumentation + // Preloading types to easily query for documentation + var workflows = + from type in assembly.GetTypes() + // where type.IsAbstract && typeof(Workflow).IsAssignableFrom(type) + select type; + + // Load manifest + + + using var openStream = manifestFile.OpenRead(); + var jsonManifest = JsonDocument.ParseAsync(openStream).Result; + + // Find Wizards + var simpleManifest = new Dictionary(); + ExtractEntitiesWithWizards(jsonManifest.RootElement, simpleManifest); + + + // Glorified for loop? + var tabsWithWorkflows = + from entity in simpleManifest + from wizard in entity.Value.Wizards + from tabs in wizard.Value.Tabs + where tabs.Value.OnTransitionOut?.Workflow != null && tabs.Value.OnTransitionIn?.Workflow != null + select tabs.Value; + + foreach (var tabsWithWorkflow in tabsWithWorkflows) + { + if (!string.IsNullOrWhiteSpace(tabsWithWorkflow?.OnTransitionOut?.Workflow)) { - PluginRegistrations = pluginRegistrations, - Name = implementingType.Name, - Summary = implementingType.GetDocumentation(), - Context = interface2.GetGenericArguments().First(), - Entity = interface2.GetGenericArguments().Last() - }; + var workflow = tabsWithWorkflow.OnTransitionOut.Workflow!; + // look for workflow in types? + Console.WriteLine(workflow); + } + } - return plugins; + foreach (var (key, wizard) in simpleManifest) + { + var t = JsonSerializer.Serialize(wizard, new JsonSerializerOptions + { + WriteIndented = true, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull + }); + Console.WriteLine(t); + } + + + // Generate Wizard object + + + // Return Wizard object + return new List(); + } + + private void ExtractEntitiesWithWizards(JsonElement element, IDictionary entities) + { + if (element.ValueKind != JsonValueKind.Object) return; + + foreach (var property in element.EnumerateObject()) + { + if (!property.NameEquals("entities") || property.Value.ValueKind != JsonValueKind.Object) continue; + + var localEntities = + JsonSerializer.Deserialize>(property.Value.GetRawText(), + new JsonSerializerOptions + { + Converters = { new TabConverter() } + }); + + if (localEntities == null) return; + + foreach (var (key, value) in localEntities.Where(x => x.Value?.Wizards?.Any() ?? false)) + { + entities[key] = value; + } + } } } } diff --git a/src/EAVFW.Extensions.Docs.Extracter/IDocumentLogic.cs b/src/EAVFW.Extensions.Docs.Extracter/IDocumentLogic.cs index eb39f45..ff95e3a 100644 --- a/src/EAVFW.Extensions.Docs.Extracter/IDocumentLogic.cs +++ b/src/EAVFW.Extensions.Docs.Extracter/IDocumentLogic.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.IO; namespace EAVFW.Extensions.Docs.Extracter { @@ -9,7 +10,17 @@ public interface IDocumentLogic /// created during a build. /// /// Remember to enable GenerateDocumentationFile for the project. + /// /// IEnumerable ExtractPluginDocumentation(PluginInfo pluginInfo); + + /// + /// Extract Wizards from the given Manifest and generate documentation based on manifest metadata and workflow + /// CLR types and Actions + /// + /// + /// + /// + IEnumerable ExtractWizardDocumentation(FileInfo manifestFile, PluginInfo pluginInfo); } } diff --git a/src/EAVFW.Extensions.Docs.Extracter/AssemblyInfo.cs b/src/EAVFW.Extensions.Docs.Extracter/Plugin/AssemblyInfo.cs similarity index 100% rename from src/EAVFW.Extensions.Docs.Extracter/AssemblyInfo.cs rename to src/EAVFW.Extensions.Docs.Extracter/Plugin/AssemblyInfo.cs diff --git a/src/EAVFW.Extensions.Docs.Extracter/PluginDocumentation.cs b/src/EAVFW.Extensions.Docs.Extracter/Plugin/PluginDocumentation.cs similarity index 100% rename from src/EAVFW.Extensions.Docs.Extracter/PluginDocumentation.cs rename to src/EAVFW.Extensions.Docs.Extracter/Plugin/PluginDocumentation.cs diff --git a/src/EAVFW.Extensions.Docs.Extracter/PluginInfo.cs b/src/EAVFW.Extensions.Docs.Extracter/Plugin/PluginInfo.cs similarity index 100% rename from src/EAVFW.Extensions.Docs.Extracter/PluginInfo.cs rename to src/EAVFW.Extensions.Docs.Extracter/Plugin/PluginInfo.cs diff --git a/src/EAVFW.Extensions.Docs.Extracter/XmlDocumentationHelper.cs b/src/EAVFW.Extensions.Docs.Extracter/Plugin/XmlDocumentationHelper.cs similarity index 98% rename from src/EAVFW.Extensions.Docs.Extracter/XmlDocumentationHelper.cs rename to src/EAVFW.Extensions.Docs.Extracter/Plugin/XmlDocumentationHelper.cs index e8f7565..1ae0044 100644 --- a/src/EAVFW.Extensions.Docs.Extracter/XmlDocumentationHelper.cs +++ b/src/EAVFW.Extensions.Docs.Extracter/Plugin/XmlDocumentationHelper.cs @@ -3,7 +3,6 @@ using System.IO; using System.Reflection; using System.Xml; -using System.Xml.Serialization; namespace EAVFW.Extensions.Docs.Extracter { diff --git a/src/EAVFW.Extensions.Docs.Extracter/XmlMemberElement.cs b/src/EAVFW.Extensions.Docs.Extracter/Plugin/XmlMemberElement.cs similarity index 100% rename from src/EAVFW.Extensions.Docs.Extracter/XmlMemberElement.cs rename to src/EAVFW.Extensions.Docs.Extracter/Plugin/XmlMemberElement.cs diff --git a/src/EAVFW.Extensions.Docs.Extracter/Wizard/Wizards.cs b/src/EAVFW.Extensions.Docs.Extracter/Wizard/Wizards.cs new file mode 100644 index 0000000..4204c2a --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Extracter/Wizard/Wizards.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace EAVFW.Extensions.Docs.Extracter +{ + public class Entity + { + [JsonPropertyName("wizards")] public Dictionary Wizards { get; set; } + } + + public class Wizard + { + [JsonPropertyName("title")] public string Title { get; set; } + + [JsonPropertyName("triggers")] public JsonElement Triggers { get; set; } + + [JsonPropertyName("tabs")] public Dictionary Tabs { get; set; } + } + + public struct Trigger + { + [JsonPropertyName("form")] public string Form { get; set; } + + [JsonPropertyName("ribbon")] public string Ribbon { get; set; } + } + + public class Tab + { + [JsonPropertyName("columns")] public JsonElement Columns { get; set; } + + [JsonPropertyName("visible")] public StringOrBoolean StringOrBoolean { get; set; } + + [JsonPropertyName("onTransitionOut")] public Transition? OnTransitionOut { get; set; } + + [JsonPropertyName("onTransitionIn")] public Transition? OnTransitionIn { get; set; } + + [JsonPropertyName("actions")] public JsonElement? Actions { get; set; } // TODO: This also needs to be enriched + } + + public struct StringOrBoolean + { + public StringOrBoolean(string stringValue) + { + StringValue = stringValue; + IsBool = false; + BooleanValue = default; + } + + public StringOrBoolean(bool booleanValue) + { + StringValue = default; + IsBool = false; + BooleanValue = booleanValue; + } + + public string? StringValue { get; } + + public bool BooleanValue { get; } + + public bool IsBool { get; } + } + + + public class TabConverter : JsonConverter + { + public override StringOrBoolean Read(ref Utf8JsonReader reader, Type typeToConvert, + JsonSerializerOptions options) + { + return reader.TokenType switch + { + JsonTokenType.String => new StringOrBoolean(reader.GetString() ?? ""), + JsonTokenType.False => new StringOrBoolean(false), + JsonTokenType.True => new StringOrBoolean(true), + _ => new StringOrBoolean() + }; + } + + public override void Write(Utf8JsonWriter writer, StringOrBoolean value, JsonSerializerOptions options) + { + if (value.IsBool) + writer.WriteBooleanValue(value.BooleanValue); + writer.WriteStringValue(value.StringValue); + } + } + + public class Transition + { + [JsonPropertyName("workflow")] public string? Workflow { get; set; } + + [JsonPropertyName("workflowSummary")] public string? WorkflowSummary { get; set; } + + [JsonPropertyName("message")] public Message? Message { get; set; } + } + + public class Message + { + [JsonPropertyName("title")] public string? Title { get; set; } + } +} diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs index b392f03..1384c3a 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs @@ -20,6 +20,11 @@ public class DocumentCommand : Command [Alias("--assembly")] [Description("Path for the assembly")] public FileInfo AssemblyPathOption { get; set; } + + [Alias("-m")] + [Alias("--manifest")] + [Description("Path for the manifest")] + public FileInfo ManifestPathOption { get; set; } [Alias("-p")] [Alias("--probing-path")] @@ -35,6 +40,19 @@ public class DocumentCommand : Command [Alias("--framework")] [Description("Framework confugraiton for the built assembly")] public string FrameworkOption { get; set; } + + + + [Alias("-t")] + [Alias("--target")] + [Description("Target?")] + public Targets Target { get; set; } + + public enum Targets + { + Plugins, + Wizards + } public DocumentCommand(IDocumentLogic documentLogic) : base("docs", "Generate documentation") @@ -62,9 +80,40 @@ private async Task Run(ParseResult parseResult, IConsole console) Console.WriteLine("Assembly does not exists"); return 1; } + + switch (Target) + { + case Targets.Plugins: + return await HandlePlugins(); + case Targets.Wizards: + return await HandleWizards(); + default: + throw new ArgumentOutOfRangeException(); + } + + return 0; + } + private async Task HandleWizards() + { + if (!ManifestPathOption?.Exists ?? true) + { + Console.WriteLine("Manifest does not exists"); + return 1; + } + + var t = documentLogic.ExtractWizardDocumentation(ManifestPathOption, new PluginInfo(RootPathOption, + AssemblyPathOption, ConfigurationOption, + FrameworkOption)); + + return 0; + } + + private async Task HandlePlugins() + { var plugins = documentLogic - .ExtractPluginDocumentation(new PluginInfo(RootPathOption, AssemblyPathOption, ConfigurationOption, FrameworkOption)) + .ExtractPluginDocumentation(new PluginInfo(RootPathOption, AssemblyPathOption, ConfigurationOption, + FrameworkOption)) .ToArray(); var jsonString = JsonSerializer.Serialize(plugins, new JsonSerializerOptions @@ -72,7 +121,7 @@ private async Task Run(ParseResult parseResult, IConsole console) WriteIndented = true }); await File.WriteAllTextAsync("docs.json", jsonString); - + var groups = plugins.GroupBy(x => x.Entity!.Name); Console.WriteLine("# Plugins "); @@ -85,7 +134,6 @@ private async Task Run(ParseResult parseResult, IConsole console) } } - return 0; } diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj index bf75144..d66cc9e 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj @@ -20,8 +20,8 @@ - + diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json index 7c30d12..0ba4c51 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json @@ -3,7 +3,8 @@ "EAVFW.Extensions.Manifest.ManifestEnricherTool": { "commandName": "Project", "workingDirectory": "/Users/thyge/dev/playground", - "commandLineArgs": "docs -c Release -f net6.0 -a \"/Users/thyge/dev/hafnia/Letter of Indemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/Letter of Indemnity\"" + "commandLineArgs": "docs -c Debug -t wizards -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Debug/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\" -m \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/manifest.loi.json\"" +// "commandLineArgs": "docs -c Debug -t plugins -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Debug/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\"" // "commandLineArgs": "binary --unzip 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" // "commandLineArgs": "binary --unzip 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" // "commandLineArgs": "binary --unzip --pretty-print 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" diff --git a/tests/EAVFW.Extensions.Manifest.Tests/EAVFW.Extensions.Manifest.Tests.csproj b/tests/EAVFW.Extensions.Manifest.Tests/EAVFW.Extensions.Manifest.Tests.csproj index 0fae815..dbad66c 100644 --- a/tests/EAVFW.Extensions.Manifest.Tests/EAVFW.Extensions.Manifest.Tests.csproj +++ b/tests/EAVFW.Extensions.Manifest.Tests/EAVFW.Extensions.Manifest.Tests.csproj @@ -10,6 +10,7 @@ + From 186dee657568fe9140ca1de662f7b4ce2c20e1d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thyge=20Sk=C3=B8dt=20Steffensen?= <31892312+thygesteffensen@users.noreply.github.com> Date: Thu, 9 Nov 2023 15:24:45 +0100 Subject: [PATCH 03/10] feat: Add plugin formatter --- ...tensions.Manifest.ManifestEnricherTool.sln | 7 ++ .../DocumentLogic.cs | 6 +- ...tensions.Docs.Extracter.csproj.DotSettings | 6 ++ .../PluginRegistrationAttributeConverter.cs | 34 +++++++ .../JsonConverters/TabConverter.cs | 30 +++++++ .../JsonConverters/TypeConverter.cs | 20 +++++ .../Plugin/PluginDocumentation.cs | 20 +---- .../ServiceCollectionExtension.cs | 14 +++ .../Wizard/Wizards.cs | 24 +---- .../EAVFW.Extensions.Docs.Generator.csproj | 12 +++ .../PluginDocumentationToReadMe.cs | 89 +++++++++++++++++++ .../Commands/DocumentCommand.cs | 24 ++--- ...sions.Manifest.ManifestEnricherTool.csproj | 1 + .../Program.cs | 2 +- .../Properties/launchSettings.json | 4 +- 15 files changed, 229 insertions(+), 64 deletions(-) create mode 100644 src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj.DotSettings create mode 100644 src/EAVFW.Extensions.Docs.Extracter/JsonConverters/PluginRegistrationAttributeConverter.cs create mode 100644 src/EAVFW.Extensions.Docs.Extracter/JsonConverters/TabConverter.cs create mode 100644 src/EAVFW.Extensions.Docs.Extracter/JsonConverters/TypeConverter.cs create mode 100644 src/EAVFW.Extensions.Docs.Extracter/ServiceCollectionExtension.cs create mode 100644 src/EAVFW.Extensions.Docs.Generator/EAVFW.Extensions.Docs.Generator.csproj create mode 100644 src/EAVFW.Extensions.Docs.Generator/PluginDocumentationToReadMe.cs diff --git a/EAVFW.Extensions.Manifest.ManifestEnricherTool.sln b/EAVFW.Extensions.Manifest.ManifestEnricherTool.sln index 283985b..1cb1253 100644 --- a/EAVFW.Extensions.Manifest.ManifestEnricherTool.sln +++ b/EAVFW.Extensions.Manifest.ManifestEnricherTool.sln @@ -46,6 +46,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EAVFW.Extensions.Manifest.S EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EAVFW.Extensions.Docs.Extracter", "src\EAVFW.Extensions.Docs.Extracter\EAVFW.Extensions.Docs.Extracter.csproj", "{432042AB-6A78-4ED7-B8AC-73B047F6630F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EAVFW.Extensions.Docs.Generator", "src\EAVFW.Extensions.Docs.Generator\EAVFW.Extensions.Docs.Generator.csproj", "{71FCB365-F4AE-4578-BF86-B4A3C278B6B1}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -70,6 +72,10 @@ Global {432042AB-6A78-4ED7-B8AC-73B047F6630F}.Debug|Any CPU.Build.0 = Debug|Any CPU {432042AB-6A78-4ED7-B8AC-73B047F6630F}.Release|Any CPU.ActiveCfg = Release|Any CPU {432042AB-6A78-4ED7-B8AC-73B047F6630F}.Release|Any CPU.Build.0 = Release|Any CPU + {71FCB365-F4AE-4578-BF86-B4A3C278B6B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {71FCB365-F4AE-4578-BF86-B4A3C278B6B1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {71FCB365-F4AE-4578-BF86-B4A3C278B6B1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {71FCB365-F4AE-4578-BF86-B4A3C278B6B1}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -82,6 +88,7 @@ Global {2F30C24A-421A-4309-9F07-99668EA70C25} = {CAE8FBC9-BDC3-4F45-81E1-57506D609011} {3BEF0769-ABD1-4D34-8004-C98DE9FB0339} = {CAE8FBC9-BDC3-4F45-81E1-57506D609011} {432042AB-6A78-4ED7-B8AC-73B047F6630F} = {0D61C87C-0809-4CD7-9200-D78AD11A1E22} + {71FCB365-F4AE-4578-BF86-B4A3C278B6B1} = {0D61C87C-0809-4CD7-9200-D78AD11A1E22} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {036D5D82-DDA4-4600-B190-739D512F1062} diff --git a/src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs b/src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs index ebefaec..0351759 100644 --- a/src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs +++ b/src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs @@ -145,11 +145,7 @@ private void ExtractEntitiesWithWizards(JsonElement element, IDictionary>(property.Value.GetRawText(), - new JsonSerializerOptions - { - Converters = { new TabConverter() } - }); + JsonSerializer.Deserialize>(property.Value.GetRawText()); if (localEntities == null) return; diff --git a/src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj.DotSettings b/src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj.DotSettings new file mode 100644 index 0000000..6ed5a98 --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj.DotSettings @@ -0,0 +1,6 @@ + + True diff --git a/src/EAVFW.Extensions.Docs.Extracter/JsonConverters/PluginRegistrationAttributeConverter.cs b/src/EAVFW.Extensions.Docs.Extracter/JsonConverters/PluginRegistrationAttributeConverter.cs new file mode 100644 index 0000000..bc70d3c --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Extracter/JsonConverters/PluginRegistrationAttributeConverter.cs @@ -0,0 +1,34 @@ +using System; +using System.Text.Json; +using System.Text.Json.Nodes; +using System.Text.Json.Serialization; +using EAVFramework.Plugins; + +namespace EAVFW.Extensions.Docs.Extracter +{ + public class PluginRegistrationAttributeConverter : JsonConverter + { + public override PluginRegistrationAttribute? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + + public override void Write( + Utf8JsonWriter writer, + PluginRegistrationAttribute value, + JsonSerializerOptions options) + { + var _object = new JsonObject + { + { nameof(value.Order), value.Order }, + { nameof(value.Operation), value.Operation.ToString() }, + { nameof(value.Execution), value.Execution.ToString() }, + { nameof(value.Mode), value.Mode.ToString() } + }; + _object.WriteTo(writer); + } + } +} diff --git a/src/EAVFW.Extensions.Docs.Extracter/JsonConverters/TabConverter.cs b/src/EAVFW.Extensions.Docs.Extracter/JsonConverters/TabConverter.cs new file mode 100644 index 0000000..b548a25 --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Extracter/JsonConverters/TabConverter.cs @@ -0,0 +1,30 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace EAVFW.Extensions.Docs.Extracter +{ + public class TabConverter : JsonConverter + { + public override StringOrBoolean Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options) + { + return reader.TokenType switch + { + JsonTokenType.String => new StringOrBoolean(reader.GetString() ?? ""), + JsonTokenType.False => new StringOrBoolean(false), + JsonTokenType.True => new StringOrBoolean(true), + _ => new StringOrBoolean() + }; + } + + public override void Write(Utf8JsonWriter writer, StringOrBoolean value, JsonSerializerOptions options) + { + if (value.IsBool) + writer.WriteBooleanValue(value.BooleanValue); + writer.WriteStringValue(value.StringValue); + } + } +} diff --git a/src/EAVFW.Extensions.Docs.Extracter/JsonConverters/TypeConverter.cs b/src/EAVFW.Extensions.Docs.Extracter/JsonConverters/TypeConverter.cs new file mode 100644 index 0000000..2f40207 --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Extracter/JsonConverters/TypeConverter.cs @@ -0,0 +1,20 @@ +using System; +using System.Text.Json; +using System.Text.Json.Nodes; +using System.Text.Json.Serialization; + +namespace EAVFW.Extensions.Docs.Extracter +{ + public class TypeConverter : JsonConverter + { + public override Type? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + + public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options) + { + JsonValue.Create(value.Name)?.WriteTo(writer, options); + } + } +} diff --git a/src/EAVFW.Extensions.Docs.Extracter/Plugin/PluginDocumentation.cs b/src/EAVFW.Extensions.Docs.Extracter/Plugin/PluginDocumentation.cs index b1830f2..e6ae712 100644 --- a/src/EAVFW.Extensions.Docs.Extracter/Plugin/PluginDocumentation.cs +++ b/src/EAVFW.Extensions.Docs.Extracter/Plugin/PluginDocumentation.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text.Json.Serialization; using EAVFramework.Plugins; @@ -8,27 +7,14 @@ namespace EAVFW.Extensions.Docs.Extracter { public class PluginDocumentation { - [JsonIgnore] public IEnumerable PluginRegistrations { get; set; } = Array.Empty(); public string? Name { get; set; } - - [JsonIgnore] - public Type? Context { get; set; } - [JsonIgnore] - public Type? Entity { get; set; } - public string Summary { get; set; } = ""; + [JsonConverter(typeof(TypeConverter))] public Type? Context { get; set; } - public override string ToString() - { - var summary = Summary?.Split("\n").Select(x => x.Trim()).ToArray() ?? Array.Empty(); - return $"Plugin: {Name} on {Entity.Name}\n* " - + string.Join("\n* ", PluginRegistrations.Select(x => $"{x.Operation} on {x.Execution} as {x.Order}")) - + '\n' - + string.Join('\n', summary) - + "\n\n"; - } + [JsonConverter(typeof(TypeConverter))] public Type? Entity { get; set; } + public string Summary { get; set; } = ""; } } diff --git a/src/EAVFW.Extensions.Docs.Extracter/ServiceCollectionExtension.cs b/src/EAVFW.Extensions.Docs.Extracter/ServiceCollectionExtension.cs new file mode 100644 index 0000000..9701d2c --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Extracter/ServiceCollectionExtension.cs @@ -0,0 +1,14 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace EAVFW.Extensions.Docs.Extracter +{ + public static class ServiceCollectionExtension + { + public static IServiceCollection AddDocument(this IServiceCollection serviceCollection) + { + serviceCollection.AddSingleton(); + + return serviceCollection; + } + } +} diff --git a/src/EAVFW.Extensions.Docs.Extracter/Wizard/Wizards.cs b/src/EAVFW.Extensions.Docs.Extracter/Wizard/Wizards.cs index 4204c2a..870b21d 100644 --- a/src/EAVFW.Extensions.Docs.Extracter/Wizard/Wizards.cs +++ b/src/EAVFW.Extensions.Docs.Extracter/Wizard/Wizards.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Text.Json; using System.Text.Json.Serialization; @@ -26,6 +25,7 @@ public struct Trigger [JsonPropertyName("ribbon")] public string Ribbon { get; set; } } + [JsonConverter(typeof(TabConverter))] public class Tab { [JsonPropertyName("columns")] public JsonElement Columns { get; set; } @@ -63,28 +63,6 @@ public StringOrBoolean(bool booleanValue) } - public class TabConverter : JsonConverter - { - public override StringOrBoolean Read(ref Utf8JsonReader reader, Type typeToConvert, - JsonSerializerOptions options) - { - return reader.TokenType switch - { - JsonTokenType.String => new StringOrBoolean(reader.GetString() ?? ""), - JsonTokenType.False => new StringOrBoolean(false), - JsonTokenType.True => new StringOrBoolean(true), - _ => new StringOrBoolean() - }; - } - - public override void Write(Utf8JsonWriter writer, StringOrBoolean value, JsonSerializerOptions options) - { - if (value.IsBool) - writer.WriteBooleanValue(value.BooleanValue); - writer.WriteStringValue(value.StringValue); - } - } - public class Transition { [JsonPropertyName("workflow")] public string? Workflow { get; set; } diff --git a/src/EAVFW.Extensions.Docs.Generator/EAVFW.Extensions.Docs.Generator.csproj b/src/EAVFW.Extensions.Docs.Generator/EAVFW.Extensions.Docs.Generator.csproj new file mode 100644 index 0000000..69e771f --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Generator/EAVFW.Extensions.Docs.Generator.csproj @@ -0,0 +1,12 @@ + + + + net6.0 + enable + + + + + + + diff --git a/src/EAVFW.Extensions.Docs.Generator/PluginDocumentationToReadMe.cs b/src/EAVFW.Extensions.Docs.Generator/PluginDocumentationToReadMe.cs new file mode 100644 index 0000000..2f79707 --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Generator/PluginDocumentationToReadMe.cs @@ -0,0 +1,89 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using EAVFW.Extensions.Docs.Extracter; +using Microsoft.AspNetCore.DataProtection; +using Sprache; + +namespace EAVFW.Extensions.Docs.Generator +{ + public class PluginDocumentationToReadMe + { + public async Task WriteReadMe(IEnumerable pluginDocumentations) + { + await using var writer = new StreamWriter("documentation.md"); + + var groups = pluginDocumentations.GroupBy(x => x.Entity!.Name); + await writer.WriteLineAsync("# Plugins "); + foreach (var group in groups) + { + await writer.WriteLineAsync($"## {group.FirstOrDefault()?.Entity?.Name}"); + foreach (var pluginDocumentation in group) + { + await writer.WriteLineAsync($"### {pluginDocumentation.Name}"); + await writer.WriteLineAsync( + $"Entity:\t[{pluginDocumentation.Entity?.Name}](#{pluginDocumentation.Entity?.Name})"); + await writer.WriteLineAsync( + $"Context:\t[{pluginDocumentation.Entity?.Name}](#{pluginDocumentation.Entity?.Name})"); + await writer.WriteLineAsync("Triggers:"); + await writer.WriteLineAsync("| Operation | Execution | Mode | Order |"); + await writer.WriteLineAsync("|---|---|---|:-:|"); + foreach (var reg in pluginDocumentation.PluginRegistrations.OrderBy(x => x.Order)) + { + await writer.WriteLineAsync($"|{reg.Operation}|{reg.Execution}|{reg.Mode}|{reg.Order}|"); + } + + await writer.WriteLineAsync("\n**Summary:**"); + + await writer.WriteLineAsync(SanitizeSummary(pluginDocumentation.Summary)); + + await writer.WriteLineAsync(); + } + } + } + + private static string SanitizeSummary(string summary) + { + if (string.IsNullOrWhiteSpace(summary)) return summary; + + var lines = summary.Split("\n").Select(x => x); + + lines = lines.Where(x => !string.IsNullOrWhiteSpace(x)); + lines = lines.Select(x => x.Trim()); + lines = lines.Select(x => ToMarkDownLink.Parse(x)); + + + return string.Join("", lines); + } + + private static readonly Parser Text = Parse.CharExcept('<').Many().Text(); + + private static readonly Parser Value = + Parse.AnyChar.Except(Parse.Char('\"')).Many().Text(); + + private static readonly Parser> Property = + from key in Parse.LetterOrDigit.Or(Parse.Char('-')).Many().Text() + from eq in Parse.Char('=') + from value in Parse.AnyChar.Except(Parse.Char('\"')).Many().Contained(Parse.Char('\"'), Parse.Char('\"')).Text() + select new KeyValuePair(key, value); + + private static readonly Parser> Properties = + from properties in Property.DelimitedBy(Parse.Char(' ')) + select properties.ToDictionary(x => x.Key, x => x.Value); + + private static readonly Parser LinkReplace = + from s in Parse.String("") + select $"[{props["cref"]}](#{props["cref"]})"; + + private static readonly Parser ToMarkDownLink = + from s in Text.Or(LinkReplace).Many() + select string.Join("", s); + + + } +} diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs index 1384c3a..0277055 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs @@ -8,6 +8,7 @@ using System.Text.Json; using System.Threading.Tasks; using EAVFW.Extensions.Docs.Extracter; +using EAVFW.Extensions.Docs.Generator; namespace EAVFW.Extensions.Manifest.ManifestEnricherTool.Commands { @@ -20,7 +21,7 @@ public class DocumentCommand : Command [Alias("--assembly")] [Description("Path for the assembly")] public FileInfo AssemblyPathOption { get; set; } - + [Alias("-m")] [Alias("--manifest")] [Description("Path for the manifest")] @@ -40,8 +41,7 @@ public class DocumentCommand : Command [Alias("--framework")] [Description("Framework confugraiton for the built assembly")] public string FrameworkOption { get; set; } - - + [Alias("-t")] [Alias("--target")] @@ -80,7 +80,7 @@ private async Task Run(ParseResult parseResult, IConsole console) Console.WriteLine("Assembly does not exists"); return 1; } - + switch (Target) { case Targets.Plugins: @@ -90,7 +90,7 @@ private async Task Run(ParseResult parseResult, IConsole console) default: throw new ArgumentOutOfRangeException(); } - + return 0; } @@ -118,21 +118,13 @@ private async Task HandlePlugins() var jsonString = JsonSerializer.Serialize(plugins, new JsonSerializerOptions { + Converters = { new PluginRegistrationAttributeConverter() }, WriteIndented = true }); await File.WriteAllTextAsync("docs.json", jsonString); - var groups = plugins.GroupBy(x => x.Entity!.Name); - - Console.WriteLine("# Plugins "); - foreach (var group in groups) - { - Console.WriteLine($"## {group.FirstOrDefault()?.Entity?.Name}"); - foreach (var pluginDocumentation in group) - { - Console.WriteLine(pluginDocumentation.ToString()); - } - } + var writer = new PluginDocumentationToReadMe(); + await writer.WriteReadMe(plugins); return 0; } diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj index d66cc9e..999995a 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj @@ -50,5 +50,6 @@ + diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Program.cs b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Program.cs index 81bfd86..f4e1b86 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Program.cs +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Program.cs @@ -29,7 +29,7 @@ static IServiceCollection ConfigureServices(IServiceCollection serviceCollection .AddManifestSDK() .AddSingleton(); - serviceCollection.AddSingleton(); + serviceCollection.AddDocument(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json index 0ba4c51..108f59a 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json @@ -3,8 +3,8 @@ "EAVFW.Extensions.Manifest.ManifestEnricherTool": { "commandName": "Project", "workingDirectory": "/Users/thyge/dev/playground", - "commandLineArgs": "docs -c Debug -t wizards -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Debug/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\" -m \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/manifest.loi.json\"" -// "commandLineArgs": "docs -c Debug -t plugins -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Debug/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\"" +// "commandLineArgs": "docs -c Release -t wizards -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\" -m \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/manifest.loi.json\"" + "commandLineArgs": "docs -c Release -t plugins -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\"" // "commandLineArgs": "binary --unzip 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" // "commandLineArgs": "binary --unzip 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" // "commandLineArgs": "binary --unzip --pretty-print 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" From 275249cea66d79cb4c3d32a862dbb1095a79bd43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thyge=20Sk=C3=B8dt=20Steffensen?= <31892312+thygesteffensen@users.noreply.github.com> Date: Fri, 10 Nov 2023 15:23:25 +0100 Subject: [PATCH 04/10] Working version with generator --- global.json | 4 +- .../DocumentLogic.cs | 7 +- .../EAVFW.Extensions.Docs.Extracter.csproj | 2 +- .../JsonConverters/TabConverter.cs | 30 ---- .../Wizard/Wizards.cs | 79 ----------- .../EAVFW.Extensions.Docs.Generator.csproj | 2 +- .../PluginDocumentationToReadMe.cs | 129 +++++++++++------- .../TransformXmlTag.cs | 58 ++++++++ .../Commands/DocumentCommand.cs | 5 +- .../Commands/SQLCommand.cs | 7 - ...sions.Manifest.ManifestEnricherTool.csproj | 7 +- .../Properties/launchSettings.json | 2 +- .../EAVFW.Extensions.Manifest.Tests.csproj | 4 +- 13 files changed, 159 insertions(+), 177 deletions(-) delete mode 100644 src/EAVFW.Extensions.Docs.Extracter/JsonConverters/TabConverter.cs delete mode 100644 src/EAVFW.Extensions.Docs.Extracter/Wizard/Wizards.cs create mode 100644 src/EAVFW.Extensions.Docs.Generator/TransformXmlTag.cs diff --git a/global.json b/global.json index f9550e8..3ecc5db 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "6.0.414" + "version": "8.0.100-rc.2.23502.2" } -} \ No newline at end of file +} diff --git a/src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs b/src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs index 0351759..2b949e0 100644 --- a/src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs +++ b/src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs @@ -7,6 +7,7 @@ using System.Text.Json; using System.Text.Json.Serialization; using EAVFramework.Plugins; +using EAVFW.Extensions.Manifest.SDK; namespace EAVFW.Extensions.Docs.Extracter { @@ -96,7 +97,7 @@ from type in assembly.GetTypes() var jsonManifest = JsonDocument.ParseAsync(openStream).Result; // Find Wizards - var simpleManifest = new Dictionary(); + var simpleManifest = new Dictionary(); ExtractEntitiesWithWizards(jsonManifest.RootElement, simpleManifest); @@ -136,7 +137,7 @@ from tabs in wizard.Value.Tabs return new List(); } - private void ExtractEntitiesWithWizards(JsonElement element, IDictionary entities) + private void ExtractEntitiesWithWizards(JsonElement element, IDictionary entities) { if (element.ValueKind != JsonValueKind.Object) return; @@ -145,7 +146,7 @@ private void ExtractEntitiesWithWizards(JsonElement element, IDictionary>(property.Value.GetRawText()); + JsonSerializer.Deserialize>(property.Value.GetRawText()); if (localEntities == null) return; diff --git a/src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj b/src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj index f7d8b2d..a3549d6 100644 --- a/src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj +++ b/src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj @@ -2,7 +2,7 @@ 9.0 - net6.0 + net8.0 enable diff --git a/src/EAVFW.Extensions.Docs.Extracter/JsonConverters/TabConverter.cs b/src/EAVFW.Extensions.Docs.Extracter/JsonConverters/TabConverter.cs deleted file mode 100644 index b548a25..0000000 --- a/src/EAVFW.Extensions.Docs.Extracter/JsonConverters/TabConverter.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace EAVFW.Extensions.Docs.Extracter -{ - public class TabConverter : JsonConverter - { - public override StringOrBoolean Read( - ref Utf8JsonReader reader, - Type typeToConvert, - JsonSerializerOptions options) - { - return reader.TokenType switch - { - JsonTokenType.String => new StringOrBoolean(reader.GetString() ?? ""), - JsonTokenType.False => new StringOrBoolean(false), - JsonTokenType.True => new StringOrBoolean(true), - _ => new StringOrBoolean() - }; - } - - public override void Write(Utf8JsonWriter writer, StringOrBoolean value, JsonSerializerOptions options) - { - if (value.IsBool) - writer.WriteBooleanValue(value.BooleanValue); - writer.WriteStringValue(value.StringValue); - } - } -} diff --git a/src/EAVFW.Extensions.Docs.Extracter/Wizard/Wizards.cs b/src/EAVFW.Extensions.Docs.Extracter/Wizard/Wizards.cs deleted file mode 100644 index 870b21d..0000000 --- a/src/EAVFW.Extensions.Docs.Extracter/Wizard/Wizards.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System.Collections.Generic; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace EAVFW.Extensions.Docs.Extracter -{ - public class Entity - { - [JsonPropertyName("wizards")] public Dictionary Wizards { get; set; } - } - - public class Wizard - { - [JsonPropertyName("title")] public string Title { get; set; } - - [JsonPropertyName("triggers")] public JsonElement Triggers { get; set; } - - [JsonPropertyName("tabs")] public Dictionary Tabs { get; set; } - } - - public struct Trigger - { - [JsonPropertyName("form")] public string Form { get; set; } - - [JsonPropertyName("ribbon")] public string Ribbon { get; set; } - } - - [JsonConverter(typeof(TabConverter))] - public class Tab - { - [JsonPropertyName("columns")] public JsonElement Columns { get; set; } - - [JsonPropertyName("visible")] public StringOrBoolean StringOrBoolean { get; set; } - - [JsonPropertyName("onTransitionOut")] public Transition? OnTransitionOut { get; set; } - - [JsonPropertyName("onTransitionIn")] public Transition? OnTransitionIn { get; set; } - - [JsonPropertyName("actions")] public JsonElement? Actions { get; set; } // TODO: This also needs to be enriched - } - - public struct StringOrBoolean - { - public StringOrBoolean(string stringValue) - { - StringValue = stringValue; - IsBool = false; - BooleanValue = default; - } - - public StringOrBoolean(bool booleanValue) - { - StringValue = default; - IsBool = false; - BooleanValue = booleanValue; - } - - public string? StringValue { get; } - - public bool BooleanValue { get; } - - public bool IsBool { get; } - } - - - public class Transition - { - [JsonPropertyName("workflow")] public string? Workflow { get; set; } - - [JsonPropertyName("workflowSummary")] public string? WorkflowSummary { get; set; } - - [JsonPropertyName("message")] public Message? Message { get; set; } - } - - public class Message - { - [JsonPropertyName("title")] public string? Title { get; set; } - } -} diff --git a/src/EAVFW.Extensions.Docs.Generator/EAVFW.Extensions.Docs.Generator.csproj b/src/EAVFW.Extensions.Docs.Generator/EAVFW.Extensions.Docs.Generator.csproj index 69e771f..ae618e2 100644 --- a/src/EAVFW.Extensions.Docs.Generator/EAVFW.Extensions.Docs.Generator.csproj +++ b/src/EAVFW.Extensions.Docs.Generator/EAVFW.Extensions.Docs.Generator.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0 enable diff --git a/src/EAVFW.Extensions.Docs.Generator/PluginDocumentationToReadMe.cs b/src/EAVFW.Extensions.Docs.Generator/PluginDocumentationToReadMe.cs index 2f79707..8ff1ba4 100644 --- a/src/EAVFW.Extensions.Docs.Generator/PluginDocumentationToReadMe.cs +++ b/src/EAVFW.Extensions.Docs.Generator/PluginDocumentationToReadMe.cs @@ -1,49 +1,84 @@ +using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Threading.Tasks; using EAVFW.Extensions.Docs.Extracter; -using Microsoft.AspNetCore.DataProtection; -using Sprache; +using EAVFW.Extensions.Manifest.SDK; +using JsonSerializer = System.Text.Json.JsonSerializer; namespace EAVFW.Extensions.Docs.Generator { - public class PluginDocumentationToReadMe + public class PluginDocumentationToReadMe : IDisposable { - public async Task WriteReadMe(IEnumerable pluginDocumentations) + private readonly StreamWriter _writer; + private readonly Dictionary _logicalNameLookup = new(); + private readonly TransformXmlTag _transformXmlTag; + + public PluginDocumentationToReadMe( + string path = "/Users/thyge/Documents/Obsidian Vault/Delegate Lava-Stone/Delegate/documentation.md") + { + _transformXmlTag = new TransformXmlTag(); + _writer = new StreamWriter(path); + } + + public async Task WriteTables(FileInfo manifest) { - await using var writer = new StreamWriter("documentation.md"); + var manifestObject = await JsonSerializer.DeserializeAsync(manifest.OpenRead()); + + await _writer.WriteLineAsync("## Tables:\n"); + + var t = new DefaultSchemaNameManager(); + + Debug.Assert(manifestObject != null, nameof(manifestObject) + " != null"); + foreach (var (key, value) in manifestObject.Entities) + { + _logicalNameLookup[t.ToSchemaName(key)] = key; + + await _writer.WriteLineAsync($"### {key}"); + await _writer.WriteLineAsync($"Logical name: `{t.ToSchemaName(key)}`"); + await _writer.WriteLineAsync($"Plural name: {value.PluralName}"); + await _writer.WriteLineAsync($"Description: {value.Description}"); + await _writer.WriteLineAsync("Attributes:"); + } + } + public async Task WritePlugins(IEnumerable pluginDocumentations) + { var groups = pluginDocumentations.GroupBy(x => x.Entity!.Name); - await writer.WriteLineAsync("# Plugins "); + await _writer.WriteLineAsync("## Plugins "); foreach (var group in groups) { - await writer.WriteLineAsync($"## {group.FirstOrDefault()?.Entity?.Name}"); + await _writer.WriteLineAsync($"### {group.FirstOrDefault()?.Entity?.Name}"); foreach (var pluginDocumentation in group) { - await writer.WriteLineAsync($"### {pluginDocumentation.Name}"); - await writer.WriteLineAsync( + await _writer.WriteLineAsync($"#### {pluginDocumentation.Name}"); + await _writer.WriteLineAsync( $"Entity:\t[{pluginDocumentation.Entity?.Name}](#{pluginDocumentation.Entity?.Name})"); - await writer.WriteLineAsync( + await _writer.WriteLineAsync( $"Context:\t[{pluginDocumentation.Entity?.Name}](#{pluginDocumentation.Entity?.Name})"); - await writer.WriteLineAsync("Triggers:"); - await writer.WriteLineAsync("| Operation | Execution | Mode | Order |"); - await writer.WriteLineAsync("|---|---|---|:-:|"); + await _writer.WriteLineAsync("Triggers:\n"); + await _writer.WriteLineAsync("| Operation | Execution | Mode | Order |"); + await _writer.WriteLineAsync("|---|---|---|:-:|"); foreach (var reg in pluginDocumentation.PluginRegistrations.OrderBy(x => x.Order)) { - await writer.WriteLineAsync($"|{reg.Operation}|{reg.Execution}|{reg.Mode}|{reg.Order}|"); + await _writer.WriteLineAsync($"|{reg.Operation}|{reg.Execution}|{reg.Mode}|{reg.Order}|"); } - await writer.WriteLineAsync("\n**Summary:**"); + await _writer.WriteLineAsync("\n**Summary:**"); - await writer.WriteLineAsync(SanitizeSummary(pluginDocumentation.Summary)); + await _writer.WriteLineAsync(SanitizeSummary(pluginDocumentation.Summary)); - await writer.WriteLineAsync(); + await _writer.WriteLineAsync(); } } } + + // public async Task WriteWizards() + - private static string SanitizeSummary(string summary) + private string SanitizeSummary(string summary) { if (string.IsNullOrWhiteSpace(summary)) return summary; @@ -51,39 +86,37 @@ private static string SanitizeSummary(string summary) lines = lines.Where(x => !string.IsNullOrWhiteSpace(x)); lines = lines.Select(x => x.Trim()); - lines = lines.Select(x => ToMarkDownLink.Parse(x)); - + lines = lines.Select(x => _transformXmlTag.TransformString(x, TransformTag)); - return string.Join("", lines); + return string.Join(" ", lines); } - private static readonly Parser Text = Parse.CharExcept('<').Many().Text(); + /// + /// Function i expression motoren + /// + /// + /// + /// + private string TransformTag(string tag, Dictionary properties) + { + if (tag != "see") + return tag; - private static readonly Parser Value = - Parse.AnyChar.Except(Parse.Char('\"')).Many().Text(); - - private static readonly Parser> Property = - from key in Parse.LetterOrDigit.Or(Parse.Char('-')).Many().Text() - from eq in Parse.Char('=') - from value in Parse.AnyChar.Except(Parse.Char('\"')).Many().Contained(Parse.Char('\"'), Parse.Char('\"')).Text() - select new KeyValuePair(key, value); - - private static readonly Parser> Properties = - from properties in Property.DelimitedBy(Parse.Char(' ')) - select properties.ToDictionary(x => x.Key, x => x.Value); - - private static readonly Parser LinkReplace = - from s in Parse.String("") - select $"[{props["cref"]}](#{props["cref"]})"; - - private static readonly Parser ToMarkDownLink = - from s in Text.Or(LinkReplace).Many() - select string.Join("", s); - - + var target = properties["cref"]; + + var key = target.Split(':').Last().Split('.').Last(); + + _logicalNameLookup.TryGetValue(key, out var value); + + return $"[{value ?? key}](#{key})"; + } + + + public async void Dispose() + { + await _writer.FlushAsync(); + await _writer.DisposeAsync(); + GC.SuppressFinalize(this); + } } } diff --git a/src/EAVFW.Extensions.Docs.Generator/TransformXmlTag.cs b/src/EAVFW.Extensions.Docs.Generator/TransformXmlTag.cs new file mode 100644 index 0000000..24218c8 --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Generator/TransformXmlTag.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Sprache; + +namespace EAVFW.Extensions.Docs.Generator +{ + public class TransformXmlTag + { + private Parser? _linkReplace; + + private readonly Parser? _toMarkDownLink; + + private readonly Parser>? _properties; + + public TransformXmlTag() + { + var text = + Parse.CharExcept('<').Many().Text(); + + var property = + from key in Parse.LetterOrDigit.Or(Parse.Char('-')).Many().Text() + from eq in Parse.Char('=') + from value in Parse.AnyChar.Except(Parse.Char('\"')).Many() + .Contained(Parse.Char('\"'), Parse.Char('\"')) + .Text() + select new KeyValuePair(key, value); + + _properties = + from properties in property.DelimitedBy(Parse.Char(' ')) + select properties.ToDictionary(x => x.Key, x => x.Value); + + _toMarkDownLink = + from s in text.Or(Parse.Ref(() => _linkReplace)).Many() + select string.Join("", s); + } + + /// + /// Transform a string with Xml tags using the tag string to locate the + /// + /// Input to transform + /// Transform function with access to the properties + /// + public string TransformString(string input, Func, string> transform) + { + _linkReplace = + from s in Parse.String("<") + from tag in Parse.LetterOrDigit.Many().Text() + from _ in Parse.WhiteSpace.Many() + from props in _properties + from __ in Parse.WhiteSpace.Many() + from e in Parse.String("/>") + select transform(tag, props); + + return _toMarkDownLink.Parse(input); + } + } +} diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs index 0277055..cc0154b 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs @@ -123,8 +123,9 @@ private async Task HandlePlugins() }); await File.WriteAllTextAsync("docs.json", jsonString); - var writer = new PluginDocumentationToReadMe(); - await writer.WriteReadMe(plugins); + using var writer = new PluginDocumentationToReadMe(); + await writer.WriteTables(ManifestPathOption); + await writer.WritePlugins(plugins); return 0; } diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/SQLCommand.cs b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/SQLCommand.cs index 68d3720..5ad962c 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/SQLCommand.cs +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/SQLCommand.cs @@ -1,25 +1,18 @@ using EAVFramework; using EAVFW.Extensions.Manifest.SDK; -using Microsoft.Azure.Documents.Spatial; -using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging.Abstractions; -using NetTopologySuite.Geometries; using Newtonsoft.Json.Linq; using System; -using System.Collections.Generic; using System.CommandLine; using System.CommandLine.NamingConventionBinder; using System.CommandLine.Parsing; using System.IO; using System.Linq; -using System.Text; using System.Threading.Tasks; -using System.Xml.Linq; -using Point = NetTopologySuite.Geometries.Point; namespace EAVFW.Extensions.Manifest.ManifestEnricherTool.Commands { diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj index 999995a..89494e0 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj @@ -1,7 +1,7 @@  Exe - net6.0 + net8.0 true eavfw-manifest ./../../artifacts @@ -37,6 +37,11 @@ 6.0.11 + + + 7.0.13 + + diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json index 108f59a..7ec3e90 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json @@ -4,7 +4,7 @@ "commandName": "Project", "workingDirectory": "/Users/thyge/dev/playground", // "commandLineArgs": "docs -c Release -t wizards -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\" -m \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/manifest.loi.json\"" - "commandLineArgs": "docs -c Release -t plugins -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\"" + "commandLineArgs": "docs -c Release -t plugins -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\" -m \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/manifest.loi.json\"" // "commandLineArgs": "binary --unzip 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" // "commandLineArgs": "binary --unzip 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" // "commandLineArgs": "binary --unzip --pretty-print 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" diff --git a/tests/EAVFW.Extensions.Manifest.Tests/EAVFW.Extensions.Manifest.Tests.csproj b/tests/EAVFW.Extensions.Manifest.Tests/EAVFW.Extensions.Manifest.Tests.csproj index dbad66c..aee4d5c 100644 --- a/tests/EAVFW.Extensions.Manifest.Tests/EAVFW.Extensions.Manifest.Tests.csproj +++ b/tests/EAVFW.Extensions.Manifest.Tests/EAVFW.Extensions.Manifest.Tests.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 disable disable @@ -9,7 +9,7 @@ - + From 06c1b72dc272b0e8240a40ed36d4d0bef840005c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thyge=20Sk=C3=B8dt=20Steffensen?= <31892312+thygesteffensen@users.noreply.github.com> Date: Fri, 17 Nov 2023 07:19:09 +0100 Subject: [PATCH 05/10] wip: Add functionality to extract documentation --- Directory.Build.props | 4 +- external/EAVFW.Extensions.CommandLine | 2 +- .../DocumentLogic.cs | 68 +++++++++-------- .../EAVFW.Extensions.Docs.Extracter.csproj | 9 +++ .../IDocumentLogic.cs | 3 +- .../JsonConverters/TypeConverter.cs | 2 +- .../EAVFW.Extensions.Docs.Generator.csproj | 6 ++ .../PluginDocumentationToReadMe.cs | 11 ++- .../App.cs | 60 +++++---------- .../Commands/DocumentCommand.cs | 56 +++++++++++--- ...sions.Manifest.ManifestEnricherTool.csproj | 1 + .../IManifestMerger.cs | 15 ++++ .../IModuleMetadataEnricher.cs | 14 ++++ .../ManifestMerger.cs | 52 +++++++++++++ .../ModuleMetadataEnricher.cs | 74 +++++++++++++++++++ .../Program.cs | 3 + .../Properties/launchSettings.json | 9 ++- .../EAVFW.Extensions.Manifest.Tests.csproj | 8 +- .../Merge/AppTest.cs | 39 ++++++++++ .../Merge/expected.manifest.json | 67 +++++++++++++++++ .../Merge/manifest.component.json | 19 +++++ .../Merge/manifest.json | 33 +++++++++ .../TestLogger.cs | 31 ++++++++ 23 files changed, 487 insertions(+), 99 deletions(-) create mode 100644 src/EAVFW.Extensions.Manifest.ManifestEnricherTool/IManifestMerger.cs create mode 100644 src/EAVFW.Extensions.Manifest.ManifestEnricherTool/IModuleMetadataEnricher.cs create mode 100644 src/EAVFW.Extensions.Manifest.ManifestEnricherTool/ManifestMerger.cs create mode 100644 src/EAVFW.Extensions.Manifest.ManifestEnricherTool/ModuleMetadataEnricher.cs create mode 100644 tests/EAVFW.Extensions.Manifest.Tests/Merge/AppTest.cs create mode 100644 tests/EAVFW.Extensions.Manifest.Tests/Merge/expected.manifest.json create mode 100644 tests/EAVFW.Extensions.Manifest.Tests/Merge/manifest.component.json create mode 100644 tests/EAVFW.Extensions.Manifest.Tests/Merge/manifest.json create mode 100644 tests/EAVFW.Extensions.Manifest.Tests/TestLogger.cs diff --git a/Directory.Build.props b/Directory.Build.props index 7925b0d..bc28d4d 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,9 +2,9 @@ 9.0 4.0.2 - true + false $(MSBuildThisFileDirectory)/external/EAVFramework $(MSBuildThisFileDirectory)/external $(MSBuildThisFileDirectory) - \ No newline at end of file + diff --git a/external/EAVFW.Extensions.CommandLine b/external/EAVFW.Extensions.CommandLine index 0350081..e43af6a 160000 --- a/external/EAVFW.Extensions.CommandLine +++ b/external/EAVFW.Extensions.CommandLine @@ -1 +1 @@ -Subproject commit 03500817f0d20e753288c4937b1bc87ca1cc664a +Subproject commit e43af6ad852b921bc688208d423b2f6e243522f5 diff --git a/src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs b/src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs index 2b949e0..0da526c 100644 --- a/src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs +++ b/src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs @@ -4,10 +4,12 @@ using System.Linq; using System.Reflection; using System.Runtime.Loader; +using System.Security.Principal; using System.Text.Json; using System.Text.Json.Serialization; using EAVFramework.Plugins; using EAVFW.Extensions.Manifest.SDK; +using WorkflowEngine.Core; namespace EAVFW.Extensions.Docs.Extracter { @@ -80,19 +82,17 @@ where d.FullName.EndsWith($"bin/{pluginInfo.Configuration}/{pluginInfo.Framework } /// - public IEnumerable ExtractWizardDocumentation(FileInfo manifestFile, PluginInfo pluginInfo) + public Dictionary ExtractWizardDocumentation(FileInfo manifestFile, + PluginInfo pluginInfo) { var assembly = LoadAssembly(pluginInfo); // Preloading types to easily query for documentation - var workflows = - from type in assembly.GetTypes() - // where type.IsAbstract && typeof(Workflow).IsAssignableFrom(type) - select type; + var workflows = assembly.GetTypes() + .Where(type => !type.IsAbstract && !type.IsInterface && typeof(IWorkflow).IsAssignableFrom(type)) + .ToDictionary(x => x.Name, x => x); // Load manifest - - using var openStream = manifestFile.OpenRead(); var jsonManifest = JsonDocument.ParseAsync(openStream).Result; @@ -100,41 +100,47 @@ from type in assembly.GetTypes() var simpleManifest = new Dictionary(); ExtractEntitiesWithWizards(jsonManifest.RootElement, simpleManifest); + var tabs = + (from entity in simpleManifest + from wizard in entity.Value.Wizards + from _tabs in wizard.Value.Tabs + select _tabs).AsEnumerable(); // Glorified for loop? var tabsWithWorkflows = - from entity in simpleManifest - from wizard in entity.Value.Wizards - from tabs in wizard.Value.Tabs - where tabs.Value.OnTransitionOut?.Workflow != null && tabs.Value.OnTransitionIn?.Workflow != null - select tabs.Value; + from tab in tabs + where tab.Value.OnTransitionOut?.Workflow != null || tab.Value.OnTransitionIn?.Workflow != null + select tab; - foreach (var tabsWithWorkflow in tabsWithWorkflows) + foreach (var (key, value) in tabsWithWorkflows) { - if (!string.IsNullOrWhiteSpace(tabsWithWorkflow?.OnTransitionOut?.Workflow)) + if (!string.IsNullOrWhiteSpace(value?.OnTransitionIn?.Workflow) && + workflows.TryGetValue(value.OnTransitionIn.Workflow, out var type1)) { - var workflow = tabsWithWorkflow.OnTransitionOut.Workflow!; - // look for workflow in types? - Console.WriteLine(workflow); + value.OnTransitionIn.AdditionalData["x-workflowSummary"] = type1.GetDocumentation(); } - } - foreach (var (key, wizard) in simpleManifest) - { - var t = JsonSerializer.Serialize(wizard, new JsonSerializerOptions + if (!string.IsNullOrWhiteSpace(value?.OnTransitionOut?.Workflow) && + workflows.TryGetValue(value.OnTransitionOut.Workflow, out var type2)) { - WriteIndented = true, - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull - }); - Console.WriteLine(t); + value.OnTransitionOut.AdditionalData["x-workflowSummary"] = type2.GetDocumentation(); + } + } + + var actionsWithWorkflows = + from tab in tabs + where tab.Value.Actions != null + from action in tab.Value.Actions + where action.Value.Workflow != null + select action; + + foreach (var (key, value) in actionsWithWorkflows) + { + if (workflows.TryGetValue(value.Workflow, out var type)) + value.AdditionalFields["x-workflowSummary"] = type.GetDocumentation(); } - - // Generate Wizard object - - - // Return Wizard object - return new List(); + return simpleManifest; } private void ExtractEntitiesWithWizards(JsonElement element, IDictionary entities) diff --git a/src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj b/src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj index a3549d6..c87d43c 100644 --- a/src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj +++ b/src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj @@ -14,4 +14,13 @@ + + + ..\EAVFW.Extensions.Manifest.ManifestEnricherTool\bin\Debug\net8.0\EAVFW.Extensions.Manifest.SDK.dll + + + ..\..\..\..\hafnia\LetterofIndemnity\Hafnia.Tests\bin\Release\net6.0\WorkflowEngine.Core.dll + + + diff --git a/src/EAVFW.Extensions.Docs.Extracter/IDocumentLogic.cs b/src/EAVFW.Extensions.Docs.Extracter/IDocumentLogic.cs index ff95e3a..bb70159 100644 --- a/src/EAVFW.Extensions.Docs.Extracter/IDocumentLogic.cs +++ b/src/EAVFW.Extensions.Docs.Extracter/IDocumentLogic.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.IO; +using EAVFW.Extensions.Manifest.SDK; namespace EAVFW.Extensions.Docs.Extracter { @@ -21,6 +22,6 @@ public interface IDocumentLogic /// /// /// - IEnumerable ExtractWizardDocumentation(FileInfo manifestFile, PluginInfo pluginInfo); + Dictionary ExtractWizardDocumentation(FileInfo manifestFile, PluginInfo pluginInfo); } } diff --git a/src/EAVFW.Extensions.Docs.Extracter/JsonConverters/TypeConverter.cs b/src/EAVFW.Extensions.Docs.Extracter/JsonConverters/TypeConverter.cs index 2f40207..3154860 100644 --- a/src/EAVFW.Extensions.Docs.Extracter/JsonConverters/TypeConverter.cs +++ b/src/EAVFW.Extensions.Docs.Extracter/JsonConverters/TypeConverter.cs @@ -14,7 +14,7 @@ public class TypeConverter : JsonConverter public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options) { - JsonValue.Create(value.Name)?.WriteTo(writer, options); + JsonValue.Create(value.Name).WriteTo(writer, options); } } } diff --git a/src/EAVFW.Extensions.Docs.Generator/EAVFW.Extensions.Docs.Generator.csproj b/src/EAVFW.Extensions.Docs.Generator/EAVFW.Extensions.Docs.Generator.csproj index ae618e2..f4f75e8 100644 --- a/src/EAVFW.Extensions.Docs.Generator/EAVFW.Extensions.Docs.Generator.csproj +++ b/src/EAVFW.Extensions.Docs.Generator/EAVFW.Extensions.Docs.Generator.csproj @@ -9,4 +9,10 @@ + + + ..\EAVFW.Extensions.Manifest.ManifestEnricherTool\bin\Debug\net8.0\EAVFW.Extensions.Manifest.SDK.dll + + + diff --git a/src/EAVFW.Extensions.Docs.Generator/PluginDocumentationToReadMe.cs b/src/EAVFW.Extensions.Docs.Generator/PluginDocumentationToReadMe.cs index 8ff1ba4..c524be7 100644 --- a/src/EAVFW.Extensions.Docs.Generator/PluginDocumentationToReadMe.cs +++ b/src/EAVFW.Extensions.Docs.Generator/PluginDocumentationToReadMe.cs @@ -23,7 +23,7 @@ public PluginDocumentationToReadMe( _writer = new StreamWriter(path); } - public async Task WriteTables(FileInfo manifest) + public async Task WriteTables(FileInfo manifest, string component) { var manifestObject = await JsonSerializer.DeserializeAsync(manifest.OpenRead()); @@ -44,7 +44,7 @@ public async Task WriteTables(FileInfo manifest) } } - public async Task WritePlugins(IEnumerable pluginDocumentations) + public async Task WritePlugins(IEnumerable pluginDocumentations, string component) { var groups = pluginDocumentations.GroupBy(x => x.Entity!.Name); await _writer.WriteLineAsync("## Plugins "); @@ -74,8 +74,11 @@ await _writer.WriteLineAsync( } } } - - // public async Task WriteWizards() + + public async Task WriteWizards() + { + + } private string SanitizeSummary(string summary) diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/App.cs b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/App.cs index 6176912..997a3c3 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/App.cs +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/App.cs @@ -1,77 +1,53 @@ - +// See https://aka.ms/new-console-template for more information - -// See https://aka.ms/new-console-template for more information +using System; using EAVFW.Extensions.Manifest.ManifestEnricherTool; using EAVFW.Extensions.Manifest.SDK; using Microsoft.Extensions.Logging; -using Newtonsoft.Json.Linq; using System.Collections.Generic; using System.CommandLine; using System.CommandLine.NamingConventionBinder; using System.CommandLine.Parsing; using System.IO; -using System.Linq; using System.Reflection; using System.Text.Json; using System.Threading.Tasks; public class App : System.CommandLine.RootCommand { - public Option Path = new Option("--path", "The path"); + public Option Path = new Option("--path", "The path"); public Option Prefix = new Option(new string[] { "--customizationprefix" }, "The prefix"); private readonly ILogger logger; private readonly IManifestEnricher manifestEnricher; + private readonly IManifestMerger _manifestMerger; - public App(ILogger logger, IEnumerable commands, IManifestEnricher manifestEnricher) : base($"Generating Manifest: v{Assembly.GetExecutingAssembly().GetCustomAttribute()?.InformationalVersion}") + public App(ILogger logger, IEnumerable commands, IManifestEnricher manifestEnricher, IManifestMerger manifestMerger) : base( + $"Generating Manifest: v{Assembly.GetExecutingAssembly().GetCustomAttribute()?.InformationalVersion}") { - this.logger=logger; + this.logger = logger; this.manifestEnricher = manifestEnricher; - Path.IsRequired=true; - - Add(Path); + _manifestMerger = manifestMerger ?? throw new ArgumentNullException(nameof(manifestMerger)); + Path.IsRequired = true; + + Add(Path); Add(Prefix); foreach (var command in commands) Add(command); - Handler = CommandHandler.Create(Run); + Handler = CommandHandler.Create(Run); } - public async Task Run(ParseResult parseResult, IConsole console) //(string path, string customizationprefix) + public async Task Run(ParseResult parseResult, IConsole console) { var path = parseResult.GetValueForOption(Path); var customizationprefix = parseResult.GetValueForOption(Prefix); - console.Out.Write($"Generating Manifest: v{Assembly.GetExecutingAssembly().GetCustomAttribute()?.InformationalVersion} - {Assembly.GetExecutingAssembly().GetCustomAttribute()?.Version}"); - - // var cmd = new EAVFW.Extensions.Manifest.ManifestEnricherTool.RootCommand(); - - - - - using (var fs = File.OpenRead(path)) - { - - var jsonraw = Newtonsoft.Json.Linq.JToken.ReadFrom(new Newtonsoft.Json.JsonTextReader(new StreamReader(fs))) as JObject; - var others = Directory.GetFiles(System.IO.Path.GetDirectoryName(path), "manifest.*.json") - .Where(c => !string.Equals("manifest.schema.json", System.IO.Path.GetFileName(c), System.StringComparison.OrdinalIgnoreCase)); - foreach (var other in others) - { - jsonraw.Merge(JToken.Parse(File.ReadAllText(other)), new JsonMergeSettings - { - // union array values together to avoid duplicates - MergeArrayHandling = MergeArrayHandling.Union, - PropertyNameComparison = System.StringComparison.OrdinalIgnoreCase, - MergeNullValueHandling = MergeNullValueHandling.Ignore - }); - } - - JsonDocument json = await manifestEnricher.LoadJsonDocumentAsync(jsonraw, customizationprefix, logger); - } - - + console.Out.Write( + $"Generating Manifest: v{Assembly.GetExecutingAssembly().GetCustomAttribute()?.InformationalVersion} - {Assembly.GetExecutingAssembly().GetCustomAttribute()?.Version}"); + var t = await _manifestMerger.MergeManifests(path); + JsonDocument json = await manifestEnricher.LoadJsonDocumentAsync(t, customizationprefix, logger); } -} \ No newline at end of file +} diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs index cc0154b..e966be2 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs @@ -16,7 +16,6 @@ public class DocumentCommand : Command { private readonly IDocumentLogic documentLogic; - [Alias("-a")] [Alias("--assembly")] [Description("Path for the assembly")] @@ -24,7 +23,7 @@ public class DocumentCommand : Command [Alias("-m")] [Alias("--manifest")] - [Description("Path for the manifest")] + [Description("Path for the enriched manifest")] public FileInfo ManifestPathOption { get; set; } [Alias("-p")] @@ -37,11 +36,19 @@ public class DocumentCommand : Command [Description("Configuration for the built assembly")] public string ConfigurationOption { get; set; } + [Alias("--component")] + [Description("Component to generate documentation. E.g., `mainfest.component.json`")] + public string ComponentOption { get; set; } + [Alias("-f")] [Alias("--framework")] [Description("Framework confugraiton for the built assembly")] public string FrameworkOption { get; set; } + [Alias("-o")] + [Alias("--output")] + [Description("Output directory for genreated documentation source files")] + public DirectoryInfo OutputOption { get; set; } [Alias("-t")] [Alias("--target")] @@ -54,7 +61,6 @@ public enum Targets Wizards } - public DocumentCommand(IDocumentLogic documentLogic) : base("docs", "Generate documentation") { this.documentLogic = documentLogic ?? throw new ArgumentNullException(nameof(documentLogic)); @@ -90,8 +96,6 @@ private async Task Run(ParseResult parseResult, IConsole console) default: throw new ArgumentOutOfRangeException(); } - - return 0; } private async Task HandleWizards() @@ -102,9 +106,29 @@ private async Task HandleWizards() return 1; } - var t = documentLogic.ExtractWizardDocumentation(ManifestPathOption, new PluginInfo(RootPathOption, - AssemblyPathOption, ConfigurationOption, - FrameworkOption)); + var entityDefinitions = documentLogic.ExtractWizardDocumentation( + ManifestPathOption, + new PluginInfo(RootPathOption, + AssemblyPathOption, + ConfigurationOption, + FrameworkOption)); + + var basePath = new DirectoryInfo(CalculateFullPath("wizards")); + + if(!basePath.Exists) + basePath.Create(); + + foreach (var (key, value) in entityDefinitions) + { + var fileName = Path.Combine(basePath.FullName, $"{key}.json"); + + await using var createStream = File.Create(fileName); + await JsonSerializer.SerializeAsync(createStream, value, new JsonSerializerOptions + { + WriteIndented = true + }); + await createStream.DisposeAsync(); + } return 0; } @@ -121,15 +145,23 @@ private async Task HandlePlugins() Converters = { new PluginRegistrationAttributeConverter() }, WriteIndented = true }); - await File.WriteAllTextAsync("docs.json", jsonString); - using var writer = new PluginDocumentationToReadMe(); - await writer.WriteTables(ManifestPathOption); - await writer.WritePlugins(plugins); + var path = CalculateFullPath("plugins.json"); + await File.WriteAllTextAsync(path, jsonString); return 0; } + private string CalculateFullPath(string path) + { + if (OutputOption != null) + { + path = Path.Combine(OutputOption.FullName, path); + } + + return path; + } + private bool IsMissingOptions(out List missing) { missing = new List(); diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj index 89494e0..445e2a4 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj @@ -20,6 +20,7 @@ + diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/IManifestMerger.cs b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/IManifestMerger.cs new file mode 100644 index 0000000..6b20534 --- /dev/null +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/IManifestMerger.cs @@ -0,0 +1,15 @@ +using System.IO; +using System.Threading.Tasks; +using Newtonsoft.Json.Linq; + +namespace EAVFW.Extensions.Manifest.ManifestEnricherTool +{ + public interface IManifestMerger + { + /// + /// Component Manifest files are loaded based on the . + /// + /// Path for the root manifest file, manifest.json + public Task MergeManifests(FileInfo path); + } +} diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/IModuleMetadataEnricher.cs b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/IModuleMetadataEnricher.cs new file mode 100644 index 0000000..d467e92 --- /dev/null +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/IModuleMetadataEnricher.cs @@ -0,0 +1,14 @@ +using Newtonsoft.Json.Linq; + +namespace EAVFW.Extensions.Manifest.ManifestEnricherTool +{ + public interface IModuleMetadataEnricher + { + /// + /// Add metadata to each module before merging and enriching manifests. + /// + /// The module manifest + /// The module manifest json file name + public void AddSource(JToken manifest, string source); + } +} diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/ManifestMerger.cs b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/ManifestMerger.cs new file mode 100644 index 0000000..48b56fd --- /dev/null +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/ManifestMerger.cs @@ -0,0 +1,52 @@ +using System; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Newtonsoft.Json.Linq; + +namespace EAVFW.Extensions.Manifest.ManifestEnricherTool +{ + public class ManifestMerger : IManifestMerger + { + private readonly IModuleMetadataEnricher _moduleMetadataEnricher; + + public ManifestMerger(IModuleMetadataEnricher moduleMetadataEnricher) + { + _moduleMetadataEnricher = + moduleMetadataEnricher ?? throw new ArgumentNullException(nameof(moduleMetadataEnricher)); + } + + /// + public async Task MergeManifests(FileInfo path) + { + await using var fs = File.OpenRead(path.FullName); + + var jtokenRaw = await JToken.ReadFromAsync(new Newtonsoft.Json.JsonTextReader(new StreamReader(fs))); + + _moduleMetadataEnricher.AddSource(jtokenRaw, path.Name); + var jsonRaw = jtokenRaw as JObject; + + var others = Directory.GetFiles(path.DirectoryName!, "manifest.*.json") + .Where(c => !string.Equals("manifest.schema.json", System.IO.Path.GetFileName(c), + StringComparison.OrdinalIgnoreCase)); + + foreach (var other in others) + { + var fileInfo = new FileInfo(other); + + var component = JToken.Parse(await File.ReadAllTextAsync(fileInfo.FullName)); + + _moduleMetadataEnricher.AddSource(component, fileInfo.Name); + jsonRaw.Merge(component, new JsonMergeSettings + { + // union array values together to avoid duplicates + MergeArrayHandling = MergeArrayHandling.Union, + PropertyNameComparison = System.StringComparison.OrdinalIgnoreCase, + MergeNullValueHandling = MergeNullValueHandling.Ignore + }); + } + + return jsonRaw; + } + } +} diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/ModuleMetadataEnricher.cs b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/ModuleMetadataEnricher.cs new file mode 100644 index 0000000..1a58fe1 --- /dev/null +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/ModuleMetadataEnricher.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using Newtonsoft.Json.Linq; + +namespace EAVFW.Extensions.Manifest.ManifestEnricherTool +{ + public class ModuleMetadataEnricher : IModuleMetadataEnricher + { + /// + public void AddSource(JToken jToken, string source) + { + var entities = jToken.SelectToken("$.entities")?.Children(); + + if (entities == null) return; + + foreach (var entity in entities) + { + (entity.First as JObject)?.Add("moduleSource", source); + (entity.First as JObject)?.Add("moduleLocation", "manifest"); + + var attributes = entity.First?.SelectToken("$.attributes")?.Children(); + + if (attributes == null) continue; + + foreach (var attribute in attributes) + { + (attribute.First as JObject)?.Add("moduleSource", source); + (attribute.First as JObject)?.Add("moduleLocation", "entity"); + } + } + + var variables = jToken.SelectToken("$.variables"); + if (variables == null) + return; + + foreach (var child in variables.Children()) + { + WalkJToken(child, source); + } + } + + private void WalkJToken(JToken jToken, string source) + { + switch (jToken) + { + case JProperty jProperty: + // jp.Add("moduleSource", source); + // jp.Add("moduleLocation", "variables"); + foreach (var child in jProperty.Children()) + { + WalkJToken(child, source); + } + + break; + case JObject jObject: + jObject.Add("moduleSource", source); + jObject.Add("moduleLocation", "variables"); + foreach (var child in jObject.Children()) + { + WalkJToken(child, source); + } + + break; + case JArray jArray: + foreach (var child in jArray.Children()) + { + WalkJToken(child, source); + } + + break; + } + } + } +} diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Program.cs b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Program.cs index f4e1b86..9535825 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Program.cs +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Program.cs @@ -38,6 +38,9 @@ static IServiceCollection ConfigureServices(IServiceCollection serviceCollection serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddGPT(); + + serviceCollection.AddTransient(); + serviceCollection.AddTransient(); serviceCollection.AddHttpClient(); return serviceCollection; diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json index 7ec3e90..fcf09a0 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json @@ -3,8 +3,9 @@ "EAVFW.Extensions.Manifest.ManifestEnricherTool": { "commandName": "Project", "workingDirectory": "/Users/thyge/dev/playground", -// "commandLineArgs": "docs -c Release -t wizards -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\" -m \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/manifest.loi.json\"" - "commandLineArgs": "docs -c Release -t plugins -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\" -m \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/manifest.loi.json\"" +// "workingDirectory": "/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models", + "commandLineArgs": "docs -c Release -t wizards -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\" -m \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/manifest.loi.json\"" +// "commandLineArgs": "docs -c Release -t plugins -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\" -m \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/manifest.loi.json\"" // "commandLineArgs": "binary --unzip 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" // "commandLineArgs": "binary --unzip 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" // "commandLineArgs": "binary --unzip --pretty-print 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" @@ -22,9 +23,11 @@ // "commandLineArgs": "--path C:\\dev\\MedlemsCentralen\\src\\MC.Models\\manifest.json --customizationprefix MC" // "commandLineArgs": "sql ./src/Hafnia.Models", + // "commandLineArgs": "gpt review pr --project https://github.com/delegateas/WorkflowEngine.git --pr 15" // "commandLineArgs": "sql ./apps/KFST.Vanddata.ManagementPortal" - //"commandLineArgs": "--path C:\\dev\\hafnia\\loi\\src\\Hafnia.Models\\manifest.json --customizationprefix hafnia" +// "commandLineArgs": "--path C:\\dev\\hafnia\\loi\\src\\Hafnia.Models\\manifest.json --customizationprefix hafnia" +// "commandLineArgs": "--path /Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/manifest.json --customizationprefix hafnia" } } } diff --git a/tests/EAVFW.Extensions.Manifest.Tests/EAVFW.Extensions.Manifest.Tests.csproj b/tests/EAVFW.Extensions.Manifest.Tests/EAVFW.Extensions.Manifest.Tests.csproj index aee4d5c..bffa217 100644 --- a/tests/EAVFW.Extensions.Manifest.Tests/EAVFW.Extensions.Manifest.Tests.csproj +++ b/tests/EAVFW.Extensions.Manifest.Tests/EAVFW.Extensions.Manifest.Tests.csproj @@ -9,8 +9,9 @@ - - + + + @@ -31,6 +32,9 @@ PreserveNewest + + PreserveNewest + diff --git a/tests/EAVFW.Extensions.Manifest.Tests/Merge/AppTest.cs b/tests/EAVFW.Extensions.Manifest.Tests/Merge/AppTest.cs new file mode 100644 index 0000000..0fd0331 --- /dev/null +++ b/tests/EAVFW.Extensions.Manifest.Tests/Merge/AppTest.cs @@ -0,0 +1,39 @@ +using System.IO; +using System.Threading.Tasks; +using EAVFW.Extensions.Manifest.ManifestEnricherTool; +using JsonDiffPatchDotNet; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace EAVFW.Extensions.Manifest.Tests.Merge +{ + [TestClass] + public class AppTest + { + [TestMethod] + public async Task Test1() + { + // Arrange + var rootManifest = new FileInfo("Merge/manifest.json"); + var expectedManifestFileInfo = new FileInfo("Merge/expected.manifest.json"); + var expectedManifest = JToken.Parse(await File.ReadAllTextAsync(expectedManifestFileInfo.FullName)); + + var merger = new ManifestMerger(new ModuleMetadataEnricher()); + + // Act + var merged = await merger.MergeManifests(rootManifest); + + await using var fileStream = new FileStream("Merge/outpot.json", FileMode.Create); + var streamWriter = new StreamWriter(fileStream); + var jsonWriter = new JsonTextWriter(streamWriter); + await merged.WriteToAsync(jsonWriter); + await jsonWriter.FlushAsync(); + + // Assert + var diff = new JsonDiffPatch().Diff(merged, expectedManifest); + + Assert.IsNull(diff); + } + } +} diff --git a/tests/EAVFW.Extensions.Manifest.Tests/Merge/expected.manifest.json b/tests/EAVFW.Extensions.Manifest.Tests/Merge/expected.manifest.json new file mode 100644 index 0000000..d07c480 --- /dev/null +++ b/tests/EAVFW.Extensions.Manifest.Tests/Merge/expected.manifest.json @@ -0,0 +1,67 @@ +{ + "variables": { + "Audit": { + "moduleSource": "manifest.json", + "moduleLocation": "variables", + "CreatedOn": { + "moduleSource": "manifest.json", + "moduleLocation": "variables", + "type": "DateTime" + } + }, + "Administrative": { + "moduleSource": "manifest.json", + "moduleLocation": "variables", + "tab": "TAB_Administrative" + } + }, + "entities": { + "System User": { + "pluralName": "System Users", +// "moduleSource": "manifest.json", + "moduleSource": "manifest.component.json", + "moduleLocation": "manifest", + "attributes": { + "Email": { + "type": "Text", + "moduleSource": "manifest.json", + "moduleLocation": "entity" + }, + "Name": { + "type": "Text", + "moduleSource": "manifest.json", + "moduleLocation": "entity" + }, + "Organization": { + "type": "Text", + "moduleSource": "manifest.component.json", + "moduleLocation": "entity" + } + } + }, + "Identity": { + "pluralName": "Identities", + "moduleSource": "manifest.json", + "moduleLocation": "manifest", + "attributes": { + "Name": { + "type": "Text", + "moduleSource": "manifest.json", + "moduleLocation": "entity" + } + } + }, + "Component Table": { + "pluralName": "Component Tables", + "moduleSource": "manifest.component.json", + "moduleLocation": "manifest", + "attributes": { + "Name": { + "type": "Text", + "moduleSource": "manifest.component.json", + "moduleLocation": "entity" + } + } + } + } +} diff --git a/tests/EAVFW.Extensions.Manifest.Tests/Merge/manifest.component.json b/tests/EAVFW.Extensions.Manifest.Tests/Merge/manifest.component.json new file mode 100644 index 0000000..b9bb20b --- /dev/null +++ b/tests/EAVFW.Extensions.Manifest.Tests/Merge/manifest.component.json @@ -0,0 +1,19 @@ +{ + "entities": { + "System User": { + "attributes": { + "Organization": { + "type": "Text" + } + } + }, + "Component Table": { + "pluralName": "Component Tables", + "attributes": { + "Name": { + "type": "Text" + } + } + } + } +} diff --git a/tests/EAVFW.Extensions.Manifest.Tests/Merge/manifest.json b/tests/EAVFW.Extensions.Manifest.Tests/Merge/manifest.json new file mode 100644 index 0000000..e109781 --- /dev/null +++ b/tests/EAVFW.Extensions.Manifest.Tests/Merge/manifest.json @@ -0,0 +1,33 @@ +{ + "variables": { + "Audit": { + "CreatedOn": { + "type": "DateTime" + } + }, + "Administrative": { + "tab": "TAB_Administrative" + } + }, + "entities": { + "System User": { + "pluralName": "System Users", + "attributes": { + "Email": { + "type": "Text" + }, + "Name": { + "type": "Text" + } + } + }, + "Identity": { + "pluralName": "Identities", + "attributes": { + "Name": { + "type": "Text" + } + } + } + } +} diff --git a/tests/EAVFW.Extensions.Manifest.Tests/TestLogger.cs b/tests/EAVFW.Extensions.Manifest.Tests/TestLogger.cs new file mode 100644 index 0000000..789e5a4 --- /dev/null +++ b/tests/EAVFW.Extensions.Manifest.Tests/TestLogger.cs @@ -0,0 +1,31 @@ +using System; +using Microsoft.Extensions.Logging; + +namespace EAVFW.Extensions.Manifest.Tests +{ + // https://alastaircrabtree.com/using-logging-in-unit-tests-in-net-core/ + public static class TestLogger + { + public static ILogger Create() + { + var logger = new NUnitLogger(); + return logger; + } + + private class NUnitLogger : ILogger, IDisposable + { + private readonly Action _output = Console.WriteLine; + + public void Dispose() + { + } + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, + Func formatter) => _output(formatter(state, exception)); + + public bool IsEnabled(LogLevel logLevel) => true; + + public IDisposable BeginScope(TState state) => this; + } + } +} From 32ec6c1649a6f41ae622def6be43223cd7298149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thyge=20Sk=C3=B8dt=20Steffensen?= <31892312+thygesteffensen@users.noreply.github.com> Date: Wed, 22 Nov 2023 14:38:33 +0100 Subject: [PATCH 06/10] feat: Working version of documentation extractor and markdown generated --- ...tensions.Manifest.ManifestEnricherTool.sln | 2 +- external/EAVFramework | 2 +- ...tensions.Docs.Extracter.csproj.DotSettings | 6 - .../PluginRegistrationAttributeConverter.cs | 34 ---- .../JsonConverters/TypeConverter.cs | 20 --- .../Plugin/PluginDocumentation.cs | 20 --- .../CustomAssemblyResolver.cs | 2 +- .../DocumentLogic.cs | 13 +- .../EAVFW.Extensions.Docs.Extractor.csproj} | 1 + .../IDocumentLogic.cs | 2 +- .../Plugin/AssemblyInfo.cs | 2 +- .../Plugin/PluginDocumentation.cs | 20 +++ .../Plugin/PluginInfo.cs | 2 +- .../Plugin/PluginRegistrationAttributeData.cs | 12 ++ .../Plugin/TypeInformation.cs | 24 +++ .../Plugin/XmlDocumentationHelper.cs | 2 +- .../Plugin/XmlMemberElement.cs | 2 +- .../ServiceCollectionExtension.cs | 2 +- .../EAVFW.Extensions.Docs.Generator.csproj | 2 +- .../IDocumentationGenerator.cs | 16 ++ .../PluginDocumentationToReadMe.cs | 125 -------------- .../ReadMeDocumentationGenerator.cs | 155 ++++++++++++++++++ .../DocumentationGeneratorCommand.cs | 92 +++++++++++ .../DocumentationSourceCommand.cs | 24 +++ .../DocumentationSourceExtractorCommand.cs} | 50 +++--- ...sions.Manifest.ManifestEnricherTool.csproj | 2 +- .../Program.cs | 7 +- .../Properties/launchSettings.json | 5 +- 28 files changed, 394 insertions(+), 252 deletions(-) delete mode 100644 src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj.DotSettings delete mode 100644 src/EAVFW.Extensions.Docs.Extracter/JsonConverters/PluginRegistrationAttributeConverter.cs delete mode 100644 src/EAVFW.Extensions.Docs.Extracter/JsonConverters/TypeConverter.cs delete mode 100644 src/EAVFW.Extensions.Docs.Extracter/Plugin/PluginDocumentation.cs rename src/{EAVFW.Extensions.Docs.Extracter => EAVFW.Extensions.Docs.Extractor}/CustomAssemblyResolver.cs (96%) rename src/{EAVFW.Extensions.Docs.Extracter => EAVFW.Extensions.Docs.Extractor}/DocumentLogic.cs (92%) rename src/{EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj => EAVFW.Extensions.Docs.Extractor/EAVFW.Extensions.Docs.Extractor.csproj} (92%) rename src/{EAVFW.Extensions.Docs.Extracter => EAVFW.Extensions.Docs.Extractor}/IDocumentLogic.cs (95%) rename src/{EAVFW.Extensions.Docs.Extracter => EAVFW.Extensions.Docs.Extractor}/Plugin/AssemblyInfo.cs (81%) create mode 100644 src/EAVFW.Extensions.Docs.Extractor/Plugin/PluginDocumentation.cs rename src/{EAVFW.Extensions.Docs.Extracter => EAVFW.Extensions.Docs.Extractor}/Plugin/PluginInfo.cs (96%) create mode 100644 src/EAVFW.Extensions.Docs.Extractor/Plugin/PluginRegistrationAttributeData.cs create mode 100644 src/EAVFW.Extensions.Docs.Extractor/Plugin/TypeInformation.cs rename src/{EAVFW.Extensions.Docs.Extracter => EAVFW.Extensions.Docs.Extractor}/Plugin/XmlDocumentationHelper.cs (97%) rename src/{EAVFW.Extensions.Docs.Extracter => EAVFW.Extensions.Docs.Extractor}/Plugin/XmlMemberElement.cs (85%) rename src/{EAVFW.Extensions.Docs.Extracter => EAVFW.Extensions.Docs.Extractor}/ServiceCollectionExtension.cs (89%) create mode 100644 src/EAVFW.Extensions.Docs.Generator/IDocumentationGenerator.cs delete mode 100644 src/EAVFW.Extensions.Docs.Generator/PluginDocumentationToReadMe.cs create mode 100644 src/EAVFW.Extensions.Docs.Generator/ReadMeDocumentationGenerator.cs create mode 100644 src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/Documentation/DocumentationGeneratorCommand.cs create mode 100644 src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/Documentation/DocumentationSourceCommand.cs rename src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/{DocumentCommand.cs => Documentation/DocumentationSourceExtractorCommand.cs} (75%) diff --git a/EAVFW.Extensions.Manifest.ManifestEnricherTool.sln b/EAVFW.Extensions.Manifest.ManifestEnricherTool.sln index 1cb1253..146db41 100644 --- a/EAVFW.Extensions.Manifest.ManifestEnricherTool.sln +++ b/EAVFW.Extensions.Manifest.ManifestEnricherTool.sln @@ -44,7 +44,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EAVFramework", "external\EA EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EAVFW.Extensions.Manifest.SDK", "external\EAVFramework\sdk\EAVFW.Extensions.Manifest.SDK.csproj", "{3BEF0769-ABD1-4D34-8004-C98DE9FB0339}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EAVFW.Extensions.Docs.Extracter", "src\EAVFW.Extensions.Docs.Extracter\EAVFW.Extensions.Docs.Extracter.csproj", "{432042AB-6A78-4ED7-B8AC-73B047F6630F}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EAVFW.Extensions.Docs.Extractor", "src\EAVFW.Extensions.Docs.Extractor\EAVFW.Extensions.Docs.Extractor.csproj", "{432042AB-6A78-4ED7-B8AC-73B047F6630F}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EAVFW.Extensions.Docs.Generator", "src\EAVFW.Extensions.Docs.Generator\EAVFW.Extensions.Docs.Generator.csproj", "{71FCB365-F4AE-4578-BF86-B4A3C278B6B1}" EndProject diff --git a/external/EAVFramework b/external/EAVFramework index 65e40e2..f58d2ee 160000 --- a/external/EAVFramework +++ b/external/EAVFramework @@ -1 +1 @@ -Subproject commit 65e40e29208c746d0580ee123845df11f209d3b1 +Subproject commit f58d2eeef1ad7c24177e434fd093465c16e55094 diff --git a/src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj.DotSettings b/src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj.DotSettings deleted file mode 100644 index 6ed5a98..0000000 --- a/src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj.DotSettings +++ /dev/null @@ -1,6 +0,0 @@ - - True diff --git a/src/EAVFW.Extensions.Docs.Extracter/JsonConverters/PluginRegistrationAttributeConverter.cs b/src/EAVFW.Extensions.Docs.Extracter/JsonConverters/PluginRegistrationAttributeConverter.cs deleted file mode 100644 index bc70d3c..0000000 --- a/src/EAVFW.Extensions.Docs.Extracter/JsonConverters/PluginRegistrationAttributeConverter.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Text.Json; -using System.Text.Json.Nodes; -using System.Text.Json.Serialization; -using EAVFramework.Plugins; - -namespace EAVFW.Extensions.Docs.Extracter -{ - public class PluginRegistrationAttributeConverter : JsonConverter - { - public override PluginRegistrationAttribute? Read( - ref Utf8JsonReader reader, - Type typeToConvert, - JsonSerializerOptions options) - { - throw new NotImplementedException(); - } - - public override void Write( - Utf8JsonWriter writer, - PluginRegistrationAttribute value, - JsonSerializerOptions options) - { - var _object = new JsonObject - { - { nameof(value.Order), value.Order }, - { nameof(value.Operation), value.Operation.ToString() }, - { nameof(value.Execution), value.Execution.ToString() }, - { nameof(value.Mode), value.Mode.ToString() } - }; - _object.WriteTo(writer); - } - } -} diff --git a/src/EAVFW.Extensions.Docs.Extracter/JsonConverters/TypeConverter.cs b/src/EAVFW.Extensions.Docs.Extracter/JsonConverters/TypeConverter.cs deleted file mode 100644 index 3154860..0000000 --- a/src/EAVFW.Extensions.Docs.Extracter/JsonConverters/TypeConverter.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Text.Json; -using System.Text.Json.Nodes; -using System.Text.Json.Serialization; - -namespace EAVFW.Extensions.Docs.Extracter -{ - public class TypeConverter : JsonConverter - { - public override Type? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - throw new NotImplementedException(); - } - - public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options) - { - JsonValue.Create(value.Name).WriteTo(writer, options); - } - } -} diff --git a/src/EAVFW.Extensions.Docs.Extracter/Plugin/PluginDocumentation.cs b/src/EAVFW.Extensions.Docs.Extracter/Plugin/PluginDocumentation.cs deleted file mode 100644 index e6ae712..0000000 --- a/src/EAVFW.Extensions.Docs.Extracter/Plugin/PluginDocumentation.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text.Json.Serialization; -using EAVFramework.Plugins; - -namespace EAVFW.Extensions.Docs.Extracter -{ - public class PluginDocumentation - { - public IEnumerable PluginRegistrations { get; set; } = - Array.Empty(); - - public string? Name { get; set; } - - [JsonConverter(typeof(TypeConverter))] public Type? Context { get; set; } - - [JsonConverter(typeof(TypeConverter))] public Type? Entity { get; set; } - public string Summary { get; set; } = ""; - } -} diff --git a/src/EAVFW.Extensions.Docs.Extracter/CustomAssemblyResolver.cs b/src/EAVFW.Extensions.Docs.Extractor/CustomAssemblyResolver.cs similarity index 96% rename from src/EAVFW.Extensions.Docs.Extracter/CustomAssemblyResolver.cs rename to src/EAVFW.Extensions.Docs.Extractor/CustomAssemblyResolver.cs index a2922f3..f0f8d67 100644 --- a/src/EAVFW.Extensions.Docs.Extracter/CustomAssemblyResolver.cs +++ b/src/EAVFW.Extensions.Docs.Extractor/CustomAssemblyResolver.cs @@ -3,7 +3,7 @@ using System.Linq; using System.Reflection; -namespace EAVFW.Extensions.Docs.Extracter +namespace EAVFW.Extensions.Docs.Extractor { public static class CustomAssemblyResolver { diff --git a/src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs b/src/EAVFW.Extensions.Docs.Extractor/DocumentLogic.cs similarity index 92% rename from src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs rename to src/EAVFW.Extensions.Docs.Extractor/DocumentLogic.cs index 0da526c..3ac7e5e 100644 --- a/src/EAVFW.Extensions.Docs.Extracter/DocumentLogic.cs +++ b/src/EAVFW.Extensions.Docs.Extractor/DocumentLogic.cs @@ -4,14 +4,12 @@ using System.Linq; using System.Reflection; using System.Runtime.Loader; -using System.Security.Principal; using System.Text.Json; -using System.Text.Json.Serialization; using EAVFramework.Plugins; using EAVFW.Extensions.Manifest.SDK; using WorkflowEngine.Core; -namespace EAVFW.Extensions.Docs.Extracter +namespace EAVFW.Extensions.Docs.Extractor { public class DocumentLogic : IDocumentLogic { @@ -53,11 +51,12 @@ from implementingType in implementingTypes .FirstOrDefault(i => i.GenericTypeArguments.Length == 2) select new PluginDocumentation { - PluginRegistrations = pluginRegistrations, + PluginRegistrations = pluginRegistrations.Select(x => new PluginRegistrationAttributeData + { Order = x.Order, Execution = x.Execution, Operation = x.Operation, Mode = x.Mode }), Name = implementingType.Name, Summary = implementingType.GetDocumentation(), - Context = _interface.GetGenericArguments().First(), - Entity = _interface.GetGenericArguments().Last() + Context = new TypeInformation(_interface.GetGenericArguments().First()), + Entity = new TypeInformation(_interface.GetGenericArguments().Last()) }; return plugins; @@ -106,7 +105,7 @@ from wizard in entity.Value.Wizards from _tabs in wizard.Value.Tabs select _tabs).AsEnumerable(); - // Glorified for loop? + // Glorified for loop?w var tabsWithWorkflows = from tab in tabs where tab.Value.OnTransitionOut?.Workflow != null || tab.Value.OnTransitionIn?.Workflow != null diff --git a/src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj b/src/EAVFW.Extensions.Docs.Extractor/EAVFW.Extensions.Docs.Extractor.csproj similarity index 92% rename from src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj rename to src/EAVFW.Extensions.Docs.Extractor/EAVFW.Extensions.Docs.Extractor.csproj index c87d43c..a3fecf8 100644 --- a/src/EAVFW.Extensions.Docs.Extracter/EAVFW.Extensions.Docs.Extracter.csproj +++ b/src/EAVFW.Extensions.Docs.Extractor/EAVFW.Extensions.Docs.Extractor.csproj @@ -4,6 +4,7 @@ 9.0 net8.0 enable + EAVFW.Extensions.Docs.Extracter diff --git a/src/EAVFW.Extensions.Docs.Extracter/IDocumentLogic.cs b/src/EAVFW.Extensions.Docs.Extractor/IDocumentLogic.cs similarity index 95% rename from src/EAVFW.Extensions.Docs.Extracter/IDocumentLogic.cs rename to src/EAVFW.Extensions.Docs.Extractor/IDocumentLogic.cs index bb70159..e74952c 100644 --- a/src/EAVFW.Extensions.Docs.Extracter/IDocumentLogic.cs +++ b/src/EAVFW.Extensions.Docs.Extractor/IDocumentLogic.cs @@ -2,7 +2,7 @@ using System.IO; using EAVFW.Extensions.Manifest.SDK; -namespace EAVFW.Extensions.Docs.Extracter +namespace EAVFW.Extensions.Docs.Extractor { public interface IDocumentLogic { diff --git a/src/EAVFW.Extensions.Docs.Extracter/Plugin/AssemblyInfo.cs b/src/EAVFW.Extensions.Docs.Extractor/Plugin/AssemblyInfo.cs similarity index 81% rename from src/EAVFW.Extensions.Docs.Extracter/Plugin/AssemblyInfo.cs rename to src/EAVFW.Extensions.Docs.Extractor/Plugin/AssemblyInfo.cs index d76edcc..6168edb 100644 --- a/src/EAVFW.Extensions.Docs.Extracter/Plugin/AssemblyInfo.cs +++ b/src/EAVFW.Extensions.Docs.Extractor/Plugin/AssemblyInfo.cs @@ -1,4 +1,4 @@ -namespace EAVFW.Extensions.Docs.Extracter +namespace EAVFW.Extensions.Docs.Extractor { public class AssemblyInfo { diff --git a/src/EAVFW.Extensions.Docs.Extractor/Plugin/PluginDocumentation.cs b/src/EAVFW.Extensions.Docs.Extractor/Plugin/PluginDocumentation.cs new file mode 100644 index 0000000..facc0f5 --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Extractor/Plugin/PluginDocumentation.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace EAVFW.Extensions.Docs.Extractor +{ + public class PluginDocumentation + { + public IEnumerable PluginRegistrations { get; set; } = + Array.Empty(); + + public string? Name { get; set; } + + [JsonPropertyName("context")] public TypeInformation Context { get; set; } + + [JsonPropertyName("entity")] public TypeInformation Entity { get; set; } + + public string Summary { get; set; } = ""; + } +} diff --git a/src/EAVFW.Extensions.Docs.Extracter/Plugin/PluginInfo.cs b/src/EAVFW.Extensions.Docs.Extractor/Plugin/PluginInfo.cs similarity index 96% rename from src/EAVFW.Extensions.Docs.Extracter/Plugin/PluginInfo.cs rename to src/EAVFW.Extensions.Docs.Extractor/Plugin/PluginInfo.cs index f26bf60..344c615 100644 --- a/src/EAVFW.Extensions.Docs.Extracter/Plugin/PluginInfo.cs +++ b/src/EAVFW.Extensions.Docs.Extractor/Plugin/PluginInfo.cs @@ -1,7 +1,7 @@ using System; using System.IO; -namespace EAVFW.Extensions.Docs.Extracter +namespace EAVFW.Extensions.Docs.Extractor { public struct PluginInfo { diff --git a/src/EAVFW.Extensions.Docs.Extractor/Plugin/PluginRegistrationAttributeData.cs b/src/EAVFW.Extensions.Docs.Extractor/Plugin/PluginRegistrationAttributeData.cs new file mode 100644 index 0000000..84ec9b5 --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Extractor/Plugin/PluginRegistrationAttributeData.cs @@ -0,0 +1,12 @@ +using EAVFramework.Plugins; + +namespace EAVFW.Extensions.Docs.Extractor +{ + public class PluginRegistrationAttributeData + { + public EntityPluginExecution Execution { get; set; } + public EntityPluginOperation Operation { get; set; } + public EntityPluginMode Mode { get; set; } + public int Order { get; set; } + } +} diff --git a/src/EAVFW.Extensions.Docs.Extractor/Plugin/TypeInformation.cs b/src/EAVFW.Extensions.Docs.Extractor/Plugin/TypeInformation.cs new file mode 100644 index 0000000..1f6c4fb --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Extractor/Plugin/TypeInformation.cs @@ -0,0 +1,24 @@ +using System; +using System.Linq; +using System.Text.Json.Serialization; + +namespace EAVFW.Extensions.Docs.Extractor +{ + public class TypeInformation + { + [JsonPropertyName("AssemblyQualifiedName")] + public string AssemblyQualifiedName { get; set; } + + [JsonIgnore] + public string Name => AssemblyQualifiedName.Split(',').First().Split('.').Last().Trim(); + + public TypeInformation() + { + } + + public TypeInformation(Type type) + { + AssemblyQualifiedName = type.AssemblyQualifiedName; + } + } +} diff --git a/src/EAVFW.Extensions.Docs.Extracter/Plugin/XmlDocumentationHelper.cs b/src/EAVFW.Extensions.Docs.Extractor/Plugin/XmlDocumentationHelper.cs similarity index 97% rename from src/EAVFW.Extensions.Docs.Extracter/Plugin/XmlDocumentationHelper.cs rename to src/EAVFW.Extensions.Docs.Extractor/Plugin/XmlDocumentationHelper.cs index 1ae0044..9aefe99 100644 --- a/src/EAVFW.Extensions.Docs.Extracter/Plugin/XmlDocumentationHelper.cs +++ b/src/EAVFW.Extensions.Docs.Extractor/Plugin/XmlDocumentationHelper.cs @@ -4,7 +4,7 @@ using System.Reflection; using System.Xml; -namespace EAVFW.Extensions.Docs.Extracter +namespace EAVFW.Extensions.Docs.Extractor { public static class XmlDocumentationHelper { diff --git a/src/EAVFW.Extensions.Docs.Extracter/Plugin/XmlMemberElement.cs b/src/EAVFW.Extensions.Docs.Extractor/Plugin/XmlMemberElement.cs similarity index 85% rename from src/EAVFW.Extensions.Docs.Extracter/Plugin/XmlMemberElement.cs rename to src/EAVFW.Extensions.Docs.Extractor/Plugin/XmlMemberElement.cs index ce53ecf..03eba34 100644 --- a/src/EAVFW.Extensions.Docs.Extracter/Plugin/XmlMemberElement.cs +++ b/src/EAVFW.Extensions.Docs.Extractor/Plugin/XmlMemberElement.cs @@ -1,6 +1,6 @@ using System.Xml.Serialization; -namespace EAVFW.Extensions.Docs.Extracter +namespace EAVFW.Extensions.Docs.Extractor { [XmlRoot("member")] public class XmlMemberElement diff --git a/src/EAVFW.Extensions.Docs.Extracter/ServiceCollectionExtension.cs b/src/EAVFW.Extensions.Docs.Extractor/ServiceCollectionExtension.cs similarity index 89% rename from src/EAVFW.Extensions.Docs.Extracter/ServiceCollectionExtension.cs rename to src/EAVFW.Extensions.Docs.Extractor/ServiceCollectionExtension.cs index 9701d2c..f690cc4 100644 --- a/src/EAVFW.Extensions.Docs.Extracter/ServiceCollectionExtension.cs +++ b/src/EAVFW.Extensions.Docs.Extractor/ServiceCollectionExtension.cs @@ -1,6 +1,6 @@ using Microsoft.Extensions.DependencyInjection; -namespace EAVFW.Extensions.Docs.Extracter +namespace EAVFW.Extensions.Docs.Extractor { public static class ServiceCollectionExtension { diff --git a/src/EAVFW.Extensions.Docs.Generator/EAVFW.Extensions.Docs.Generator.csproj b/src/EAVFW.Extensions.Docs.Generator/EAVFW.Extensions.Docs.Generator.csproj index f4f75e8..07bae44 100644 --- a/src/EAVFW.Extensions.Docs.Generator/EAVFW.Extensions.Docs.Generator.csproj +++ b/src/EAVFW.Extensions.Docs.Generator/EAVFW.Extensions.Docs.Generator.csproj @@ -6,7 +6,7 @@ - + diff --git a/src/EAVFW.Extensions.Docs.Generator/IDocumentationGenerator.cs b/src/EAVFW.Extensions.Docs.Generator/IDocumentationGenerator.cs new file mode 100644 index 0000000..b3daecd --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Generator/IDocumentationGenerator.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using EAVFW.Extensions.Docs.Extractor; +using EAVFW.Extensions.Manifest.SDK; + +namespace EAVFW.Extensions.Docs.Generator +{ + public interface IDocumentationGenerator + { + public void AddPluginSource(IEnumerable pluginDocumentations); + public void AddWizardSource(Dictionary entitiesWithWizards); + public void AddGeneratedManifest(ManifestDefinition generatedManifest); + public Task Write(FileInfo outputLocation, string component); + } +} diff --git a/src/EAVFW.Extensions.Docs.Generator/PluginDocumentationToReadMe.cs b/src/EAVFW.Extensions.Docs.Generator/PluginDocumentationToReadMe.cs deleted file mode 100644 index c524be7..0000000 --- a/src/EAVFW.Extensions.Docs.Generator/PluginDocumentationToReadMe.cs +++ /dev/null @@ -1,125 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using EAVFW.Extensions.Docs.Extracter; -using EAVFW.Extensions.Manifest.SDK; -using JsonSerializer = System.Text.Json.JsonSerializer; - -namespace EAVFW.Extensions.Docs.Generator -{ - public class PluginDocumentationToReadMe : IDisposable - { - private readonly StreamWriter _writer; - private readonly Dictionary _logicalNameLookup = new(); - private readonly TransformXmlTag _transformXmlTag; - - public PluginDocumentationToReadMe( - string path = "/Users/thyge/Documents/Obsidian Vault/Delegate Lava-Stone/Delegate/documentation.md") - { - _transformXmlTag = new TransformXmlTag(); - _writer = new StreamWriter(path); - } - - public async Task WriteTables(FileInfo manifest, string component) - { - var manifestObject = await JsonSerializer.DeserializeAsync(manifest.OpenRead()); - - await _writer.WriteLineAsync("## Tables:\n"); - - var t = new DefaultSchemaNameManager(); - - Debug.Assert(manifestObject != null, nameof(manifestObject) + " != null"); - foreach (var (key, value) in manifestObject.Entities) - { - _logicalNameLookup[t.ToSchemaName(key)] = key; - - await _writer.WriteLineAsync($"### {key}"); - await _writer.WriteLineAsync($"Logical name: `{t.ToSchemaName(key)}`"); - await _writer.WriteLineAsync($"Plural name: {value.PluralName}"); - await _writer.WriteLineAsync($"Description: {value.Description}"); - await _writer.WriteLineAsync("Attributes:"); - } - } - - public async Task WritePlugins(IEnumerable pluginDocumentations, string component) - { - var groups = pluginDocumentations.GroupBy(x => x.Entity!.Name); - await _writer.WriteLineAsync("## Plugins "); - foreach (var group in groups) - { - await _writer.WriteLineAsync($"### {group.FirstOrDefault()?.Entity?.Name}"); - foreach (var pluginDocumentation in group) - { - await _writer.WriteLineAsync($"#### {pluginDocumentation.Name}"); - await _writer.WriteLineAsync( - $"Entity:\t[{pluginDocumentation.Entity?.Name}](#{pluginDocumentation.Entity?.Name})"); - await _writer.WriteLineAsync( - $"Context:\t[{pluginDocumentation.Entity?.Name}](#{pluginDocumentation.Entity?.Name})"); - await _writer.WriteLineAsync("Triggers:\n"); - await _writer.WriteLineAsync("| Operation | Execution | Mode | Order |"); - await _writer.WriteLineAsync("|---|---|---|:-:|"); - foreach (var reg in pluginDocumentation.PluginRegistrations.OrderBy(x => x.Order)) - { - await _writer.WriteLineAsync($"|{reg.Operation}|{reg.Execution}|{reg.Mode}|{reg.Order}|"); - } - - await _writer.WriteLineAsync("\n**Summary:**"); - - await _writer.WriteLineAsync(SanitizeSummary(pluginDocumentation.Summary)); - - await _writer.WriteLineAsync(); - } - } - } - - public async Task WriteWizards() - { - - } - - - private string SanitizeSummary(string summary) - { - if (string.IsNullOrWhiteSpace(summary)) return summary; - - var lines = summary.Split("\n").Select(x => x); - - lines = lines.Where(x => !string.IsNullOrWhiteSpace(x)); - lines = lines.Select(x => x.Trim()); - lines = lines.Select(x => _transformXmlTag.TransformString(x, TransformTag)); - - return string.Join(" ", lines); - } - - /// - /// Function i expression motoren - /// - /// - /// - /// - private string TransformTag(string tag, Dictionary properties) - { - if (tag != "see") - return tag; - - var target = properties["cref"]; - - var key = target.Split(':').Last().Split('.').Last(); - - _logicalNameLookup.TryGetValue(key, out var value); - - return $"[{value ?? key}](#{key})"; - } - - - public async void Dispose() - { - await _writer.FlushAsync(); - await _writer.DisposeAsync(); - GC.SuppressFinalize(this); - } - } -} diff --git a/src/EAVFW.Extensions.Docs.Generator/ReadMeDocumentationGenerator.cs b/src/EAVFW.Extensions.Docs.Generator/ReadMeDocumentationGenerator.cs new file mode 100644 index 0000000..7a92899 --- /dev/null +++ b/src/EAVFW.Extensions.Docs.Generator/ReadMeDocumentationGenerator.cs @@ -0,0 +1,155 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using EAVFW.Extensions.Docs.Extractor; +using EAVFW.Extensions.Manifest.SDK; + +namespace EAVFW.Extensions.Docs.Generator +{ + public class ReadMeDocumentationGenerator : IDocumentationGenerator + { + private readonly TransformXmlTag _transformXmlTag = new(); + private readonly Dictionary _logicalNameLookup = new(); + private Dictionary _wizards; + private IEnumerable _pluginDocumentations; + private ManifestDefinition _manifestObject; + + + public void AddPluginSource(IEnumerable pluginDocumentations) + { + _pluginDocumentations = pluginDocumentations; + } + + + public void AddWizardSource(Dictionary entitiesWithWizards) + { + _wizards = entitiesWithWizards; + } + + public void AddGeneratedManifest(ManifestDefinition generatedManifest) + { + _manifestObject = generatedManifest; + } + + public async Task Write(FileInfo outputLocation, string component) + { + var writer = new StreamWriter(outputLocation.FullName); + + await WriteTables(writer, component); + await WriteWizards(writer); + await WritePlugins(writer); + + await writer.FlushAsync(); + } + + + private async Task WriteTables(TextWriter writer, string component) + { + await writer.WriteLineAsync("## Tables:\n"); + + var t = new DefaultSchemaNameManager(); + + var entitiesToWrite = _manifestObject.Entities; + + if (!string.IsNullOrWhiteSpace(component)) + { + entitiesToWrite = entitiesToWrite.Where(entity => + entity.Value.AdditionalFields.ContainsKey("moduleSource") && + entity.Value.AdditionalFields["moduleSource"].ToString() == component) + .ToDictionary(x => x.Key, x => x.Value); + } + + foreach (var (key, value) in entitiesToWrite) + { + _logicalNameLookup[t.ToSchemaName(key)] = key; + + await writer.WriteLineAsync($"### {key}"); + await writer.WriteLineAsync($"Logical name: `{t.ToSchemaName(key)}`"); + await writer.WriteLineAsync($"Plural name: {value.PluralName}"); + await writer.WriteLineAsync($"Description: {value.Description}"); + await writer.WriteLineAsync("Attributes:"); + } + } + + private async Task WritePlugins(TextWriter writer) + { + var groups = _pluginDocumentations.GroupBy(x => x.Entity!.Name); + await writer.WriteLineAsync("## Plugins: "); + foreach (var group in groups) + { + await writer.WriteLineAsync($"### {group.FirstOrDefault()?.Entity?.Name}"); + foreach (var pluginDocumentation in group) + { + await writer.WriteLineAsync($"#### {pluginDocumentation.Name}"); + await writer.WriteLineAsync( + $"Entity:\t[{pluginDocumentation.Entity?.Name}](#{pluginDocumentation.Entity?.Name})"); + await writer.WriteLineAsync( + $"Context:\t[{pluginDocumentation.Entity?.Name}](#{pluginDocumentation.Entity?.Name})"); + await writer.WriteLineAsync("Triggers:\n"); + await writer.WriteLineAsync("| Operation | Execution | Mode | Order |"); + await writer.WriteLineAsync("|---|---|---|:-:|"); + foreach (var reg in pluginDocumentation.PluginRegistrations.OrderBy(x => x.Order)) + { + await writer.WriteLineAsync($"|{reg.Operation}|{reg.Execution}|{reg.Mode}|{reg.Order}|"); + } + + await writer.WriteLineAsync("\n**Summary:**"); + + await writer.WriteLineAsync(SanitizeSummary(pluginDocumentation.Summary)); + + await writer.WriteLineAsync(); + } + } + } + + private async Task WriteWizards(TextWriter writer) + { + await writer.WriteLineAsync("## Wizards:"); + + foreach (var (key, value) in _wizards.Where(x => x.Value.Wizards.Count > 0)) + { + await writer.WriteLineAsync($"### {key}"); + + foreach (var (wizardKey, wizardDefinition) in value.Wizards) + { + await writer.WriteLineAsync($"#### {wizardKey}"); + } + } + } + + + private string SanitizeSummary(string summary) + { + if (string.IsNullOrWhiteSpace(summary)) return summary; + + var lines = summary.Split("\n").Select(x => x); + + lines = lines.Where(x => !string.IsNullOrWhiteSpace(x)); + lines = lines.Select(x => x.Trim()); + lines = lines.Select(x => _transformXmlTag.TransformString(x, TransformTag)); + + return string.Join(" ", lines); + } + + /// + /// Function i expression motoren + /// + /// + /// + /// + private string TransformTag(string tag, Dictionary properties) + { + if (tag != "see") + return tag; + + var target = properties["cref"]; + + var key = target.Split(':').Last().Split('.').Last(); + + _logicalNameLookup.TryGetValue(key, out var value); + + return $"[{value ?? key}](#{key})"; + } + } +} diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/Documentation/DocumentationGeneratorCommand.cs b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/Documentation/DocumentationGeneratorCommand.cs new file mode 100644 index 0000000..f1cc919 --- /dev/null +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/Documentation/DocumentationGeneratorCommand.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Parsing; +using System.ComponentModel; +using System.IO; +using System.Text.Json; +using System.Threading.Tasks; +using EAVFW.Extensions.Docs.Extractor; +using EAVFW.Extensions.Docs.Generator; +using EAVFW.Extensions.Manifest.SDK; + +namespace EAVFW.Extensions.Manifest.ManifestEnricherTool.Commands.Documentation +{ + public class DocumentationGeneratorCommand : Command + { + [Alias("-gm")] + [Description("Path to the generate manifest")] + public FileInfo GeneratedManifestPath { get; set; } + + [Alias("-p")] + [Description("Path to plugin source")] + public FileInfo PluginSourcePath { get; set; } + + [Alias("-w")] + [Description("Path to wizard source directory")] + public DirectoryInfo WizardSourcePath { get; set; } + + [Alias("-c")] + [Description("Component")] + public string Component { get; set; } + + [Alias("-o")] [Description("Output")] public FileInfo Output { get; set; } + + public DocumentationGeneratorCommand() : base("generate", "Generate") + { + Handler = COmmandExtensions.Create(this, Array.Empty(), Run); + } + + private async Task Run(ParseResult parseResult, IConsole console) + { + if (IsFilesAndFoldersMissing(out var missing)) + { + console.WriteLine($"The following file(s)/folder(s) are missing: {string.Join(", ", missing)}"); + return 1; + } + + var documentationGenerator = new ReadMeDocumentationGenerator(); + + await using var pluginStream = PluginSourcePath.OpenRead(); + documentationGenerator.AddPluginSource( + await JsonSerializer.DeserializeAsync>(pluginStream)); + + + var wizards = new Dictionary(); + var files = Directory.GetFiles(WizardSourcePath.FullName, "*.json"); + foreach (var file in files) + { + var fileInfo = new FileInfo(file); + await using var openStream = fileInfo.OpenRead(); + var w = await JsonSerializer.DeserializeAsync(openStream); + wizards[Path.GetFileNameWithoutExtension(fileInfo.Name)] = w; + } + + documentationGenerator.AddWizardSource(wizards); + + await using var manifestStream = GeneratedManifestPath.OpenRead(); + documentationGenerator.AddGeneratedManifest( + await JsonSerializer.DeserializeAsync(manifestStream)); + + await documentationGenerator.Write(Output, Component); + + return 0; + } + + private bool IsFilesAndFoldersMissing(out List missing) + { + missing = new List(); + + if (!GeneratedManifestPath.Exists) + missing.Add(GeneratedManifestPath.Name); + + if (!PluginSourcePath.Exists) + missing.Add(PluginSourcePath.Name); + + if (!WizardSourcePath.Exists) + missing.Add(WizardSourcePath.Name); + + return missing.Count > 0; + } + } +} diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/Documentation/DocumentationSourceCommand.cs b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/Documentation/DocumentationSourceCommand.cs new file mode 100644 index 0000000..a24158f --- /dev/null +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/Documentation/DocumentationSourceCommand.cs @@ -0,0 +1,24 @@ +using System; +using System.CommandLine; +using System.CommandLine.Parsing; +using System.Threading.Tasks; +using EAVFW.Extensions.Docs.Extractor; + +namespace EAVFW.Extensions.Manifest.ManifestEnricherTool.Commands.Documentation +{ + public class DocumentationSourceCommand : Command + { + public DocumentationSourceCommand(IDocumentLogic documentLogic) : base("docs", "Work with documentation") + { + Handler = COmmandExtensions.Create(this, Array.Empty(), Run); + + AddCommand(new DocumentationSourceExtractorCommand(documentLogic)); + AddCommand(new DocumentationGeneratorCommand()); + } + + private Task Run(ParseResult parseResult, IConsole console) + { + return Task.FromResult(0); + } + } +} diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/Documentation/DocumentationSourceExtractorCommand.cs similarity index 75% rename from src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs rename to src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/Documentation/DocumentationSourceExtractorCommand.cs index e966be2..5d01223 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/DocumentCommand.cs +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/Documentation/DocumentationSourceExtractorCommand.cs @@ -7,14 +7,19 @@ using System.Linq; using System.Text.Json; using System.Threading.Tasks; -using EAVFW.Extensions.Docs.Extracter; -using EAVFW.Extensions.Docs.Generator; +using EAVFW.Extensions.Docs.Extractor; -namespace EAVFW.Extensions.Manifest.ManifestEnricherTool.Commands +namespace EAVFW.Extensions.Manifest.ManifestEnricherTool.Commands.Documentation { - public class DocumentCommand : Command + /* + * There are many parameters to the command and generating source for both plugin and wizard requires the tool to be + * executed twice. Alternatively, the "configuration" could be done using a configuration, which would provide all + * necessary parameters. Both it would be more rigid and could not easily be changed in a pipeline or other. + */ + + public class DocumentationSourceExtractorCommand : Command { - private readonly IDocumentLogic documentLogic; + private readonly IDocumentLogic _documentLogic; [Alias("-a")] [Alias("--assembly")] @@ -29,15 +34,15 @@ public class DocumentCommand : Command [Alias("-p")] [Alias("--probing-path")] [Description("Path to probe for dependent assemblies")] - public DirectoryInfo RootPathOption { get; set; } + public DirectoryInfo ProbePathOption { get; set; } [Alias("-c")] [Alias("--configuration")] [Description("Configuration for the built assembly")] public string ConfigurationOption { get; set; } - + [Alias("--component")] - [Description("Component to generate documentation. E.g., `mainfest.component.json`")] + [Description("Component to generate documentation. E.g., `manifest.component.json`")] public string ComponentOption { get; set; } [Alias("-f")] @@ -61,9 +66,9 @@ public enum Targets Wizards } - public DocumentCommand(IDocumentLogic documentLogic) : base("docs", "Generate documentation") + public DocumentationSourceExtractorCommand(IDocumentLogic documentLogic) : base("extract", "Extract documentation source") { - this.documentLogic = documentLogic ?? throw new ArgumentNullException(nameof(documentLogic)); + _documentLogic = documentLogic ?? throw new ArgumentNullException(nameof(documentLogic)); Handler = COmmandExtensions.Create(this, Array.Empty(), Run); } @@ -75,7 +80,7 @@ private async Task Run(ParseResult parseResult, IConsole console) return 126; } - if (!RootPathOption.Exists) + if (!ProbePathOption.Exists) { Console.WriteLine("Probing path does not exists"); return 1; @@ -90,15 +95,15 @@ private async Task Run(ParseResult parseResult, IConsole console) switch (Target) { case Targets.Plugins: - return await HandlePlugins(); + return await GeneratePluginSource(); case Targets.Wizards: - return await HandleWizards(); + return await GenerateWizardSource(); default: throw new ArgumentOutOfRangeException(); } } - private async Task HandleWizards() + private async Task GenerateWizardSource() { if (!ManifestPathOption?.Exists ?? true) { @@ -106,9 +111,9 @@ private async Task HandleWizards() return 1; } - var entityDefinitions = documentLogic.ExtractWizardDocumentation( + var entityDefinitions = _documentLogic.ExtractWizardDocumentation( ManifestPathOption, - new PluginInfo(RootPathOption, + new PluginInfo(ProbePathOption, AssemblyPathOption, ConfigurationOption, FrameworkOption)); @@ -133,16 +138,15 @@ private async Task HandleWizards() return 0; } - private async Task HandlePlugins() + private async Task GeneratePluginSource() { - var plugins = documentLogic - .ExtractPluginDocumentation(new PluginInfo(RootPathOption, AssemblyPathOption, ConfigurationOption, + var plugins = _documentLogic + .ExtractPluginDocumentation(new PluginInfo(ProbePathOption, AssemblyPathOption, ConfigurationOption, FrameworkOption)) .ToArray(); - + var jsonString = JsonSerializer.Serialize(plugins, new JsonSerializerOptions { - Converters = { new PluginRegistrationAttributeConverter() }, WriteIndented = true }); @@ -169,8 +173,8 @@ private bool IsMissingOptions(out List missing) if (AssemblyPathOption == null) missing.Add(nameof(AssemblyPathOption)); - if (RootPathOption == null) - missing.Add(nameof(RootPathOption)); + if (ProbePathOption == null) + missing.Add(nameof(ProbePathOption)); if (string.IsNullOrWhiteSpace(ConfigurationOption)) missing.Add(nameof(ConfigurationOption)); diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj index 445e2a4..bd60682 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj @@ -55,7 +55,7 @@ - + diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Program.cs b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Program.cs index 9535825..0b0153f 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Program.cs +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Program.cs @@ -1,6 +1,4 @@  - - // See https://aka.ms/new-console-template for more information using EAVFW.Extensions.Manifest.ManifestEnricherTool.Commands; using EAVFW.Extensions.Manifest.ManifestEnricherTool.Commands.GPT; @@ -9,7 +7,8 @@ using Microsoft.Extensions.Logging; using System.CommandLine; using System.Threading.Tasks; -using EAVFW.Extensions.Docs.Extracter; +using EAVFW.Extensions.Docs.Extractor; +using EAVFW.Extensions.Manifest.ManifestEnricherTool.Commands.Documentation; using EAVFW.Extensions.Manifest.ManifestEnricherTool.Commands.Gzip; namespace EAVFW.Extensions.Manifest.ManifestEnricherTool @@ -36,7 +35,7 @@ static IServiceCollection ConfigureServices(IServiceCollection serviceCollection serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); serviceCollection.AddGPT(); serviceCollection.AddTransient(); diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json index fcf09a0..48460f1 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json @@ -4,8 +4,9 @@ "commandName": "Project", "workingDirectory": "/Users/thyge/dev/playground", // "workingDirectory": "/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models", - "commandLineArgs": "docs -c Release -t wizards -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\" -m \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/manifest.loi.json\"" -// "commandLineArgs": "docs -c Release -t plugins -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\" -m \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/manifest.loi.json\"" +// "commandLineArgs": "docs extract -c Release -t wizards -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\" -m \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/manifest.loi.json\"" +// "commandLineArgs": "docs extract -c Release -t plugins -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\" -m \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/manifest.loi.json\"" + "commandLineArgs": "docs generate -c manifest.loi.json -p /Users/thyge/dev/playground/plugins.json -w /Users/thyge/dev/playground/wizards -o \"/Users/thyge/Documents/Obsidian Vault/Delegate Lava-Stone/Delegate/documentation.md\" -gm /Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/obj/manifest.g.json" // "commandLineArgs": "binary --unzip 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" // "commandLineArgs": "binary --unzip 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" // "commandLineArgs": "binary --unzip --pretty-print 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" From 7e58cf83b1eb22b080f0866fbcc71222fd004675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thyge=20Sk=C3=B8dt=20Steffensen?= <31892312+thygesteffensen@users.noreply.github.com> Date: Thu, 23 Nov 2023 18:10:11 +0100 Subject: [PATCH 07/10] feat: Finishing version of documentation generator --- .../ReadMeDocumentationGenerator.cs | 261 +++++++++++++++--- .../Commands/Documentation/README.md | 25 ++ 2 files changed, 245 insertions(+), 41 deletions(-) create mode 100644 src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/Documentation/README.md diff --git a/src/EAVFW.Extensions.Docs.Generator/ReadMeDocumentationGenerator.cs b/src/EAVFW.Extensions.Docs.Generator/ReadMeDocumentationGenerator.cs index 7a92899..bae36e2 100644 --- a/src/EAVFW.Extensions.Docs.Generator/ReadMeDocumentationGenerator.cs +++ b/src/EAVFW.Extensions.Docs.Generator/ReadMeDocumentationGenerator.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text; using System.Threading.Tasks; using EAVFW.Extensions.Docs.Extractor; using EAVFW.Extensions.Manifest.SDK; @@ -15,6 +16,8 @@ public class ReadMeDocumentationGenerator : IDocumentationGenerator private IEnumerable _pluginDocumentations; private ManifestDefinition _manifestObject; + private ISchemaNameManager _schemaNameManager = new DefaultSchemaNameManager(); + public void AddPluginSource(IEnumerable pluginDocumentations) { @@ -32,23 +35,59 @@ public void AddGeneratedManifest(ManifestDefinition generatedManifest) _manifestObject = generatedManifest; } - public async Task Write(FileInfo outputLocation, string component) + private string BuildAttributeDescription(AttributeObjectDefinition attribute, string key) { - var writer = new StreamWriter(outputLocation.FullName); + var s = ""; + var _component = "manifest.loi.json"; + if (attribute.AttributeType.Type == "lookup") + { + var lookup = attribute.AttributeType.ReferenceType; + _manifestObject.Entities.FirstOrDefault(x => x.Key == lookup).Value.AdditionalFields + .TryGetValue("moduleSource", out var source); - await WriteTables(writer, component); - await WriteWizards(writer); - await WritePlugins(writer); + if (source.ToString() == _component) + { + s += + $"Lookup: [{attribute.AttributeType.ReferenceType}](#{_schemaNameManager.ToSchemaName(attribute.AttributeType.ReferenceType)})
"; + } + else + { + s += $"Lookup: {attribute.AttributeType.ReferenceType} ({source})
"; + } + } - await writer.FlushAsync(); - } + if (attribute.AttributeType.Type == "Choice") + { + var defaultOption = attribute.AdditionalFields.TryGetValue("default", out var _default); + var defaultValue = 0; + if (defaultOption) + { + // defaultValue = _default.GetInt32(); + } + + + s += "Options:
"; + foreach (var (key1, value) in attribute.AttributeType.Options) + { + s += $"- {value}: {key1}"; + + if (defaultOption && value.GetInt32() == defaultValue) + { + s += " (default)"; + } + + s += "
"; + } + } + return s + $"_Display name:_ {key}"; + } - private async Task WriteTables(TextWriter writer, string component) + public async Task Write(FileInfo outputLocation, string component) { - await writer.WriteLineAsync("## Tables:\n"); + var writer = new StreamWriter(outputLocation.FullName); - var t = new DefaultSchemaNameManager(); + await writer.WriteLineAsync($"# Documentation for {component}"); var entitiesToWrite = _manifestObject.Entities; @@ -60,64 +99,145 @@ private async Task WriteTables(TextWriter writer, string component) .ToDictionary(x => x.Key, x => x.Value); } + await writer.WriteLineAsync("## Table of contents"); + + var index = 2; + await writer.WriteLineAsync("1. [Class diagram](#class-diagram)"); + foreach (var (key, value) in entitiesToWrite) + { + await writer.WriteLineAsync($"{index++}. [{key}](#{_schemaNameManager.ToSchemaName(key)})"); + } + + await writer.WriteLineAsync("# Class diagram "); + await writer.WriteAsync(EntitiesToClassDiagram(_manifestObject, component)); + + var ignored = new List + { "Modified On", "Modified By", "Created By", "Created On", "Row Version", "Owner" }; + foreach (var (key, value) in entitiesToWrite) { - _logicalNameLookup[t.ToSchemaName(key)] = key; + await writer.WriteLineAsync($"## {key} "); + + await writer.WriteLineAsync(value.Description); + + await WriteAttributes(writer, value, ignored); + + await WritePlugins(writer, key); - await writer.WriteLineAsync($"### {key}"); - await writer.WriteLineAsync($"Logical name: `{t.ToSchemaName(key)}`"); - await writer.WriteLineAsync($"Plural name: {value.PluralName}"); - await writer.WriteLineAsync($"Description: {value.Description}"); - await writer.WriteLineAsync("Attributes:"); + + await WriteWizards(writer, key); } + + await writer.FlushAsync(); } - private async Task WritePlugins(TextWriter writer) + private async Task WriteWizards(StreamWriter writer, string key) { - var groups = _pluginDocumentations.GroupBy(x => x.Entity!.Name); - await writer.WriteLineAsync("## Plugins: "); - foreach (var group in groups) + await writer.WriteLineAsync("### Wizards"); + + if (_wizards.TryGetValue(key, out var wizard)) { - await writer.WriteLineAsync($"### {group.FirstOrDefault()?.Entity?.Name}"); - foreach (var pluginDocumentation in group) + foreach (var (s, wizardDefinition) in wizard.Wizards) { - await writer.WriteLineAsync($"#### {pluginDocumentation.Name}"); - await writer.WriteLineAsync( - $"Entity:\t[{pluginDocumentation.Entity?.Name}](#{pluginDocumentation.Entity?.Name})"); - await writer.WriteLineAsync( - $"Context:\t[{pluginDocumentation.Entity?.Name}](#{pluginDocumentation.Entity?.Name})"); - await writer.WriteLineAsync("Triggers:\n"); - await writer.WriteLineAsync("| Operation | Execution | Mode | Order |"); - await writer.WriteLineAsync("|---|---|---|:-:|"); - foreach (var reg in pluginDocumentation.PluginRegistrations.OrderBy(x => x.Order)) + await writer.WriteLineAsync($"#### {wizardDefinition.Title}"); + + await writer.WriteLineAsync("\nTriggers:\n"); + await writer.WriteLineAsync("| Type | Value |"); + await writer.WriteLineAsync("|------|-------|"); + + foreach (var (k, triggerDefinition) in wizardDefinition.Triggers) { - await writer.WriteLineAsync($"|{reg.Operation}|{reg.Execution}|{reg.Mode}|{reg.Order}|"); + if (string.IsNullOrWhiteSpace(triggerDefinition.Form)) + await writer.WriteLineAsync($"| Ribbon | {triggerDefinition.Ribbon} |"); + else + await writer.WriteLineAsync($"| Form | {triggerDefinition.Form} |"); } - await writer.WriteLineAsync("\n**Summary:**"); + await writer.WriteLineAsync("\nTabs:\n"); + await writer.WriteLineAsync("| Tab | Visible | OnTransitionIn | OnTransitionOut |"); + await writer.WriteLineAsync("| -- | -- | -- | -- |"); + + foreach (var (key1, tabDefinition) in wizardDefinition.Tabs) + { + await writer.WriteLineAsync( + $"| {key1} | {GetVisibleString(tabDefinition.Visible.ToString())} | {GetTransitionString(tabDefinition.OnTransitionIn)} | {GetTransitionString(tabDefinition.OnTransitionOut)} |"); + } + } + } + else + { + await writer.WriteLineAsync("_No wizards_"); + } + } - await writer.WriteLineAsync(SanitizeSummary(pluginDocumentation.Summary)); + private string GetVisibleString(string visible) + { + return string.IsNullOrWhiteSpace(visible) ? "" : $"`{visible}`"; + } - await writer.WriteLineAsync(); + private string GetTransitionString(TransitionDefinition transitionDefinition) + { + if (!string.IsNullOrWhiteSpace(transitionDefinition?.Workflow)) + { + var summaryString = ""; + if (transitionDefinition.AdditionalData.TryGetValue("x-workflowSummary", out var summary) && + summary != null) + { + summaryString = $"
Summary: {SanitizeSummary(summary.ToString())}"; } + + return $"{transitionDefinition.Workflow} {summaryString}"; } + + return ""; } - private async Task WriteWizards(TextWriter writer) + private async Task WritePlugins(StreamWriter writer, string key) { - await writer.WriteLineAsync("## Wizards:"); + await writer.WriteLineAsync("### Plugins"); - foreach (var (key, value) in _wizards.Where(x => x.Value.Wizards.Count > 0)) + var plugins = _pluginDocumentations.Where(x => x.Entity.Name == _schemaNameManager.ToSchemaName(key)) + .ToList(); + if (!plugins.Any()) await writer.WriteLineAsync("_No plugins_"); + foreach (var pluginDocumentation in plugins) { - await writer.WriteLineAsync($"### {key}"); + await writer.WriteLineAsync($"#### {pluginDocumentation.Name}"); + + await writer.WriteLineAsync(SanitizeSummary(pluginDocumentation.Summary)); + + await writer.WriteLineAsync(); - foreach (var (wizardKey, wizardDefinition) in value.Wizards) + await writer.WriteLineAsync( + $"Entity:\t[{pluginDocumentation.Entity?.Name}](#{pluginDocumentation.Entity?.Name})"); + await writer.WriteLineAsync( + $"Context:\t[{pluginDocumentation.Entity?.Name}](#{pluginDocumentation.Entity?.Name})"); + + await writer.WriteLineAsync(); + await writer.WriteLineAsync("| Operation | Execution | Mode | Order |"); + await writer.WriteLineAsync("|---|---|---|:-:|"); + foreach (var reg in pluginDocumentation.PluginRegistrations.OrderBy(x => x.Order)) { - await writer.WriteLineAsync($"#### {wizardKey}"); + await writer.WriteLineAsync($"|{reg.Operation}|{reg.Execution}|{reg.Mode}|{reg.Order}|"); } } } + private async Task WriteAttributes(StreamWriter writer, EntityDefinition value, List ignored) + { + await writer.WriteLineAsync("### Attributes"); + + await writer.WriteLineAsync("| Name | Type | Details |"); + await writer.WriteLineAsync("|------|------|---------|"); + + foreach (var (s, attributeBase) in value.Attributes.Where(x => !ignored.Contains(x.Key))) + { + if (attributeBase is AttributeObjectDefinition attributeDefinition) + { + await writer.WriteLineAsync( + $"| {_schemaNameManager.ToSchemaName(s)} | {attributeDefinition.AttributeType.Type} | {BuildAttributeDescription(attributeDefinition, s)} |"); + } + } + } private string SanitizeSummary(string summary) { @@ -151,5 +271,64 @@ private string TransformTag(string tag, Dictionary properties) return $"[{value ?? key}](#{key})"; } + + private string EntitiesToClassDiagram(ManifestDefinition manifest, string component) + { + var diagramBuilder = new StringBuilder(); + + diagramBuilder.AppendLine("```mermaid"); + diagramBuilder.AppendLine("classDiagram"); + diagramBuilder.AppendLine($"\tnote \"Class diagram for {component}\""); + + var t = new DefaultSchemaNameManager(); + + var entities = manifest.Entities.Where(entity => + entity.Value.AdditionalFields.ContainsKey("moduleSource") && + entity.Value.AdditionalFields["moduleSource"].ToString() == component); + + var ignored = new List + { "Modified On", "Modified By", "Created By", "Created On", "Row Version", "Owner" }; + + foreach (var (key, value) in entities) + { + var attributes = value.Attributes.Where(x => !ignored.Contains(x.Key)).ToList(); + + diagramBuilder.AppendLine($"\tclass {t.ToSchemaName(key)}[\"{key}\"]{{"); + foreach (var (s, attributeDefinitionBase) in attributes) + { + if (attributeDefinitionBase is AttributeObjectDefinition o) + { + // Argmunt + if (o.AttributeType.Type == "lookup") + { + diagramBuilder.AppendLine($"\t\t+{t.ToSchemaName(o.AttributeType.ReferenceType)} {s}"); + } + else + { + diagramBuilder.AppendLine($"\t\t+{o.AttributeType.Type} {s}"); + } + } + } + + diagramBuilder.AppendLine("\t}"); + + var relations = new HashSet(); + foreach (var (_, attributeDefinitionBase) in attributes) + { + if (attributeDefinitionBase is AttributeObjectDefinition o && o.AttributeType.Type == "lookup") + { + relations.Add($"\t{o.AttributeType.ReferenceType} <-- {key}"); + } + } + + foreach (var relation in relations) + { + diagramBuilder.AppendLine(relation); + } + } + + diagramBuilder.AppendLine("```"); + return diagramBuilder.ToString(); + } } } diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/Documentation/README.md b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/Documentation/README.md new file mode 100644 index 0000000..91c1f45 --- /dev/null +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/Documentation/README.md @@ -0,0 +1,25 @@ +# EAVFW Documentation Generator + +The process of generating documentation for EAVFW is a two step process. + +1. Extract information from metadata and code +2. Generate documentation from sources. + +The process is divided in two steps and seperated by JSON files. The makes it possible to enrich the source files and to create a custom generator without extracting information twice. + +## Extract information + +`eavfw docs extract -h` + +The metadata extract for both plugins and wizards are saved as JSON files. + +Plugins is a single file and `PluginDocumentation` can be used to deserialize the document. +Wizards are saved in a directory `wizards` where each JSON file is a `EntityDefinition` enrich with extracted documentation from Workflow. + +OnTransitionIn, OnTransitionOut and Actions with workflows are enriched with `x-workflowSummary` with the doc-string for the given class. + +## Generate information + +The interface `IDocumentationGenerator` depicts how the source can be loaded and at the end written. `EAVFW.Extensions.Docs.Generator` implement a simple markdown generator, that writes all the content to a single markdown file. + +This is the default invoked in `eavfw docs generate`. From 6149963720afc8d13204c01cb9d296ffb6c1c142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thyge=20Sk=C3=B8dt=20Steffensen?= <31892312+thygesteffensen@users.noreply.github.com> Date: Fri, 24 Nov 2023 15:44:09 +0100 Subject: [PATCH 08/10] fix: Operating on generated manifest --- src/EAVFW.Extensions.Docs.Extractor/DocumentLogic.cs | 2 +- .../Documentation/DocumentationSourceExtractorCommand.cs | 8 ++------ .../Properties/launchSettings.json | 6 +++--- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/EAVFW.Extensions.Docs.Extractor/DocumentLogic.cs b/src/EAVFW.Extensions.Docs.Extractor/DocumentLogic.cs index 3ac7e5e..b189836 100644 --- a/src/EAVFW.Extensions.Docs.Extractor/DocumentLogic.cs +++ b/src/EAVFW.Extensions.Docs.Extractor/DocumentLogic.cs @@ -105,7 +105,7 @@ from wizard in entity.Value.Wizards from _tabs in wizard.Value.Tabs select _tabs).AsEnumerable(); - // Glorified for loop?w + // Glorified for loop? var tabsWithWorkflows = from tab in tabs where tab.Value.OnTransitionOut?.Workflow != null || tab.Value.OnTransitionIn?.Workflow != null diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/Documentation/DocumentationSourceExtractorCommand.cs b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/Documentation/DocumentationSourceExtractorCommand.cs index 5d01223..3f7d10b 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/Documentation/DocumentationSourceExtractorCommand.cs +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Commands/Documentation/DocumentationSourceExtractorCommand.cs @@ -26,8 +26,8 @@ public class DocumentationSourceExtractorCommand : Command [Description("Path for the assembly")] public FileInfo AssemblyPathOption { get; set; } - [Alias("-m")] - [Alias("--manifest")] + [Alias("-gm")] + [Alias("--generated-manifest")] [Description("Path for the enriched manifest")] public FileInfo ManifestPathOption { get; set; } @@ -40,10 +40,6 @@ public class DocumentationSourceExtractorCommand : Command [Alias("--configuration")] [Description("Configuration for the built assembly")] public string ConfigurationOption { get; set; } - - [Alias("--component")] - [Description("Component to generate documentation. E.g., `manifest.component.json`")] - public string ComponentOption { get; set; } [Alias("-f")] [Alias("--framework")] diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json index 48460f1..0cede8f 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json @@ -4,9 +4,9 @@ "commandName": "Project", "workingDirectory": "/Users/thyge/dev/playground", // "workingDirectory": "/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models", -// "commandLineArgs": "docs extract -c Release -t wizards -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\" -m \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/manifest.loi.json\"" -// "commandLineArgs": "docs extract -c Release -t plugins -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\" -m \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/manifest.loi.json\"" - "commandLineArgs": "docs generate -c manifest.loi.json -p /Users/thyge/dev/playground/plugins.json -w /Users/thyge/dev/playground/wizards -o \"/Users/thyge/Documents/Obsidian Vault/Delegate Lava-Stone/Delegate/documentation.md\" -gm /Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/obj/manifest.g.json" + "commandLineArgs": "docs extract -c Release -t wizards -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\" -gm /Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/obj/manifest.g.json" +// "commandLineArgs": "docs extract -c Release -t plugins -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\" -gm /Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/obj/manifest.g.json" +// "commandLineArgs": "docs generate -c manifest.loi.json -p /Users/thyge/dev/playground/plugins.json -w /Users/thyge/dev/playground/wizards -o \"/Users/thyge/Documents/Obsidian Vault/Delegate Lava-Stone/Delegate/documentation.md\" -gm /Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/obj/manifest.g.json" // "commandLineArgs": "binary --unzip 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" // "commandLineArgs": "binary --unzip 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" // "commandLineArgs": "binary --unzip --pretty-print 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" From eb346ad01c154d4ff6617c219d805fbf9e0912bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thyge=20Sk=C3=B8dt=20Steffensen?= <31892312+thygesteffensen@users.noreply.github.com> Date: Fri, 24 Nov 2023 17:25:21 +0100 Subject: [PATCH 09/10] fix: References and NuGet packages --- .../EAVFW.Extensions.Docs.Extractor.csproj | 15 ++++++++------- .../EAVFW.Extensions.Docs.Generator.csproj | 14 +++++++++----- ...xtensions.Manifest.ManifestEnricherTool.csproj | 5 +++-- .../Properties/launchSettings.json | 4 ++-- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/EAVFW.Extensions.Docs.Extractor/EAVFW.Extensions.Docs.Extractor.csproj b/src/EAVFW.Extensions.Docs.Extractor/EAVFW.Extensions.Docs.Extractor.csproj index a3fecf8..a4747ac 100644 --- a/src/EAVFW.Extensions.Docs.Extractor/EAVFW.Extensions.Docs.Extractor.csproj +++ b/src/EAVFW.Extensions.Docs.Extractor/EAVFW.Extensions.Docs.Extractor.csproj @@ -15,13 +15,14 @@
- - - ..\EAVFW.Extensions.Manifest.ManifestEnricherTool\bin\Debug\net8.0\EAVFW.Extensions.Manifest.SDK.dll - - - ..\..\..\..\hafnia\LetterofIndemnity\Hafnia.Tests\bin\Release\net6.0\WorkflowEngine.Core.dll - + + + + + + + + diff --git a/src/EAVFW.Extensions.Docs.Generator/EAVFW.Extensions.Docs.Generator.csproj b/src/EAVFW.Extensions.Docs.Generator/EAVFW.Extensions.Docs.Generator.csproj index 07bae44..3c06e14 100644 --- a/src/EAVFW.Extensions.Docs.Generator/EAVFW.Extensions.Docs.Generator.csproj +++ b/src/EAVFW.Extensions.Docs.Generator/EAVFW.Extensions.Docs.Generator.csproj @@ -6,13 +6,17 @@ - + - - - ..\EAVFW.Extensions.Manifest.ManifestEnricherTool\bin\Debug\net8.0\EAVFW.Extensions.Manifest.SDK.dll - + + + + + + + + diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj index bd60682..5603ed0 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/EAVFW.Extensions.Manifest.ManifestEnricherTool.csproj @@ -48,12 +48,13 @@ - + - + + diff --git a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json index 0cede8f..f04303c 100644 --- a/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json +++ b/src/EAVFW.Extensions.Manifest.ManifestEnricherTool/Properties/launchSettings.json @@ -4,8 +4,8 @@ "commandName": "Project", "workingDirectory": "/Users/thyge/dev/playground", // "workingDirectory": "/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models", - "commandLineArgs": "docs extract -c Release -t wizards -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\" -gm /Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/obj/manifest.g.json" -// "commandLineArgs": "docs extract -c Release -t plugins -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\" -gm /Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/obj/manifest.g.json" +// "commandLineArgs": "docs extract -c Release -t wizards -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\" -gm /Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/obj/manifest.g.json" + "commandLineArgs": "docs extract -c Release -t plugins -f net6.0 -a \"/Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.BusinessLogic/bin/Release/net6.0/Hafnia.BusinessLogic.dll\" -p \"/Users/thyge/dev/hafnia/LetterofIndemnity\" -gm /Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/obj/manifest.g.json" // "commandLineArgs": "docs generate -c manifest.loi.json -p /Users/thyge/dev/playground/plugins.json -w /Users/thyge/dev/playground/wizards -o \"/Users/thyge/Documents/Obsidian Vault/Delegate Lava-Stone/Delegate/documentation.md\" -gm /Users/thyge/dev/hafnia/LetterofIndemnity/src/Hafnia.Models/obj/manifest.g.json" // "commandLineArgs": "binary --unzip 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" // "commandLineArgs": "binary --unzip 0x1F8B08000000000000139C51414EC33010FC8BAFD4C8719C36C9AD824BA50252E90D71D8D8EBC852EA147B73A8A2FE1D3B05CE153E8DAC99D99DD999812637FAC8DA993D0504C2FDDBEE19080EF83561A4178C117ADC2EAC4C72FE3C5106C3E8C28DC35A06CA182937C0D142C795EE2A5EA2042E6AD369B0AAAA9A82AD5840EDCE0E3DA5791FACA884EAACB45CDB3572D5E8861B5B36BFA235405DB3CFEB8A45029A9284BD4F5AA34193ACBAD15CEE1F6CC10D680E0831A7F0D3305C932F05D7F71896F0C71BCE90DC0993B514B2E485E0853C8A4DAB8A56C9C7B2484B370F42B442FC2D31B394C8D1E51516DD1E89308CD67983279FFE7FAA8CB702C66076E6FECD4DBA451EF1AFEAF2FB060000FFFF" From a109a5f4c2698c0c37a255c77e8c3da619a13707 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thyge=20Sk=C3=B8dt=20Steffensen?= <31892312+thygesteffensen@users.noreply.github.com> Date: Fri, 24 Nov 2023 17:25:54 +0100 Subject: [PATCH 10/10] Use nuget --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index bc28d4d..2d08e79 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,7 +2,7 @@ 9.0 4.0.2 - false + true $(MSBuildThisFileDirectory)/external/EAVFramework $(MSBuildThisFileDirectory)/external $(MSBuildThisFileDirectory)