Skip to content

Commit

Permalink
Fixed Switch/Map
Browse files Browse the repository at this point in the history
  • Loading branch information
PawelGerr committed Dec 18, 2024
1 parent b65d089 commit 8f4e6d7
Show file tree
Hide file tree
Showing 18 changed files with 314 additions and 476 deletions.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<Copyright>(c) $([System.DateTime]::Now.Year), Pawel Gerr. All rights reserved.</Copyright>
<VersionPrefix>8.0.1</VersionPrefix>
<VersionPrefix>8.0.2</VersionPrefix>
<Authors>Pawel Gerr</Authors>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageProjectUrl>https://github.com/PawelGerr/Thinktecture.Runtime.Extensions</PackageProjectUrl>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,56 +108,14 @@ private void GenerateEnum(CancellationToken cancellationToken)
{
GenerateModuleInitializer(_state.KeyMember);

if (_state.KeyMember.IsString())
{
_sb.Append(@"
#if NET9_0_OR_GREATER
private static readonly global::System.Lazy<");

AppendLookupTypeTuple(_state.KeyMember);
_sb.Append(@"> _lookups
= new global::System.Lazy<");
AppendLookupTypeTuple(_state.KeyMember);
_sb.Append(@">(GetLookup, global::System.Threading.LazyThreadSafetyMode.PublicationOnly);
private static ");
AppendLookupType(_state.KeyMember);
_sb.Append(@" _itemsLookup => _lookups.Value.Item1;
#else");
}
else
{
_sb.Append(@"
");
}

_sb.Append(@"
private static readonly global::System.Lazy<");
AppendLookupType(_state.KeyMember);
_sb.Append(@"> _lookups
= new global::System.Lazy<");
AppendLookupType(_state.KeyMember);
_sb.Append(@">(GetLookup, global::System.Threading.LazyThreadSafetyMode.PublicationOnly);
private static ");
AppendLookupType(_state.KeyMember);
_sb.Append(" _itemsLookup => _lookups.Value;");

if (_state.KeyMember.IsString())
{
_sb.Append(@"
#endif");
}

_sb.Append(@"
private static readonly global::System.Lazy<global::System.Collections.Generic.IReadOnlyList<").AppendTypeFullyQualified(_state).Append(@">> _items
= new global::System.Lazy<global::System.Collections.Generic.IReadOnlyList<").AppendTypeFullyQualified(_state).Append(@">>(() => global::System.Linq.Enumerable.ToList(_itemsLookup.Values).AsReadOnly(), global::System.Threading.LazyThreadSafetyMode.PublicationOnly);
private static readonly global::System.Lazy<Lookups> _lookups = new global::System.Lazy<Lookups>(GetLookups, global::System.Threading.LazyThreadSafetyMode.PublicationOnly);
/// <summary>
/// Gets all valid items.
/// </summary>
public static global::System.Collections.Generic.IReadOnlyList<").AppendTypeFullyQualified(_state).Append("> Items => _items.Value;");
public static global::System.Collections.Generic.IReadOnlyList<").AppendTypeFullyQualified(_state).Append("> Items => _lookups.Value.List;");

GenerateKeyMember(_sb, _state.KeyMember, true);
}
Expand Down Expand Up @@ -286,7 +244,7 @@ public override int GetHashCode()

if (_state.KeyMember is not null)
{
GenerateGetLookup(_state.KeyMember);
GenerateGetLookups(_state.KeyMember);
}
else
{
Expand Down Expand Up @@ -915,7 +873,7 @@ public static bool TryGet([global::System.Diagnostics.CodeAnalysis.AllowNull] ")
if (_state.Settings.IsValidatable)
{
_sb.Append(@"
if(_itemsLookup.TryGetValue(").AppendEscaped(keyProperty.ArgumentName).Append(@", out item))
if(_lookups.Value.Lookup.TryGetValue(").AppendEscaped(keyProperty.ArgumentName).Append(@", out item))
return true;
item = CreateAndCheckInvalidItem(").AppendEscaped(keyProperty.ArgumentName).Append(@");
Expand All @@ -924,7 +882,7 @@ public static bool TryGet([global::System.Diagnostics.CodeAnalysis.AllowNull] ")
else
{
_sb.Append(@"
return _itemsLookup.TryGetValue(").AppendEscaped(keyProperty.ArgumentName).Append(", out item);");
return _lookups.Value.Lookup.TryGetValue(").AppendEscaped(keyProperty.ArgumentName).Append(", out item);");
}

_sb.Append(@"
Expand All @@ -948,7 +906,7 @@ public static bool TryGet(global::System.ReadOnlySpan<char> ").AppendEscaped(key
if (_state.Settings.IsValidatable)
{
_sb.Append(@"
if(_lookups.Value.Item2.TryGetValue(").AppendEscaped(keyProperty.ArgumentName).Append(@", out item))
if(_lookups.Value.AlternateLookup.TryGetValue(").AppendEscaped(keyProperty.ArgumentName).Append(@", out item))
return true;
item = CreateAndCheckInvalidItem(").AppendEscaped(keyProperty.ArgumentName).Append(@".ToString());
Expand All @@ -957,7 +915,7 @@ public static bool TryGet(global::System.ReadOnlySpan<char> ").AppendEscaped(key
else
{
_sb.Append(@"
return _lookups.Value.Item2.TryGetValue(").AppendEscaped(keyProperty.ArgumentName).Append(", out item);");
return _lookups.Value.AlternateLookup.TryGetValue(").AppendEscaped(keyProperty.ArgumentName).Append(", out item);");
}

_sb.Append(@"
Expand Down Expand Up @@ -1153,35 +1111,13 @@ public bool Equals(").AppendTypeFullyQualifiedNullAnnotated(_state).Append(@" ot
}");
}

private void GenerateGetLookup(KeyMemberState keyMember)
private void GenerateGetLookups(KeyMemberState keyMember)
{
var totalNumberOfItems = _state.Items.Count;

_sb.Append(@"
private static");

if (keyMember.IsString())
{
_sb.Append(@"
#if NET9_0_OR_GREATER
");
AppendLookupTypeTuple(keyMember);
_sb.Append(@"
#else
");
AppendLookupType(keyMember);
_sb.Append(@"
#endif
");
}
else
{
_sb.Append(" ");
AppendLookupType(keyMember);
}

_sb.Append(@" GetLookup()
private static Lookups GetLookups()
{
var lookup = new global::System.Collections.Generic.Dictionary<").AppendTypeFullyQualified(keyMember).Append(", ").AppendTypeFullyQualified(_state).Append(">(").Append(totalNumberOfItems);

Expand All @@ -1194,7 +1130,8 @@ private void GenerateGetLookup(KeyMemberState keyMember)
_sb.Append(", global::System.StringComparer.OrdinalIgnoreCase");
}

_sb.Append(");");
_sb.Append(@");
var list = new global::System.Collections.Generic.List<").AppendTypeFullyQualified(_state).Append(">(").Append(totalNumberOfItems).Append(");");

if (_state.Items.Count > 0)
{
Expand Down Expand Up @@ -1232,6 +1169,7 @@ void AddItem(").AppendTypeFullyQualified(_state).Append(@" item, string itemName
throw new global::System.ArgumentException($""The type \""").AppendTypeMinimallyQualified(_state).Append(@"\"" has multiple items with the identifier \""{item.").Append(keyMember.Name).Append(@"}\""."");
lookup.Add(item.").Append(keyMember.Name).Append(@", item);
list.Add(item);
}
");

Expand Down Expand Up @@ -1264,32 +1202,36 @@ void AddItem(").AppendTypeFullyQualified(_state).Append(@" item, string itemName
{
_sb.Append(@"
#if NET9_0_OR_GREATER
return (frozenDictionary, frozenDictionary.GetAlternateLookup<global::System.ReadOnlySpan<char>>());
return new Lookups(frozenDictionary, frozenDictionary.GetAlternateLookup<global::System.ReadOnlySpan<char>>(), list.AsReadOnly());
#else
return frozenDictionary;
return new Lookups(frozenDictionary, list.AsReadOnly());
#endif");
}
else
{
_sb.Append(@"
return frozenDictionary;");
return new Lookups(frozenDictionary, list.AsReadOnly());");
}

_sb.Append(@"
#else
return lookup;
return new Lookups(lookup, list.AsReadOnly());
#endif
}");
}
}
private void AppendLookupType(KeyMemberState keyMember)
{
_sb.Append("global::System.Collections.Generic.IReadOnlyDictionary<").AppendTypeFullyQualified(keyMember).Append(", ").AppendTypeFullyQualified(_state).Append(">");
}
private record struct Lookups(
global::System.Collections.Generic.IReadOnlyDictionary<").AppendTypeFullyQualified(keyMember).Append(", ").AppendTypeFullyQualified(_state).Append("> Lookup,");

private void AppendLookupTypeTuple(KeyMemberState keyMember)
{
_sb.Append("(global::System.Collections.Generic.IReadOnlyDictionary<").AppendTypeFullyQualified(keyMember).Append(", ").AppendTypeFullyQualified(_state).Append(">, global::System.Collections.Frozen.FrozenDictionary<string, ").AppendTypeFullyQualified(_state).Append(">.AlternateLookup<global::System.ReadOnlySpan<char>>").Append(")");
if (keyMember.IsString())
{
_sb.Append(@"
#if NET9_0_OR_GREATER
global::System.Collections.Frozen.FrozenDictionary<string, ").AppendTypeFullyQualified(_state).Append(">.AlternateLookup<global::System.ReadOnlySpan<char>>").Append(@" AlternateLookup,
#endif");
}

_sb.Append(@"
global::System.Collections.Generic.IReadOnlyList<").AppendTypeFullyQualified(_state).Append("> List);");
}

private void GenerateGetItems()
Expand Down Expand Up @@ -1396,7 +1338,7 @@ private void GenerateGet(IMemberState keyProperty)
}

_sb.Append(@"
if (!_itemsLookup.TryGetValue(").AppendEscaped(keyProperty.ArgumentName).Append(@", out var item))
if (!_lookups.Value.Lookup.TryGetValue(").AppendEscaped(keyProperty.ArgumentName).Append(@", out var item))
{");

if (_state.Settings.IsValidatable)
Expand Down Expand Up @@ -1437,7 +1379,7 @@ private void GenerateGetForReadOnlySpanOfChar(IMemberState keyProperty)
_sb.Append(@"
public static ").AppendTypeFullyQualified(_state).Append(" ").Append(Constants.Methods.GET).Append("(global::System.ReadOnlySpan<char> ").AppendEscaped(keyProperty.ArgumentName).Append(@")
{
if (!_lookups.Value.Item2.TryGetValue(").AppendEscaped(keyProperty.ArgumentName).Append(@", out var item))
if (!_lookups.Value.AlternateLookup.TryGetValue(").AppendEscaped(keyProperty.ArgumentName).Append(@", out var item))
{");

if (_state.Settings.IsValidatable)
Expand Down Expand Up @@ -1495,7 +1437,7 @@ private void GenerateCreateAndCheckInvalidItem(IMemberState keyProperty, bool ne
{
_sb.Append(@"
if (_itemsLookup.ContainsKey(item.").Append(keyProperty.Name).Append(@"))
if (_lookups.Value.Lookup.ContainsKey(item.").Append(keyProperty.Name).Append(@"))
throw new global::System.Exception(""The implementation of method '").Append(Constants.Methods.CREATE_INVALID_ITEM).Append("' must not return an instance with property '").Append(keyProperty.Name).Append(@"' equals to one of a valid item."");");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,12 @@ internal static void ModuleInit()
global::Thinktecture.Internal.KeyedValueObjectMetadataLookup.AddMetadata(enumType, metadata);
}

#if NET9_0_OR_GREATER
private static readonly global::System.Lazy<(global::System.Collections.Generic.IReadOnlyDictionary<string, global::Thinktecture.Tests.TestEnum>, global::System.Collections.Frozen.FrozenDictionary<string, global::Thinktecture.Tests.TestEnum>.AlternateLookup<global::System.ReadOnlySpan<char>>)> _lookups
= new global::System.Lazy<(global::System.Collections.Generic.IReadOnlyDictionary<string, global::Thinktecture.Tests.TestEnum>, global::System.Collections.Frozen.FrozenDictionary<string, global::Thinktecture.Tests.TestEnum>.AlternateLookup<global::System.ReadOnlySpan<char>>)>(GetLookup, global::System.Threading.LazyThreadSafetyMode.PublicationOnly);

private static global::System.Collections.Generic.IReadOnlyDictionary<string, global::Thinktecture.Tests.TestEnum> _itemsLookup => _lookups.Value.Item1;
#else
private static readonly global::System.Lazy<global::System.Collections.Generic.IReadOnlyDictionary<string, global::Thinktecture.Tests.TestEnum>> _lookups
= new global::System.Lazy<global::System.Collections.Generic.IReadOnlyDictionary<string, global::Thinktecture.Tests.TestEnum>>(GetLookup, global::System.Threading.LazyThreadSafetyMode.PublicationOnly);

private static global::System.Collections.Generic.IReadOnlyDictionary<string, global::Thinktecture.Tests.TestEnum> _itemsLookup => _lookups.Value;
#endif
private static readonly global::System.Lazy<global::System.Collections.Generic.IReadOnlyList<global::Thinktecture.Tests.TestEnum>> _items
= new global::System.Lazy<global::System.Collections.Generic.IReadOnlyList<global::Thinktecture.Tests.TestEnum>>(() => global::System.Linq.Enumerable.ToList(_itemsLookup.Values).AsReadOnly(), global::System.Threading.LazyThreadSafetyMode.PublicationOnly);
private static readonly global::System.Lazy<Lookups> _lookups = new global::System.Lazy<Lookups>(GetLookups, global::System.Threading.LazyThreadSafetyMode.PublicationOnly);

/// <summary>
/// Gets all valid items.
/// </summary>
public static global::System.Collections.Generic.IReadOnlyList<global::Thinktecture.Tests.TestEnum> Items => _items.Value;
public static global::System.Collections.Generic.IReadOnlyList<global::Thinktecture.Tests.TestEnum> Items => _lookups.Value.List;

/// <summary>
/// The identifier of this item.
Expand Down Expand Up @@ -152,7 +140,7 @@ static partial void ValidateConstructorArguments(
if (@name is null)
return default;

if (!_itemsLookup.TryGetValue(@name, out var item))
if (!_lookups.Value.Lookup.TryGetValue(@name, out var item))
{
item = CreateAndCheckInvalidItem(@name);
}
Expand All @@ -168,7 +156,7 @@ static partial void ValidateConstructorArguments(
/// <returns>An instance of <see cref="TestEnum"/> if <paramref name="name"/> is not <c>null</c>; otherwise <c>null</c>.</returns>
public static global::Thinktecture.Tests.TestEnum Get(global::System.ReadOnlySpan<char> @name)
{
if (!_lookups.Value.Item2.TryGetValue(@name, out var item))
if (!_lookups.Value.AlternateLookup.TryGetValue(@name, out var item))
{
item = CreateAndCheckInvalidItem(@name.ToString());
}
Expand All @@ -187,7 +175,7 @@ static partial void ValidateConstructorArguments(
if (item.IsValid)
throw new global::System.Exception("The implementation of method 'CreateInvalidItem' must return an instance with property 'IsValid' equals to 'false'.");

if (_itemsLookup.ContainsKey(item.Name))
if (_lookups.Value.Lookup.ContainsKey(item.Name))
throw new global::System.Exception("The implementation of method 'CreateInvalidItem' must not return an instance with property 'Name' equals to one of a valid item.");

return item;
Expand All @@ -207,7 +195,7 @@ public static bool TryGet([global::System.Diagnostics.CodeAnalysis.AllowNull] st
return false;
}

if(_itemsLookup.TryGetValue(@name, out item))
if(_lookups.Value.Lookup.TryGetValue(@name, out item))
return true;

item = CreateAndCheckInvalidItem(@name);
Expand All @@ -223,7 +211,7 @@ public static bool TryGet([global::System.Diagnostics.CodeAnalysis.AllowNull] st
/// <returns><c>true</c> if a valid item with provided <paramref name="name"/> exists; <c>false</c> otherwise.</returns>
public static bool TryGet(global::System.ReadOnlySpan<char> @name, [global::System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] out global::Thinktecture.Tests.TestEnum item)
{
if(_lookups.Value.Item2.TryGetValue(@name, out item))
if(_lookups.Value.AlternateLookup.TryGetValue(@name, out item))
return true;

item = CreateAndCheckInvalidItem(@name.ToString());
Expand Down Expand Up @@ -712,15 +700,10 @@ public TResult MapPartially<TResult>(
return @default;
}

private static
#if NET9_0_OR_GREATER
(global::System.Collections.Generic.IReadOnlyDictionary<string, global::Thinktecture.Tests.TestEnum>, global::System.Collections.Frozen.FrozenDictionary<string, global::Thinktecture.Tests.TestEnum>.AlternateLookup<global::System.ReadOnlySpan<char>>)
#else
global::System.Collections.Generic.IReadOnlyDictionary<string, global::Thinktecture.Tests.TestEnum>
#endif
GetLookup()
private static Lookups GetLookups()
{
var lookup = new global::System.Collections.Generic.Dictionary<string, global::Thinktecture.Tests.TestEnum>(2, global::Thinktecture.ComparerAccessors.StringOrdinal.EqualityComparer);
var list = new global::System.Collections.Generic.List<global::Thinktecture.Tests.TestEnum>(2);

void AddItem(global::Thinktecture.Tests.TestEnum item, string itemName)
{
Expand All @@ -737,6 +720,7 @@ void AddItem(global::Thinktecture.Tests.TestEnum item, string itemName)
throw new global::System.ArgumentException($"The type \"TestEnum\" has multiple items with the identifier \"{item.Name}\".");

lookup.Add(item.Name, item);
list.Add(item);
}

AddItem(@Item1, nameof(@Item1));
Expand All @@ -745,13 +729,20 @@ void AddItem(global::Thinktecture.Tests.TestEnum item, string itemName)
#if NET8_0_OR_GREATER
var frozenDictionary = global::System.Collections.Frozen.FrozenDictionary.ToFrozenDictionary(lookup, global::Thinktecture.ComparerAccessors.StringOrdinal.EqualityComparer);
#if NET9_0_OR_GREATER
return (frozenDictionary, frozenDictionary.GetAlternateLookup<global::System.ReadOnlySpan<char>>());
return new Lookups(frozenDictionary, frozenDictionary.GetAlternateLookup<global::System.ReadOnlySpan<char>>(), list.AsReadOnly());
#else
return frozenDictionary;
return new Lookups(frozenDictionary, list.AsReadOnly());
#endif
#else
return lookup;
return new Lookups(lookup, list.AsReadOnly());
#endif
}

private record struct Lookups(
global::System.Collections.Generic.IReadOnlyDictionary<string, global::Thinktecture.Tests.TestEnum> Lookup,
#if NET9_0_OR_GREATER
global::System.Collections.Frozen.FrozenDictionary<string, global::Thinktecture.Tests.TestEnum>.AlternateLookup<global::System.ReadOnlySpan<char>> AlternateLookup,
#endif
global::System.Collections.Generic.IReadOnlyList<global::Thinktecture.Tests.TestEnum> List);
}
}
Loading

0 comments on commit 8f4e6d7

Please sign in to comment.