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

add code enhancement and tests, also some fixes #15

Merged
merged 6 commits into from
Apr 27, 2024
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
11 changes: 10 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -287,4 +287,13 @@ dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case

# IDE0290: Use primary constructor
dotnet_diagnostic.IDE0290.severity = none
dotnet_diagnostic.IDE0290.severity = none

# MA0017: Abstract types should not have public or internal constructors
dotnet_diagnostic.MA0017.severity = none

# MA0018: Do not declare static members on generic types (deprecated; use CA1000 instead)
dotnet_diagnostic.MA0018.severity = none

# MA0154: Use langword in XML comment
dotnet_diagnostic.MA0154.severity = none
8 changes: 5 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,19 @@ jobs:
steps:

- name: Cancel previous builds in PR
uses: styfle/cancel-workflow-action@0.9.1
uses: styfle/cancel-workflow-action@0.12.1

- name: 'Checkoud Code'
- name: 'Checkout Code'
uses: actions/checkout@v4
with:
fetch-depth: 0 # avoid shallow clone so nbgv can do its work.

- name: 'Install .NET SDK'
uses: actions/setup-dotnet@v3
uses: actions/setup-dotnet@v4
with:
global-json-file: ./global.json
#dotnet-version: '9.x'
#dotnet-quality: 'preview'

- name: Versioning
uses: dotnet/nbgv@master
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
</PropertyGroup>

<PropertyGroup Label="Project Defaults">
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
<TargetFrameworks>net7.0;net8.0;net9.0</TargetFrameworks>
</PropertyGroup>

<PropertyGroup Label="Package">
Expand Down
4 changes: 4 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
</PackageVersion>
<PackageVersion Include="Microsoft.CodeAnalysis.Common" Version="4.5.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
<PackageVersion Include="Meziantou.Analyzer" Version="2.0.149">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageVersion>
</ItemGroup>

<ItemGroup Label="DevOps">
Expand Down
3 changes: 1 addition & 2 deletions global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{
"sdk": {
"version": "8.0.100"
"version": "9.0.100-preview.3.24204.13"
}
}

7 changes: 7 additions & 0 deletions src/StrongOf.AspNetCore/StrongOf.AspNetCore.csproj
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup Label="Analyzers">
<PackageReference Include="Meziantou.Analyzer">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>

<PropertyGroup Label="Package">
<IsPackable>true</IsPackable>
<PackageReadmeFile>readme.md</PackageReadmeFile>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup Label="Analyzers">
<PackageReference Include="Meziantou.Analyzer">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>

<PropertyGroup Label="Package">
<IsPackable>true</IsPackable>
<PackageReadmeFile>readme.md</PackageReadmeFile>
Expand All @@ -16,6 +23,6 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\StrongOf\StrongOf.csproj" />
<ProjectReference Include="..\StrongOf\StrongOf.csproj" />
</ItemGroup>
</Project>
21 changes: 13 additions & 8 deletions src/StrongOf.FluentValidation/StrongStringValidators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public static class StrongStringValidators
/// <returns>The rule builder options.</returns>
public static IRuleBuilderOptions<T, TStrong?> HasMaximumLength<T, TStrong>(this IRuleBuilder<T, TStrong?> rule, int maxLength)
where TStrong : StrongString<TStrong>
=> rule.Must(content => content?.Value is null ? true : content.Value.Length <= maxLength);
=> rule.Must(content => content?.Value is null || content.Value.Length <= maxLength);

/// <summary>
/// Validates that the strong string matches a regular expression.
Expand Down Expand Up @@ -94,15 +94,20 @@ public static class StrongStringValidators
}

/// <summary>
/// Validates that the strong string only contains allowed characters.
/// Specifies that the value being validated must only contain characters from the specified collection.
/// </summary>
/// <typeparam name="T">The type of the object being validated.</typeparam>
/// <typeparam name="TStrong">The type of the strong string.</typeparam>
/// <typeparam name="T">The type of the parent object being validated.</typeparam>
/// <typeparam name="TStrong">The type of the strong string being validated.</typeparam>
/// <param name="rule">The rule builder.</param>
/// <param name="chars">The set of allowed characters.</param>
/// <param name="messagePattern">The message pattern to use if the validation fails.</param>
/// <param name="chars">The collection of allowed characters.</param>
/// <param name="messagePattern">The pattern used to format the error message if validation fails.</param>
/// <param name="formatProvider">An optional <see cref="IFormatProvider"/> that supplies culture-specific formatting information.</param>
/// <returns>The rule builder options.</returns>
public static IRuleBuilderOptionsConditions<T, TStrong?> AllowedChars<T, TStrong>(this IRuleBuilder<T, TStrong?> rule, HashSet<char> chars, string messagePattern)
/// <remarks>
/// This method adds a custom validation rule to the rule builder that checks if the value being validated contains only characters from the specified collection.
/// If the validation fails, an error message is added to the validation context using the provided message pattern.
/// </remarks>
public static IRuleBuilderOptionsConditions<T, TStrong?> AllowedChars<T, TStrong>(this IRuleBuilder<T, TStrong?> rule, ICollection<char> chars, string messagePattern, IFormatProvider? formatProvider = null)
where TStrong : StrongString<TStrong>
{
return rule.Custom((topic, context) =>
Expand All @@ -111,7 +116,7 @@ public static class StrongStringValidators
{
if (strong.ContainsInvalidChars(chars, out ICollection<char>? invalidChars))
{
context.AddFailure(string.Format(messagePattern, string.Concat(invalidChars)));
context.AddFailure(string.Format(formatProvider, messagePattern, string.Concat(invalidChars)));
}
}
});
Expand Down
5 changes: 3 additions & 2 deletions src/StrongOf.Json/StrongDateTimeOffsetJsonConverter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text.Json;
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace StrongOf.Json;
Expand Down Expand Up @@ -35,5 +36,5 @@ public class StrongDateTimeOffsetJsonConverter<TStrong> : JsonConverter<TStrong>
/// <param name="strong">The value to write.</param>
/// <param name="options">Options to control the serializer behavior during writing.</param>
public override void Write(Utf8JsonWriter writer, TStrong strong, JsonSerializerOptions options)
=> writer.WriteStringValue(strong.Value.ToString());
=> writer.WriteStringValue(strong.Value.ToString(CultureInfo.InvariantCulture));
}
5 changes: 3 additions & 2 deletions src/StrongOf.Json/StrongInt32JsonConverter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text.Json;
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace StrongOf.Json;
Expand Down Expand Up @@ -35,5 +36,5 @@ public class StrongInt32JsonConverter<TStrong> : JsonConverter<TStrong>
/// <param name="strong">The value to write.</param>
/// <param name="options">Options to control the serializer behavior during writing.</param>
public override void Write(Utf8JsonWriter writer, TStrong strong, JsonSerializerOptions options)
=> writer.WriteStringValue(strong.Value.ToString());
=> writer.WriteStringValue(strong.Value.ToString(CultureInfo.InvariantCulture));
}
5 changes: 3 additions & 2 deletions src/StrongOf.Json/StrongInt64JsonConverter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text.Json;
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace StrongOf.Json;
Expand Down Expand Up @@ -35,5 +36,5 @@ public class StrongInt64JsonConverter<TStrong> : JsonConverter<TStrong>
/// <param name="strong">The value to write.</param>
/// <param name="options">Options to control the serializer behavior during writing.</param>
public override void Write(Utf8JsonWriter writer, TStrong strong, JsonSerializerOptions options)
=> writer.WriteStringValue(strong.Value.ToString());
=> writer.WriteStringValue(strong.Value.ToString(CultureInfo.InvariantCulture));
}
7 changes: 7 additions & 0 deletions src/StrongOf.Json/StrongOf.Json.csproj
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup Label="Analyzers">
<PackageReference Include="Meziantou.Analyzer">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>

<PropertyGroup Label="Package">
<IsPackable>true</IsPackable>
<PackageReadmeFile>readme.md</PackageReadmeFile>
Expand Down
177 changes: 177 additions & 0 deletions src/StrongOf/StrongChar.Operators.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
namespace StrongOf;

public abstract partial class StrongChar<TStrong>
{
/// <summary>
/// Determines whether two specified instances of StrongChar are equal.
/// </summary>
/// <param name="strong">The first instance to compare.</param>
/// <param name="other">The object to compare.</param>
/// <returns>True if strong and value represent the same char; otherwise, false.</returns>
public static bool operator ==(StrongChar<TStrong>? strong, object? other)
{
if (strong is null)
{
return other is null;
}

if (other is char charValue)
{
return strong.Value == charValue;
}

if (other is StrongChar<TStrong> otherStrong)
{
return strong.Value == otherStrong.Value;
}

return false;
}

/// <summary>
/// Determines whether two specified instances of StrongChar are not equal.
/// </summary>
/// <param name="strong">The first instance to compare.</param>
/// <param name="other">The object to compare.</param>
/// <returns>True if strong and other do not represent the same char; otherwise, false.</returns>
public static bool operator !=(StrongChar<TStrong>? strong, object? other)
{
return (strong == other) is false;
}

/// <summary>
/// Determines whether a <see cref="StrongChar{TStrong}"/> object is less than another object.
/// </summary>
/// <param name="strong">The <see cref="StrongChar{TStrong}"/> object to compare.</param>
/// <param name="other">The object to compare with the <paramref name="strong"/> object.</param>
/// <returns>
/// <see langword="true"/> if the <paramref name="strong"/> object is less than the <paramref name="other"/> object;
/// otherwise, <see langword="false"/>.
/// </returns>
/// <remarks>
/// If <paramref name="strong"/> is <see langword="null"/>, the method returns <see langword="true"/> if <paramref name="other"/> is also <see langword="null"/>, otherwise <see langword="false"/>.
/// If <paramref name="other"/> is a char, the method compares the value of <paramref name="strong"/> with the char value.
/// If <paramref name="other"/> is a <see cref="StrongChar{TStrong}"/> object, the method compares the value of <paramref name="strong"/> with the value of the other <see cref="StrongChar{TStrong}"/> object.
/// </remarks>
public static bool operator <(StrongChar<TStrong>? strong, object? other)
{
if (strong is null)
{
return other is null;
}

if (other is char charValue)
{
return strong.Value < charValue;
}

if (other is StrongChar<TStrong> otherStrong)
{
return strong.Value < otherStrong.Value;
}

return false;
}

/// <summary>
/// Determines whether a <see cref="StrongChar{TStrong}"/> object is greater than another object.
/// </summary>
/// <param name="strong">The <see cref="StrongChar{TStrong}"/> object to compare.</param>
/// <param name="other">The object to compare with the <paramref name="strong"/> object.</param>
/// <returns>
/// <see langword="true"/> if the <paramref name="strong"/> object is greater than the <paramref name="other"/> object;
/// otherwise, <see langword="false"/>.
/// </returns>
/// <remarks>
/// If <paramref name="strong"/> is <see langword="null"/>, the method returns <see langword="true"/> if <paramref name="other"/> is also <see langword="null"/>, otherwise <see langword="false"/>.
/// If <paramref name="other"/> is a char, the method compares the value of <paramref name="strong"/> with the char value.
/// If <paramref name="other"/> is a <see cref="StrongChar{TStrong}"/> object, the method compares the value of <paramref name="strong"/> with the value of the other <see cref="StrongChar{TStrong}"/> object.
/// </remarks>
public static bool operator >(StrongChar<TStrong>? strong, object? other)
{
if (strong is null)
{
return other is null;
}

if (other is char charValue)
{
return strong.Value > charValue;
}

if (other is StrongChar<TStrong> otherStrong)
{
return strong.Value > otherStrong.Value;
}

return false;
}

/// <summary>
/// Determines whether a <see cref="StrongChar{TStrong}"/> object is less than or equal to another object.
/// </summary>
/// <param name="strong">The <see cref="StrongChar{TStrong}"/> object to compare.</param>
/// <param name="other">The object to compare with the <paramref name="strong"/> object.</param>
/// <returns>
/// <see langword="true"/> if the <paramref name="strong"/> object is less than or equal to the <paramref name="other"/> object;
/// otherwise, <see langword="false"/>.
/// </returns>
/// <remarks>
/// If <paramref name="strong"/> is <see langword="null"/>, the method returns <see langword="true"/> if <paramref name="other"/> is also <see langword="null"/>, otherwise <see langword="false"/>.
/// If <paramref name="other"/> is a char, the method compares the value of <paramref name="strong"/> with the char value.
/// If <paramref name="other"/> is a <see cref="StrongChar{TStrong}"/> object, the method compares the value of <paramref name="strong"/> with the value of the other <see cref="StrongChar{TStrong}"/> object.
/// </remarks>
public static bool operator <=(StrongChar<TStrong>? strong, object? other)
{
if (strong is null)
{
return other is null;
}

if (other is char charValue)
{
return strong.Value <= charValue;
}

if (other is StrongChar<TStrong> otherStrong)
{
return strong.Value <= otherStrong.Value;
}

return false;
}

/// <summary>
/// Determines whether a <see cref="StrongChar{TStrong}"/> object is greater than or equal to another object.
/// </summary>
/// <param name="strong">The <see cref="StrongChar{TStrong}"/> object to compare.</param>
/// <param name="other">The object to compare with the <paramref name="strong"/> object.</param>
/// <returns>
/// <see langword="true"/> if the <paramref name="strong"/> object is greater than or equal to the <paramref name="other"/> object;
/// otherwise, <see langword="false"/>.
/// </returns>
/// <remarks>
/// If <paramref name="strong"/> is <see langword="null"/>, the method returns <see langword="true"/> if <paramref name="other"/> is also <see langword="null"/>, otherwise <see langword="false"/>.
/// If <paramref name="other"/> is a char, the method compares the value of <paramref name="strong"/> with the char value.
/// If <paramref name="other"/> is a <see cref="StrongChar{TStrong}"/> object, the method compares the value of <paramref name="strong"/> with the value of the other <see cref="StrongChar{TStrong}"/> object.
/// </remarks>
public static bool operator >=(StrongChar<TStrong>? strong, object? other)
{
if (strong is null)
{
return other is null;
}

if (other is char charValue)
{
return strong.Value >= charValue;
}

if (other is StrongChar<TStrong> otherStrong)
{
return strong.Value >= otherStrong.Value;
}

return false;
}
}
Loading