Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ public bool Equals(ExtendedTypeReference? x, ExtendedTypeReference? y)
return false;
}

if (x.Context != y.Context
&& x.Context != TypeContext.None
&& y.Context != TypeContext.None)
if (x.Context != y.Context)
{
return false;
}
Expand Down Expand Up @@ -54,10 +52,11 @@ public int GetHashCode(ExtendedTypeReference obj)
unchecked
{
var hashCode = GetHashCode(obj.Type);
hashCode = (hashCode * 397) ^ obj.Context.GetHashCode();

if (obj.Scope is not null)
{
hashCode ^= obj.GetHashCode() * 397;
hashCode = (hashCode * 397) ^ StringComparer.Ordinal.GetHashCode(obj.Scope);
}

return hashCode;
Expand Down
32 changes: 28 additions & 4 deletions src/HotChocolate/Core/src/Types/Configuration/TypeRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public bool IsRegistered(TypeReference typeReference)
}

if (typeReference is ExtendedTypeReference extendedTypeRef
&& _runtimeTypeRefs.TryGetValue(extendedTypeRef, out var reference))
&& TryGetRuntimeTypeRefInternal(extendedTypeRef, out var reference))
{
return _typeRegister.ContainsKey(reference);
}
Expand All @@ -61,7 +61,7 @@ public bool TryGetType(
ArgumentNullException.ThrowIfNull(typeRef);

if (typeRef is ExtendedTypeReference clrTypeRef
&& _runtimeTypeRefs.TryGetValue(clrTypeRef, out var internalRef))
&& TryGetRuntimeTypeRefInternal(clrTypeRef, out var internalRef))
{
typeRef = internalRef;
}
Expand All @@ -75,14 +75,20 @@ public bool TryGetTypeRef(
{
ArgumentNullException.ThrowIfNull(runtimeTypeRef);

return _runtimeTypeRefs.TryGetValue(runtimeTypeRef, out typeRef);
return TryGetRuntimeTypeRefInternal(runtimeTypeRef, out typeRef);
}

public bool IsExplicitBinding(ExtendedTypeReference runtimeTypeRef)
{
ArgumentNullException.ThrowIfNull(runtimeTypeRef);

return _explicitRuntimeTypeRefs.Contains(runtimeTypeRef);
if (_explicitRuntimeTypeRefs.Contains(runtimeTypeRef))
{
return true;
}

return runtimeTypeRef.Context is not TypeContext.None
&& _explicitRuntimeTypeRefs.Contains(runtimeTypeRef.WithContext());
}

public bool TryGetTypeRef(
Expand All @@ -102,6 +108,24 @@ public bool TryGetTypeRef(

public IEnumerable<TypeReference> GetTypeRefs() => _runtimeTypeRefs.Values;

private bool TryGetRuntimeTypeRefInternal(
ExtendedTypeReference runtimeTypeRef,
[NotNullWhen(true)] out TypeReference? typeRef)
{
if (_runtimeTypeRefs.TryGetValue(runtimeTypeRef, out typeRef))
{
return true;
}

if (runtimeTypeRef.Context is not TypeContext.None)
{
return _runtimeTypeRefs.TryGetValue(runtimeTypeRef.WithContext(), out typeRef);
}

typeRef = null;
return false;
}

public void TryRegister(
ExtendedTypeReference runtimeTypeRef,
TypeReference typeRef,
Expand Down
89 changes: 89 additions & 0 deletions src/HotChocolate/Core/test/Types.Tests/Regressions/Issue_7609.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
using Microsoft.Extensions.DependencyInjection;
using HotChocolate.Execution;
using HotChocolate.Types;

namespace HotChocolate.Regressions;

public class Issue_7609
{
[Fact]
public async Task Query_Only_Reusing_Dtos_Works()
{
var schema = await new ServiceCollection()
.AddGraphQLServer()
.AddQueryType<Issue7609Query>()
.AddType<Issue7609Boat>()
.AddType<Issue7609Car>()
.BuildSchemaAsync();

Assert.NotNull(schema);
}

[Fact]
public async Task Interface_Output_And_OneOf_Input_Reusing_Dtos_Does_Not_Throw()
{
// Repro from #7609: reuse the same DTOs for interface output and oneOf input.
var schema = await new ServiceCollection()
.AddGraphQLServer()
.AddQueryType<Issue7609Query>()
.AddMutationType<Issue7609Mutation>()
.AddType<Issue7609Boat>()
.AddType<Issue7609Car>()
.AddType<Issue7609BoatInput>()
.AddType<Issue7609CarInput>()
.BuildSchemaAsync();

Assert.NotNull(schema);
}

public class Issue7609Query
{
public Issue7609BaseThing? GetThing(string? name) => name switch
{
"Car" => new Issue7609Car { Name = name, Make = "Toyota" },
"Boat" => new Issue7609Boat { Name = name, Make = "Yamaha", Length = 10 },
_ => null
};
}

[InterfaceType]
public interface Issue7609BaseThing
{
string? Name { get; }
}

[ObjectType]
public class Issue7609Car : Issue7609BaseThing
{
public required string Name { get; set; }

public required string Make { get; set; }
}

[ObjectType]
public class Issue7609Boat : Issue7609BaseThing
{
public required string Name { get; set; }

public required string Make { get; set; }

public int Length { get; set; }
}

public class Issue7609Mutation
{
public bool AddThingy(Issue7609CouldBeInputThingInput thing) => thing is not null;
}

[OneOf]
public class Issue7609CouldBeInputThingInput
{
public Issue7609Boat? Boat { get; set; }

public Issue7609Car? Car { get; set; }
}

public class Issue7609BoatInput : InputObjectType<Issue7609Boat>;

public class Issue7609CarInput : InputObjectType<Issue7609Car>;
}
Loading