Files
csharp/gen/LibKubernetesGenerator/VersionConverterGenerator.cs
Boshi Lian 250a45741e move all generated code to c# source generator (#756)
* remove the dependency of unprocessed swagger file

* all code generator

* good bye generated code

* remove generator cmd from sln

* eliminate generated folder

* fix multi target build

* disable dotnet fmt due to cannot load lib generator

* fix race

* fix race for multi target
2021-12-22 17:16:44 -08:00

118 lines
3.9 KiB
C#

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using NSwag;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace LibKubernetesGenerator
{
internal class VersionConverterGenerator
{
private readonly ClassNameHelper classNameHelper;
public VersionConverterGenerator(ClassNameHelper classNameHelper)
{
this.classNameHelper = classNameHelper;
}
public void Generate(OpenApiDocument swagger, GeneratorExecutionContext context)
{
var allGeneratedModelClassNames = new List<string>();
foreach (var kv in swagger.Definitions)
{
var def = kv.Value;
var clz = classNameHelper.GetClassNameForSchemaDefinition(def);
allGeneratedModelClassNames.Add(clz);
}
var manualMaps = new List<(string, string)>();
var manualconverter = context.Compilation.SyntaxTrees.First(s => PathSuffixMath(s.FilePath, "Versioning/VersionConverter.cs"));
manualMaps = Regex.Matches(manualconverter.GetText().ToString(), @"\.CreateMap<(?<T1>.+?),\s?(?<T2>.+?)>")
.OfType<Match>()
.Select(x => (x.Groups["T1"].Value, x.Groups["T2"].Value))
.ToList();
var versionRegex = @"(^V|v)[0-9]+((alpha|beta)[0-9]+)?";
var typePairs = allGeneratedModelClassNames
.OrderBy(x => x)
.Select(x => new
{
Version = Regex.Match(x, versionRegex).Value?.ToLower(),
Kinda = Regex.Replace(x, versionRegex, string.Empty),
Type = x,
})
.Where(x => !string.IsNullOrEmpty(x.Version))
.GroupBy(x => x.Kinda)
.Where(x => x.Count() > 1)
.SelectMany(x =>
x.SelectMany((value, index) => x.Skip(index + 1), (first, second) => new { first, second }))
.OrderBy(x => x.first.Kinda)
.ThenBy(x => x.first.Version)
.Select(x => (x.first.Type, x.second.Type))
.ToList();
var versionConverterPairs = typePairs.Except(manualMaps).ToList();
var sbmodel = new StringBuilder(@"// <auto-generated />
namespace k8s.Models;
using k8s.Versioning;
");
var sbversion = new StringBuilder(@"// <auto-generated />
namespace k8s.Versioning;
using AutoMapper;
using k8s.Models;
public static partial class VersionConverter
{
private static void AutoConfigurations(IMapperConfigurationExpression cfg)
{
");
foreach (var (t0, t1) in versionConverterPairs)
{
sbmodel.AppendLine($@"
public partial class {t0}
{{
public static explicit operator {t0}({t1} s) => VersionConverter.Mapper.Map<{t0}>(s);
}}
public partial class {t1}
{{
public static explicit operator {t1}({t0} s) => VersionConverter.Mapper.Map<{t1}>(s);
}}");
sbversion.AppendLine($@"cfg.CreateMap<{t0}, {t1}>().ReverseMap();");
}
sbversion.AppendLine("}}");
context.AddSource($"ModelOperators.g.cs", SourceText.From(sbmodel.ToString(), Encoding.UTF8));
context.AddSource($"VersionConverter.g.cs", SourceText.From(sbversion.ToString(), Encoding.UTF8));
}
private IEnumerable<string> PathSplit(string path)
{
var p = path;
while (!string.IsNullOrEmpty(p))
{
yield return Path.GetFileName(p);
p = Path.GetDirectoryName(p);
}
}
private bool PathSuffixMath(string path, string suffix)
{
var s = PathSplit(suffix).ToList();
return PathSplit(path).Take(s.Count).SequenceEqual(s);
}
}
}