Skip to content

Commit

Permalink
feat: Added MethodNamingConvention support.
Browse files Browse the repository at this point in the history
  • Loading branch information
HavenDV committed May 21, 2024
1 parent 7726d02 commit 6befdfc
Show file tree
Hide file tree
Showing 17 changed files with 235 additions and 121 deletions.
3 changes: 3 additions & 0 deletions src/libs/OpenApiGenerator.Cli/Commands/GenerateCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using OpenApiGenerator.Core.Extensions;
using OpenApiGenerator.Core.Generators;
using OpenApiGenerator.Core.Models;
using OpenApiGenerator.Core.Naming.Methods;

namespace OpenApiGenerator.Cli.Commands;

Expand Down Expand Up @@ -73,6 +74,8 @@ private static async Task HandleAsync(
UseRequiredKeyword: default,
GenerateConstructors: false,
GenerateMethods: false,
MethodNamingConvention: default,
MethodNamingConventionFallback: MethodNamingConvention.MethodAndPath,
GenerateMethodsAsHttpClientExtensions: false,
GenerateMethodsUsingSystemNetHttpJson: false,
IncludeOperationIds: [],
Expand Down
28 changes: 7 additions & 21 deletions src/libs/OpenApiGenerator.Core/Extensions/OpenApiExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Readers;
using OpenApiGenerator.Core.Models;
using OpenApiGenerator.Core.Naming.Methods;
using OpenApiGenerator.Core.Serialization;

namespace OpenApiGenerator.Core.Extensions;
Expand All @@ -29,31 +30,16 @@ public static OpenApiDocument GetOpenApiDocument(
return openApiDocument;
}


public static string GetOperationIdOrCompute(this OpenApiOperation operation, string path, OperationType operationType)
public static string GetMethodName(this OpenApiOperation operation, string path, OperationType operationType, MethodNamingConvention convention, MethodNamingConvention fallback)
{
operation = operation ?? throw new ArgumentNullException(nameof(operation));

if (operation.OperationId != null)
{
return operation.OperationId.ToPropertyName();
}
var mainGenerator = convention.GetGenerator();
var fallbackGenerator = fallback.GetGenerator();

path = path ?? throw new ArgumentNullException(nameof(path));

var prefix = operationType switch
{
OperationType.Get => "get",
OperationType.Post => "create",
OperationType.Put => "put",
OperationType.Delete => "delete",
OperationType.Patch => "edit",
OperationType.Head => "head",
OperationType.Options => "options",
OperationType.Trace => "trace",
_ => throw new NotSupportedException($"OperationType {operationType} is not supported."),
};
return $"{prefix}{path.TrimStart('/').ToPropertyName().UseWordSeparator('/')}";
return mainGenerator.TryGenerate(operation, path, operationType) ??
fallbackGenerator.TryGenerate(operation, path, operationType) ??
throw new InvalidOperationException("Failed to generate method name");
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace OpenApiGenerator.Core.Generators;
public static class ClientGeneratorMethods
{
public static ImmutableArray<EndPoint> PrepareData(
(string yaml, Settings settings) tuple,
(string text, Settings settings) tuple,
CancellationToken cancellationToken = default)
{
var (text, settings) = tuple;
Expand All @@ -26,9 +26,19 @@ public static ImmutableArray<EndPoint> PrepareData(
return openApiDocument.Paths.SelectMany(path =>
path.Value.Operations
.Where(x =>
(includedOperationIds.Count == 0 ||
includedOperationIds.Contains(x.Value.GetOperationIdOrCompute(path: path.Key, operationType: x.Key))) &&
!excludedOperationIds.Contains(x.Value.GetOperationIdOrCompute(path: path.Key, operationType: x.Key)))
{
if (includedOperationIds.Count == 0 && excludedOperationIds.Count == 0)
{
return true;
}

var methodName = x.Value.GetMethodName(path: path.Key, operationType: x.Key,
settings.MethodNamingConvention, settings.MethodNamingConventionFallback);

return (includedOperationIds.Count == 0 ||
includedOperationIds.Contains(methodName)) &&
!excludedOperationIds.Contains(methodName);
})
.Select(operation => EndPoint.FromSchema(operation, settings, path.Key)))
// Constructor
.Concat(settings.GenerateSdk || settings.GenerateConstructors ? [new EndPoint(
Expand Down
2 changes: 1 addition & 1 deletion src/libs/OpenApiGenerator.Core/Models/EndPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public static EndPoint FromSchema(
: ModelData.FromKey("test", settings) with{ Schema = default };
var response = operation.Value.Responses.Values.FirstOrDefault();
var endPoint = new EndPoint(
Id: operation.Value.GetOperationIdOrCompute(path: path, operationType: operation.Key),
Id: operation.Value.GetMethodName(path: path, operationType: operation.Key, settings.MethodNamingConvention, settings.MethodNamingConventionFallback),
Namespace: settings.Namespace,
ClassName: settings.ClassName.Replace(".", string.Empty),
BaseUrl: string.Empty,
Expand Down
3 changes: 3 additions & 0 deletions src/libs/OpenApiGenerator.Core/Models/Settings.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Immutable;
using OpenApiGenerator.Core.Json;
using OpenApiGenerator.Core.Naming.Methods;

namespace OpenApiGenerator.Core.Models;

Expand All @@ -13,6 +14,8 @@ public readonly record struct Settings(

bool GenerateConstructors,
bool GenerateMethods,
MethodNamingConvention MethodNamingConvention,
MethodNamingConvention MethodNamingConventionFallback,
bool GenerateMethodsAsHttpClientExtensions,
bool GenerateMethodsUsingSystemNetHttpJson,
ImmutableArray<string> IncludeOperationIds,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Microsoft.OpenApi.Models;

namespace OpenApiGenerator.Core.Naming.Methods;

public interface IMethodNameGenerator
{
public string? TryGenerate(OpenApiOperation operation, string path, OperationType operationType);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Microsoft.OpenApi.Models;
using OpenApiGenerator.Core.Extensions;

namespace OpenApiGenerator.Core.Naming.Methods;

public class MethodAndPathGenerator : IMethodNameGenerator
{
public string TryGenerate(OpenApiOperation operation, string path, OperationType operationType)
{
path = path ?? throw new ArgumentNullException(nameof(path));

var prefix = operationType switch
{
OperationType.Get => "get",
OperationType.Post => "create",
OperationType.Put => "put",
OperationType.Delete => "delete",
OperationType.Patch => "edit",
OperationType.Head => "head",
OperationType.Options => "options",
OperationType.Trace => "trace",
_ => throw new NotSupportedException($"OperationType {operationType} is not supported."),
};

return $"{prefix}{path.TrimStart('/').ToPropertyName().UseWordSeparator('/')}";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace OpenApiGenerator.Core.Naming.Methods;

public enum MethodNamingConvention
{
SimpleOperationId,
MethodAndPath,
OperationIdWithDots,
}

public static class MethodNamingConventionExtensions
{
public static IMethodNameGenerator GetGenerator(this MethodNamingConvention operation)
{
return operation switch
{
MethodNamingConvention.SimpleOperationId => new SimpleOperationIdGenerator(),
MethodNamingConvention.OperationIdWithDots => new OperationIdWithDotsGenerator(),
MethodNamingConvention.MethodAndPath => new MethodAndPathGenerator(),
_ => throw new ArgumentOutOfRangeException(nameof(operation), operation, null),
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Microsoft.OpenApi.Models;
using OpenApiGenerator.Core.Extensions;

namespace OpenApiGenerator.Core.Naming.Methods;

public class OperationIdWithDotsGenerator : IMethodNameGenerator
{
public string? TryGenerate(OpenApiOperation operation, string path, OperationType operationType)
{
operation = operation ?? throw new ArgumentNullException(nameof(operation));

if (operation.OperationId is null ||
!operation.OperationId.Contains('.'))
{
return null;
}

return string.Concat(operation.OperationId
.Split('.')
.Reverse()
.Select(x => x.ToPropertyName()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Microsoft.OpenApi.Models;
using OpenApiGenerator.Core.Extensions;

namespace OpenApiGenerator.Core.Naming.Methods;

public class SimpleOperationIdGenerator : IMethodNameGenerator
{
public string? TryGenerate(OpenApiOperation operation, string path, OperationType operationType)
{
operation = operation ?? throw new ArgumentNullException(nameof(operation));

return operation.OperationId?.ToPropertyName();
}
}
4 changes: 4 additions & 0 deletions src/libs/OpenApiGenerator/OpenApiGenerator.props
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
<CompilerVisibleProperty Include="OpenApiGenerator_GenerateConstructors"/>
<!-- true/false. Default: false -->
<CompilerVisibleProperty Include="OpenApiGenerator_GenerateMethods"/>
<!-- SimpleOperationId/MethodAndPath/OperationIdWithDots. Default: SimpleOperationId -->
<CompilerVisibleProperty Include="OpenApiGenerator_MethodNamingConvention"/>
<!-- SimpleOperationId/MethodAndPath/OperationIdWithDots. Default: MethodAndPath -->
<CompilerVisibleProperty Include="OpenApiGenerator_MethodNamingConventionFallback"/>
<!-- true/false. Default: false. Not Implemented. -->
<CompilerVisibleProperty Include="OpenApiGenerator_GenerateMethodsAsHttpClientExtensions"/>
<!-- true/false. Default: false. Not Implemented. -->
Expand Down
8 changes: 6 additions & 2 deletions src/libs/OpenApiGenerator/OptionsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using OpenApiGenerator.Core.Models;
using OpenApiGenerator.Core.Extensions;
using OpenApiGenerator.Core.Json;
using OpenApiGenerator.Core.Naming.Methods;

namespace OpenApiGenerator;

Expand Down Expand Up @@ -32,6 +33,8 @@ public static Settings GetSettings(

GenerateConstructors: options.GetBoolGlobalOption(nameof(Settings.GenerateConstructors), prefix),
GenerateMethods: options.GetBoolGlobalOption(nameof(Settings.GenerateMethods), prefix),
MethodNamingConvention: options.GetEnumGlobalOption<MethodNamingConvention>(nameof(Settings.MethodNamingConvention), prefix),
MethodNamingConventionFallback: options.GetEnumGlobalOption(nameof(Settings.MethodNamingConventionFallback), prefix, defaultValue: MethodNamingConvention.MethodAndPath),
GenerateMethodsAsHttpClientExtensions: options.GetBoolGlobalOption(nameof(Settings.GenerateMethodsAsHttpClientExtensions), prefix),
GenerateMethodsUsingSystemNetHttpJson: options.GetBoolGlobalOption(nameof(Settings.GenerateMethodsUsingSystemNetHttpJson), prefix),
IncludeOperationIds: (options.GetGlobalOption(nameof(Settings.IncludeOperationIds), prefix)?.Split(';') ??
Expand Down Expand Up @@ -69,14 +72,15 @@ public static bool GetBoolGlobalOption(
public static T GetEnumGlobalOption<T>(
this AnalyzerConfigOptionsProvider provider,
string name,
string? prefix = null) where T : struct, Enum
string? prefix = null,
T defaultValue = default) where T : struct, Enum
{
provider = provider ?? throw new ArgumentNullException(nameof(provider));
name = name ?? throw new ArgumentNullException(nameof(name));

return Enum.TryParse<T>(
provider.GetGlobalOption(name, prefix) ??
$"{default(T):G}",
$"{defaultValue:G}",
ignoreCase: true,
out var value) ? value : default;
}
Expand Down
9 changes: 6 additions & 3 deletions src/tests/OpenApiGenerator.SnapshotTests/Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,12 @@ public Task Replicate(JsonSerializerType jsonSerializerType)
{
return CheckSourceAsync<SdkGenerator>(jsonSerializerType, [
new CustomAdditionalText(
path: H.Resources.ollamacurated_yaml.FileName,
text: H.Resources.ollamacurated_yaml.AsString())
]);
path: H.Resources.replicate_json.FileName,
text: H.Resources.replicate_json.AsString())
], new Dictionary<string, string>
{
["build_property.OpenApiGenerator_MethodNamingConvention"] = "OperationIdWithDots",
});
}

[DataTestMethod]
Expand Down
3 changes: 3 additions & 0 deletions src/tests/OpenApiGenerator.UnitTests/CacheTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Immutable;
using OpenApiGenerator.Core.Models;
using OpenApiGenerator.Core.Naming.Methods;

namespace OpenApiGenerator.UnitTests;

Expand All @@ -15,6 +16,8 @@ public class CacheTests
UseRequiredKeyword: default,
GenerateConstructors: false,
GenerateMethods: false,
MethodNamingConvention: default,
MethodNamingConventionFallback: MethodNamingConvention.MethodAndPath,
GenerateMethodsAsHttpClientExtensions: false,
GenerateMethodsUsingSystemNetHttpJson: false,
IncludeOperationIds: ImmutableArray.Create(["123", "456"]),
Expand Down
13 changes: 8 additions & 5 deletions src/tests/OpenApiGenerator.UnitTests/ClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Runtime.CompilerServices;
using OpenApiGenerator.Core.Generators;
using OpenApiGenerator.Core.Models;
using OpenApiGenerator.Core.Naming.Methods;

namespace OpenApiGenerator.UnitTests;

Expand All @@ -18,6 +19,8 @@ public class ClientTests :
UseRequiredKeyword: default,
GenerateConstructors: false,
GenerateMethods: false,
MethodNamingConvention: default,
MethodNamingConventionFallback: MethodNamingConvention.MethodAndPath,
GenerateMethodsAsHttpClientExtensions: false,
GenerateMethodsUsingSystemNetHttpJson: false,
IncludeOperationIds: [],
Expand Down Expand Up @@ -70,12 +73,12 @@ public Task Ollama()
[TestMethod]
public Task Replicate()
{
var yaml = H.Resources.replicate_json.AsString();
var settings = DefaultSettings;

var models = ClientGeneratorMethods.PrepareData((yaml, settings));
var methods = ClientGeneratorMethods.PrepareData((H.Resources.replicate_json.AsString(), DefaultSettings with
{
MethodNamingConvention = MethodNamingConvention.OperationIdWithDots,
}));

return VerifyAsync(models);
return VerifyAsync(methods);
}

[TestMethod]
Expand Down
9 changes: 5 additions & 4 deletions src/tests/OpenApiGenerator.UnitTests/ModelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Runtime.CompilerServices;
using OpenApiGenerator.Core.Generators;
using OpenApiGenerator.Core.Models;
using OpenApiGenerator.Core.Naming.Methods;

namespace OpenApiGenerator.UnitTests;

Expand All @@ -18,6 +19,8 @@ public class ModelTests :
UseRequiredKeyword: default,
GenerateConstructors: false,
GenerateMethods: false,
MethodNamingConvention: default,
MethodNamingConventionFallback: MethodNamingConvention.MethodAndPath,
GenerateMethodsAsHttpClientExtensions: false,
GenerateMethodsUsingSystemNetHttpJson: false,
IncludeOperationIds: [],
Expand Down Expand Up @@ -72,13 +75,11 @@ public Task Ollama()
[TestMethod]
public Task Replicate()
{
var yaml = H.Resources.replicate_json.AsString();
var settings = DefaultSettings;

var models = ModelGeneratorMethods.PrepareData((yaml, settings));
var models = ModelGeneratorMethods.PrepareData((H.Resources.replicate_json.AsString(), DefaultSettings));

return VerifyAsync(models);
}

//
// [TestMethod]
// public Task GitHub()
Expand Down
Loading

0 comments on commit 6befdfc

Please sign in to comment.