@@ -14,6 +14,7 @@ namespace HotChocolate;
14
14
internal sealed class SemanticNonNullTypeInterceptor : TypeInterceptor
15
15
{
16
16
private ITypeInspector _typeInspector = null ! ;
17
+ private ObjectTypeDefinition ? _mutationDef ;
17
18
18
19
public override bool IsEnabled ( IDescriptorContext context )
19
20
=> context . Options . EnableSemanticNonNull ;
@@ -28,52 +29,16 @@ internal override void InitializeContext(
28
29
_typeInspector = context . TypeInspector ;
29
30
}
30
31
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 ,
41
33
OperationType operationType )
42
34
{
43
- if ( operationType == OperationType . Mutation )
35
+ if ( operationType is OperationType . Mutation )
44
36
{
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 ;
73
38
}
74
39
}
75
40
76
- public override void OnAfterCompleteName ( ITypeCompletionContext completionContext , DefinitionBase definition )
41
+ public override void OnBeforeCompleteType ( ITypeCompletionContext completionContext , DefinitionBase definition )
77
42
{
78
43
if ( completionContext . IsIntrospectionType )
79
44
{
@@ -87,6 +52,14 @@ public override void OnAfterCompleteName(ITypeCompletionContext completionContex
87
52
return ;
88
53
}
89
54
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
+
90
63
foreach ( var field in objectDef . Fields )
91
64
{
92
65
if ( field . IsIntrospectionField )
0 commit comments