Skip to content

Commit 020b24f

Browse files
refactor(decrease-complexity): refactor to decrease complexity (#21)
Refactored CoreHelper and TestHelper to decrease cognitive complexity. Added the Maintainability badge again
1 parent db64d64 commit 020b24f

File tree

4 files changed

+125
-93
lines changed

4 files changed

+125
-93
lines changed

APIMatic.Core.Test/Utilities/TestHelperTest.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,16 @@ public void IsJsonObjectProperSubsetOf_ListInRight()
303303
Assert.IsTrue(TestHelper.IsJsonObjectProperSubsetOf(leftObject: leftObject, rightObject: rightObject, checkValues: true, allowExtra: true, isOrdered: false));
304304
}
305305

306+
[Test]
307+
public void IsJsonObjectProperSubsetOf_EmptyObject()
308+
{
309+
string leftObject = "{}";
310+
311+
string rightObject = "{}";
312+
313+
Assert.IsTrue(TestHelper.IsJsonObjectProperSubsetOf(leftObject: leftObject, rightObject: rightObject, checkValues: true, allowExtra: true, isOrdered: false));
314+
}
315+
306316
[Test]
307317
public void IsSameAsFile_GistURL()
308318
{

APIMatic.Core/Utilities/CoreHelper.cs

Lines changed: 76 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ private static void AppendParameters(StringBuilder queryBuilder, ArraySerializat
129129
// load element value as string
130130
if (pair.Value is ICollection)
131131
{
132-
paramKeyValPair = FlattenCollection(pair.Value as ICollection, arraySerialization, GetSeparator(arraySerialization), true, Uri.EscapeDataString(pair.Key));
132+
paramKeyValPair = FlattenCollection(pair.Value as ICollection, arraySerialization, Uri.EscapeDataString(pair.Key));
133133
}
134134
else
135135
{
@@ -196,7 +196,7 @@ internal static List<KeyValuePair<string, object>> PrepareFormFieldsFromObject(s
196196
}
197197
else if (value is IList enumerable)
198198
{
199-
PrepareFormFieldsForEnumerable(name, arraySerializationFormat, keys, propInfo, enumerable);
199+
PrepareFormFieldsForEnumerable(name, enumerable, arraySerializationFormat, keys, propInfo);
200200
}
201201
else if (value is Stream || value is JToken || value is Enum)
202202
{
@@ -205,30 +205,21 @@ internal static List<KeyValuePair<string, object>> PrepareFormFieldsFromObject(s
205205
}
206206
else if (value is IDictionary dictionary)
207207
{
208-
PrepareFormFieldsForDictionary(name, arraySerializationFormat, keys, propInfo, dictionary);
209-
}
210-
else if (value is CoreJsonObject jsonObject)
211-
{
212-
PrepareFormFieldsFromObject(name, RemoveNullValues(jsonObject.GetStoredObject()), arraySerializationFormat, keys, propInfo);
208+
PrepareFormFieldsForDictionary(name, dictionary, arraySerializationFormat, keys, propInfo);
209+
return keys;
213210
}
214-
else if (value is CoreJsonValue jsonValue)
211+
else if (value is CoreJsonObject || value is CoreJsonValue)
215212
{
216-
PrepareFormFieldsFromObject(name, jsonValue.GetStoredObject(), arraySerializationFormat, keys, propInfo);
213+
PrepareFormFieldsFromObject(name, GetProcessedValue(value), arraySerializationFormat, keys, propInfo);
217214
}
218215
else if (!value.GetType().Namespace.StartsWith("System"))
219216
{
220217
PrepareFormFieldsForCustomTypes(name, value, arraySerializationFormat, keys);
221218
}
222-
else if (value is DateTime dateTime)
223-
{
224-
var convertedValue = GetConvertedValue(value, propInfo);
225-
keys.Add(new KeyValuePair<string, object>(name, convertedValue ?? dateTime.ToString(DateTimeFormat)));
226-
}
227219
else
228220
{
229-
keys.Add(new KeyValuePair<string, object>(name, GetProcessedValue(value)));
221+
keys.Add(new KeyValuePair<string, object>(name, GetProcessedValue(value, propInfo)));
230222
}
231-
232223
return keys;
233224
}
234225

@@ -285,7 +276,7 @@ private static void PrepareFormFieldsForCustomTypes(string name, object value, A
285276
}
286277
}
287278

288-
private static void PrepareFormFieldsForDictionary(string name, ArraySerialization arraySerializationFormat, List<KeyValuePair<string, object>> keys, PropertyInfo propInfo, IDictionary dictionary)
279+
private static void PrepareFormFieldsForDictionary(string name, IDictionary dictionary, ArraySerialization arraySerializationFormat, List<KeyValuePair<string, object>> keys = null, PropertyInfo propInfo = null)
289280
{
290281
foreach (var sName in dictionary.Keys)
291282
{
@@ -296,21 +287,10 @@ private static void PrepareFormFieldsForDictionary(string name, ArraySerializati
296287
}
297288
}
298289

299-
private static void PrepareFormFieldsForEnumerable(string name, ArraySerialization arraySerializationFormat, List<KeyValuePair<string, object>> keys, PropertyInfo propInfo, IList enumerable)
290+
private static void PrepareFormFieldsForEnumerable(string name, IList enumerable, ArraySerialization arraySerializationFormat, List<KeyValuePair<string, object>> keys, PropertyInfo propInfo)
300291
{
301292
var enumerator = enumerable.GetEnumerator();
302-
303-
var hasNested = false;
304-
while (enumerator.MoveNext())
305-
{
306-
var subValue = enumerator.Current;
307-
if (subValue != null && (subValue is JObject || subValue is IList || subValue is IDictionary || !subValue.GetType().Namespace.StartsWith("System")))
308-
{
309-
hasNested = true;
310-
break;
311-
}
312-
}
313-
293+
bool hasNested = HasCustomeNestedType(enumerator);
314294
int i = 0;
315295
enumerator.Reset();
316296
while (enumerator.MoveNext())
@@ -330,28 +310,50 @@ private static void PrepareFormFieldsForEnumerable(string name, ArraySerializati
330310
{
331311
continue;
332312
}
333-
334313
PrepareFormFieldsFromObject(fullSubName, subValue, arraySerializationFormat, keys, propInfo);
335314
i++;
336315
}
337316
}
338317

339-
private static object GetProcessedValue(object value)
318+
private static bool HasCustomeNestedType(IEnumerator enumerator)
319+
{
320+
while (enumerator.MoveNext())
321+
{
322+
var subValue = enumerator.Current;
323+
if (subValue != null && (subValue is JObject || subValue is IList || subValue is IDictionary || !subValue.GetType().Namespace.StartsWith("System")))
324+
{
325+
return true;
326+
}
327+
}
328+
return false;
329+
}
330+
331+
private static object GetProcessedValue(object value, PropertyInfo propInfo = null)
340332
{
341333
if (value is Stream)
342334
{
343335
return value;
344336
}
345-
346337
if (value is Enum)
347338
{
348339
return JsonSerialize(value).Trim('\"');
349340
}
350-
351341
if (value is JToken)
352342
{
353343
return value.ToString();
354344
}
345+
if (value is CoreJsonObject jsonObject)
346+
{
347+
return RemoveNullValues(jsonObject.GetStoredObject());
348+
}
349+
if (value is CoreJsonValue jsonValue)
350+
{
351+
return jsonValue.GetStoredObject();
352+
}
353+
if (value is DateTime dateTime)
354+
{
355+
return GetConvertedValue(dateTime, propInfo) ?? dateTime.ToString(DateTimeFormat);
356+
}
355357
return value;
356358
}
357359

@@ -459,18 +461,17 @@ private static int IndexOf(StringBuilder stringBuilder, string strCheck)
459461
private static string FlattenCollection(
460462
ICollection array,
461463
ArraySerialization fmt,
462-
char separator,
463-
bool urlEncode,
464464
string key = "")
465465
{
466466
StringBuilder builder = new StringBuilder();
467467
string format = GetFormatString(fmt, key, builder);
468468

469469
// append all elements in the array into a string
470470
int index = 0;
471+
char separator = GetSeparator(fmt);
471472
foreach (object element in array)
472473
{
473-
builder.AppendFormat(format, GetElementValue(element, urlEncode), separator, index++);
474+
builder.AppendFormat(format, GetElementValue(element, true), separator, index++);
474475
}
475476

476477
// remove the last separator, if appended
@@ -545,46 +546,54 @@ private static List<KeyValuePair<string, object>> ProcessQueryParamsForCustomTyp
545546

546547
if (kvp.Value.GetType().Namespace.StartsWith("System"))
547548
{
548-
if (kvp.Value is IList)
549-
{
550-
var list = kvp.Value as IList;
551-
552-
if (list?.Count != 0)
553-
{
554-
var item = list[0];
555-
556-
if (item.GetType().Namespace.StartsWith("System"))
557-
{
558-
// List of scalar type
559-
processedParameters.Add(kvp);
560-
}
561-
else
562-
{
563-
// List of custom type
564-
var innerList = PrepareFormFieldsFromObject(kvp.Key, kvp.Value, arraySerializationFormat: ArraySerialization.Indexed);
565-
innerList = ApplySerializationFormatToScalarArrays(innerList);
566-
processedParameters.AddRange(innerList);
567-
}
568-
}
569-
}
570-
else
571-
{
572-
// Scalar type
573-
processedParameters.Add(kvp);
574-
}
549+
HandlePrimitiveTypes(processedParameters, kvp);
575550
}
576551
else
577552
{
578553
// Custom type
579-
var list = PrepareFormFieldsFromObject(kvp.Key, kvp.Value, arraySerializationFormat: ArraySerialization.Indexed);
580-
list = ApplySerializationFormatToScalarArrays(list);
581-
processedParameters.AddRange(list);
554+
HandleCustomType(processedParameters, kvp);
582555
}
583556
}
584557

585558
return processedParameters;
586559
}
587560

561+
private static void HandleCustomType(List<KeyValuePair<string, object>> processedParameters, KeyValuePair<string, object> kvp)
562+
{
563+
var list = PrepareFormFieldsFromObject(kvp.Key, kvp.Value, arraySerializationFormat: ArraySerialization.Indexed);
564+
list = ApplySerializationFormatToScalarArrays(list);
565+
processedParameters.AddRange(list);
566+
}
567+
568+
private static void HandlePrimitiveTypes(List<KeyValuePair<string, object>> processedParameters, KeyValuePair<string, object> kvp)
569+
{
570+
if (kvp.Value is IList)
571+
{
572+
var list = kvp.Value as IList;
573+
574+
if (list?.Count != 0)
575+
{
576+
var item = list[0];
577+
578+
if (item.GetType().Namespace.StartsWith("System"))
579+
{
580+
// List of scalar type
581+
processedParameters.Add(kvp);
582+
}
583+
else
584+
{
585+
// List of custom type
586+
HandleCustomType(processedParameters, kvp);
587+
}
588+
}
589+
}
590+
else
591+
{
592+
// Scalar type
593+
processedParameters.Add(kvp);
594+
}
595+
}
596+
588597
/// <summary>
589598
/// Apply serialization to scalar arrays in custom objects.
590599
/// </summary>

APIMatic.Core/Utilities/TestHelper.cs

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -415,36 +415,49 @@ private static bool IsProperSubsetOf(
415415

416416
if (leftVal is JObject leftSideValue)
417417
{
418-
// If left value is tree, right value should be be tree too
419-
if (!(rightVal is JObject rightSideValue))
420-
{
421-
return false;
422-
}
423-
if (!IsProperSubsetOf(leftSideValue, rightSideValue, checkValues, allowExtra, isOrdered))
424-
{
425-
return false;
426-
}
418+
return IsProperSubsetOfJObject(checkValues, allowExtra, isOrdered, rightVal, leftSideValue);
427419
}
428420
else if (checkValues)
429421
{
430-
// If left value is a primitive, check if it equals right value
431-
if (leftVal is JArray leftJArray)
432-
{
433-
if (!DoesRightValContainsSameItems(leftJArray, rightVal, allowExtra, isOrdered))
434-
{
435-
return false;
436-
}
437-
}
438-
else if (!leftVal.Equals(rightVal))
439-
{
440-
return false;
441-
}
422+
return CheckValuesAreSameOnBothSides(allowExtra, isOrdered, leftVal, rightVal);
442423
}
443424
}
444-
445425
return true;
446426
}
447427

428+
private static bool IsProperSubsetOfJObject(bool checkValues, bool allowExtra, bool isOrdered, object rightVal, JObject leftSideValue)
429+
{
430+
bool isProperSubset = true;
431+
// If left value is tree, right value should be be tree too
432+
if (!(rightVal is JObject rightSideValue))
433+
{
434+
return false;
435+
}
436+
if (!IsProperSubsetOf(leftSideValue, rightSideValue, checkValues, allowExtra, isOrdered))
437+
{
438+
isProperSubset = false;
439+
}
440+
return isProperSubset;
441+
}
442+
443+
private static bool CheckValuesAreSameOnBothSides(bool allowExtra, bool isOrdered, object leftVal, object rightVal)
444+
{
445+
bool isSame = true;
446+
// If left value is a primitive, check if it equals right value
447+
if (leftVal is JArray leftJArray)
448+
{
449+
if (!DoesRightValContainsSameItems(leftJArray, rightVal, allowExtra, isOrdered))
450+
{
451+
isSame = false;
452+
}
453+
}
454+
else if (!leftVal.Equals(rightVal))
455+
{
456+
isSame = false;
457+
}
458+
return isSame;
459+
}
460+
448461
private static bool DoesRightValContainsSameItems(JArray leftJArray, object rightVal, bool allowExtra, bool isOrdered)
449462
{
450463
if (!(rightVal is JArray rightJArray))
@@ -470,10 +483,7 @@ private static bool DoesRightValContainsSameItems(JArray leftJArray, object righ
470483
JArray remainingLeftList = new JArray(remainingLeftListToken);
471484
var remainingRightListToken = rightJArray.Where(x => !(x is JObject));
472485
JArray remainingRightList = new JArray(remainingRightListToken);
473-
if (!IsListProperSubsetOf(remainingLeftList, remainingRightList, allowExtra, isOrdered))
474-
{
475-
return false;
476-
}
486+
return DoesRightValContainsSameItems(remainingLeftList, remainingRightList, allowExtra, isOrdered);
477487
}
478488
else if (leftJArray.First is JObject && bothArrayContainsJObject)
479489
{

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
[![Version][nuget-version]][nuget-url]
44
[![Build & Tests][test-badge]][test-url]
55
[![Test Coverage][coverage-badge]][coverage-url]
6+
[![Maintainability][maintainability-badge]][maintainability-url]
67
[![Licence][license-badge]][license-url]
78

89
## Introduction
@@ -32,5 +33,7 @@ This project contains core logic and the utilities for the APIMatic's C# SDK
3233
[test-url]: https://github.com/apimatic/core-lib-csharp/actions/workflows/test.yml
3334
[coverage-badge]: https://api.codeclimate.com/v1/badges/d613a5f73f605369e745/test_coverage
3435
[coverage-url]: https://codeclimate.com/github/apimatic/core-lib-csharp/test_coverage
36+
[maintainability-badge]: https://api.codeclimate.com/v1/badges/d613a5f73f605369e745/maintainability
37+
[maintainability-url]: https://codeclimate.com/github/apimatic/core-lib-csharp/maintainability
3538
[license-badge]: https://img.shields.io/badge/licence-APIMATIC-blue
3639
[license-url]: LICENSE

0 commit comments

Comments
 (0)