Skip to content

Commit 43e9a88

Browse files
authored
Reworked the type inititialization flow. (#7953)
1 parent 01b22c4 commit 43e9a88

38 files changed

+896
-111
lines changed

src/HotChocolate/ApolloFederation/src/ApolloFederation/FederationTypeInterceptor.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ public override void OnBeforeCompleteType(
338338
definition);
339339
}
340340

341-
public override void OnAfterCompleteType(
341+
public override void OnAfterMakeExecutable(
342342
ITypeCompletionContext completionContext,
343343
DefinitionBase definition)
344344
{
@@ -350,8 +350,6 @@ public override void OnAfterCompleteType(
350350
}
351351
}
352352

353-
internal override void OnAfterCreateSchemaInternal(IDescriptorContext context, ISchema schema) { }
354-
355353
private void CompleteExternalFieldSetters(ObjectType type, ObjectTypeDefinition typeDef)
356354
=> ExternalSetterExpressionHelper.TryAddExternalSetter(type, typeDef);
357355

src/HotChocolate/ApolloFederation/src/ApolloFederation/Resolvers/ExternalSetterExpressionHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public static void TryAddExternalSetter(ObjectType type, ObjectTypeDefinition ty
3131
foreach (var field in type.Fields)
3232
{
3333
if (field.Directives.ContainsDirective<ExternalDirective>() &&
34-
field.Member is PropertyInfo { SetMethod: { }, } property)
34+
field.Member is PropertyInfo { SetMethod: not null, } property)
3535
{
3636
var expression = CreateTrySetValue(type.RuntimeType, property, field.Name);
3737
(block ??= []).Add(expression);

src/HotChocolate/Core/src/Authorization/AuthorizationTypeInterceptor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public override void OnBeforeCompleteType(
124124
}
125125
}
126126

127-
public override void OnAfterCompleteTypes()
127+
public override void OnAfterMakeExecutable()
128128
{
129129
foreach (var type in _objectTypes)
130130
{

src/HotChocolate/Core/src/Types/Configuration/AggregateTypeInterceptor.cs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,102 @@ public override void OnAfterCompleteType(
403403
}
404404
}
405405

406+
public override void OnBeforeCompleteMetadata()
407+
{
408+
ref var first = ref GetReference();
409+
var length = _typeInterceptors.Length;
410+
411+
for (var i = 0; i < length; i++)
412+
{
413+
Unsafe.Add(ref first, i).OnBeforeCompleteMetadata();
414+
}
415+
}
416+
417+
public override void OnAfterCompleteMetadata()
418+
{
419+
ref var first = ref GetReference();
420+
var length = _typeInterceptors.Length;
421+
422+
for (var i = 0; i < length; i++)
423+
{
424+
Unsafe.Add(ref first, i).OnAfterCompleteMetadata();
425+
}
426+
}
427+
428+
public override void OnBeforeCompleteMetadata(
429+
ITypeCompletionContext context,
430+
DefinitionBase definition)
431+
{
432+
ref var first = ref GetReference();
433+
var length = _typeInterceptors.Length;
434+
435+
for (var i = 0; i < length; i++)
436+
{
437+
Unsafe.Add(ref first, i).OnBeforeCompleteMetadata(context, definition);
438+
}
439+
}
440+
441+
public override void OnAfterCompleteMetadata(
442+
ITypeCompletionContext context,
443+
DefinitionBase definition)
444+
{
445+
ref var first = ref GetReference();
446+
var length = _typeInterceptors.Length;
447+
448+
for (var i = 0; i < length; i++)
449+
{
450+
Unsafe.Add(ref first, i).OnAfterCompleteMetadata(context, definition);
451+
}
452+
}
453+
454+
public override void OnBeforeMakeExecutable()
455+
{
456+
ref var first = ref GetReference();
457+
var length = _typeInterceptors.Length;
458+
459+
for (var i = 0; i < length; i++)
460+
{
461+
Unsafe.Add(ref first, i).OnBeforeMakeExecutable();
462+
}
463+
}
464+
465+
public override void OnAfterMakeExecutable()
466+
{
467+
ref var first = ref GetReference();
468+
var length = _typeInterceptors.Length;
469+
470+
for (var i = 0; i < length; i++)
471+
{
472+
Unsafe.Add(ref first, i).OnAfterMakeExecutable();
473+
}
474+
}
475+
476+
public override void OnBeforeMakeExecutable(
477+
ITypeCompletionContext context,
478+
DefinitionBase definition)
479+
{
480+
ref var first = ref GetReference();
481+
var length = _typeInterceptors.Length;
482+
483+
for (var i = 0; i < length; i++)
484+
{
485+
Unsafe.Add(ref first, i).OnBeforeMakeExecutable(context, definition);
486+
}
487+
}
488+
489+
public override void OnAfterMakeExecutable(
490+
ITypeCompletionContext context,
491+
DefinitionBase definition)
492+
{
493+
ref var first = ref GetReference();
494+
var length = _typeInterceptors.Length;
495+
496+
for (var i = 0; i < length; i++)
497+
{
498+
Unsafe.Add(ref first, i).OnAfterMakeExecutable(context, definition);
499+
}
500+
}
501+
406502
public override void OnValidateType(
407503
ITypeSystemObjectContext validationContext,
408504
DefinitionBase definition)

src/HotChocolate/Core/src/Types/Configuration/TypeInitializer.cs

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,19 @@ public void Initialize()
101101
// before we start completing types we will compile the resolvers.
102102
CompileResolvers();
103103

104-
// last we complete the types. Completing types means that we will assign all
105-
// the fields resolving all missing parts and then making the types immutable.
104+
// now we complete the types. This means at this point we are completing
105+
// the type structure. Fields and arguments will be accessible after
106+
// types are completed.
106107
CompleteTypes();
107108

109+
// next we are completing type system directives and feature metadata.
110+
CompleteMetadata();
111+
112+
// before we can finalize the types and make the immutable we are going to make the
113+
// types executable. This means that at this point we are taking the compiled resolvers
114+
// and are compiling from them field middleware that are assigned to the output fields.
115+
MakeExecutable();
116+
108117
// at this point everything is completely initialized, and we just trigger a type
109118
// finalize to allow the type to clean up any initialization data structures.
110119
FinalizeTypes();
@@ -574,10 +583,13 @@ private void CompleteTypes()
574583
{
575584
_interceptor.OnBeforeCompleteTypes();
576585

577-
ProcessTypes(Completed, type => CompleteType(type));
586+
if(ProcessTypes(Completed, type => CompleteType(type)))
587+
{
588+
_interceptor.OnTypesCompleted();
589+
}
590+
578591
EnsureNoErrors();
579592

580-
_interceptor.OnTypesCompleted();
581593
_interceptor.OnAfterCompleteTypes();
582594
}
583595

@@ -597,6 +609,40 @@ internal bool CompleteType(RegisteredType registeredType)
597609
return true;
598610
}
599611

612+
private void CompleteMetadata()
613+
{
614+
_interceptor.OnBeforeCompleteMetadata();
615+
616+
foreach (var registeredType in _typeRegistry.Types)
617+
{
618+
if (!registeredType.IsExtension)
619+
{
620+
registeredType.Type.CompleteMetadata(registeredType);
621+
}
622+
}
623+
624+
EnsureNoErrors();
625+
626+
_interceptor.OnAfterCompleteMetadata();
627+
}
628+
629+
private void MakeExecutable()
630+
{
631+
_interceptor.OnBeforeMakeExecutable();
632+
633+
foreach (var registeredType in _typeRegistry.Types)
634+
{
635+
if (!registeredType.IsExtension)
636+
{
637+
registeredType.Type.MakeExecutable(registeredType);
638+
}
639+
}
640+
641+
EnsureNoErrors();
642+
643+
_interceptor.OnAfterMakeExecutable();
644+
}
645+
600646
private void FinalizeTypes()
601647
{
602648
foreach (var registeredType in _typeRegistry.Types)
@@ -606,6 +652,8 @@ private void FinalizeTypes()
606652
registeredType.Type.FinalizeType(registeredType);
607653
}
608654
}
655+
656+
EnsureNoErrors();
609657
}
610658

611659
private bool ProcessTypes(

src/HotChocolate/Core/src/Types/Configuration/TypeInterceptor.cs

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,9 @@ public virtual void OnAfterResolveRootType(
226226
{
227227
}
228228

229+
/// <summary>
230+
/// This event is called after the type name is assigned.
231+
/// </summary>
229232
public virtual void OnTypesCompletedName() { }
230233

231234
/// <summary>
@@ -259,6 +262,11 @@ public virtual void OnBeforeCompleteMutationField(
259262
/// </summary>
260263
public virtual void OnBeforeCompleteTypes() { }
261264

265+
/// <summary>
266+
/// This method is called after the types are completed.
267+
/// </summary>
268+
public virtual void OnTypesCompleted() { }
269+
262270
/// <summary>
263271
/// This method is called after the types are completed.
264272
/// </summary>
@@ -294,6 +302,86 @@ public virtual void OnAfterCompleteType(
294302
{
295303
}
296304

305+
/// <summary>
306+
/// This method is called before the metadata of all types are completed.
307+
/// </summary>
308+
public virtual void OnBeforeCompleteMetadata() { }
309+
310+
/// <summary>
311+
/// This method is called after the metadata of all types are completed.
312+
/// </summary>
313+
public virtual void OnAfterCompleteMetadata() { }
314+
315+
/// <summary>
316+
/// This event is called before the metadata of the type system member is fully completed.
317+
/// </summary>
318+
/// <param name="context">
319+
/// The type completion context.
320+
/// </param>
321+
/// <param name="definition">
322+
/// The type definition of the type system member.
323+
/// </param>
324+
public virtual void OnBeforeCompleteMetadata(
325+
ITypeCompletionContext context,
326+
DefinitionBase definition)
327+
{
328+
}
329+
330+
/// <summary>
331+
/// This event is called after the metadata of the type system member was fully completed.
332+
/// </summary>
333+
/// <param name="context">
334+
/// The type completion context.
335+
/// </param>
336+
/// <param name="definition">
337+
/// The type definition of the type system member.
338+
/// </param>
339+
public virtual void OnAfterCompleteMetadata(
340+
ITypeCompletionContext context,
341+
DefinitionBase definition)
342+
{
343+
}
344+
345+
/// <summary>
346+
/// This method is called before the types are made executable.
347+
/// </summary>
348+
public virtual void OnBeforeMakeExecutable() { }
349+
350+
/// <summary>
351+
/// This method is called after the types are made executable.
352+
/// </summary>
353+
public virtual void OnAfterMakeExecutable() { }
354+
355+
/// <summary>
356+
/// This event is called before the type system member is made executable.
357+
/// </summary>
358+
/// <param name="context">
359+
/// The type completion context.
360+
/// </param>
361+
/// <param name="definition">
362+
/// The type definition of the type system member.
363+
/// </param>
364+
public virtual void OnBeforeMakeExecutable(
365+
ITypeCompletionContext context,
366+
DefinitionBase definition)
367+
{
368+
}
369+
370+
/// <summary>
371+
/// This event is called after the type system member is made executable.
372+
/// </summary>
373+
/// <param name="context">
374+
/// The type completion context.
375+
/// </param>
376+
/// <param name="definition">
377+
/// The type definition of the type system member.
378+
/// </param>
379+
public virtual void OnAfterMakeExecutable(
380+
ITypeCompletionContext context,
381+
DefinitionBase definition)
382+
{
383+
}
384+
297385
/// <summary>
298386
/// This event is called after the type system member is fully completed and is
299387
/// intended to add validation logic. If the type is not valid throw a
@@ -311,8 +399,6 @@ public virtual void OnValidateType(
311399
{
312400
}
313401

314-
public virtual void OnTypesCompleted() { }
315-
316402
// note: this hook is a legacy hook and will be removed once the new schema building API is completed.
317403
/// <summary>
318404
/// This hook is invoked after schema is fully created and gives access

src/HotChocolate/Core/src/Types/Internal/TypeDependencyHelper.cs

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public static void CollectDependencies(
109109

110110
if (field.Type is not null)
111111
{
112-
dependencies.Add(new(field.Type, GetDefaultValueDependencyKind(field)));
112+
dependencies.Add(new(field.Type));
113113
}
114114

115115
CollectDirectiveDependencies(field, dependencies);
@@ -182,9 +182,7 @@ public static void CollectDependencies(
182182

183183
if (argument.Type is not null)
184184
{
185-
dependencies.Add(new(
186-
argument.Type,
187-
GetDefaultValueDependencyKind(argument)));
185+
dependencies.Add(new(argument.Type));
188186
}
189187
}
190188
}
@@ -334,16 +332,4 @@ public static void RegisterDependencies(
334332

335333
CollectDependencies(definition, context.Dependencies);
336334
}
337-
338-
private static TypeDependencyFulfilled GetDefaultValueDependencyKind(
339-
ArgumentDefinition argumentDefinition)
340-
{
341-
var hasDefaultValue =
342-
argumentDefinition.DefaultValue is not null and not NullValueNode ||
343-
argumentDefinition.RuntimeDefaultValue is not null;
344-
345-
return hasDefaultValue
346-
? Completed
347-
: Default;
348-
}
349335
}

src/HotChocolate/Core/src/Types/InvalidSchemaCoordinateException.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ namespace HotChocolate;
77
/// <see cref="InvalidSchemaCoordinateException.Coordinate"/>
88
/// could not be resolved.
99
/// </summary>
10+
#pragma warning disable RCS1194
1011
public class InvalidSchemaCoordinateException : Exception
1112
{
1213
/// <summary>
@@ -26,3 +27,4 @@ public InvalidSchemaCoordinateException(string message, SchemaCoordinate coordin
2627
/// <value></value>
2728
public SchemaCoordinate Coordinate { get; }
2829
}
30+
#pragma warning restore RCS1194

0 commit comments

Comments
 (0)