Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public override void OnBeforeCompleteName(
"IL2072",
Justification =
"Runtime types come from the schema type model and are statically referenced.")]
public override void OnBeforeCompleteType(
public override void OnAfterCompleteType(
ITypeCompletionContext completionContext,
TypeSystemConfiguration configuration)
{
Comment thread
michaelstaib marked this conversation as resolved.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,15 @@ public IReadOnlyList<DirectiveConfiguration> GetDirectives()

public void SetConnectionTotalCountFieldFlags() => Flags |= CoreFieldFlags.TotalCount;

public void SetFieldRequirements(string requirements, Type entityType)
public void SetFieldRequirements(string? requirements, Type? entityType)
{
if (string.IsNullOrEmpty(requirements) || entityType is null)
{
Flags &= ~CoreFieldFlags.WithRequirements;
Features.Set<FieldRequirementFeature>(null);
return;
}

Flags |= CoreFieldFlags.WithRequirements;
Features.Set(new FieldRequirementFeature(requirements, entityType));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,4 +330,37 @@ IInterfaceFieldDescriptor Directive<T>()
IInterfaceFieldDescriptor Directive(
string name,
params ArgumentNode[] arguments);

/// <summary>
/// Specifies the requirements for the parent object.
/// </summary>
/// <param name="selector">
/// The requirements for the parent object.
/// </param>
/// <returns>
/// Returns the descriptor to chain further configuration.
/// </returns>
IInterfaceFieldDescriptor ParentRequires<TParent>(Expression<Func<TParent, object>> selector);

/// <summary>
/// Specifies the requirements for the parent object.
/// </summary>
/// <param name="requires">
/// The requirements for the parent object.
/// </param>
/// <returns>
/// Returns the descriptor to chain further configuration.
/// </returns>
IInterfaceFieldDescriptor ParentRequires<TParent>(string? requires);

/// <summary>
/// Specifies the requirements for the parent object.
/// </summary>
/// <param name="requires">
/// The requirements for the parent object.
/// </param>
/// <returns>
/// Returns the descriptor to chain further configuration.
/// </returns>
IInterfaceFieldDescriptor ParentRequires(string? requires);
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ private void CompleteArguments(InterfaceFieldConfiguration definition)
_parameterInfos,
definition.GetParameterExpressionBuilders(),
IsBatchResolver());

FieldDescriptorUtilities.DiscoverParentRequirements(_parameterInfos, Configuration);

_argumentsInitialized = true;
}
}
Expand Down Expand Up @@ -353,6 +356,21 @@ public IInterfaceFieldDescriptor Use(FieldMiddleware middleware)
return this;
}

public IInterfaceFieldDescriptor ParentRequires<TParent>(Expression<Func<TParent, object>> selector)
=> ParentRequires<TParent>(ObjectFieldDescriptor.ExpressionSelectionSetFormatter.Format(selector));

public IInterfaceFieldDescriptor ParentRequires<TParent>(string? requires)
{
Configuration.SetFieldRequirements(requires, typeof(TParent));
return this;
}

public IInterfaceFieldDescriptor ParentRequires(string? requires)
{
Configuration.SetFieldRequirements(requires, Configuration.SourceType);
return this;
}

public static InterfaceFieldDescriptor New(
IDescriptorContext context,
string fieldName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,22 +242,7 @@ private void CompleteArguments(ObjectFieldConfiguration definition)
definition.GetParameterExpressionBuilders(),
IsBatchResolver());

foreach (var parameter in _parameterInfos)
{
if (!parameter.IsDefined(typeof(ParentAttribute)))
{
continue;
}

var requirements = parameter.GetCustomAttribute<ParentAttribute>()?.Requires;
if (!(requirements?.Length > 0))
{
continue;
}

Configuration.Flags |= CoreFieldFlags.WithRequirements;
Configuration.Features.Set(new FieldRequirementFeature(requirements, parameter.ParameterType));
}
FieldDescriptorUtilities.DiscoverParentRequirements(_parameterInfos, Configuration);
}

_argumentsInitialized = true;
Expand Down Expand Up @@ -603,29 +588,13 @@ public IObjectFieldDescriptor ParentRequires<TParent>(Expression<Func<TParent, o
/// <inheritdoc />
public IObjectFieldDescriptor ParentRequires<TParent>(string? requires)
{
if (!(requires?.Length > 0))
{
Configuration.Flags &= ~CoreFieldFlags.WithRequirements;
Configuration.Features.Set<FieldRequirementFeature>(null);
return this;
}

Configuration.Flags |= CoreFieldFlags.WithRequirements;
Configuration.Features.Set(new FieldRequirementFeature(requires, typeof(TParent)));
Configuration.SetFieldRequirements(requires, typeof(TParent));
return this;
}

public IObjectFieldDescriptor ParentRequires(string? requires)
{
if (!(requires?.Length > 0))
{
Configuration.Flags &= ~CoreFieldFlags.WithRequirements;
Configuration.Features.Set<FieldRequirementFeature>(null);
return this;
}

Configuration.Flags |= CoreFieldFlags.WithRequirements;
Configuration.Features.Set(new FieldRequirementFeature(requires, Configuration.SourceType));
Configuration.SetFieldRequirements(requires, Configuration.SourceType);
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,25 @@ public static void DiscoverArguments(
}
}
}

public static void DiscoverParentRequirements(
ParameterInfo[] parameters,
FieldConfiguration configuration)
{
foreach (var parameter in parameters)
{
if (!parameter.IsDefined(typeof(ParentAttribute)))
{
continue;
}

var requirements = parameter.GetCustomAttribute<ParentAttribute>()?.Requires;
if (!(requirements?.Length > 0))
{
continue;
}

configuration.SetFieldRequirements(requirements, parameter.ParameterType);
}
}
}
18 changes: 18 additions & 0 deletions src/HotChocolate/Core/src/Types/Types/ObjectType.Initialization.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using HotChocolate.Configuration;
using HotChocolate.Features;
using HotChocolate.Internal;
using HotChocolate.Resolvers;
using HotChocolate.Types.Descriptors;
Expand Down Expand Up @@ -133,15 +134,32 @@ protected virtual ObjectFieldCollection OnCompleteFields(
if (processed.Add(field.Name)
&& interfaceFields.TryGetValue(field.Name, out var interfaceField))
{
var inheritedResolver = false;

if (!field.Resolvers.HasResolvers)
{
field.Resolvers = interfaceField.Resolvers;
inheritedResolver = true;
}

if (field.BatchResolver is null && interfaceField.BatchResolver is not null)
{
field.BatchResolver = interfaceField.BatchResolver;
field.SetBatchResolverFlags();
inheritedResolver = true;
}

// The [Parent(requires:)] metadata is bound to the inherited resolver, so it has
// to travel with it. The CopyTo path below already does this for fields that are
// created from the interface field, but a field that is already declared on the
// object type reuses this merge path and would otherwise drop the requirement,
// leaving the required column out of the projection.
if (inheritedResolver
&& (interfaceField.Flags & CoreFieldFlags.WithRequirements) == CoreFieldFlags.WithRequirements
&& (field.Flags & CoreFieldFlags.WithRequirements) != CoreFieldFlags.WithRequirements)
{
var requirements = interfaceField.Features.GetRequired<FieldRequirementFeature>();
field.SetFieldRequirements(requirements.Requirements, requirements.EntityType);
}
}
}
Expand Down
Loading
Loading