static void BuildGetHashCode(ITypeSymbol symbol, AttributesMetadata attributesMetadata, StringBuilder sb)
        {
            var baseTypeName = symbol.BaseType?.ToFQF();

            sb.AppendLine("#nullable enable");

            sb.AppendLine(@"public override int GetHashCode() {
                var hashCode = new global::System.HashCode();
            ");

            sb.AppendLine(baseTypeName == "object"
                ? "hashCode.Add(this.EqualityContract);"
                : "hashCode.Add(base.GetHashCode());");

            foreach (var property in symbol.GetProperties())
            {
                var propertyName = property.ToFQF();

                if (propertyName == "EqualityContract")
                {
                    continue;
                }

                BuildPropertyHashCode(property, attributesMetadata, sb);
            }

            sb.AppendLine("return hashCode.ToHashCode();");
            sb.AppendLine("}");

            sb.AppendLine("#nullable restore");
        }
        static void BuildEquals(ITypeSymbol symbol, AttributesMetadata attributesMetadata, StringBuilder sb)
        {
            var symbolName   = symbol.ToFQF();
            var baseTypeName = symbol.BaseType?.ToFQF();

            sb.AppendLine("#nullable enable");

            sb.AppendLine(symbol.IsSealed
                ? $"public bool Equals({symbolName}? other) {{"
                : $"public virtual bool Equals({symbolName}? other) {{");

            sb.AppendLine(baseTypeName == "object"
                ? "return !ReferenceEquals(other, null) && EqualityContract == other.EqualityContract"
                : $"return base.Equals(({baseTypeName}?)other)");

            foreach (var property in symbol.GetProperties())
            {
                var propertyName = property.ToFQF();

                if (propertyName == "EqualityContract")
                {
                    continue;
                }

                BuildPropertyEquality(attributesMetadata, sb, property);
            }

            sb.AppendLine(";");
            sb.AppendLine("}");

            sb.AppendLine("#nullable restore");
        }
Example #3
0
        static void BuildEquals(ITypeSymbol symbol, AttributesMetadata attributesMetadata, StringBuilder sb, bool explicitMode)
        {
            var symbolName   = symbol.ToFQF();
            var baseTypeName = symbol.BaseType?.ToFQF();

            sb.AppendLine(InheritDocComment);
            sb.AppendLine(GeneratedCodeAttributeDeclaration);
            sb.AppendLine(symbol.IsSealed
                ? $"public bool Equals({symbolName}? other) {{"
                : $"public virtual bool Equals({symbolName}? other) {{");

            sb.AppendLine(baseTypeName == "object"
                ? "return !ReferenceEquals(other, null) && EqualityContract == other.EqualityContract"
                : $"return base.Equals(({baseTypeName}?)other)");

            foreach (var property in symbol.GetProperties())
            {
                var propertyName = property.ToFQF();

                if (propertyName == "EqualityContract")
                {
                    continue;
                }

                BuildPropertyEquality(attributesMetadata, sb, property, explicitMode);
            }

            sb.AppendLine(";");
            sb.AppendLine("}");
        }
        static void BuildEquals(ITypeSymbol symbol, AttributesMetadata attributesMetadata, StringBuilder sb)
        {
            var symbolName   = symbol.ToFQF();
            var baseTypeName = symbol.BaseType?.ToFQF();

            sb.AppendLine("#nullable enable");

            sb.AppendLine($"public static bool operator ==({symbolName}? a, {symbolName}? b) => global::System.Collections.Generic.EqualityComparer<{symbolName}>.Default.Equals(a, b);");
            sb.AppendLine($"public static bool operator !=({symbolName}? a, {symbolName}? b) => !(a == b);");
            sb.AppendLine($"public override bool Equals(object? obj) => Equals(obj as {symbolName});");
            sb.AppendLine($"public bool Equals({symbolName}? other) {{");

            sb.AppendLine(baseTypeName == "object"
                ? "return !ReferenceEquals(other, null) && this.GetType() == other.GetType()"
                : $"return base.Equals(other as {baseTypeName})");

            foreach (var property in symbol.GetProperties())
            {
                BuildPropertyEquality(attributesMetadata, sb, property);
            }

            sb.AppendLine(";");
            sb.AppendLine("}");

            sb.AppendLine("#nullable restore");
        }
Example #5
0
        static void BuildGetHashCode(ITypeSymbol symbol, AttributesMetadata attributesMetadata, StringBuilder sb, bool explicitMode)
        {
            var baseTypeName = symbol.BaseType?.ToFQF();

            sb.AppendLine(InheritDocComment);
            sb.AppendLine(GeneratedCodeAttributeDeclaration);
            sb.AppendLine(@"public override int GetHashCode() {
                var hashCode = new global::System.HashCode();
            ");

            sb.AppendLine(baseTypeName == "object"
                ? "hashCode.Add(this.EqualityContract);"
                : "hashCode.Add(base.GetHashCode());");

            foreach (var property in symbol.GetProperties())
            {
                var propertyName = property.ToFQF();

                if (propertyName == "EqualityContract")
                {
                    continue;
                }

                BuildPropertyHashCode(property, attributesMetadata, sb, explicitMode);
            }

            sb.AppendLine("return hashCode.ToHashCode();");
            sb.AppendLine("}");
        }
        static void BuildEquals(ITypeSymbol symbol, AttributesMetadata attributesMetadata, StringBuilder sb, bool explicitMode)
        {
            var symbolName   = symbol.ToFQF();
            var baseTypeName = symbol.BaseType?.ToFQF();

            sb.AppendLine(EqualsOperatorCodeComment);
            sb.AppendLine(GeneratedCodeAttributeDeclaration);
            sb.AppendLine($"public static bool operator ==({symbolName}? left, {symbolName}? right) => global::System.Collections.Generic.EqualityComparer<{symbolName}?>.Default.Equals(left, right);");

            sb.AppendLine(NotEqualsOperatorCodeComment);
            sb.AppendLine(GeneratedCodeAttributeDeclaration);
            sb.AppendLine($"public static bool operator !=({symbolName}? left, {symbolName}? right) => !(left == right);");

            sb.AppendLine(InheritDocComment);
            sb.AppendLine(GeneratedCodeAttributeDeclaration);
            sb.AppendLine($"public override bool Equals(object? obj) => Equals(obj as {symbolName});");

            sb.AppendLine(InheritDocComment);
            sb.AppendLine(GeneratedCodeAttributeDeclaration);
            sb.AppendLine($"public bool Equals({symbolName}? other) {{");

            sb.AppendLine(baseTypeName == "object"
                ? "return !ReferenceEquals(other, null) && this.GetType() == other.GetType()"
                : $"return base.Equals(other as {baseTypeName})");

            foreach (var property in symbol.GetProperties())
            {
                BuildPropertyEquality(attributesMetadata, sb, property, explicitMode);
            }

            sb.AppendLine(";");
            sb.AppendLine("}");
        }
        public static string Generate(ITypeSymbol symbol, AttributesMetadata attributesMetadata)
        {
            var code = ContainingTypesBuilder.Build(symbol, includeSelf: true, content: sb =>
            {
                BuildEquals(symbol, attributesMetadata, sb);

                BuildGetHashCode(symbol, attributesMetadata, sb);
            });

            return(code);
        }
        public static string Generate(ITypeSymbol symbol, AttributesMetadata attributesMetadata)
        {
            var code = ContainingTypesBuilder.Build(symbol, includeSelf: false, content: sb =>
            {
                var typeName = symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat);
                sb.AppendLine($"partial class {typeName} : global::System.IEquatable<{typeName}> {{");

                BuildEquals(symbol, attributesMetadata, sb);
                BuildGetHashCode(symbol, attributesMetadata, sb);

                sb.AppendLine("}");
            });

            return(code);
        }
Example #9
0
        public static string Generate(ITypeSymbol symbol, AttributesMetadata attributesMetadata, bool explicitMode)
        {
            var code = ContainingTypesBuilder.Build(symbol, includeSelf: true, content: sb =>
            {
                sb.AppendLine(EnableNullableContext);
                sb.AppendLine(SuppressObsoleteWarningsPragma);

                BuildEquals(symbol, attributesMetadata, sb, explicitMode);
                BuildGetHashCode(symbol, attributesMetadata, sb, explicitMode);

                sb.AppendLine(RestoreObsoleteWarningsPragma);
                sb.AppendLine(RestoreNullableContext);
            });

            return(code);
        }
Example #10
0
        public static void BuildPropertyHashCode(IPropertySymbol property, AttributesMetadata attributesMetadata,
                                                 StringBuilder sb)
        {
            if (property.HasAttribute(attributesMetadata.IgnoreEquality))
            {
                return;
            }

            var propertyName = property.ToFQF();

            var typeName = property.Type.ToNullableFQF();

            sb.Append($"hashCode.Add(this.{propertyName}!, ");

            if (property.HasAttribute(attributesMetadata.UnorderedEquality))
            {
                var types = property.GetIDictionaryTypeArguments();

                if (types != null)
                {
                    sb.Append(
                        $"global::Generator.Equals.DictionaryEqualityComparer<{string.Join(", ", types.Value)}>.Default");
                }
                else
                {
                    types = property.GetIEnumerableTypeArguments() !;
                    sb.Append(
                        $"global::Generator.Equals.UnorderedEqualityComparer<{string.Join(", ", types.Value)}>.Default");
                }
            }
            else if (property.HasAttribute(attributesMetadata.OrderedEquality))
            {
                var types = property.GetIEnumerableTypeArguments() !;
                sb.Append(
                    $"global::Generator.Equals.OrderedEqualityComparer<{string.Join(", ", types.Value)}>.Default");
            }
            else if (property.HasAttribute(attributesMetadata.ReferenceEquality))
            {
                sb.Append($"global::Generator.Equals.ReferenceEqualityComparer<{typeName}>.Default");
            }
            else
            {
                sb.Append($"global::System.Collections.Generic.EqualityComparer<{typeName}>.Default");
            }

            sb.AppendLine(");");
        }
        public static string Generate(ITypeSymbol symbol, AttributesMetadata attributesMetadata, bool explicitMode)
        {
            var code = ContainingTypesBuilder.Build(symbol, includeSelf: false, content: sb =>
            {
                var typeName = symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat);
                sb.AppendLine($"partial class {typeName} : global::System.IEquatable<{typeName}> {{");

                sb.AppendLine(EnableNullableContext);
                sb.AppendLine(SuppressObsoleteWarningsPragma);

                BuildEquals(symbol, attributesMetadata, sb, explicitMode);
                BuildGetHashCode(symbol, attributesMetadata, sb, explicitMode);

                sb.AppendLine(RestoreObsoleteWarningsPragma);
                sb.AppendLine(RestoreNullableContext);

                sb.AppendLine("}");
            });

            return(code);
        }
Example #12
0
        public static void BuildPropertyEquality(AttributesMetadata attributesMetadata, StringBuilder sb,
                                                 IPropertySymbol property, bool explicitMode)
        {
            if (property.HasAttribute(attributesMetadata.IgnoreEquality))
            {
                return;
            }

            var propertyName = property.ToFQF();

            var typeName = property.Type.ToNullableFQF();

            if (property.HasAttribute(attributesMetadata.UnorderedEquality))
            {
                var types = property.GetIDictionaryTypeArguments();

                if (types != null)
                {
                    sb.AppendLine(
                        $"&& global::Generator.Equals.DictionaryEqualityComparer<{string.Join(", ", types.Value)}>.Default.Equals({propertyName}!, other.{propertyName}!)");
                }
                else
                {
                    types = property.GetIEnumerableTypeArguments() !;
                    sb.AppendLine(
                        $"&& global::Generator.Equals.UnorderedEqualityComparer<{string.Join(", ", types.Value)}>.Default.Equals({propertyName}!, other.{propertyName}!)");
                }
            }
            else if (property.HasAttribute(attributesMetadata.OrderedEquality))
            {
                var types = property.GetIEnumerableTypeArguments() !;

                sb.AppendLine(
                    $"&& global::Generator.Equals.OrderedEqualityComparer<{string.Join(", ", types.Value)}>.Default.Equals({propertyName}!, other.{propertyName}!)");
            }
            else if (property.HasAttribute(attributesMetadata.ReferenceEquality))
            {
                sb.AppendLine(
                    $"&& global::Generator.Equals.ReferenceEqualityComparer<{typeName}>.Default.Equals({propertyName}!, other.{propertyName}!)");
            }
            else if (property.HasAttribute(attributesMetadata.SetEquality))
            {
                var types = property.GetIEnumerableTypeArguments() !;

                sb.AppendLine(
                    $"&& global::Generator.Equals.SetEqualityComparer<{string.Join(", ", types.Value)}>.Default.Equals({propertyName}!, other.{propertyName}!)");
            }
            else if (property.HasAttribute(attributesMetadata.CustomEquality))
            {
                var attribute          = property.GetAttribute(attributesMetadata.CustomEquality);
                var comparerType       = (INamedTypeSymbol)attribute?.ConstructorArguments[0].Value !;
                var comparerMemberName = (string)attribute?.ConstructorArguments[1].Value !;

                if (comparerType.GetMembers().Any(x => x.Name == comparerMemberName && x.IsStatic) || comparerType.GetProperties().Any(x => x.Name == comparerMemberName && x.IsStatic))
                {
                    sb.AppendLine(
                        $"&& {comparerType.ToFQF()}.{comparerMemberName}.Equals({propertyName}!, other.{propertyName}!)");
                }
                else
                {
                    sb.AppendLine(
                        $"&& new {comparerType.ToFQF()}().Equals({propertyName}!, other.{propertyName}!)");
                }
            }
            else if (
                !explicitMode ||
                property.HasAttribute(attributesMetadata.DefaultEquality))
            {
                sb.AppendLine(
                    $"&& global::System.Collections.Generic.EqualityComparer<{typeName}>.Default.Equals({propertyName}!, other.{propertyName}!)");
            }
        }