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

Upgrade RazorLight and use embedded resource project #233

Merged
merged 1 commit into from
Jun 20, 2023
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
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
Loading