Skip to content

Commit

Permalink
Fix the way requiredness is determined.
Browse files Browse the repository at this point in the history
  • Loading branch information
Corniel committed Feb 26, 2024
1 parent be67c5f commit f93b67c
Show file tree
Hide file tree
Showing 19 changed files with 77 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@ namespace PetShopBoys;
public sealed partial record Address
{
[System.Text.Json.Serialization.JsonPropertyName("street")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public string? Street { get; init; }

[System.Text.Json.Serialization.JsonPropertyName("city")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public string? City { get; init; }

[System.Text.Json.Serialization.JsonPropertyName("state")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public string? State { get; init; }

[System.Text.Json.Serialization.JsonPropertyName("zip")]
[Qowaiv.Validation.DataAnnotations.Mandatory]
[Qowaiv.Validation.DataAnnotations.Optional]
public Qowaiv.PostalCode Zip { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ namespace PetShopBoys;
public sealed partial record ApiResponse
{
[System.Text.Json.Serialization.JsonPropertyName("code")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public int Code { get; init; }

[System.Text.Json.Serialization.JsonPropertyName("type")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public string? Type { get; init; }

[System.Text.Json.Serialization.JsonPropertyName("message")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public string? Message { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ namespace PetShopBoys;
public sealed partial record Category
{
[System.Text.Json.Serialization.JsonPropertyName("id")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public long Id { get; init; }

[System.Text.Json.Serialization.JsonPropertyName("name")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public string? Name { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ namespace PetShopBoys;
public sealed partial record Customer
{
[System.Text.Json.Serialization.JsonPropertyName("id")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public long Id { get; init; }

[System.Text.Json.Serialization.JsonPropertyName("username")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public string? Username { get; init; }

[System.Text.Json.Serialization.JsonPropertyName("address")]
[Qowaiv.Validation.DataAnnotations.Any]
[Qowaiv.Validation.DataAnnotations.Optional]
public PetShopBoys.Address[] Address { get; init; } = System.Array.Empty<PetShopBoys.Address>();
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,27 @@ namespace PetShopBoys;
public sealed partial record Order
{
[System.Text.Json.Serialization.JsonPropertyName("id")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public long Id { get; init; }

[System.Text.Json.Serialization.JsonPropertyName("petId")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public long PetId { get; init; }

[System.Text.Json.Serialization.JsonPropertyName("quantity")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public int Quantity { get; init; }

[System.Text.Json.Serialization.JsonPropertyName("shipDate")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public System.DateTime ShipDate { get; init; }

/// <summary>Order Status</summary>
[System.Text.Json.Serialization.JsonPropertyName("status")]
[Qowaiv.Validation.DataAnnotations.Mandatory]
[Qowaiv.Validation.DataAnnotations.Optional]
public PetShopBoys.Status Status { get; init; }

[System.Text.Json.Serialization.JsonPropertyName("complete")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public bool Complete { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,27 @@ namespace PetShopBoys;
public sealed partial record Pet
{
[System.Text.Json.Serialization.JsonPropertyName("id")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public long Id { get; init; }

[System.Text.Json.Serialization.JsonPropertyName("name")]
[System.ComponentModel.DataAnnotations.Required]
public string? Name { get; init; }

[System.Text.Json.Serialization.JsonPropertyName("category")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public PetShopBoys.Category? Category { get; init; }

[System.Text.Json.Serialization.JsonPropertyName("photoUrls")]
[Qowaiv.Validation.DataAnnotations.Any]
public string[] PhotoUrls { get; init; } = System.Array.Empty<string>();

[System.Text.Json.Serialization.JsonPropertyName("tags")]
[Qowaiv.Validation.DataAnnotations.Any]
[Qowaiv.Validation.DataAnnotations.Optional]
public PetShopBoys.Tag[] Tags { get; init; } = System.Array.Empty<PetShopBoys.Tag>();

/// <summary>pet status in the store</summary>
[System.Text.Json.Serialization.JsonPropertyName("status")]
[Qowaiv.Validation.DataAnnotations.Mandatory]
[Qowaiv.Validation.DataAnnotations.Optional]
public PetShopBoys.Status Status { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace PetShopBoys;
/// <summary>Order Status</summary>
public enum Status
{
[System.Runtime.Serialization.EnumMember(Value = "")]
[System.Runtime.Serialization.EnumMember(Value = null)]
None = 0,

[System.Runtime.Serialization.EnumMember(Value = "placed")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ namespace PetShopBoys;
public sealed partial record Tag
{
[System.Text.Json.Serialization.JsonPropertyName("id")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public long Id { get; init; }

[System.Text.Json.Serialization.JsonPropertyName("name")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public string? Name { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,35 @@ namespace PetShopBoys;
public sealed partial record User
{
[System.Text.Json.Serialization.JsonPropertyName("id")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public long Id { get; init; }

[System.Text.Json.Serialization.JsonPropertyName("username")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public string? Username { get; init; }

[System.Text.Json.Serialization.JsonPropertyName("firstName")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public string? FirstName { get; init; }

[System.Text.Json.Serialization.JsonPropertyName("lastName")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public string? LastName { get; init; }

[System.Text.Json.Serialization.JsonPropertyName("email")]
[Qowaiv.Validation.DataAnnotations.Mandatory]
[Qowaiv.Validation.DataAnnotations.Optional]
public Qowaiv.EmailAddress Email { get; init; }

[System.Text.Json.Serialization.JsonPropertyName("password")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public string? Password { get; init; }

[System.Text.Json.Serialization.JsonPropertyName("phone")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public string? Phone { get; init; }

/// <summary>User Status</summary>
[System.Text.Json.Serialization.JsonPropertyName("userStatus")]
[System.ComponentModel.DataAnnotations.Required]
[Qowaiv.Validation.DataAnnotations.Optional]
public int UserStatus { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ protected virtual IEnumerable<AttributeInfo> DecorateProperty(Property property,
{
Guard.NotNull(property);

if (!schema.Schema.Nullable)
if (property.IsRequired)
{
if (property.PropertyType.IsArray)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public partial class OpenApiTypeResolver
}

[Pure]
private Property? ResolveProperty(ResolveOpenApiSchema schema)
private Property? ResolveProperty(ResolveOpenApiSchema schema, ISet<string> required)
{
if (schema.Model is Class @class && Resolve(schema) is { } propertyType)
{
Expand All @@ -47,7 +47,8 @@ public partial class OpenApiTypeResolver
ResolveAccess(schema),
attributes,
documentation,
nullable);
nullable,
required.Contains(schema.Path.Last));

attributes.AddRange(DecorateProperty(prop, schema));
return prop;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ _ when schema.AllOf.Any() => ResolveAllOf(schema),
}
if (!fields.Exists(IsNone))
{
fields.Insert(0, new(type, "None", 0, new[] { AttributeInfo.System_Runtime_Serialization_EnumMember(string.Empty) }));
fields.Insert(0, new(type, "None", 0, [AttributeInfo.System_Runtime_Serialization_EnumMember(null)]));
}

return type;
Expand Down Expand Up @@ -160,15 +160,16 @@ static bool IsNone(EnumerationField field)

schema = schema.WithModel(classType);

properties.AddRange(schema.Properties.Select(ResolveProperty).OfType<Property>());
properties.AddRange(schema.Properties.Select(p => ResolveProperty(p, schema.Schema.Required)).OfType<Property>());

if (schema.AllOf.Count > 1)
{
foreach (var reference in schema.AllOf)
{
schema = schema.With(reference);

properties.AddRange(reference.OpenApiProperties().Select(prop => ResolveProperty(schema.With(prop))).OfType<Property>());
properties.AddRange(reference.OpenApiProperties()
.Select(prop => ResolveProperty(schema.With(prop), schema.Required))
.OfType<Property>());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<Version>0.0.1-alpha-005</Version>
<Version>0.0.1-alpha-007</Version>
<PackageId>Qowaiv.CodeGeneration.OpenApi</PackageId>
<PackageReleaseNotes>
ToBeReleased
Expand Down
11 changes: 7 additions & 4 deletions src/Qowaiv.CodeGeneration.OpenApi/ResolveOpenApiSchema.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ public ResolveOpenApiSchema(OpenApiPath path, OpenApiSchema schema, Type? model,
public string? ReferenceId => Reference?.Id;

/// <inheritdoc cref="OpenApiSchema.AllOf"/>
public IList<OpenApiSchema> AllOf => Schema?.AllOf ?? Array.Empty<OpenApiSchema>();
public IList<OpenApiSchema> AllOf => Schema?.AllOf ?? [];

/// <inheritdoc cref="OpenApiSchema.AnyOf"/>
public IList<OpenApiSchema> AnyOf => Schema?.AnyOf ?? Array.Empty<OpenApiSchema>();
public IList<OpenApiSchema> AnyOf => Schema?.AnyOf ?? [];

/// <inheritdoc cref="OpenApiSchema.OneOf"/>
public IEnumerable<ResolveOpenApiSchema> OneOf
Expand All @@ -34,15 +34,18 @@ public IEnumerable<ResolveOpenApiSchema> OneOf
{
var self = this;
return Schema?.OneOf?.Select(self.With)
?? Array.Empty<ResolveOpenApiSchema>();
?? [];
}
}

/// <inheritdoc cref="OpenApiSchema.Description"/>
public string? Description => Schema?.Description;

/// <inheritdoc cref="OpenApiSchema.Enum"/>
public IList<IOpenApiAny> Enum => Schema?.Enum ?? Array.Empty<IOpenApiAny>();
public IList<IOpenApiAny> Enum => Schema?.Enum ?? [];

/// <inheritdoc cref="OpenApiSchema.Required"/>
public ISet<string> Required => Schema?.Required ?? new HashSet<string>();

/// <inheritdoc cref="OpenApiSchema.Format"/>
public string? Format => Schema?.Format;
Expand Down
2 changes: 1 addition & 1 deletion src/Qowaiv.CodeGeneration/Qowaiv.CodeGeneration.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<Version>0.0.1-alpha-005</Version>
<Version>0.0.1-alpha-007</Version>
<PackageId>Qowaiv.CodeGeneration</PackageId>
<PackageReleaseNotes>
ToBeReleased
Expand Down
7 changes: 6 additions & 1 deletion src/Qowaiv.CodeGeneration/Syntax/Property.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ public Property(
PropertyAccess access,
IReadOnlyCollection<AttributeInfo>? attributes = null,
XmlDocumentation? documentation = null,
bool nullable = false)
bool nullable = false,
bool required = false)
{
Name = Guard.NotNullOrEmpty(name);
PropertyType = Guard.NotNull(propertyType);
Expand All @@ -24,13 +25,17 @@ public Property(
AttributeInfos = attributes ?? Array.Empty<AttributeInfo>();
Documentation = documentation ?? new XmlDocumentation();
IsNullable = nullable;
IsRequired = required;
}

public XmlDocumentation Documentation { get; }

/// <inheritdoc />
public override string Name { get; }

/// <summary>True if the property is required.</summary>
public bool IsRequired { get; }

/// <inheritdoc />
public override Type PropertyType { get; }

Expand Down
11 changes: 10 additions & 1 deletion src/Qowaiv.CodeGeneration/Syntax/XmlDocumentation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public sealed class XmlDocumentation : Code
/// <summary>The collection with parameters.</summary>
public IReadOnlyDictionary<string, string> Params { get; init; } = new Dictionary<string, string>();

private static readonly string[] NewLineChars = ["\r\n", "\n"];

/// <inheritdoc />
public void WriteTo(CSharpWriter writer)
{
Expand All @@ -33,7 +35,7 @@ private static void WriteText(CSharpWriter writer, string? text, string tag)
{
if (text is { Length: > 0 })
{
var lines = text.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None);
var lines = Trim(text.Split(NewLineChars, StringSplitOptions.None));

if (lines.Length == 1)
{
Expand All @@ -51,6 +53,13 @@ private static void WriteText(CSharpWriter writer, string? text, string tag)
}
}

[Pure]
private static string[] Trim(string[] lines)
=> lines
.SkipWhile(l => l.Trim().Length == 0)
.TakeWhile(l => l.Trim().Length > 0)
.ToArray();

[Pure]
private static string Escape(string s) => new XText(s).ToString();
}
8 changes: 4 additions & 4 deletions src/Qowaiv.CodeGeneration/Types/AttributeInfo.Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public partial class AttributeInfo
public static readonly AttributeInfo Qowaiv_Validation_DataAnnotations_Mandatory = new(typeof(Qowaiv.Validation.DataAnnotations.MandatoryAttribute));

public static readonly AttributeInfo Qowaiv_Validation_DataAnnotations_Optional = new(typeof(Qowaiv.Validation.DataAnnotations.OptionalAttribute));

public static readonly AttributeInfo System_ComponentModel_DataAnnotations_Required = new(typeof(System.ComponentModel.DataAnnotations.RequiredAttribute));

public static readonly AttributeInfo System_Flags = new(typeof(System.FlagsAttribute));
Expand Down Expand Up @@ -46,12 +46,12 @@ public static AttributeInfo Qowaiv_Validation_DataAnnotations_MultipleOf(double
[Pure]
public static AttributeInfo System_Text_Json_Serialization_JsonDerivedTypeAttribute(Type type)
=> new(typeof(System.Text.Json.Serialization.JsonDerivedTypeAttribute), new object[] { type });

[Pure]
public static AttributeInfo System_Text_Json_Serialization_JsonPropertyName(string name)
=> new(typeof(System.Text.Json.Serialization.JsonPropertyNameAttribute), new[] { name });

[Pure]
public static AttributeInfo System_Runtime_Serialization_EnumMember(string value)
=> new(typeof(System.Runtime.Serialization.EnumMemberAttribute), null, KeyValuePair.Create("Value", (object) value));
public static AttributeInfo System_Runtime_Serialization_EnumMember(string? value)
=> new(typeof(System.Runtime.Serialization.EnumMemberAttribute), null, KeyValuePair.Create("Value", (object?)value));
}
Loading

0 comments on commit f93b67c

Please sign in to comment.