From 6da330e2ba2c999124a6a68dddcfe4324a0416b4 Mon Sep 17 00:00:00 2001 From: SimonCropp Date: Sun, 2 Feb 2020 22:40:19 +1100 Subject: [PATCH] add error for incorrect attribute usage --- .../PropertyAttribuesWithNoEquals.cs | 11 +++++ Directory.Build.props | 2 +- Equals.Fody/Equals.Fody.csproj | 2 +- Equals.Fody/Injectors/EqualsInjector.cs | 4 +- Equals.Fody/Injectors/GetHashCodeInjector.cs | 2 +- Equals.Fody/ModuleWeaver.cs | 44 ++++++++++++++++--- ...te.cs => CustomEqualsInternalAttribute.cs} | 0 Equals/Equals.csproj | 4 +- ...tionTests.IncorrectAttributes.verified.txt | 5 +++ Tests/IntegrationTests_operators.cs | 7 +++ Tests/Tests.csproj | 4 +- 11 files changed, 69 insertions(+), 16 deletions(-) create mode 100644 AssemblyToProcess/PropertyAttribuesWithNoEquals.cs rename Equals/{EqualsInternalAttribute.cs => CustomEqualsInternalAttribute.cs} (100%) create mode 100644 Tests/IntegrationTests.IncorrectAttributes.verified.txt diff --git a/AssemblyToProcess/PropertyAttribuesWithNoEquals.cs b/AssemblyToProcess/PropertyAttribuesWithNoEquals.cs new file mode 100644 index 0000000..81696ab --- /dev/null +++ b/AssemblyToProcess/PropertyAttribuesWithNoEquals.cs @@ -0,0 +1,11 @@ +public class PropertyAttributesWithNoEquals +{ + [IgnoreDuringEquals] + public int Property { get; set; } + + [CustomEqualsInternal] + [CustomGetHashCode] + public void Method() + { + } +} \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props index 2cff639..a8048ed 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,6 +3,6 @@ true latest - 4.0.0 + 4.0.1 diff --git a/Equals.Fody/Equals.Fody.csproj b/Equals.Fody/Equals.Fody.csproj index 8aee526..38e86ff 100644 --- a/Equals.Fody/Equals.Fody.csproj +++ b/Equals.Fody/Equals.Fody.csproj @@ -5,6 +5,6 @@ portable - + \ No newline at end of file diff --git a/Equals.Fody/Injectors/EqualsInjector.cs b/Equals.Fody/Injectors/EqualsInjector.cs index b88452e..74b5c79 100644 --- a/Equals.Fody/Injectors/EqualsInjector.cs +++ b/Equals.Fody/Injectors/EqualsInjector.cs @@ -89,7 +89,7 @@ public MethodReference InjectEqualsInternal(TypeDefinition type, TypeReference t body.InitLocals = true; var ins = body.Instructions; - var properties = type.GetPropertiesWithoutIgnores(ignoreAttributeName); + var properties = type.GetPropertiesWithoutIgnores(ignoreDuringEqualsAttributeName); if (ignoreBaseClassProperties) { properties = properties.IgnoreBaseClassProperties(type); @@ -102,7 +102,7 @@ public MethodReference InjectEqualsInternal(TypeDefinition type, TypeReference t var methods = type.GetMethods(); var customLogic = methods - .Where(x => x.CustomAttributes.Any(y => y.AttributeType.Name == customEqualsAttribute)).ToArray(); + .Where(x => x.CustomAttributes.Any(y => y.AttributeType.Name == customEqualsInternalAttribute)).ToArray(); if (customLogic.Length > 2) { diff --git a/Equals.Fody/Injectors/GetHashCodeInjector.cs b/Equals.Fody/Injectors/GetHashCodeInjector.cs index ec86cd0..9e74c50 100644 --- a/Equals.Fody/Injectors/GetHashCodeInjector.cs +++ b/Equals.Fody/Injectors/GetHashCodeInjector.cs @@ -26,7 +26,7 @@ public void InjectGetHashCode(TypeDefinition type, bool ignoreBaseClassPropertie ins.Add(Instruction.Create(OpCodes.Ldc_I4_0)); ins.Add(Instruction.Create(OpCodes.Stloc, resultVariable)); - var properties = ModuleDefinition.ImportReference(type).Resolve().GetPropertiesWithoutIgnores(ignoreAttributeName); + var properties = ModuleDefinition.ImportReference(type).Resolve().GetPropertiesWithoutIgnores(ignoreDuringEqualsAttributeName); if (ignoreBaseClassProperties) { properties = properties.IgnoreBaseClassProperties(type); diff --git a/Equals.Fody/ModuleWeaver.cs b/Equals.Fody/ModuleWeaver.cs index 8c6a23b..22f6bc0 100644 --- a/Equals.Fody/ModuleWeaver.cs +++ b/Equals.Fody/ModuleWeaver.cs @@ -8,8 +8,8 @@ public partial class ModuleWeaver : BaseModuleWeaver { public const string attributeName = "EqualsAttribute"; - public const string ignoreAttributeName = "IgnoreDuringEqualsAttribute"; - public const string customEqualsAttribute = "CustomEqualsInternalAttribute"; + public const string ignoreDuringEqualsAttributeName = "IgnoreDuringEqualsAttribute"; + public const string customEqualsInternalAttribute = "CustomEqualsInternalAttribute"; public const string DoNotAddEqualityOperators = "DoNotAddEqualityOperators"; public const string DoNotAddGetHashCode = "DoNotAddGetHashCode"; @@ -35,9 +35,9 @@ TypeReference GetGenericType(TypeReference type) public override void Execute() { - if (!FindReferencesAndDetermineWhetherEqualsIsReferenced(FindType)) + if (!FindReferencesAndDetermineWhetherEqualsIsReferenced(FindTypeDefinition)) { - LogDebug("Assembly does not reference 'Equals' assembly. No work to do - exiting."); + WriteDebug("Assembly does not reference 'Equals' assembly. No work to do - exiting."); return; } @@ -97,6 +97,36 @@ public override void Execute() { RemoveFodyAttributes(type); } + + CheckForInvalidAttributes(); + } + + void CheckForInvalidAttributes() + { + foreach (var type in ModuleDefinition.GetTypes()) + { + foreach (var method in type.Methods) + { + if (method.CustomAttributes.Any(x => x.AttributeType.Name == customEqualsInternalAttribute)) + { + WriteError($"Method `{type.FullName}.{method.Name}` contains {customEqualsInternalAttribute} but has no `[Equals]` attribute.", method); + } + + if (method.CustomAttributes.Any(x => x.AttributeType.Name == CustomGetHashCodeAttribute)) + { + WriteError($"Method `{type.FullName}.{method.Name}` contains {CustomGetHashCodeAttribute} but has no `[Equals]` attribute.", method); + } + } + + foreach (var property in type.Properties) + { + if (property.CustomAttributes.Any(x => x.AttributeType.Name == ignoreDuringEqualsAttributeName)) + { + //TODO: add sequence point + WriteError($"Property `{type.FullName}.{property.Name}` contains {ignoreDuringEqualsAttributeName} but has no `[Equals]` attribute."); + } + } + } } public override IEnumerable GetAssembliesForScanning() @@ -128,17 +158,17 @@ void RemoveFodyAttributes(TypeDefinition type) foreach (var property in type.Properties) { - property.RemoveAttribute(ignoreAttributeName); + property.RemoveAttribute(ignoreDuringEqualsAttributeName); } foreach (var property in type.Fields) { - property.RemoveAttribute(ignoreAttributeName); + property.RemoveAttribute(ignoreDuringEqualsAttributeName); } foreach (var method in type.Methods) { - method.RemoveAttribute(customEqualsAttribute); + method.RemoveAttribute(customEqualsInternalAttribute); method.RemoveAttribute(CustomGetHashCodeAttribute); } } diff --git a/Equals/EqualsInternalAttribute.cs b/Equals/CustomEqualsInternalAttribute.cs similarity index 100% rename from Equals/EqualsInternalAttribute.cs rename to Equals/CustomEqualsInternalAttribute.cs diff --git a/Equals/Equals.csproj b/Equals/Equals.csproj index 7073c97..77a99ec 100644 --- a/Equals/Equals.csproj +++ b/Equals/Equals.csproj @@ -14,7 +14,7 @@ Equals, GetHashCode, ILWeaving, Fody, Cecil - - + + \ No newline at end of file diff --git a/Tests/IntegrationTests.IncorrectAttributes.verified.txt b/Tests/IntegrationTests.IncorrectAttributes.verified.txt new file mode 100644 index 0000000..768b4b4 --- /dev/null +++ b/Tests/IntegrationTests.IncorrectAttributes.verified.txt @@ -0,0 +1,5 @@ +[ + 'Method `PropertyAttributesWithNoEquals.Method` contains CustomEqualsInternalAttribute but has no `[Equals]` attribute.', + 'Method `PropertyAttributesWithNoEquals.Method` contains CustomGetHashCodeAttribute but has no `[Equals]` attribute.', + 'Property `PropertyAttributesWithNoEquals.Property` contains IgnoreDuringEqualsAttribute but has no `[Equals]` attribute.' +] \ No newline at end of file diff --git a/Tests/IntegrationTests_operators.cs b/Tests/IntegrationTests_operators.cs index 2f318c1..5a27d1c 100644 --- a/Tests/IntegrationTests_operators.cs +++ b/Tests/IntegrationTests_operators.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Threading.Tasks; using Xunit; public partial class IntegrationTests @@ -135,6 +136,12 @@ public void Equality_operator_should_return_true_for_equal_object_collections() Assert.False(first != second); } + [Fact] + public Task IncorrectAttributes() + { + return Verify(testResult.Errors.Select(x => x.Text)); + } + [Fact] public void Equality_operator_should_return_false_for_collections_with_different_size() { diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index c3ee339..c661ab6 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -6,10 +6,10 @@ - + - +