diff --git a/samples/Thinktecture.Runtime.Extensions.Samples/ValueObjects/EndDate.cs b/samples/Thinktecture.Runtime.Extensions.Samples/ValueObjects/EndDate.cs
index 679ae59a..fe0aa0fc 100644
--- a/samples/Thinktecture.Runtime.Extensions.Samples/ValueObjects/EndDate.cs
+++ b/samples/Thinktecture.Runtime.Extensions.Samples/ValueObjects/EndDate.cs
@@ -2,12 +2,14 @@
namespace Thinktecture.ValueObjects;
-[ValueObject(DefaultInstancePropertyName = "Infinite")]
+[ValueObject(DefaultInstancePropertyName = "Infinite",
+ EqualityComparisonOperators = OperatorsGeneration.DefaultWithKeyTypeOverloads)] // for comparison with DateTime without implicit cast
public readonly partial struct EndDate
{
[ValueObjectMemberIgnore]
private readonly DateOnly? _date;
+ // can be public as well
private DateOnly Date
{
get => _date ?? DateOnly.MaxValue;
diff --git a/samples/Thinktecture.Runtime.Extensions.Samples/ValueObjects/ValueObjectDemos.cs b/samples/Thinktecture.Runtime.Extensions.Samples/ValueObjects/ValueObjectDemos.cs
index b4bea651..1af7de89 100644
--- a/samples/Thinktecture.Runtime.Extensions.Samples/ValueObjects/ValueObjectDemos.cs
+++ b/samples/Thinktecture.Runtime.Extensions.Samples/ValueObjects/ValueObjectDemos.cs
@@ -102,7 +102,7 @@ private static void DemoForEndDate(ILogger logger)
logger.Information("DateOnly of EndDate.Infinite and default(EndDate) are equal: {AreEqual}", dateOfInfiniteDate == dateOfDefaultDate);
- logger.Information("EndDate.Infinite and DateOnly.MaxValue are equal: {AreEqual}", dateOfInfiniteDate == DateOnly.MaxValue);
+ logger.Information("EndDate.Infinite and DateOnly.MaxValue are equal: {AreEqual}", infiniteEndDate == DateOnly.MaxValue);
}
private static void DemoForComplexValueObjects(ILogger logger)
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ComparerInfo.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ComparerInfo.cs
new file mode 100644
index 00000000..80956521
--- /dev/null
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ComparerInfo.cs
@@ -0,0 +1,3 @@
+namespace Thinktecture.CodeAnalysis;
+
+public readonly record struct ComparerInfo(string Comparer, bool IsAccessor);
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ComparisonOperatorsCodeGenerator.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ComparisonOperatorsCodeGenerator.cs
index d146127f..e18cc406 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ComparisonOperatorsCodeGenerator.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ComparisonOperatorsCodeGenerator.cs
@@ -65,6 +65,12 @@ public void GenerateBaseTypes(StringBuilder sb, ITypeInformation type, IMemberIn
sb.Append(@"
global::System.Numerics.IComparisonOperators<").Append(type.TypeFullyQualified).Append(", ").Append(type.TypeFullyQualified).Append(", bool>");
+
+ if (!_withKeyTypeOverloads)
+ return;
+
+ sb.Append(@",
+ global::System.Numerics.IComparisonOperators<").Append(type.TypeFullyQualified).Append(", ").Append(keyMember.TypeFullyQualified).Append(", bool>");
}
public void GenerateImplementation(StringBuilder sb, ITypeInformation type, IMemberInformation keyMember)
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/DefaultMemberState.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/DefaultMemberState.cs
index 95a143e8..aa7c1988 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/DefaultMemberState.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/DefaultMemberState.cs
@@ -38,10 +38,10 @@ public bool Equals(IMemberState? obj)
public bool Equals(DefaultMemberState? other)
{
+ if (other is null)
+ return false;
if (ReferenceEquals(this, other))
return true;
- if (ReferenceEquals(null, other))
- return false;
return _typedMemberState.Equals(other._typedMemberState)
&& Name == other.Name
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/EqualityComparisonOperatorsCodeGenerator.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/EqualityComparisonOperatorsCodeGenerator.cs
new file mode 100644
index 00000000..bd0a7b1b
--- /dev/null
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/EqualityComparisonOperatorsCodeGenerator.cs
@@ -0,0 +1,218 @@
+using System.Diagnostics.CodeAnalysis;
+using System.Text;
+
+namespace Thinktecture.CodeAnalysis;
+
+public sealed class EqualityComparisonOperatorsCodeGenerator : IInterfaceCodeGenerator
+{
+ private static readonly IInterfaceCodeGenerator _default = new EqualityComparisonOperatorsCodeGenerator(false, null);
+ private static readonly IInterfaceCodeGenerator _defaultWithKeyTypeOverloads = new EqualityComparisonOperatorsCodeGenerator(true, null);
+
+ public static bool TryGet(
+ OperatorsGeneration operatorsGeneration,
+ ComparerInfo? equalityComparer,
+ [MaybeNullWhen(false)] out IInterfaceCodeGenerator generator)
+ {
+ switch (operatorsGeneration)
+ {
+ case OperatorsGeneration.None:
+ generator = null;
+ return false;
+ case OperatorsGeneration.Default:
+ generator = equalityComparer is null
+ ? _default
+ : new EqualityComparisonOperatorsCodeGenerator(false, equalityComparer);
+ return true;
+ case OperatorsGeneration.DefaultWithKeyTypeOverloads:
+ generator = equalityComparer is null
+ ? _defaultWithKeyTypeOverloads
+ : new EqualityComparisonOperatorsCodeGenerator(true, equalityComparer);
+ return true;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(operatorsGeneration), operatorsGeneration, "Invalid operations generation.");
+ }
+ }
+
+ private readonly bool _withKeyTypeOverloads;
+ private readonly ComparerInfo? _equalityComparer;
+
+ public string CodeGeneratorName => "EqualityComparisonOperators-CodeGenerator";
+ public string FileNameSuffix => ".EqualityComparisonOperators";
+
+ private EqualityComparisonOperatorsCodeGenerator(
+ bool withKeyTypeOverloads,
+ ComparerInfo? equalityComparer)
+ {
+ _withKeyTypeOverloads = withKeyTypeOverloads;
+ _equalityComparer = equalityComparer;
+ }
+
+ public void GenerateBaseTypes(StringBuilder sb, ITypeInformation type, IMemberInformation keyMember)
+ {
+ sb.Append(@"
+ global::System.Numerics.IEqualityOperators<").Append(type.TypeFullyQualified).Append(", ").Append(type.TypeFullyQualified).Append(", bool>");
+
+ if (!_withKeyTypeOverloads)
+ return;
+
+ sb.Append(@",
+ global::System.Numerics.IEqualityOperators<").Append(type.TypeFullyQualified).Append(", ").Append(keyMember.TypeFullyQualified).Append(", bool>");
+ }
+
+ public void GenerateImplementation(StringBuilder sb, ITypeInformation type, IMemberInformation keyMember)
+ {
+ GenerateUsingEquals(sb, type);
+
+ if (_withKeyTypeOverloads)
+ GenerateKeyOverloads(sb, type, keyMember);
+ }
+
+ private static void GenerateUsingEquals(StringBuilder sb, ITypeInformation type)
+ {
+ sb.Append(@"
+ ///
+ /// Compares two instances of .
+ ///
+ /// Instance to compare.
+ /// Another instance to compare.
+ /// true if objects are equal; otherwise false.
+ public static bool operator ==(").Append(type.TypeFullyQualifiedNullAnnotated).Append(" obj, ").Append(type.TypeFullyQualifiedNullAnnotated).Append(@" other)
+ {");
+
+ if (type.IsReferenceType)
+ {
+ if (type.IsEqualWithReferenceEquality)
+ {
+ sb.Append(@"
+ return global::System.Object.ReferenceEquals(obj, other);");
+ }
+ else
+ {
+ sb.Append(@"
+ if (obj is null)
+ return other is null;
+
+ return obj.Equals(other);");
+ }
+ }
+ else
+ {
+ sb.Append(@"
+ return obj.Equals(other);");
+ }
+
+ sb.Append(@"
+ }
+
+ ///
+ /// Compares two instances of .
+ ///
+ /// Instance to compare.
+ /// Another instance to compare.
+ /// false if objects are equal; otherwise true.
+ public static bool operator !=(").Append(type.TypeFullyQualifiedNullAnnotated).Append(" obj, ").Append(type.TypeFullyQualifiedNullAnnotated).Append(@" other)
+ {
+ return !(obj == other);
+ }");
+ }
+
+ private void GenerateKeyOverloads(
+ StringBuilder sb,
+ ITypeInformation type,
+ IMemberInformation keyMember)
+ {
+ sb.Append(@"
+
+ private static bool Equals(").Append(type.TypeFullyQualifiedNullAnnotated).Append(" obj, ").Append(keyMember.TypeFullyQualified).Append(@" value)
+ {");
+
+ if (type.IsReferenceType)
+ {
+ if (keyMember.IsReferenceType)
+ {
+ sb.Append(@"
+ if (obj is null)
+ return value is null;
+");
+ }
+ else
+ {
+ sb.Append(@"
+ if (obj is null)
+ return false;
+");
+ }
+ }
+
+ sb.Append(@"
+ return ");
+
+ if (_equalityComparer == null)
+ {
+ if (keyMember.IsReferenceType)
+ {
+ sb.Append("obj.").Append(keyMember.Name).Append(" is null ? value").Append(" is null : obj.").Append(keyMember.Name).Append(".Equals(value").Append(")");
+ }
+ else
+ {
+ sb.Append("obj.").Append(keyMember.Name).Append(".Equals(value)");
+ }
+ }
+ else
+ {
+ sb.Append(_equalityComparer.Value.Comparer);
+
+ if (_equalityComparer.Value.IsAccessor)
+ sb.Append(".EqualityComparer");
+
+ sb.Append(".Equals(obj.").Append(keyMember.Name).Append(", value)");
+ }
+
+ sb.Append(@";
+ }
+
+ ///
+ /// Compares an instance of with .
+ ///
+ /// Instance to compare.
+ /// Value to compare with.
+ /// true if objects are equal; otherwise false.
+ public static bool operator ==(").Append(type.TypeFullyQualifiedNullAnnotated).Append(" obj, ").Append(keyMember.TypeFullyQualified).Append(@" value)
+ {
+ return Equals(obj, value);
+ }
+
+ ///
+ /// Compares an instance of with .
+ ///
+ /// Value to compare.
+ /// Instance to compare with.
+ /// true if objects are equal; otherwise false.
+ public static bool operator ==(").Append(keyMember.TypeFullyQualified).Append(" value, ").Append(type.TypeFullyQualifiedNullAnnotated).Append(@" obj)
+ {
+ return Equals(obj, value);
+ }
+
+ ///
+ /// Compares an instance of with .
+ ///
+ /// Instance to compare.
+ /// Value to compare with.
+ /// false if objects are equal; otherwise true.
+ public static bool operator !=(").Append(type.TypeFullyQualifiedNullAnnotated).Append(" obj, ").Append(keyMember.TypeFullyQualified).Append(@" value)
+ {
+ return !(obj == value);
+ }
+
+ ///
+ /// Compares an instance of with .
+ ///
+ /// Value to compare.
+ /// Instance to compare with.
+ /// false if objects are equal; otherwise true.
+ public static bool operator !=(").Append(keyMember.TypeFullyQualified).Append(" value, ").Append(type.TypeFullyQualifiedNullAnnotated).Append(@" obj)
+ {
+ return !(obj == value);
+ }");
+ }
+}
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/EqualityComparisonOperatorsGeneratorState.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/EqualityComparisonOperatorsGeneratorState.cs
new file mode 100644
index 00000000..e8bcecd9
--- /dev/null
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/EqualityComparisonOperatorsGeneratorState.cs
@@ -0,0 +1,47 @@
+namespace Thinktecture.CodeAnalysis;
+
+public readonly struct EqualityComparisonOperatorsGeneratorState : IEquatable
+{
+ public ITypeInformation Type { get; }
+ public IMemberInformation KeyMember { get; }
+ public OperatorsGeneration OperatorsGeneration { get; }
+ public ComparerInfo? EqualityComparer { get; }
+
+ public EqualityComparisonOperatorsGeneratorState(
+ ITypeInformation type,
+ IMemberInformation keyMember,
+ OperatorsGeneration operatorsGeneration,
+ ComparerInfo? equalityComparer)
+ {
+ Type = type;
+ KeyMember = keyMember;
+ OperatorsGeneration = operatorsGeneration;
+ EqualityComparer = equalityComparer;
+ }
+
+ public bool Equals(EqualityComparisonOperatorsGeneratorState other)
+ {
+ return TypeInformationComparer.Instance.Equals(Type, other.Type)
+ && MemberInformationComparer.Instance.Equals(KeyMember, other.KeyMember)
+ && OperatorsGeneration == other.OperatorsGeneration
+ && EqualityComparer == other.EqualityComparer;
+ }
+
+ public override bool Equals(object? obj)
+ {
+ return obj is EqualityComparisonOperatorsGeneratorState state && Equals(state);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = TypeInformationComparer.Instance.GetHashCode(Type);
+ hashCode = (hashCode * 397) ^ MemberInformationComparer.Instance.GetHashCode(KeyMember);
+ hashCode = (hashCode * 397) ^ (int)OperatorsGeneration;
+ hashCode = (hashCode * 397) ^ EqualityComparer?.GetHashCode() ?? 0;
+
+ return hashCode;
+ }
+ }
+}
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/EqualityInstanceMemberInfo.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/EqualityInstanceMemberInfo.cs
index 900eacbe..90b940c9 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/EqualityInstanceMemberInfo.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/EqualityInstanceMemberInfo.cs
@@ -29,7 +29,7 @@ public override bool Equals(object? obj)
public bool Equals(EqualityInstanceMemberInfo? other)
{
- if (ReferenceEquals(null, other))
+ if (other is null)
return false;
if (ReferenceEquals(this, other))
return true;
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ITypeInformation.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ITypeInformation.cs
index cf4651ea..c578455f 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ITypeInformation.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ITypeInformation.cs
@@ -5,4 +5,5 @@ public interface ITypeInformation : INamespaceAndName, ITypeFullyQualified
string TypeMinimallyQualified { get; }
string TypeFullyQualifiedNullAnnotated { get; }
bool IsReferenceType { get; }
+ bool IsEqualWithReferenceEquality { get; }
}
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/InstanceMemberInfo.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/InstanceMemberInfo.cs
index bd6d57b9..ae3d8982 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/InstanceMemberInfo.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/InstanceMemberInfo.cs
@@ -104,7 +104,7 @@ public bool Equals(IMemberState? obj)
public bool Equals(InstanceMemberInfo? other)
{
- if (ReferenceEquals(null, other))
+ if (other is null)
return false;
if (ReferenceEquals(this, other))
return true;
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/BaseTypeState.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/BaseTypeState.cs
index 7d05a2e3..76886b44 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/BaseTypeState.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/BaseTypeState.cs
@@ -20,7 +20,7 @@ public override bool Equals(object? obj)
public bool Equals(BaseTypeState? other)
{
- if (ReferenceEquals(null, other))
+ if (other is null)
return false;
if (ReferenceEquals(this, other))
return true;
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/ConstructorState.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/ConstructorState.cs
index 56830657..fc598e7b 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/ConstructorState.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/ConstructorState.cs
@@ -11,7 +11,7 @@ public ConstructorState(IReadOnlyList arguments)
public bool Equals(ConstructorState? other)
{
- if (ReferenceEquals(null, other))
+ if (other is null)
return false;
if (ReferenceEquals(this, other))
return true;
@@ -21,7 +21,7 @@ public bool Equals(ConstructorState? other)
public override bool Equals(object? obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj is null)
return false;
if (ReferenceEquals(this, obj))
return true;
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/EnumSettings.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/EnumSettings.cs
index e697cd0f..52699bb0 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/EnumSettings.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/EnumSettings.cs
@@ -8,6 +8,7 @@ public sealed class EnumSettings : IEquatable
public bool SkipIComparable { get; }
public bool SkipIParsable { get; }
public OperatorsGeneration ComparisonOperators { get; }
+ public OperatorsGeneration EqualityComparisonOperators { get; }
public bool SkipIFormattable { get; }
public bool SkipToString { get; }
@@ -17,8 +18,13 @@ public EnumSettings(AttributeData? attribute)
SkipIComparable = attribute?.FindSkipIComparable() ?? false;
SkipIParsable = attribute?.FindSkipIParsable() ?? false;
ComparisonOperators = attribute?.FindComparisonOperators() ?? OperatorsGeneration.Default;
+ EqualityComparisonOperators = attribute?.FindEqualityComparisonOperators() ?? OperatorsGeneration.Default;
SkipIFormattable = attribute?.FindSkipIFormattable() ?? false;
SkipToString = attribute?.FindSkipToString() ?? false;
+
+ // Comparison operators depend on the equality comparison operators
+ if (ComparisonOperators > EqualityComparisonOperators)
+ EqualityComparisonOperators = ComparisonOperators;
}
public override bool Equals(object? obj)
@@ -28,7 +34,7 @@ public override bool Equals(object? obj)
public bool Equals(EnumSettings? other)
{
- if (ReferenceEquals(null, other))
+ if (other is null)
return false;
if (ReferenceEquals(this, other))
return true;
@@ -37,6 +43,7 @@ public bool Equals(EnumSettings? other)
&& SkipIComparable == other.SkipIComparable
&& SkipIParsable == other.SkipIParsable
&& ComparisonOperators == other.ComparisonOperators
+ && EqualityComparisonOperators == other.EqualityComparisonOperators
&& SkipIFormattable == other.SkipIFormattable
&& SkipToString == other.SkipToString;
}
@@ -49,6 +56,7 @@ public override int GetHashCode()
hashCode = (hashCode * 397) ^ SkipIComparable.GetHashCode();
hashCode = (hashCode * 397) ^ SkipIParsable.GetHashCode();
hashCode = (hashCode * 397) ^ ComparisonOperators.GetHashCode();
+ hashCode = (hashCode * 397) ^ EqualityComparisonOperators.GetHashCode();
hashCode = (hashCode * 397) ^ SkipIFormattable.GetHashCode();
hashCode = (hashCode * 397) ^ SkipToString.GetHashCode();
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/EnumSourceGeneratorState.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/EnumSourceGeneratorState.cs
index 1de85f4e..d2505b42 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/EnumSourceGeneratorState.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/EnumSourceGeneratorState.cs
@@ -9,6 +9,7 @@ public sealed class EnumSourceGeneratorState : ITypeInformation, IEquatable !IsValidatable;
public IMemberState KeyProperty { get; }
public bool IsValidatable { get; }
@@ -78,7 +79,7 @@ public override bool Equals(object? obj)
public bool Equals(EnumSourceGeneratorState? other)
{
- if (ReferenceEquals(null, other))
+ if (other is null)
return false;
if (ReferenceEquals(this, other))
return true;
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/SmartEnumCodeGenerator.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/SmartEnumCodeGenerator.cs
index 3ae64ef4..1ccb5797 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/SmartEnumCodeGenerator.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/SmartEnumCodeGenerator.cs
@@ -53,8 +53,7 @@ private void GenerateEnum(CancellationToken cancellationToken)
_sb.Append(@"
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter<").Append(_state.TypeFullyQualified).Append(", ").Append(_state.KeyProperty.TypeFullyQualified).Append(@">))]
partial ").Append(_state.IsReferenceType ? "class" : "struct").Append(" ").Append(_state.Name).Append(" : global::Thinktecture.IEnum<").Append(_state.KeyProperty.TypeFullyQualified).Append(", ").Append(_state.TypeFullyQualified).Append(@">,
- global::System.IEquatable<").Append(_state.TypeFullyQualifiedNullAnnotated).Append(@">,
- global::System.Numerics.IEqualityOperators<").Append(_state.TypeFullyQualified).Append(", ").Append(_state.TypeFullyQualified).Append(@", bool>
+ global::System.IEquatable<").Append(_state.TypeFullyQualifiedNullAnnotated).Append(@">
{");
GenerateModuleInitializer(_state.KeyProperty);
@@ -127,7 +126,6 @@ private void GenerateEnum(CancellationToken cancellationToken)
GenerateValidate();
GenerateImplicitConversion();
GenerateExplicitConversion();
- GenerateEqualityOperators();
GenerateEquals();
cancellationToken.ThrowIfCancellationRequested();
@@ -439,53 +437,6 @@ private void GenerateValidate()
}");
}
- private void GenerateEqualityOperators()
- {
- _sb.Append(@"
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if items are equal; otherwise false.
- public static bool operator ==(").Append(_state.TypeFullyQualifiedNullAnnotated).Append(" item1, ").Append(_state.TypeFullyQualifiedNullAnnotated).Append(@" item2)
- {");
-
- if (_state.IsValidatable)
- {
- if (_state.IsReferenceType)
- {
- _sb.Append(@"
- if (item1 is null)
- return item2 is null;
-");
- }
-
- _sb.Append(@"
- return item1.Equals(item2);");
- }
- else
- {
- _sb.Append(@"
- return global::System.Object.ReferenceEquals(item1, item2);");
- }
-
- _sb.Append(@"
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if items are equal; otherwise true.
- public static bool operator !=(").Append(_state.TypeFullyQualifiedNullAnnotated).Append(" item1, ").Append(_state.TypeFullyQualifiedNullAnnotated).Append(@" item2)
- {
- return !(item1 == item2);
- }");
- }
-
private void GenerateImplicitConversion()
{
_sb.Append(@"
@@ -564,6 +515,7 @@ public bool Equals(").Append(_state.TypeFullyQualifiedNullAnnotated).Append(@" o
}
else
{
+ // ReferenceEquals is ok because non-validatable smart enums are classes only
_sb.Append(@"
return global::System.Object.ReferenceEquals(this, other);");
}
@@ -720,7 +672,7 @@ private void GenerateCreateAndCheckInvalidItem(bool needsCreateInvalidItemImplem
private static ").Append(_state.TypeFullyQualified).Append(" CreateAndCheckInvalidItem(").Append(_state.KeyProperty.TypeFullyQualified).Append(" ").Append(_state.KeyProperty.ArgumentName).Append(@")
{
- var item = ");
+ var item = ");
if (needsCreateInvalidItemImplementation && _state.IsAbstract)
{
@@ -737,24 +689,25 @@ private void GenerateCreateAndCheckInvalidItem(bool needsCreateInvalidItemImplem
if (_state.IsReferenceType)
{
_sb.Append(@"
- if (item is null)
- throw new global::System.Exception(""The implementation of method '").Append(Constants.Methods.CREATE_INVALID_ITEM).Append(@"' must not return 'null'."");
+ if (item is null)
+ throw new global::System.Exception(""The implementation of method '").Append(Constants.Methods.CREATE_INVALID_ITEM).Append(@"' must not return 'null'."");
");
}
_sb.Append(@"
- if (item.IsValid)
- throw new global::System.Exception(""The implementation of method '").Append(Constants.Methods.CREATE_INVALID_ITEM).Append(@"' must return an instance with property 'IsValid' equals to 'false'."");");
+ if (item.IsValid)
+ throw new global::System.Exception(""The implementation of method '").Append(Constants.Methods.CREATE_INVALID_ITEM).Append(@"' must return an instance with property 'IsValid' equals to 'false'."");");
if (!needsCreateInvalidItemImplementation)
{
_sb.Append(@"
- if (_itemsLookup.Value.ContainsKey(item.").Append(_state.KeyProperty.Name).Append(@"))
- throw new global::System.Exception(""The implementation of method '").Append(Constants.Methods.CREATE_INVALID_ITEM).Append("' must not return an instance with property '").Append(_state.KeyProperty.Name).Append(@"' equals to one of a valid item."");");
+ if (_itemsLookup.Value.ContainsKey(item.").Append(_state.KeyProperty.Name).Append(@"))
+ throw new global::System.Exception(""The implementation of method '").Append(Constants.Methods.CREATE_INVALID_ITEM).Append("' must not return an instance with property '").Append(_state.KeyProperty.Name).Append(@"' equals to one of a valid item."");");
}
_sb.Append(@"
+
return item;
}");
}
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/SmartEnumSourceGenerator.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/SmartEnumSourceGenerator.cs
index 12e08e63..b1ef6645 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/SmartEnumSourceGenerator.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/SmartEnums/SmartEnumSourceGenerator.cs
@@ -36,6 +36,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
InitializeComparableCodeGenerator(context, validStates, options);
InitializeParsableCodeGenerator(context, validStates, options);
InitializeComparisonOperatorsCodeGenerator(context, validStates, options);
+ InitializeEqualityComparisonOperatorsCodeGenerator(context, validStates, options);
InitializeErrorReporting(context, enumTypeOrError);
InitializeExceptionReporting(context, enumTypeOrError);
@@ -53,6 +54,17 @@ private void InitializeComparisonOperatorsCodeGenerator(IncrementalGeneratorInit
InitializeComparisonOperatorsCodeGenerator(context, comparables, options);
}
+ private void InitializeEqualityComparisonOperatorsCodeGenerator(IncrementalGeneratorInitializationContext context, IncrementalValuesProvider validStates, IncrementalValueProvider options)
+ {
+ var comparables = validStates
+ .Select((state, _) => new EqualityComparisonOperatorsGeneratorState(state.State,
+ state.KeyMember,
+ state.Settings.EqualityComparisonOperators,
+ new ComparerInfo(Constants.KEY_EQUALITY_COMPARER_NAME, false)));
+
+ InitializeEqualityComparisonOperatorsCodeGenerator(context, comparables, options);
+ }
+
private void InitializeParsableCodeGenerator(IncrementalGeneratorInitializationContext context, IncrementalValuesProvider validStates, IncrementalValueProvider options)
{
var parsables = validStates
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ThinktectureSourceGeneratorBase.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ThinktectureSourceGeneratorBase.cs
index d6d4e040..646ff0d2 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ThinktectureSourceGeneratorBase.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ThinktectureSourceGeneratorBase.cs
@@ -215,6 +215,36 @@ protected void InitializeComparisonOperatorsCodeGenerator(
});
}
+ protected void InitializeEqualityComparisonOperatorsCodeGenerator(
+ IncrementalGeneratorInitializationContext context,
+ IncrementalValuesProvider comparables,
+ IncrementalValueProvider options)
+ {
+ var operators = comparables
+ .Where(state => state.OperatorsGeneration != OperatorsGeneration.None)
+ .Collect()
+ .Select(static (states, _) => states.IsDefaultOrEmpty
+ ? ImmutableArray.Empty
+ : states.Distinct(TypeOnlyComparer.Instance).ToImmutableArray())
+ .WithComparer(new SetComparer())
+ .SelectMany((states, _) => states)
+ .SelectMany((state, _) =>
+ {
+ if (EqualityComparisonOperatorsCodeGenerator.TryGet(state.OperatorsGeneration, state.EqualityComparer, out var codeGenerator))
+ return ImmutableArray.Create((State: state, CodeGenerator: codeGenerator));
+
+ return ImmutableArray<(EqualityComparisonOperatorsGeneratorState State, IInterfaceCodeGenerator CodeGenerator)>.Empty;
+ });
+
+ context.RegisterSourceOutput(operators.Combine(options), (ctx, tuple) =>
+ {
+ var state = tuple.Left.State;
+ var generator = tuple.Left.CodeGenerator;
+
+ GenerateCode(ctx, state.Type.Namespace, state.Type.Name, (state.Type, state.KeyMember), tuple.Right, InterfaceCodeGeneratorFactory.Create(generator));
+ });
+ }
+
protected void InitializeOperatorsCodeGenerator(
IncrementalGeneratorInitializationContext context,
IncrementalValuesProvider operators,
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/TypeOnlyComparer.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/TypeOnlyComparer.cs
index 2291b18c..c83c9c90 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/TypeOnlyComparer.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/TypeOnlyComparer.cs
@@ -5,6 +5,7 @@ public class TypeOnlyComparer
IEqualityComparer,
IEqualityComparer,
IEqualityComparer,
+ IEqualityComparer,
IEqualityComparer
{
public static readonly TypeOnlyComparer Instance = new();
@@ -13,12 +14,14 @@ public class TypeOnlyComparer
public bool Equals(ComparableGeneratorState x, ComparableGeneratorState y) => x.Type.TypeFullyQualified == y.Type.TypeFullyQualified;
public bool Equals(ParsableGeneratorState x, ParsableGeneratorState y) => x.Type.TypeFullyQualified == y.Type.TypeFullyQualified;
public bool Equals(ComparisonOperatorsGeneratorState x, ComparisonOperatorsGeneratorState y) => x.Type.TypeFullyQualified == y.Type.TypeFullyQualified;
+ public bool Equals(EqualityComparisonOperatorsGeneratorState x, EqualityComparisonOperatorsGeneratorState y) => x.Type.TypeFullyQualified == y.Type.TypeFullyQualified;
public bool Equals(OperatorsGeneratorState x, OperatorsGeneratorState y) => x.Type.TypeFullyQualified == y.Type.TypeFullyQualified;
public int GetHashCode(FormattableGeneratorState obj) => obj.Type.TypeFullyQualified.GetHashCode();
public int GetHashCode(ComparableGeneratorState obj) => obj.Type.TypeFullyQualified.GetHashCode();
public int GetHashCode(ParsableGeneratorState obj) => obj.Type.TypeFullyQualified.GetHashCode();
public int GetHashCode(ComparisonOperatorsGeneratorState obj) => obj.Type.TypeFullyQualified.GetHashCode();
+ public int GetHashCode(EqualityComparisonOperatorsGeneratorState obj) => obj.Type.TypeFullyQualified.GetHashCode();
public int GetHashCode(OperatorsGeneratorState obj) => obj.Type.TypeFullyQualified.GetHashCode();
}
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/TypedMemberState.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/TypedMemberState.cs
index 2f3c3cd5..b868da1e 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/TypedMemberState.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/TypedMemberState.cs
@@ -153,7 +153,7 @@ public bool Equals(ITypedMemberState? obj)
public bool Equals(TypedMemberState? other)
{
- if (ReferenceEquals(null, other))
+ if (other is null)
return false;
if (ReferenceEquals(this, other))
return true;
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/AllValueObjectSettings.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/AllValueObjectSettings.cs
index 565e280a..d6ba2ca7 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/AllValueObjectSettings.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/AllValueObjectSettings.cs
@@ -16,6 +16,7 @@ public sealed class AllValueObjectSettings : IEquatable
public OperatorsGeneration MultiplyOperators { get; }
public OperatorsGeneration DivisionOperators { get; }
public OperatorsGeneration ComparisonOperators { get; }
+ public OperatorsGeneration EqualityComparisonOperators { get; }
public string DefaultInstancePropertyName { get; }
public AllValueObjectSettings(AttributeData valueObjectAttribute)
@@ -31,8 +32,13 @@ public AllValueObjectSettings(AttributeData valueObjectAttribute)
SubtractionOperators = SkipFactoryMethods ? OperatorsGeneration.None : valueObjectAttribute.FindSubtractionOperators();
MultiplyOperators = SkipFactoryMethods ? OperatorsGeneration.None : valueObjectAttribute.FindMultiplyOperators();
DivisionOperators = SkipFactoryMethods ? OperatorsGeneration.None : valueObjectAttribute.FindDivisionOperators();
+ EqualityComparisonOperators = valueObjectAttribute.FindEqualityComparisonOperators();
ComparisonOperators = valueObjectAttribute.FindComparisonOperators();
DefaultInstancePropertyName = valueObjectAttribute.FindDefaultInstancePropertyName() ?? "Empty";
+
+ // Comparison operators depend on the equality comparison operators
+ if (ComparisonOperators > EqualityComparisonOperators)
+ EqualityComparisonOperators = ComparisonOperators;
}
public override bool Equals(object? obj)
@@ -42,7 +48,7 @@ public override bool Equals(object? obj)
public bool Equals(AllValueObjectSettings? other)
{
- if (ReferenceEquals(null, other))
+ if (other is null)
return false;
if (ReferenceEquals(this, other))
return true;
@@ -59,6 +65,7 @@ public bool Equals(AllValueObjectSettings? other)
&& MultiplyOperators == other.MultiplyOperators
&& DivisionOperators == other.DivisionOperators
&& ComparisonOperators == other.ComparisonOperators
+ && EqualityComparisonOperators == other.EqualityComparisonOperators
&& DefaultInstancePropertyName == other.DefaultInstancePropertyName;
}
@@ -78,6 +85,7 @@ public override int GetHashCode()
hashCode = (hashCode * 397) ^ MultiplyOperators.GetHashCode();
hashCode = (hashCode * 397) ^ DivisionOperators.GetHashCode();
hashCode = (hashCode * 397) ^ ComparisonOperators.GetHashCode();
+ hashCode = (hashCode * 397) ^ EqualityComparisonOperators.GetHashCode();
hashCode = (hashCode * 397) ^ DefaultInstancePropertyName.GetHashCode();
return hashCode;
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/DivisionOperatorsCodeGenerator.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/DivisionOperatorsCodeGenerator.cs
index 5ac9da37..580b487c 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/DivisionOperatorsCodeGenerator.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/DivisionOperatorsCodeGenerator.cs
@@ -56,11 +56,11 @@ public void GenerateBaseTypes(StringBuilder sb, ITypeInformation type, IMemberIn
sb.Append(@"
global::System.Numerics.IDivisionOperators<").Append(type.TypeFullyQualified).Append(", ").Append(type.TypeFullyQualified).Append(", ").Append(type.TypeFullyQualified).Append(">");
- if (_withKeyTypeOverloads)
- {
- sb.Append(@",
+ if (!_withKeyTypeOverloads)
+ return;
+
+ sb.Append(@",
global::System.Numerics.IDivisionOperators<").Append(type.TypeFullyQualified).Append(", ").Append(keyMember.TypeFullyQualified).Append(", ").Append(type.TypeFullyQualified).Append(">");
- }
}
public void GenerateImplementation(StringBuilder sb, ITypeInformation type, IMemberInformation keyMember)
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/MultiplyOperatorsCodeGenerator.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/MultiplyOperatorsCodeGenerator.cs
index 066725c3..e9512ebb 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/MultiplyOperatorsCodeGenerator.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/MultiplyOperatorsCodeGenerator.cs
@@ -56,11 +56,11 @@ public void GenerateBaseTypes(StringBuilder sb, ITypeInformation type, IMemberIn
sb.Append(@"
global::System.Numerics.IMultiplyOperators<").Append(type.TypeFullyQualified).Append(", ").Append(type.TypeFullyQualified).Append(", ").Append(type.TypeFullyQualified).Append(">");
- if (_withKeyTypeOverloads)
- {
- sb.Append(@",
+ if (!_withKeyTypeOverloads)
+ return;
+
+ sb.Append(@",
global::System.Numerics.IMultiplyOperators<").Append(type.TypeFullyQualified).Append(", ").Append(keyMember.TypeFullyQualified).Append(", ").Append(type.TypeFullyQualified).Append(">");
- }
}
public void GenerateImplementation(StringBuilder sb, ITypeInformation type, IMemberInformation keyMember)
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/SubtractionOperatorsCodeGenerator.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/SubtractionOperatorsCodeGenerator.cs
index 4286ab87..fc0b0c29 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/SubtractionOperatorsCodeGenerator.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/SubtractionOperatorsCodeGenerator.cs
@@ -59,11 +59,11 @@ public void GenerateBaseTypes(StringBuilder sb, ITypeInformation type, IMemberIn
sb.Append(@"
global::System.Numerics.ISubtractionOperators<").Append(type.TypeFullyQualified).Append(", ").Append(type.TypeFullyQualified).Append(", ").Append(type.TypeFullyQualified).Append(">");
- if (_withKeyTypeOverloads)
- {
- sb.Append(@",
+ if (!_withKeyTypeOverloads)
+ return;
+
+ sb.Append(@",
global::System.Numerics.ISubtractionOperators<").Append(type.TypeFullyQualified).Append(", ").Append(keyMember.TypeFullyQualified).Append(", ").Append(type.TypeFullyQualified).Append(">");
- }
}
public void GenerateImplementation(StringBuilder sb, ITypeInformation type, IMemberInformation keyMember)
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/ValueObjectCodeGenerator.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/ValueObjectCodeGenerator.cs
index c854f40c..9d26e991 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/ValueObjectCodeGenerator.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/ValueObjectCodeGenerator.cs
@@ -55,8 +55,7 @@ private void GenerateValueObject(bool emptyStringYieldsNull, CancellationToken c
}
_sb.Append(@"
- partial ").Append(_state.IsReferenceType ? "class" : "struct").Append(" ").Append(_state.Name).Append(" : global::System.IEquatable<").Append(_state.TypeFullyQualifiedNullAnnotated).Append(@">,
- global::System.Numerics.IEqualityOperators<").Append(_state.TypeFullyQualified).Append(", ").Append(_state.TypeFullyQualified).Append(", bool>");
+ partial ").Append(_state.IsReferenceType ? "class" : "struct").Append(" ").Append(_state.Name).Append(" : global::System.IEquatable<").Append(_state.TypeFullyQualifiedNullAnnotated).Append(">");
if (_state.HasKeyMember)
{
@@ -72,6 +71,7 @@ private void GenerateValueObject(bool emptyStringYieldsNull, CancellationToken c
else
{
_sb.Append(@",
+ global::System.Numerics.IEqualityOperators<").Append(_state.TypeFullyQualified).Append(", ").Append(_state.TypeFullyQualified).Append(@", bool>,
global::Thinktecture.IComplexValueObject");
}
@@ -124,7 +124,11 @@ private void GenerateValueObject(bool emptyStringYieldsNull, CancellationToken c
cancellationToken.ThrowIfCancellationRequested();
GenerateConstructor();
- GenerateEqualityOperators();
+
+ // Keyed value object get their equality operators from EqualityComparisonOperatorsCodeGenerator
+ if (!_state.HasKeyMember)
+ GenerateEqualityOperators();
+
GenerateEquals();
GenerateGetHashCode();
@@ -564,7 +568,7 @@ private void GenerateConstructor()
var isStructDefaultCtor = !_state.IsReferenceType && fieldsAndProperties.Count == 0;
- if(isStructDefaultCtor)
+ if (isStructDefaultCtor)
return;
_sb.Append(@"
@@ -628,9 +632,6 @@ public bool Equals(").Append(_state.TypeFullyQualifiedNullAnnotated).Append(@" o
if (other is null)
return false;
- if (!global::System.Object.ReferenceEquals(GetType(), other.GetType()))
- return false;
-
if (global::System.Object.ReferenceEquals(this, other))
return true;
");
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/ValueObjectMemberSettings.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/ValueObjectMemberSettings.cs
index 21758f54..11c4bb1e 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/ValueObjectMemberSettings.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/ValueObjectMemberSettings.cs
@@ -83,7 +83,7 @@ public override bool Equals(object? obj)
public bool Equals(ValueObjectMemberSettings? other)
{
- if (ReferenceEquals(null, other))
+ if (other is null)
return false;
if (ReferenceEquals(this, other))
return true;
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/ValueObjectSourceGenerator.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/ValueObjectSourceGenerator.cs
index ef6c7cf1..599b82e6 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/ValueObjectSourceGenerator.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/ValueObjectSourceGenerator.cs
@@ -46,6 +46,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
InitializeComparableCodeGenerator(context, keyedValueObjects, options);
InitializeParsableCodeGenerator(context, keyedValueObjects, options);
InitializeComparisonOperatorsCodeGenerator(context, keyedValueObjects, options);
+ InitializeEqualityComparisonOperatorsCodeGenerator(context, keyedValueObjects, options);
InitializeAdditionOperatorsCodeGenerator(context, keyedValueObjects, options);
InitializeSubtractionOperatorsCodeGenerator(context, keyedValueObjects, options);
InitializeMultiplyOperatorsCodeGenerator(context, keyedValueObjects, options);
@@ -178,6 +179,17 @@ private void InitializeComparisonOperatorsCodeGenerator(IncrementalGeneratorInit
InitializeComparisonOperatorsCodeGenerator(context, comparables, options);
}
+ private void InitializeEqualityComparisonOperatorsCodeGenerator(IncrementalGeneratorInitializationContext context, IncrementalValuesProvider validStates, IncrementalValueProvider options)
+ {
+ var comparables = validStates
+ .Select((state, _) => new EqualityComparisonOperatorsGeneratorState(state.Type,
+ state.KeyMember.Member,
+ state.Settings.EqualityComparisonOperators,
+ state.KeyMember.EqualityComparerAccessor is null ? null : new ComparerInfo(state.KeyMember.EqualityComparerAccessor, true)));
+
+ InitializeEqualityComparisonOperatorsCodeGenerator(context, comparables, options);
+ }
+
private void InitializeAdditionOperatorsCodeGenerator(IncrementalGeneratorInitializationContext context, IncrementalValuesProvider validStates, IncrementalValueProvider options)
{
var operators = validStates
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/ValueObjectSourceGeneratorState.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/ValueObjectSourceGeneratorState.cs
index c4f7a2ec..9f3278e9 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/ValueObjectSourceGeneratorState.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueObjects/ValueObjectSourceGeneratorState.cs
@@ -9,6 +9,7 @@ public sealed class ValueObjectSourceGeneratorState : ITypeInformation, IEquatab
public string TypeFullyQualifiedNullable { get; }
public string TypeFullyQualifiedNullAnnotated => IsReferenceType ? TypeFullyQualifiedNullable : TypeFullyQualified;
public string TypeMinimallyQualified { get; }
+ public bool IsEqualWithReferenceEquality => false;
public string? Namespace { get; }
public string Name { get; }
@@ -108,7 +109,7 @@ public override bool Equals(object? obj)
public bool Equals(ValueObjectSourceGeneratorState? other)
{
- if (ReferenceEquals(null, other))
+ if (other is null)
return false;
if (ReferenceEquals(this, other))
return true;
diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/Extensions/AttributeDataExtensions.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/Extensions/AttributeDataExtensions.cs
index e5b15a90..2994c80c 100644
--- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/Extensions/AttributeDataExtensions.cs
+++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/Extensions/AttributeDataExtensions.cs
@@ -70,6 +70,11 @@ public static OperatorsGeneration FindComparisonOperators(this AttributeData att
return GetOperatorsGeneration(attributeData, "ComparisonOperators");
}
+ public static OperatorsGeneration FindEqualityComparisonOperators(this AttributeData attributeData)
+ {
+ return GetOperatorsGeneration(attributeData, "EqualityComparisonOperators");
+ }
+
public static bool? FindSkipToString(this AttributeData attributeData)
{
return GetBooleanParameterValue(attributeData, "SkipToString");
diff --git a/src/Thinktecture.Runtime.Extensions/EnumGenerationAttribute.cs b/src/Thinktecture.Runtime.Extensions/EnumGenerationAttribute.cs
index 559c14d0..763bfa09 100644
--- a/src/Thinktecture.Runtime.Extensions/EnumGenerationAttribute.cs
+++ b/src/Thinktecture.Runtime.Extensions/EnumGenerationAttribute.cs
@@ -38,11 +38,31 @@ public string KeyPropertyName
///
/// Indication whether and how the generator should generate the implementation of .
///
+ /// Please note that the comparison operators depend on . For example, if are set to
+ /// then the are set to as well.
+ ///
/// This setting has no effect:
- /// - if the key is not an itself and has no corresponding operators (op_GreaterThan
, op_GreaterThanOrEqual
, op_LessThan
, op_LessThanOrEqual
).
+ /// - if key-member is not an itself and has no corresponding operators (op_GreaterThan
, op_GreaterThanOrEqual
, op_LessThan
, op_LessThanOrEqual
).
///
public OperatorsGeneration ComparisonOperators { get; set; }
+ private OperatorsGeneration _equalityComparisonOperators;
+
+ ///
+ /// Indication whether and how the generator should generate the implementation of .
+ ///
+ /// Please note that the comparison operators depend on . For example, if are set to
+ /// then the are set to as well.
+ ///
+ /// This setting has no effect:
+ /// - if key-member is not an itself and has no corresponding operators (op_Equality
, op_Inequality
).
+ ///
+ public OperatorsGeneration EqualityComparisonOperators
+ {
+ get => ComparisonOperators > _equalityComparisonOperators ? ComparisonOperators : _equalityComparisonOperators;
+ set => _equalityComparisonOperators = value;
+ }
+
///
/// Indication whether the generator should skip the implementation of or not.
///
diff --git a/src/Thinktecture.Runtime.Extensions/ValueObjectAttribute.cs b/src/Thinktecture.Runtime.Extensions/ValueObjectAttribute.cs
index 1c07e31c..75781a06 100644
--- a/src/Thinktecture.Runtime.Extensions/ValueObjectAttribute.cs
+++ b/src/Thinktecture.Runtime.Extensions/ValueObjectAttribute.cs
@@ -106,12 +106,33 @@ public bool NullInFactoryMethodsYieldsNull
///
/// Indication whether and how the generator should generate the implementation of .
///
+ /// Please note that the comparison operators depend on . For example, if are set to
+ /// then the are set to as well.
+ ///
/// This setting has no effect:
/// - on non-keyed value objects (i.e. has more than 1 field/property)
/// - if key-member is not an itself and has no corresponding operators (op_GreaterThan
, op_GreaterThanOrEqual
, op_LessThan
, op_LessThanOrEqual
).
///
public OperatorsGeneration ComparisonOperators { get; set; }
+ private OperatorsGeneration _equalityComparisonOperators;
+
+ ///
+ /// Indication whether and how the generator should generate the implementation of .
+ ///
+ /// Please note that the comparison operators depend on . For example, if are set to
+ /// then the are set to as well.
+ ///
+ /// This setting has no effect:
+ /// - on non-keyed value objects (i.e. has more than 1 field/property)
+ /// - if key-member is not an itself and has no corresponding operators (op_Equality
, op_Inequality
).
+ ///
+ public OperatorsGeneration EqualityComparisonOperators
+ {
+ get => ComparisonOperators > _equalityComparisonOperators ? ComparisonOperators : _equalityComparisonOperators;
+ set => _equalityComparisonOperators = value;
+ }
+
///
/// Indication whether the generator should skip the implementation of or not.
///
diff --git a/test/Thinktecture.Runtime.Extensions.SourceGenerator.Tests/SourceGeneratorTests/EnumSourceGeneratorTests.cs b/test/Thinktecture.Runtime.Extensions.SourceGenerator.Tests/SourceGeneratorTests/EnumSourceGeneratorTests.cs
index 08292849..871e4293 100644
--- a/test/Thinktecture.Runtime.Extensions.SourceGenerator.Tests/SourceGeneratorTests/EnumSourceGeneratorTests.cs
+++ b/test/Thinktecture.Runtime.Extensions.SourceGenerator.Tests/SourceGeneratorTests/EnumSourceGeneratorTests.cs
@@ -24,8 +24,7 @@ namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial class TestEnum : global::Thinktecture.IEnum,
- global::System.IEquatable,
- global::System.Numerics.IEqualityOperators
+ global::System.IEquatable
{
[global::System.Runtime.CompilerServices.ModuleInitializer]
internal static void ModuleInit()
@@ -161,28 +160,6 @@ public static bool TryGet([global::System.Diagnostics.CodeAnalysis.AllowNull] st
return global::Thinktecture.Tests.TestEnum.Get(key);
}
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if items are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestEnum? item1, global::Thinktecture.Tests.TestEnum? item2)
- {
- return global::System.Object.ReferenceEquals(item1, item2);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if items are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestEnum? item1, global::Thinktecture.Tests.TestEnum? item2)
- {
- return !(item1 == item2);
- }
-
///
public bool Equals(global::Thinktecture.Tests.TestEnum? other)
{
@@ -408,6 +385,194 @@ public static bool TryParse(
}
}
+""";
+
+ /* language=c# */
+ private const string _EQUALITY_COMPARABLE_OPERATORS_CLASS = _GENERATED_HEADER + """
+
+namespace Thinktecture.Tests;
+
+partial class TestEnum :
+ global::System.Numerics.IEqualityOperators
+{
+ ///
+ /// Compares two instances of .
+ ///
+ /// Instance to compare.
+ /// Another instance to compare.
+ /// true if objects are equal; otherwise false.
+ public static bool operator ==(global::Thinktecture.Tests.TestEnum? obj, global::Thinktecture.Tests.TestEnum? other)
+ {
+ return global::System.Object.ReferenceEquals(obj, other);
+ }
+
+ ///
+ /// Compares two instances of .
+ ///
+ /// Instance to compare.
+ /// Another instance to compare.
+ /// false if objects are equal; otherwise true.
+ public static bool operator !=(global::Thinktecture.Tests.TestEnum? obj, global::Thinktecture.Tests.TestEnum? other)
+ {
+ return !(obj == other);
+ }
+}
+
+""";
+
+ /* language=c# */
+ private const string _EQUALITY_COMPARABLE_OPERATORS_STRUCT = _GENERATED_HEADER + """
+
+namespace Thinktecture.Tests;
+
+partial struct TestEnum :
+ global::System.Numerics.IEqualityOperators
+{
+ ///
+ /// Compares two instances of .
+ ///
+ /// Instance to compare.
+ /// Another instance to compare.
+ /// true if objects are equal; otherwise false.
+ public static bool operator ==(global::Thinktecture.Tests.TestEnum obj, global::Thinktecture.Tests.TestEnum other)
+ {
+ return obj.Equals(other);
+ }
+
+ ///
+ /// Compares two instances of .
+ ///
+ /// Instance to compare.
+ /// Another instance to compare.
+ /// false if objects are equal; otherwise true.
+ public static bool operator !=(global::Thinktecture.Tests.TestEnum obj, global::Thinktecture.Tests.TestEnum other)
+ {
+ return !(obj == other);
+ }
+}
+
+""";
+
+ /* language=c# */
+ private const string _EQUALITY_COMPARABLE_OPERATORS_CLASS_WITH_KEY_OVERLOADS = _GENERATED_HEADER + """
+
+namespace Thinktecture.Tests;
+
+partial class TestEnum :
+ global::System.Numerics.IEqualityOperators,
+ global::System.Numerics.IEqualityOperators
+{
+ ///
+ /// Compares two instances of .
+ ///
+ /// Instance to compare.
+ /// Another instance to compare.
+ /// true if objects are equal; otherwise false.
+ public static bool operator ==(global::Thinktecture.Tests.TestEnum? obj, global::Thinktecture.Tests.TestEnum? other)
+ {
+ return global::System.Object.ReferenceEquals(obj, other);
+ }
+
+ ///
+ /// Compares two instances of .
+ ///
+ /// Instance to compare.
+ /// Another instance to compare.
+ /// false if objects are equal; otherwise true.
+ public static bool operator !=(global::Thinktecture.Tests.TestEnum? obj, global::Thinktecture.Tests.TestEnum? other)
+ {
+ return !(obj == other);
+ }
+
+ private static bool Equals(global::Thinktecture.Tests.TestEnum? obj, int value)
+ {
+ if (obj is null)
+ return false;
+
+ return KeyEqualityComparer.Equals(obj.Key, value);
+ }
+
+ ///
+ /// Compares an instance of with .
+ ///
+ /// Instance to compare.
+ /// Value to compare with.
+ /// true if objects are equal; otherwise false.
+ public static bool operator ==(global::Thinktecture.Tests.TestEnum? obj, int value)
+ {
+ return Equals(obj, value);
+ }
+
+ ///
+ /// Compares an instance of with .
+ ///
+ /// Value to compare.
+ /// Instance to compare with.
+ /// true if objects are equal; otherwise false.
+ public static bool operator ==(int value, global::Thinktecture.Tests.TestEnum? obj)
+ {
+ return Equals(obj, value);
+ }
+
+ ///
+ /// Compares an instance of with .
+ ///
+ /// Instance to compare.
+ /// Value to compare with.
+ /// false if objects are equal; otherwise true.
+ public static bool operator !=(global::Thinktecture.Tests.TestEnum? obj, int value)
+ {
+ return !(obj == value);
+ }
+
+ ///
+ /// Compares an instance of with .
+ ///
+ /// Value to compare.
+ /// Instance to compare with.
+ /// false if objects are equal; otherwise true.
+ public static bool operator !=(int value, global::Thinktecture.Tests.TestEnum? obj)
+ {
+ return !(obj == value);
+ }
+}
+
+""";
+
+ /* language=c# */
+ private const string _EQUALITY_COMPARABLE_OPERATORS_VALIDATABLE_CLASS = _GENERATED_HEADER + """
+
+namespace Thinktecture.Tests;
+
+partial class TestEnum :
+ global::System.Numerics.IEqualityOperators
+{
+ ///
+ /// Compares two instances of .
+ ///
+ /// Instance to compare.
+ /// Another instance to compare.
+ /// true if objects are equal; otherwise false.
+ public static bool operator ==(global::Thinktecture.Tests.TestEnum? obj, global::Thinktecture.Tests.TestEnum? other)
+ {
+ if (obj is null)
+ return other is null;
+
+ return obj.Equals(other);
+ }
+
+ ///
+ /// Compares two instances of .
+ ///
+ /// Instance to compare.
+ /// Another instance to compare.
+ /// false if objects are equal; otherwise true.
+ public static bool operator !=(global::Thinktecture.Tests.TestEnum? obj, global::Thinktecture.Tests.TestEnum? other)
+ {
+ return !(obj == other);
+ }
+}
+
""";
/* language=c# */
@@ -563,15 +728,17 @@ public partial class TestEnum : IEnum
}
";
var outputs = GetGeneratedOutputs(source, typeof(IEnum<>).Assembly);
- outputs.Should().HaveCount(3);
+ outputs.Should().HaveCount(4);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.Parsable.g.cs")).Value;
+ var equalityComparisonOperators = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.EqualityComparisonOperators.g.cs")).Value;
AssertOutput(mainOutput, _MAIN_OUTPUT_CLASS);
AssertOutput(comparableOutput, _COMPARABLE_OUTPUT_CLASS);
AssertOutput(parsableOutput, _PARSABLE_OUTPUT_CLASS_STRING_BASED);
+ AssertOutput(equalityComparisonOperators, _EQUALITY_COMPARABLE_OPERATORS_CLASS);
}
[Fact]
@@ -602,14 +769,16 @@ public partial class TestEnum : BaseClass, IEnum
}
";
var outputs = GetGeneratedOutputs(source, typeof(IEnum<>).Assembly);
- outputs.Should().HaveCount(3);
+ outputs.Should().HaveCount(4);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.Parsable.g.cs")).Value;
+ var equalityComparisonOperators = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.EqualityComparisonOperators.g.cs")).Value;
AssertOutput(comparableOutput, _COMPARABLE_OUTPUT_CLASS);
AssertOutput(parsableOutput, _PARSABLE_OUTPUT_CLASS_STRING_BASED);
+ AssertOutput(equalityComparisonOperators, _EQUALITY_COMPARABLE_OPERATORS_CLASS);
/* language=c# */
AssertOutput(mainOutput, _GENERATED_HEADER + """
@@ -618,8 +787,7 @@ namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial class TestEnum : global::Thinktecture.IEnum,
- global::System.IEquatable,
- global::System.Numerics.IEqualityOperators
+ global::System.IEquatable
{
[global::System.Runtime.CompilerServices.ModuleInitializer]
internal static void ModuleInit()
@@ -770,28 +938,6 @@ public static bool TryGet([global::System.Diagnostics.CodeAnalysis.AllowNull] st
return global::Thinktecture.Tests.TestEnum.Get(key);
}
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if items are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestEnum? item1, global::Thinktecture.Tests.TestEnum? item2)
- {
- return global::System.Object.ReferenceEquals(item1, item2);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if items are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestEnum? item1, global::Thinktecture.Tests.TestEnum? item2)
- {
- return !(item1 == item2);
- }
-
///
public bool Equals(global::Thinktecture.Tests.TestEnum? other)
{
@@ -966,15 +1112,17 @@ public partial class TestEnum : Thinktecture.IEnum
}
";
var outputs = GetGeneratedOutputs(source, typeof(IEnum<>).Assembly);
- outputs.Should().HaveCount(3);
+ outputs.Should().HaveCount(4);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.Parsable.g.cs")).Value;
+ var equalityComparisonOperators = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.EqualityComparisonOperators.g.cs")).Value;
AssertOutput(mainOutput, _MAIN_OUTPUT_CLASS);
AssertOutput(comparableOutput, _COMPARABLE_OUTPUT_CLASS);
AssertOutput(parsableOutput, _PARSABLE_OUTPUT_CLASS_STRING_BASED);
+ AssertOutput(equalityComparisonOperators, _EQUALITY_COMPARABLE_OPERATORS_CLASS);
}
[Fact]
@@ -992,19 +1140,19 @@ public partial class TestEnum : IEnum
}
";
var outputs = GetGeneratedOutputs(source, typeof(IEnum<>).Assembly);
- outputs.Should().HaveCount(3);
+ outputs.Should().HaveCount(4);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("TestEnum.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("TestEnum.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("TestEnum.Parsable.g.cs")).Value;
+ var equalityComparisonOperators = outputs.Single(kvp => kvp.Key.Contains("TestEnum.EqualityComparisonOperators.g.cs")).Value;
/* language=c# */
AssertOutput(mainOutput, _GENERATED_HEADER + """
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial class TestEnum : global::Thinktecture.IEnum,
- global::System.IEquatable,
- global::System.Numerics.IEqualityOperators
+ global::System.IEquatable
{
[global::System.Runtime.CompilerServices.ModuleInitializer]
internal static void ModuleInit()
@@ -1140,28 +1288,6 @@ public static bool TryGet([global::System.Diagnostics.CodeAnalysis.AllowNull] st
return global::TestEnum.Get(key);
}
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if items are equal; otherwise false.
- public static bool operator ==(global::TestEnum? item1, global::TestEnum? item2)
- {
- return global::System.Object.ReferenceEquals(item1, item2);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if items are equal; otherwise true.
- public static bool operator !=(global::TestEnum? item1, global::TestEnum? item2)
- {
- return !(item1 == item2);
- }
-
///
public bool Equals(global::TestEnum? other)
{
@@ -1382,6 +1508,37 @@ public static bool TryParse(
}
}
+""");
+
+ /* language=c# */
+ AssertOutput(equalityComparisonOperators, _GENERATED_HEADER + """
+
+partial class TestEnum :
+ global::System.Numerics.IEqualityOperators
+{
+ ///
+ /// Compares two instances of .
+ ///
+ /// Instance to compare.
+ /// Another instance to compare.
+ /// true if objects are equal; otherwise false.
+ public static bool operator ==(global::TestEnum? obj, global::TestEnum? other)
+ {
+ return global::System.Object.ReferenceEquals(obj, other);
+ }
+
+ ///
+ /// Compares two instances of .
+ ///
+ /// Instance to compare.
+ /// Another instance to compare.
+ /// false if objects are equal; otherwise true.
+ public static bool operator !=(global::TestEnum? obj, global::TestEnum? other)
+ {
+ return !(obj == other);
+ }
+}
+
""");
}
@@ -1442,15 +1599,17 @@ public UnusedDerivedEnum(string key)
""";
var outputs = GetGeneratedOutputs(source, typeof(IEnum<>).Assembly);
- outputs.Should().HaveCount(4);
+ outputs.Should().HaveCount(5);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.Parsable.g.cs")).Value;
var derivedTypesOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.DerivedTypes.g.cs")).Value;
+ var equalityComparisonOperators = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.EqualityComparisonOperators.g.cs")).Value;
AssertOutput(comparableOutput, _COMPARABLE_OUTPUT_CLASS);
AssertOutput(parsableOutput, _PARSABLE_OUTPUT_CLASS_STRING_BASED);
+ AssertOutput(equalityComparisonOperators, _EQUALITY_COMPARABLE_OPERATORS_CLASS);
/* language=c# */
AssertOutput(mainOutput, _GENERATED_HEADER + """
@@ -1459,8 +1618,7 @@ namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial class TestEnum : global::Thinktecture.IEnum,
- global::System.IEquatable,
- global::System.Numerics.IEqualityOperators
+ global::System.IEquatable
{
[global::System.Runtime.CompilerServices.ModuleInitializer]
internal static void ModuleInit()
@@ -1596,28 +1754,6 @@ public static bool TryGet([global::System.Diagnostics.CodeAnalysis.AllowNull] st
return global::Thinktecture.Tests.TestEnum.Get(key);
}
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if items are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestEnum? item1, global::Thinktecture.Tests.TestEnum? item2)
- {
- return global::System.Object.ReferenceEquals(item1, item2);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if items are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestEnum? item1, global::Thinktecture.Tests.TestEnum? item2)
- {
- return !(item1 == item2);
- }
-
///
public bool Equals(global::Thinktecture.Tests.TestEnum? other)
{
@@ -1957,14 +2093,16 @@ public partial class TestEnum : IValidatableEnum
}
";
var outputs = GetGeneratedOutputs(source, typeof(IValidatableEnum<>).Assembly);
- outputs.Should().HaveCount(3);
+ outputs.Should().HaveCount(4);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.Parsable.g.cs")).Value;
+ var equalityComparisonOperators = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.EqualityComparisonOperators.g.cs")).Value;
AssertOutput(comparableOutput, _COMPARABLE_OUTPUT_CLASS);
AssertOutput(parsableOutput, _PARSABLE_OUTPUT_VALIDATABLE_CLASS_STRING_BASED);
+ AssertOutput(equalityComparisonOperators, _EQUALITY_COMPARABLE_OPERATORS_VALIDATABLE_CLASS);
/* language=c# */
AssertOutput(mainOutput, _GENERATED_HEADER + """
@@ -1973,8 +2111,7 @@ namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial class TestEnum : global::Thinktecture.IEnum,
- global::System.IEquatable,
- global::System.Numerics.IEqualityOperators
+ global::System.IEquatable
{
[global::System.Runtime.CompilerServices.ModuleInitializer]
internal static void ModuleInit()
@@ -2073,13 +2210,14 @@ private TestEnum(string key, bool isValid)
private static global::Thinktecture.Tests.TestEnum CreateAndCheckInvalidItem(string key)
{
- var item = CreateInvalidItem(key);
+ var item = CreateInvalidItem(key);
- if (item is null)
- throw new global::System.Exception("The implementation of method 'CreateInvalidItem' must not return 'null'.");
+ if (item is null)
+ throw new global::System.Exception("The implementation of method 'CreateInvalidItem' must not return 'null'.");
+
+ if (item.IsValid)
+ throw new global::System.Exception("The implementation of method 'CreateInvalidItem' must return an instance with property 'IsValid' equals to 'false'.");
- if (item.IsValid)
- throw new global::System.Exception("The implementation of method 'CreateInvalidItem' must return an instance with property 'IsValid' equals to 'false'.");
return item;
}
@@ -2151,31 +2289,6 @@ public static bool TryGet([global::System.Diagnostics.CodeAnalysis.AllowNull] st
return global::Thinktecture.Tests.TestEnum.Get(key);
}
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if items are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestEnum? item1, global::Thinktecture.Tests.TestEnum? item2)
- {
- if (item1 is null)
- return item2 is null;
-
- return item1.Equals(item2);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if items are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestEnum? item1, global::Thinktecture.Tests.TestEnum? item2)
- {
- return !(item1 == item2);
- }
-
///
public bool Equals(global::Thinktecture.Tests.TestEnum? other)
{
@@ -2365,11 +2478,14 @@ namespace Thinktecture.Tests
}
";
var outputs = GetGeneratedOutputs(source, typeof(IValidatableEnum<>).Assembly);
- outputs.Should().HaveCount(3);
+ outputs.Should().HaveCount(4);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.Parsable.g.cs")).Value;
+ var equalityComparisonOperators = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.EqualityComparisonOperators.g.cs")).Value;
+
+ AssertOutput(equalityComparisonOperators, _EQUALITY_COMPARABLE_OPERATORS_STRUCT);
/* language=c# */
AssertOutput(mainOutput, _GENERATED_HEADER + """
@@ -2379,8 +2495,7 @@ namespace Thinktecture.Tests
[global::System.Runtime.InteropServices.StructLayout(global::System.Runtime.InteropServices.LayoutKind.Auto)]
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial struct TestEnum : global::Thinktecture.IEnum,
- global::System.IEquatable,
- global::System.Numerics.IEqualityOperators
+ global::System.IEquatable
{
[global::System.Runtime.CompilerServices.ModuleInitializer]
internal static void ModuleInit()
@@ -2479,10 +2594,11 @@ private TestEnum(string key, bool isValid)
private static global::Thinktecture.Tests.TestEnum CreateAndCheckInvalidItem(string key)
{
- var item = CreateInvalidItem(key);
+ var item = CreateInvalidItem(key);
+
+ if (item.IsValid)
+ throw new global::System.Exception("The implementation of method 'CreateInvalidItem' must return an instance with property 'IsValid' equals to 'false'.");
- if (item.IsValid)
- throw new global::System.Exception("The implementation of method 'CreateInvalidItem' must return an instance with property 'IsValid' equals to 'false'.");
return item;
}
@@ -2554,28 +2670,6 @@ public static bool TryGet([global::System.Diagnostics.CodeAnalysis.AllowNull] st
return global::Thinktecture.Tests.TestEnum.Get(key);
}
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if items are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestEnum item1, global::Thinktecture.Tests.TestEnum item2)
- {
- return item1.Equals(item2);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if items are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestEnum item1, global::Thinktecture.Tests.TestEnum item2)
- {
- return !(item1 == item2);
- }
-
///
public bool Equals(global::Thinktecture.Tests.TestEnum other)
{
@@ -2853,13 +2947,15 @@ public DerivedEnum(
";
var outputs = GetGeneratedOutputs(source, typeof(IValidatableEnum<>).Assembly);
- outputs.Should().HaveCount(3);
+ outputs.Should().HaveCount(4);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.Parsable.g.cs")).Value;
+ var equalityComparisonOperators = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.EqualityComparisonOperators.g.cs")).Value;
AssertOutput(parsableOutput, _PARSABLE_OUTPUT_VALIDATABLE_CLASS_STRING_BASED);
+ AssertOutput(equalityComparisonOperators, _EQUALITY_COMPARABLE_OPERATORS_VALIDATABLE_CLASS);
/* language=c# */
AssertOutput(mainOutput, _GENERATED_HEADER + """
@@ -2868,8 +2964,7 @@ namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial class TestEnum : global::Thinktecture.IEnum,
- global::System.IEquatable,
- global::System.Numerics.IEqualityOperators
+ global::System.IEquatable
{
[global::System.Runtime.CompilerServices.ModuleInitializer]
internal static void ModuleInit()
@@ -2974,16 +3069,17 @@ private TestEnum(string name, bool isValid, int structProperty, int? nullableStr
private static global::Thinktecture.Tests.TestEnum CreateAndCheckInvalidItem(string name)
{
- var item = CreateInvalidItem(name);
+ var item = CreateInvalidItem(name);
- if (item is null)
- throw new global::System.Exception("The implementation of method 'CreateInvalidItem' must not return 'null'.");
+ if (item is null)
+ throw new global::System.Exception("The implementation of method 'CreateInvalidItem' must not return 'null'.");
- if (item.IsValid)
- throw new global::System.Exception("The implementation of method 'CreateInvalidItem' must return an instance with property 'IsValid' equals to 'false'.");
+ if (item.IsValid)
+ throw new global::System.Exception("The implementation of method 'CreateInvalidItem' must return an instance with property 'IsValid' equals to 'false'.");
+
+ if (_itemsLookup.Value.ContainsKey(item.Name))
+ throw new global::System.Exception("The implementation of method 'CreateInvalidItem' must not return an instance with property 'Name' equals to one of a valid item.");
- if (_itemsLookup.Value.ContainsKey(item.Name))
- throw new global::System.Exception("The implementation of method 'CreateInvalidItem' must not return an instance with property 'Name' equals to one of a valid item.");
return item;
}
@@ -3050,31 +3146,6 @@ public static bool TryGet([global::System.Diagnostics.CodeAnalysis.AllowNull] st
return global::Thinktecture.Tests.TestEnum.Get(name);
}
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if items are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestEnum? item1, global::Thinktecture.Tests.TestEnum? item2)
- {
- if (item1 is null)
- return item2 is null;
-
- return item1.Equals(item2);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if items are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestEnum? item1, global::Thinktecture.Tests.TestEnum? item2)
- {
- return !(item1 == item2);
- }
-
///
public bool Equals(global::Thinktecture.Tests.TestEnum? other)
{
@@ -3297,17 +3368,19 @@ public partial class TestEnum : IEnum
}
";
var outputs = GetGeneratedOutputs(source, typeof(IEnum<>).Assembly);
- outputs.Should().HaveCount(5);
+ outputs.Should().HaveCount(6);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.g.cs")).Value;
var formattable = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.Formattable.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.Parsable.g.cs")).Value;
var comparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.ComparisonOperators.g.cs")).Value;
+ var equalityComparisonOperators = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.EqualityComparisonOperators.g.cs")).Value;
AssertOutput(formattable, _FORMATTABLE_OUTPUT_CLASS);
AssertOutput(comparableOutput, _COMPARABLE_OUTPUT_CLASS);
AssertOutput(parsableOutput, _PARSABLE_OUTPUT_CLASS_INT_BASED);
+ AssertOutput(equalityComparisonOperators, _EQUALITY_COMPARABLE_OPERATORS_CLASS);
/* language=c# */
AssertOutput(mainOutput, _GENERATED_HEADER + """
@@ -3316,8 +3389,7 @@ namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial class TestEnum : global::Thinktecture.IEnum,
- global::System.IEquatable,
- global::System.Numerics.IEqualityOperators
+ global::System.IEquatable
{
[global::System.Runtime.CompilerServices.ModuleInitializer]
internal static void ModuleInit()
@@ -3441,28 +3513,6 @@ public static implicit operator int(global::Thinktecture.Tests.TestEnum? item)
return global::Thinktecture.Tests.TestEnum.Get(key);
}
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if items are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestEnum? item1, global::Thinktecture.Tests.TestEnum? item2)
- {
- return global::System.Object.ReferenceEquals(item1, item2);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if items are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestEnum? item1, global::Thinktecture.Tests.TestEnum? item2)
- {
- return !(item1 == item2);
- }
-
///
public bool Equals(global::Thinktecture.Tests.TestEnum? other)
{
@@ -3678,17 +3728,19 @@ public partial class TestEnum : IEnum
}
";
var outputs = GetGeneratedOutputs(source, typeof(IEnum<>).Assembly);
- outputs.Should().HaveCount(5);
+ outputs.Should().HaveCount(6);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.g.cs")).Value;
var formattable = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.Formattable.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.Parsable.g.cs")).Value;
var comparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.ComparisonOperators.g.cs")).Value;
+ var equalityComparisonOperators = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestEnum.EqualityComparisonOperators.g.cs")).Value;
AssertOutput(formattable, _FORMATTABLE_OUTPUT_CLASS);
AssertOutput(comparableOutput, _COMPARABLE_OUTPUT_CLASS);
AssertOutput(parsableOutput, _PARSABLE_OUTPUT_CLASS_INT_BASED);
+ AssertOutput(equalityComparisonOperators, _EQUALITY_COMPARABLE_OPERATORS_CLASS_WITH_KEY_OVERLOADS);
/* language=c# */
AssertOutput(mainOutput, _GENERATED_HEADER + """
@@ -3697,8 +3749,7 @@ namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial class TestEnum : global::Thinktecture.IEnum,
- global::System.IEquatable,
- global::System.Numerics.IEqualityOperators
+ global::System.IEquatable
{
[global::System.Runtime.CompilerServices.ModuleInitializer]
internal static void ModuleInit()
@@ -3822,28 +3873,6 @@ public static implicit operator int(global::Thinktecture.Tests.TestEnum? item)
return global::Thinktecture.Tests.TestEnum.Get(key);
}
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if items are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestEnum? item1, global::Thinktecture.Tests.TestEnum? item2)
- {
- return global::System.Object.ReferenceEquals(item1, item2);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if items are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestEnum? item1, global::Thinktecture.Tests.TestEnum? item2)
- {
- return !(item1 == item2);
- }
-
///
public bool Equals(global::Thinktecture.Tests.TestEnum? other)
{
@@ -4003,7 +4032,8 @@ void AddItem(global::Thinktecture.Tests.TestEnum item, string itemName)
namespace Thinktecture.Tests;
partial class TestEnum :
- global::System.Numerics.IComparisonOperators
+ global::System.Numerics.IComparisonOperators,
+ global::System.Numerics.IComparisonOperators
{
///
public static bool operator <(global::Thinktecture.Tests.TestEnum left, global::Thinktecture.Tests.TestEnum right)
diff --git a/test/Thinktecture.Runtime.Extensions.SourceGenerator.Tests/SourceGeneratorTests/ValueObjectSourceGeneratorTests.cs b/test/Thinktecture.Runtime.Extensions.SourceGenerator.Tests/SourceGeneratorTests/ValueObjectSourceGeneratorTests.cs
index 433f77d3..040360bb 100644
--- a/test/Thinktecture.Runtime.Extensions.SourceGenerator.Tests/SourceGeneratorTests/ValueObjectSourceGeneratorTests.cs
+++ b/test/Thinktecture.Runtime.Extensions.SourceGenerator.Tests/SourceGeneratorTests/ValueObjectSourceGeneratorTests.cs
@@ -447,6 +447,164 @@ partial class TestValueObject :
}
}
+""";
+
+ /* language=c# */
+ private const string _EQUALITY_COMPARISON_OPERATORS_CLASS = _GENERATED_HEADER + """
+
+namespace Thinktecture.Tests;
+
+partial class TestValueObject :
+ global::System.Numerics.IEqualityOperators
+{
+ ///
+ /// Compares two instances of .
+ ///
+ /// Instance to compare.
+ /// Another instance to compare.
+ /// true if objects are equal; otherwise false.
+ public static bool operator ==(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
+ {
+ if (obj is null)
+ return other is null;
+
+ return obj.Equals(other);
+ }
+
+ ///
+ /// Compares two instances of .
+ ///
+ /// Instance to compare.
+ /// Another instance to compare.
+ /// false if objects are equal; otherwise true.
+ public static bool operator !=(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
+ {
+ return !(obj == other);
+ }
+}
+
+""";
+
+ /* language=c# */
+ private const string _EQUALITY_COMPARISON_OPERATORS_STRUCT = _GENERATED_HEADER + """
+
+namespace Thinktecture.Tests;
+
+partial struct TestValueObject :
+ global::System.Numerics.IEqualityOperators
+{
+ ///
+ /// Compares two instances of .
+ ///
+ /// Instance to compare.
+ /// Another instance to compare.
+ /// true if objects are equal; otherwise false.
+ public static bool operator ==(global::Thinktecture.Tests.TestValueObject obj, global::Thinktecture.Tests.TestValueObject other)
+ {
+ return obj.Equals(other);
+ }
+
+ ///
+ /// Compares two instances of .
+ ///
+ /// Instance to compare.
+ /// Another instance to compare.
+ /// false if objects are equal; otherwise true.
+ public static bool operator !=(global::Thinktecture.Tests.TestValueObject obj, global::Thinktecture.Tests.TestValueObject other)
+ {
+ return !(obj == other);
+ }
+}
+
+""";
+
+ /* language=c# */
+ private const string _EQUALITY_COMPARISON_OPERATORS_INT_WITH_KEY_OVERLOADS = _GENERATED_HEADER + """
+
+namespace Thinktecture.Tests;
+
+partial class TestValueObject :
+ global::System.Numerics.IEqualityOperators,
+ global::System.Numerics.IEqualityOperators
+{
+ ///
+ /// Compares two instances of .
+ ///
+ /// Instance to compare.
+ /// Another instance to compare.
+ /// true if objects are equal; otherwise false.
+ public static bool operator ==(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
+ {
+ if (obj is null)
+ return other is null;
+
+ return obj.Equals(other);
+ }
+
+ ///
+ /// Compares two instances of .
+ ///
+ /// Instance to compare.
+ /// Another instance to compare.
+ /// false if objects are equal; otherwise true.
+ public static bool operator !=(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
+ {
+ return !(obj == other);
+ }
+
+ private static bool Equals(global::Thinktecture.Tests.TestValueObject? obj, int value)
+ {
+ if (obj is null)
+ return false;
+
+ return obj.StructField.Equals(value);
+ }
+
+ ///
+ /// Compares an instance of with .
+ ///
+ /// Instance to compare.
+ /// Value to compare with.
+ /// true if objects are equal; otherwise false.
+ public static bool operator ==(global::Thinktecture.Tests.TestValueObject? obj, int value)
+ {
+ return Equals(obj, value);
+ }
+
+ ///
+ /// Compares an instance of with .
+ ///
+ /// Value to compare.
+ /// Instance to compare with.
+ /// true if objects are equal; otherwise false.
+ public static bool operator ==(int value, global::Thinktecture.Tests.TestValueObject? obj)
+ {
+ return Equals(obj, value);
+ }
+
+ ///
+ /// Compares an instance of with .
+ ///
+ /// Instance to compare.
+ /// Value to compare with.
+ /// false if objects are equal; otherwise true.
+ public static bool operator !=(global::Thinktecture.Tests.TestValueObject? obj, int value)
+ {
+ return !(obj == value);
+ }
+
+ ///
+ /// Compares an instance of with .
+ ///
+ /// Value to compare.
+ /// Instance to compare with.
+ /// false if objects are equal; otherwise true.
+ public static bool operator !=(int value, global::Thinktecture.Tests.TestValueObject? obj)
+ {
+ return !(obj == value);
+ }
+}
+
""";
/* language=c# */
@@ -670,9 +828,6 @@ public bool Equals(global::Thinktecture.Tests.TestValueObject? other)
if (other is null)
return false;
- if (!global::System.Object.ReferenceEquals(GetType(), other.GetType()))
- return false;
-
if (global::System.Object.ReferenceEquals(this, other))
return true;
@@ -890,9 +1045,6 @@ public bool Equals(global::Thinktecture.Tests.TestValueObject? other)
if (other is null)
return false;
- if (!global::System.Object.ReferenceEquals(GetType(), other.GetType()))
- return false;
-
if (global::System.Object.ReferenceEquals(this, other))
return true;
@@ -1053,9 +1205,6 @@ public bool Equals(global::Thinktecture.Tests.TestValueObject? other)
if (other is null)
return false;
- if (!global::System.Object.ReferenceEquals(GetType(), other.GetType()))
- return false;
-
if (global::System.Object.ReferenceEquals(this, other))
return true;
@@ -1225,9 +1374,6 @@ public bool Equals(global::TestValueObject? other)
if (other is null)
return false;
- if (!global::System.Object.ReferenceEquals(GetType(), other.GetType()))
- return false;
-
if (global::System.Object.ReferenceEquals(this, other))
return true;
@@ -1307,16 +1453,18 @@ public partial class TestValueObject
}
";
var outputs = GetGeneratedOutputs(source, typeof(ValueObjectAttribute).Assembly);
- outputs.Should().HaveCount(4);
+ outputs.Should().HaveCount(5);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.g.cs")).Value;
var formattableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Formattable.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Comparable.g.cs")).Value;
var comparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.ComparisonOperators.g.cs")).Value;
+ var equalityComparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.EqualityComparisonOperators.g.cs")).Value;
AssertOutput(formattableOutput, _FORMATTABLE_INT);
AssertOutput(comparableOutput, _COMPARABLE_INT);
AssertOutput(comparisonOperatorsOutput, _COMPARISON_OPERATORS_INT);
+ AssertOutput(equalityComparisonOperatorsOutput, _EQUALITY_COMPARISON_OPERATORS_CLASS);
/* language=c# */
AssertOutput(mainOutput, _GENERATED_HEADER + """
@@ -1324,7 +1472,6 @@ public partial class TestValueObject
namespace Thinktecture.Tests
{
partial class TestValueObject : global::System.IEquatable,
- global::System.Numerics.IEqualityOperators,
global::Thinktecture.IKeyedValueObject
{
[global::System.Runtime.CompilerServices.ModuleInitializer]
@@ -1388,31 +1535,6 @@ private TestValueObject(int structField)
static partial void ValidateConstructorArguments(ref int structField);
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if objects are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
- {
- if (obj is null)
- return other is null;
-
- return obj.Equals(other);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if objects are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
- {
- return !(obj == other);
- }
-
///
public override bool Equals(object? other)
{
@@ -1425,9 +1547,6 @@ public bool Equals(global::Thinktecture.Tests.TestValueObject? other)
if (other is null)
return false;
- if (!global::System.Object.ReferenceEquals(GetType(), other.GetType()))
- return false;
-
if (global::System.Object.ReferenceEquals(this, other))
return true;
@@ -1755,16 +1874,18 @@ public readonly partial struct TestValueObject
}
";
var outputs = GetGeneratedOutputs(source, typeof(ValueObjectAttribute).Assembly);
- outputs.Should().HaveCount(4);
+ outputs.Should().HaveCount(5);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Parsable.g.cs")).Value;
var comparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.ComparisonOperators.g.cs")).Value;
+ var equalityComparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.EqualityComparisonOperators.g.cs")).Value;
AssertOutput(comparableOutput, _COMPARABLE_STRUCT_STRING);
AssertOutput(parsableOutput, _PARSABLE_STRUCT_STRING);
AssertOutput(comparisonOperatorsOutput, _COMPARISON_OPERATORS_STRUCT_STRING);
+ AssertOutput(equalityComparisonOperatorsOutput, _EQUALITY_COMPARISON_OPERATORS_STRUCT);
/* language=c# */
AssertOutput(mainOutput, _GENERATED_HEADER + """
@@ -1773,7 +1894,6 @@ namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial struct TestValueObject : global::System.IEquatable,
- global::System.Numerics.IEqualityOperators,
global::Thinktecture.IKeyedValueObject,
global::Thinktecture.IKeyedValueObject
{
@@ -1885,28 +2005,6 @@ private TestValueObject(string referenceField)
static partial void ValidateConstructorArguments(ref string referenceField);
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if objects are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestValueObject obj, global::Thinktecture.Tests.TestValueObject other)
- {
- return obj.Equals(other);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if objects are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestValueObject obj, global::Thinktecture.Tests.TestValueObject other)
- {
- return !(obj == other);
- }
-
///
public override bool Equals(object? other)
{
@@ -1956,18 +2054,21 @@ public readonly partial struct TestValueObject
}
";
var outputs = GetGeneratedOutputs(source, typeof(ValueObjectAttribute).Assembly);
- outputs.Should().HaveCount(9);
+ outputs.Should().HaveCount(10);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.g.cs")).Value;
var formattableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Formattable.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Parsable.g.cs")).Value;
var comparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.ComparisonOperators.g.cs")).Value;
+ var equalityComparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.EqualityComparisonOperators.g.cs")).Value;
var additionOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.AdditionOperators.g.cs")).Value;
var subtractionOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.SubtractionOperators.g.cs")).Value;
var multiplyOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.MultiplyOperators.g.cs")).Value;
var divisionOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.DivisionOperators.g.cs")).Value;
+ AssertOutput(equalityComparisonOperatorsOutput, _EQUALITY_COMPARISON_OPERATORS_STRUCT);
+
/* language=c# */
AssertOutput(mainOutput, _GENERATED_HEADER + """
@@ -1975,7 +2076,6 @@ namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial struct TestValueObject : global::System.IEquatable,
- global::System.Numerics.IEqualityOperators,
global::Thinktecture.IKeyedValueObject,
global::Thinktecture.IKeyedValueObject
{
@@ -2091,28 +2191,6 @@ private TestValueObject(int structField)
static partial void ValidateConstructorArguments(ref int structField);
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if objects are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestValueObject obj, global::Thinktecture.Tests.TestValueObject other)
- {
- return obj.Equals(other);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if objects are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestValueObject obj, global::Thinktecture.Tests.TestValueObject other)
- {
- return !(obj == other);
- }
-
///
public override bool Equals(object? other)
{
@@ -2379,18 +2457,21 @@ public readonly partial struct TestValueObject
}
";
var outputs = GetGeneratedOutputs(source, typeof(ValueObjectAttribute).Assembly);
- outputs.Should().HaveCount(9);
+ outputs.Should().HaveCount(10);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.g.cs")).Value;
var formattableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Formattable.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Parsable.g.cs")).Value;
var comparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.ComparisonOperators.g.cs")).Value;
+ var equalityComparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.EqualityComparisonOperators.g.cs")).Value;
var additionOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.AdditionOperators.g.cs")).Value;
var subtractionOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.SubtractionOperators.g.cs")).Value;
var multiplyOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.MultiplyOperators.g.cs")).Value;
var divisionOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.DivisionOperators.g.cs")).Value;
+ AssertOutput(equalityComparisonOperatorsOutput, _EQUALITY_COMPARISON_OPERATORS_STRUCT);
+
/* language=c# */
AssertOutput(mainOutput, _GENERATED_HEADER + """
@@ -2398,7 +2479,6 @@ namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial struct TestValueObject : global::System.IEquatable,
- global::System.Numerics.IEqualityOperators,
global::Thinktecture.IKeyedValueObject,
global::Thinktecture.IKeyedValueObject
{
@@ -2514,28 +2594,6 @@ private TestValueObject(int structField)
static partial void ValidateConstructorArguments(ref int structField);
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if objects are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestValueObject obj, global::Thinktecture.Tests.TestValueObject other)
- {
- return obj.Equals(other);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if objects are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestValueObject obj, global::Thinktecture.Tests.TestValueObject other)
- {
- return !(obj == other);
- }
-
///
public override bool Equals(object? other)
{
@@ -2802,16 +2860,18 @@ public readonly partial struct TestValueObject
}
";
var outputs = GetGeneratedOutputs(source, typeof(ValueObjectAttribute).Assembly);
- outputs.Should().HaveCount(4);
+ outputs.Should().HaveCount(5);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Parsable.g.cs")).Value;
var comparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.ComparisonOperators.g.cs")).Value;
+ var equalityComparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.EqualityComparisonOperators.g.cs")).Value;
AssertOutput(comparableOutput, _COMPARABLE_STRUCT_STRING);
AssertOutput(parsableOutput, _PARSABLE_STRUCT_STRING);
AssertOutput(comparisonOperatorsOutput, _COMPARISON_OPERATORS_STRUCT_STRING);
+ AssertOutput(equalityComparisonOperatorsOutput, _EQUALITY_COMPARISON_OPERATORS_STRUCT);
/* language=c# */
AssertOutput(mainOutput, _GENERATED_HEADER + """
@@ -2820,7 +2880,6 @@ namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial struct TestValueObject : global::System.IEquatable,
- global::System.Numerics.IEqualityOperators,
global::Thinktecture.IKeyedValueObject,
global::Thinktecture.IKeyedValueObject
{
@@ -2932,36 +2991,14 @@ private TestValueObject(string referenceField)
static partial void ValidateConstructorArguments(ref string referenceField);
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if objects are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestValueObject obj, global::Thinktecture.Tests.TestValueObject other)
+ ///
+ public override bool Equals(object? other)
{
- return obj.Equals(other);
+ return other is global::Thinktecture.Tests.TestValueObject obj && Equals(obj);
}
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if objects are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestValueObject obj, global::Thinktecture.Tests.TestValueObject other)
- {
- return !(obj == other);
- }
-
- ///
- public override bool Equals(object? other)
- {
- return other is global::Thinktecture.Tests.TestValueObject obj && Equals(obj);
- }
-
- ///
- public bool Equals(global::Thinktecture.Tests.TestValueObject other)
+ ///
+ public bool Equals(global::Thinktecture.Tests.TestValueObject other)
{
return global::Thinktecture.ComparerAccessors.StringOrdinalIgnoreCase.EqualityComparer.Equals(this.ReferenceField, other.ReferenceField);
}
@@ -3003,16 +3040,18 @@ public readonly partial struct TestValueObject
}
";
var outputs = GetGeneratedOutputs(source, typeof(ValueObjectAttribute).Assembly);
- outputs.Should().HaveCount(4);
+ outputs.Should().HaveCount(5);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Parsable.g.cs")).Value;
var comparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.ComparisonOperators.g.cs")).Value;
+ var equalityComparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.EqualityComparisonOperators.g.cs")).Value;
AssertOutput(comparableOutput, _COMPARABLE_STRUCT_STRING);
AssertOutput(parsableOutput, _PARSABLE_STRUCT_STRING);
AssertOutput(comparisonOperatorsOutput, _COMPARISON_OPERATORS_STRUCT_STRING);
+ AssertOutput(equalityComparisonOperatorsOutput, _EQUALITY_COMPARISON_OPERATORS_STRUCT);
/* language=c# */
AssertOutput(mainOutput, _GENERATED_HEADER + """
@@ -3021,7 +3060,6 @@ namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial struct TestValueObject : global::System.IEquatable,
- global::System.Numerics.IEqualityOperators,
global::Thinktecture.IKeyedValueObject,
global::Thinktecture.IKeyedValueObject
{
@@ -3133,28 +3171,6 @@ private TestValueObject(string referenceField)
static partial void ValidateConstructorArguments(ref string referenceField);
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if objects are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestValueObject obj, global::Thinktecture.Tests.TestValueObject other)
- {
- return obj.Equals(other);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if objects are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestValueObject obj, global::Thinktecture.Tests.TestValueObject other)
- {
- return !(obj == other);
- }
-
///
public override bool Equals(object? other)
{
@@ -3204,16 +3220,18 @@ public partial class TestValueObject
}
";
var outputs = GetGeneratedOutputs(source, typeof(ValueObjectAttribute).Assembly);
- outputs.Should().HaveCount(4);
+ outputs.Should().HaveCount(5);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Parsable.g.cs")).Value;
var comparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.ComparisonOperators.g.cs")).Value;
+ var equalityComparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.EqualityComparisonOperators.g.cs")).Value;
AssertOutput(comparableOutput, _COMPARABLE_CLASS_STRING);
AssertOutput(parsableOutput, _PARSABLE_CLASS_STRING);
AssertOutput(comparisonOperatorsOutput, _COMPARISON_OPERATORS_CLASS_STRING);
+ AssertOutput(equalityComparisonOperatorsOutput, _EQUALITY_COMPARISON_OPERATORS_CLASS);
/* language=c# */
AssertOutput(mainOutput, _GENERATED_HEADER + """
@@ -3222,7 +3240,6 @@ namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial class TestValueObject : global::System.IEquatable,
- global::System.Numerics.IEqualityOperators,
global::Thinktecture.IKeyedValueObject,
global::Thinktecture.IKeyedValueObject
{
@@ -3336,31 +3353,6 @@ private TestValueObject(string referenceField)
static partial void ValidateConstructorArguments(ref string referenceField);
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if objects are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
- {
- if (obj is null)
- return other is null;
-
- return obj.Equals(other);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if objects are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
- {
- return !(obj == other);
- }
-
///
public override bool Equals(object? other)
{
@@ -3373,9 +3365,6 @@ public bool Equals(global::Thinktecture.Tests.TestValueObject? other)
if (other is null)
return false;
- if (!global::System.Object.ReferenceEquals(GetType(), other.GetType()))
- return false;
-
if (global::System.Object.ReferenceEquals(this, other))
return true;
@@ -3419,13 +3408,14 @@ public partial class TestValueObject
}
";
var outputs = GetGeneratedOutputs(source, typeof(ValueObjectAttribute).Assembly);
- outputs.Should().HaveCount(9);
+ outputs.Should().HaveCount(10);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.g.cs")).Value;
var formattableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Formattable.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Parsable.g.cs")).Value;
var comparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.ComparisonOperators.g.cs")).Value;
+ var equalityComparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.EqualityComparisonOperators.g.cs")).Value;
var additionOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.AdditionOperators.g.cs")).Value;
var subtractionOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.SubtractionOperators.g.cs")).Value;
var multiplyOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.MultiplyOperators.g.cs")).Value;
@@ -3435,6 +3425,7 @@ public partial class TestValueObject
AssertOutput(comparableOutput, _COMPARABLE_INT);
AssertOutput(parsableOutput, _PARSABLE_INT);
AssertOutput(comparisonOperatorsOutput, _COMPARISON_OPERATORS_INT);
+ AssertOutput(equalityComparisonOperatorsOutput, _EQUALITY_COMPARISON_OPERATORS_CLASS);
AssertOutput(additionOperatorsOutput, _ADDITION_OPERATORS_INT);
AssertOutput(subtractionOperatorsOutput, _SUBTRACTION_OPERATORS_INT);
AssertOutput(multiplyOperatorsOutput, _MULTIPLY_OPERATORS_INT);
@@ -3447,7 +3438,6 @@ namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial class TestValueObject : global::System.IEquatable,
- global::System.Numerics.IEqualityOperators,
global::Thinktecture.IKeyedValueObject,
global::Thinktecture.IKeyedValueObject
{
@@ -3565,31 +3555,6 @@ private TestValueObject(int structField)
static partial void ValidateConstructorArguments(ref int structField);
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if objects are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
- {
- if (obj is null)
- return other is null;
-
- return obj.Equals(other);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if objects are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
- {
- return !(obj == other);
- }
-
///
public override bool Equals(object? other)
{
@@ -3602,9 +3567,6 @@ public bool Equals(global::Thinktecture.Tests.TestValueObject? other)
if (other is null)
return false;
- if (!global::System.Object.ReferenceEquals(GetType(), other.GetType()))
- return false;
-
if (global::System.Object.ReferenceEquals(this, other))
return true;
@@ -3638,7 +3600,7 @@ public void Should_generate_class_with_DateOnly_key_member()
namespace Thinktecture.Tests
{
- [ValueObject(ComparisonOperators = OperatorsGeneration.ForcedWithKeyTypeOverloads)]
+ [ValueObject]
public partial class TestValueObject
{
public readonly DateOnly StructField;
@@ -3646,13 +3608,14 @@ public partial class TestValueObject
}
";
var outputs = GetGeneratedOutputs(source, typeof(ValueObjectAttribute).Assembly);
- outputs.Should().HaveCount(5);
+ outputs.Should().HaveCount(6);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.g.cs")).Value;
var formattableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Formattable.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Parsable.g.cs")).Value;
var comparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.ComparisonOperators.g.cs")).Value;
+ var equalityComparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.EqualityComparisonOperators.g.cs")).Value;
/* language=c# */
AssertOutput(mainOutput, _GENERATED_HEADER + """
@@ -3661,7 +3624,6 @@ namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial class TestValueObject : global::System.IEquatable,
- global::System.Numerics.IEqualityOperators,
global::Thinktecture.IKeyedValueObject,
global::Thinktecture.IKeyedValueObject
{
@@ -3779,8 +3741,188 @@ private TestValueObject(global::System.DateOnly structField)
static partial void ValidateConstructorArguments(ref global::System.DateOnly structField);
+ ///
+ public override bool Equals(object? other)
+ {
+ return other is global::Thinktecture.Tests.TestValueObject obj && Equals(obj);
+ }
+
+ ///
+ public bool Equals(global::Thinktecture.Tests.TestValueObject? other)
+ {
+ if (other is null)
+ return false;
+
+ if (global::System.Object.ReferenceEquals(this, other))
+ return true;
+
+ return this.StructField.Equals(other.StructField);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ return global::System.HashCode.Combine(this.StructField);
+ }
+
+ ///
+ public override string ToString()
+ {
+ return this.StructField.ToString();
+ }
+ }
+}
+
+""");
+
+ /* language=c# */
+ AssertOutput(formattableOutput, _GENERATED_HEADER + """
+
+namespace Thinktecture.Tests;
+
+partial class TestValueObject :
+ global::System.IFormattable
+{
+ ///
+ public string ToString(string? format, global::System.IFormatProvider? formatProvider = null)
+ {
+ return this.StructField.ToString(format, formatProvider);
+ }
+}
+
+""");
+
+ /* language=c# */
+ AssertOutput(comparableOutput, _GENERATED_HEADER + """
+
+namespace Thinktecture.Tests;
+
+partial class TestValueObject :
+ global::System.IComparable,
+ global::System.IComparable
+{
+ ///
+ public int CompareTo(object? obj)
+ {
+ if(obj is null)
+ return 1;
+
+ if(obj is not global::Thinktecture.Tests.TestValueObject item)
+ throw new global::System.ArgumentException("Argument must be of type \"TestValueObject\".", nameof(obj));
+
+ return this.CompareTo(item);
+ }
+
+ ///
+ public int CompareTo(global::Thinktecture.Tests.TestValueObject? obj)
+ {
+ if(obj is null)
+ return 1;
+
+ return this.StructField.CompareTo(obj.StructField);
+ }
+}
+
+""");
+
+ /* language=c# */
+ AssertOutput(parsableOutput, _GENERATED_HEADER + """
+
+namespace Thinktecture.Tests;
+
+partial class TestValueObject :
+ global::System.IParsable
+{
+ ///
+ public static global::Thinktecture.Tests.TestValueObject Parse(string s, global::System.IFormatProvider? provider)
+ {
+ var key = global::System.DateOnly.Parse(s, provider);
+ var validationResult = global::Thinktecture.Tests.TestValueObject.Validate(key, out var result);
+
+ if(validationResult is null)
+ return result!;
+
+ throw new global::System.FormatException(validationResult.ErrorMessage);
+ }
+
+ ///
+ public static bool TryParse(
+ string? s,
+ global::System.IFormatProvider? provider,
+ [global::System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] out global::Thinktecture.Tests.TestValueObject result)
+ {
+ if(s is null)
+ {
+ result = default;
+ return false;
+ }
+
+ if(!global::System.DateOnly.TryParse(s, provider, out var key))
+ {
+ result = default;
+ return false;
+ }
+
+ var validationResult = global::Thinktecture.Tests.TestValueObject.Validate(key, out result!);
+ return validationResult is null;
+ }
+}
+
+""");
+
+ /* language=c# */
+ AssertOutput(comparisonOperatorsOutput, _GENERATED_HEADER + """
+
+namespace Thinktecture.Tests;
+
+partial class TestValueObject :
+ global::System.Numerics.IComparisonOperators
+{
+ ///
+ public static bool operator <(global::Thinktecture.Tests.TestValueObject left, global::Thinktecture.Tests.TestValueObject right)
+ {
+ global::System.ArgumentNullException.ThrowIfNull(nameof(left));
+ global::System.ArgumentNullException.ThrowIfNull(nameof(right));
+ return left.StructField < right.StructField;
+ }
+
+ ///
+ public static bool operator <=(global::Thinktecture.Tests.TestValueObject left, global::Thinktecture.Tests.TestValueObject right)
+ {
+ global::System.ArgumentNullException.ThrowIfNull(nameof(left));
+ global::System.ArgumentNullException.ThrowIfNull(nameof(right));
+ return left.StructField <= right.StructField;
+ }
+
+ ///
+ public static bool operator >(global::Thinktecture.Tests.TestValueObject left, global::Thinktecture.Tests.TestValueObject right)
+ {
+ global::System.ArgumentNullException.ThrowIfNull(nameof(left));
+ global::System.ArgumentNullException.ThrowIfNull(nameof(right));
+ return left.StructField > right.StructField;
+ }
+
+ ///
+ public static bool operator >=(global::Thinktecture.Tests.TestValueObject left, global::Thinktecture.Tests.TestValueObject right)
+ {
+ global::System.ArgumentNullException.ThrowIfNull(nameof(left));
+ global::System.ArgumentNullException.ThrowIfNull(nameof(right));
+ return left.StructField >= right.StructField;
+ }
+}
+
+""");
+
+ /* language=c# */
+ AssertOutput(equalityComparisonOperatorsOutput, _GENERATED_HEADER + """
+
+namespace Thinktecture.Tests;
+
+partial class TestValueObject :
+ global::System.Numerics.IEqualityOperators
+{
///
- /// Compares to instances of .
+ /// Compares two instances of .
///
/// Instance to compare.
/// Another instance to compare.
@@ -3794,7 +3936,7 @@ private TestValueObject(global::System.DateOnly structField)
}
///
- /// Compares to instances of .
+ /// Compares two instances of .
///
/// Instance to compare.
/// Another instance to compare.
@@ -3803,6 +3945,161 @@ private TestValueObject(global::System.DateOnly structField)
{
return !(obj == other);
}
+}
+
+""");
+ }
+
+ [Fact]
+ public void Should_generate_class_with_DateOnly_key_member_with_DefaultWithKeyTypeOverloads()
+ {
+ /* language=c# */
+ var source = @"
+using System;
+using Thinktecture;
+
+namespace Thinktecture.Tests
+{
+ [ValueObject(EqualityComparisonOperators = OperatorsGeneration.DefaultWithKeyTypeOverloads)]
+ public partial class TestValueObject
+ {
+ public readonly DateOnly StructField;
+ }
+}
+";
+ var outputs = GetGeneratedOutputs(source, typeof(ValueObjectAttribute).Assembly);
+ outputs.Should().HaveCount(6);
+
+ var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.g.cs")).Value;
+ var formattableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Formattable.g.cs")).Value;
+ var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Comparable.g.cs")).Value;
+ var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Parsable.g.cs")).Value;
+ var comparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.ComparisonOperators.g.cs")).Value;
+ var equalityComparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.EqualityComparisonOperators.g.cs")).Value;
+
+ /* language=c# */
+ AssertOutput(mainOutput, _GENERATED_HEADER + """
+
+namespace Thinktecture.Tests
+{
+ [global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
+ partial class TestValueObject : global::System.IEquatable,
+ global::Thinktecture.IKeyedValueObject,
+ global::Thinktecture.IKeyedValueObject
+ {
+ [global::System.Runtime.CompilerServices.ModuleInitializer]
+ internal static void ModuleInit()
+ {
+ global::System.Func convertFromKey = new (global::Thinktecture.Tests.TestValueObject.Create);
+ global::System.Linq.Expressions.Expression> convertFromKeyExpression = static structField => global::Thinktecture.Tests.TestValueObject.Create(structField);
+ global::System.Linq.Expressions.Expression> convertFromKeyExpressionViaCtor = static structField => new global::Thinktecture.Tests.TestValueObject(structField);
+
+ var convertToKey = new global::System.Func(static item => item.StructField);
+ global::System.Linq.Expressions.Expression> convertToKeyExpression = static obj => obj.StructField;
+
+ var type = typeof(global::Thinktecture.Tests.TestValueObject);
+ var metadata = new global::Thinktecture.Internal.KeyedValueObjectMetadata(type, typeof(global::System.DateOnly), false, false, convertFromKey, convertFromKeyExpression, convertFromKeyExpressionViaCtor, convertToKey, convertToKeyExpression);
+
+ global::Thinktecture.Internal.KeyedValueObjectMetadataLookup.AddMetadata(type, metadata);
+ }
+
+ private static readonly global::System.Type _type = typeof(global::Thinktecture.Tests.TestValueObject);
+
+ public static global::System.ComponentModel.DataAnnotations.ValidationResult? Validate(
+ global::System.DateOnly structField,
+ out global::Thinktecture.Tests.TestValueObject? obj)
+ {
+ var validationResult = global::System.ComponentModel.DataAnnotations.ValidationResult.Success;
+ ValidateFactoryArguments(ref validationResult, ref structField);
+
+ if (validationResult == global::System.ComponentModel.DataAnnotations.ValidationResult.Success)
+ {
+ obj = new global::Thinktecture.Tests.TestValueObject(structField);
+ obj.FactoryPostInit();
+ }
+ else
+ {
+ obj = default;
+ }
+
+ return validationResult;
+ }
+
+ public static global::Thinktecture.Tests.TestValueObject Create(global::System.DateOnly structField)
+ {
+ var validationResult = Validate(structField, out global::Thinktecture.Tests.TestValueObject? obj);
+
+ if (validationResult != global::System.ComponentModel.DataAnnotations.ValidationResult.Success)
+ throw new global::System.ComponentModel.DataAnnotations.ValidationException(validationResult!.ErrorMessage ?? "Validation failed.");
+
+ return obj!;
+ }
+
+ public static bool TryCreate(
+ global::System.DateOnly structField,
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out global::Thinktecture.Tests.TestValueObject? obj)
+ {
+ var validationResult = Validate(structField, out obj);
+
+ return validationResult == global::System.ComponentModel.DataAnnotations.ValidationResult.Success;
+ }
+
+ static partial void ValidateFactoryArguments(ref global::System.ComponentModel.DataAnnotations.ValidationResult? validationResult, ref global::System.DateOnly structField);
+
+ partial void FactoryPostInit();
+
+ ///
+ /// Gets the identifier of the item.
+ ///
+ [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ global::System.DateOnly global::Thinktecture.IKeyedValueObject.GetKey()
+ {
+ return this.StructField;
+ }
+
+ ///
+ /// Implicit conversion to the type .
+ ///
+ /// Object to covert.
+ /// The of provided or default if is null.
+ [return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull("obj")]
+ public static implicit operator global::System.DateOnly?(global::Thinktecture.Tests.TestValueObject? obj)
+ {
+ return obj?.StructField;
+ }
+
+ ///
+ /// Explicit conversion to the type .
+ ///
+ /// Object to covert.
+ /// The of provided or default if is null.
+ [return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull("obj")]
+ public static explicit operator global::System.DateOnly(global::Thinktecture.Tests.TestValueObject obj)
+ {
+ if(obj is null)
+ throw new global::System.NullReferenceException();
+
+ return obj.StructField;
+ }
+
+ ///
+ /// Explicit conversion from the type .
+ ///
+ /// Value to covert.
+ /// An instance of .
+ public static explicit operator global::Thinktecture.Tests.TestValueObject(global::System.DateOnly structField)
+ {
+ return global::Thinktecture.Tests.TestValueObject.Create(structField);
+ }
+
+ private TestValueObject(global::System.DateOnly structField)
+ {
+ ValidateConstructorArguments(ref structField);
+
+ this.StructField = structField;
+ }
+
+ static partial void ValidateConstructorArguments(ref global::System.DateOnly structField);
///
public override bool Equals(object? other)
@@ -3816,9 +4113,6 @@ public bool Equals(global::Thinktecture.Tests.TestValueObject? other)
if (other is null)
return false;
- if (!global::System.Object.ReferenceEquals(GetType(), other.GetType()))
- return false;
-
if (global::System.Object.ReferenceEquals(this, other))
return true;
@@ -3968,13 +4262,102 @@ partial class TestValueObject :
return left.StructField > right.StructField;
}
- ///
- public static bool operator >=(global::Thinktecture.Tests.TestValueObject left, global::Thinktecture.Tests.TestValueObject right)
- {
- global::System.ArgumentNullException.ThrowIfNull(nameof(left));
- global::System.ArgumentNullException.ThrowIfNull(nameof(right));
- return left.StructField >= right.StructField;
- }
+ ///
+ public static bool operator >=(global::Thinktecture.Tests.TestValueObject left, global::Thinktecture.Tests.TestValueObject right)
+ {
+ global::System.ArgumentNullException.ThrowIfNull(nameof(left));
+ global::System.ArgumentNullException.ThrowIfNull(nameof(right));
+ return left.StructField >= right.StructField;
+ }
+}
+
+""");
+
+ /* language=c# */
+ AssertOutput(equalityComparisonOperatorsOutput, _GENERATED_HEADER + """
+
+namespace Thinktecture.Tests;
+
+partial class TestValueObject :
+ global::System.Numerics.IEqualityOperators,
+ global::System.Numerics.IEqualityOperators
+{
+ ///
+ /// Compares two instances of .
+ ///
+ /// Instance to compare.
+ /// Another instance to compare.
+ /// true if objects are equal; otherwise false.
+ public static bool operator ==(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
+ {
+ if (obj is null)
+ return other is null;
+
+ return obj.Equals(other);
+ }
+
+ ///
+ /// Compares two instances of .
+ ///
+ /// Instance to compare.
+ /// Another instance to compare.
+ /// false if objects are equal; otherwise true.
+ public static bool operator !=(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
+ {
+ return !(obj == other);
+ }
+
+ private static bool Equals(global::Thinktecture.Tests.TestValueObject? obj, global::System.DateOnly value)
+ {
+ if (obj is null)
+ return false;
+
+ return obj.StructField.Equals(value);
+ }
+
+ ///
+ /// Compares an instance of with .
+ ///
+ /// Instance to compare.
+ /// Value to compare with.
+ /// true if objects are equal; otherwise false.
+ public static bool operator ==(global::Thinktecture.Tests.TestValueObject? obj, global::System.DateOnly value)
+ {
+ return Equals(obj, value);
+ }
+
+ ///
+ /// Compares an instance of with .
+ ///
+ /// Value to compare.
+ /// Instance to compare with.
+ /// true if objects are equal; otherwise false.
+ public static bool operator ==(global::System.DateOnly value, global::Thinktecture.Tests.TestValueObject? obj)
+ {
+ return Equals(obj, value);
+ }
+
+ ///
+ /// Compares an instance of with .
+ ///
+ /// Instance to compare.
+ /// Value to compare with.
+ /// false if objects are equal; otherwise true.
+ public static bool operator !=(global::Thinktecture.Tests.TestValueObject? obj, global::System.DateOnly value)
+ {
+ return !(obj == value);
+ }
+
+ ///
+ /// Compares an instance of with .
+ ///
+ /// Value to compare.
+ /// Instance to compare with.
+ /// false if objects are equal; otherwise true.
+ public static bool operator !=(global::System.DateOnly value, global::Thinktecture.Tests.TestValueObject? obj)
+ {
+ return !(obj == value);
+ }
}
""");
@@ -4002,13 +4385,14 @@ public partial class TestValueObject
}
";
var outputs = GetGeneratedOutputs(source, typeof(ValueObjectAttribute).Assembly);
- outputs.Should().HaveCount(9);
+ outputs.Should().HaveCount(10);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.g.cs")).Value;
var formattableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Formattable.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Parsable.g.cs")).Value;
var comparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.ComparisonOperators.g.cs")).Value;
+ var equalityComparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.EqualityComparisonOperators.g.cs")).Value;
var additionOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.AdditionOperators.g.cs")).Value;
var subtractionOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.SubtractionOperators.g.cs")).Value;
var multiplyOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.MultiplyOperators.g.cs")).Value;
@@ -4017,6 +4401,7 @@ public partial class TestValueObject
AssertOutput(formattableOutput, _FORMATTABLE_INT);
AssertOutput(comparableOutput, _COMPARABLE_INT);
AssertOutput(parsableOutput, _PARSABLE_INT);
+ AssertOutput(equalityComparisonOperatorsOutput, _EQUALITY_COMPARISON_OPERATORS_INT_WITH_KEY_OVERLOADS);
/* language=c# */
AssertOutput(mainOutput, _GENERATED_HEADER + """
@@ -4025,7 +4410,6 @@ namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial class TestValueObject : global::System.IEquatable,
- global::System.Numerics.IEqualityOperators,
global::Thinktecture.IKeyedValueObject,
global::Thinktecture.IKeyedValueObject
{
@@ -4143,31 +4527,6 @@ private TestValueObject(int structField)
static partial void ValidateConstructorArguments(ref int structField);
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if objects are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
- {
- if (obj is null)
- return other is null;
-
- return obj.Equals(other);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if objects are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
- {
- return !(obj == other);
- }
-
///
public override bool Equals(object? other)
{
@@ -4180,9 +4539,6 @@ public bool Equals(global::Thinktecture.Tests.TestValueObject? other)
if (other is null)
return false;
- if (!global::System.Object.ReferenceEquals(GetType(), other.GetType()))
- return false;
-
if (global::System.Object.ReferenceEquals(this, other))
return true;
@@ -4211,7 +4567,8 @@ public override string ToString()
namespace Thinktecture.Tests;
partial class TestValueObject :
- global::System.Numerics.IComparisonOperators
+ global::System.Numerics.IComparisonOperators,
+ global::System.Numerics.IComparisonOperators
{
///
public static bool operator <(global::Thinktecture.Tests.TestValueObject left, global::Thinktecture.Tests.TestValueObject right)
@@ -4547,16 +4904,18 @@ public partial class TestValueObject
}
";
var outputs = GetGeneratedOutputs(source, typeof(ValueObjectAttribute).Assembly);
- outputs.Should().HaveCount(4);
+ outputs.Should().HaveCount(5);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Parsable.g.cs")).Value;
var comparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.ComparisonOperators.g.cs")).Value;
+ var equalityComparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.EqualityComparisonOperators.g.cs")).Value;
AssertOutput(comparableOutput, _COMPARABLE_CLASS_STRING);
AssertOutput(parsableOutput, _PARSABLE_CLASS_STRING);
AssertOutput(comparisonOperatorsOutput, _COMPARISON_OPERATORS_CLASS_STRING);
+ AssertOutput(equalityComparisonOperatorsOutput, _EQUALITY_COMPARISON_OPERATORS_CLASS);
/* language=c# */
AssertOutput(mainOutput, _GENERATED_HEADER + """
@@ -4565,7 +4924,6 @@ namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial class TestValueObject : global::System.IEquatable,
- global::System.Numerics.IEqualityOperators,
global::Thinktecture.IKeyedValueObject,
global::Thinktecture.IKeyedValueObject
{
@@ -4680,31 +5038,6 @@ private TestValueObject(string referenceField)
static partial void ValidateConstructorArguments(ref string referenceField);
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if objects are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
- {
- if (obj is null)
- return other is null;
-
- return obj.Equals(other);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if objects are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
- {
- return !(obj == other);
- }
-
///
public override bool Equals(object? other)
{
@@ -4717,9 +5050,6 @@ public bool Equals(global::Thinktecture.Tests.TestValueObject? other)
if (other is null)
return false;
- if (!global::System.Object.ReferenceEquals(GetType(), other.GetType()))
- return false;
-
if (global::System.Object.ReferenceEquals(this, other))
return true;
@@ -4763,16 +5093,18 @@ public partial class TestValueObject
}
";
var outputs = GetGeneratedOutputs(source, typeof(ValueObjectAttribute).Assembly);
- outputs.Should().HaveCount(4);
+ outputs.Should().HaveCount(5);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Parsable.g.cs")).Value;
var comparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.ComparisonOperators.g.cs")).Value;
+ var equalityComparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.EqualityComparisonOperators.g.cs")).Value;
AssertOutput(comparableOutput, _COMPARABLE_CLASS_STRING);
AssertOutput(parsableOutput, _PARSABLE_CLASS_STRING);
AssertOutput(comparisonOperatorsOutput, _COMPARISON_OPERATORS_CLASS_STRING);
+ AssertOutput(equalityComparisonOperatorsOutput, _EQUALITY_COMPARISON_OPERATORS_CLASS);
/* language=c# */
AssertOutput(mainOutput, _GENERATED_HEADER + """
@@ -4781,7 +5113,6 @@ namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial class TestValueObject : global::System.IEquatable,
- global::System.Numerics.IEqualityOperators,
global::Thinktecture.IKeyedValueObject,
global::Thinktecture.IKeyedValueObject
{
@@ -4894,31 +5225,6 @@ private TestValueObject(string referenceField)
static partial void ValidateConstructorArguments(ref string referenceField);
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if objects are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
- {
- if (obj is null)
- return other is null;
-
- return obj.Equals(other);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if objects are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
- {
- return !(obj == other);
- }
-
///
public override bool Equals(object? other)
{
@@ -4931,9 +5237,6 @@ public bool Equals(global::Thinktecture.Tests.TestValueObject? other)
if (other is null)
return false;
- if (!global::System.Object.ReferenceEquals(GetType(), other.GetType()))
- return false;
-
if (global::System.Object.ReferenceEquals(this, other))
return true;
@@ -4977,13 +5280,14 @@ public partial class TestValueObject
}
";
var outputs = GetGeneratedOutputs(source, typeof(ValueObjectAttribute).Assembly);
- outputs.Should().HaveCount(9);
+ outputs.Should().HaveCount(10);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.g.cs")).Value;
var formattableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Formattable.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Parsable.g.cs")).Value;
var comparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.ComparisonOperators.g.cs")).Value;
+ var equalityComparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.EqualityComparisonOperators.g.cs")).Value;
var additionOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.AdditionOperators.g.cs")).Value;
var subtractionOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.SubtractionOperators.g.cs")).Value;
var multiplyOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.MultiplyOperators.g.cs")).Value;
@@ -4993,6 +5297,7 @@ public partial class TestValueObject
AssertOutput(comparableOutput, _COMPARABLE_INT);
AssertOutput(parsableOutput, _PARSABLE_INT);
AssertOutput(comparisonOperatorsOutput, _COMPARISON_OPERATORS_INT);
+ AssertOutput(equalityComparisonOperatorsOutput, _EQUALITY_COMPARISON_OPERATORS_CLASS);
AssertOutput(additionOperatorsOutput, _ADDITION_OPERATORS_INT);
AssertOutput(subtractionOperatorsOutput, _SUBTRACTION_OPERATORS_INT);
AssertOutput(multiplyOperatorsOutput, _MULTIPLY_OPERATORS_INT);
@@ -5005,7 +5310,6 @@ namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial class TestValueObject : global::System.IEquatable,
- global::System.Numerics.IEqualityOperators,
global::Thinktecture.IKeyedValueObject,
global::Thinktecture.IKeyedValueObject
{
@@ -5123,31 +5427,6 @@ private TestValueObject(int structField)
static partial void ValidateConstructorArguments(ref int structField);
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if objects are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
- {
- if (obj is null)
- return other is null;
-
- return obj.Equals(other);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if objects are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
- {
- return !(obj == other);
- }
-
///
public override bool Equals(object? other)
{
@@ -5160,9 +5439,6 @@ public bool Equals(global::Thinktecture.Tests.TestValueObject? other)
if (other is null)
return false;
- if (!global::System.Object.ReferenceEquals(GetType(), other.GetType()))
- return false;
-
if (global::System.Object.ReferenceEquals(this, other))
return true;
@@ -5204,13 +5480,14 @@ public partial class TestValueObject
}
";
var outputs = GetGeneratedOutputs(source, typeof(ValueObjectAttribute).Assembly);
- outputs.Should().HaveCount(9);
+ outputs.Should().HaveCount(10);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.g.cs")).Value;
var formattableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Formattable.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Parsable.g.cs")).Value;
var comparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.ComparisonOperators.g.cs")).Value;
+ var equalityComparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.EqualityComparisonOperators.g.cs")).Value;
var additionOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.AdditionOperators.g.cs")).Value;
var subtractionOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.SubtractionOperators.g.cs")).Value;
var multiplyOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.MultiplyOperators.g.cs")).Value;
@@ -5220,6 +5497,7 @@ public partial class TestValueObject
AssertOutput(comparableOutput, _COMPARABLE_INT);
AssertOutput(parsableOutput, _PARSABLE_INT);
AssertOutput(comparisonOperatorsOutput, _COMPARISON_OPERATORS_INT);
+ AssertOutput(equalityComparisonOperatorsOutput, _EQUALITY_COMPARISON_OPERATORS_CLASS);
AssertOutput(additionOperatorsOutput, _ADDITION_OPERATORS_INT);
AssertOutput(subtractionOperatorsOutput, _SUBTRACTION_OPERATORS_INT);
AssertOutput(multiplyOperatorsOutput, _MULTIPLY_OPERATORS_INT);
@@ -5232,7 +5510,6 @@ namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial class TestValueObject : global::System.IEquatable,
- global::System.Numerics.IEqualityOperators,
global::Thinktecture.IKeyedValueObject,
global::Thinktecture.IKeyedValueObject
{
@@ -5350,31 +5627,6 @@ private TestValueObject(int structField)
static partial void ValidateConstructorArguments(ref int structField);
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if objects are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
- {
- if (obj is null)
- return other is null;
-
- return obj.Equals(other);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if objects are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
- {
- return !(obj == other);
- }
-
///
public override bool Equals(object? other)
{
@@ -5387,9 +5639,6 @@ public bool Equals(global::Thinktecture.Tests.TestValueObject? other)
if (other is null)
return false;
- if (!global::System.Object.ReferenceEquals(GetType(), other.GetType()))
- return false;
-
if (global::System.Object.ReferenceEquals(this, other))
return true;
@@ -5434,16 +5683,18 @@ public partial class TestValueObject
}
";
var outputs = GetGeneratedOutputs(source, typeof(ValueObjectAttribute).Assembly);
- outputs.Should().HaveCount(4);
+ outputs.Should().HaveCount(5);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Parsable.g.cs")).Value;
var comparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.ComparisonOperators.g.cs")).Value;
+ var equalityComparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.EqualityComparisonOperators.g.cs")).Value;
AssertOutput(comparableOutput, _COMPARABLE_CLASS_STRING);
AssertOutput(parsableOutput, _PARSABLE_CLASS_STRING);
AssertOutput(comparisonOperatorsOutput, _COMPARISON_OPERATORS_CLASS_STRING);
+ AssertOutput(equalityComparisonOperatorsOutput, _EQUALITY_COMPARISON_OPERATORS_CLASS);
/* language=c# */
AssertOutput(mainOutput, _GENERATED_HEADER + """
@@ -5452,7 +5703,6 @@ namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial class TestValueObject : global::System.IEquatable,
- global::System.Numerics.IEqualityOperators,
global::Thinktecture.IKeyedValueObject,
global::Thinktecture.IKeyedValueObject
{
@@ -5566,31 +5816,6 @@ private TestValueObject(string referenceField)
static partial void ValidateConstructorArguments(ref string referenceField);
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if objects are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
- {
- if (obj is null)
- return other is null;
-
- return obj.Equals(other);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if objects are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
- {
- return !(obj == other);
- }
-
///
public override bool Equals(object? other)
{
@@ -5603,9 +5828,6 @@ public bool Equals(global::Thinktecture.Tests.TestValueObject? other)
if (other is null)
return false;
- if (!global::System.Object.ReferenceEquals(GetType(), other.GetType()))
- return false;
-
if (global::System.Object.ReferenceEquals(this, other))
return true;
@@ -5651,16 +5873,18 @@ public partial class TestValueObject
}
";
var outputs = GetGeneratedOutputs(source, typeof(ValueObjectAttribute).Assembly);
- outputs.Should().HaveCount(4);
+ outputs.Should().HaveCount(5);
var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.g.cs")).Value;
var comparableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Comparable.g.cs")).Value;
var parsableOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.Parsable.g.cs")).Value;
var comparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.ComparisonOperators.g.cs")).Value;
+ var equalityComparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.EqualityComparisonOperators.g.cs")).Value;
AssertOutput(comparableOutput, _COMPARABLE_CLASS_STRING_WITH_ORDINAL_COMPARER);
AssertOutput(parsableOutput, _PARSABLE_CLASS_STRING);
AssertOutput(comparisonOperatorsOutput, _COMPARISON_OPERATORS_STRING_WITH_ORDINAL_COMPARER);
+ AssertOutput(equalityComparisonOperatorsOutput, _EQUALITY_COMPARISON_OPERATORS_CLASS);
/* language=c# */
AssertOutput(mainOutput, _GENERATED_HEADER + """
@@ -5669,7 +5893,6 @@ namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial class TestValueObject : global::System.IEquatable,
- global::System.Numerics.IEqualityOperators,
global::Thinktecture.IKeyedValueObject,
global::Thinktecture.IKeyedValueObject
{
@@ -5783,31 +6006,6 @@ private TestValueObject(string referenceField)
static partial void ValidateConstructorArguments(ref string referenceField);
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if objects are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
- {
- if (obj is null)
- return other is null;
-
- return obj.Equals(other);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if objects are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
- {
- return !(obj == other);
- }
-
///
public override bool Equals(object? other)
{
@@ -5820,9 +6018,6 @@ public bool Equals(global::Thinktecture.Tests.TestValueObject? other)
if (other is null)
return false;
- if (!global::System.Object.ReferenceEquals(GetType(), other.GetType()))
- return false;
-
if (global::System.Object.ReferenceEquals(this, other))
return true;
@@ -5870,16 +6065,21 @@ public class Foo
}
}
";
- var output = GetGeneratedOutput(source, typeof(ValueObjectAttribute).Assembly);
+ var outputs = GetGeneratedOutputs(source, typeof(ValueObjectAttribute).Assembly);
+ outputs.Should().HaveCount(2);
+
+ var mainOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.g.cs")).Value;
+ var equalityComparisonOperatorsOutput = outputs.Single(kvp => kvp.Key.Contains("Thinktecture.Tests.TestValueObject.EqualityComparisonOperators.g.cs")).Value;
+
+ AssertOutput(equalityComparisonOperatorsOutput, _EQUALITY_COMPARISON_OPERATORS_CLASS);
/* language=c# */
- AssertOutput(output, _GENERATED_HEADER + """
+ AssertOutput(mainOutput, _GENERATED_HEADER + """
namespace Thinktecture.Tests
{
[global::System.ComponentModel.TypeConverter(typeof(global::Thinktecture.ValueObjectTypeConverter))]
partial class TestValueObject : global::System.IEquatable,
- global::System.Numerics.IEqualityOperators,
global::Thinktecture.IKeyedValueObject,
global::Thinktecture.IKeyedValueObject
{
@@ -5993,31 +6193,6 @@ private TestValueObject(global::Thinktecture.Tests.Foo referenceField)
static partial void ValidateConstructorArguments(ref global::Thinktecture.Tests.Foo referenceField);
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// true if objects are equal; otherwise false.
- public static bool operator ==(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
- {
- if (obj is null)
- return other is null;
-
- return obj.Equals(other);
- }
-
- ///
- /// Compares to instances of .
- ///
- /// Instance to compare.
- /// Another instance to compare.
- /// false if objects are equal; otherwise true.
- public static bool operator !=(global::Thinktecture.Tests.TestValueObject? obj, global::Thinktecture.Tests.TestValueObject? other)
- {
- return !(obj == other);
- }
-
///
public override bool Equals(object? other)
{
@@ -6030,9 +6205,6 @@ public bool Equals(global::Thinktecture.Tests.TestValueObject? other)
if (other is null)
return false;
- if (!global::System.Object.ReferenceEquals(GetType(), other.GetType()))
- return false;
-
if (global::System.Object.ReferenceEquals(this, other))
return true;
@@ -6244,9 +6416,6 @@ public bool Equals(global::Thinktecture.Tests.TestValueObject? other)
if (other is null)
return false;
- if (!global::System.Object.ReferenceEquals(GetType(), other.GetType()))
- return false;
-
if (global::System.Object.ReferenceEquals(this, other))
return true;
@@ -6454,9 +6623,6 @@ public bool Equals(global::Thinktecture.Tests.TestValueObject? other)
if (other is null)
return false;
- if (!global::System.Object.ReferenceEquals(GetType(), other.GetType()))
- return false;
-
if (global::System.Object.ReferenceEquals(this, other))
return true;