diff --git a/src/HotChocolate/Core/src/Types/IReadOnlySchemaOptions.cs b/src/HotChocolate/Core/src/Types/IReadOnlySchemaOptions.cs
index 4c831fba6c5..2d70e9bacb8 100644
--- a/src/HotChocolate/Core/src/Types/IReadOnlySchemaOptions.cs
+++ b/src/HotChocolate/Core/src/Types/IReadOnlySchemaOptions.cs
@@ -87,10 +87,10 @@ public interface IReadOnlySchemaOptions
///
bool StripLeadingIFromInterface { get; }
-
+
///
bool EnableTrueNullability { get; }
-
+
///
bool EnableTag { get; }
}
diff --git a/src/HotChocolate/Core/src/Types/Types/Extensions/TypeExtensions.cs b/src/HotChocolate/Core/src/Types/Types/Extensions/TypeExtensions.cs
index 6fec956d0b8..c2c954c7dc2 100644
--- a/src/HotChocolate/Core/src/Types/Types/Extensions/TypeExtensions.cs
+++ b/src/HotChocolate/Core/src/Types/Types/Extensions/TypeExtensions.cs
@@ -354,7 +354,7 @@ internal static bool IsType(this IType type, TypeKind kind)
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static bool IsType(this IType type, TypeKind kind1, TypeKind kind2)
+ internal static bool IsType(this IType type, TypeKind kind1, TypeKind kind2)
{
if (type.Kind == kind1 || type.Kind == kind2)
{
diff --git a/src/HotChocolate/Core/src/Validation/DocumentValidatorContext.cs b/src/HotChocolate/Core/src/Validation/DocumentValidatorContext.cs
index a7ceb5338da..91b3e1fff39 100644
--- a/src/HotChocolate/Core/src/Validation/DocumentValidatorContext.cs
+++ b/src/HotChocolate/Core/src/Validation/DocumentValidatorContext.cs
@@ -106,6 +106,12 @@ public IOutputType NonNullString
public IDictionary ContextData { get; set; } = default!;
+ public List CurrentFieldPairs { get; } = new();
+
+ public List NextFieldPairs { get; } = new();
+
+ public HashSet ProcessedFieldPairs { get; } = new();
+
public IList RentFieldInfoList()
{
var buffer = _buffers.Peek();
@@ -159,6 +165,9 @@ public void Clear()
InputFields.Clear();
_errors.Clear();
List.Clear();
+ CurrentFieldPairs.Clear();
+ NextFieldPairs.Clear();
+ ProcessedFieldPairs.Clear();
UnexpectedErrorsDetected = false;
Count = 0;
Max = 0;
diff --git a/src/HotChocolate/Core/src/Validation/FieldInfo.cs b/src/HotChocolate/Core/src/Validation/FieldInfo.cs
index 80e770d06b1..85e73310a3d 100644
--- a/src/HotChocolate/Core/src/Validation/FieldInfo.cs
+++ b/src/HotChocolate/Core/src/Validation/FieldInfo.cs
@@ -1,3 +1,4 @@
+using System;
using HotChocolate.Language;
using HotChocolate.Types;
@@ -7,7 +8,7 @@ namespace HotChocolate.Validation;
/// The validation field info provides access to the field node and the type
/// information of the referenced field.
///
-public readonly struct FieldInfo
+public readonly struct FieldInfo : IEquatable
{
///
/// Initializes a new instance of
@@ -41,4 +42,39 @@ public FieldInfo(IType declaringType, IType type, FieldNode field)
/// Gets the field selection.
///
public FieldNode Field { get; }
-}
+
+ ///
+ /// Compares this field info to another field info.
+ ///
+ ///
+ /// The other field info.
+ ///
+ ///
+ /// true if the field infos are equal.
+ ///
+ public bool Equals(FieldInfo other)
+ => Field.Equals(other.Field) &&
+ DeclaringType.Equals(other.DeclaringType) &&
+ Type.Equals(other.Type);
+
+ ///
+ /// Compares this field info to another object.
+ ///
+ ///
+ /// The other object.
+ ///
+ ///
+ /// true if the field infos are equal.
+ ///
+ public override bool Equals(object? obj)
+ => obj is FieldInfo other && Equals(other);
+
+ ///
+ /// Returns the hash code of this instance.
+ ///
+ ///
+ /// The hash code of this instance.
+ ///
+ public override int GetHashCode()
+ => HashCode.Combine(Field, DeclaringType, Type);
+}
\ No newline at end of file
diff --git a/src/HotChocolate/Core/src/Validation/FieldInfoPair.cs b/src/HotChocolate/Core/src/Validation/FieldInfoPair.cs
new file mode 100644
index 00000000000..d51ca737651
--- /dev/null
+++ b/src/HotChocolate/Core/src/Validation/FieldInfoPair.cs
@@ -0,0 +1,67 @@
+using System;
+
+namespace HotChocolate.Validation;
+
+///
+/// Represents a pair of field infos.
+///
+public readonly struct FieldInfoPair : IEquatable
+{
+ ///
+ /// Initializes a new instance of .
+ ///
+ ///
+ /// The first field info.
+ ///
+ ///
+ /// The second field info.
+ ///
+ public FieldInfoPair(FieldInfo fieldA, FieldInfo fieldB)
+ {
+ FieldA = fieldA;
+ FieldB = fieldB;
+ }
+
+ ///
+ /// Gets the first field info.
+ ///
+ public FieldInfo FieldA { get; }
+
+ ///
+ /// Gets the second field info.
+ ///
+ public FieldInfo FieldB { get; }
+
+ ///
+ /// Compares this field info pair to another field info pair.
+ ///
+ ///
+ /// The other field info pair.
+ ///
+ ///
+ /// true if the field info pairs are equal.
+ ///
+ public bool Equals(FieldInfoPair other)
+ => FieldA.Equals(other.FieldA) && FieldB.Equals(other.FieldB);
+
+ ///
+ /// Compares this field info pair to another object.
+ ///
+ ///
+ /// The other object.
+ ///
+ ///
+ /// true if the field info pairs are equal.
+ ///
+ public override bool Equals(object? obj)
+ => obj is FieldInfoPair other && Equals(other);
+
+ ///
+ /// Returns the hash code for this field info pair.
+ ///
+ ///
+ /// The hash code for this field info pair.
+ ///
+ public override int GetHashCode()
+ => HashCode.Combine(FieldA, FieldB);
+}
\ No newline at end of file
diff --git a/src/HotChocolate/Core/src/Validation/IDocumentValidatorContext.cs b/src/HotChocolate/Core/src/Validation/IDocumentValidatorContext.cs
index db5e5503937..ec0062cc053 100644
--- a/src/HotChocolate/Core/src/Validation/IDocumentValidatorContext.cs
+++ b/src/HotChocolate/Core/src/Validation/IDocumentValidatorContext.cs
@@ -160,6 +160,21 @@ public interface IDocumentValidatorContext : ISyntaxVisitorContext
///
IDictionary ContextData { get; }
+ ///
+ /// When processing field merging this list holds the field pairs that are processed.
+ ///
+ List CurrentFieldPairs { get; }
+
+ ///
+ /// When processing field merging this list holds the field pairs that are processed next.
+ ///
+ List NextFieldPairs { get; }
+
+ ///
+ /// When processing field merging this set represents the already processed field pairs.
+ ///
+ HashSet ProcessedFieldPairs { get; }
+
///
/// Rents a list of field infos.
///
diff --git a/src/HotChocolate/Core/src/Validation/Rules/FieldVisitor.cs b/src/HotChocolate/Core/src/Validation/Rules/FieldVisitor.cs
index de582a560cb..f25120a0ebe 100644
--- a/src/HotChocolate/Core/src/Validation/Rules/FieldVisitor.cs
+++ b/src/HotChocolate/Core/src/Validation/Rules/FieldVisitor.cs
@@ -1,11 +1,11 @@
using System.Collections.Generic;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using HotChocolate.Language;
using HotChocolate.Language.Visitors;
using HotChocolate.Types;
using HotChocolate.Types.Introspection;
using HotChocolate.Utilities;
-using static System.StringComparison;
using static HotChocolate.Language.SyntaxComparer;
namespace HotChocolate.Validation.Rules;
@@ -45,9 +45,17 @@ protected override ISyntaxVisitorAction Leave(
{
if (context.FieldSets.Count > 0)
{
- foreach (var selectionSet in context.FieldSets.Keys)
+ foreach (var item in context.FieldSets)
{
- TryMergeFieldsInSet(context, context.FieldSets[selectionSet]);
+ TryMergeFieldsInSet(context, item.Value);
+ }
+
+ var next = context.NextFieldPairs;
+
+ while (next.Count > 0)
+ {
+ FillCurrentFieldPairs(context);
+ ProcessCurrentFieldPairs(context);
}
}
@@ -147,16 +155,14 @@ protected override ISyntaxVisitorAction Enter(
type.NamedType() is { Kind: TypeKind.Union } unionType &&
HasFields(node))
{
- context.ReportError(context.UnionFieldError(node, (UnionType)unionType));
+ context.ReportError(context.UnionFieldError(node, (UnionType) unionType));
return Skip;
}
- if (context.Path.TryPeek(out var parent))
+ if (context.Path.TryPeek(out var parent) &&
+ parent.Kind is SyntaxKind.OperationDefinition or SyntaxKind.Field)
{
- if (parent.Kind is SyntaxKind.OperationDefinition or SyntaxKind.Field)
- {
- context.SelectionSets.Push(node);
- }
+ context.SelectionSets.Push(node);
}
return Continue;
@@ -166,12 +172,14 @@ protected override ISyntaxVisitorAction Leave(
SelectionSetNode node,
IDocumentValidatorContext context)
{
- if (context.Path.TryPeek(out var parent))
+ if (!context.Path.TryPeek(out var parent))
{
- if (parent.Kind is SyntaxKind.OperationDefinition or SyntaxKind.Field)
- {
- context.SelectionSets.Pop();
- }
+ return Continue;
+ }
+
+ if (parent.Kind is SyntaxKind.OperationDefinition or SyntaxKind.Field)
+ {
+ context.SelectionSets.Pop();
}
return Continue;
@@ -181,9 +189,7 @@ protected override ISyntaxVisitorAction VisitChildren(
FragmentSpreadNode node,
IDocumentValidatorContext context)
{
- if (context.Fragments.TryGetValue(
- node.Name.Value,
- out var fragment) &&
+ if (context.Fragments.TryGetValue(node.Name.Value, out var fragment) &&
context.VisitedFragments.Add(fragment.Name.Value))
{
var result = Visit(fragment, node, context);
@@ -206,7 +212,7 @@ private static bool HasFields(SelectionSetNode selectionSet)
if (selection.Kind is SyntaxKind.Field)
{
- if (!IsTypeNameField(((FieldNode)selection).Name.Value))
+ if (!IsTypeNameField(((FieldNode) selection).Name.Value))
{
return true;
}
@@ -223,51 +229,62 @@ private static void TryMergeFieldsInSet(
IDocumentValidatorContext context,
IList fields)
{
- if (fields.Count == 1)
+ while (true)
{
- if (fields[0].Field.SelectionSet is { } selectionSet &&
- context.FieldSets.TryGetValue(selectionSet, out var fieldSet))
+ if (fields.Count == 1)
{
- TryMergeFieldsInSet(context, fieldSet);
+ if (fields[0].Field.SelectionSet is { } selectionSet &&
+ context.FieldSets.TryGetValue(selectionSet, out var fieldSet))
+ {
+ fields = fieldSet;
+ continue;
+ }
+ return;
}
+ break;
}
- else
+
+ for (var i = 0; i < fields.Count - 1; i++)
{
- for (var i = 0; i < fields.Count - 1; i++)
+ var fieldA = fields[i];
+
+ for (var j = i + 1; j < fields.Count; j++)
{
- var fieldA = fields[i];
+ var fieldB = fields[j];
- for (var j = i + 1; j < fields.Count; j++)
+ if (ReferenceEquals(fieldA.Field, fieldB.Field) ||
+ !fieldA.ResponseName.EqualsOrdinal(fieldB.ResponseName))
{
- var fieldB = fields[j];
+ continue;
+ }
- if (!ReferenceEquals(fieldA.Field, fieldB.Field) &&
- string.Equals(fieldA.ResponseName, fieldB.ResponseName, Ordinal))
+ if (SameResponseShape(
+ fieldA.Type.RewriteNullability(fieldA.Field.Required),
+ fieldB.Type.RewriteNullability(fieldB.Field.Required)) &&
+ SameStreamDirective(fieldA, fieldB))
+ {
+ if (!IsParentTypeAligned(fieldA, fieldB))
{
- if (SameResponseShape(
- fieldA.Type.RewriteNullability(fieldA.Field.Required),
- fieldB.Type.RewriteNullability(fieldB.Field.Required)) &&
- SameStreamDirective(fieldA, fieldB))
- {
- if (IsParentTypeAligned(fieldA, fieldB))
- {
- if (BySyntax.Equals(fieldA.Field.Name, fieldB.Field.Name) &&
- AreArgumentsIdentical(fieldA.Field, fieldB.Field))
- {
- TryMergeFieldsInSet(context, fieldA, fieldB);
- }
- else if (context.FieldTuples.Add((fieldA.Field, fieldB.Field)))
- {
- context.ReportError(
- context.FieldsAreNotMergeable(fieldA, fieldB));
- }
- }
- }
- else if (context.FieldTuples.Add((fieldA.Field, fieldB.Field)))
+ continue;
+ }
+
+ if (BySyntax.Equals(fieldA.Field.Name, fieldB.Field.Name) &&
+ AreArgumentsIdentical(fieldA.Field, fieldB.Field))
+ {
+ var pair = new FieldInfoPair(fieldA, fieldB);
+ if (context.ProcessedFieldPairs.Add(pair))
{
- context.ReportError(context.FieldsAreNotMergeable(fieldA, fieldB));
+ context.NextFieldPairs.Add(pair);
}
}
+ else if (context.FieldTuples.Add((fieldA.Field, fieldB.Field)))
+ {
+ context.ReportError(context.FieldsAreNotMergeable(fieldA, fieldB));
+ }
+ }
+ else if (context.FieldTuples.Add((fieldA.Field, fieldB.Field)))
+ {
+ context.ReportError(context.FieldsAreNotMergeable(fieldA, fieldB));
}
}
}
@@ -283,26 +300,38 @@ fieldB.Field.SelectionSet is { } b &&
context.FieldSets.TryGetValue(a, out var al) &&
context.FieldSets.TryGetValue(b, out var bl))
{
- var mergedSet = context.RentFieldInfoList();
- CopyFieldInfos(al, mergedSet);
- CopyFieldInfos(bl, mergedSet);
+ var mergedSet = Unsafe.As>(context.RentFieldInfoList());
+#if NET6_0_OR_GREATER
+ mergedSet.EnsureCapacity(al.Count + bl.Count);
+#endif
+ CopyFieldInfos(Unsafe.As>(al), mergedSet);
+ CopyFieldInfos(Unsafe.As>(bl), mergedSet);
TryMergeFieldsInSet(context, mergedSet);
}
}
- private static void CopyFieldInfos(IList from, IList to)
+ private static void CopyFieldInfos(List from, List to)
{
- for (var i = 0; i < from.Count; i++)
+#if NETSTANDARD2_0
+ foreach (var field in from)
+ {
+ to.Add(field);
+ }
+#else
+ ref var field = ref MemoryMarshal.GetReference(CollectionsMarshal.AsSpan(from));
+ ref var end = ref Unsafe.Add(ref field, from.Count);
+
+ while (Unsafe.IsAddressLessThan(ref field, ref end))
{
- to.Add(from[i]);
+ to.Add(field);
+ field = ref Unsafe.Add(ref field, 1);
}
+#endif
}
private static bool IsParentTypeAligned(FieldInfo fieldA, FieldInfo fieldB)
- {
- return ReferenceEquals(fieldA.DeclaringType, fieldB.DeclaringType) ||
+ => ReferenceEquals(fieldA.DeclaringType, fieldB.DeclaringType) ||
!fieldA.DeclaringType.IsObjectType() && !fieldB.DeclaringType.IsObjectType();
- }
private static bool AreArgumentsIdentical(FieldNode fieldA, FieldNode fieldB)
{
@@ -344,9 +373,9 @@ private static bool SameResponseShape(IType typeA, IType typeB)
{
while (!typeA.IsNamedType() && !typeB.IsNamedType())
{
- if (typeA.IsNonNullType() || typeB.IsNonNullType())
+ if (typeA.Kind is TypeKind.NonNull || typeB.Kind is TypeKind.NonNull)
{
- if (typeA.IsNullableType() || typeB.IsNullableType())
+ if (typeA.Kind is not TypeKind.NonNull || typeB.Kind is not TypeKind.NonNull)
{
return false;
}
@@ -355,9 +384,9 @@ private static bool SameResponseShape(IType typeA, IType typeB)
typeB = typeB.InnerType();
}
- if (typeA.IsListType() || typeB.IsListType())
+ if (typeA.IsType(TypeKind.List) || typeB.IsType(TypeKind.List))
{
- if (!typeA.IsListType() || !typeB.IsListType())
+ if (!typeA.IsType(TypeKind.List) || !typeB.IsType(TypeKind.List))
{
return false;
}
@@ -367,12 +396,13 @@ private static bool SameResponseShape(IType typeA, IType typeB)
}
}
- if (typeA.IsLeafType() || typeB.IsLeafType())
+ if (typeA.IsType(TypeKind.Scalar, TypeKind.Enum) || typeB.IsType(TypeKind.Scalar, TypeKind.Enum))
{
return ReferenceEquals(typeA, typeB);
}
- if (typeA.IsCompositeType() && typeB.IsCompositeType())
+ if (typeA.IsType(TypeKind.Object, TypeKind.Interface, TypeKind.Union) &&
+ typeB.IsType(TypeKind.Object, TypeKind.Interface, TypeKind.Union))
{
return true;
}
@@ -400,4 +430,57 @@ private static bool SameStreamDirective(FieldInfo fieldA, FieldInfo fieldB)
// if both fields have a stream directive we need to check if they are equal.
return streamA.StreamDirectiveEquals(streamB);
}
-}
+
+ private static void FillCurrentFieldPairs(IDocumentValidatorContext context)
+ {
+ var next = context.NextFieldPairs;
+ var current = context.CurrentFieldPairs;
+
+#if NETSTANDARD2_0
+ foreach (var pair in next)
+ {
+ current.Add(pair);
+ }
+
+ next.Clear();
+#else
+ ref var pair = ref MemoryMarshal.GetReference(CollectionsMarshal.AsSpan(next));
+ ref var end = ref Unsafe.Add(ref pair, next.Count);
+
+ current.EnsureCapacity(next.Count);
+
+ while (Unsafe.IsAddressLessThan(ref pair, ref end))
+ {
+ current.Add(pair);
+ pair = ref Unsafe.Add(ref pair, 1);
+ }
+
+ next.Clear();
+#endif
+ }
+
+ private static void ProcessCurrentFieldPairs(IDocumentValidatorContext context)
+ {
+ var current = context.CurrentFieldPairs;
+
+#if NETSTANDARD2_0
+ foreach (var pair in current)
+ {
+ TryMergeFieldsInSet(context, pair.FieldA, pair.FieldB);
+ }
+
+ current.Clear();
+#else
+ ref var pair = ref MemoryMarshal.GetReference(CollectionsMarshal.AsSpan(current));
+ ref var end = ref Unsafe.Add(ref pair, current.Count);
+
+ while (Unsafe.IsAddressLessThan(ref pair, ref end))
+ {
+ TryMergeFieldsInSet(context, pair.FieldA, pair.FieldB);
+ pair = ref Unsafe.Add(ref pair, 1);
+ }
+
+ current.Clear();
+#endif
+ }
+}
\ No newline at end of file
diff --git a/src/HotChocolate/Core/test/Execution.Tests/Processing/OperationCompilerTests.cs b/src/HotChocolate/Core/test/Execution.Tests/Processing/OperationCompilerTests.cs
index 08f74024dc8..214ed137f93 100644
--- a/src/HotChocolate/Core/test/Execution.Tests/Processing/OperationCompilerTests.cs
+++ b/src/HotChocolate/Core/test/Execution.Tests/Processing/OperationCompilerTests.cs
@@ -324,7 +324,7 @@ public void Field_Is_Visible_When_One_Selection_Is_Visible_1()
.Create();
var document = Utf8GraphQLParser.Parse(
- @"query foo($v: Boolean){
+ @"query foo($v: Boolean!){
hero(episode: EMPIRE) {
name
... abc @include(if: $v)
@@ -363,7 +363,7 @@ public void Field_Is_Visible_When_One_Selection_Is_Visible_2()
.Create();
var document = Utf8GraphQLParser.Parse(
- @"query foo($v: Boolean){
+ @"query foo($v: Boolean!){
hero(episode: EMPIRE) {
name @include(if: $v)
... abc
@@ -403,7 +403,7 @@ public void Field_Is_Visible_When_One_Selection_Is_Visible_3()
.Create();
var document = Utf8GraphQLParser.Parse(
- @"query foo($v: Boolean, $q: Boolean){
+ @"query foo($v: Boolean!, $q: Boolean!){
hero(episode: EMPIRE) {
name @include(if: $v)
... abc @include(if: $q)
@@ -442,7 +442,7 @@ public void Field_Is_Visible_When_One_Selection_Is_Visible_4()
.Create();
var document = Utf8GraphQLParser.Parse(
- @"query foo($v: Boolean){
+ @"query foo($v: Boolean!){
hero(episode: EMPIRE) {
name @include(if: $v)
... abc
@@ -487,7 +487,7 @@ public void Object_Field_Visibility_Is_Correctly_Inherited()
.Create();
var document = Utf8GraphQLParser.Parse(
- @"query foo($v: Boolean) {
+ @"query foo($v: Boolean!) {
hero(episode: EMPIRE) @include(if: $v) {
name
}
@@ -608,7 +608,7 @@ public void Object_Field_Visibility_Is_Correctly_Inherited_2()
.Create();
var document = Utf8GraphQLParser.Parse(
- @"query foo($v: Boolean, $q: Boolean) {
+ @"query foo($v: Boolean!, $q: Boolean!) {
hero(episode: EMPIRE) @include(if: $v) {
name @include(if: $q)
}
@@ -653,7 +653,7 @@ public void Object_Field_Visibility_Is_Correctly_Inherited_3()
.Create();
var document = Utf8GraphQLParser.Parse(
- @"query foo($v: Boolean, $q: Boolean) {
+ @"query foo($v: Boolean!, $q: Boolean!) {
hero(episode: EMPIRE) @include(if: $v) {
name @include(if: $q)
}
@@ -1162,14 +1162,14 @@ private static void MatchSnapshot(DocumentNode original, IOperation compiled)
public class Foo
{
- public Bar Bar => new Bar();
+ public Bar Bar => new();
}
public class Bar
{
public string Text => "Bar";
- public Baz Baz => new Baz();
+ public Baz Baz => new();
}
public class Baz
diff --git a/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Field_Is_Visible_When_One_Selection_Is_Visible_1.snap b/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Field_Is_Visible_When_One_Selection_Is_Visible_1.snap
index 6cd0f2b738d..8d36b29707a 100644
--- a/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Field_Is_Visible_When_One_Selection_Is_Visible_1.snap
+++ b/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Field_Is_Visible_When_One_Selection_Is_Visible_1.snap
@@ -1,4 +1,4 @@
-query foo($v: Boolean) {
+query foo($v: Boolean!) {
hero(episode: EMPIRE) {
name
... abc @include(if: $v)
@@ -11,7 +11,7 @@ fragment abc on Droid {
---------------------------------------------------------
-query foo($v: Boolean) @includeCondition(flag: 2) {
+query foo($v: Boolean!) @includeCondition(flag: 2) {
... on Query {
hero(episode: EMPIRE) @__execute(id: 0, kind: PURE, type: COMPOSITE) {
... on Human {
diff --git a/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Field_Is_Visible_When_One_Selection_Is_Visible_2.snap b/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Field_Is_Visible_When_One_Selection_Is_Visible_2.snap
index df34c2c38b4..2c7965c4d7e 100644
--- a/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Field_Is_Visible_When_One_Selection_Is_Visible_2.snap
+++ b/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Field_Is_Visible_When_One_Selection_Is_Visible_2.snap
@@ -1,4 +1,4 @@
-query foo($v: Boolean) {
+query foo($v: Boolean!) {
hero(episode: EMPIRE) {
name @include(if: $v)
... abc
@@ -11,7 +11,7 @@ fragment abc on Droid {
---------------------------------------------------------
-query foo($v: Boolean) @includeCondition(flag: 2) {
+query foo($v: Boolean!) @includeCondition(flag: 2) {
... on Query {
hero(episode: EMPIRE) @__execute(id: 0, kind: PURE, type: COMPOSITE) {
... on Human {
diff --git a/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Field_Is_Visible_When_One_Selection_Is_Visible_3.snap b/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Field_Is_Visible_When_One_Selection_Is_Visible_3.snap
index 7dcdf88e876..b0e88db9614 100644
--- a/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Field_Is_Visible_When_One_Selection_Is_Visible_3.snap
+++ b/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Field_Is_Visible_When_One_Selection_Is_Visible_3.snap
@@ -1,4 +1,4 @@
-query foo($v: Boolean, $q: Boolean) {
+query foo($v: Boolean!, $q: Boolean!) {
hero(episode: EMPIRE) {
name @include(if: $v)
... abc @include(if: $q)
@@ -11,7 +11,7 @@ fragment abc on Droid {
---------------------------------------------------------
-query foo($v: Boolean, $q: Boolean) @includeCondition(flag: 2) @includeCondition(flag: 3) {
+query foo($v: Boolean!, $q: Boolean!) @includeCondition(flag: 2) @includeCondition(flag: 3) {
... on Query {
hero(episode: EMPIRE) @__execute(id: 0, kind: PURE, type: COMPOSITE) {
... on Human {
diff --git a/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Field_Is_Visible_When_One_Selection_Is_Visible_4.snap b/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Field_Is_Visible_When_One_Selection_Is_Visible_4.snap
index 6411fc8392b..9a58cd5a551 100644
--- a/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Field_Is_Visible_When_One_Selection_Is_Visible_4.snap
+++ b/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Field_Is_Visible_When_One_Selection_Is_Visible_4.snap
@@ -1,4 +1,4 @@
-query foo($v: Boolean) {
+query foo($v: Boolean!) {
hero(episode: EMPIRE) {
name @include(if: $v)
... abc
@@ -14,7 +14,7 @@ fragment abc on Droid {
---------------------------------------------------------
-query foo($v: Boolean) @includeCondition(flag: 2) {
+query foo($v: Boolean!) @includeCondition(flag: 2) {
... on Query {
hero(episode: EMPIRE) @__execute(id: 0, kind: PURE, type: COMPOSITE) {
... on Human {
diff --git a/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Object_Field_Visibility_Is_Correctly_Inherited.snap b/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Object_Field_Visibility_Is_Correctly_Inherited.snap
index 79070ef0441..d491047b689 100644
--- a/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Object_Field_Visibility_Is_Correctly_Inherited.snap
+++ b/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Object_Field_Visibility_Is_Correctly_Inherited.snap
@@ -1,4 +1,4 @@
-query foo($v: Boolean) {
+query foo($v: Boolean!) {
hero(episode: EMPIRE) @include(if: $v) {
name
}
@@ -16,7 +16,7 @@
---------------------------------------------------------
-query foo($v: Boolean) @includeCondition(flag: 2) {
+query foo($v: Boolean!) @includeCondition(flag: 2) {
... on Query {
hero(episode: EMPIRE) @__execute(id: 0, kind: PURE, type: COMPOSITE) {
... on Human {
diff --git a/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Object_Field_Visibility_Is_Correctly_Inherited_2.snap b/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Object_Field_Visibility_Is_Correctly_Inherited_2.snap
index 17f1fc0ee4c..6ffba23a92a 100644
--- a/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Object_Field_Visibility_Is_Correctly_Inherited_2.snap
+++ b/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Object_Field_Visibility_Is_Correctly_Inherited_2.snap
@@ -1,4 +1,4 @@
-query foo($v: Boolean, $q: Boolean) {
+query foo($v: Boolean!, $q: Boolean!) {
hero(episode: EMPIRE) @include(if: $v) {
name @include(if: $q)
}
@@ -16,7 +16,7 @@
---------------------------------------------------------
-query foo($v: Boolean, $q: Boolean) @includeCondition(flag: 2) @includeCondition(flag: 3) {
+query foo($v: Boolean!, $q: Boolean!) @includeCondition(flag: 2) @includeCondition(flag: 3) {
... on Query {
hero(episode: EMPIRE) @__execute(id: 0, kind: PURE, type: COMPOSITE) {
... on Human {
diff --git a/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Object_Field_Visibility_Is_Correctly_Inherited_3.snap b/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Object_Field_Visibility_Is_Correctly_Inherited_3.snap
index f878e77ddcd..8702b4b0fae 100644
--- a/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Object_Field_Visibility_Is_Correctly_Inherited_3.snap
+++ b/src/HotChocolate/Core/test/Execution.Tests/Processing/__snapshots__/OperationCompilerTests.Object_Field_Visibility_Is_Correctly_Inherited_3.snap
@@ -1,4 +1,4 @@
-query foo($v: Boolean, $q: Boolean) {
+query foo($v: Boolean!, $q: Boolean!) {
hero(episode: EMPIRE) @include(if: $v) {
name @include(if: $q)
}
@@ -6,7 +6,7 @@
---------------------------------------------------------
-query foo($v: Boolean, $q: Boolean) @includeCondition(flag: 2) @includeCondition(flag: 3) {
+query foo($v: Boolean!, $q: Boolean!) @includeCondition(flag: 2) @includeCondition(flag: 3) {
... on Query {
hero(episode: EMPIRE) @conditional @__execute(id: 0, kind: PURE, type: COMPOSITE) {
... on Human {
diff --git a/src/HotChocolate/Core/test/Validation.Tests/FieldSelectionMergingRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/FieldSelectionMergingRuleTests.cs
index ef54cfdbdb4..e4eb409ba68 100644
--- a/src/HotChocolate/Core/test/Validation.Tests/FieldSelectionMergingRuleTests.cs
+++ b/src/HotChocolate/Core/test/Validation.Tests/FieldSelectionMergingRuleTests.cs
@@ -823,31 +823,32 @@ public void ReportsDeepConflictToNearestCommonAncestor()
[Fact]
public void ReportsDeepConflictToNearestCommonAncestorInFragments()
{
- ExpectErrors(@"
- {
- f1 {
- ...F
+ ExpectErrors(
+ """
+ {
+ f1 {
+ ...F
+ }
+ f1 {
+ ...F
+ }
+ }
+ fragment F on Query {
+ f2 {
+ f3 {
+ x: a
}
- f1 {
- ...F
+ f3 {
+ x: b
}
}
- fragment F on Query {
- f2 {
- f3 {
- x: a
- }
- f3 {
- x: b
- }
- },
- f2 {
- f3 {
- y
- }
+ f2 {
+ f3 {
+ y
}
}
- ");
+ }
+ """);
}
[Fact]
diff --git a/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/FieldSelectionMergingRuleTests.ReportsDeepConflictToNearestCommonAncestorInFragments.snap b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/FieldSelectionMergingRuleTests.ReportsDeepConflictToNearestCommonAncestorInFragments.snap
index d412406b5b8..f5fb0b36f16 100644
--- a/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/FieldSelectionMergingRuleTests.ReportsDeepConflictToNearestCommonAncestorInFragments.snap
+++ b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/FieldSelectionMergingRuleTests.ReportsDeepConflictToNearestCommonAncestorInFragments.snap
@@ -5,12 +5,12 @@
"Path": null,
"Locations": [
{
- "Line": 13,
- "Column": 29
+ "Line": 12,
+ "Column": 13
},
{
- "Line": 16,
- "Column": 29
+ "Line": 15,
+ "Column": 13
}
],
"Extensions": {
@@ -30,10 +30,10 @@
"Alias": {
"Kind": "Name",
"Location": {
- "Start": 397,
- "End": 399,
- "Line": 16,
- "Column": 29
+ "Start": 156,
+ "End": 158,
+ "Line": 15,
+ "Column": 13
},
"Value": "x"
},
@@ -41,18 +41,18 @@
"Required": null,
"SelectionSet": null,
"Location": {
- "Start": 397,
- "End": 427,
- "Line": 16,
- "Column": 29
+ "Start": 156,
+ "End": 170,
+ "Line": 15,
+ "Column": 13
},
"Name": {
"Kind": "Name",
"Location": {
- "Start": 400,
- "End": 427,
- "Line": 16,
- "Column": 32
+ "Start": 159,
+ "End": 170,
+ "Line": 15,
+ "Column": 16
},
"Value": "b"
},
@@ -65,12 +65,12 @@
"Path": null,
"Locations": [
{
- "Line": 16,
- "Column": 29
+ "Line": 15,
+ "Column": 13
},
{
- "Line": 13,
- "Column": 29
+ "Line": 12,
+ "Column": 13
}
],
"Extensions": {
@@ -90,10 +90,10 @@
"Alias": {
"Kind": "Name",
"Location": {
- "Start": 309,
- "End": 311,
- "Line": 13,
- "Column": 29
+ "Start": 116,
+ "End": 118,
+ "Line": 12,
+ "Column": 13
},
"Value": "x"
},
@@ -101,18 +101,18 @@
"Required": null,
"SelectionSet": null,
"Location": {
- "Start": 309,
- "End": 339,
- "Line": 13,
- "Column": 29
+ "Start": 116,
+ "End": 130,
+ "Line": 12,
+ "Column": 13
},
"Name": {
"Kind": "Name",
"Location": {
- "Start": 312,
- "End": 339,
- "Line": 13,
- "Column": 32
+ "Start": 119,
+ "End": 130,
+ "Line": 12,
+ "Column": 16
},
"Value": "a"
},