Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
22f4ebe
Added Sundew.Base.Identification
hugener Mar 8, 2026
b36907d
Added Sundew.Base.Identification
hugener Mar 8, 2026
5895fd3
Starting implementinf AId parser
hugener Mar 22, 2026
a9cf41f
Continued work on Id parser
hugener Apr 10, 2026
29d0405
Merge branch 'feature/Identification' of https://github.com/sundews/S…
hugener Apr 10, 2026
fddf54f
Fixed merge conflicts
hugener Apr 10, 2026
195492c
Implemented serialization and deserialization for Ids and ValueIds
hugener Apr 14, 2026
5922df0
Added Uri support to Ids
hugener Apr 14, 2026
440b7c6
Added SequenceId for implementing simple counted ids
hugener Apr 15, 2026
b09393b
Added literal support for specifying null and instance ids
hugener Apr 16, 2026
b0057c2
Null literal improvements
hugener Apr 17, 2026
47a1c63
Fix flasky test
hugener May 2, 2026
d6ac42d
Fix GetHashCode consistency for ValueList, ValueArray, ValueDictionar…
Copilot May 2, 2026
95b0345
Improve Id fragment handling
hugener May 2, 2026
f852bcc
Merge branch 'feature/Identification' of https://github.com/sundews/S…
hugener May 2, 2026
030e9c9
Fix Parser.Undo() to prevent popping initial state; fix GetInputTypes…
Copilot May 2, 2026
f0435ed
Fix GetScalar to use raw ScalarValue.Value instead of escaped ToString()
Copilot May 2, 2026
cee067e
Refactor GetScalar: extract raw-value helper to avoid duplication
Copilot May 2, 2026
c4f8bc9
Fix RegexLexerRule to reject matches not starting exactly at state.Po…
Copilot May 2, 2026
a2d7da5
Fixed result extension And returned incorrect result
hugener May 2, 2026
3e995cd
Fix IdRouteParser array/route loop conditions and ValueIdBuilder sing…
Copilot May 2, 2026
bc626b0
Merge branch 'feature/Identification' of https://github.com/sundews/S…
hugener May 2, 2026
24b80be
Improve test flakyness
hugener May 2, 2026
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
4 changes: 4 additions & 0 deletions Source/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
</PackageReference>
</ItemGroup>

<PropertyGroup Condition="$(TargetFramework.StartsWith('net4')) OR $(TargetFramework.StartsWith('netstandard')) OR $(TargetFramework.StartsWith('net6'))">
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
</PropertyGroup>

<PropertyGroup Condition="$(AssemblyName.EndsWith('Tests'))">
<IsTestProject>true</IsTestProject>
<IsPackable>false</IsPackable>
Expand Down
22 changes: 11 additions & 11 deletions Source/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,32 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="AwesomeAssertions" Version="9.3.0" />
<PackageVersion Include="AwesomeAssertions" Version="9.4.0" />
<PackageVersion Include="BenchmarkDotNet" Version="0.15.3" />
<PackageVersion Include="coverlet.collector" Version="6.0.4" />
<PackageVersion Include="coverlet.collector" Version="8.0.1" />
<PackageVersion Include="Disposal.Interfaces" Version="1.0.3" />
<PackageVersion Include="Initialization.Interfaces" Version="1.0.3" />
<PackageVersion Include="JustMock" Version="2025.4.1112.487" />
<PackageVersion Include="JustMock" Version="2026.1.211.494" />
<PackageVersion Include="MemoryPack" Version="1.21.4" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.2" />
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.102" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="10.0.102" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.5" />
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.201" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="10.0.201" />
<PackageVersion Include="Microsoft.VisualStudio.Threading" Version="17.14.15" />
<PackageVersion Include="Microsoft.VisualStudio.Threading.Only" Version="17.14.15" />
<PackageVersion Include="Paket.Core" Version="9.0.2" />
<PackageVersion Include="PolySharp" Version="1.15.0" />
<PackageVersion Include="StyleCop.Analyzers.Unstable" Version="1.2.0.556" />
<PackageVersion Include="Sundew.DiscriminatedUnions" Version="5.4.1" />
<PackageVersion Include="Sundew.DiscriminatedUnions" Version="6.0.1" />
<PackageVersion Include="Sundew.Packaging.Publish" Version="10.0.12" />
<PackageVersion Include="System.Reactive" Version="6.1.0" />
<PackageVersion Include="System.Reflection.Metadata" Version="9.0.4" />
<PackageVersion Include="System.Security.Permissions" Version="10.0.2" />
<PackageVersion Include="System.Security.Permissions" Version="10.0.5" />
<PackageVersion Include="TransparentMoq" Version="4.20.70.2" />
<PackageVersion Include="TUnit" Version="1.12.111" />
<PackageVersion Include="TUnit" Version="1.24.31" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' != 'net6.0'">
<PackageVersion Include="System.Collections.Immutable" Version="10.0.2" />
<PackageVersion Include="System.Collections.Immutable" Version="10.0.5" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
<PackageVersion Include="System.Collections.Immutable" Version="8.0.0" />
Expand Down
11 changes: 8 additions & 3 deletions Source/Sundew.Base.Collections.Immutable/ValueArray{TItem}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,12 @@ IEnumerator<TItem> IEnumerable<TItem>.GetEnumerator()
/// <returns>The hashcode.</returns>
public override int GetHashCode()
{
if (this.inner.HasValue)
if (this.Count == 0)
{
return StructuralComparisons.StructuralEqualityComparer.GetHashCode(this.inner);
return 0;
}

return 0;
return StructuralComparisons.StructuralEqualityComparer.GetHashCode(this.inner!);
}

/// <summary>
Expand All @@ -175,6 +175,11 @@ public override int GetHashCode()
/// <returns><c>true</c>, if the values are equal otherwise false.</returns>
public bool Equals(ValueArray<TItem> other)
{
if (this.Count == 0 && other.Count == 0)
{
return true;
Comment on lines 176 to +180
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already fixed in d6ac42dGetHashCode() for ValueArray now returns 0 when Count == 0, consistent with the equality rule.

}

return StructuralComparisons.StructuralEqualityComparer.Equals(this.inner, other.inner);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,13 +162,13 @@ public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
public override int GetHashCode()
{
#if NETSTANDARD2_0_OR_GREATER || NET6_0_OR_GREATER
if (this.inner == null)
if (this.Count == 0)
{
return 0;
}

var hashCode = default(HashCode);
foreach (var pair in this.inner)
foreach (var pair in this.inner!)
{
hashCode.Add(pair.Key);
hashCode.Add(pair.Value);
Expand All @@ -186,7 +186,7 @@ static int CombineHashCode(int hashCode1, int hashcode2)
}
}

return this.inner == default ? 0 : Equality.Equality.GetItemsHashCode(this.inner.Select(x => CombineHashCode(x.Key?.GetHashCode() ?? 0, x.Value?.GetHashCode() ?? 0)));
return this.Count == 0 ? 0 : Equality.Equality.GetItemsHashCode(this.inner!.Select(x => CombineHashCode(x.Key?.GetHashCode() ?? 0, x.Value?.GetHashCode() ?? 0)));

#endif
}
Expand All @@ -198,6 +198,11 @@ static int CombineHashCode(int hashCode1, int hashcode2)
/// <returns><c>true</c>, if the values are equal otherwise false.</returns>
public bool Equals(ValueDictionary<TKey, TValue> other)
{
if (this.Count == 0 && other.Count == 0)
{
return true;
Comment on lines 199 to +203
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already fixed in d6ac42dGetHashCode() for ValueDictionary now returns 0 when Count == 0, consistent with the equality rule.

}

if (this.inner == null)
{
if (other.inner == null)
Expand Down
11 changes: 8 additions & 3 deletions Source/Sundew.Base.Collections.Immutable/ValueList{TItem}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,20 +133,20 @@ public IEnumerator<TItem> GetEnumerator()
public override int GetHashCode()
{
#if NETSTANDARD2_0_OR_GREATER || NET6_0_OR_GREATER
if (this.inner == null)
if (this.Count == 0)
{
return 0;
}

var hashCode = default(HashCode);
foreach (var item in this.inner)
foreach (var item in this.inner!)
{
hashCode.Add(item?.GetHashCode() ?? 0);
}

return hashCode.ToHashCode();
#else
return this.inner == default ? 0 : Equality.Equality.GetItemsHashCode(this.inner.Select(x => x?.GetHashCode() ?? 0));
return this.Count == 0 ? 0 : Equality.Equality.GetItemsHashCode(this.inner!.Select(x => x?.GetHashCode() ?? 0));

#endif
}
Expand All @@ -158,6 +158,11 @@ public override int GetHashCode()
/// <returns><c>true</c>, if the values are equal otherwise false.</returns>
public bool Equals(ValueList<TItem> other)
{
if (this.Count == 0 && other.Count == 0)
{
return true;
Comment on lines 159 to +163
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in d6ac42d. Updated GetHashCode() in all three types (ValueList, ValueArray, ValueDictionary) to return 0 when Count == 0, consistent with the equality rule that treats default and Empty as equal. Equal instances now always produce the same hash code.

}

if (this.inner == null)
{
if (other.inner == null)
Expand Down
4 changes: 2 additions & 2 deletions Source/Sundew.Base.Collections.Linq/Empty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ namespace Sundew.Base.Collections.Linq;
/// </summary>
/// <typeparam name="TItem">The item type.</typeparam>
#if NETSTANDARD2_0_OR_GREATER || NET6_0_OR_GREATER
public sealed record Empty<TItem> : ListCardinality<TItem>
public sealed partial record Empty<TItem> : ListCardinality<TItem>
#else
public sealed class Empty<TItem> : ListCardinality<TItem>
public sealed partial class Empty<TItem> : ListCardinality<TItem>
#endif
{
}
24 changes: 24 additions & 0 deletions Source/Sundew.Base.Collections.Linq/Item.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ namespace Sundew.Base.Collections.Linq;
/// </summary>
public static class Item
{
/// <summary>
/// Converts the item into an item result.
/// </summary>
/// <typeparam name="TSuccess">The success type.</typeparam>
/// <param name="result">The result.</param>
/// <returns>An Item result.</returns>
[MethodImpl((MethodImplOptions)0x300)]
public static Item<TSuccess> PassIfSuccess<TSuccess>(R<TSuccess> result)
{
return result.ToItem();
}

/// <summary>
/// Converts the item into an item result.
/// </summary>
Expand Down Expand Up @@ -167,6 +179,18 @@ public static Item<TValue> ToItem<TValue>(this TValue? option)
return new Item<TValue>(option, option.HasValue);
}

/// <summary>
/// Converts the option to an item.
/// </summary>
/// <typeparam name="TResult">The value type.</typeparam>
/// <param name="result">The result.</param>
/// <returns>The new item.</returns>
[MethodImpl((MethodImplOptions)0x300)]
public static Item<TResult> ToItem<TResult>(this R<TResult> result)
{
return new Item<TResult>(result.Value, result.IsSuccess);
}

/// <summary>
/// Converts the option to an item.
/// </summary>
Expand Down
4 changes: 2 additions & 2 deletions Source/Sundew.Base.Collections.Linq/Multiple.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ namespace Sundew.Base.Collections.Linq;
/// </summary>
/// <typeparam name="TItem">The item type.</typeparam>
#if NETSTANDARD2_0_OR_GREATER || NET6_0_OR_GREATER
public sealed record Multiple<TItem> : ListCardinality<TItem>, IEnumerable<TItem>
public sealed partial record Multiple<TItem> : ListCardinality<TItem>, IEnumerable<TItem>
#else
public sealed class Multiple<TItem> : ListCardinality<TItem>, IEnumerable<TItem>
public sealed partial class Multiple<TItem> : ListCardinality<TItem>, IEnumerable<TItem>
#endif
{
/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion Source/Sundew.Base.Collections.Linq/Single.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Sundew.Base.Collections.Linq;
/// </summary>
/// <typeparam name="TItem">The item type.</typeparam>
#if NETSTANDARD2_0_OR_GREATER || NET6_0_OR_GREATER
public sealed record Single<TItem> : ListCardinality<TItem>
public sealed partial record Single<TItem> : ListCardinality<TItem>
#else
public sealed class Single<TItem> : ListCardinality<TItem>
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ public void Equals_When_IsDefault_Then_LhsAndRhsShouldBeEqual()
((object)lhs).Should().Be(rhs);
}

[Test]
public void Equals_When_OneIsDefaultAndTheOtherIsEmpty_Then_LhsAndRhsShouldBeEqual()
{
ValueArray<int> lhs = ValueArray<int>.Empty;
ValueArray<int> rhs = default;

((object)lhs).Should().Be(rhs);
}

[Test]
public void Equals_When_UsedWithInt_Then_LhsAndRhsShouldBeEqual()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ namespace Sundew.Base.Development.Tests.Collections;

public class ValueDictionaryTests
{
[Test]
public void Equals_When_OneIsDefaultAndTheOtherIsEmpty_Then_LhsAndRhsShouldBeEqual()
{
ValueDictionary<int, int> lhs = ValueDictionary<int, int>.Empty;
ValueDictionary<int, int> rhs = default;

((object)lhs).Should().Be(rhs);
}

[Test]
public void Equals_When_UsedWithInt_Then_LhsAndRhsShouldBeEqual()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ namespace Sundew.Base.Development.Tests.Collections;

public class ValueListTests
{
[Test]
public void Equals_When_OneIsDefaultAndTheOtherIsEmpty_Then_LhsAndRhsShouldBeEqual()
{
ValueList<int> lhs = ValueList<int>.Empty;
ValueList<int> rhs = default;

((object)lhs).Should().Be(rhs);
}

[Test]
public void Equals_When_UsedWithInt_Then_LhsAndRhsShouldBeEqual()
{
Expand Down
Loading
Loading