Skip to content

Commit b197b46

Browse files
authored
Merge pull request #81 from jnyrup/cleanup
Modernizations
2 parents fa7de19 + 4647ab1 commit b197b46

38 files changed

+2447
-2463
lines changed

.editorconfig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,11 @@ dotnet_diagnostic.SA1633.severity = none
218218
dotnet_diagnostic.SA1642.severity = suggestion
219219

220220
# CSharpGuidelines
221+
222+
# Purpose: Argument for parameter calls nested method
223+
# Rationale: Modern debuggers allow stepping into nested calls, so no need to avoid them.
224+
dotnet_diagnostic.AV1580.severity = none
225+
221226
dotnet_diagnostic.AV1561.max_parameter_count = 5
222227
# AV1008: Class should be non-static or its name should be suffixed with Extensions
223228
dotnet_diagnostic.AV1008.severity = none
@@ -262,6 +267,16 @@ dotnet_diagnostic.AV2305.severity = none
262267
# AV2407: Region should be removed
263268
dotnet_diagnostic.AV2407.severity = none
264269

270+
# Meziantou.Analyzer
271+
272+
# Purpose: Use string.Equals instead of Equals operator
273+
# Rationale: Does not improve readability
274+
dotnet_diagnostic.MA0006.severity = none
275+
276+
# Purpose: Regular expressions should not be vulnerable to Denial of Service attacks
277+
# Rationale: See https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0009.md
278+
dotnet_diagnostic.MA0009.severity = suggestion
279+
265280
# ReSharper/Rider
266281
# Convert lambda expression to method group
267282
resharper_convert_closure_to_method_group_highlighting=none

Build/_build.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<PackageReference Include="Nuke.Common" Version="9.0.4" />
1414
<PackageReference Include="System.Formats.Asn1" Version="8.0.1" />
1515
<PackageDownload Include="GitVersion.Tool" Version="[5.12.0]" />
16-
<PackageDownload Include="ReportGenerator" Version="[5.1.23]" />
16+
<PackageDownload Include="ReportGenerator" Version="[5.5.0]" />
1717
</ItemGroup>
1818

1919
</Project>

Directory.Build.props

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<Project>
2+
<PropertyGroup>
3+
<LangVersion>13.0</LangVersion>
4+
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
5+
</PropertyGroup>
6+
7+
<PropertyGroup Condition="'$(TargetFramework)' != 'net47'">
8+
<RunAnalyzersDuringBuild>false</RunAnalyzersDuringBuild>
9+
<RunAnalyzersDuringLiveAnalysis>false</RunAnalyzersDuringLiveAnalysis>
10+
<RunAnalyzers>false</RunAnalyzers>
11+
</PropertyGroup>
12+
<PropertyGroup Condition="'$(TargetFramework)' == 'net47'">
13+
<EnableNETAnalyzers>true</EnableNETAnalyzers>
14+
<AnalysisLevel>9.0</AnalysisLevel>
15+
<AnalysisMode>All</AnalysisMode>
16+
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
17+
</PropertyGroup>
18+
<ItemGroup Condition="'$(TargetFramework)' == 'net47'">
19+
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="4.14.0">
20+
<PrivateAssets>all</PrivateAssets>
21+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
22+
</PackageReference>
23+
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556">
24+
<PrivateAssets>all</PrivateAssets>
25+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
26+
</PackageReference>
27+
<PackageReference Include="CSharpGuidelinesAnalyzer" Version="3.8.5">
28+
<PrivateAssets>all</PrivateAssets>
29+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
30+
</PackageReference>
31+
<PackageReference Include="Roslynator.Analyzers" Version="4.14.1">
32+
<PrivateAssets>all</PrivateAssets>
33+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
34+
</PackageReference>
35+
<PackageReference Include="Meziantou.Analyzer" Version="2.0.253">
36+
<PrivateAssets>all</PrivateAssets>
37+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
38+
</PackageReference>
39+
</ItemGroup>
40+
</Project>

FluentAssertions.Json.sln

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# Visual Studio Version 17
4-
VisualStudioVersion = 17.2.32210.308
3+
# Visual Studio Version 18
4+
VisualStudioVersion = 18.0.11205.157 d18.0
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E5A0B454-22D4-4694-99FF-D6A8B7DE7DA3}"
77
ProjectSection(SolutionItems) = preProject

Src/FluentAssertions.Json/Common/JTokenExtensions.cs

Lines changed: 75 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -3,91 +3,102 @@
33
using System.Linq;
44
using Newtonsoft.Json.Linq;
55

6-
namespace FluentAssertions.Json.Common
6+
namespace FluentAssertions.Json.Common;
7+
8+
internal static class JTokenExtensions
79
{
8-
internal static class JTokenExtensions
9-
{
10-
private static readonly JTokenComparer Comparer = new();
10+
private static readonly JTokenComparer Comparer = new();
1111

12-
/// <summary>
13-
/// Recursively sorts the properties of JObject instances by name and
14-
/// the elements of JArray instances by their string representation,
15-
/// producing a normalized JToken for consistent comparison
16-
/// </summary>
17-
public static JToken Normalize(this JToken token)
12+
/// <summary>
13+
/// Recursively sorts the properties of JObject instances by name and
14+
/// the elements of JArray instances by their string representation,
15+
/// producing a normalized JToken for consistent comparison
16+
/// </summary>
17+
public static JToken Normalize(this JToken token)
18+
{
19+
return token switch
1820
{
19-
return token switch
20-
{
21-
JObject obj => new JObject(obj.Properties().OrderBy(p => p.Name).Select(p => new JProperty(p.Name, Normalize(p.Value)))),
22-
JArray array => new JArray(array.Select(Normalize).OrderBy(x => x, Comparer)),
23-
_ => token
24-
};
25-
}
21+
JObject obj => new JObject(obj.Properties().OrderBy(p => p.Name, StringComparer.Ordinal).Select(p => new JProperty(p.Name, Normalize(p.Value)))),
22+
JArray array => new JArray(array.Select(Normalize).OrderBy(x => x, Comparer)),
23+
_ => token
24+
};
25+
}
2626

27-
private sealed class JTokenComparer : IComparer<JToken>
27+
private sealed class JTokenComparer : IComparer<JToken>
28+
{
29+
public int Compare(JToken x, JToken y)
2830
{
29-
public int Compare(JToken x, JToken y)
31+
if (ReferenceEquals(x, y))
3032
{
31-
if (ReferenceEquals(x, y))
32-
return 0;
33-
34-
if (x is null)
35-
return -1;
36-
37-
if (y is null)
38-
return 1;
39-
40-
var typeComparison = x.Type.CompareTo(y.Type);
41-
if (typeComparison != 0)
42-
return typeComparison;
43-
44-
return x switch
45-
{
46-
JArray a => Compare(a, (JArray)y),
47-
JObject o => Compare(o, (JObject)y),
48-
JProperty p => Compare(p, (JProperty)y),
49-
JValue v => Compare(v, (JValue)y),
50-
JConstructor c => Compare(c, (JConstructor)y),
51-
_ => string.Compare(x.ToString(), y.ToString(), StringComparison.Ordinal)
52-
};
33+
return 0;
5334
}
5435

55-
private static int Compare(JValue x, JValue y) => Comparer<object>.Default.Compare(x.Value, y.Value);
56-
57-
private static int Compare(JConstructor x, JConstructor y)
36+
if (x is null)
5837
{
59-
var nameComparison = string.Compare(x.Name, y.Name, StringComparison.Ordinal);
60-
return nameComparison != 0 ? nameComparison : Compare(x, (JContainer)y);
38+
return -1;
6139
}
6240

63-
private static int Compare(JContainer x, JContainer y)
41+
if (y is null)
6442
{
65-
var countComparison = x.Count.CompareTo(y.Count);
66-
if (countComparison != 0)
67-
return countComparison;
43+
return 1;
44+
}
6845

69-
return x
70-
.Select((t, i) => Comparer.Compare(t, y[i]))
71-
.FirstOrDefault(itemComparison => itemComparison != 0);
46+
var typeComparison = x.Type.CompareTo(y.Type);
47+
if (typeComparison != 0)
48+
{
49+
return typeComparison;
7250
}
7351

74-
private static int Compare(JObject x, JObject y)
52+
return x switch
7553
{
76-
var countComparison = x.Count.CompareTo(y.Count);
77-
if (countComparison != 0)
78-
return countComparison;
54+
JArray a => Compare(a, (JArray)y),
55+
JObject o => Compare(o, (JObject)y),
56+
JProperty p => Compare(p, (JProperty)y),
57+
JValue v => Compare(v, (JValue)y),
58+
JConstructor c => Compare(c, (JConstructor)y),
59+
_ => string.CompareOrdinal(x.ToString(), y.ToString())
60+
};
61+
}
62+
63+
private static int Compare(JValue x, JValue y) => Comparer<object>.Default.Compare(x.Value, y.Value);
64+
65+
private static int Compare(JConstructor x, JConstructor y)
66+
{
67+
var nameComparison = string.CompareOrdinal(x.Name, y.Name);
68+
return nameComparison != 0 ? nameComparison : Compare(x, (JContainer)y);
69+
}
7970

80-
return x.Properties()
81-
.OrderBy(p => p.Name)
82-
.Zip(y.Properties().OrderBy(p => p.Name), (px, py) => Compare(px, py))
83-
.FirstOrDefault(itemComparison => itemComparison != 0);
71+
private static int Compare(JContainer x, JContainer y)
72+
{
73+
var countComparison = x.Count.CompareTo(y.Count);
74+
if (countComparison != 0)
75+
{
76+
return countComparison;
8477
}
8578

86-
private static int Compare(JProperty x, JProperty y)
79+
return x
80+
.Select((t, i) => Comparer.Compare(t, y[i]))
81+
.FirstOrDefault(itemComparison => itemComparison != 0);
82+
}
83+
84+
private static int Compare(JObject x, JObject y)
85+
{
86+
var countComparison = x.Count.CompareTo(y.Count);
87+
if (countComparison != 0)
8788
{
88-
var nameComparison = string.Compare(x.Name, y.Name, StringComparison.Ordinal);
89-
return nameComparison != 0 ? nameComparison : Comparer.Compare(x.Value, y.Value);
89+
return countComparison;
9090
}
91+
92+
return x.Properties()
93+
.OrderBy(p => p.Name, StringComparer.Ordinal)
94+
.Zip(y.Properties().OrderBy(p => p.Name, StringComparer.Ordinal), (px, py) => Compare(px, py))
95+
.FirstOrDefault(itemComparison => itemComparison != 0);
96+
}
97+
98+
private static int Compare(JProperty x, JProperty y)
99+
{
100+
var nameComparison = string.CompareOrdinal(x.Name, y.Name);
101+
return nameComparison != 0 ? nameComparison : Comparer.Compare(x.Value, y.Value);
91102
}
92103
}
93104
}
Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
namespace FluentAssertions.Json.Common
1+
namespace FluentAssertions.Json.Common;
2+
3+
internal static class StringExtensions
24
{
3-
internal static class StringExtensions
4-
{
5-
/// <summary>
6-
/// Replaces all characters that might conflict with formatting placeholders with their escaped counterparts.
7-
/// </summary>
8-
public static string EscapePlaceholders(this string value) =>
9-
value.Replace("{", "{{").Replace("}", "}}");
5+
/// <summary>
6+
/// Replaces all characters that might conflict with formatting placeholders with their escaped counterparts.
7+
/// </summary>
8+
public static string EscapePlaceholders(this string value) =>
9+
value.Replace("{", "{{").Replace("}", "}}");
1010

11-
public static string RemoveNewLines(this string @this)
12-
{
13-
return @this.Replace("\n", string.Empty).Replace("\r", string.Empty).Replace("\\r\\n", string.Empty);
14-
}
11+
public static string RemoveNewLines(this string @this)
12+
{
13+
return @this.Replace("\n", string.Empty).Replace("\r", string.Empty).Replace("\\r\\n", string.Empty);
1514
}
1615
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System;
2+
3+
namespace FluentAssertions.Json;
4+
5+
internal sealed class Difference
6+
{
7+
public Difference(DifferenceKind kind, JPath path, object actual, object expected)
8+
: this(kind, path)
9+
{
10+
Actual = actual;
11+
Expected = expected;
12+
}
13+
14+
public Difference(DifferenceKind kind, JPath path)
15+
{
16+
Kind = kind;
17+
Path = path;
18+
}
19+
20+
private DifferenceKind Kind { get; }
21+
22+
private JPath Path { get; }
23+
24+
private object Actual { get; }
25+
26+
private object Expected { get; }
27+
28+
public override string ToString()
29+
{
30+
return Kind switch
31+
{
32+
DifferenceKind.ActualIsNull => "is null",
33+
DifferenceKind.ExpectedIsNull => "is not null",
34+
DifferenceKind.OtherType => $"has {Actual} instead of {Expected} at {Path}",
35+
DifferenceKind.OtherName => $"has a different name at {Path}",
36+
DifferenceKind.OtherValue => $"has a different value at {Path}",
37+
DifferenceKind.DifferentLength => $"has {Actual} elements instead of {Expected} at {Path}",
38+
DifferenceKind.ActualMissesProperty => $"misses property {Path}",
39+
DifferenceKind.ExpectedMissesProperty => $"has extra property {Path}",
40+
DifferenceKind.ActualMissesElement => $"misses expected element {Path}",
41+
DifferenceKind.WrongOrder => $"has expected element {Path} in the wrong order",
42+
#pragma warning disable MA0015 // Specify the parameter name in ArgumentException
43+
_ => throw new ArgumentOutOfRangeException(),
44+
#pragma warning restore MA0015 // Specify the parameter name in ArgumentException
45+
};
46+
}
47+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace FluentAssertions.Json;
2+
3+
internal enum DifferenceKind
4+
{
5+
ActualIsNull,
6+
ExpectedIsNull,
7+
OtherType,
8+
OtherName,
9+
OtherValue,
10+
DifferentLength,
11+
ActualMissesProperty,
12+
ExpectedMissesProperty,
13+
ActualMissesElement,
14+
WrongOrder
15+
}

0 commit comments

Comments
 (0)