From dbd03a08255d5d4f41715abcd8d0fec3a7e5d249 Mon Sep 17 00:00:00 2001 From: Carl de Billy Date: Mon, 12 Feb 2018 11:33:49 -0500 Subject: [PATCH] Added new global option `GenerateEqualityByDefault` --- doc/Equality Generation.md | 28 ++++++++++++++++--- doc/Immutable Generation.md | 25 ++++++++++++++++- .../Given_ImmutableEntity.cs | 4 +-- src/Uno.CodeGen/ImmutableGenerator.cs | 18 ++++++++---- .../ImmutableGenerationOptionsAttribute.cs | 25 +++++++++++++++++ 5 files changed, 87 insertions(+), 13 deletions(-) diff --git a/doc/Equality Generation.md b/doc/Equality Generation.md index cdc4092..8e02973 100644 --- a/doc/Equality Generation.md +++ b/doc/Equality Generation.md @@ -241,11 +241,31 @@ The generation logic for fields/properties in the class, using a first-match rul # FAQ - ## I'm getting the error `warning CS0282: There is no defined ordering between fields - ## in multiple declarations of partial struct ''. To specify an ordering, all - ## instance fields must be in the same declaration.` - You have this error because the generator is using partial declarations for a `struct`. + ## Why am I getting the `warning CS0282`? + The complete warning message is : + ``` + warning CS0282: There is no defined ordering between fields in multiple declarations of partial struct ''. To specify an ordering, all instance fields must be in the same declaration. + ``` + You have this warning because the generator is using partial declarations for a `struct`. If the layout is not important for your structs (mostly used for native interop), you can mute this warning in your project. You can also consider replacing the `struct` by a `class`. + + ## Are equality generation automatic for generated immutables? + Yes they are by default. If you want to chagne this behavior, use the global + `[ImmutableGenerationOptions]` attribute. Example: + ``` csharp + [assembly: Uno.ImmutableGenerationOptions(GenerateEqualityByDefault = true)] + ``` + + You can also override this default by specifying per-type: + ```csharp + [GeneratedImmutable(GenerateEquality = false)] + public class MyImmutable + { + } + ``` + > GOOD TO KNOW: The `[GenerateEquality]` attribute is _inheritable_. It means + > any inherited class will be generated too, even if they are defined in another + > assembly. (Assuming the `Uno.CodeGen` package is used, obviously) diff --git a/doc/Immutable Generation.md b/doc/Immutable Generation.md index dfba66d..21649b4 100644 --- a/doc/Immutable Generation.md +++ b/doc/Immutable Generation.md @@ -335,4 +335,27 @@ by setting this attribute on your assembly: ``` csharp [assembly: Uno.ImmutableGenerationOptions(TreatArrayAsImmutable = true)] -``` \ No newline at end of file +``` + +## Are equality generation automatic for generated immutables? +Yes they are by default. If you want to chagne this behavior, use the global +`[ImmutableGenerationOptions]` attribute. Example: +``` csharp +[assembly: Uno.ImmutableGenerationOptions(GenerateEqualityByDefault = true)] +``` + +You can also override this default by specifying per-type: +```csharp +[GeneratedImmutable(GenerateEquality = false)] +public class MyImmutable +{ +} +``` +> GOOD TO KNOW: Both `[GeneratedImmutable]` and `[GeneratedEquality]` attributes +> are _inheritable_. It means > any inherited class will be generated too, +> even if they are defined in another assembly +> (Assuming the `Uno.CodeGen` package is used, obviously). +> So, disabling equality generation +> (`[GeneratedImmutable(GenerateEquality = false)]`) +> won't have any effect in inherited class if the generation is active on the +> base class. diff --git a/src/Uno.CodeGen.Tests/Given_ImmutableEntity.cs b/src/Uno.CodeGen.Tests/Given_ImmutableEntity.cs index e48c2ed..3c2fbaa 100644 --- a/src/Uno.CodeGen.Tests/Given_ImmutableEntity.cs +++ b/src/Uno.CodeGen.Tests/Given_ImmutableEntity.cs @@ -21,7 +21,7 @@ using System.ComponentModel.DataAnnotations; using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; -[assembly: Uno.ImmutableGenerationOptions(TreatArrayAsImmutable = true)] +[assembly: Uno.ImmutableGenerationOptions(TreatArrayAsImmutable = true, GenerateEqualityByDefault = true)] namespace Uno.CodeGen.Tests { @@ -206,7 +206,7 @@ namespace Uno.CodeGen.Tests } [ImmutableAttributeCopyIgnore("RequiredAttribute")] - [GeneratedImmutable(GenerateEquality = true)] + [GeneratedImmutable()] public abstract partial class MySuperGenericImmutable where T1: MyImmutableEntity where T2: T1 diff --git a/src/Uno.CodeGen/ImmutableGenerator.cs b/src/Uno.CodeGen/ImmutableGenerator.cs index 660734e..f67cf41 100644 --- a/src/Uno.CodeGen/ImmutableGenerator.cs +++ b/src/Uno.CodeGen/ImmutableGenerator.cs @@ -44,7 +44,7 @@ namespace Uno private INamedTypeSymbol _immutableGenerationOptionsAttributeSymbol; private bool _generateOptionCode = true; - private (bool generateOptionCode, bool treatArrayAsImmutable) _generationOptions; + private (bool generateOptionCode, bool treatArrayAsImmutable, bool generateEqualityByDefault) _generationOptions; private Regex[] _copyIgnoreAttributeRegexes; @@ -90,10 +90,11 @@ namespace Uno .Select(a => new Regex(a.ConstructorArguments[0].Value.ToString())); } - private (bool generateOptionCode, bool treatArrayAsImmutable) ExtractGenerationOptions(IAssemblySymbol assembly) + private (bool generateOptionCode, bool treatArrayAsImmutable, bool generateEqualityByDefault) ExtractGenerationOptions(IAssemblySymbol assembly) { var generateOptionCode = true; var treatArrayAsImmutable = false; + var generateEqualityByDefault = true; var attribute = assembly .GetAttributes() @@ -111,19 +112,24 @@ namespace Uno case nameof(ImmutableGenerationOptionsAttribute.TreatArrayAsImmutable): treatArrayAsImmutable = (bool) argument.Value.Value; break; + case nameof(ImmutableGenerationOptionsAttribute.GenerateEqualityByDefault): + generateEqualityByDefault = (bool)argument.Value.Value; + break; } } } - return (generateOptionCode, treatArrayAsImmutable); + return (generateOptionCode, treatArrayAsImmutable, generateEqualityByDefault); } private bool GetShouldGenerateEquality(AttributeData attribute) { - return attribute.NamedArguments - .Where(na => na.Key.Equals("GenerateEquality")) - .Select(na => (bool) na.Value.Value) + var shouldGenerateEquality = attribute.NamedArguments + .Where(na => na.Key.Equals(nameof(GeneratedImmutableAttribute.GenerateEquality))) + .Select(na => (bool?) na.Value.Value) .FirstOrDefault(); + + return shouldGenerateEquality ?? _generationOptions.generateEqualityByDefault; } private (bool isBaseType, string baseType, string builderBaseType, bool isImmutablePresent) GetTypeInfo( diff --git a/src/Uno.Immutables/ImmutableGenerationOptionsAttribute.cs b/src/Uno.Immutables/ImmutableGenerationOptionsAttribute.cs index ca06787..fb360fb 100644 --- a/src/Uno.Immutables/ImmutableGenerationOptionsAttribute.cs +++ b/src/Uno.Immutables/ImmutableGenerationOptionsAttribute.cs @@ -18,11 +18,36 @@ using System; namespace Uno { + /// + /// Global settings for [GenerateImmutable] generator. + /// [System.AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] public sealed class ImmutableGenerationOptionsAttribute : Attribute { + /// + /// If you want arrays to be treat as immutable in the validation. + /// + /// + /// Recommendation is to set this to false if you want actually immutable entities. + /// public bool TreatArrayAsImmutable { get; set; } = false; + /// + /// If you want to generate `Option`-specific Code + /// + /// + /// No effect if not using `Uno.Core`. + /// Default to true. + /// public bool GenerateOptionCode { get; set; } = true; + + /// + /// If you want to generate equality by default. + /// + /// + /// Default is true. Can be overridden by type on the attribute declaration + /// `[GenerateImmutable(GenerateEquality=XXX)]` + /// + public bool GenerateEqualityByDefault { get; set; } = true; } } \ No newline at end of file