Skip to content

Commit b9aaab4

Browse files
tobias-tenglermichaelstaib
authored andcommitted
@semanticNonNull support (#7681)
1 parent 341b113 commit b9aaab4

File tree

60 files changed

+2921
-128
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+2921
-128
lines changed

src/HotChocolate/Core/src/Abstractions/ErrorCodes.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public static class Execution
4949
public const string OneSlicingArgumentRequired = "HC0082";
5050

5151
public const string NonNullViolation = "HC0018";
52+
public const string SemanticNonNullViolation = "HC0088";
5253
public const string MustBeInputType = "HC0017";
5354
public const string InvalidType = "HC0016";
5455
public const string QueryNotFound = "HC0015";

src/HotChocolate/Core/src/Abstractions/WellKnownDirectives.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,14 @@ public static class WellKnownDirectives
6969
/// The name of the @tag argument name.
7070
/// </summary>
7171
public const string Name = "name";
72+
73+
/// <summary>
74+
/// The name of the @semanticNonNull directive.
75+
/// </summary>
76+
public const string SemanticNonNull = "semanticNonNull";
77+
78+
/// <summary>
79+
/// The name of the @semanticNonNull argument levels.
80+
/// </summary>
81+
public const string Levels = "levels";
7282
}

src/HotChocolate/Core/src/Abstractions/WellKnownMiddleware.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,9 @@ public static class WellKnownMiddleware
9090
/// The key identifies the authorization middleware.
9191
/// </summary>
9292
public const string Authorization = "HotChocolate.Authorization";
93+
94+
/// <summary>
95+
/// This key identifies the semantic-non-null middleware.
96+
/// </summary>
97+
public const string SemanticNonNull = "HotChocolate.Types.SemanticNonNull";
9398
}

src/HotChocolate/Core/src/Types/IReadOnlySchemaOptions.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,13 @@ public interface IReadOnlySchemaOptions
165165
/// </summary>
166166
bool EnableStream { get; }
167167

168+
/// <summary>
169+
/// Enables the @semanticNonNull directive and rewrites Non-Null types to nullable types
170+
/// with this directive attached to indicate semantic non-nullability.
171+
/// This feature is experimental and might be changed or removed in the future.
172+
/// </summary>
173+
bool EnableSemanticNonNull { get; }
174+
168175
/// <summary>
169176
/// Specifies the maximum allowed nodes that can be fetched at once through the nodes field.
170177
/// </summary>

src/HotChocolate/Core/src/Types/SchemaBuilder.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public partial class SchemaBuilder : ISchemaBuilder
3737
typeof(InterfaceCompletionTypeInterceptor),
3838
typeof(MiddlewareValidationTypeInterceptor),
3939
typeof(EnableTrueNullabilityTypeInterceptor),
40+
typeof(SemanticNonNullTypeInterceptor),
4041
];
4142

4243
private SchemaOptions _options = new();

src/HotChocolate/Core/src/Types/SchemaOptions.cs

Lines changed: 34 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -15,58 +15,34 @@ public class SchemaOptions : IReadOnlySchemaOptions
1515
private BindingBehavior _defaultBindingBehavior = BindingBehavior.Implicit;
1616
private FieldBindingFlags _defaultFieldBindingFlags = FieldBindingFlags.Instance;
1717

18-
/// <summary>
19-
/// Gets or sets the name of the query type.
20-
/// </summary>
18+
/// <inheritdoc cref="IReadOnlySchemaOptions.QueryTypeName"/>
2119
public string? QueryTypeName { get; set; }
2220

23-
/// <summary>
24-
/// Gets or sets the name of the mutation type.
25-
/// </summary>
21+
/// <inheritdoc cref="IReadOnlySchemaOptions.MutationTypeName"/>
2622
public string? MutationTypeName { get; set; }
2723

28-
/// <summary>
29-
/// Gets or sets the name of the subscription type.
30-
/// </summary>
24+
/// <inheritdoc cref="IReadOnlySchemaOptions.SubscriptionTypeName"/>
3125
public string? SubscriptionTypeName { get; set; }
3226

33-
/// <summary>
34-
/// Defines if the schema allows the query type to be omitted.
35-
/// </summary>
27+
/// <inheritdoc cref="IReadOnlySchemaOptions.StrictValidation"/>
3628
public bool StrictValidation { get; set; } = true;
3729

38-
/// <summary>
39-
/// Defines if the CSharp XML documentation shall be integrated.
40-
/// </summary>
30+
/// <inheritdoc cref="IReadOnlySchemaOptions.UseXmlDocumentation"/>
4131
public bool UseXmlDocumentation { get; set; } = true;
4232

43-
/// <summary>
44-
/// A delegate which defines the name of the XML documentation file to be read.
45-
/// Only used if <seealso cref="UseXmlDocumentation"/> is true.
46-
/// </summary>
33+
/// <inheritdoc cref="IReadOnlySchemaOptions.ResolveXmlDocumentationFileName"/>
4734
public Func<Assembly, string>? ResolveXmlDocumentationFileName { get; set; }
4835

49-
/// <summary>
50-
/// Defines if fields shall be sorted by name.
51-
/// Default: <c>false</c>
52-
/// </summary>
36+
/// <inheritdoc cref="IReadOnlySchemaOptions.SortFieldsByName"/>
5337
public bool SortFieldsByName { get; set; }
5438

55-
/// <summary>
56-
/// Defines if types shall be removed from the schema that are
57-
/// unreachable from the root types.
58-
/// </summary>
39+
/// <inheritdoc cref="IReadOnlySchemaOptions.RemoveUnreachableTypes"/>
5940
public bool RemoveUnreachableTypes { get; set; }
6041

61-
/// <summary>
62-
/// Defines if unused type system directives shall
63-
/// be removed from the schema.
64-
/// </summary>
42+
/// <inheritdoc cref="IReadOnlySchemaOptions.RemoveUnusedTypeSystemDirectives"/>
6543
public bool RemoveUnusedTypeSystemDirectives { get; set; } = true;
6644

67-
/// <summary>
68-
/// Defines the default binding behavior.
69-
/// </summary>
45+
/// <inheritdoc cref="IReadOnlySchemaOptions.DefaultBindingBehavior"/>
7046
public BindingBehavior DefaultBindingBehavior
7147
{
7248
get => _defaultBindingBehavior;
@@ -81,10 +57,7 @@ public BindingBehavior DefaultBindingBehavior
8157
}
8258
}
8359

84-
/// <summary>
85-
/// Defines which members shall be by default inferred as GraphQL fields.
86-
/// This default applies to <see cref="ObjectType"/> and <see cref="ObjectTypeExtension"/>.
87-
/// </summary>
60+
/// <inheritdoc cref="IReadOnlySchemaOptions.DefaultFieldBindingFlags"/>
8861
public FieldBindingFlags DefaultFieldBindingFlags
8962
{
9063
get => _defaultFieldBindingFlags;
@@ -99,137 +72,69 @@ public FieldBindingFlags DefaultFieldBindingFlags
9972
}
10073
}
10174

102-
/// <summary>
103-
/// Defines on which fields a middleware pipeline can be applied on.
104-
/// </summary>
75+
/// <inheritdoc cref="IReadOnlySchemaOptions.FieldMiddleware"/>
10576
public FieldMiddlewareApplication FieldMiddleware { get; set; } =
10677
FieldMiddlewareApplication.UserDefinedFields;
10778

108-
/// <summary>
109-
/// Defines if the experimental directive introspection feature shall be enabled.
110-
/// </summary>
79+
/// <inheritdoc cref="IReadOnlySchemaOptions.EnableDirectiveIntrospection"/>
11180
public bool EnableDirectiveIntrospection { get; set; }
11281

113-
/// <summary>
114-
/// The default directive visibility when directive introspection is enabled.
115-
/// </summary>
82+
/// <inheritdoc cref="IReadOnlySchemaOptions.DefaultDirectiveVisibility"/>
11683
public DirectiveVisibility DefaultDirectiveVisibility { get; set; } =
11784
DirectiveVisibility.Public;
11885

119-
/// <summary>
120-
/// Defines that the default resolver execution strategy.
121-
/// </summary>
86+
/// <inheritdoc cref="IReadOnlySchemaOptions.DefaultResolverStrategy"/>
12287
public ExecutionStrategy DefaultResolverStrategy { get; set; } =
12388
ExecutionStrategy.Parallel;
12489

125-
/// <summary>
126-
/// Defines if the order of important middleware components shall be validated.
127-
/// </summary>
90+
/// <inheritdoc cref="IReadOnlySchemaOptions.ValidatePipelineOrder"/>
12891
public bool ValidatePipelineOrder { get; set; } = true;
12992

130-
/// <summary>
131-
/// Defines if the runtime types of types shall be validated.
132-
/// </summary>
93+
/// <inheritdoc cref="IReadOnlySchemaOptions.StrictRuntimeTypeValidation"/>
13394
public bool StrictRuntimeTypeValidation { get; set; }
13495

135-
/// <summary>
136-
/// Defines a delegate that determines if a runtime
137-
/// is an instance of an <see cref="ObjectType{T}"/>.
138-
/// </summary>
96+
/// <inheritdoc cref="IReadOnlySchemaOptions.DefaultIsOfTypeCheck"/>
13997
public IsOfTypeFallback? DefaultIsOfTypeCheck { get; set; }
14098

141-
/// <summary>
142-
/// Defines if the OneOf spec RFC is enabled. This feature is experimental.
143-
/// </summary>
99+
/// <inheritdoc cref="IReadOnlySchemaOptions.EnableOneOf"/>
144100
public bool EnableOneOf { get; set; }
145101

146-
/// <summary>
147-
/// Defines if the schema building process shall validate that all nodes are resolvable through `node`.
148-
/// </summary>
102+
/// <inheritdoc cref="IReadOnlySchemaOptions.EnsureAllNodesCanBeResolved"/>
149103
public bool EnsureAllNodesCanBeResolved { get; set; } = true;
150104

151-
/// <summary>
152-
/// Defines if flag enums should be inferred as object value nodes
153-
/// </summary>
154-
/// <example>
155-
/// Given the following enum
156-
/// <br/>
157-
/// <code>
158-
/// [Flags]
159-
/// public enum Example { First, Second, Third }
160-
///
161-
/// public class Query { public Example Loopback(Example input) => input;
162-
/// </code>
163-
/// <br/>
164-
/// The following schema is produced
165-
/// <br/>
166-
/// <code>
167-
/// type Query {
168-
/// loopback(input: ExampleFlagsInput!): ExampleFlags
169-
/// }
170-
///
171-
/// type ExampleFlags {
172-
/// isFirst: Boolean!
173-
/// isSecond: Boolean!
174-
/// isThird: Boolean!
175-
/// }
176-
///
177-
/// input ExampleFlagsInput {
178-
/// isFirst: Boolean
179-
/// isSecond: Boolean
180-
/// isThird: Boolean
181-
/// }
182-
/// </code>
183-
/// </example>
105+
/// <inheritdoc cref="IReadOnlySchemaOptions.EnableFlagEnums"/>
184106
public bool EnableFlagEnums { get; set; }
185107

186-
/// <summary>
187-
/// Enables the @defer directive.
188-
/// Defer and stream both are at the moment preview features.
189-
/// </summary>
108+
/// <inheritdoc cref="IReadOnlySchemaOptions.EnableDefer"/>
190109
public bool EnableDefer { get; set; }
191110

192-
/// <summary>
193-
/// Enables the @stream directive.
194-
/// Defer and stream both are at the moment preview features.
195-
/// </summary>
111+
/// <inheritdoc cref="IReadOnlySchemaOptions.EnableStream"/>
196112
public bool EnableStream { get; set; }
197113

198-
/// <summary>
199-
/// Specifies the maximum allowed nodes that can be fetched at once through the nodes field.
200-
/// </summary>
114+
/// <inheritdoc cref="IReadOnlySchemaOptions.EnableSemanticNonNull"/>
115+
public bool EnableSemanticNonNull { get; set; }
116+
117+
/// <inheritdoc cref="IReadOnlySchemaOptions.MaxAllowedNodeBatchSize"/>
201118
public int MaxAllowedNodeBatchSize { get; set; } = 50;
202119

203-
/// <summary>
204-
/// Specified if the leading I shall be stripped from the interface name.
205-
/// </summary>
120+
/// <inheritdoc cref="IReadOnlySchemaOptions.StripLeadingIFromInterface"/>
206121
public bool StripLeadingIFromInterface { get; set; }
207122

208-
/// <summary>
209-
/// Specifies that the true nullability proto type shall be enabled.
210-
/// </summary>
123+
/// <inheritdoc cref="IReadOnlySchemaOptions.EnableTrueNullability"/>
211124
public bool EnableTrueNullability { get; set; }
212125

213-
/// <summary>
214-
/// Specifies that the @tag directive shall be registered with the type system.
215-
/// </summary>
126+
/// <inheritdoc cref="IReadOnlySchemaOptions.EnableTag"/>
216127
public bool EnableTag { get; set; } = true;
217128

218-
/// <summary>
219-
/// Defines the default dependency injection scope for query fields.
220-
/// </summary>
129+
/// <inheritdoc cref="IReadOnlySchemaOptions.DefaultQueryDependencyInjectionScope"/>
221130
public DependencyInjectionScope DefaultQueryDependencyInjectionScope { get; set; } =
222131
DependencyInjectionScope.Resolver;
223132

224-
/// <summary>
225-
/// Defines the default dependency injection scope for mutation fields.
226-
/// </summary>
133+
/// <inheritdoc cref="IReadOnlySchemaOptions.DefaultMutationDependencyInjectionScope"/>
227134
public DependencyInjectionScope DefaultMutationDependencyInjectionScope { get; set; } =
228135
DependencyInjectionScope.Request;
229136

230-
/// <summary>
231-
/// Defines if the root field pages shall be published to the promise cache.
232-
/// </summary>
137+
/// <inheritdoc cref="IReadOnlySchemaOptions.PublishRootFieldPagesToPromiseCache"/>
233138
public bool PublishRootFieldPagesToPromiseCache { get; set; } = true;
234139

235140
/// <summary>
@@ -263,6 +168,7 @@ public static SchemaOptions FromOptions(IReadOnlySchemaOptions options)
263168
EnableFlagEnums = options.EnableFlagEnums,
264169
EnableDefer = options.EnableDefer,
265170
EnableStream = options.EnableStream,
171+
EnableSemanticNonNull = options.EnableSemanticNonNull,
266172
DefaultFieldBindingFlags = options.DefaultFieldBindingFlags,
267173
MaxAllowedNodeBatchSize = options.MaxAllowedNodeBatchSize,
268174
StripLeadingIFromInterface = options.StripLeadingIFromInterface,

0 commit comments

Comments
 (0)