Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Generator.Equals.Runtime/Attributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ public class EquatableAttribute : Attribute
/// Equality and hash code do not consider members of base classes.
/// </summary>
public bool IgnoreInheritedMembers { get; set; }

/// <summary>
/// Indicates whether the equality operators (<c>==</c> and <c>!=</c>) will be overridden for the decorated member.
/// <br/>Default value is <see langword="true"/>.
/// </summary>
public bool OverrideEqualityOperators { get; set; } = true;
}

[GeneratedCode("Generator.Equals", "1.0.0.0")]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
namespace Generator.Equals.Tests.Classes
{
public partial class BaseEqualityWithoutOperators
{
[Equatable(OverrideEqualityOperators = false)]
public partial class Person
{
public Person(int age)
{
Age = age;
}

public int Age { get; }
}

[Equatable(OverrideEqualityOperators = false)]
public partial class Manager : Person
{
public Manager(int age, string department) : base(age)
{
Department = department;
}

public string Department { get; }
}
}
}
22 changes: 22 additions & 0 deletions Generator.Equals.Tests/Classes/BaseEqualityWithoutOperators.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace Generator.Equals.Tests.Classes
{
public partial class BaseEqualityWithoutOperators
{
public class EqualsTest : EqualityTestCase<Person>
{
public override object Factory1() => new Manager(25, "IT");
public override bool EqualsOperator(object value1, object value2) => (Manager) value1 == (Manager) value2;
public override bool NotEqualsOperator(object value1, object value2) => (Manager) value1 != (Manager) value2;
public override bool ExpectedOperatorEquals => false;
}

public class NotEqualsTest : EqualityTestCase<Person>
{
public override bool Expected => false;
public override object Factory1() => new Manager(25, "IT");
public override object Factory2() => new Manager(25, "Sales");
public override bool EqualsOperator(object value1, object value2) => (Manager) value1 == (Person) value2;
public override bool NotEqualsOperator(object value1, object value2) => (Manager) value1 != (Person) value2;
}
}
}
5 changes: 3 additions & 2 deletions Generator.Equals.Tests/EqualityTestCase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public abstract class EqualityTestCase
public abstract object Factory1();
public virtual object Factory2() => Factory1();
public virtual bool Expected => true;
public virtual bool ExpectedOperatorEquals => Expected;
public abstract bool EqualsOperator(object value1, object value2);
public abstract bool NotEqualsOperator(object value1, object value2);

Expand All @@ -27,7 +28,7 @@ public void TestEqualsOperator()
var value1 = Factory1();
var value2 = Factory2();
var result = EqualsOperator(value1, value2);
result.Should().Be(Expected);
result.Should().Be(ExpectedOperatorEquals);
}

[Fact]
Expand All @@ -36,7 +37,7 @@ public void TestNotEqualsOperator()
var value1 = Factory1();
var value2 = Factory2();
var result = NotEqualsOperator(value1, value2);
result.Should().NotBe(Expected);
result.Should().NotBe(ExpectedOperatorEquals);
}

[Fact]
Expand Down
4 changes: 3 additions & 1 deletion Generator.Equals/EqualityTypeModelTransformer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public EqualityTypeModelTransformer(GeneratorAttributeSyntaxContext context)

var explicitMode = equatableAttributeData.GetNamedArgumentValue("Explicit") is true;
var ignoreInheritedMembers = equatableAttributeData.GetNamedArgumentValue("IgnoreInheritedMembers") is true;
var overrideEqualityOperators = equatableAttributeData.GetNamedArgumentValue(nameof(EquatableAttribute.OverrideEqualityOperators)) is not false;

if (_context.TargetSymbol is not ITypeSymbol symbol)
{
Expand Down Expand Up @@ -83,7 +84,8 @@ public EqualityTypeModelTransformer(GeneratorAttributeSyntaxContext context)
IsSealed = symbol.IsSealed,
BaseTypeName = baseTypeName,
Fullname = fullname,
SyntaxKind = _context.TargetNode.Kind()
SyntaxKind = _context.TargetNode.Kind(),
OverrideEqualityOperators = overrideEqualityOperators,
};

if (model.SyntaxKind is not (
Expand Down
29 changes: 16 additions & 13 deletions Generator.Equals/Generators/ClassEqualityGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,23 @@ IndentedTextWriter writer
var baseTypeName = model.BaseTypeName;
var isRootClass = baseTypeName == "object";

writer.WriteLines(EqualsOperatorCodeComment);
writer.WriteLine(GeneratedCodeAttributeDeclaration);
writer.WriteLine("public static bool operator ==(");
writer.WriteLine(1, $"{symbolName}? left,");
writer.WriteLine(1, $"{symbolName}? right) =>");
writer.WriteLine(1, $"global::Generator.Equals.DefaultEqualityComparer<{symbolName}?>.Default");
writer.WriteLine(2, $".Equals(left, right);");
writer.WriteLine();
if (model.OverrideEqualityOperators)
{
writer.WriteLines(EqualsOperatorCodeComment);
writer.WriteLine(GeneratedCodeAttributeDeclaration);
writer.WriteLine("public static bool operator ==(");
writer.WriteLine(1, $"{symbolName}? left,");
writer.WriteLine(1, $"{symbolName}? right) =>");
writer.WriteLine(1, $"global::Generator.Equals.DefaultEqualityComparer<{symbolName}?>.Default");
writer.WriteLine(2, $".Equals(left, right);");
writer.WriteLine();

writer.WriteLines(NotEqualsOperatorCodeComment);
writer.WriteLine(GeneratedCodeAttributeDeclaration);
writer.WriteLine($"public static bool operator !=({symbolName}? left, {symbolName}? right) =>");
writer.WriteLine(1, "!(left == right);");
writer.WriteLine();
writer.WriteLines(NotEqualsOperatorCodeComment);
writer.WriteLine(GeneratedCodeAttributeDeclaration);
writer.WriteLine($"public static bool operator !=({symbolName}? left, {symbolName}? right) =>");
writer.WriteLine(1, "!(left == right);");
writer.WriteLine();
}

writer.WriteLine(InheritDocComment);
writer.WriteLine(GeneratedCodeAttributeDeclaration);
Expand Down
1 change: 1 addition & 0 deletions Generator.Equals/Models/EqualityTypeModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ internal sealed record EqualityTypeModel
public required bool IgnoreInheritedMembers { get; init; }
public required EquatableImmutableArray<EqualityMemberModel> BuildEqualityModels { get; init; }
public required string Fullname { get; init; }
public required bool OverrideEqualityOperators { get; init; }
}