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

loresoft / FluentCommand / 10891700765

16 Sep 2024 08:36PM UTC coverage: 54.514%. First build
10891700765

push

github

pwelter34
add GenerateReaderAttribute

1672 of 3548 branches covered (47.13%)

Branch coverage included in aggregate %.

37 of 131 new or added lines in 9 files covered. (28.24%)

4221 of 7262 relevant lines covered (58.12%)

229.05 hits per line

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

66.09
/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
            .Append("public static partial class ")
1✔
31
            .Append(entityClass.EntityName)
1✔
32
            .AppendLine("DataReaderExtensions")
1✔
33
            .AppendLine("{")
1✔
34
            .IncrementIndent();
1✔
35

36
        WriteQueryEntity(codeBuilder, entityClass);
1✔
37

38
        WriteQuerySingleEntity(codeBuilder, entityClass);
1✔
39

40
        WriteQueryEntityTask(codeBuilder, entityClass);
1✔
41

42
        WriteQuerySingleEntityTask(codeBuilder, entityClass);
1✔
43

44
        WriteEntityFactory(codeBuilder, entityClass);
1✔
45

46
        codeBuilder
1✔
47
            .DecrementIndent()
1✔
48
            .AppendLine("}") // class
1✔
49
            .DecrementIndent()
1✔
50
            .AppendLine("}"); // namespace
1✔
51

52
        return codeBuilder.ToString();
1✔
53
    }
54

55
    private static void WriteQuerySingleEntityTask(IndentedStringBuilder codeBuilder, EntityClass entity)
56
    {
57
        // public static Task<Entity> QuerySingleEntityAsync(this IDataQueryAsync dataQuery) => QuerySingleAsync(dataQuery, EntityFactory);
58
        codeBuilder
1✔
59
            .AppendLine("/// <summary>")
1✔
60
            .Append("/// Executes the query and returns the first row in the result as a <see cref=\"T:")
1✔
61
            .Append(entity.FullyQualified)
1✔
62
            .AppendLine("\"/> object.")
1✔
63
            .AppendLine("/// </summary>")
1✔
64
            .AppendLine("/// <param name=\"dataQuery\">The <see cref=\"T:FluentCommand.IDataQueryAsync\"/> for this extension method.</param>")
1✔
65
            .AppendLine("/// <param name=\"cancellationToken\">The cancellation instruction.</param>")
1✔
66
            .AppendLine("/// <returns>")
1✔
67
            .Append("/// A instance of <see cref=\"T:")
1✔
68
            .Append(entity.FullyQualified)
1✔
69
            .AppendLine("\"/>  if row exists; otherwise null.")
1✔
70
            .AppendLine("/// </returns>")
1✔
71
            .Append("[global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"")
1✔
72
            .Append(ThisAssembly.Product)
1✔
73
            .Append("\", \"")
1✔
74
            .Append(ThisAssembly.InformationalVersion)
1✔
75
            .AppendLine("\")]")
1✔
76
            .Append("public static global::System.Threading.Tasks.Task<")
1✔
77
            .Append(entity.FullyQualified)
1✔
78
            .Append("> QuerySingle")
1✔
79
            .AppendLine("Async<TEntity>(")
1✔
80
            .IncrementIndent()
1✔
81
            .AppendLine("this global::FluentCommand.IDataQueryAsync dataQuery,")
1✔
82
            .AppendLine("global::System.Threading.CancellationToken cancellationToken = default)")
1✔
83
            .Append("where TEntity : ")
1✔
84
            .AppendLine(entity.FullyQualified)
1✔
85
            .DecrementIndent()
1✔
86
            .AppendLine("{")
1✔
87
            .IncrementIndent()
1✔
88
            .Append("return dataQuery.QuerySingleAsync<")
1✔
89
            .Append(entity.FullyQualified)
1✔
90
            .AppendLine(">(")
1✔
91
            .IncrementIndent()
1✔
92
            .Append("factory: ")
1✔
93
            .Append(entity.EntityName)
1✔
94
            .Append("DataReaderExtensions.")
1✔
95
            .Append(entity.EntityName)
1✔
96
            .AppendLine("Factory,")
1✔
97
            .AppendLine("commandBehavior: global::System.Data.CommandBehavior.SequentialAccess |")
1✔
98
            .AppendLine("                 global::System.Data.CommandBehavior.SingleResult |")
1✔
99
            .AppendLine("                 global::System.Data.CommandBehavior.SingleRow,")
1✔
100
            .AppendLine("cancellationToken: cancellationToken);")
1✔
101
            .DecrementIndent()
1✔
102
            .DecrementIndent()
1✔
103
            .AppendLine("}")
1✔
104
            .AppendLine();
1✔
105
    }
1✔
106

107
    private static void WriteQueryEntityTask(IndentedStringBuilder codeBuilder, EntityClass entity)
108
    {
109
        // public static Task<IEnumerable<Entity>> QueryEntityAsync(this IDataQueryAsync dataQuery) => QueryAsync(dataQuery, EntityFactory);
110
        codeBuilder
1✔
111
            .AppendLine("/// <summary>")
1✔
112
            .Append("/// Executes the command against the connection and converts the results to <see cref=\"T:")
1✔
113
            .Append(entity.FullyQualified)
1✔
114
            .AppendLine("\"/> objects.")
1✔
115
            .AppendLine("/// </summary>")
1✔
116
            .AppendLine("/// <param name=\"dataQuery\">The <see cref=\"T:FluentCommand.IDataQueryAsync\"/> for this extension method.</param>")
1✔
117
            .AppendLine("/// <param name=\"cancellationToken\">The cancellation instruction.</param>")
1✔
118
            .AppendLine("/// <returns>")
1✔
119
            .Append("/// An <see cref=\"T:System.Collections.Generic.IEnumerable`1\" /> of <see cref=\"T:")
1✔
120
            .Append(entity.FullyQualified)
1✔
121
            .AppendLine("\"/> objects.")
1✔
122
            .AppendLine("/// </returns>")
1✔
123
            .Append("[global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"")
1✔
124
            .Append(ThisAssembly.Product)
1✔
125
            .Append("\", \"")
1✔
126
            .Append(ThisAssembly.InformationalVersion)
1✔
127
            .AppendLine("\")]")
1✔
128
            .Append("public static global::System.Threading.Tasks.Task<global::System.Collections.Generic.IEnumerable<")
1✔
129
            .Append(entity.FullyQualified)
1✔
130
            .AppendLine(">> QueryAsync<TEntity>(")
1✔
131
            .IncrementIndent()
1✔
132
            .AppendLine("this global::FluentCommand.IDataQueryAsync dataQuery,")
1✔
133
            .AppendLine("global::System.Threading.CancellationToken cancellationToken = default)")
1✔
134
            .Append("where TEntity : ")
1✔
135
            .AppendLine(entity.FullyQualified)
1✔
136
            .DecrementIndent()
1✔
137
            .AppendLine("{")
1✔
138
            .IncrementIndent()
1✔
139
            .Append("return dataQuery.QueryAsync<")
1✔
140
            .Append(entity.FullyQualified)
1✔
141
            .AppendLine(">(")
1✔
142
            .IncrementIndent()
1✔
143
            .Append("factory: ")
1✔
144
            .Append(entity.EntityName)
1✔
145
            .Append("DataReaderExtensions.")
1✔
146
            .Append(entity.EntityName)
1✔
147
            .AppendLine("Factory,")
1✔
148
            .AppendLine("commandBehavior: global::System.Data.CommandBehavior.SequentialAccess |")
1✔
149
            .AppendLine("                 global::System.Data.CommandBehavior.SingleResult,")
1✔
150
            .AppendLine("cancellationToken: cancellationToken);")
1✔
151
            .DecrementIndent()
1✔
152
            .DecrementIndent()
1✔
153
            .AppendLine("}")
1✔
154
            .AppendLine();
1✔
155
    }
1✔
156

157
    private static void WriteQuerySingleEntity(IndentedStringBuilder codeBuilder, EntityClass entity)
158
    {
159
        // public static Entity QuerySingleEntity(this IDataQuery dataQuery) => QuerySingle(dataQuery, EntityFactory);
160
        codeBuilder
1✔
161
            .AppendLine("/// <summary>")
1✔
162
            .Append("/// Executes the query and returns the first row in the result as a <see cref=\"T:")
1✔
163
            .Append(entity.FullyQualified)
1✔
164
            .AppendLine("\"/> object.")
1✔
165
            .AppendLine("/// </summary>")
1✔
166
            .AppendLine("/// <param name=\"dataQuery\">The <see cref=\"T:FluentCommand.IDataQuery\"/> for this extension method.</param>")
1✔
167
            .AppendLine("/// <returns>")
1✔
168
            .Append("/// A instance of <see cref=\"T:")
1✔
169
            .Append(entity.FullyQualified)
1✔
170
            .AppendLine("\"/>  if row exists; otherwise null.")
1✔
171
            .AppendLine("/// </returns>")
1✔
172
            .Append("[global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"")
1✔
173
            .Append(ThisAssembly.Product)
1✔
174
            .Append("\", \"")
1✔
175
            .Append(ThisAssembly.InformationalVersion)
1✔
176
            .AppendLine("\")]")
1✔
177
            .Append("public static ")
1✔
178
            .Append(entity.FullyQualified)
1✔
179
            .AppendLine(" QuerySingle<TEntity>(")
1✔
180
            .IncrementIndent()
1✔
181
            .AppendLine("this global::FluentCommand.IDataQuery dataQuery)")
1✔
182
            .Append("where TEntity : ")
1✔
183
            .AppendLine(entity.FullyQualified)
1✔
184
            .DecrementIndent()
1✔
185
            .AppendLine("{")
1✔
186
            .IncrementIndent()
1✔
187
            .Append("return dataQuery.QuerySingle<")
1✔
188
            .Append(entity.FullyQualified)
1✔
189
            .AppendLine(">(")
1✔
190
            .IncrementIndent()
1✔
191
            .Append("factory: ")
1✔
192
            .Append(entity.EntityName)
1✔
193
            .Append("DataReaderExtensions.")
1✔
194
            .Append(entity.EntityName)
1✔
195
            .AppendLine("Factory,")
1✔
196
            .AppendLine("commandBehavior: global::System.Data.CommandBehavior.SequentialAccess |")
1✔
197
            .AppendLine("                 global::System.Data.CommandBehavior.SingleResult |")
1✔
198
            .AppendLine("                 global::System.Data.CommandBehavior.SingleRow);")
1✔
199
            .DecrementIndent()
1✔
200
            .DecrementIndent()
1✔
201
            .AppendLine("}")
1✔
202
            .AppendLine();
1✔
203
    }
1✔
204

205
    private static void WriteQueryEntity(IndentedStringBuilder codeBuilder, EntityClass entity)
206
    {
207
        // public static IEnumerable<Entity> QueryEntity(this IDataQuery dataQuery) => Query(dataQuery, EntityFactory);
208
        codeBuilder
1✔
209
            .AppendLine("/// <summary>")
1✔
210
            .Append("/// Executes the command against the connection and converts the results to <see cref=\"T:")
1✔
211
            .Append(entity.FullyQualified)
1✔
212
            .AppendLine("\"/> objects.")
1✔
213
            .AppendLine("/// </summary>")
1✔
214
            .AppendLine("/// <param name=\"dataQuery\">The <see cref=\"T:FluentCommand.IDataQuery\"/> for this extension method.</param>")
1✔
215
            .AppendLine("/// <returns>")
1✔
216
            .Append("/// An <see cref=\"T:System.Collections.Generic.IEnumerable`1\" /> of <see cref=\"T:")
1✔
217
            .Append(entity.FullyQualified)
1✔
218
            .AppendLine("\"/> objects.")
1✔
219
            .AppendLine("/// </returns>")
1✔
220
            .Append("[global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"")
1✔
221
            .Append(ThisAssembly.Product)
1✔
222
            .Append("\", \"")
1✔
223
            .Append(ThisAssembly.InformationalVersion)
1✔
224
            .AppendLine("\")]")
1✔
225
            .Append("public static global::System.Collections.Generic.IEnumerable<")
1✔
226
            .Append(entity.FullyQualified)
1✔
227
            .AppendLine("> Query<TEntity>(")
1✔
228
            .IncrementIndent()
1✔
229
            .AppendLine("this global::FluentCommand.IDataQuery dataQuery)")
1✔
230
            .Append("where TEntity : ")
1✔
231
            .AppendLine(entity.FullyQualified)
1✔
232
            .DecrementIndent()
1✔
233
            .AppendLine("{")
1✔
234
            .IncrementIndent()
1✔
235
            .Append("return dataQuery.Query<")
1✔
236
            .Append(entity.FullyQualified)
1✔
237
            .AppendLine(">(")
1✔
238
            .IncrementIndent()
1✔
239
            .Append("factory: ")
1✔
240
            .Append(entity.EntityName)
1✔
241
            .Append("DataReaderExtensions.")
1✔
242
            .Append(entity.EntityName)
1✔
243
            .AppendLine("Factory,")
1✔
244
            .AppendLine("commandBehavior: global::System.Data.CommandBehavior.SequentialAccess |")
1✔
245
            .AppendLine("                 global::System.Data.CommandBehavior.SingleResult);")
1✔
246
            .DecrementIndent()
1✔
247
            .DecrementIndent()
1✔
248
            .AppendLine("}")
1✔
249
            .AppendLine();
1✔
250
    }
1✔
251

252
    private static void WriteEntityFactory(IndentedStringBuilder codeBuilder, EntityClass entity)
253
    {
254
        codeBuilder
1✔
255
            .AppendLine("/// <summary>")
1✔
256
            .Append("/// A factory for creating <see cref=\"T:")
1✔
257
            .Append(entity.FullyQualified)
1✔
258
            .AppendLine("\"/> objects from the current row in the specified <paramref name=\"dataRecord\"/>.")
1✔
259
            .AppendLine("/// </summary>")
1✔
260
            .AppendLine("/// <param name=\"dataRecord\">The open <see cref=\"T:System.Data.IDataReader\"/> to get the object from.</param>")
1✔
261
            .AppendLine("/// <returns>")
1✔
262
            .Append("/// A instance of <see cref=\"")
1✔
263
            .Append(entity.FullyQualified)
1✔
264
            .AppendLine("\"/>  having property names set that match the field names in the <paramref name=\"dataRecord\"/>.")
1✔
265
            .AppendLine("/// </returns>")
1✔
266
            .Append("[global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"")
1✔
267
            .Append(ThisAssembly.Product)
1✔
268
            .Append("\", \"")
1✔
269
            .Append(ThisAssembly.InformationalVersion)
1✔
270
            .AppendLine("\")]")
1✔
271
            .Append("public static ")
1✔
272
            .Append(entity.FullyQualified)
1✔
273
            .Append(" ")
1✔
274
            .Append(entity.EntityName)
1✔
275
            .AppendLine("Factory(this global::System.Data.IDataReader dataRecord)")
1✔
276
            .AppendLine("{")
1✔
277
            .IncrementIndent()
1✔
278
            .AppendLine("if (dataRecord == null)")
1✔
279
            .IncrementIndent()
1✔
280
            .AppendLine("throw new global::System.ArgumentNullException(nameof(dataRecord));")
1✔
281
            .DecrementIndent()
1✔
282
            .AppendLine();
1✔
283

284
        foreach (var entityProperty in entity.Properties)
12✔
285
        {
286
            var aliasType = GetAliasMap(entityProperty.PropertyType);
5✔
287
            var fieldName = CamelCase(entityProperty.PropertyName);
5✔
288

289
            // local variable
290
            codeBuilder
5✔
291
                .Append(aliasType)
5✔
292
                .Append(" v_")
5✔
293
                .Append(fieldName)
5✔
294
                .Append(" = default")
5✔
295
                .AppendIf("!", _ => !entityProperty.PropertyType.EndsWith("?"))
5✔
296
                .AppendLine(";");
5✔
297
        }
298

299
        codeBuilder
1✔
300
            .AppendLine()
1✔
301
            .AppendLine("for (var __index = 0; __index < dataRecord.FieldCount; __index++)")
1✔
302
            .AppendLine("{")
1✔
303
            .IncrementIndent()
1✔
304
            .AppendLine("if (dataRecord.IsDBNull(__index))")
1✔
305
            .IncrementIndent()
1✔
306
            .AppendLine(" continue;")
1✔
307
            .DecrementIndent()
1✔
308
            .AppendLine();
1✔
309

310
        codeBuilder
1✔
311
            .AppendLine("var __name = dataRecord.GetName(__index);")
1✔
312
            .AppendLine("switch (__name)")
1✔
313
            .AppendLine("{")
1✔
314
            .IncrementIndent();
1✔
315

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

320
            codeBuilder
5✔
321
                .Append("case \"")
5✔
322
                .Append(entityProperty.ColumnName)
5✔
323
                .AppendLine("\":");
5✔
324

325
            if (string.IsNullOrEmpty(entityProperty.ConverterName))
5!
326
            {
327
                var readerName = GetReaderName(entityProperty.PropertyType);
5✔
328

329
                codeBuilder
5✔
330
                    .IncrementIndent()
5✔
331
                    .Append("v_")
5✔
332
                    .Append(fieldName)
5✔
333
                    .Append(" = dataRecord.")
5✔
334
                    .Append(readerName)
5✔
335
                    .AppendLine("(__index);")
5✔
336
                    .AppendLine("break;")
5✔
337
                    .DecrementIndent();
5✔
338
            }
339
            else
340
            {
341
                // create converter via singleton helper
342
                codeBuilder
×
343
                    .IncrementIndent()
×
344
                    .Append("var c_")
×
345
                    .Append(fieldName)
×
346
                    .Append(" = global::FluentCommand.Internal.Singleton<")
×
347
                    .Append(entityProperty.ConverterName)
×
348
                    .AppendLine(">.Current")
×
349
                    .IncrementIndent()
×
350
                    .Append("as global::FluentCommand.IDataFieldConverter<")
×
351
                    .Append(entityProperty.PropertyType)
×
352
                    .AppendLine(">;")
×
353
                    .DecrementIndent()
×
354
                    .AppendLine();
×
355

356
                // read via converter instance
357
                codeBuilder
×
358
                    .Append("v_")
×
359
                    .Append(fieldName)
×
360
                    .Append(" = c_")
×
361
                    .Append(fieldName)
×
362
                    .AppendLine(".ReadValue(dataRecord, __index);")
×
363
                    .AppendLine("break;")
×
364
                    .DecrementIndent();
×
365
            }
366
        }
367

368
        codeBuilder
1✔
369
            .DecrementIndent()
1✔
370
            .AppendLine("}") // switch
1✔
371
            .DecrementIndent()
1✔
372
            .AppendLine("}") // for
1✔
373
            .AppendLine();
1✔
374

375
        if (entity.InitializationMode == InitializationMode.Constructor)
1!
376
            WriteReturnConstructor(codeBuilder, entity);
×
377
        else
378
            WriteReturnObjectInitializer(codeBuilder, entity);
1✔
379

380
        codeBuilder
1✔
381
            .DecrementIndent()
1✔
382
            .AppendLine("}") // method
1✔
383
            .AppendLine();
1✔
384
    }
1✔
385

386
    private static void WriteReturnConstructor(IndentedStringBuilder codeBuilder, EntityClass entity)
387
    {
388
        codeBuilder
×
389
            .Append("return new ")
×
NEW
390
            .Append(entity.FullyQualified)
×
391
            .AppendLine("(")
×
392
            .IncrementIndent();
×
393

394
        var index = 0;
×
395
        var count = entity.Properties.Count;
×
396

397
        foreach (var entityProperty in entity.Properties)
×
398
        {
399
            var fieldName = CamelCase(entityProperty.PropertyName);
×
400
            codeBuilder
×
401
                .Append(entityProperty.ParameterName)
×
402
                .Append(": ")
×
403
                .Append(" v_")
×
404
                .Append(fieldName);
×
405

406
            if (++index == count)
×
407
                codeBuilder.AppendLine();
×
408
            else
409
                codeBuilder.AppendLine(",");
×
410
        }
411

412
        codeBuilder
×
413
            .DecrementIndent()
×
414
            .AppendLine(");"); // new
×
415
    }
×
416

417
    private static void WriteReturnObjectInitializer(IndentedStringBuilder codeBuilder, EntityClass entity)
418
    {
419
        codeBuilder
1✔
420
            .Append("return new ")
1✔
421
            .AppendLine(entity.FullyQualified)
1✔
422
            .AppendLine("{")
1✔
423
            .IncrementIndent();
1✔
424

425
        var index = 0;
1✔
426
        var count = entity.Properties.Count;
1✔
427

428
        foreach (var entityProperty in entity.Properties)
12✔
429
        {
430
            var fieldName = CamelCase(entityProperty.PropertyName);
5✔
431
            codeBuilder
5✔
432
                .Append(entityProperty.PropertyName)
5✔
433
                .Append(" = ")
5✔
434
                .Append(" v_")
5✔
435
                .Append(fieldName);
5✔
436

437
            if (++index == count)
5✔
438
                codeBuilder.AppendLine();
1✔
439
            else
440
                codeBuilder.AppendLine(",");
4✔
441
        }
442

443
        codeBuilder
1✔
444
            .DecrementIndent()
1✔
445
            .AppendLine("};"); // new
1✔
446
    }
1✔
447

448
    private static string GetAliasMap(string type)
449
    {
450
        return type switch
5!
451
        {
5✔
452
            "System.Boolean" => "bool",
1✔
453
            "System.Byte" => "byte",
×
454
            "System.Byte[]" => "byte[]",
1✔
455
            "System.Char" => "char",
×
456
            "System.Decimal" => "decimal",
×
457
            "System.Double" => "double",
×
458
            "System.Single" => "float",
×
459
            "System.Int16" => "short",
×
460
            "System.Int32" => "int",
1✔
461
            "System.Int64" => "long",
×
462
            "System.String" => "string",
1✔
463
            _ => type,
1✔
464
        };
5✔
465
    }
466

467
    private static string GetReaderName(string propertyType)
468
    {
469
        // remove nullable
470
        var type = propertyType.EndsWith("?") ? propertyType.Substring(0, propertyType.Length - 1) : propertyType;
5!
471

472
        return type switch
5!
473
        {
5✔
474
            "System.Boolean" => "GetBoolean",
1✔
475
            "System.Byte" => "GetByte",
×
476
            "System.Byte[]" => "GetBytes",
1✔
477
            "System.Char" => "GetChar",
×
478
            "System.DateTime" => "GetDateTime",
×
479
            "System.DateTimeOffset" => "GetDateTimeOffset",
1✔
480
            "System.Decimal" => "GetDecimal",
×
481
            "System.Double" => "GetDouble",
×
482
            "System.Guid" => "GetGuid",
×
483
            "System.Single" => "GetFloat",
×
484
            "System.Int16" => "GetInt16",
×
485
            "System.Int32" => "GetInt32",
1✔
486
            "System.Int64" => "GetInt64",
×
487
            "System.String" => "GetString",
1✔
488
            "bool" => "GetBoolean",
×
489
            "byte" => "GetByte",
×
490
            "byte[]" => "GetBytes",
×
491
            "char" => "GetChar",
×
492
            "decimal" => "GetDecimal",
×
493
            "double" => "GetDouble",
×
494
            "float" => "GetFloat",
×
495
            "short" => "GetInt16",
×
496
            "int" => "GetInt32",
×
497
            "long" => "GetInt64",
×
498
            "string" => "GetString",
×
499
            "FluentCommand.ConcurrencyToken" => "GetBytes",
×
500
            _ => $"GetValue<{type}>"
×
501
        };
5✔
502
    }
503

504
    private static string CamelCase(string name)
505
    {
506
        if (string.IsNullOrEmpty(name) || !char.IsUpper(name[0]))
15!
507
            return name;
×
508

509
        char[] chars = name.ToCharArray();
15✔
510
        FixCasing(chars);
15✔
511

512
        return new string(chars);
15✔
513
    }
514

515
    private static void FixCasing(Span<char> chars)
516
    {
517
        for (int i = 0; i < chars.Length; i++)
60✔
518
        {
519
            if (i == 1 && !char.IsUpper(chars[i]))
30✔
520
                break;
521

522
            bool hasNext = (i + 1 < chars.Length);
15✔
523

524
            // Stop when next char is already lowercase.
525
            if (i > 0 && hasNext && !char.IsUpper(chars[i + 1]))
15!
526
            {
527
                // If the next char is a space, lowercase current char before exiting.
528
                if (chars[i + 1] == ' ')
×
529
                    chars[i] = char.ToLowerInvariant(chars[i]);
×
530

531
                break;
×
532
            }
533

534
            chars[i] = char.ToLowerInvariant(chars[i]);
15✔
535
        }
536
    }
15✔
537
}
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