From 3ea447952b82e6aa78062ce0922a35aefeefd994 Mon Sep 17 00:00:00 2001 From: Vadim Hatsura Date: Sun, 10 Apr 2022 22:04:53 +0200 Subject: [PATCH 1/3] equality for ObjectTypeExtensionNode --- .../ObjectTypeExtensionNode.cs | 131 +++++++++++++----- .../ObjectTypeExtensionNodeTests.cs | 130 +++++++++++++++++ 2 files changed, 226 insertions(+), 35 deletions(-) create mode 100644 src/HotChocolate/Language/test/Language.SyntaxTree.Tests/ObjectTypeExtensionNodeTests.cs diff --git a/src/HotChocolate/Language/src/Language.SyntaxTree/ObjectTypeExtensionNode.cs b/src/HotChocolate/Language/src/Language.SyntaxTree/ObjectTypeExtensionNode.cs index 7fc858c5b9e..1cbdc5dbe84 100644 --- a/src/HotChocolate/Language/src/Language.SyntaxTree/ObjectTypeExtensionNode.cs +++ b/src/HotChocolate/Language/src/Language.SyntaxTree/ObjectTypeExtensionNode.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using HotChocolate.Language.Utilities; @@ -6,7 +7,26 @@ namespace HotChocolate.Language; public sealed class ObjectTypeExtensionNode : ObjectTypeDefinitionNodeBase , ITypeExtensionNode + , IEquatable { + /// + /// Initializes a new instance of . + /// + /// + /// The location of the syntax node within the original source text. + /// + /// + /// The name that this syntax node holds. + /// + /// + /// The directives that are annotated to this syntax node. + /// + /// + /// The interfaces that this type implements. + /// + /// + /// The fields that this type exposes. + /// public ObjectTypeExtensionNode( Location? location, NameNode name, @@ -14,10 +34,13 @@ public ObjectTypeExtensionNode( IReadOnlyList interfaces, IReadOnlyList fields) : base(location, name, directives, interfaces, fields) - { } + { + } - public override SyntaxKind Kind { get; } = SyntaxKind.ObjectTypeExtension; + /// + public override SyntaxKind Kind => SyntaxKind.ObjectTypeExtension; + /// public override IEnumerable GetNodes() { yield return Name; @@ -59,41 +82,79 @@ public override IEnumerable GetNodes() /// public override string ToString(bool indented) => SyntaxPrinter.Print(this, indented); - public ObjectTypeExtensionNode WithLocation(Location? location) - { - return new ObjectTypeExtensionNode( - location, Name, Directives, - Interfaces, Fields); - } + /// + /// Creates a new node from the current instance and replaces the + /// with . + /// + /// + /// The location that shall be used to replace the current location. + /// + /// + /// Returns the new node with the new + /// + public ObjectTypeExtensionNode WithLocation(Location? location) => + new(location, Name, Directives, Interfaces, Fields); - public ObjectTypeExtensionNode WithName(NameNode name) - { - return new ObjectTypeExtensionNode( - Location, name, Directives, - Interfaces, Fields); - } + /// + /// Creates a new node from the current instance and replaces the + /// with + /// + /// + /// The name that shall be used to replace the current name. + /// + /// + /// Returns the new node with the new + /// + public ObjectTypeExtensionNode WithName(NameNode name) => + new(Location, name, Directives, Interfaces, Fields); - public ObjectTypeExtensionNode WithDirectives( - IReadOnlyList directives) - { - return new ObjectTypeExtensionNode( - Location, Name, directives, - Interfaces, Fields); - } + /// + /// Creates a new node from the current instance and replaces the + /// with + /// + /// + /// The directives that shall be used to replace the current directives. + /// + /// + /// Returns the new node with the new + /// + public ObjectTypeExtensionNode WithDirectives(IReadOnlyList directives) => + new(Location, Name, directives, Interfaces, Fields); - public ObjectTypeExtensionNode WithInterfaces( - IReadOnlyList interfaces) - { - return new ObjectTypeExtensionNode( - Location, Name, Directives, - interfaces, Fields); - } + /// + /// Creates a new node from the current instance and replaces the + /// with + /// + /// + /// The interfaces that shall be used to replace the current interfaces. + /// + /// + /// Returns the new node with the new + /// + public ObjectTypeExtensionNode WithInterfaces(IReadOnlyList interfaces) => + new(Location, Name, Directives, interfaces, Fields); - public ObjectTypeExtensionNode WithFields( - IReadOnlyList fields) - { - return new ObjectTypeExtensionNode( - Location, Name, Directives, - Interfaces, fields); - } + /// + /// Creates a new node from the current instance and replaces the + /// with + /// + /// + /// The fields that shall be used to replace the current fields. + /// + /// + /// Returns the new node with the new + /// + public ObjectTypeExtensionNode WithFields(IReadOnlyList fields) => + new(Location, Name, Directives, Interfaces, fields); + + /// + public bool Equals(ObjectTypeExtensionNode? other) => base.Equals(other); + + /// + public override bool Equals(object? obj) => ReferenceEquals(this, obj) || + obj is ObjectTypeExtensionNode other && + Equals(other); + + /// + public override int GetHashCode() => base.GetHashCode(); } diff --git a/src/HotChocolate/Language/test/Language.SyntaxTree.Tests/ObjectTypeExtensionNodeTests.cs b/src/HotChocolate/Language/test/Language.SyntaxTree.Tests/ObjectTypeExtensionNodeTests.cs new file mode 100644 index 00000000000..18424b56592 --- /dev/null +++ b/src/HotChocolate/Language/test/Language.SyntaxTree.Tests/ObjectTypeExtensionNodeTests.cs @@ -0,0 +1,130 @@ +using System.Collections.Generic; +using Xunit; + +namespace HotChocolate.Language.SyntaxTree; + +public class ObjectTypeExtensionNodeTests +{ + [Fact] + public void Equals_With_Same_Location() + + { + // arrange + var a = new ObjectTypeExtensionNode( + TestLocations.Location1, + new NameNode("aa"), + new List(0), + new List(0), + new List(0) + ); + var b = new ObjectTypeExtensionNode( + TestLocations.Location1, + new NameNode("bb"), + new List(0), + new List(0), + new List(0) + ); + var c = new ObjectTypeExtensionNode( + TestLocations.Location1, + new NameNode("aa"), + new List(0), + new List(0), + new List(0) + ); + + // act + var aaResult = a.Equals(a); + var abResult = a.Equals(b); + var acResult = a.Equals(c); + var aNullResult = a.Equals(default); + + // assert + Assert.True(aaResult); + Assert.False(abResult); + Assert.True(acResult); + Assert.False(aNullResult); + } + + [Fact] + public void Equals_With_Different_Location() + { + // arrange + var a = new ObjectTypeExtensionNode( + TestLocations.Location1, + new NameNode("aa"), + new List(0), + new List(0), + new List(0) + ); + var b = new ObjectTypeExtensionNode( + TestLocations.Location2, + new NameNode("aa"), + new List(0), + new List(0), + new List(0) + ); + var c = new ObjectTypeExtensionNode( + TestLocations.Location3, + new NameNode("bb"), + new List(0), + new List(0), + new List(0) + ); + + // act + var aaResult = a.Equals(a); + var abResult = a.Equals(b); + var acResult = a.Equals(c); + + // assert + Assert.True(aaResult); + Assert.True(abResult); + Assert.False(acResult); + } + + [Fact] + public void GetHashCode_With_Location() + { + // arrange + var a = new ObjectTypeExtensionNode( + TestLocations.Location1, + new NameNode("aa"), + new List(0), + new List(0), + new List(0) + ); + var b = new ObjectTypeExtensionNode( + TestLocations.Location2, + new NameNode("aa"), + new List(0), + new List(0), + new List(0) + ); + var c = new ObjectTypeExtensionNode( + TestLocations.Location1, + new NameNode("bb"), + new List(0), + new List(0), + new List(0) + ); + var d = new ObjectTypeExtensionNode( + TestLocations.Location2, + new NameNode("cc"), + new List(0), + new List(0), + new List(0) + ); + + // act + var aHash = a.GetHashCode(); + var bHash = b.GetHashCode(); + var cHash = c.GetHashCode(); + var dHash = d.GetHashCode(); + + // assert + Assert.Equal(aHash, bHash); + Assert.NotEqual(aHash, cHash); + Assert.NotEqual(cHash, dHash); + Assert.NotEqual(aHash, dHash); + } +} From 34a1dc81e5e05bc1df9ecb40fe323711df5bfea3 Mon Sep 17 00:00:00 2001 From: Vadim Hatsura Date: Sun, 10 Apr 2022 22:05:06 +0200 Subject: [PATCH 2/3] fix operation type definition node tests --- .../OperationTypeDefinitionNodeTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/HotChocolate/Language/test/Language.SyntaxTree.Tests/OperationTypeDefinitionNodeTests.cs b/src/HotChocolate/Language/test/Language.SyntaxTree.Tests/OperationTypeDefinitionNodeTests.cs index eb49869e6a7..300da4f12db 100644 --- a/src/HotChocolate/Language/test/Language.SyntaxTree.Tests/OperationTypeDefinitionNodeTests.cs +++ b/src/HotChocolate/Language/test/Language.SyntaxTree.Tests/OperationTypeDefinitionNodeTests.cs @@ -94,6 +94,6 @@ public void CompareGetHashCode_WithLocations() // assert Assert.Equal(aHash, bHash); Assert.NotEqual(aHash, cHash); - Assert.Equal(cHash, dHash); + Assert.NotEqual(cHash, dHash); } } From 93b7ef1ed8b433d1b14b9265662518538996169a Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Thu, 14 Apr 2022 20:16:27 +0200 Subject: [PATCH 3/3] fixed --- .../ObjectTypeExtensionNode.cs | 62 ++++++++++++++----- .../SyntaxSerializer.SchemaSyntax.cs | 14 ++--- .../ObjectTypeDefinitionNodeTests.cs | 3 +- .../ObjectTypeExtensionNodeTests.cs | 35 ++++------- 4 files changed, 62 insertions(+), 52 deletions(-) diff --git a/src/HotChocolate/Language/src/Language.SyntaxTree/ObjectTypeExtensionNode.cs b/src/HotChocolate/Language/src/Language.SyntaxTree/ObjectTypeExtensionNode.cs index cc4bb0932f1..997f8a3a618 100644 --- a/src/HotChocolate/Language/src/Language.SyntaxTree/ObjectTypeExtensionNode.cs +++ b/src/HotChocolate/Language/src/Language.SyntaxTree/ObjectTypeExtensionNode.cs @@ -4,6 +4,11 @@ namespace HotChocolate.Language; +/// +/// Object type extensions are used to represent a type which has been extended +/// from some original type. For example, this might be used to represent local data, +/// or by a GraphQL service which is itself an extension of another GraphQL service. +/// public sealed class ObjectTypeExtensionNode : ComplexTypeDefinitionNodeBase , ITypeExtensionNode @@ -92,8 +97,8 @@ public override IEnumerable GetNodes() /// /// Returns the new node with the new /// - public ObjectTypeExtensionNode WithLocation(Location? location) => - new(location, Name, Directives, Interfaces, Fields); + public ObjectTypeExtensionNode WithLocation(Location? location) + => new(location, Name, Directives, Interfaces, Fields); /// /// Creates a new node from the current instance and replaces the @@ -105,12 +110,12 @@ public ObjectTypeExtensionNode WithLocation(Location? location) => /// /// Returns the new node with the new /// - public ObjectTypeExtensionNode WithName(NameNode name) => - new(Location, name, Directives, Interfaces, Fields); + public ObjectTypeExtensionNode WithName(NameNode name) + => new(Location, name, Directives, Interfaces, Fields); /// /// Creates a new node from the current instance and replaces the - /// with + /// with /// /// /// The directives that shall be used to replace the current directives. @@ -118,12 +123,12 @@ public ObjectTypeExtensionNode WithName(NameNode name) => /// /// Returns the new node with the new /// - public ObjectTypeExtensionNode WithDirectives(IReadOnlyList directives) => - new(Location, Name, directives, Interfaces, Fields); + public ObjectTypeExtensionNode WithDirectives(IReadOnlyList directives) + => new(Location, Name, directives, Interfaces, Fields); /// /// Creates a new node from the current instance and replaces the - /// with + /// with /// /// /// The interfaces that shall be used to replace the current interfaces. @@ -131,12 +136,12 @@ public ObjectTypeExtensionNode WithDirectives(IReadOnlyList direc /// /// Returns the new node with the new /// - public ObjectTypeExtensionNode WithInterfaces(IReadOnlyList interfaces) => - new(Location, Name, Directives, interfaces, Fields); + public ObjectTypeExtensionNode WithInterfaces(IReadOnlyList interfaces) + => new(Location, Name, Directives, interfaces, Fields); /// /// Creates a new node from the current instance and replaces the - /// with + /// with /// /// /// The fields that shall be used to replace the current fields. @@ -144,17 +149,40 @@ public ObjectTypeExtensionNode WithInterfaces(IReadOnlyList inter /// /// Returns the new node with the new /// - public ObjectTypeExtensionNode WithFields(IReadOnlyList fields) => - new(Location, Name, Directives, Interfaces, fields); + public ObjectTypeExtensionNode WithFields(IReadOnlyList fields) + => new(Location, Name, Directives, Interfaces, fields); /// public bool Equals(ObjectTypeExtensionNode? other) => base.Equals(other); /// - public override bool Equals(object? obj) => ReferenceEquals(this, obj) || - obj is ObjectTypeExtensionNode other && - Equals(other); + public override bool Equals(object? obj) + => ReferenceEquals(this, obj) || + (obj is ObjectTypeExtensionNode other && Equals(other)); /// - public override int GetHashCode() => base.GetHashCode(); + public override int GetHashCode() + => HashCode.Combine(base.GetHashCode(), Kind); + + /// + /// The equal operator. + /// + /// The left parameter + /// The right parameter + /// + /// true if and are equal. + /// + public static bool operator ==(ObjectTypeExtensionNode? left, ObjectTypeExtensionNode? right) + => Equals(left, right); + + /// + /// The not equal operator. + /// + /// The left parameter + /// The right parameter + /// + /// true if and are not equal. + /// + public static bool operator !=(ObjectTypeExtensionNode? left, ObjectTypeExtensionNode? right) + => !Equals(left, right); } diff --git a/src/HotChocolate/Language/src/Language.SyntaxTree/Utilities/SyntaxSerializer.SchemaSyntax.cs b/src/HotChocolate/Language/src/Language.SyntaxTree/Utilities/SyntaxSerializer.SchemaSyntax.cs index 1d3953c96ee..9bb1947efaa 100644 --- a/src/HotChocolate/Language/src/Language.SyntaxTree/Utilities/SyntaxSerializer.SchemaSyntax.cs +++ b/src/HotChocolate/Language/src/Language.SyntaxTree/Utilities/SyntaxSerializer.SchemaSyntax.cs @@ -48,7 +48,7 @@ private void VisitObjectTypeExtension(ObjectTypeExtensionNode node, ISyntaxWrite } private void VisitObjectTypeDefinitionBase( - ObjectTypeDefinitionNodeBase node, + ComplexTypeDefinitionNodeBase node, ISyntaxWriter writer) { writer.Write(Keywords.Type); @@ -60,9 +60,7 @@ private void VisitObjectTypeDefinitionBase( writer.WriteSpace(); writer.Write(Keywords.Implements); writer.WriteSpace(); - writer.WriteMany(node.Interfaces, - (n, w) => writer.WriteNamedType(n), - " & "); + writer.WriteMany(node.Interfaces, (n, _) => writer.WriteNamedType(n), " & "); } WriteDirectives(node.Directives, writer); @@ -159,9 +157,7 @@ private void VisitUnionTypeDefinitionBase( writer.Write('='); writer.WriteSpace(); - writer.WriteMany(node.Types, - (n, w) => writer.WriteNamedType(n), - " | "); + writer.WriteMany(node.Types, (n, _) => writer.WriteNamedType(n), " | "); } private void VisitEnumTypeDefinition( @@ -376,9 +372,7 @@ private void VisitDirectiveDefinition( writer.Write(Keywords.On); writer.WriteSpace(); - writer.WriteMany(node.Locations, - (n, w) => writer.WriteName(n), - " | "); + writer.WriteMany(node.Locations, (n, _) => writer.WriteName(n), " | "); } private void VisitArgumentValueDefinition( diff --git a/src/HotChocolate/Language/test/Language.SyntaxTree.Tests/ObjectTypeDefinitionNodeTests.cs b/src/HotChocolate/Language/test/Language.SyntaxTree.Tests/ObjectTypeDefinitionNodeTests.cs index f7d3394c1c7..76dc8d07983 100644 --- a/src/HotChocolate/Language/test/Language.SyntaxTree.Tests/ObjectTypeDefinitionNodeTests.cs +++ b/src/HotChocolate/Language/test/Language.SyntaxTree.Tests/ObjectTypeDefinitionNodeTests.cs @@ -112,8 +112,7 @@ public void GetHashCode_With_Location() new StringValueNode("cc"), new List(0), new List(0), - new List(0) - ); + new List(0)); // act var aHash = a.GetHashCode(); diff --git a/src/HotChocolate/Language/test/Language.SyntaxTree.Tests/ObjectTypeExtensionNodeTests.cs b/src/HotChocolate/Language/test/Language.SyntaxTree.Tests/ObjectTypeExtensionNodeTests.cs index 18424b56592..e1911fd6a73 100644 --- a/src/HotChocolate/Language/test/Language.SyntaxTree.Tests/ObjectTypeExtensionNodeTests.cs +++ b/src/HotChocolate/Language/test/Language.SyntaxTree.Tests/ObjectTypeExtensionNodeTests.cs @@ -7,7 +7,6 @@ public class ObjectTypeExtensionNodeTests { [Fact] public void Equals_With_Same_Location() - { // arrange var a = new ObjectTypeExtensionNode( @@ -15,22 +14,19 @@ public void Equals_With_Same_Location() new NameNode("aa"), new List(0), new List(0), - new List(0) - ); + new List(0)); var b = new ObjectTypeExtensionNode( TestLocations.Location1, new NameNode("bb"), new List(0), new List(0), - new List(0) - ); + new List(0)); var c = new ObjectTypeExtensionNode( TestLocations.Location1, new NameNode("aa"), new List(0), new List(0), - new List(0) - ); + new List(0)); // act var aaResult = a.Equals(a); @@ -54,22 +50,19 @@ public void Equals_With_Different_Location() new NameNode("aa"), new List(0), new List(0), - new List(0) - ); + new List(0)); var b = new ObjectTypeExtensionNode( TestLocations.Location2, new NameNode("aa"), new List(0), new List(0), - new List(0) - ); + new List(0)); var c = new ObjectTypeExtensionNode( TestLocations.Location3, new NameNode("bb"), new List(0), new List(0), - new List(0) - ); + new List(0)); // act var aaResult = a.Equals(a); @@ -91,29 +84,25 @@ public void GetHashCode_With_Location() new NameNode("aa"), new List(0), new List(0), - new List(0) - ); + new List(0)); var b = new ObjectTypeExtensionNode( TestLocations.Location2, new NameNode("aa"), new List(0), new List(0), - new List(0) - ); + new List(0)); var c = new ObjectTypeExtensionNode( TestLocations.Location1, new NameNode("bb"), new List(0), new List(0), - new List(0) - ); + new List(0)); var d = new ObjectTypeExtensionNode( TestLocations.Location2, - new NameNode("cc"), + new NameNode("bb"), new List(0), new List(0), - new List(0) - ); + new List(0)); // act var aHash = a.GetHashCode(); @@ -124,7 +113,7 @@ public void GetHashCode_With_Location() // assert Assert.Equal(aHash, bHash); Assert.NotEqual(aHash, cHash); - Assert.NotEqual(cHash, dHash); + Assert.Equal(cHash, dHash); Assert.NotEqual(aHash, dHash); } }