@@ -4,41 +4,79 @@ namespace Thinktecture.CodeAnalysis;
4
4
5
5
public sealed class ParsableCodeGenerator : IInterfaceCodeGenerator < ParsableGeneratorState >
6
6
{
7
- public static readonly IInterfaceCodeGenerator < ParsableGeneratorState > Default = new ParsableCodeGenerator ( false ) ;
8
- public static readonly IInterfaceCodeGenerator < ParsableGeneratorState > ForValidatableEnum = new ParsableCodeGenerator ( true ) ;
7
+ public static readonly IInterfaceCodeGenerator < ParsableGeneratorState > ForValueObject = new ParsableCodeGenerator ( false , false ) ;
8
+ public static readonly IInterfaceCodeGenerator < ParsableGeneratorState > ForEnum = new ParsableCodeGenerator ( true , false ) ;
9
+ public static readonly IInterfaceCodeGenerator < ParsableGeneratorState > ForValidatableEnum = new ParsableCodeGenerator ( true , true ) ;
9
10
11
+ private readonly bool _isForEnum ;
10
12
private readonly bool _isForValidatableEnum ;
11
13
12
14
public string CodeGeneratorName => "Parsable-CodeGenerator" ;
13
15
public string FileNameSuffix => ".Parsable" ;
14
16
15
- private ParsableCodeGenerator ( bool isForValidatableEnum )
17
+ private ParsableCodeGenerator (
18
+ bool isForEnum ,
19
+ bool isForValidatableEnum )
16
20
{
21
+ _isForEnum = isForEnum ;
17
22
_isForValidatableEnum = isForValidatableEnum ;
18
23
}
19
24
20
25
public void GenerateBaseTypes ( StringBuilder sb , ParsableGeneratorState state )
21
26
{
22
27
sb . Append ( @"
23
28
global::System.IParsable<" ) . AppendTypeFullyQualified ( state . Type ) . Append ( ">" ) ;
29
+
30
+ if ( _isForEnum && state . KeyMember ? . IsString ( ) == true )
31
+ {
32
+ sb . Append ( @"
33
+ #if NET9_0_OR_GREATER
34
+ , global::System.ISpanParsable<" ) . AppendTypeFullyQualified ( state . Type ) . Append ( @">
35
+ #endif" ) ;
36
+ }
24
37
}
25
38
26
39
public void GenerateImplementation ( StringBuilder sb , ParsableGeneratorState state )
27
40
{
41
+ var isKeyTypeString = state . KeyMember ? . IsString ( ) == true ;
42
+
28
43
GenerateValidate ( sb , state ) ;
44
+
29
45
GenerateParse ( sb , state ) ;
46
+
47
+ if ( _isForEnum && isKeyTypeString )
48
+ GenerateParseForReadOnlySpanOfChar ( sb , state ) ;
49
+
30
50
GenerateTryParse ( sb , state ) ;
51
+
52
+ if ( _isForEnum && isKeyTypeString )
53
+ GenerateTryParseForReadOnlySpanOfChar ( sb , state ) ;
31
54
}
32
55
33
- private static void GenerateValidate ( StringBuilder sb , ParsableGeneratorState state )
56
+ private void GenerateValidate ( StringBuilder sb , ParsableGeneratorState state )
34
57
{
35
- var keyType = state . KeyMember ? . IsString ( ) == true || state . HasStringBasedValidateMethod ? "string" : state . KeyMember ? . TypeFullyQualified ;
58
+ var isKeyTypeString = state . KeyMember ? . IsString ( ) == true ;
59
+ var keyType = isKeyTypeString || state . HasStringBasedValidateMethod ? "string" : state . KeyMember ? . TypeFullyQualified ;
60
+
36
61
sb . Append ( @"
37
62
private static " ) . AppendTypeFullyQualified ( state . ValidationError ) . Append ( "? Validate<T>(" ) . Append ( keyType ) . Append ( " key, global::System.IFormatProvider? provider, out " ) . AppendTypeFullyQualifiedNullAnnotated ( state . Type ) . Append ( @" result)
38
63
where T : global::Thinktecture.IValueObjectFactory<" ) . AppendTypeFullyQualified ( state . Type ) . Append ( ", " ) . Append ( keyType ) . Append ( ", " ) . AppendTypeFullyQualified ( state . ValidationError ) . Append ( @">
39
64
{
40
65
return T.Validate(key, provider, out result);
41
66
}" ) ;
67
+
68
+ if ( _isForEnum && isKeyTypeString )
69
+ {
70
+ sb . Append ( @"
71
+
72
+ #if NET9_0_OR_GREATER
73
+ private static " ) . AppendTypeFullyQualified ( state . ValidationError ) . Append ( "? Validate<T>(global::System.ReadOnlySpan<char> key, global::System.IFormatProvider? provider, out " ) . AppendTypeFullyQualifiedNullAnnotated ( state . Type ) . Append ( @" result)
74
+ where T : global::Thinktecture.IValueObjectFactory<" ) . AppendTypeFullyQualified ( state . Type ) . Append ( ", global::System.ReadOnlySpan<char>, " ) . AppendTypeFullyQualified ( state . ValidationError ) . Append ( @">
75
+ {
76
+ return T.Validate(key, provider, out result);
77
+ }
78
+ #endif" ) ;
79
+ }
42
80
}
43
81
44
82
private void GenerateParse ( StringBuilder sb , ParsableGeneratorState state )
@@ -79,6 +117,39 @@ private void GenerateParse(StringBuilder sb, ParsableGeneratorState state)
79
117
}
80
118
}
81
119
120
+ private void GenerateParseForReadOnlySpanOfChar ( StringBuilder sb , ParsableGeneratorState state )
121
+ {
122
+ sb . Append ( @"
123
+
124
+ #if NET9_0_OR_GREATER
125
+ /// <inheritdoc />
126
+ public static " ) . AppendTypeFullyQualified ( state . Type ) . Append ( @" Parse(global::System.ReadOnlySpan<char> s, global::System.IFormatProvider? provider)
127
+ {" ) ;
128
+
129
+ sb . Append ( @"
130
+ var validationError = Validate<" ) . AppendTypeFullyQualified ( state . Type ) . Append ( ">(s, provider, out var result);" ) ;
131
+
132
+ if ( _isForValidatableEnum )
133
+ {
134
+ sb . Append ( @"
135
+ return result!;
136
+ }" ) ;
137
+ }
138
+ else
139
+ {
140
+ sb . Append ( @"
141
+
142
+ if(validationError is null)
143
+ return result!;
144
+
145
+ throw new global::System.FormatException(validationError.ToString() ?? ""Unable to parse \""" ) . Append ( state . Type . Name ) . Append ( @"\""."");
146
+ }" ) ;
147
+ }
148
+
149
+ sb . Append ( @"
150
+ #endif" ) ;
151
+ }
152
+
82
153
private void GenerateTryParse ( StringBuilder sb , ParsableGeneratorState state )
83
154
{
84
155
sb . Append ( @"
@@ -127,4 +198,34 @@ public static bool TryParse(
127
198
}" ) ;
128
199
}
129
200
}
201
+
202
+ private void GenerateTryParseForReadOnlySpanOfChar ( StringBuilder sb , ParsableGeneratorState state )
203
+ {
204
+ sb . Append ( @"
205
+
206
+ #if NET9_0_OR_GREATER
207
+ /// <inheritdoc />
208
+ public static bool TryParse(
209
+ global::System.ReadOnlySpan<char> s,
210
+ global::System.IFormatProvider? provider,
211
+ [global::System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] out " ) . AppendTypeFullyQualified ( state . Type ) . Append ( @" result)
212
+ {
213
+ var validationError = Validate<" ) . AppendTypeFullyQualified ( state . Type ) . Append ( ">(s, provider, out result!);" ) ;
214
+
215
+ if ( _isForValidatableEnum )
216
+ {
217
+ sb . Append ( @"
218
+ return true;
219
+ }" ) ;
220
+ }
221
+ else
222
+ {
223
+ sb . Append ( @"
224
+ return validationError is null;
225
+ }" ) ;
226
+ }
227
+
228
+ sb . Append ( @"
229
+ #endif" ) ;
230
+ }
130
231
}
0 commit comments