Skip to content

Commit

Permalink
Implemented equality for ObjectTypeExtensionNode (#4962)
Browse files Browse the repository at this point in the history
  • Loading branch information
vhatsura authored Apr 14, 2022
1 parent 3ac80ad commit f3fed88
Show file tree
Hide file tree
Showing 5 changed files with 246 additions and 45 deletions.
Original file line number Diff line number Diff line change
@@ -1,23 +1,51 @@
using System;
using System.Collections.Generic;
using HotChocolate.Language.Utilities;

namespace HotChocolate.Language;

/// <summary>
/// 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.
/// </summary>
public sealed class ObjectTypeExtensionNode
: ComplexTypeDefinitionNodeBase
, ITypeExtensionNode
, IEquatable<ObjectTypeExtensionNode>
{
/// <summary>
/// Initializes a new instance of <see cref="ObjectTypeExtensionNode"/>.
/// </summary>
/// <param name="location">
/// The location of the syntax node within the original source text.
/// </param>
/// <param name="name">
/// The name that this syntax node holds.
/// </param>
/// <param name="directives">
/// The directives that are annotated to this syntax node.
/// </param>
/// <param name="interfaces">
/// The interfaces that this type implements.
/// </param>
/// <param name="fields">
/// The fields that this type exposes.
/// </param>
public ObjectTypeExtensionNode(
Location? location,
NameNode name,
IReadOnlyList<DirectiveNode> directives,
IReadOnlyList<NamedTypeNode> interfaces,
IReadOnlyList<FieldDefinitionNode> fields)
: base(location, name, directives, interfaces, fields)
{ }
{
}

/// <inheritdoc />
public override SyntaxKind Kind => SyntaxKind.ObjectTypeExtension;

/// <inheritdoc />
public override IEnumerable<ISyntaxNode> GetNodes()
{
yield return Name;
Expand Down Expand Up @@ -59,41 +87,102 @@ public override IEnumerable<ISyntaxNode> GetNodes()
/// </returns>
public override string ToString(bool indented) => SyntaxPrinter.Print(this, indented);

/// <summary>
/// Creates a new node from the current instance and replaces the
/// <see cref="Location"/> with <paramref name="location"/>.
/// </summary>
/// <param name="location">
/// The location that shall be used to replace the current location.
/// </param>
/// <returns>
/// Returns the new node with the new <paramref name="location"/>
/// </returns>
public ObjectTypeExtensionNode WithLocation(Location? location)
{
return new ObjectTypeExtensionNode(
location, Name, Directives,
Interfaces, Fields);
}
=> new(location, Name, Directives, Interfaces, Fields);

/// <summary>
/// Creates a new node from the current instance and replaces the
/// <see cref="NameNode"/> with <paramref name="name"/>
/// </summary>
/// <param name="name">
/// The name that shall be used to replace the current name.
/// </param>
/// <returns>
/// Returns the new node with the new <paramref name="name"/>
/// </returns>
public ObjectTypeExtensionNode WithName(NameNode name)
{
return new ObjectTypeExtensionNode(
Location, name, Directives,
Interfaces, Fields);
}
=> new(Location, name, Directives, Interfaces, Fields);

public ObjectTypeExtensionNode WithDirectives(
IReadOnlyList<DirectiveNode> directives)
{
return new ObjectTypeExtensionNode(
Location, Name, directives,
Interfaces, Fields);
}
/// <summary>
/// Creates a new node from the current instance and replaces the
/// <see cref="NamedSyntaxNode.Directives"/> with <paramref name="directives"/>
/// </summary>
/// <param name="directives">
/// The directives that shall be used to replace the current directives.
/// </param>
/// <returns>
/// Returns the new node with the new <paramref name="directives"/>
/// </returns>
public ObjectTypeExtensionNode WithDirectives(IReadOnlyList<DirectiveNode> directives)
=> new(Location, Name, directives, Interfaces, Fields);

public ObjectTypeExtensionNode WithInterfaces(
IReadOnlyList<NamedTypeNode> interfaces)
{
return new ObjectTypeExtensionNode(
Location, Name, Directives,
interfaces, Fields);
}
/// <summary>
/// Creates a new node from the current instance and replaces the
/// <see cref="ComplexTypeDefinitionNodeBase.Interfaces"/> with <paramref name="interfaces"/>
/// </summary>
/// <param name="interfaces">
/// The interfaces that shall be used to replace the current interfaces.
/// </param>
/// <returns>
/// Returns the new node with the new <paramref name="interfaces"/>
/// </returns>
public ObjectTypeExtensionNode WithInterfaces(IReadOnlyList<NamedTypeNode> interfaces)
=> new(Location, Name, Directives, interfaces, Fields);

public ObjectTypeExtensionNode WithFields(
IReadOnlyList<FieldDefinitionNode> fields)
{
return new ObjectTypeExtensionNode(
Location, Name, Directives,
Interfaces, fields);
}
/// <summary>
/// Creates a new node from the current instance and replaces the
/// <see cref="ComplexTypeDefinitionNodeBase.Fields"/> with <paramref name="fields"/>
/// </summary>
/// <param name="fields">
/// The fields that shall be used to replace the current fields.
/// </param>
/// <returns>
/// Returns the new node with the new <paramref name="fields"/>
/// </returns>
public ObjectTypeExtensionNode WithFields(IReadOnlyList<FieldDefinitionNode> fields)
=> new(Location, Name, Directives, Interfaces, fields);

/// <inheritdoc />
public bool Equals(ObjectTypeExtensionNode? other) => base.Equals(other);

/// <inheritdoc />
public override bool Equals(object? obj)
=> ReferenceEquals(this, obj) ||
(obj is ObjectTypeExtensionNode other && Equals(other));

/// <inheritdoc />
public override int GetHashCode()
=> HashCode.Combine(base.GetHashCode(), Kind);

/// <summary>
/// The equal operator.
/// </summary>
/// <param name="left">The left parameter</param>
/// <param name="right">The right parameter</param>
/// <returns>
/// <c>true</c> if <paramref name="left"/> and <paramref name="right"/> are equal.
/// </returns>
public static bool operator ==(ObjectTypeExtensionNode? left, ObjectTypeExtensionNode? right)
=> Equals(left, right);

/// <summary>
/// The not equal operator.
/// </summary>
/// <param name="left">The left parameter</param>
/// <param name="right">The right parameter</param>
/// <returns>
/// <c>true</c> if <paramref name="left"/> and <paramref name="right"/> are not equal.
/// </returns>
public static bool operator !=(ObjectTypeExtensionNode? left, ObjectTypeExtensionNode? right)
=> !Equals(left, right);
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ private void VisitObjectTypeExtension(ObjectTypeExtensionNode node, ISyntaxWrite
}

private void VisitObjectTypeDefinitionBase(
ObjectTypeDefinitionNodeBase node,
ComplexTypeDefinitionNodeBase node,
ISyntaxWriter writer)
{
writer.Write(Keywords.Type);
Expand All @@ -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);
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,7 @@ public void GetHashCode_With_Location()
new StringValueNode("cc"),
new List<DirectiveNode>(0),
new List<NamedTypeNode>(0),
new List<FieldDefinitionNode>(0)
);
new List<FieldDefinitionNode>(0));

// act
var aHash = a.GetHashCode();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
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<DirectiveNode>(0),
new List<NamedTypeNode>(0),
new List<FieldDefinitionNode>(0));
var b = new ObjectTypeExtensionNode(
TestLocations.Location1,
new NameNode("bb"),
new List<DirectiveNode>(0),
new List<NamedTypeNode>(0),
new List<FieldDefinitionNode>(0));
var c = new ObjectTypeExtensionNode(
TestLocations.Location1,
new NameNode("aa"),
new List<DirectiveNode>(0),
new List<NamedTypeNode>(0),
new List<FieldDefinitionNode>(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<DirectiveNode>(0),
new List<NamedTypeNode>(0),
new List<FieldDefinitionNode>(0));
var b = new ObjectTypeExtensionNode(
TestLocations.Location2,
new NameNode("aa"),
new List<DirectiveNode>(0),
new List<NamedTypeNode>(0),
new List<FieldDefinitionNode>(0));
var c = new ObjectTypeExtensionNode(
TestLocations.Location3,
new NameNode("bb"),
new List<DirectiveNode>(0),
new List<NamedTypeNode>(0),
new List<FieldDefinitionNode>(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<DirectiveNode>(0),
new List<NamedTypeNode>(0),
new List<FieldDefinitionNode>(0));
var b = new ObjectTypeExtensionNode(
TestLocations.Location2,
new NameNode("aa"),
new List<DirectiveNode>(0),
new List<NamedTypeNode>(0),
new List<FieldDefinitionNode>(0));
var c = new ObjectTypeExtensionNode(
TestLocations.Location1,
new NameNode("bb"),
new List<DirectiveNode>(0),
new List<NamedTypeNode>(0),
new List<FieldDefinitionNode>(0));
var d = new ObjectTypeExtensionNode(
TestLocations.Location2,
new NameNode("bb"),
new List<DirectiveNode>(0),
new List<NamedTypeNode>(0),
new List<FieldDefinitionNode>(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.Equal(cHash, dHash);
Assert.NotEqual(aHash, dHash);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

0 comments on commit f3fed88

Please sign in to comment.