Skip to content

Commit 50f7047

Browse files
Fix @semanticNonNull on mutation types (#8239)
1 parent 8abf12b commit 50f7047

File tree

3 files changed

+22
-41
lines changed

3 files changed

+22
-41
lines changed

src/HotChocolate/Core/src/Types/SemanticNonNullTypeInterceptor.cs

Lines changed: 13 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ namespace HotChocolate;
1414
internal sealed class SemanticNonNullTypeInterceptor : TypeInterceptor
1515
{
1616
private ITypeInspector _typeInspector = null!;
17+
private ObjectTypeDefinition? _mutationDef;
1718

1819
public override bool IsEnabled(IDescriptorContext context)
1920
=> context.Options.EnableSemanticNonNull;
@@ -28,52 +29,16 @@ internal override void InitializeContext(
2829
_typeInspector = context.TypeInspector;
2930
}
3031

31-
/// <summary>
32-
/// After the root types have been resolved, we go through all the fields of the mutation type
33-
/// and undo semantic non-nullability. This is because mutations can be chained and we want to retain
34-
/// the null-bubbling so execution is aborted once one non-null mutation field produces an error.
35-
/// We have to do this in a different hook because the mutation type is not yet fully resolved in the
36-
/// <see cref="OnAfterCompleteName"/> hook.
37-
/// </summary>
38-
public override void OnAfterResolveRootType(
39-
ITypeCompletionContext completionContext,
40-
ObjectTypeDefinition definition,
32+
public override void OnAfterResolveRootType(ITypeCompletionContext completionContext, ObjectTypeDefinition definition,
4133
OperationType operationType)
4234
{
43-
if (operationType == OperationType.Mutation)
35+
if (operationType is OperationType.Mutation)
4436
{
45-
foreach (var field in definition.Fields)
46-
{
47-
if (field.IsIntrospectionField)
48-
{
49-
continue;
50-
}
51-
52-
if (!field.HasDirectives)
53-
{
54-
continue;
55-
}
56-
57-
var semanticNonNullDirective =
58-
field.Directives.FirstOrDefault(d => d.Value is SemanticNonNullDirective);
59-
60-
if (semanticNonNullDirective is not null)
61-
{
62-
field.Directives.Remove(semanticNonNullDirective);
63-
}
64-
65-
var semanticNonNullFormatterDefinition =
66-
field.FormatterDefinitions.FirstOrDefault(fd => fd.Key == WellKnownMiddleware.SemanticNonNull);
67-
68-
if (semanticNonNullFormatterDefinition is not null)
69-
{
70-
field.FormatterDefinitions.Remove(semanticNonNullFormatterDefinition);
71-
}
72-
}
37+
_mutationDef = definition;
7338
}
7439
}
7540

76-
public override void OnAfterCompleteName(ITypeCompletionContext completionContext, DefinitionBase definition)
41+
public override void OnBeforeCompleteType(ITypeCompletionContext completionContext, DefinitionBase definition)
7742
{
7843
if (completionContext.IsIntrospectionType)
7944
{
@@ -87,6 +52,14 @@ public override void OnAfterCompleteName(ITypeCompletionContext completionContex
8752
return;
8853
}
8954

55+
// We undo semantic non-nullability on each mutation field, since mutations can be chained
56+
// and we want to retain the null-bubbling so execution is aborted if a non-null mutation field
57+
// produces an error.
58+
if (objectDef == _mutationDef)
59+
{
60+
return;
61+
}
62+
9063
foreach (var field in objectDef.Fields)
9164
{
9265
if (field.IsIntrospectionField)

src/HotChocolate/Core/test/Types.Tests/SemanticNonNullTests.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ public async Task MutationConventions()
3535
o.StrictValidation = false;
3636
o.EnableSemanticNonNull = true;
3737
})
38-
.AddMutationConventions()
38+
.AddMutationConventions(applyToAllMutations: false)
3939
.AddMutationType<Mutation>()
40+
.AddTypeExtension<MutationExtensions>()
4041
.BuildSchemaAsync()
4142
.MatchSnapshotAsync();
4243
}
@@ -319,6 +320,12 @@ public class Mutation
319320
public bool DoSomething() => true;
320321
}
321322

323+
[ExtendObjectType<Mutation>]
324+
public class MutationExtensions
325+
{
326+
public bool DoSomethingElse() => true;
327+
}
328+
322329
public class MyException : Exception;
323330

324331
public class QueryWithPagination

src/HotChocolate/Core/test/Types.Tests/__snapshots__/SemanticNonNullTests.MutationConventions.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ type DoSomethingPayload {
1313

1414
type Mutation {
1515
doSomething: DoSomethingPayload!
16+
doSomethingElse: Boolean!
1617
}
1718

1819
type MyError implements Error {

0 commit comments

Comments
 (0)