Skip to content

Commit 8bd4dfe

Browse files
author
Oguzhan Kahyaoglu
committed
Added default values for ToStringFast/ToDisplayFast methods.
Added ToDescriptionFast method. Added "DisplayNames" and "DisplayDescriptions" dictionaries to hold static values as dictionaries.
1 parent eb53599 commit 8bd4dfe

File tree

4 files changed

+194
-26
lines changed

4 files changed

+194
-26
lines changed

README.md

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,9 @@ To use the generator, add the `[EnumGenerator]` attribute to an enum. For exampl
3030
[EnumGenerator]
3131
public enum UserTypeTest
3232
{
33-
[Display(Name = "مرد")]
34-
Men,
33+
[Display(Name = "مرد", Description = "Descمرد")] Men = 3,
3534

36-
[Display(Name = "زن")]
37-
Women,
35+
[Display(Name = "زن", Description = "Descزن")] Women = 4,
3836

3937
//[Display(Name = "نامشخص")]
4038
None
@@ -47,14 +45,14 @@ For example:
4745
```csharp
4846
public static class UserTypeTestEnumExtensions
4947
{
50-
public static string ToStringFast(this UnitTests.UserTypeTest states)
48+
public static string ToStringFast(this UnitTests.UserTypeTest states, string defaultValue = null)
5149
{
5250
return states switch
5351
{
5452
UnitTests.UserTypeTest.Men => nameof(UnitTests.UserTypeTest.Men),
5553
UnitTests.UserTypeTest.Women => nameof(UnitTests.UserTypeTest.Women),
5654
UnitTests.UserTypeTest.None => nameof(UnitTests.UserTypeTest.None),
57-
_ => throw new ArgumentOutOfRangeException(nameof(states), states, null)
55+
_ => defaultValue ?? throw new ArgumentOutOfRangeException(nameof(states), states, null)
5856
};
5957
}
6058
public static bool IsDefinedFast(UnitTests.UserTypeTest states)
@@ -77,16 +75,28 @@ For example:
7775
_ => false
7876
};
7977
}
80-
public static string ToDisplayFast(this UnitTests.UserTypeTest states)
78+
public static string ToDisplayFast(this UnitTests.UserTypeTest states, string defaultValue = null)
8179
{
8280
return states switch
8381
{
8482
UnitTests.UserTypeTest.Men => "مرد",
8583
UnitTests.UserTypeTest.Women => "زن",
8684
UnitTests.UserTypeTest.None => "None",
87-
_ => throw new ArgumentOutOfRangeException(nameof(states), states, null)
85+
_ => defaultValue ?? throw new ArgumentOutOfRangeException(nameof(states), states, null)
8886
};
8987
}
88+
89+
public static string ToDescriptionFast(this UnitTests.UserTypeTest states, string defaultValue = null)
90+
{
91+
return states switch
92+
{
93+
UnitTests.UserTypeTest.Men => "Descمرد",
94+
UnitTests.UserTypeTest.Women => "Descزن",
95+
UnitTests.UserTypeTest.None => "None",
96+
_ => defaultValue ?? throw new ArgumentOutOfRangeException(nameof(states), states, null)
97+
};
98+
}
99+
90100
public static UnitTests.UserTypeTest[] GetValuesFast()
91101
{
92102
return new[]

Supernova.Enum.Generators/EnumSourceGenerator.cs

Lines changed: 102 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ public sealed class {SourceGeneratorHelper.AttributeName}Attribute : Attribute
7171

7272

7373
/**********************/
74-
var memberAttribute = new Dictionary<string, string>();
74+
var enumDisplayNames = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
75+
var enumDescriptions = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
7576
foreach (var member in enumSymbol.GetMembers())
7677
{
7778
if (member is not IFieldSymbol field
@@ -84,21 +85,36 @@ public sealed class {SourceGeneratorHelper.AttributeName}Attribute : Attribute
8485
attribute.AttributeClass.Name != "DisplayAttribute") continue;
8586

8687
foreach (var namedArgument in attribute.NamedArguments)
88+
{
8789
if (namedArgument.Key.Equals("Name", StringComparison.OrdinalIgnoreCase) &&
88-
namedArgument.Value.Value?.ToString() is { } dn)
90+
namedArgument.Value.Value?.ToString() is { } displayName)
8991
{
90-
memberAttribute.Add(member.Name, dn);
91-
break;
92+
enumDisplayNames.Add(member.Name, displayName);
93+
}
94+
if (namedArgument.Key.Equals("Description", StringComparison.OrdinalIgnoreCase) &&
95+
namedArgument.Value.Value?.ToString() is { } description)
96+
{
97+
enumDescriptions.Add(member.Name, description);
9298
}
99+
100+
}
93101
}
94102
}
95103

96104
var sourceBuilder = new StringBuilder($@"using System;
105+
using System.Collections.Generic;
106+
using System.Collections.Immutable;
97107
namespace {SourceGeneratorHelper.NameSpace}
98108
{{
99109
public static class {symbol.Name}EnumExtensions
100110
{{");
101111

112+
//DisplayNames Dictionary
113+
DisplayNamesDictionary(sourceBuilder, symbolName, e, enumDisplayNames);
114+
115+
//DisplayDescriptions Dictionary
116+
DisplayDescriptionsDictionary(sourceBuilder, symbolName, e, enumDescriptions);
117+
102118
//ToStringFast
103119
ToStringFast(sourceBuilder, symbolName, e);
104120

@@ -109,7 +125,10 @@ public static class {symbol.Name}EnumExtensions
109125
IsDefinedString(sourceBuilder, e, symbolName);
110126

111127
//ToDisplay string
112-
ToDisplay(sourceBuilder, symbolName, e, memberAttribute);
128+
ToDisplay(sourceBuilder, symbolName, e, enumDisplayNames);
129+
130+
//ToDisplay string
131+
ToDescription(sourceBuilder, symbolName, e, enumDescriptions);
113132

114133
//GetValues
115134
GetValuesFast(sourceBuilder, symbolName, e);
@@ -131,28 +150,51 @@ public static class {symbol.Name}EnumExtensions
131150
}
132151

133152
private static void ToDisplay(StringBuilder sourceBuilder, string symbolName, EnumDeclarationSyntax e,
134-
Dictionary<string, string> memberAttribute)
153+
Dictionary<string, string> enumDisplayNames)
135154
{
136155
sourceBuilder.Append($@"
137-
public static string {SourceGeneratorHelper.ExtensionMethodNameToDisplay}(this {symbolName} states)
156+
public static string {SourceGeneratorHelper.ExtensionMethodNameToDisplay}(this {symbolName} states, string defaultValue = null)
138157
{{
139158
return states switch
140159
{{
141160
");
142161
foreach (var member in e.Members)
143162
{
144-
var display = memberAttribute
145-
.FirstOrDefault(r =>
146-
r.Key.Equals(member.Identifier.ValueText, StringComparison.OrdinalIgnoreCase))
147-
.Value
148-
?? member.Identifier.ValueText;
163+
var key = member.Identifier.ValueText;
164+
var enumDisplayName = enumDisplayNames.TryGetValue(key, out var found)
165+
? found
166+
: key;
167+
sourceBuilder.AppendLine(
168+
$@" {symbolName}.{member.Identifier.ValueText} => ""{enumDisplayName ?? key}"",");
169+
}
170+
171+
sourceBuilder.Append(
172+
@" _ => defaultValue ?? throw new ArgumentOutOfRangeException(nameof(states), states, null)
173+
};
174+
}");
175+
}
149176

177+
private static void ToDescription(StringBuilder sourceBuilder, string symbolName, EnumDeclarationSyntax e,
178+
Dictionary<string, string> enumDescriptions)
179+
{
180+
sourceBuilder.Append($@"
181+
public static string {SourceGeneratorHelper.ExtensionMethodNameToDescription}(this {symbolName} states, string defaultValue = null)
182+
{{
183+
return states switch
184+
{{
185+
");
186+
foreach (var member in e.Members)
187+
{
188+
var key = member.Identifier.ValueText;
189+
var enumDescription = enumDescriptions.TryGetValue(key, out var found)
190+
? found
191+
: key;
150192
sourceBuilder.AppendLine(
151-
$@" {symbolName}.{member.Identifier.ValueText} => ""{display}"",");
193+
$@" {symbolName}.{member.Identifier.ValueText} => ""{enumDescription ?? key}"",");
152194
}
153195

154196
sourceBuilder.Append(
155-
@" _ => throw new ArgumentOutOfRangeException(nameof(states), states, null)
197+
@" _ => defaultValue ?? throw new ArgumentOutOfRangeException(nameof(states), states, null)
156198
};
157199
}");
158200
}
@@ -192,19 +234,63 @@ private static void IsDefinedEnum(StringBuilder sourceBuilder, string symbolName
192234
private static void ToStringFast(StringBuilder sourceBuilder, string symbolName, EnumDeclarationSyntax e)
193235
{
194236
sourceBuilder.Append($@"
195-
public static string {SourceGeneratorHelper.ExtensionMethodNameToString}(this {symbolName} states)
237+
public static string {SourceGeneratorHelper.ExtensionMethodNameToString}(this {symbolName} states, string defaultValue = null)
196238
{{
197239
return states switch
198240
{{
199241
");
200242
foreach (var member in e.Members.Select(x => x.Identifier.ValueText))
201243
sourceBuilder.AppendLine($@" {symbolName}.{member} => nameof({symbolName}.{member}),");
202244
sourceBuilder.Append(
203-
@" _ => throw new ArgumentOutOfRangeException(nameof(states), states, null)
245+
@" _ => defaultValue ?? throw new ArgumentOutOfRangeException(nameof(states), states, null)
204246
};
205247
}");
206248
}
207249

250+
private static void DisplayNamesDictionary(StringBuilder sourceBuilder, string symbolName, EnumDeclarationSyntax e,
251+
Dictionary<string, string> enumDisplayNames)
252+
{
253+
sourceBuilder.Append($@"
254+
public static readonly ImmutableDictionary<{symbolName}, string> {SourceGeneratorHelper.PropertyDisplayNamesDictionary} = new Dictionary<{symbolName}, string>
255+
{{
256+
");
257+
foreach (var member in e.Members)
258+
{
259+
var key = member.Identifier.ValueText;
260+
var enumDisplayName = enumDisplayNames.TryGetValue(key, out var found)
261+
? found
262+
: key;
263+
sourceBuilder.AppendLine(
264+
$@" {{{symbolName}.{member.Identifier.ValueText}, ""{enumDisplayName ?? key}""}},");
265+
}
266+
sourceBuilder.Append(
267+
@"
268+
}.ToImmutableDictionary();
269+
");
270+
}
271+
272+
private static void DisplayDescriptionsDictionary(StringBuilder sourceBuilder, string symbolName, EnumDeclarationSyntax e,
273+
Dictionary<string, string> enumDescriptionNames)
274+
{
275+
sourceBuilder.Append($@"
276+
public static readonly ImmutableDictionary<{symbolName}, string> {SourceGeneratorHelper.PropertyDisplayDescriptionsDictionary} = new Dictionary<{symbolName}, string>
277+
{{
278+
");
279+
foreach (var member in e.Members)
280+
{
281+
var key = member.Identifier.ValueText;
282+
var enumDescription = enumDescriptionNames.TryGetValue(key, out var found)
283+
? found
284+
: key;
285+
sourceBuilder.AppendLine(
286+
$@" {{{symbolName}.{member.Identifier.ValueText}, ""{enumDescription ?? key}""}},");
287+
}
288+
sourceBuilder.Append(
289+
@"
290+
}.ToImmutableDictionary();
291+
");
292+
}
293+
208294
private static void GetValuesFast(StringBuilder sourceBuilder, string symbolName, EnumDeclarationSyntax e)
209295
{
210296
sourceBuilder.Append($@"

Supernova.Enum.Generators/SourceGeneratorHelper.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@ public static class SourceGeneratorHelper
1616
public const string ExtensionMethodNameToString = "ToStringFast";
1717
public const string ExtensionMethodNameIsDefined = "IsDefinedFast";
1818
public const string ExtensionMethodNameToDisplay = "ToDisplayFast";
19+
public const string ExtensionMethodNameToDescription = "ToDescriptionFast";
1920
public const string ExtensionMethodNameGetValues = "GetValuesFast";
2021
public const string ExtensionMethodNameGetNames = "GetNamesFast";
2122
public const string ExtensionMethodNameGetLength = "GetLengthFast";
23+
public const string PropertyDisplayNamesDictionary = "DisplayNamesDictionary";
24+
public const string PropertyDisplayDescriptionsDictionary = "DisplayDescriptionsDictionary";
2225

2326
public const string Attribute = Header + $@"
2427

test/UnitTests/EnumGeneratorTest.cs

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@
22
using FluentAssertions;
33
using Microsoft.VisualStudio.TestTools.UnitTesting;
44
using System;
5+
using System.Collections.Generic;
56
using System.ComponentModel.DataAnnotations;
67

78
namespace UnitTests;
89

910
[EnumGenerator]
1011
public enum UserTypeTest
1112
{
12-
[Display(Name = "مرد")] Men,
13+
[Display(Name = "مرد", Description = "Descمرد")] Men = 3,
1314

14-
[Display(Name = "زن")] Women,
15+
[Display(Name = "زن", Description = "Descزن")] Women = 4,
1516

1617
//[Display(Name = "نامشخص")]
1718
None
@@ -52,6 +53,38 @@ public void TestEnumToString_Undefined()
5253
action.Should().Throw<ArgumentOutOfRangeException>();
5354
}
5455

56+
[TestMethod]
57+
public void TestEnumToString_Undefined_DefaultValue()
58+
{
59+
var value = GetUndefinedEnumValue().ToStringFast("DefaultValue");
60+
61+
value.Should().Be("DefaultValue");
62+
}
63+
64+
[TestMethod]
65+
public void TestEnumToDescription()
66+
{
67+
var menString = UserTypeTest.Men.ToDescriptionFast();
68+
69+
menString.Should().Be("Descمرد");
70+
}
71+
72+
[TestMethod]
73+
public void TestEnumToDescription_Undefined()
74+
{
75+
var action = () => GetUndefinedEnumValue().ToDescriptionFast();
76+
77+
action.Should().Throw<ArgumentOutOfRangeException>();
78+
}
79+
80+
[TestMethod]
81+
public void TestEnumToDescription_Undefined_DefaultValue()
82+
{
83+
var value = GetUndefinedEnumValue().ToDescriptionFast("DefaultValue");
84+
85+
value.Should().Be("DefaultValue");
86+
}
87+
5588
[TestMethod]
5689
public void TestEnumToDisplay()
5790
{
@@ -76,6 +109,14 @@ public void TestEnumToDisplay_Undefined()
76109
action.Should().Throw<ArgumentOutOfRangeException>();
77110
}
78111

112+
[TestMethod]
113+
public void TestEnumToDisplay_Undefined_DefaultValue()
114+
{
115+
var value = GetUndefinedEnumValue().ToDisplayFast("DefaultValue");
116+
117+
value.Should().Be("DefaultValue");
118+
}
119+
79120
[TestMethod]
80121
public void TestEnumGetNames()
81122
{
@@ -88,6 +129,34 @@ public void TestEnumGetNames()
88129
.And.ContainItemsAssignableTo<string>();
89130
}
90131

132+
[TestMethod]
133+
public void TestEnumDisplayNamesDictionary()
134+
{
135+
var names = UserTypeTestEnumExtensions.DisplayNamesDictionary;
136+
Assert.IsNotNull(names);
137+
names.Should().NotBeEmpty()
138+
.And.HaveCount(3)
139+
.And.ContainInOrder(
140+
new KeyValuePair<UserTypeTest, string>(UserTypeTest.Men, "مرد"),
141+
new KeyValuePair<UserTypeTest, string>(UserTypeTest.Women, "زن"),
142+
new KeyValuePair<UserTypeTest, string>(UserTypeTest.None, "None")
143+
);
144+
}
145+
146+
[TestMethod]
147+
public void TestEnumDisplayDescriptionsDictionary()
148+
{
149+
var names = UserTypeTestEnumExtensions.DisplayDescriptionsDictionary;
150+
Assert.IsNotNull(names);
151+
names.Should().NotBeEmpty()
152+
.And.HaveCount(3)
153+
.And.ContainInOrder(
154+
new KeyValuePair<UserTypeTest, string>(UserTypeTest.Men, "Descمرد"),
155+
new KeyValuePair<UserTypeTest, string>(UserTypeTest.Women, "Descزن"),
156+
new KeyValuePair<UserTypeTest, string>(UserTypeTest.None, "None")
157+
);
158+
}
159+
91160
[TestMethod]
92161
public void TestEnumGetValues()
93162
{

0 commit comments

Comments
 (0)