• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

loresoft / FluentCommand / 6187172006

14 Sep 2023 02:50PM UTC coverage: 51.061% (-0.007%) from 51.068%
6187172006

push

github

pwelter34
Update DataReaderFactoryWriterTests.Generate.verified.txt

952 of 2400 branches covered (0.0%)

Branch coverage included in aggregate %.

2777 of 4903 relevant lines covered (56.64%)

161.33 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

67.61
/src/FluentCommand.Generators/DataReaderFactoryWriter.cs
1
using FluentCommand.Generators.Models;
2

3
namespace FluentCommand.Generators;
4

5
public static class DataReaderFactoryWriter
6
{
7
    public static string Generate(EntityClass entityClass)
8
    {
9
        if (entityClass == null)
1!
10
            throw new ArgumentNullException(nameof(entityClass));
×
11

12
        var codeBuilder = new IndentedStringBuilder();
1✔
13
        codeBuilder
1✔
14
            .AppendLine("// <auto-generated />")
1✔
15
            .AppendLine("#nullable enable")
1✔
16
            .AppendLine()
1✔
17
            .AppendLine("using global::FluentCommand.Extensions;")
1✔
18
            .AppendLine();
1✔
19

20
        codeBuilder
1✔
21
            .Append("namespace ")
1✔
22
            .AppendLine(entityClass.EntityNamespace)
1✔
23
            .AppendLine("{")
1✔
24
            .IncrementIndent();
1✔
25

26
        codeBuilder
1✔
27
            .AppendLine("/// <summary>")
1✔
28
            .AppendLine("/// Extension methods for FluentCommand")
1✔
29
            .AppendLine("/// </summary>");
1✔
30

31
        codeBuilder
1✔
32
            .Append("[global::System.CodeDom.Compiler.GeneratedCode(\"")
1✔
33
            .Append("FluentCommand.Generators")
1✔
34
            .Append("\", \"")
1✔
35
            .Append("1.0.0.0")
1✔
36
            .AppendLine("\")]");
1✔
37

38
        codeBuilder
1✔
39
            .AppendLine("[global::System.Diagnostics.DebuggerNonUserCodeAttribute]")
1✔
40
            .AppendLine("[global::System.Diagnostics.DebuggerStepThroughAttribute]")
1✔
41
            .Append("public static partial class ")
1✔
42
            .Append(entityClass.EntityName)
1✔
43
            .AppendLine("DataReaderExtensions")
1✔
44
            .AppendLine("{")
1✔
45
            .IncrementIndent();
1✔
46

47
        WriteQueryEntity(codeBuilder, entityClass);
1✔
48

49
        WriteQuerySingleEntity(codeBuilder, entityClass);
1✔
50

51
        WriteQueryEntityTask(codeBuilder, entityClass);
1✔
52

53
        WriteQuerySingleEntityTask(codeBuilder, entityClass);
1✔
54

55
        WriteEntityFactory(codeBuilder, entityClass);
1✔
56

57
        codeBuilder
1✔
58
            .DecrementIndent()
1✔
59
            .AppendLine("}") // class
1✔
60
            .DecrementIndent()
1✔
61
            .AppendLine("}"); // namespace
1✔
62

63
        return codeBuilder.ToString();
1✔
64
    }
65

66
    private static void WriteQuerySingleEntityTask(IndentedStringBuilder codeBuilder, EntityClass entity)
67
    {
68
        // public static Task<Entity> QuerySingleEntityAsync(this IDataQueryAsync dataQuery) => QuerySingleAsync(dataQuery, EntityFactory);
69
        codeBuilder
1✔
70
            .AppendLine("/// <summary>")
1✔
71
            .Append("/// Executes the query and returns the first row in the result as a <see cref=\"T:")
1✔
72
            .Append(entity.EntityNamespace)
1✔
73
            .Append(".")
1✔
74
            .Append(entity.EntityName)
1✔
75
            .AppendLine("\"/> object.")
1✔
76
            .AppendLine("/// </summary>")
1✔
77
            .AppendLine("/// <param name=\"dataQuery\">The <see cref=\"T:FluentCommand.IDataQueryAsync\"/> for this extension method.</param>")
1✔
78
            .AppendLine("/// <param name=\"cancellationToken\">The cancellation instruction.</param>")
1✔
79
            .AppendLine("/// <returns>")
1✔
80
            .Append("/// A instance of <see cref=\"T:")
1✔
81
            .Append(entity.EntityNamespace)
1✔
82
            .Append(".")
1✔
83
            .Append(entity.EntityName)
1✔
84
            .AppendLine("\"/>  if row exists; otherwise null.")
1✔
85
            .AppendLine("/// </returns>")
1✔
86
            .Append("public static global::System.Threading.Tasks.Task<")
1✔
87
            .Append(entity.EntityNamespace)
1✔
88
            .Append(".")
1✔
89
            .Append(entity.EntityName)
1✔
90
            .Append("> QuerySingle")
1✔
91
            .AppendLine("Async<TEntity>(")
1✔
92
            .IncrementIndent()
1✔
93
            .AppendLine("this global::FluentCommand.IDataQueryAsync dataQuery,")
1✔
94
            .AppendLine("global::System.Threading.CancellationToken cancellationToken = default)")
1✔
95
            .Append("where TEntity : ")
1✔
96
            .Append(entity.EntityNamespace)
1✔
97
            .Append(".")
1✔
98
            .AppendLine(entity.EntityName)
1✔
99
            .DecrementIndent()
1✔
100
            .AppendLine("{")
1✔
101
            .IncrementIndent()
1✔
102
            .Append("return dataQuery.QuerySingleAsync<")
1✔
103
            .Append(entity.EntityNamespace)
1✔
104
            .Append(".")
1✔
105
            .Append(entity.EntityName)
1✔
106
            .AppendLine(">(")
1✔
107
            .IncrementIndent()
1✔
108
            .Append("factory: ")
1✔
109
            .Append(entity.EntityName)
1✔
110
            .Append("DataReaderExtensions.")
1✔
111
            .Append(entity.EntityName)
1✔
112
            .AppendLine("Factory,")
1✔
113
            .AppendLine("commandBehavior: global::System.Data.CommandBehavior.SequentialAccess |")
1✔
114
            .AppendLine("                 global::System.Data.CommandBehavior.SingleResult |")
1✔
115
            .AppendLine("                 global::System.Data.CommandBehavior.SingleRow,")
1✔
116
            .AppendLine("cancellationToken: cancellationToken);")
1✔
117
            .DecrementIndent()
1✔
118
            .DecrementIndent()
1✔
119
            .AppendLine("}")
1✔
120
            .AppendLine();
1✔
121
    }
1✔
122

123
    private static void WriteQueryEntityTask(IndentedStringBuilder codeBuilder, EntityClass entity)
124
    {
125
        // public static Task<IEnumerable<Entity>> QueryEntityAsync(this IDataQueryAsync dataQuery) => QueryAsync(dataQuery, EntityFactory);
126
        codeBuilder
1✔
127
            .AppendLine("/// <summary>")
1✔
128
            .Append("/// Executes the command against the connection and converts the results to <see cref=\"T:")
1✔
129
            .Append(entity.EntityNamespace)
1✔
130
            .Append(".")
1✔
131
            .Append(entity.EntityName)
1✔
132
            .AppendLine("\"/> objects.")
1✔
133
            .AppendLine("/// </summary>")
1✔
134
            .AppendLine("/// <param name=\"dataQuery\">The <see cref=\"T:FluentCommand.IDataQueryAsync\"/> for this extension method.</param>")
1✔
135
            .AppendLine("/// <param name=\"cancellationToken\">The cancellation instruction.</param>")
1✔
136
            .AppendLine("/// <returns>")
1✔
137
            .Append("/// An <see cref=\"T:System.Collections.Generic.IEnumerable`1\" /> of <see cref=\"T:")
1✔
138
            .Append(entity.EntityNamespace)
1✔
139
            .Append(".")
1✔
140
            .Append(entity.EntityName)
1✔
141
            .AppendLine("\"/> objects.")
1✔
142
            .AppendLine("/// </returns>")
1✔
143
            .Append("public static global::System.Threading.Tasks.Task<global::System.Collections.Generic.IEnumerable<")
1✔
144
            .Append(entity.EntityNamespace)
1✔
145
            .Append(".")
1✔
146
            .Append(entity.EntityName)
1✔
147
            .AppendLine(">> QueryAsync<TEntity>(")
1✔
148
            .IncrementIndent()
1✔
149
            .AppendLine("this global::FluentCommand.IDataQueryAsync dataQuery,")
1✔
150
            .AppendLine("global::System.Threading.CancellationToken cancellationToken = default)")
1✔
151
            .Append("where TEntity : ")
1✔
152
            .Append(entity.EntityNamespace)
1✔
153
            .Append(".")
1✔
154
            .AppendLine(entity.EntityName)
1✔
155
            .DecrementIndent()
1✔
156
            .AppendLine("{")
1✔
157
            .IncrementIndent()
1✔
158
            .Append("return dataQuery.QueryAsync<")
1✔
159
            .Append(entity.EntityNamespace)
1✔
160
            .Append(".")
1✔
161
            .Append(entity.EntityName)
1✔
162
            .AppendLine(">(")
1✔
163
            .IncrementIndent()
1✔
164
            .Append("factory: ")
1✔
165
            .Append(entity.EntityName)
1✔
166
            .Append("DataReaderExtensions.")
1✔
167
            .Append(entity.EntityName)
1✔
168
            .AppendLine("Factory,")
1✔
169
            .AppendLine("commandBehavior: global::System.Data.CommandBehavior.SequentialAccess |")
1✔
170
            .AppendLine("                 global::System.Data.CommandBehavior.SingleResult,")
1✔
171
            .AppendLine("cancellationToken: cancellationToken);")
1✔
172
            .DecrementIndent()
1✔
173
            .DecrementIndent()
1✔
174
            .AppendLine("}")
1✔
175
            .AppendLine();
1✔
176
    }
1✔
177

178
    private static void WriteQuerySingleEntity(IndentedStringBuilder codeBuilder, EntityClass entity)
179
    {
180
        // public static Entity QuerySingleEntity(this IDataQuery dataQuery) => QuerySingle(dataQuery, EntityFactory);
181
        codeBuilder
1✔
182
            .AppendLine("/// <summary>")
1✔
183
            .Append("/// Executes the query and returns the first row in the result as a <see cref=\"T:")
1✔
184
            .Append(entity.EntityNamespace)
1✔
185
            .Append(".")
1✔
186
            .Append(entity.EntityName)
1✔
187
            .AppendLine("\"/> object.")
1✔
188
            .AppendLine("/// </summary>")
1✔
189
            .AppendLine("/// <param name=\"dataQuery\">The <see cref=\"T:FluentCommand.IDataQuery\"/> for this extension method.</param>")
1✔
190
            .AppendLine("/// <returns>")
1✔
191
            .Append("/// A instance of <see cref=\"T:")
1✔
192
            .Append(entity.EntityNamespace)
1✔
193
            .Append(".")
1✔
194
            .Append(entity.EntityName)
1✔
195
            .AppendLine("\"/>  if row exists; otherwise null.")
1✔
196
            .AppendLine("/// </returns>")
1✔
197
            .Append("public static ")
1✔
198
            .Append(entity.EntityNamespace)
1✔
199
            .Append(".")
1✔
200
            .Append(entity.EntityName)
1✔
201
            .AppendLine(" QuerySingle<TEntity>(")
1✔
202
            .IncrementIndent()
1✔
203
            .AppendLine("this global::FluentCommand.IDataQuery dataQuery)")
1✔
204
            .Append("where TEntity : ")
1✔
205
            .Append(entity.EntityNamespace)
1✔
206
            .Append(".")
1✔
207
            .AppendLine(entity.EntityName)
1✔
208
            .DecrementIndent()
1✔
209
            .AppendLine("{")
1✔
210
            .IncrementIndent()
1✔
211
            .Append("return dataQuery.QuerySingle<")
1✔
212
            .Append(entity.EntityNamespace)
1✔
213
            .Append(".")
1✔
214
            .Append(entity.EntityName)
1✔
215
            .AppendLine(">(")
1✔
216
            .IncrementIndent()
1✔
217
            .Append("factory: ")
1✔
218
            .Append(entity.EntityName)
1✔
219
            .Append("DataReaderExtensions.")
1✔
220
            .Append(entity.EntityName)
1✔
221
            .AppendLine("Factory,")
1✔
222
            .AppendLine("commandBehavior: global::System.Data.CommandBehavior.SequentialAccess |")
1✔
223
            .AppendLine("                 global::System.Data.CommandBehavior.SingleResult |")
1✔
224
            .AppendLine("                 global::System.Data.CommandBehavior.SingleRow);")
1✔
225
            .DecrementIndent()
1✔
226
            .DecrementIndent()
1✔
227
            .AppendLine("}")
1✔
228
            .AppendLine();
1✔
229
    }
1✔
230

231
    private static void WriteQueryEntity(IndentedStringBuilder codeBuilder, EntityClass entity)
232
    {
233
        // public static IEnumerable<Entity> QueryEntity(this IDataQuery dataQuery) => Query(dataQuery, EntityFactory);
234
        codeBuilder
1✔
235
            .AppendLine("/// <summary>")
1✔
236
            .Append("/// Executes the command against the connection and converts the results to <see cref=\"T:")
1✔
237
            .Append(entity.EntityNamespace)
1✔
238
            .Append(".")
1✔
239
            .Append(entity.EntityName)
1✔
240
            .AppendLine("\"/> objects.")
1✔
241
            .AppendLine("/// </summary>")
1✔
242
            .AppendLine("/// <param name=\"dataQuery\">The <see cref=\"T:FluentCommand.IDataQuery\"/> for this extension method.</param>")
1✔
243
            .AppendLine("/// <returns>")
1✔
244
            .Append("/// An <see cref=\"T:System.Collections.Generic.IEnumerable`1\" /> of <see cref=\"T:")
1✔
245
            .Append(entity.EntityNamespace)
1✔
246
            .Append(".")
1✔
247
            .Append(entity.EntityName)
1✔
248
            .AppendLine("\"/> objects.")
1✔
249
            .AppendLine("/// </returns>")
1✔
250
            .Append("public static global::System.Collections.Generic.IEnumerable<")
1✔
251
            .Append(entity.EntityNamespace)
1✔
252
            .Append(".")
1✔
253
            .Append(entity.EntityName)
1✔
254
            .AppendLine("> Query<TEntity>(")
1✔
255
            .IncrementIndent()
1✔
256
            .AppendLine("this global::FluentCommand.IDataQuery dataQuery)")
1✔
257
            .Append("where TEntity : ")
1✔
258
            .Append(entity.EntityNamespace)
1✔
259
            .Append(".")
1✔
260
            .AppendLine(entity.EntityName)
1✔
261
            .DecrementIndent()
1✔
262
            .AppendLine("{")
1✔
263
            .IncrementIndent()
1✔
264
            .Append("return dataQuery.Query<")
1✔
265
            .Append(entity.EntityNamespace)
1✔
266
            .Append(".")
1✔
267
            .Append(entity.EntityName)
1✔
268
            .AppendLine(">(")
1✔
269
            .IncrementIndent()
1✔
270
            .Append("factory: ")
1✔
271
            .Append(entity.EntityName)
1✔
272
            .Append("DataReaderExtensions.")
1✔
273
            .Append(entity.EntityName)
1✔
274
            .AppendLine("Factory,")
1✔
275
            .AppendLine("commandBehavior: global::System.Data.CommandBehavior.SequentialAccess |")
1✔
276
            .AppendLine("                 global::System.Data.CommandBehavior.SingleResult);")
1✔
277
            .DecrementIndent()
1✔
278
            .DecrementIndent()
1✔
279
            .AppendLine("}")
1✔
280
            .AppendLine();
1✔
281
    }
1✔
282

283
    private static void WriteEntityFactory(IndentedStringBuilder codeBuilder, EntityClass entity)
284
    {
285
        codeBuilder
1✔
286
            .AppendLine("/// <summary>")
1✔
287
            .Append("/// A factory for creating <see cref=\"T:")
1✔
288
            .Append(entity.EntityNamespace)
1✔
289
            .Append(".")
1✔
290
            .Append(entity.EntityName)
1✔
291
            .AppendLine("\"/> objects from the current row in the specified <paramref name=\"dataRecord\"/>.")
1✔
292
            .AppendLine("/// </summary>")
1✔
293
            .AppendLine("/// <param name=\"dataRecord\">The open <see cref=\"T:System.Data.IDataReader\"/> to get the object from.</param>")
1✔
294
            .AppendLine("/// <returns>")
1✔
295
            .Append("/// A instance of <see cref=\"")
1✔
296
            .Append(entity.EntityNamespace)
1✔
297
            .Append(".")
1✔
298
            .Append(entity.EntityName)
1✔
299
            .AppendLine("\"/>  having property names set that match the field names in the <paramref name=\"dataRecord\"/>.")
1✔
300
            .AppendLine("/// </returns>")
1✔
301
            .Append("public static ")
1✔
302
            .Append(entity.EntityNamespace)
1✔
303
            .Append(".")
1✔
304
            .Append(entity.EntityName)
1✔
305
            .Append(" ")
1✔
306
            .Append(entity.EntityName)
1✔
307
            .AppendLine("Factory(this global::System.Data.IDataReader dataRecord)")
1✔
308
            .AppendLine("{")
1✔
309
            .IncrementIndent()
1✔
310
            .AppendLine("if (dataRecord == null)")
1✔
311
            .IncrementIndent()
1✔
312
            .AppendLine("throw new global::System.ArgumentNullException(nameof(dataRecord));")
1✔
313
            .DecrementIndent()
1✔
314
            .AppendLine();
1✔
315

316
        foreach (var entityProperty in entity.Properties)
12✔
317
        {
318
            var aliasType = GetAliasMap(entityProperty.PropertyType);
5✔
319
            var fieldName = CamelCase(entityProperty.PropertyName);
5✔
320

321
            // local variable
322
            codeBuilder
5✔
323
                .Append(aliasType)
5✔
324
                .Append(" v_")
5✔
325
                .Append(fieldName)
5✔
326
                .AppendLine(" = default;");
5✔
327
        }
328

329
        codeBuilder
1✔
330
            .AppendLine()
1✔
331
            .AppendLine("for (var __index = 0; __index < dataRecord.FieldCount; __index++)")
1✔
332
            .AppendLine("{")
1✔
333
            .IncrementIndent()
1✔
334
            .AppendLine("if (dataRecord.IsDBNull(__index))")
1✔
335
            .IncrementIndent()
1✔
336
            .AppendLine(" continue;")
1✔
337
            .DecrementIndent()
1✔
338
            .AppendLine();
1✔
339

340
        codeBuilder
1✔
341
            .AppendLine("var __name = dataRecord.GetName(__index);")
1✔
342
            .AppendLine("switch (__name)")
1✔
343
            .AppendLine("{")
1✔
344
            .IncrementIndent();
1✔
345

346
        foreach (var entityProperty in entity.Properties)
12✔
347
        {
348
            var fieldName = CamelCase(entityProperty.PropertyName);
5✔
349

350
            codeBuilder
5✔
351
                .Append("case nameof(")
5✔
352
                .Append(entity.EntityNamespace)
5✔
353
                .Append(".")
5✔
354
                .Append(entity.EntityName)
5✔
355
                .Append(".")
5✔
356
                .Append(entityProperty.PropertyName)
5✔
357
                .AppendLine("):");
5✔
358

359
            if (string.IsNullOrEmpty(entityProperty.ConverterName))
5!
360
            {
361
                var readerName = GetReaderName(entityProperty.PropertyType);
5✔
362

363
                codeBuilder
5✔
364
                    .IncrementIndent()
5✔
365
                    .Append("v_")
5✔
366
                    .Append(fieldName)
5✔
367
                    .Append(" = dataRecord.")
5✔
368
                    .Append(readerName)
5✔
369
                    .AppendLine("(__index);")
5✔
370
                    .AppendLine("break;")
5✔
371
                    .DecrementIndent();
5✔
372
            }
373
            else
374
            {
375
                // create converter via singleton helper
376
                codeBuilder
×
377
                    .IncrementIndent()
×
378
                    .Append("var c_")
×
379
                    .Append(fieldName)
×
380
                    .Append(" = global::FluentCommand.Internal.Singleton<")
×
381
                    .Append(entityProperty.ConverterName)
×
382
                    .AppendLine(">.Current")
×
383
                    .IncrementIndent()
×
384
                    .Append("as global::FluentCommand.IDataFieldConverter<")
×
385
                    .Append(entityProperty.PropertyType)
×
386
                    .AppendLine(">;")
×
387
                    .DecrementIndent()
×
388
                    .AppendLine();
×
389

390
                // read via converter instance
391
                codeBuilder
×
392
                    .Append("v_")
×
393
                    .Append(fieldName)
×
394
                    .Append(" = c_")
×
395
                    .Append(fieldName)
×
396
                    .AppendLine(".ReadValue(dataRecord, __index);")
×
397
                    .AppendLine("break;")
×
398
                    .DecrementIndent();
×
399
            }
400
        }
401

402
        codeBuilder
1✔
403
            .DecrementIndent()
1✔
404
            .AppendLine("}") // switch
1✔
405
            .DecrementIndent()
1✔
406
            .AppendLine("}") // for
1✔
407
            .AppendLine();
1✔
408

409
        if (entity.InitializationMode == InitializationMode.Constructor)
1!
410
            WriteReturnConstructor(codeBuilder, entity);
×
411
        else
412
            WriteReturnObjectInitializer(codeBuilder, entity);
1✔
413

414
        codeBuilder
1✔
415
            .DecrementIndent()
1✔
416
            .AppendLine("}") // method
1✔
417
            .AppendLine();
1✔
418
    }
1✔
419

420
    private static void WriteReturnConstructor(IndentedStringBuilder codeBuilder, EntityClass entity)
421
    {
422
        codeBuilder
×
423
            .Append("return new ")
×
424
            .Append(entity.EntityNamespace)
×
425
            .Append(".")
×
426
            .Append(entity.EntityName)
×
427
            .AppendLine("(")
×
428
            .IncrementIndent();
×
429

430
        var index = 0;
×
431
        var count = entity.Properties.Count;
×
432

433
        foreach (var entityProperty in entity.Properties)
×
434
        {
435
            var fieldName = CamelCase(entityProperty.PropertyName);
×
436
            codeBuilder
×
437
                .Append(entityProperty.ParameterName)
×
438
                .Append(": ")
×
439
                .Append(" v_")
×
440
                .Append(fieldName);
×
441

442
            if (++index == count)
×
443
                codeBuilder.AppendLine();
×
444
            else
445
                codeBuilder.AppendLine(",");
×
446
        }
447

448
        codeBuilder
×
449
            .DecrementIndent()
×
450
            .AppendLine(");"); // new
×
451
    }
×
452

453
    private static void WriteReturnObjectInitializer(IndentedStringBuilder codeBuilder, EntityClass entity)
454
    {
455
        codeBuilder
1✔
456
            .Append("return new ")
1✔
457
            .Append(entity.EntityNamespace)
1✔
458
            .Append(".")
1✔
459
            .AppendLine(entity.EntityName)
1✔
460
            .AppendLine("{")
1✔
461
            .IncrementIndent();
1✔
462

463
        var index = 0;
1✔
464
        var count = entity.Properties.Count;
1✔
465

466
        foreach (var entityProperty in entity.Properties)
12✔
467
        {
468
            var fieldName = CamelCase(entityProperty.PropertyName);
5✔
469
            codeBuilder
5✔
470
                .Append(entityProperty.PropertyName)
5✔
471
                .Append(" = ")
5✔
472
                .Append(" v_")
5✔
473
                .Append(fieldName);
5✔
474

475
            if (++index == count)
5✔
476
                codeBuilder.AppendLine();
1✔
477
            else
478
                codeBuilder.AppendLine(",");
4✔
479
        }
480

481
        codeBuilder
1✔
482
            .DecrementIndent()
1✔
483
            .AppendLine("};"); // new
1✔
484
    }
1✔
485

486
    private static string GetAliasMap(string type)
487
    {
488
        return type switch
5!
489
        {
5✔
490
            "System.Boolean" => "bool",
1✔
491
            "System.Byte" => "byte",
×
492
            "System.Byte[]" => "byte[]",
1✔
493
            "System.Char" => "char",
×
494
            "System.Decimal" => "decimal",
×
495
            "System.Double" => "double",
×
496
            "System.Single" => "float",
×
497
            "System.Int16" => "short",
×
498
            "System.Int32" => "int",
1✔
499
            "System.Int64" => "long",
×
500
            "System.String" => "string",
1✔
501
            _ => type,
1✔
502
        };
5✔
503
    }
504

505
    private static string GetReaderName(string propertyType)
506
    {
507
        // remove nullable
508
        var type = propertyType.EndsWith("?") ? propertyType.Substring(0, propertyType.Length - 1) : propertyType;
5!
509

510
        return type switch
5!
511
        {
5✔
512
            "System.Boolean" => "GetBoolean",
1✔
513
            "System.Byte" => "GetByte",
×
514
            "System.Byte[]" => "GetBytes",
1✔
515
            "System.Char" => "GetChar",
×
516
            "System.DateTime" => "GetDateTime",
×
517
            "System.DateTimeOffset" => "GetDateTimeOffset",
1✔
518
            "System.Decimal" => "GetDecimal",
×
519
            "System.Double" => "GetDouble",
×
520
            "System.Guid" => "GetGuid",
×
521
            "System.Single" => "GetFloat",
×
522
            "System.Int16" => "GetInt16",
×
523
            "System.Int32" => "GetInt32",
1✔
524
            "System.Int64" => "GetInt64",
×
525
            "System.String" => "GetString",
1✔
526
            "bool" => "GetBoolean",
×
527
            "byte" => "GetByte",
×
528
            "byte[]" => "GetBytes",
×
529
            "char" => "GetChar",
×
530
            "decimal" => "GetDecimal",
×
531
            "double" => "GetDouble",
×
532
            "float" => "GetFloat",
×
533
            "short" => "GetInt16",
×
534
            "int" => "GetInt32",
×
535
            "long" => "GetInt64",
×
536
            "string" => "GetString",
×
537
            "FluentCommand.ConcurrencyToken" => "GetBytes",
×
538
            _ => $"GetValue<{propertyType}>"
×
539
        };
5✔
540
    }
541

542
    private static string CamelCase(string name)
543
    {
544
        if (string.IsNullOrEmpty(name) || !char.IsUpper(name[0]))
15!
545
            return name;
×
546

547
        char[] chars = name.ToCharArray();
15✔
548
        FixCasing(chars);
15✔
549

550
        return new string(chars);
15✔
551
    }
552

553
    private static void FixCasing(Span<char> chars)
554
    {
555
        for (int i = 0; i < chars.Length; i++)
60✔
556
        {
557
            if (i == 1 && !char.IsUpper(chars[i]))
30✔
558
                break;
559

560
            bool hasNext = (i + 1 < chars.Length);
15✔
561

562
            // Stop when next char is already lowercase.
563
            if (i > 0 && hasNext && !char.IsUpper(chars[i + 1]))
15!
564
            {
565
                // If the next char is a space, lowercase current char before exiting.
566
                if (chars[i + 1] == ' ')
×
567
                    chars[i] = char.ToLowerInvariant(chars[i]);
×
568

569
                break;
×
570
            }
571

572
            chars[i] = char.ToLowerInvariant(chars[i]);
15✔
573
        }
574
    }
15✔
575
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc