Skip to content

Commit

Permalink
Upgrade RazorLight and use embedded resource project (opensearch-proj…
Browse files Browse the repository at this point in the history
…ect#233)

Signed-off-by: Thomas Farr <[email protected]>
  • Loading branch information
Xtansia committed Dec 3, 2023
1 parent 5dc9ef2 commit 681b16b
Show file tree
Hide file tree
Showing 42 changed files with 204 additions and 258 deletions.
3 changes: 2 additions & 1 deletion src/ApiGenerator/ApiGenerator.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@
<PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="Spectre.Console" Version="0.47.0" />
<PackageReference Include="System.CommandLine.DragonFruit" Version="0.3.0-alpha.20371.2" />
<PackageReference Include="RazorLight" Version="2.1.0" />
<PackageReference Include="RazorLight" Version="2.3.1" />
<PackageReference Include="System.Text.Encodings.Web" Version="7.0.0" />
</ItemGroup>
<ItemGroup>
<Folder Include="RestSpecification\Core" />
<EmbeddedResource Include="Views\**\*.cshtml" />
</ItemGroup>
</Project>
15 changes: 7 additions & 8 deletions src/ApiGenerator/CodeTemplatePage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,16 @@
* under the License.
*/

using System;
using System.Threading.Tasks;
using RazorLight;

namespace ApiGenerator
namespace ApiGenerator
{
/// <summary> This only exists to make the IDE tooling happy, not actually used to render the templates </summary>
public class CodeTemplatePage<TModel> : TemplatePage<TModel>
{
public override Task ExecuteAsync() => throw new NotImplementedException();
public abstract class CodeTemplatePage<TModel> : TemplatePage<TModel>
{
protected new Task IncludeAsync(string key, object model = null)
=> base.IncludeAsync(key.Replace('/', '.'), model);

public Task Execute() => Task.CompletedTask;
}
protected async Task IncludeGeneratorNotice() => await IncludeAsync("GeneratorNotice");
}
}
11 changes: 4 additions & 7 deletions src/ApiGenerator/Configuration/ViewLocations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,12 @@
* under the License.
*/

namespace ApiGenerator.Configuration
namespace ApiGenerator.Configuration
{
public static class ViewLocations
{
public static string Root { get; } = $@"{GeneratorLocations.Root}Views/";
private static string HighLevelRoot { get; } = $@"{Root}/HighLevel/";
public static string HighLevel(params string[] paths) => HighLevelRoot + string.Join("/", paths);

private static string LowLevelRoot { get; } = $@"{Root}/LowLevel/";
public static string LowLevel(params string[] paths) => LowLevelRoot + string.Join("/", paths);
public static string HighLevel(params string[] paths) => "HighLevel." + string.Join(".", paths);

public static string LowLevel(params string[] paths) => "LowLevel." + string.Join(".", paths);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public override async Task Generate(RestApiSpec spec, ProgressBar progressBar, C
var view = ViewLocations.HighLevel("Requests", "ApiUrlsLookup.cshtml");
var target = GeneratorLocations.HighLevel("_Generated", "ApiUrlsLookup.generated.cs");

await DoRazor(spec, view, target, null, token);
await DoRazor(spec, view, target, token);
}
}
}
2 changes: 1 addition & 1 deletion src/ApiGenerator/Generator/Razor/DescriptorsGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public override async Task Generate(RestApiSpec spec, ProgressBar progressBar, C

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

var dependantView = ViewLocations.HighLevel("Descriptors", "Descriptors.cshtml");
string Target(string id) => GeneratorLocations.HighLevel($"Descriptors.{id}.cs");
Expand Down
2 changes: 1 addition & 1 deletion src/ApiGenerator/Generator/Razor/EnumsGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public override async Task Generate(RestApiSpec spec, ProgressBar progressBar, C
var view = ViewLocations.LowLevel("Enums.Generated.cshtml");
var target = GeneratorLocations.LowLevel("Api", "Enums.Generated.cs");

await DoRazor(spec, view, target, null, token);
await DoRazor(spec, view, target, token);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public override async Task Generate(RestApiSpec spec, ProgressBar progressBar, C

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

string Target(string id) => GeneratorLocations.HighLevel($"OpenSearchClient.{id}.cs");

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

await DoRazor(spec, view, target, null, token);
await DoRazor(spec, view, target, token);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public override async Task Generate(RestApiSpec spec, ProgressBar progressBar, C

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

var namespaced = spec.EndpointsPerNamespaceLowLevel.Where(kv => kv.Key != CsharpNames.RootNamespace).ToList();
var namespacedView = ViewLocations.LowLevel("Client", "Implementation", "OpenSearchLowLevelClient.Namespace.cshtml");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public override async Task Generate(RestApiSpec spec, ProgressBar progressBar, C
var view = ViewLocations.LowLevel("Client", "Interface", "IOpenSearchLowLevelClient.cshtml");
var target = GeneratorLocations.LowLevel("IOpenSearchLowLevelClient.Generated.cs");

await DoRazor(spec, view, target, null, token);
await DoRazor(spec, view, target, token);
}
}
}
14 changes: 7 additions & 7 deletions src/ApiGenerator/Generator/Razor/RazorGeneratorBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,18 @@ namespace ApiGenerator.Generator.Razor
public abstract class RazorGeneratorBase
{
private static readonly RazorLightEngine Engine = new RazorLightEngineBuilder()
.UseProject(new FileSystemRazorProject(Path.GetFullPath(ViewLocations.Root)))
.UseMemoryCachingProvider()
.UseProject(new EmbeddedRazorProject(typeof(CodeTemplatePage<>).Assembly, "ApiGenerator.Views"))
.SetOperatingAssembly(typeof(CodeTemplatePage<>).Assembly)
.UseMemoryCachingProvider()
.EnableDebugMode()
.Build();

protected async Task DoRazor<TModel>(TModel model, string viewLocation, string targetLocation, string cacheNameSuffix, CancellationToken token)
protected async Task DoRazor<TModel>(TModel model, string viewLocation, string targetLocation, CancellationToken token)
{
try
{
var name = GetType().Name + cacheNameSuffix;
var sourceFileContents = await File.ReadAllTextAsync(viewLocation, token);
token.ThrowIfCancellationRequested();
var generated = await Engine.CompileRenderStringAsync(name, sourceFileContents, model);
var generated = await Engine.CompileRenderAsync(viewLocation, model);
WriteFormattedCsharpFile(targetLocation, generated);
}
catch (TemplateGenerationException e)
Expand All @@ -82,7 +82,7 @@ CancellationToken token
{
var id = identifier(item);
var targetLocation = target(id);
await DoRazor(item, viewLocation, targetLocation, id, token);
await DoRazor(item, viewLocation, targetLocation, token);
c.Tick($"{Title}: {id}");
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/ApiGenerator/Generator/Razor/RequestsGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public override async Task Generate(RestApiSpec spec, ProgressBar progressBar, C

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

var dependantView = ViewLocations.HighLevel("Requests", "Requests.cshtml");
string Target(string id) => GeneratorLocations.HighLevel($"Requests.{id}.cs");
Expand Down
2 changes: 1 addition & 1 deletion src/ApiGenerator/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ private static async Task<int> Main(
AnsiConsole.WriteLine();
AnsiConsole.Write(new Rule("[b white on darkred] Exception [/]").LeftJustified());
AnsiConsole.WriteLine();
AnsiConsole.WriteException(ex);
AnsiConsole.WriteException(ex, ExceptionFormats.ShowLinks);
return 1;
}
return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,17 @@
@using ApiGenerator.Domain.Code.HighLevel.Methods
@inherits ApiGenerator.CodeTemplatePage<FluentSyntaxView>
@{
FluentSyntaxBase syntax = Model.Syntax;

var method = !Model.Async ? syntax.MethodName : string.Format("{0}Async", syntax.MethodName);
var method = !Model.Async ? Model.Syntax.MethodName : string.Format("{0}Async", Model.Syntax.MethodName);
var asyncKeyword = Model.Syntax.InterfaceResponse && Model.Async ? "async " : String.Empty;
var awaitKeyWord = Model.Syntax.InterfaceResponse && Model.Async ? "await ": string.Empty;
var configureAwait = Model.Syntax.InterfaceResponse && Model.Async ? ".ConfigureAwait(false)" : String.Empty;

var requestMethodGenerics = syntax.RequestMethodGenerics;
var descriptor = syntax.DescriptorName;
var selectorArgs = syntax.SelectorArguments();
var selectorChained = syntax.SelectorChainedDefaults();
var requestMethodGenerics = Model.Syntax.RequestMethodGenerics;
var descriptor = Model.Syntax.DescriptorName;
var selectorArgs = Model.Syntax.SelectorArguments();
var selectorChained = Model.Syntax.SelectorChainedDefaults();
var cancellationToken = !Model.Async ? string.Empty : ", ct";
}
@{ await IncludeAsync("HighLevel/Client/MethodXmlDocs.cshtml", syntax); }
@{ await IncludeAsync("HighLevel/Client/MethodXmlDocs.cshtml", Model.Syntax); }
public @(asyncKeyword)@{ await IncludeAsync("HighLevel/Client/FluentSyntax/FluentMethodHeader.cshtml", Model);} @Raw("=>")
@(awaitKeyWord)@(method)@(Raw(requestMethodGenerics))(selector.InvokeOrDefault(new @(Raw(descriptor))(@Raw(selectorArgs))@(@selectorChained))@cancellationToken)@Raw(configureAwait);
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
@using ApiGenerator.Domain.Code.HighLevel.Methods
@inherits ApiGenerator.CodeTemplatePage<FluentSyntaxView>
@{
FluentSyntaxBase syntax = Model.Syntax;

var response = !Model.Async ? syntax.ResponseName : string.Format("Task<{0}>", syntax.ResponseName);
var method = !Model.Async ? syntax.MethodName : string.Format("{0}Async", syntax.MethodName);
var response = !Model.Async ? Model.Syntax.ResponseName : string.Format("Task<{0}>", Model.Syntax.ResponseName);
var method = !Model.Async ? Model.Syntax.MethodName : string.Format("{0}Async", Model.Syntax.MethodName);

var methodGenerics = syntax.MethodGenerics;
var descriptorArgs = syntax.DescriptorArguments();
var selector = syntax.Selector;
var optionalSelector = syntax.OptionalSelectorSuffix;
var whereClause = syntax.GenericWhereClause;
var methodGenerics = Model.Syntax.MethodGenerics;
var descriptorArgs = Model.Syntax.DescriptorArguments();
var selector = Model.Syntax.Selector;
var optionalSelector = Model.Syntax.OptionalSelectorSuffix;
var whereClause = Model.Syntax.GenericWhereClause;
var cancellationToken = !Model.Async ? string.Empty : ", CancellationToken ct = default";
}
@Raw(response) @(method)@(Raw(methodGenerics))(@(Raw(descriptorArgs))@(Raw(selector)) selector@(optionalSelector)@(cancellationToken))@whereClause
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@
@using HighLevelModel = ApiGenerator.Domain.Code.HighLevel.Methods.HighLevelModel
@inherits CodeTemplatePage<HighLevelModel>
@{
HighLevelModel model = Model;
var fluentPath = "HighLevel/Client/FluentSyntax/FluentMethod.cshtml";
var initializerPath = "HighLevel/Client/InitializerSyntax/InitializerMethod.cshtml";
const string fluentPath = "HighLevel/Client/FluentSyntax/FluentMethod.cshtml";
const string initializerPath = "HighLevel/Client/InitializerSyntax/InitializerMethod.cshtml";
}
@{ await IncludeAsync(fluentPath, new FluentSyntaxView(model.Fluent, async: false)); }
@{ await IncludeAsync(fluentPath, new FluentSyntaxView(model.Fluent, async: true)); }
@if (model.FluentBound != null)
@{ await IncludeAsync(fluentPath, new FluentSyntaxView(Model.Fluent, async: false)); }
@{ await IncludeAsync(fluentPath, new FluentSyntaxView(Model.Fluent, async: true)); }
@if (Model.FluentBound != null)
{
<text>
@{ await IncludeAsync(fluentPath, new FluentSyntaxView(model.FluentBound, async: false)); }
@{ await IncludeAsync(fluentPath, new FluentSyntaxView(model.FluentBound, async: true)); }
@{ await IncludeAsync(fluentPath, new FluentSyntaxView(Model.FluentBound, async: false)); }
@{ await IncludeAsync(fluentPath, new FluentSyntaxView(Model.FluentBound, async: true)); }
</text>
}
@{ await IncludeAsync(initializerPath, new InitializerSyntaxView(model.Initializer, async: false)); }
@{ await IncludeAsync(initializerPath, new InitializerSyntaxView(model.Initializer, async: true)); }
@{ await IncludeAsync(initializerPath, new InitializerSyntaxView(Model.Initializer, async: false)); }
@{ await IncludeAsync(initializerPath, new InitializerSyntaxView(Model.Initializer, async: true)); }
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,28 @@
@using ApiGenerator.Domain.Specification
@inherits ApiGenerator.CodeTemplatePage<KeyValuePair<string, ReadOnlyCollection<ApiEndpoint>>>
@{
KeyValuePair<string, ReadOnlyCollection<ApiEndpoint>> model = Model;
string ns = model.Key;
var endpoints = model.Value;
var (ns, endpoints) = Model;
}
@{ await IncludeAsync("GeneratorNotice.cshtml", model); }
@{ await IncludeGeneratorNotice(); }
// ReSharper disable RedundantUsingDirective
using System;
using System.Threading;
using System.Threading.Tasks;
using OpenSearch.Net.@(CsharpNames.ApiNamespace).@(ns)@(CsharpNames.ApiNamespaceSuffix);
using OpenSearch.Net.@(CsharpNames.ApiNamespace).@ns@(CsharpNames.ApiNamespaceSuffix);

// ReSharper disable once CheckNamespace
// ReSharper disable RedundantTypeArgumentsOfMethod
namespace OpenSearch.Client.@(CsharpNames.ApiNamespace).@(ns)@(CsharpNames.ApiNamespaceSuffix)
namespace OpenSearch.Client.@(CsharpNames.ApiNamespace).@ns@(CsharpNames.ApiNamespaceSuffix)
{
///<summary>
/// @(ns.SplitPascalCase()) APIs.
/// @ns.SplitPascalCase() APIs.
/// <para>Not intended to be instantiated directly. Use the <see cref="IOpenSearchClient.@ns"/> property
/// on <see cref="IOpenSearchClient"/>.
///</para>
///</summary>
public class @(CsharpNames.HighLevelClientNamespacePrefix)@(model.Key)@(CsharpNames.ClientNamespaceSuffix) : NamespacedClientProxy
public class @(CsharpNames.HighLevelClientNamespacePrefix)@ns@(CsharpNames.ClientNamespaceSuffix) : NamespacedClientProxy
{
internal @(CsharpNames.HighLevelClientNamespacePrefix)@(model.Key)@(CsharpNames.ClientNamespaceSuffix)(OpenSearchClient client) : base(client) {}
internal @(CsharpNames.HighLevelClientNamespacePrefix)@ns@(CsharpNames.ClientNamespaceSuffix)(OpenSearchClient client) : base(client) {}
@foreach(var e in endpoints)
{
await IncludeAsync("HighLevel/Client/Implementation/MethodImplementation.cshtml", e.HighLevelModel);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
@using ApiGenerator
@using ApiGenerator.Domain.Code
@inherits CodeTemplatePage<RestApiSpec>
@{ await IncludeAsync("GeneratorNotice.cshtml", Model); }
@{ await IncludeGeneratorNotice(); }
// ReSharper disable RedundantUsingDirective
using System;
using System.Threading;
Expand All @@ -12,8 +12,7 @@ using OpenSearch.Client;
@{ await IncludeAsync("HighLevel/Client/Usings.cshtml", Model);}

@{
RestApiSpec model = Model;
var namespaces = model.EndpointsPerNamespaceHighLevel.Keys.Where(k => k != CsharpNames.RootNamespace).ToList();
var namespaces = Model.EndpointsPerNamespaceHighLevel.Keys.Where(k => k != CsharpNames.RootNamespace).ToList();
<text>
// ReSharper disable RedundantTypeArgumentsOfMethod
namespace OpenSearch.Client
Expand Down Expand Up @@ -44,7 +43,7 @@ namespace OpenSearch.Client
</text>


foreach (var kv in model.EndpointsPerNamespaceHighLevel)
foreach (var kv in Model.EndpointsPerNamespaceHighLevel)
{
if (kv.Key != CsharpNames.RootNamespace)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@
@using ApiGenerator.Domain.Code.HighLevel.Methods
@inherits ApiGenerator.CodeTemplatePage<InitializerSyntaxView>
@{
InitializerMethod syntax = Model.Syntax;

var dispatchMethod = !Model.Async ? syntax.DispatchMethod : string.Format("{0}Async", syntax.DispatchMethod);
var dispatchGenerics = syntax.DispatchGenerics;
var dispatchParameters = syntax.DispatchParameters;
var dispatchMethod = !Model.Async ? Model.Syntax.DispatchMethod : string.Format("{0}Async", Model.Syntax.DispatchMethod);
var dispatchGenerics = Model.Syntax.DispatchGenerics;
var dispatchParameters = Model.Syntax.DispatchParameters;
var asyncKeyword = Model.Syntax.InterfaceResponse && Model.Async ? "async " : String.Empty;
var awaitKeyWord = Model.Syntax.InterfaceResponse && Model.Async ? "await ": string.Empty;
var configureAwait = Model.Syntax.InterfaceResponse && Model.Async ? ".ConfigureAwait(false)" : String.Empty;
Expand All @@ -15,7 +13,7 @@
dispatchParameters += ", ct";
}
}
@{ await IncludeAsync("HighLevel/Client/MethodXmlDocs.cshtml", syntax); }
@{ await IncludeAsync("HighLevel/Client/MethodXmlDocs.cshtml", Model.Syntax); }
public @Raw(asyncKeyword)@{ await IncludeAsync("HighLevel/Client/InitializerSyntax/InitializerMethodHeader.cshtml", Model); } @Raw("=>")
@(awaitKeyWord)@(dispatchMethod)@(Raw(dispatchGenerics))(@Raw(dispatchParameters))@Raw(configureAwait);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
@using ApiGenerator.Domain.Code.HighLevel.Methods
@inherits ApiGenerator.CodeTemplatePage<InitializerSyntaxView>
@{
InitializerMethod syntax = Model.Syntax;

var response = !Model.Async ? syntax.ResponseName : string.Format("Task<{0}>", syntax.ResponseName);
var method = !Model.Async ? syntax.MethodName : string.Format("{0}Async", syntax.MethodName);
var requestMethodGenerics = syntax.MethodGenerics;
var response = !Model.Async ? Model.Syntax.ResponseName : string.Format("Task<{0}>", Model.Syntax.ResponseName);
var method = !Model.Async ? Model.Syntax.MethodName : string.Format("{0}Async", Model.Syntax.MethodName);
var requestMethodGenerics = Model.Syntax.MethodGenerics;

var methodsArgs = string.Format("{0} request", syntax.ArgumentType);
var methodsArgs = string.Format("{0} request", Model.Syntax.ArgumentType);
if (Model.Async)
{
methodsArgs += ", CancellationToken ct = default";
}
var whereClause = syntax.GenericWhereClause;
var whereClause = Model.Syntax.GenericWhereClause;
}
@Raw(response) @(method)@(Raw(requestMethodGenerics))(@Raw(methodsArgs))@whereClause
Loading

0 comments on commit 681b16b

Please sign in to comment.