Skip to content

Commit aae1cbd

Browse files
committed
Add base Comparer<T, TSelf> type
1 parent 9cc7d41 commit aae1cbd

File tree

8 files changed

+150
-243
lines changed

8 files changed

+150
-243
lines changed

CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/Models/AttributeInfo.cs

Lines changed: 12 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Collections.Immutable;
88
using System.Linq;
99
using CommunityToolkit.Mvvm.SourceGenerators.Extensions;
10+
using CommunityToolkit.Mvvm.SourceGenerators.Helpers;
1011
using Microsoft.CodeAnalysis;
1112
using Microsoft.CodeAnalysis.CSharp.Syntax;
1213
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
@@ -74,31 +75,24 @@ public AttributeSyntax GetSyntax()
7475
/// <summary>
7576
/// An <see cref="IEqualityComparer{T}"/> implementation for <see cref="AttributeInfo"/>.
7677
/// </summary>
77-
public sealed class Comparer : IEqualityComparer<AttributeInfo>
78+
public sealed class Comparer : Comparer<AttributeInfo, Comparer>
7879
{
79-
/// <summary>
80-
/// The singleton <see cref="Comparer"/> instance.
81-
/// </summary>
82-
public static Comparer Default { get; } = new();
83-
8480
/// <inheritdoc/>
85-
public bool Equals(AttributeInfo? x, AttributeInfo? y)
81+
protected override void AddToHashCode(ref HashCode hashCode, AttributeInfo obj)
8682
{
87-
if (x is null && y is null)
88-
{
89-
return true;
90-
}
91-
92-
if (x is null || y is null)
93-
{
94-
return false;
95-
}
83+
hashCode.Add(obj.TypeName);
84+
hashCode.AddRange(obj.ConstructorArgumentInfo, TypedConstantInfo.Comparer.Default);
9685

97-
if (ReferenceEquals(x, y))
86+
foreach ((string key, TypedConstantInfo value) in obj.NamedArgumentInfo)
9887
{
99-
return true;
88+
hashCode.Add(key);
89+
hashCode.Add(value, TypedConstantInfo.Comparer.Default);
10090
}
91+
}
10192

93+
/// <inheritdoc/>
94+
protected override bool AreEqual(AttributeInfo x, AttributeInfo y)
95+
{
10296
if (x.TypeName != y.TypeName ||
10397
!x.ConstructorArgumentInfo.SequenceEqual(y.ConstructorArgumentInfo, TypedConstantInfo.Comparer.Default) ||
10498
x.NamedArgumentInfo.Length != y.NamedArgumentInfo.Length)
@@ -120,22 +114,5 @@ public bool Equals(AttributeInfo? x, AttributeInfo? y)
120114

121115
return true;
122116
}
123-
124-
/// <inheritdoc/>
125-
public int GetHashCode(AttributeInfo obj)
126-
{
127-
HashCode hashCode = default;
128-
129-
hashCode.Add(obj.TypeName);
130-
hashCode.AddRange(obj.ConstructorArgumentInfo, TypedConstantInfo.Comparer.Default);
131-
132-
foreach ((string key, TypedConstantInfo value) in obj.NamedArgumentInfo)
133-
{
134-
hashCode.Add(key);
135-
hashCode.Add(value, TypedConstantInfo.Comparer.Default);
136-
}
137-
138-
return hashCode.ToHashCode();
139-
}
140117
}
141118
}

CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/Models/PropertyInfo.cs

Lines changed: 15 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Collections.Immutable;
88
using System.Linq;
99
using CommunityToolkit.Mvvm.SourceGenerators.Extensions;
10+
using CommunityToolkit.Mvvm.SourceGenerators.Helpers;
1011

1112
namespace CommunityToolkit.Mvvm.SourceGenerators.ComponentModel.Models;
1213

@@ -34,31 +35,24 @@ internal sealed record PropertyInfo(
3435
/// <summary>
3536
/// An <see cref="IEqualityComparer{T}"/> implementation for <see cref="PropertyInfo"/>.
3637
/// </summary>
37-
public sealed class Comparer : IEqualityComparer<PropertyInfo>
38+
public sealed class Comparer : Comparer<PropertyInfo, Comparer>
3839
{
39-
/// <summary>
40-
/// The singleton <see cref="Comparer"/> instance.
41-
/// </summary>
42-
public static Comparer Default { get; } = new();
43-
4440
/// <inheritdoc/>
45-
public bool Equals(PropertyInfo? x, PropertyInfo? y)
41+
protected override void AddToHashCode(ref HashCode hashCode, PropertyInfo obj)
4642
{
47-
if (x is null && y is null)
48-
{
49-
return true;
50-
}
51-
52-
if (x is null || y is null)
53-
{
54-
return false;
55-
}
56-
57-
if (ReferenceEquals(x, y))
58-
{
59-
return true;
60-
}
43+
hashCode.Add(obj.TypeName);
44+
hashCode.Add(obj.IsNullableReferenceType);
45+
hashCode.Add(obj.FieldName);
46+
hashCode.Add(obj.PropertyName);
47+
hashCode.AddRange(obj.PropertyChangingNames);
48+
hashCode.AddRange(obj.PropertyChangedNames);
49+
hashCode.AddRange(obj.NotifiedCommandNames);
50+
hashCode.AddRange(obj.ValidationAttributes, AttributeInfo.Comparer.Default);
51+
}
6152

53+
/// <inheritdoc/>
54+
protected override bool AreEqual(PropertyInfo x, PropertyInfo y)
55+
{
6256
return
6357
x.TypeName == y.TypeName &&
6458
x.IsNullableReferenceType == y.IsNullableReferenceType &&
@@ -69,22 +63,5 @@ public bool Equals(PropertyInfo? x, PropertyInfo? y)
6963
x.NotifiedCommandNames.SequenceEqual(y.NotifiedCommandNames) &&
7064
x.ValidationAttributes.SequenceEqual(y.ValidationAttributes, AttributeInfo.Comparer.Default);
7165
}
72-
73-
/// <inheritdoc/>
74-
public int GetHashCode(PropertyInfo obj)
75-
{
76-
HashCode hashCode = default;
77-
78-
hashCode.Add(obj.TypeName);
79-
hashCode.Add(obj.IsNullableReferenceType);
80-
hashCode.Add(obj.FieldName);
81-
hashCode.Add(obj.PropertyName);
82-
hashCode.AddRange(obj.PropertyChangingNames);
83-
hashCode.AddRange(obj.PropertyChangedNames);
84-
hashCode.AddRange(obj.NotifiedCommandNames);
85-
hashCode.AddRange(obj.ValidationAttributes, AttributeInfo.Comparer.Default);
86-
87-
return hashCode.ToHashCode();
88-
}
8966
}
9067
}

CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/Models/TypedConstantInfo.Comparer.cs

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
using System;
66
using System.Collections.Generic;
7+
using CommunityToolkit.Mvvm.SourceGenerators.Helpers;
78

89
namespace CommunityToolkit.Mvvm.SourceGenerators.ComponentModel.Models;
910

@@ -13,42 +14,18 @@ partial record TypedConstantInfo
1314
/// <summary>
1415
/// An <see cref="IEqualityComparer{T}"/> implementation for <see cref="TypedConstantInfo"/>.
1516
/// </summary>
16-
public sealed class Comparer : IEqualityComparer<TypedConstantInfo>
17+
public sealed class Comparer : Comparer<TypedConstantInfo, Comparer>
1718
{
18-
/// <summary>
19-
/// The singleton <see cref="Comparer"/> instance.
20-
/// </summary>
21-
public static Comparer Default { get; } = new();
22-
2319
/// <inheritdoc/>
24-
public bool Equals(TypedConstantInfo? x, TypedConstantInfo? y)
20+
protected override void AddToHashCode(ref HashCode hashCode, TypedConstantInfo obj)
2521
{
26-
if (x is null && y is null)
27-
{
28-
return true;
29-
}
30-
31-
if (x is null || y is null)
32-
{
33-
return false;
34-
}
35-
36-
if (ReferenceEquals(x, y))
37-
{
38-
return true;
39-
}
40-
41-
return x.IsEqualTo(y);
22+
obj.AddToHashCode(ref hashCode);
4223
}
4324

4425
/// <inheritdoc/>
45-
public int GetHashCode(TypedConstantInfo obj)
26+
protected override bool AreEqual(TypedConstantInfo x, TypedConstantInfo y)
4627
{
47-
HashCode hashCode = default;
48-
49-
obj.AddToHashCode(ref hashCode);
50-
51-
return hashCode.ToHashCode();
28+
return x.IsEqualTo(y);
5229
}
5330
}
5431
}

CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/Models/ValidationInfo.cs

Lines changed: 10 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Collections.Immutable;
88
using System.Linq;
99
using CommunityToolkit.Mvvm.SourceGenerators.Extensions;
10+
using CommunityToolkit.Mvvm.SourceGenerators.Helpers;
1011

1112
namespace CommunityToolkit.Mvvm.SourceGenerators.Input.Models;
1213

@@ -24,47 +25,23 @@ internal sealed record ValidationInfo(
2425
/// <summary>
2526
/// An <see cref="IEqualityComparer{T}"/> implementation for <see cref="ValidationInfo"/>.
2627
/// </summary>
27-
public sealed class Comparer : IEqualityComparer<ValidationInfo>
28+
public sealed class Comparer : Comparer<ValidationInfo, Comparer>
2829
{
29-
/// <summary>
30-
/// The singleton <see cref="Comparer"/> instance.
31-
/// </summary>
32-
public static Comparer Default { get; } = new();
33-
3430
/// <inheritdoc/>
35-
public bool Equals(ValidationInfo x, ValidationInfo y)
31+
protected override void AddToHashCode(ref HashCode hashCode, ValidationInfo obj)
3632
{
37-
if (x is null && y is null)
38-
{
39-
return true;
40-
}
41-
42-
if (x is null || y is null)
43-
{
44-
return false;
45-
}
46-
47-
if (ReferenceEquals(x, y))
48-
{
49-
return true;
50-
}
33+
hashCode.Add(obj.FilenameHint);
34+
hashCode.Add(obj.TypeName);
35+
hashCode.AddRange(obj.PropertyNames);
36+
}
5137

38+
/// <inheritdoc/>
39+
protected override bool AreEqual(ValidationInfo x, ValidationInfo y)
40+
{
5241
return
5342
x.FilenameHint == y.FilenameHint &&
5443
x.TypeName == y.TypeName &&
5544
x.PropertyNames.SequenceEqual(y.PropertyNames);
5645
}
57-
58-
/// <inheritdoc/>
59-
public int GetHashCode(ValidationInfo obj)
60-
{
61-
HashCode hashCode = default;
62-
63-
hashCode.Add(obj.FilenameHint);
64-
hashCode.Add(obj.TypeName);
65-
hashCode.AddRange(obj.PropertyNames);
66-
67-
return hashCode.ToHashCode();
68-
}
6946
}
7047
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Collections.Generic;
7+
8+
namespace CommunityToolkit.Mvvm.SourceGenerators.Helpers;
9+
10+
/// <summary>
11+
/// A base <see cref="IEqualityComparer{T}"/> implementation for <typeparamref name="T"/> instances.
12+
/// </summary>
13+
/// <typeparam name="T">The type of items to compare.</typeparam>
14+
/// <typeparam name="TSelf">The concrete comparer type.</typeparam>
15+
internal abstract class Comparer<T, TSelf> : IEqualityComparer<T>
16+
where TSelf : Comparer<T, TSelf>, new()
17+
{
18+
/// <summary>
19+
/// The singleton <typeparamref name="TSelf"/> instance.
20+
/// </summary>
21+
public static TSelf Default { get; } = new();
22+
23+
/// <inheritdoc/>
24+
public bool Equals(T? x, T? y)
25+
{
26+
if (x is null && y is null)
27+
{
28+
return true;
29+
}
30+
31+
if (x is null || y is null)
32+
{
33+
return false;
34+
}
35+
36+
if (ReferenceEquals(x, y))
37+
{
38+
return true;
39+
}
40+
41+
return AreEqual(x, y);
42+
}
43+
44+
/// <inheritdoc/>
45+
public int GetHashCode(T obj)
46+
{
47+
HashCode hashCode = default;
48+
49+
AddToHashCode(ref hashCode, obj);
50+
51+
return hashCode.ToHashCode();
52+
}
53+
54+
/// <summary>
55+
/// Adds the current instance to an incremental <see cref="HashCode"/> value.
56+
/// </summary>
57+
/// <param name="hashCode">The target <see cref="HashCode"/> value.</param>
58+
/// <param name="obj">The <typeparamref name="T"/> instance being inspected.</param>
59+
protected abstract void AddToHashCode(ref HashCode hashCode, T obj);
60+
61+
/// <summary>
62+
/// Compares two <typeparamref name="T"/> instances for equality.
63+
/// </summary>
64+
/// <param name="x">The first <typeparamref name="T"/> instance to compare.</param>
65+
/// <param name="y">The second <typeparamref name="T"/> instance to compare.</param>
66+
/// <returns>Whether or not <paramref name="x"/> and <paramref name="y"/> are equal.</returns>
67+
protected abstract bool AreEqual(T x, T y);
68+
}

0 commit comments

Comments
 (0)