Skip to content

Commit

Permalink
Fixes several issues for projecting from node fields. (#5425)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelstaib committed Sep 22, 2022
1 parent 102a881 commit 468118a
Show file tree
Hide file tree
Showing 48 changed files with 380 additions and 118 deletions.
1 change: 0 additions & 1 deletion .vscode/tasks.json
Expand Up @@ -23,7 +23,6 @@
"args": [
"build",
"src/All.sln",
"-c Debug",
// Ask dotnet build to generate full paths for file names.
"/property:GenerateFullPaths=true",
// Do not generate summary otherwise it leads to duplicate errors in Problems panel
Expand Down
5 changes: 2 additions & 3 deletions global.json
@@ -1,6 +1,5 @@
{
"sdk": {
"version": "7.0.100-preview.7.22377.5",
"rollForward": "latestMinor"
"version": "7.0.100-preview.7.22377.5"
}
}
}
Expand Up @@ -183,6 +183,11 @@ public static class WellKnownContextData
/// </summary>
public const string InternalId = "HotChocolate.Relay.Node.Id.InternalId";

/// <summary>
/// The key to get the id type name from the context data.
/// </summary>
public const string InternalTypeName = "HotChocolate.Relay.Node.Id.InternalTypeName";

/// <summary>
/// The key to get the id type from the context data.
/// </summary>
Expand Down
Expand Up @@ -14,6 +14,7 @@
<ItemGroup>
<InternalsVisibleTo Include="HotChocolate.Types.Mutations" />
<InternalsVisibleTo Include="HotChocolate.AspNetCore.Tests" />
<InternalsVisibleTo Include="HotChocolate.Data" />
<InternalsVisibleTo Include="HotChocolate.Fusion" />
<InternalsVisibleTo Include="HotChocolate.Fusion.Tests" />
<InternalsVisibleTo Include="StrawberryShake.CodeGeneration" />
Expand Down
Expand Up @@ -466,7 +466,7 @@ private void CollectFields(CompilerContext context)
responseName: responseName,
isParallelExecutable: field.IsParallelExecutable,
arguments: CoerceArgumentValues(field, selection, responseName),
includeCondition: includeCondition);
includeConditions: includeCondition == 0 ? null : new[] { includeCondition });

context.Fields.Add(responseName, preparedSelection);

Expand Down
8 changes: 4 additions & 4 deletions src/HotChocolate/Core/src/Execution/Processing/Selection.cs
Expand Up @@ -29,7 +29,7 @@ public class Selection : ISelection
FieldNode syntaxNode,
string responseName,
IArgumentMap? arguments = null,
long includeCondition = 0,
long[]? includeConditions = null,
bool isInternal = false,
bool isParallelExecutable = true,
FieldDelegate? resolverPipeline = null,
Expand All @@ -46,9 +46,7 @@ public class Selection : ISelection
PureResolver = pureResolver;
Strategy = InferStrategy(!isParallelExecutable, pureResolver is not null);

_includeConditions = includeCondition is 0
? Array.Empty<long>()
: new[] { includeCondition };
_includeConditions = includeConditions ?? Array.Empty<long>();

_flags = isInternal ? Flags.Internal : Flags.None;

Expand Down Expand Up @@ -152,6 +150,8 @@ public bool HasStreamDirective(long includeFlags)
public bool IsConditional
=> _includeConditions.Length > 0 || (_flags & Flags.Internal) == Flags.Internal;

internal ReadOnlySpan<long> IncludeConditions => _includeConditions;

public bool IsIncluded(long includeFlags, bool allowInternals = false)
{
// in most case we do not have any include condition,
Expand Down
Expand Up @@ -67,7 +67,7 @@ public static class DataLoaderObjectFieldExtensions
dataLoaderType);
},
definition,
ApplyConfigurationOn.Completion));
ApplyConfigurationOn.BeforeCompletion));
});

return descriptor;
Expand Down
Expand Up @@ -58,14 +58,14 @@ internal class ConnectionType
TypeContext.Output);
},
Definition,
ApplyConfigurationOn.Naming,
ApplyConfigurationOn.BeforeNaming,
nodeType,
TypeDependencyKind.Named));
Definition.Configurations.Add(
new CompleteConfiguration(
(c, _) => EdgeType = c.GetType<IEdgeType>(TypeReference.Create(edgeTypeName)),
Definition,
ApplyConfigurationOn.Completion));
ApplyConfigurationOn.BeforeCompletion));
}

internal ConnectionType(ITypeReference nodeType, bool withTotalCount)
Expand Down Expand Up @@ -110,7 +110,7 @@ internal ConnectionType(ITypeReference nodeType, bool withTotalCount)
TypeContext.Output);
},
Definition,
ApplyConfigurationOn.Naming,
ApplyConfigurationOn.BeforeNaming,
nodeType,
TypeDependencyKind.Named));
Definition.Configurations.Add(
Expand All @@ -120,7 +120,7 @@ internal ConnectionType(ITypeReference nodeType, bool withTotalCount)
EdgeType = c.GetType<IEdgeType>(edgeType);
},
Definition,
ApplyConfigurationOn.Completion));
ApplyConfigurationOn.BeforeCompletion));
}

/// <summary>
Expand Down
6 changes: 3 additions & 3 deletions src/HotChocolate/Core/src/Types.CursorPagination/EdgeType.cs
Expand Up @@ -32,7 +32,7 @@ internal sealed class EdgeType : ObjectType, IEdgeType
new CompleteConfiguration(
(c, _) => NodeType = c.GetType<IOutputType>(nodeType),
Definition,
ApplyConfigurationOn.Completion));
ApplyConfigurationOn.BeforeCompletion));
}

internal EdgeType(ITypeReference nodeType)
Expand All @@ -54,14 +54,14 @@ internal EdgeType(ITypeReference nodeType)
((ObjectTypeDefinition)d).Name = NameHelper.CreateEdgeName(ConnectionName);
},
Definition,
ApplyConfigurationOn.Naming,
ApplyConfigurationOn.BeforeNaming,
nodeType,
TypeDependencyKind.Named));
Definition.Configurations.Add(
new CompleteConfiguration(
(c, _) => NodeType = c.GetType<IOutputType>(nodeType),
Definition,
ApplyConfigurationOn.Completion));
ApplyConfigurationOn.BeforeCompletion));
}

/// <summary>
Expand Down
Expand Up @@ -42,7 +42,7 @@ internal sealed class FromJsonSchemaDirective : ISchemaDirective
throw ThrowHelper.CannotInferTypeFromJsonObj(ctx.Type.Name);
},
fieldDef,
ApplyConfigurationOn.Completion));
ApplyConfigurationOn.BeforeCompletion));
}
}

Expand Down
Expand Up @@ -41,7 +41,7 @@ internal class CollectionSegmentType
definition.Name = type.NamedType().Name + "CollectionSegment";
},
Definition,
ApplyConfigurationOn.Naming,
ApplyConfigurationOn.BeforeNaming,
nodeType,
TypeDependencyKind.Named));
}
Expand All @@ -57,7 +57,7 @@ internal class CollectionSegmentType
nodes.Type = TypeReference.Parse($"[{ItemType.Print()}]", TypeContext.Output);
},
Definition,
ApplyConfigurationOn.Naming,
ApplyConfigurationOn.BeforeNaming,
nodeType,
TypeDependencyKind.Named));

Expand Down
7 changes: 3 additions & 4 deletions src/HotChocolate/Core/src/Types/SchemaErrorBuilder.cs
Expand Up @@ -6,10 +6,9 @@

namespace HotChocolate;

public partial class SchemaErrorBuilder
: ISchemaErrorBuilder
public partial class SchemaErrorBuilder : ISchemaErrorBuilder
{
private Error _error = new Error();
private readonly Error _error = new();

public ISchemaErrorBuilder SetMessage(string message)
{
Expand Down Expand Up @@ -84,5 +83,5 @@ public ISchemaError Build()
return _error.Clone();
}

public static SchemaErrorBuilder New() => new SchemaErrorBuilder();
public static SchemaErrorBuilder New() => new();
}
@@ -1,8 +1,33 @@
namespace HotChocolate.Types;

/// <summary>
/// This enum defines the events on which configurations can be applied.
/// </summary>
public enum ApplyConfigurationOn
{

/// <summary>
/// Before the type is created.
/// </summary>
Create,
Naming,
Completion

/// <summary>
/// Before the types name is completed.
/// </summary>
BeforeNaming,

/// <summary>
/// After the types name is completed.
/// </summary>
AfterNaming,

/// <summary>
/// Before the type is completed.
/// </summary>
BeforeCompletion,

/// <summary>
/// After the type is completed.
/// </summary>
AfterCompletion
}
Expand Up @@ -109,7 +109,7 @@ private void OnBeforeCreate(Action<IDescriptorContext, T> configure)
var configuration = new CompleteConfiguration(
(c, d) => configure(c, (T)d),
Definition,
ApplyConfigurationOn.Naming);
ApplyConfigurationOn.BeforeNaming);

Definition.Configurations.Add(configuration);

Expand All @@ -130,7 +130,7 @@ private void OnBeforeCreate(Action<IDescriptorContext, T> configure)
var configuration = new CompleteConfiguration(
(c, d) => configure(c, (T)d),
Definition,
ApplyConfigurationOn.Completion);
ApplyConfigurationOn.BeforeCompletion);

Definition.Configurations.Add(configuration);

Expand Down
Expand Up @@ -24,7 +24,7 @@ public static T SingleOrDefault<T>(this IDirectiveCollection directives)
}
}

return default;
return default!;
}

internal static IValueNode? SkipValue(this IReadOnlyList<DirectiveNode> directives)
Expand Down
Expand Up @@ -43,7 +43,7 @@ public static class PagingHelper
options,
placeholder),
definition,
ApplyConfigurationOn.Completion));
ApplyConfigurationOn.BeforeCompletion));

return descriptor;
}
Expand Down
Expand Up @@ -33,10 +33,16 @@ public NodeDescriptor(IObjectTypeDescriptor<TNode> descriptor)
{
_typeDescriptor = descriptor;

_typeDescriptor
.Implements<NodeType>()
.Extend()
.OnBeforeCompletion(OnCompleteDefinition);
// we use the CompleteConfiguration instead of the higher level api since
// we want to target a specific event.
var ownerDef = _typeDescriptor.Implements<NodeType>().Extend().Definition;

var configuration = new CompleteConfiguration(
(c, d) => OnCompleteDefinition(c, (ObjectTypeDefinition)d),
ownerDef,
ApplyConfigurationOn.AfterNaming);

ownerDef.Configurations.Add(configuration);
}

private void OnCompleteDefinition(
Expand All @@ -45,7 +51,21 @@ public NodeDescriptor(IObjectTypeDescriptor<TNode> descriptor)
{
if (Definition.ResolverField is null)
{
ResolveNodeWith<TNode>();
var resolverMethod =
Context.TypeInspector.GetNodeResolverMethod(typeof(TNode), typeof(TNode));

// we allow a node to not have a node resolver.
// this opens up type interceptors bringing these in later.
// we also introduced a validation option that makes sure that node resolvers are
// available after the schema is completed.
if (resolverMethod is not null)
{
ResolveNodeWith(resolverMethod);
}
else
{
ConfigureNodeField();
}
}

CompleteResolver(context, definition);
Expand Down Expand Up @@ -150,11 +170,13 @@ public INodeDescriptor<TNode> IdField(MemberInfo propertyOrMethod)
}

/// <inheritdoc cref="INodeDescriptor{TNode}.ResolveNodeWith{TResolver}()"/>
public IObjectFieldDescriptor ResolveNodeWith<TResolver>() =>
ResolveNodeWith(
public IObjectFieldDescriptor ResolveNodeWith<TResolver>()
{
return ResolveNodeWith(
Context.TypeInspector.GetNodeResolverMethod(
typeof(TNode),
typeof(TResolver))!);
}

/// <inheritdoc cref="INodeDescriptor{TNode}.ResolveNodeWith(Type)"/>
public IObjectFieldDescriptor ResolveNodeWith(Type type) =>
Expand Down
Expand Up @@ -105,7 +105,7 @@ internal static class RelayIdFieldHelpers
placeholder,
typeName),
definition,
ApplyConfigurationOn.Completion);
ApplyConfigurationOn.BeforeCompletion);

definition.Configurations.Add(configuration);
}
Expand Down
Expand Up @@ -2,6 +2,7 @@

using System;
using System.Buffers;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using HotChocolate.Execution;
Expand Down Expand Up @@ -36,7 +37,7 @@ internal static class NodeFieldResolvers
type.ContextData.TryGetValue(NodeResolver, out var o) &&
o is NodeResolverInfo nodeResolverInfo)
{
SetLocalContext(context, nodeId, deserializedId, typeName);
SetLocalContext(context, nodeId, deserializedId, type);
TryReplaceArguments(context, nodeResolverInfo, Id, nodeId);

await nodeResolverInfo.Pipeline.Invoke(context);
Expand Down Expand Up @@ -86,7 +87,7 @@ internal static class NodeFieldResolvers
{
var nodeContext = context.Clone();

SetLocalContext(nodeContext, nodeId, deserializedId, typeName);
SetLocalContext(nodeContext, nodeId, deserializedId, type);
TryReplaceArguments(nodeContext, nodeResolverInfo, Ids, nodeId);

tasks[i] = ExecutePipelineAsync(nodeContext, nodeResolverInfo);
Expand Down Expand Up @@ -155,7 +156,7 @@ internal static class NodeFieldResolvers
{
var nodeContext = context.Clone();

SetLocalContext(nodeContext, nodeId, deserializedId, typeName);
SetLocalContext(nodeContext, nodeId, deserializedId, type);
TryReplaceArguments(nodeContext, nodeResolverInfo, Ids, nodeId);

result[0] = await ExecutePipelineAsync(nodeContext, nodeResolverInfo);
Expand Down Expand Up @@ -188,11 +189,12 @@ internal static class NodeFieldResolvers
IMiddlewareContext context,
StringValueNode nodeId,
IdValue deserializedId,
string typeName)
ObjectType type)
{
context.SetLocalState(NodeId, nodeId.Value);
context.SetLocalState(InternalId, deserializedId.Value);
context.SetLocalState(InternalType, typeName);
context.SetLocalState(InternalType, type);
context.SetLocalState(InternalTypeName, type.Name);
context.SetLocalState(WellKnownContextData.IdValue, deserializedId);
}

Expand Down
Expand Up @@ -3,7 +3,6 @@
using System.Collections.Generic;
using System.Linq;
using HotChocolate.Configuration;
using HotChocolate.Language;
using HotChocolate.Types.Descriptors;
using HotChocolate.Types.Descriptors.Definitions;
using HotChocolate.Types.Introspection;
Expand Down

0 comments on commit 468118a

Please sign in to comment.