Skip to content

Refactor LibKubernetesGenerator code structure #1546

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 15, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 21 additions & 6 deletions src/LibKubernetesGenerator/ApiGenerator.cs
Original file line number Diff line number Diff line change
@@ -8,6 +8,13 @@ namespace LibKubernetesGenerator
{
internal class ApiGenerator
{
private readonly ScriptObjectFactory scriptObjectFactory;

public ApiGenerator(ScriptObjectFactory scriptObjectFactory)
{
this.scriptObjectFactory = scriptObjectFactory;
}

public void Generate(OpenApiDocument swagger, IncrementalGeneratorPostInitializationContext context)
{
var data = swagger.Operations
@@ -42,6 +49,8 @@ public void Generate(OpenApiDocument swagger, IncrementalGeneratorPostInitializa
})
.ToArray();

var sc = scriptObjectFactory.CreateScriptObject();

var groups = new List<string>();

foreach (var grouped in data.GroupBy(d => d.Operation.Tags.First()))
@@ -50,14 +59,20 @@ public void Generate(OpenApiDocument swagger, IncrementalGeneratorPostInitializa
groups.Add(name);

var apis = grouped.ToArray();
var gctx = new { name, apis };
context.RenderToContext($"IOperations.cs.template", gctx, $"I{name}Operations.g.cs");
context.RenderToContext("Operations.cs.template", gctx, $"{name}Operations.g.cs");
context.RenderToContext("OperationsExtensions.cs.template", gctx, $"{name}OperationsExtensions.g.cs");

sc.SetValue("name", name, true);
sc.SetValue("apis", apis, true);

context.RenderToContext($"IOperations.cs.template", sc, $"I{name}Operations.g.cs");
context.RenderToContext("Operations.cs.template", sc, $"{name}Operations.g.cs");
context.RenderToContext("OperationsExtensions.cs.template", sc, $"{name}OperationsExtensions.g.cs");
}

context.RenderToContext($"IBasicKubernetes.cs.template", groups, $"IBasicKubernetes.g.cs");
context.RenderToContext($"AbstractKubernetes.cs.template", groups, $"AbstractKubernetes.g.cs");
sc = scriptObjectFactory.CreateScriptObject();
sc.SetValue("groups", groups, true);

context.RenderToContext($"IBasicKubernetes.cs.template", sc, $"IBasicKubernetes.g.cs");
context.RenderToContext($"AbstractKubernetes.cs.template", sc, $"AbstractKubernetes.g.cs");
}
}
}
37 changes: 7 additions & 30 deletions src/LibKubernetesGenerator/ClassNameHelper.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
using CaseExtensions;
using NJsonSchema;
using NSwag;
using Nustache.Core;
using Scriban.Runtime;
using System;
using System.Collections.Generic;
using System.Linq;

namespace LibKubernetesGenerator
{
internal class ClassNameHelper : INustacheHelper
internal class ClassNameHelper : IScriptObjectHelper
{
private readonly Dictionary<string, string> classNameMap;
private readonly Dictionary<JsonSchema, string> schemaToNameMapCooked;
@@ -18,9 +19,10 @@ public ClassNameHelper(OpenApiDocument swagger)
schemaToNameMapCooked = GenerateSchemaToNameMapCooked(swagger);
}

public void RegisterHelper()

public void RegisterHelper(ScriptObject scriptObject)
{
Helpers.Register(nameof(GetClassName), GetClassName);
scriptObject.Import(nameof(GetClassName), new Func<JsonSchema, string>(GetClassNameForSchemaDefinition));
}

private static Dictionary<JsonSchema, string> GenerateSchemaToNameMapCooked(OpenApiDocument swagger)
@@ -50,27 +52,7 @@ private Dictionary<string, string> InitClassNameMap(OpenApiDocument doc)
return map;
}

public void GetClassName(RenderContext context, IList<object> arguments, IDictionary<string, object> options,
RenderBlock fn, RenderBlock inverse)
{
if (arguments != null && arguments.Count > 0 && arguments[0] != null && arguments[0] is OpenApiOperation)
{
context.Write(GetClassName(arguments[0] as OpenApiOperation));
}
else if (arguments != null && arguments.Count > 0 && arguments[0] != null && arguments[0] is JsonSchema)
{
context.Write(GetClassNameForSchemaDefinition(arguments[0] as JsonSchema));
}
}

public string GetClassName(OpenApiOperation operation)
{
var groupVersionKind =
(Dictionary<string, object>)operation.ExtensionData["x-kubernetes-group-version-kind"];
return GetClassName(groupVersionKind);
}

public string GetClassName(Dictionary<string, object> groupVersionKind)
private string GetClassName(Dictionary<string, object> groupVersionKind)
{
var group = (string)groupVersionKind["group"];
var kind = (string)groupVersionKind["kind"];
@@ -98,10 +80,5 @@ public string GetClassNameForSchemaDefinition(JsonSchema definition)

return schemaToNameMapCooked[definition];
}

private static Dictionary<JsonSchema, string> InitSchemaToNameCooked(OpenApiDocument swagger)
{
return swagger.Definitions.ToDictionary(x => x.Value, x => x.Key.Replace(".", "").ToPascalCase());
}
}
}
61 changes: 13 additions & 48 deletions src/LibKubernetesGenerator/GeneralNameHelper.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
using CaseExtensions;
using NJsonSchema;
using NSwag;
using Nustache.Core;
using Scriban.Runtime;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace LibKubernetesGenerator
{
internal class GeneralNameHelper : INustacheHelper
internal class GeneralNameHelper : IScriptObjectHelper
{
private readonly ClassNameHelper classNameHelper;

@@ -17,20 +18,12 @@ public GeneralNameHelper(ClassNameHelper classNameHelper)
this.classNameHelper = classNameHelper;
}

public void RegisterHelper()
public void RegisterHelper(ScriptObject scriptObject)
{
Helpers.Register(nameof(GetInterfaceName), GetInterfaceName);
Helpers.Register(nameof(GetMethodName), GetMethodName);
Helpers.Register(nameof(GetDotNetName), GetDotNetName);
}

public void GetInterfaceName(RenderContext context, IList<object> arguments,
IDictionary<string, object> options, RenderBlock fn, RenderBlock inverse)
{
if (arguments != null && arguments.Count > 0 && arguments[0] != null && arguments[0] is JsonSchema)
{
context.Write(GetInterfaceName(arguments[0] as JsonSchema));
}
scriptObject.Import(nameof(GetInterfaceName), new Func<JsonSchema, string>(GetInterfaceName));
scriptObject.Import(nameof(GetMethodName), new Func<OpenApiOperation, string, string>(GetMethodName));
scriptObject.Import(nameof(GetDotNetName), new Func<string, string, string>(GetDotNetName));
scriptObject.Import(nameof(GetDotNetNameOpenApiParameter), new Func<OpenApiParameter, string, string>(GetDotNetNameOpenApiParameter));
}

private string GetInterfaceName(JsonSchema definition)
@@ -68,44 +61,16 @@ private string GetInterfaceName(JsonSchema definition)
return string.Join(", ", interfaces);
}

public void GetMethodName(RenderContext context, IList<object> arguments, IDictionary<string, object> options,
RenderBlock fn, RenderBlock inverse)
public string GetDotNetNameOpenApiParameter(OpenApiParameter parameter, string init)
{
if (arguments != null && arguments.Count > 0 && arguments[0] != null && arguments[0] is OpenApiOperation)
{
string suffix = null;
if (arguments.Count > 1)
{
suffix = arguments[1] as string;
}
var name = GetDotNetName(parameter.Name);

context.Write(GetMethodName(arguments[0] as OpenApiOperation, suffix));
}
}

public void GetDotNetName(RenderContext context, IList<object> arguments, IDictionary<string, object> options,
RenderBlock fn, RenderBlock inverse)
{
if (arguments != null && arguments.Count > 0 && arguments[0] != null && arguments[0] is OpenApiParameter)
if (init == "true" && !parameter.IsRequired)
{
var parameter = arguments[0] as OpenApiParameter;
context.Write(GetDotNetName(parameter.Name));

if (arguments.Count > 1 && (arguments[1] as string) == "true" && !parameter.IsRequired)
{
context.Write(" = null");
}
name += " = null";
}
else if (arguments != null && arguments.Count > 0 && arguments[0] != null && arguments[0] is string)
{
var style = "parameter";
if (arguments.Count > 1)
{
style = arguments[1] as string;
}

context.Write(GetDotNetName((string)arguments[0], style));
}
return name;
}

public string GetDotNetName(string jsonName, string style = "parameter")
16 changes: 12 additions & 4 deletions src/LibKubernetesGenerator/GeneratorExecutionContextExt.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using Nustache.Core;
using Scriban;
using Scriban.Runtime;
using System.Text;

namespace LibKubernetesGenerator
{
internal static class GeneratorExecutionContextExt
{
public static void RenderToContext(this IncrementalGeneratorPostInitializationContext context, string templatefile, object data, string generatedfile)
public static void RenderToContext(this IncrementalGeneratorPostInitializationContext context, string templatefile, ScriptObject sc, string generatedfile)
{
var template = EmbedResource.GetResource(templatefile);
var generated = Render.StringToString(template, data);
var tc = new TemplateContext();
tc.PushGlobal(sc);
context.RenderToContext(templatefile, tc, generatedfile);
}

public static void RenderToContext(this IncrementalGeneratorPostInitializationContext context, string templatefile, TemplateContext tc, string generatedfile)
{
var template = Template.Parse(EmbedResource.GetResource(templatefile));
var generated = template.Render(tc);
context.AddSource(generatedfile, SourceText.From(generated, Encoding.UTF8));
}
}
7 changes: 0 additions & 7 deletions src/LibKubernetesGenerator/INustacheHelper.cs

This file was deleted.

8 changes: 8 additions & 0 deletions src/LibKubernetesGenerator/IScriptObjectHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Scriban.Runtime;

namespace LibKubernetesGenerator;

internal interface IScriptObjectHelper
{
void RegisterHelper(ScriptObject scriptObject);
}
45 changes: 12 additions & 33 deletions src/LibKubernetesGenerator/KubernetesClientSourceGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,38 +1,22 @@
using Autofac;
using Microsoft.CodeAnalysis;
using NSwag;
using Nustache.Core;
#if GENERATE_AUTOMAPPER
using System.Collections.Generic;
using System;
using System.IO;
using System.Linq;
#endif
using System.Collections.Generic;
using System.Reflection;

namespace LibKubernetesGenerator
{
[Generator]
public class KubernetesClientSourceGenerator : IIncrementalGenerator
{
private static readonly object Execlock = new object();

private static (OpenApiDocument, IContainer) BuildContainer()
{
var swagger = OpenApiDocument.FromJsonAsync(EmbedResource.GetResource("swagger.json")).GetAwaiter().GetResult();
var container = BuildContainer(swagger);
// TODO move to Handlebars.Net
// here is to clean up the custom helpers in static Nustache.Core.Helpers
{
var ch = typeof(Helpers).GetField("CustomHelpers", BindingFlags.Static | BindingFlags.NonPublic);
((Dictionary<string, Helper>)ch.GetValue(null)).Clear();
}

foreach (var helper in container.Resolve<IEnumerable<INustacheHelper>>())
{
helper.RegisterHelper();
}

return (swagger, container);
}

@@ -77,6 +61,9 @@ private static IContainer BuildContainer(OpenApiDocument swagger)
.AsImplementedInterfaces()
;

builder.RegisterType<ScriptObjectFactory>()
;

builder.RegisterType<ModelExtGenerator>();
builder.RegisterType<ModelGenerator>();
builder.RegisterType<ApiGenerator>();
@@ -92,31 +79,23 @@ public void Initialize(IncrementalGeneratorInitializationContext generatorContex
#if GENERATE_BASIC
generatorContext.RegisterPostInitializationOutput(ctx =>
{
lock (Execlock)
{
var (swagger, container) = BuildContainer();

container.Resolve<VersionGenerator>().Generate(swagger, ctx);
var (swagger, container) = BuildContainer();

container.Resolve<ModelGenerator>().Generate(swagger, ctx);
container.Resolve<ModelExtGenerator>().Generate(swagger, ctx);
container.Resolve<VersionConverterStubGenerator>().Generate(swagger, ctx);
container.Resolve<VersionGenerator>().Generate(swagger, ctx);

container.Resolve<ApiGenerator>().Generate(swagger, ctx);
}
container.Resolve<ModelGenerator>().Generate(swagger, ctx);
container.Resolve<ModelExtGenerator>().Generate(swagger, ctx);
container.Resolve<VersionConverterStubGenerator>().Generate(swagger, ctx);
container.Resolve<ApiGenerator>().Generate(swagger, ctx);
});
#endif

#if GENERATE_AUTOMAPPER
var automappersrc = generatorContext.CompilationProvider.Select((c, _) => c.SyntaxTrees.First(s => PathSuffixMath(s.FilePath, "AutoMapper/VersionConverter.cs")));
generatorContext.RegisterSourceOutput(automappersrc, (ctx, srctree) =>
{
lock (Execlock)
{
var (swagger, container) = BuildContainer();

container.Resolve<VersionConverterAutoMapperGenerator>().Generate(swagger, ctx, srctree);
}
var (swagger, container) = BuildContainer();
container.Resolve<VersionConverterAutoMapperGenerator>().Generate(swagger, ctx, srctree);
});
#endif
}
Loading
Loading