Skip to content

Commit

Permalink
Fix code generation enum handling (#836)
Browse files Browse the repository at this point in the history
Signed-off-by: Thomas Farr <[email protected]>
  • Loading branch information
Xtansia authored Oct 21, 2024
1 parent e16d034 commit 67a70ab
Show file tree
Hide file tree
Showing 5 changed files with 611 additions and 434 deletions.
54 changes: 22 additions & 32 deletions src/ApiGenerator/Generator/ApiEndpointFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,7 @@ Action<string, bool> trackEnumToGenerate

Body body = null;
if (variants.Select(v => v.Operation.RequestBody).FirstOrDefault() is { } requestBody)
{
body = new Body { Description = GetDescription(requestBody)?.SanitizeDescription(), Required = requestBody.IsRequired };
}

return new ApiEndpoint
{
Expand Down Expand Up @@ -175,11 +173,11 @@ Action<string, bool> trackEnumToGenerate
List<PathParameter> paramCombo
)
{
if (i == paramCount) return new[] { (variantHttpPath, paramCombo) };
if (i == paramCount) return [(variantHttpPath, paramCombo)];

var originalParameter = pathParams[i];
var overloads = !originalParameter.IsOverloaded()
? new[] { (variantHttpPath, new PathParameter(originalParameter)) }
? [(variantHttpPath, new PathParameter(originalParameter))]
: originalParameter.Schema.AnyOf
.Select(overload =>
(
Expand All @@ -188,7 +186,7 @@ List<PathParameter> paramCombo
)
);

return overloads.SelectMany(o => GenerateVariants(o.HttpPath, i + 1, new List<PathParameter>(paramCombo) { o.PathParameter }));
return overloads.SelectMany(o => GenerateVariants(o.HttpPath, i + 1, [..paramCombo, o.PathParameter]));
}
}

Expand Down Expand Up @@ -227,36 +225,31 @@ private static string GetOpenSearchType(JsonSchema schema, Action<string, bool>
var schemaKey = ((IJsonReference)schema).ReferencePath?.Split('/').Last();
schema = schema.ActualSchema;

if (schemaKey != null && schema.IsEnum())
{
trackEnumToGenerate(schemaKey, isListContext);
return CsharpNames.GetEnumName(schemaKey) + "?";
}

if (schema.OneOf.Count > 0 || schema.AnyOf.Count > 0)
{
var oneOf = (schema.OneOf.Count > 0 ? schema.OneOf : schema.AnyOf).ToArray();

if (oneOf.Length == 2)
{
var first = GetOpenSearchType(oneOf[0], trackEnumToGenerate);
var second = GetOpenSearchType(oneOf[1], trackEnumToGenerate);
if (first.EndsWith("?")) return first;
if (first == second) return first;

return (first, second) switch
{
(_, "list") => second,
("boolean", "string") => first,
("number", _) => "string",
(_, "number") => "string",
(_, _) => throw new Exception($"Unable to determine type of: {first} and {second}")
};
}
if (oneOf.Length != 2) throw new Exception("Unable to determine type of oneOf");

throw new Exception("Unable to determine type of oneOf");
}
var first = GetOpenSearchType(oneOf[0], trackEnumToGenerate);
var second = GetOpenSearchType(oneOf[1], trackEnumToGenerate);
if (first.EndsWith("?")) return first;
if (first == second) return first;

var enumOptions = schema.Enumeration.Where(e => e != null).Select(e => e.ToString()).ToList();

if (schemaKey != null && schema.Type == JsonObjectType.String && enumOptions.Count > 0)
{
trackEnumToGenerate(schemaKey, isListContext);
return CsharpNames.GetEnumName(schemaKey) + "?";
return (first, second) switch
{
(_, "list") => second,
("boolean", "string") => first,
("number", _) => "string",
(_, "number") => "string",
(_, _) => throw new Exception($"Unable to determine type of: {first} and {second}")
};
}

if (schema.Type == JsonObjectType.Array && (schema.Item?.HasReference ?? false))
Expand Down Expand Up @@ -340,8 +333,5 @@ private static Version CoerceVersion(string s) =>
2 => new Version($"{s}.0"),
_ => new Version(s),
};

private static object GetExtension(this IJsonExtensionObject schema, string key) =>
schema.ExtensionData?.TryGetValue(key, out var value) ?? false ? value : null;
}
}
2 changes: 1 addition & 1 deletion src/ApiGenerator/Generator/ApiGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public static async Task<RestApiSpec> CreateRestApiSpecModel(CancellationToken t
{
Name = CsharpNames.GetEnumName(kvp.Key),
IsFlag = kvp.Value,
Options = document.Components.Schemas[kvp.Key].Enumeration.Where(e => e != null).Select(e => e.ToString()).ToImmutableList()
Options = document.Components.Schemas[kvp.Key].GetEnumValues()
})
.OrderBy(e => e.Name)
.ToImmutableList();
Expand Down
49 changes: 49 additions & 0 deletions src/ApiGenerator/Generator/OpenApiUtils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using NJsonSchema;

namespace ApiGenerator.Generator;

public static class OpenApiUtils
{
public static bool HasOneOf(this JsonSchema schema) => schema.OneOf.Count > 0;

public static bool IsEnum(this JsonSchema schema)
{
if (schema.Type == JsonObjectType.String)
return schema.Enumeration.Count > 0 || schema.Const<string>() != null;

return schema.HasOneOf() && schema.OneOf.All(IsEnum);
}

public static IImmutableList<string> GetEnumValues(this JsonSchema schema)
{
var values = new SortedSet<string>();
Visit(schema);
return values.ToImmutableList();

void Visit(JsonSchema s)
{
if (s.HasOneOf())
foreach (var oneOf in schema.OneOf) Visit(oneOf);
else if (s.Enumeration.Count > 0)
foreach (var v in s.Enumeration.Where(v => v != null)) values.Add((string) v);
else if (s.Const<string>() != null)
values.Add(s.Const<string>());
}
}

public static T Const<T>(this JsonSchema schema) where T: class =>
schema.GetExtension("const") as T;

public static object GetExtension(this IJsonExtensionObject schema, string key) =>
schema.ExtensionData?.TryGetValue(key, out var value) ?? false ? value : null;
}
Loading

0 comments on commit 67a70ab

Please sign in to comment.