Skip to content

Commit

Permalink
Fixes diegofrata#60: String array + Comparer
Browse files Browse the repository at this point in the history
  • Loading branch information
JKamsker committed Oct 10, 2024
1 parent ceb45e2 commit 62a62cf
Show file tree
Hide file tree
Showing 9 changed files with 206 additions and 53 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using Microsoft.CodeAnalysis.CSharp;
using SourceGeneratorTestHelpers;

namespace Generator.Equals.DynamicGenerationTests.Issues;

public class Issue_60_StringEquality_Enumerables
{
[Fact]
public void Test3_Struct_UnorderedEquality()
{
// StringComparer.OrdinalIgnoreCase;

var input = SourceText.CSharp(
"""
using System;
using System.Collections.Generic;
using Generator.Equals;
[Equatable]
public partial class Resource
{
[UnorderedEquality]
[StringEqualityAttribute(StringComparison.OrdinalIgnoreCase)]
public string[] Tags { get; set; } = Array.Empty<string>();
}
"""
);

var result = IncrementalGenerator.Run<EqualsGenerator>
(
input,
new CSharpParseOptions(),
UnitTest1.References
);

var gensource = result.Results
.SelectMany(x => x.GeneratedSources)
.Select(x => x.SourceText)
.ToList()
;

Assert.NotNull(gensource);

Assert.Contains("new global::Generator.Equals.UnorderedEqualityComparer<string>(StringComparer.OrdinalIgnoreCase)",
gensource.FirstOrDefault()?.ToString());
}
}
10 changes: 5 additions & 5 deletions Generator.Equals.DynamicGenerationTests/UnitTest1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Generator.Equals.DynamicGenerationTests;

public class UnitTest1
{
public static readonly List<PortableExecutableReference> References2 =
public static readonly List<PortableExecutableReference> References =
AppDomain.CurrentDomain.GetAssemblies()
.Where(_ => !_.IsDynamic && !string.IsNullOrWhiteSpace(_.Location))
.Select(_ => MetadataReference.CreateFromFile(_.Location))
Expand Down Expand Up @@ -45,7 +45,7 @@ public partial record MyRecord(
new CSharpParseOptions()
{
},
References2
References
);

var gensource = result.Results
Expand Down Expand Up @@ -114,7 +114,7 @@ class LengthEqualityComparer : IEqualityComparer<string>
new CSharpParseOptions()
{
},
References2
References
);

var gensource = result.Results
Expand Down Expand Up @@ -153,7 +153,7 @@ public partial struct Sample
new CSharpParseOptions()
{
},
References2
References
);

var gensource = result.Results
Expand Down Expand Up @@ -202,7 +202,7 @@ public Sample(string name, int age, bool flag)
new CSharpParseOptions()
{
},
References2
References
);

var gensource = result.Results
Expand Down
18 changes: 9 additions & 9 deletions Generator.Equals.Runtime/Attributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace Generator.Equals
{
[GeneratedCode("Generator.Equals", "1.0.0.0")]
[Conditional("GENERATOR_EQUALS")]
//[Conditional("GENERATOR_EQUALS")]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class EquatableAttribute : Attribute
{
Expand All @@ -21,49 +21,49 @@ public class EquatableAttribute : Attribute
}

[GeneratedCode("Generator.Equals", "1.0.0.0")]
[Conditional("GENERATOR_EQUALS")]
//[Conditional("GENERATOR_EQUALS")]
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class DefaultEqualityAttribute : Attribute
{
}

[GeneratedCode("Generator.Equals", "1.0.0.0")]
[Conditional("GENERATOR_EQUALS")]
//[Conditional("GENERATOR_EQUALS")]
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class OrderedEqualityAttribute : Attribute
{
}

[GeneratedCode("Generator.Equals", "1.0.0.0")]
[Conditional("GENERATOR_EQUALS")]
//[Conditional("GENERATOR_EQUALS")]
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class IgnoreEqualityAttribute : Attribute
{
}

[GeneratedCode("Generator.Equals", "1.0.0.0")]
[Conditional("GENERATOR_EQUALS")]
//[Conditional("GENERATOR_EQUALS")]
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class UnorderedEqualityAttribute : Attribute
{
}

[GeneratedCode("Generator.Equals", "1.0.0.0")]
[Conditional("GENERATOR_EQUALS")]
//[Conditional("GENERATOR_EQUALS")]
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class ReferenceEqualityAttribute : Attribute
{
}

[GeneratedCode("Generator.Equals", "1.0.0.0")]
[Conditional("GENERATOR_EQUALS")]
//[Conditional("GENERATOR_EQUALS")]
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class SetEqualityAttribute : Attribute
{
}

[GeneratedCode("Generator.Equals", "1.0.0.0")]
[Conditional("GENERATOR_EQUALS")]
//[Conditional("GENERATOR_EQUALS")]
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class StringEqualityAttribute : Attribute
{
Expand All @@ -76,7 +76,7 @@ public StringEqualityAttribute(StringComparison comparisonType)
}

[GeneratedCode("Generator.Equals", "1.0.0.0")]
[Conditional("GENERATOR_EQUALS")]
//[Conditional("GENERATOR_EQUALS")]
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class CustomEqualityAttribute : Attribute
{
Expand Down
49 changes: 49 additions & 0 deletions Generator.Equals.Tests/Classes/StringArrayEquality.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System;

namespace Generator.Equals.Tests.Classes;

public partial class StringArrayEquality
{
[Equatable]
public partial class Sample
{
[UnorderedEquality, StringEquality(StringComparison.OrdinalIgnoreCase)]
public string[] Tags { get; set; }
}
}

public partial class StringArrayEquality
{
public class EqualsTests : EqualityTestCase
{
public override object Factory1()
{
return new Sample
{
Tags = new[] { "a", "b", "c" }
};
}

public override bool EqualsOperator(object value1, object value2) => (Sample)value1 == (Sample)value2;
public override bool NotEqualsOperator(object value1, object value2) => (Sample)value1 != (Sample)value2;
}

// Order doesnt matter
public class OrderDoesntMatterEqualsTest : EqualityTestCase
{
public override bool Expected => true;

public override object Factory1() => new Sample
{
Tags = new[] { "a", "b", "c" }
};

public override object Factory2() => new Sample
{
Tags = new[] { "c", "b", "a" }
};

public override bool EqualsOperator(object value1, object value2) => (Sample)value1 == (Sample)value2;
public override bool NotEqualsOperator(object value1, object value2) => (Sample)value1 != (Sample)value2;
}
}
1 change: 1 addition & 0 deletions Generator.Equals.Tests/Classes/UnorderedEquality.Sample.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;

namespace Generator.Equals.Tests.Classes
Expand Down
16 changes: 8 additions & 8 deletions Generator.Equals.Tests/Classes/UnorderedEquality.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,30 @@ public override object Factory1()
Properties = Enumerable
.Range(1, 1000)
.OrderBy(_ => randomSort.NextDouble())
.ToList()
.ToList(),
};
}

public override bool EqualsOperator(object value1, object value2) => (Sample) value1 == (Sample) value2;
public override bool NotEqualsOperator(object value1, object value2) => (Sample) value1 != (Sample) value2;
public override bool EqualsOperator(object value1, object value2) => (Sample)value1 == (Sample)value2;
public override bool NotEqualsOperator(object value1, object value2) => (Sample)value1 != (Sample)value2;
}

public class NotEqualsTest : EqualityTestCase
{
public override bool Expected => false;

public override object Factory1() => new Sample
{
Properties = Enumerable.Range(1, 1000).ToList()
Properties = Enumerable.Range(1, 1000).ToList(),
};

public override object Factory2() => new Sample
{
Properties = Enumerable.Range(1, 1001).ToList()
Properties = Enumerable.Range(1, 1001).ToList(),
};

public override bool EqualsOperator(object value1, object value2) => (Sample) value1 == (Sample) value2;
public override bool NotEqualsOperator(object value1, object value2) => (Sample) value1 != (Sample) value2;
public override bool EqualsOperator(object value1, object value2) => (Sample)value1 == (Sample)value2;
public override bool NotEqualsOperator(object value1, object value2) => (Sample)value1 != (Sample)value2;
}
}
}
40 changes: 36 additions & 4 deletions Generator.Equals/EqualityGeneratorBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,32 @@ private static void BuildEquality(EqualityMemberModel memberModel, IndentedTextW
case EqualityType.IgnoreEquality:
break;

case EqualityType.UnorderedEquality when !memberModel.IsDictionary:
case EqualityType.UnorderedEquality
when memberModel is { IsDictionary: false, StringComparer: not null and not "" }:

writer.WriteLine(
$"&& new global::Generator.Equals.UnorderedEqualityComparer<{memberModel.TypeName}>(global::System.StringComparer.{memberModel.StringComparer}).Equals(this.{memberModel.PropertyName}!, other.{memberModel.PropertyName}!)");
break;

case EqualityType.UnorderedEquality
when memberModel is { IsDictionary: false, StringComparer: null }:
writer.WriteLine(
$"&& global::Generator.Equals.UnorderedEqualityComparer<{memberModel.TypeName}>.Default.Equals(this.{memberModel.PropertyName}!, other.{memberModel.PropertyName}!)");
break;

case EqualityType.UnorderedEquality when memberModel.IsDictionary:
case EqualityType.UnorderedEquality
when memberModel is { IsDictionary: true, StringComparer: null }:
writer.WriteLine(
$"&& global::Generator.Equals.DictionaryEqualityComparer<{memberModel.TypeName}>.Default.Equals(this.{memberModel.PropertyName}!, other.{memberModel.PropertyName}!)");
break;

case EqualityType.OrderedEquality
when memberModel is { StringComparer: not null and not "" }:

writer.WriteLine(
$"&& new global::Generator.Equals.OrderedEqualityComparer<{memberModel.TypeName}>(global::System.StringComparer.{memberModel.StringComparer}).Equals(this.{memberModel.PropertyName}!, other.{memberModel.PropertyName}!)");
break;

case EqualityType.OrderedEquality:
writer.WriteLine(
$"&& global::Generator.Equals.OrderedEqualityComparer<{memberModel.TypeName}>.Default.Equals(this.{memberModel.PropertyName}!, other.{memberModel.PropertyName}!)");
Expand Down Expand Up @@ -137,13 +153,29 @@ private static void BuildHashCode(EqualityMemberModel memberModel, IndentedTextW
case EqualityType.IgnoreEquality:
break;

case EqualityType.UnorderedEquality when memberModel.IsDictionary:
case EqualityType.UnorderedEquality
when memberModel is { StringComparer: null, IsDictionary: true }:

BuildHashCodeAdd($"global::Generator.Equals.DictionaryEqualityComparer<{memberModel.TypeName}>.Default");
break;

case EqualityType.UnorderedEquality when !memberModel.IsDictionary:
case EqualityType.UnorderedEquality
when memberModel is { StringComparer: null, IsDictionary: false}:

BuildHashCodeAdd($"global::Generator.Equals.UnorderedEqualityComparer<{memberModel.TypeName}>.Default");
break;

case EqualityType.UnorderedEquality
when memberModel is { StringComparer: not null and not "", IsDictionary: false }:

BuildHashCodeAdd($"new global::Generator.Equals.UnorderedEqualityComparer<{memberModel.TypeName}>(global::System.StringComparer.{memberModel.StringComparer})");
break;

case EqualityType.OrderedEquality
when memberModel is { StringComparer: not null and not "" }:

BuildHashCodeAdd($"new global::Generator.Equals.OrderedEqualityComparer<{memberModel.TypeName}>(global::System.StringComparer.{memberModel.StringComparer})");
break;

case EqualityType.OrderedEquality:
BuildHashCodeAdd($"global::Generator.Equals.OrderedEqualityComparer<{memberModel.TypeName}>.Default");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,18 @@ public static bool HasAttribute(this ISymbol symbol, INamedTypeSymbol attribute)
? null
: new DictionaryArgumentsResult(res);
}

public static bool IsStringArray(this ITypeSymbol typeSymbol)
{
// Check if the symbol is an array
if (typeSymbol is IArrayTypeSymbol arrayTypeSymbol)
{
// Check if the element type is string
return arrayTypeSymbol.ElementType.SpecialType == SpecialType.System_String;
}

return false;
}
}

public record DictionaryArgumentsResult(ImmutableArray<ITypeSymbol>? Arguments) : ArgumentsResult(Arguments)
Expand Down
Loading

0 comments on commit 62a62cf

Please sign in to comment.