Skip to content
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

Add ability to generate only a subset of operations #278

Merged
Merged
Show file tree
Hide file tree
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
3 changes: 2 additions & 1 deletion src/ApiGenerator/ApiGenerator.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
Expand All @@ -9,6 +9,7 @@
<PreserveCompilationContext>true</PreserveCompilationContext>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Glob" Version="1.1.9" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.6.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NSwag.Core.Yaml" Version="13.19.0" />
Expand Down
10 changes: 9 additions & 1 deletion src/ApiGenerator/Configuration/CodeConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,19 @@
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using GlobExpressions;

namespace ApiGenerator.Configuration
{
public static class CodeConfiguration
{
{
private static readonly Glob[] OperationsToInclude =
{
// e.g. new Glob("nodes.*"),
};

public static bool IncludeOperation(string name) => OperationsToInclude.Any(g => g.IsMatch(name));

/// <summary>
/// Map API default names for API's we are only supporting on the low level client first
/// </summary>
Expand Down
11 changes: 8 additions & 3 deletions src/ApiGenerator/Configuration/GeneratorLocations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,15 @@ public static class GeneratorLocations
public static string OpenSearchNetFolder { get; } = $@"{Root}../../src/OpenSearch.Net/";

public static string OpenSearchClientFolder { get; } = $@"{Root}../../src/OpenSearch.Client/";
// @formatter:on — enable formatter after this line

public static string HighLevel(params string[] paths) => OpenSearchClientFolder + string.Join("/", paths);
public static string LowLevel(params string[] paths) => OpenSearchNetFolder + string.Join("/", paths);
public static string LowLevelGeneratedFolder { get; } = $"{OpenSearchNetFolder}_Generated/";

public static string HighLevelGeneratedFolder { get; } = $"{OpenSearchClientFolder}_Generated/";

// @formatter:on — enable formatter after this line

public static string HighLevel(params string[] paths) => HighLevelGeneratedFolder + string.Join("/", paths);
public static string LowLevel(params string[] paths) => LowLevelGeneratedFolder + string.Join("/", paths);

public static readonly Assembly Assembly = typeof(Generator.ApiGenerator).Assembly;

Expand Down
2 changes: 1 addition & 1 deletion src/ApiGenerator/Generator/ApiEndpointFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ private static string GetOpenSearchType(JsonSchema schema)
while (schema.HasReference) schema = schema.Reference;

if (schema.GetExtension("x-data-type") is string dataType)
return dataType;
return dataType == "array" ? "list" : dataType;

return schema.Type switch
{
Expand Down
68 changes: 40 additions & 28 deletions src/ApiGenerator/Generator/ApiGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Threading;
using System.Threading.Tasks;
using ApiGenerator.Configuration;
using ApiGenerator.Domain;
using ApiGenerator.Generator.Razor;
Expand All @@ -42,48 +43,51 @@ namespace ApiGenerator.Generator
{
public class ApiGenerator
{
public static List<string> Warnings { get; private set; } = new List<string>();
public static List<string> Warnings { get; private set; } = new();

public static async Task Generate(bool lowLevelOnly, RestApiSpec spec, CancellationToken token)
{
static async Task DoGenerate(ICollection<RazorGeneratorBase> generators, RestApiSpec restApiSpec, bool highLevel, CancellationToken token)
async Task DoGenerate(IReadOnlyCollection<RazorGeneratorBase> generators, bool highLevel)
{
var pbarOpts = new ProgressBarOptions { ProgressCharacter = '─', BackgroundColor = ConsoleColor.Yellow };
var message = $"Generating {(highLevel ? "high" : "low")} level code";
using var pbar = new ProgressBar(generators.Count, message, pbarOpts);
foreach (var generator in generators)
{
pbar.Message = "Generating " + generator.Title;
await generator.Generate(restApiSpec, pbar, token);
await generator.Generate(spec, pbar, token);
pbar.Tick("Generated " + generator.Title);
}
}

RecursiveDelete(GeneratorLocations.LowLevelGeneratedFolder);
await DoGenerate(
new RazorGeneratorBase[] {
//low level client
new LowLevelClientInterfaceGenerator(),
new LowLevelClientImplementationGenerator(),
new RequestParametersGenerator(),
new EnumsGenerator()
},
highLevel: false
);

var lowLevelGenerators = new List<RazorGeneratorBase>
{
//low level client
new LowLevelClientInterfaceGenerator(),
new LowLevelClientImplementationGenerator(),
new RequestParametersGenerator(),
new EnumsGenerator(),
new ApiUrlsLookupsGenerator(),
};

var highLevelGenerators = new List<RazorGeneratorBase>
{
//high level client
new HighLevelClientInterfaceGenerator(),
new HighLevelClientImplementationGenerator(),
new DescriptorsGenerator(),
new RequestsGenerator(),
};
if (lowLevelOnly) return;

await DoGenerate(lowLevelGenerators, spec, highLevel: false, token);
if (!lowLevelOnly)
await DoGenerate(highLevelGenerators, spec, highLevel: true, token);

}
RecursiveDelete(GeneratorLocations.HighLevelGeneratedFolder);
await DoGenerate(
new RazorGeneratorBase[]
{
//high level client
new ApiUrlsLookupsGenerator(),
new HighLevelClientInterfaceGenerator(),
new HighLevelClientImplementationGenerator(),
new DescriptorsGenerator(),
new RequestsGenerator(),
},
highLevel: true
);
}

public static async Task<RestApiSpec> CreateRestApiSpecModel(CancellationToken token = default)
{
Expand All @@ -93,10 +97,18 @@ public static async Task<RestApiSpec> CreateRestApiSpecModel(CancellationToken t
.Select(kv => new { HttpPath = kv.Key, PathItem = kv.Value })
.SelectMany(p => p.PathItem.Select(kv => new { p.HttpPath, p.PathItem, HttpMethod = kv.Key, Operation = kv.Value }))
.GroupBy(o => o.Operation.ExtensionData["x-operation-group"].ToString())
.Where(o => CodeConfiguration.IncludeOperation(o.Key))
.Select(o => ApiEndpointFactory.From(o.Key, o.Select(i => (i.HttpPath, i.PathItem, i.HttpMethod, i.Operation)).ToList()))
.ToImmutableSortedDictionary(e => e.Name, e => e);

return new RestApiSpec { Endpoints = endpoints };
}

private static void RecursiveDelete(string path)
{
if (!Directory.Exists(path)) return;

Directory.Delete(path, true);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public class ApiUrlsLookupsGenerator : RazorGeneratorBase
public override async Task Generate(RestApiSpec spec, ProgressBar progressBar, CancellationToken token)
{
var view = ViewLocations.HighLevel("Requests", "ApiUrlsLookup.cshtml");
var target = GeneratorLocations.HighLevel("_Generated", "ApiUrlsLookup.generated.cs");
var target = GeneratorLocations.HighLevel("ApiUrlsLookup.cs");

await DoRazor(spec, view, target, token);
}
Expand Down
6 changes: 1 addition & 5 deletions src/ApiGenerator/Generator/Razor/DescriptorsGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,7 @@ public class DescriptorsGenerator : RazorGeneratorBase

public override async Task Generate(RestApiSpec spec, ProgressBar progressBar, CancellationToken token)
{
// Delete existing files
foreach (var file in Directory.GetFiles(GeneratorLocations.OpenSearchClientFolder, "Descriptors.*.cs"))
File.Delete(file);

var view = ViewLocations.HighLevel("Descriptors", "RequestDescriptorBase.cshtml");
var view = ViewLocations.HighLevel("Descriptors", "RequestDescriptorBase.cshtml");
var target = GeneratorLocations.HighLevel("Descriptors.cs");
await DoRazor(spec, view, target, token);

Expand Down
4 changes: 2 additions & 2 deletions src/ApiGenerator/Generator/Razor/EnumsGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ public class EnumsGenerator : RazorGeneratorBase

public override async Task Generate(RestApiSpec spec, ProgressBar progressBar, CancellationToken token)
{
var view = ViewLocations.LowLevel("Enums.Generated.cshtml");
var target = GeneratorLocations.LowLevel("Api", "Enums.Generated.cs");
var view = ViewLocations.LowLevel("Enums.cshtml");
var target = GeneratorLocations.LowLevel("Api", "Enums.cs");

await DoRazor(spec, view, target, token);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,7 @@ public class HighLevelClientImplementationGenerator : RazorGeneratorBase

public override async Task Generate(RestApiSpec spec, ProgressBar progressBar, CancellationToken token)
{
// Delete existing files
foreach (var file in Directory.GetFiles(GeneratorLocations.OpenSearchClientFolder, "OpenSearchClient.*.cs"))
File.Delete(file);

var view = ViewLocations.HighLevel("Client", "Implementation", "OpenSearchClient.cshtml");
var view = ViewLocations.HighLevel("Client", "Implementation", "OpenSearchClient.cshtml");
var target = GeneratorLocations.HighLevel($"OpenSearchClient.{CsharpNames.RootNamespace}.cs");
await DoRazor(spec, view, target, token);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public class HighLevelClientInterfaceGenerator : RazorGeneratorBase
public override async Task Generate(RestApiSpec spec, ProgressBar progressBar, CancellationToken token)
{
var view = ViewLocations.HighLevel("Client", "Interface", "IOpenSearchClient.cshtml");
var target = GeneratorLocations.HighLevel("IOpenSearchClient.Generated.cs");
var target = GeneratorLocations.HighLevel("IOpenSearchClient.cs");

await DoRazor(spec, view, target, token);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,7 @@ public class LowLevelClientImplementationGenerator : RazorGeneratorBase

public override async Task Generate(RestApiSpec spec, ProgressBar progressBar, CancellationToken token)
{
// Delete existing files
foreach (var file in Directory.GetFiles(GeneratorLocations.OpenSearchNetFolder, "OpenSearchLowLevelClient.*.cs"))
File.Delete(file);

var view = ViewLocations.LowLevel("Client", "Implementation", "OpenSearchLowLevelClient.cshtml");
var view = ViewLocations.LowLevel("Client", "Implementation", "OpenSearchLowLevelClient.cshtml");
var target = GeneratorLocations.LowLevel($"OpenSearchLowLevelClient.{CsharpNames.RootNamespace}.cs");
await DoRazor(spec, view, target, token);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public class LowLevelClientInterfaceGenerator : RazorGeneratorBase
public override async Task Generate(RestApiSpec spec, ProgressBar progressBar, CancellationToken token)
{
var view = ViewLocations.LowLevel("Client", "Interface", "IOpenSearchLowLevelClient.cshtml");
var target = GeneratorLocations.LowLevel("IOpenSearchLowLevelClient.Generated.cs");
var target = GeneratorLocations.LowLevel("IOpenSearchLowLevelClient.cs");

await DoRazor(spec, view, target, token);
}
Expand Down
5 changes: 4 additions & 1 deletion src/ApiGenerator/Generator/Razor/RazorGeneratorBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,10 @@ protected static void WriteFormattedCsharpFile(string path, string contents)
var tree = CSharpSyntaxTree.ParseText(contents);
var root = tree.GetRoot().NormalizeWhitespace(indentation:"\t", "\n");
contents = root.ToFullString();
File.WriteAllText(path, contents);

if (Directory.GetParent(path) is { Exists: false } dir) dir.Create();

File.WriteAllText(path, contents);
}

public abstract string Title { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,7 @@ public class RequestParametersGenerator : RazorGeneratorBase

public override async Task Generate(RestApiSpec spec, ProgressBar progressBar, CancellationToken token)
{
// Delete existing files
foreach (var file in Directory.GetFiles(GeneratorLocations.OpenSearchNetFolder, "RequestParameters.*.cs"))
File.Delete(file);

var view = ViewLocations.LowLevel("RequestParameters", "RequestParameters.cshtml");
var view = ViewLocations.LowLevel("RequestParameters", "RequestParameters.cshtml");
string Target(string id) => GeneratorLocations.LowLevel("Api", "RequestParameters", $"RequestParameters.{id}.cs");

var namespaced = spec.EndpointsPerNamespaceLowLevel.ToList();
Expand Down
4 changes: 0 additions & 4 deletions src/ApiGenerator/Generator/Razor/RequestsGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,6 @@ public class RequestsGenerator : RazorGeneratorBase

public override async Task Generate(RestApiSpec spec, ProgressBar progressBar, CancellationToken token)
{
// Delete existing files
foreach (var file in Directory.GetFiles(GeneratorLocations.OpenSearchClientFolder, "Requests.*.cs"))
File.Delete(file);

var view = ViewLocations.HighLevel("Requests", "PlainRequestBase.cshtml");
var target = GeneratorLocations.HighLevel("Requests.cs");
await DoRazor(spec, view, target, token);
Expand Down
Loading
Loading