Skip to content

Commit

Permalink
task: updated attribute classes
Browse files Browse the repository at this point in the history
  • Loading branch information
dtanglr committed Jan 21, 2024
1 parent f89c463 commit 494f9fc
Show file tree
Hide file tree
Showing 20 changed files with 180 additions and 41 deletions.
13 changes: 10 additions & 3 deletions src/Primitively.Abstractions/ByteAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,18 @@ namespace Primitively;
/// </summary>
[AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
[Conditional(Constants.ConditionalCompilationSymbol)]
public sealed class ByteAttribute : Attribute
public sealed class ByteAttribute : Attribute, IIntegerAttribute<byte>
{
/// <inheritdoc/>
public bool ImplementIValidatableObject { get; set; }

public byte Minimum { get; set; }
/// <inheritdoc/>
public byte Minimum { get; set; } = byte.MinValue;

public byte Maximum { get; set; }
/// <inheritdoc/>
public byte Maximum { get; set; } = byte.MaxValue;

object IIntegerAttribute.Minimum { get => Minimum; }

object IIntegerAttribute.Maximum { get => Maximum; }
}
3 changes: 2 additions & 1 deletion src/Primitively.Abstractions/DateOnlyAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ namespace Primitively;
/// </summary>
[AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
[Conditional(Constants.ConditionalCompilationSymbol)]
public sealed class DateOnlyAttribute : Attribute
public sealed class DateOnlyAttribute : Attribute, IPimitivelyAttribute
{
/// <inheritdoc/>
public bool ImplementIValidatableObject { get; set; }
}
7 changes: 4 additions & 3 deletions src/Primitively.Abstractions/GuidAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Primitively;
/// </summary>
[AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
[Conditional(Constants.ConditionalCompilationSymbol)]
public sealed class GuidAttribute : Attribute
public sealed class GuidAttribute : Attribute, IPimitivelyAttribute
{
public GuidAttribute()
{
Expand All @@ -19,7 +19,8 @@ public GuidAttribute(Specifier specifier)
Specifier = specifier;
}

public Specifier Specifier { get; }

/// <inheritdoc/>
public bool ImplementIValidatableObject { get; set; }

public Specifier Specifier { get; }
}
17 changes: 17 additions & 0 deletions src/Primitively.Abstractions/IIntegerAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace Primitively;

/// <summary>
/// An interface used to provide a default contract to Primitively attributes that are used to source generate integer data types.
/// </summary>
public interface IIntegerAttribute : IPimitivelyAttribute
{
/// <summary>
/// The minimum value of the Primitively integer type
/// </summary>
object Minimum { get; }

/// <summary>
/// The maximum value of the Primitively integer type
/// </summary>
object Maximum { get; }
}
18 changes: 18 additions & 0 deletions src/Primitively.Abstractions/IIntegerAttribute`1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace Primitively;

/// <summary>
/// An interface used to provide a default contract to Primitively attributes that are used to source generate integer data types.
/// </summary>
/// <typeparam name="T">The .net integer type that the Primitively type encapsulates</typeparam>
public interface IIntegerAttribute<T> : IIntegerAttribute where T : struct, IComparable, IComparable<T>, IConvertible, IEquatable<T>, IFormattable
{
/// <summary>
/// The minimum value of the Primitively type
/// </summary>
new T Minimum { get; set; }

/// <summary>
/// The maximum value of the Primitively type
/// </summary>
new T Maximum { get; set; }
}
17 changes: 17 additions & 0 deletions src/Primitively.Abstractions/IPimitivelyAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.ComponentModel.DataAnnotations;

namespace Primitively;

/// <summary>
/// The interface that is implemented by all the Primitively attributes that invoke source code generation
/// </summary>
public interface IPimitivelyAttribute
{
/// <summary>
/// When set to true; will output a Primitively type that implements the <see cref="IValidatableObject"/>
/// </summary>
/// <remarks>
/// For more information about validation: <see href="https://learn.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-8.0#ivalidatableobject"/>
/// </remarks>
bool ImplementIValidatableObject { get; set; }
}
11 changes: 6 additions & 5 deletions src/Primitively.Abstractions/IntAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ namespace Primitively;
/// </summary>
[AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
[Conditional(Constants.ConditionalCompilationSymbol)]
public sealed class IntAttribute : Attribute
public sealed class IntAttribute : Attribute, IIntegerAttribute<int>
{
/// <inheritdoc/>
public bool ImplementIValidatableObject { get; set; }

public int Minimum { get; set; }

public int Maximum { get; set; }
public int Minimum { get; set; } = int.MinValue;
public int Maximum { get; set; } = int.MaxValue;
object IIntegerAttribute.Minimum { get => Minimum; }
object IIntegerAttribute.Maximum { get => Maximum; }
}
13 changes: 10 additions & 3 deletions src/Primitively.Abstractions/LongAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,18 @@ namespace Primitively;
/// </summary>
[AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
[Conditional(Constants.ConditionalCompilationSymbol)]
public sealed class LongAttribute : Attribute
public sealed class LongAttribute : Attribute, IIntegerAttribute<long>
{
/// <inheritdoc/>
public bool ImplementIValidatableObject { get; set; }

public long Minimum { get; set; }
/// <inheritdoc/>
public long Minimum { get; set; } = long.MinValue;

public long Maximum { get; set; }
/// <inheritdoc/>
public long Maximum { get; set; } = long.MaxValue;

object IIntegerAttribute.Minimum { get => Minimum; }

object IIntegerAttribute.Maximum { get => Maximum; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
</ItemGroup>

</Project>
13 changes: 10 additions & 3 deletions src/Primitively.Abstractions/SByteAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,18 @@ namespace Primitively;
/// </summary>
[AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
[Conditional(Constants.ConditionalCompilationSymbol)]
public sealed class SByteAttribute : Attribute
public sealed class SByteAttribute : Attribute, IIntegerAttribute<sbyte>
{
/// <inheritdoc/>
public bool ImplementIValidatableObject { get; set; }

public sbyte Minimum { get; set; }
/// <inheritdoc/>
public sbyte Minimum { get; set; } = sbyte.MinValue;

public sbyte Maximum { get; set; }
/// <inheritdoc/>
public sbyte Maximum { get; set; } = sbyte.MaxValue;

object IIntegerAttribute.Minimum { get => Minimum; }

object IIntegerAttribute.Maximum { get => Maximum; }
}
13 changes: 10 additions & 3 deletions src/Primitively.Abstractions/ShortAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,18 @@ namespace Primitively;
/// </summary>
[AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
[Conditional(Constants.ConditionalCompilationSymbol)]
public sealed class ShortAttribute : Attribute
public sealed class ShortAttribute : Attribute, IIntegerAttribute<short>
{
/// <inheritdoc/>
public bool ImplementIValidatableObject { get; set; }

public short Minimum { get; set; }
/// <inheritdoc/>
public short Minimum { get; set; } = short.MinValue;

public short Maximum { get; set; }
/// <inheritdoc/>
public short Maximum { get; set; } = short.MaxValue;

object IIntegerAttribute.Minimum { get => Minimum; }

object IIntegerAttribute.Maximum { get => Maximum; }
}
11 changes: 7 additions & 4 deletions src/Primitively.Abstractions/StringAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
using System.Diagnostics;

#nullable enable

namespace Primitively;

/// <summary>
/// Make a readonly record struct that encapsulates a String primitive value
/// </summary>
[AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
[Conditional(Constants.ConditionalCompilationSymbol)]
public sealed class StringAttribute : Attribute
public sealed class StringAttribute : Attribute, IPimitivelyAttribute
{
/// <summary>
/// Make a readonly record struct that encapsulates a
Expand Down Expand Up @@ -41,12 +43,13 @@ public StringAttribute(int minLength, int maxLength)
MaxLength = maxLength;
}

/// <inheritdoc/>
public bool ImplementIValidatableObject { get; set; }
public int MinLength { get; }
public int MaxLength { get; }
#nullable enable
public string? Pattern { get; set; }
public string? Example { get; set; }
public string? Format { get; set; }
#nullable disable
public bool ImplementIValidatableObject { get; set; }
}

#nullable disable
23 changes: 23 additions & 0 deletions src/Primitively.Abstractions/TypeExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,30 @@
namespace Primitively;

/// <summary>
/// A static class to provide extension methods on the <see cref="Type"/> class
/// </summary>
/// <remarks>
/// This provides the method <see cref="IsAssignableTo(Type, Type)"/> which is missing from .netStandard
/// </remarks>
public static class TypeExtensions
{
/// <summary>
/// Determines whether the current type can be assigned to a variable of the specified targetType.
/// </summary>
/// <param name="type">The current type</param>
/// <param name="baseType">The type to compare with the current type.</param>
/// <returns>
/// true if any of the following conditions is true: - The current instance and targetType
/// represent the same type. - The current type is derived either directly or indirectly
/// from targetType.The current type is derived directly from targetType if it inherits
/// from targetType; the current type is derived indirectly from targetType if it
/// inherits from a succession of one or more classes that inherit from targetType.
/// - targetType is an interface that the current type implements. - The current
/// type is a generic type parameter, and targetType represents one of the constraints
/// of the current type. - The current type represents a value type, and targetType
/// represents <see cref="Nullable{c}"/> (Nullable(Of c) in Visual Basic). false if none of these
/// conditions are true, or if targetType is null.
/// </returns>
public static bool IsAssignableTo(this Type type, Type baseType)
{
return baseType.IsAssignableFrom(type);
Expand Down
13 changes: 10 additions & 3 deletions src/Primitively.Abstractions/UIntAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,18 @@ namespace Primitively;
/// </summary>
[AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
[Conditional(Constants.ConditionalCompilationSymbol)]
public sealed class UIntAttribute : Attribute
public sealed class UIntAttribute : Attribute, IIntegerAttribute<uint>
{
/// <inheritdoc/>
public bool ImplementIValidatableObject { get; set; }

public uint Minimum { get; set; }
/// <inheritdoc/>
public uint Minimum { get; set; } = uint.MinValue;

public uint Maximum { get; set; }
/// <inheritdoc/>
public uint Maximum { get; set; } = uint.MaxValue;

object IIntegerAttribute.Minimum { get => Minimum; }

object IIntegerAttribute.Maximum { get => Maximum; }
}
13 changes: 10 additions & 3 deletions src/Primitively.Abstractions/ULongAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,18 @@ namespace Primitively;
/// </summary>
[AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
[Conditional(Constants.ConditionalCompilationSymbol)]
public sealed class ULongAttribute : Attribute
public sealed class ULongAttribute : Attribute, IIntegerAttribute<ulong>
{
/// <inheritdoc/>
public bool ImplementIValidatableObject { get; set; }

public ulong Minimum { get; set; }
/// <inheritdoc/>
public ulong Minimum { get; set; } = ulong.MinValue;

public ulong Maximum { get; set; }
/// <inheritdoc/>
public ulong Maximum { get; set; } = ulong.MaxValue;

object IIntegerAttribute.Minimum { get => Minimum; }

object IIntegerAttribute.Maximum { get => Maximum; }
}
13 changes: 10 additions & 3 deletions src/Primitively.Abstractions/UShortAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,18 @@ namespace Primitively;
/// </summary>
[AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
[Conditional(Constants.ConditionalCompilationSymbol)]
public sealed class UShortAttribute : Attribute
public sealed class UShortAttribute : Attribute, IIntegerAttribute<ushort>
{
/// <inheritdoc/>
public bool ImplementIValidatableObject { get; set; }

public ushort Minimum { get; set; }
/// <inheritdoc/>
public ushort Minimum { get; set; } = ushort.MinValue;

public ushort Maximum { get; set; }
/// <inheritdoc/>
public ushort Maximum { get; set; } = ushort.MaxValue;

object IIntegerAttribute.Minimum { get => Minimum; }

object IIntegerAttribute.Maximum { get => Maximum; }
}
2 changes: 2 additions & 0 deletions src/Primitively/Parsers/DateOnlyParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ private static bool TryParseNamedArguments(AttributeData attributeData, RecordSt
case nameof(DateOnlyAttribute.ImplementIValidatableObject):
recordStructData.ImplementIValidatableObject = (bool?)value ?? false;
break;
default:
break;
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/Primitively/Parsers/GuidParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ private static bool TryParseNamedArguments(AttributeData attributeData, RecordSt
case nameof(GuidAttribute.ImplementIValidatableObject):
recordStructData.ImplementIValidatableObject = (bool?)value ?? false;
break;
default:
break;
}
}

Expand Down
12 changes: 7 additions & 5 deletions src/Primitively/Parsers/IntegerParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,19 @@ private static bool TryParseNamedArguments(AttributeData attributeData, RecordSt

switch (key)
{
case "ImplementIValidatableObject":
case nameof(IIntegerAttribute.ImplementIValidatableObject):
recordStructData.ImplementIValidatableObject = (bool?)value ?? false;
break;
case "Minimum":
recordStructData.Minimum = decimal.Parse(value?.ToString() ?? "0");
case nameof(IIntegerAttribute.Minimum):
recordStructData.Minimum = decimal.TryParse(value?.ToString(), out var minimum) ? minimum : recordStructData.Minimum;
rangeHasChanged = true;
break;
case "Maximum":
recordStructData.Maximum = decimal.Parse(value?.ToString() ?? "0");
case nameof(IIntegerAttribute.Maximum):
recordStructData.Maximum = decimal.TryParse(value?.ToString(), out var maximum) ? maximum : recordStructData.Maximum;
rangeHasChanged = true;
break;
default:
break;
}
}

Expand Down
6 changes: 4 additions & 2 deletions src/Primitively/Parsers/StringParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ private static bool TryParseNamedArguments(AttributeData attributeData, RecordSt

switch (key)
{
case nameof(StringAttribute.ImplementIValidatableObject):
recordStructData.ImplementIValidatableObject = (bool?)value ?? false;
break;
case nameof(StringAttribute.Example):
recordStructData.Example = (string?)value;
break;
Expand All @@ -94,8 +97,7 @@ private static bool TryParseNamedArguments(AttributeData attributeData, RecordSt
case nameof(StringAttribute.Pattern):
recordStructData.Pattern = (string?)value;
break;
case nameof(StringAttribute.ImplementIValidatableObject):
recordStructData.ImplementIValidatableObject = (bool?)value ?? false;
default:
break;
}
}
Expand Down

0 comments on commit 494f9fc

Please sign in to comment.