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 @@ -58,8 +58,7 @@ public EntityKey(SelectionSetNode fields)
public EntityKey(string fields)
{
ArgumentNullException.ThrowIfNull(fields);
fields = $"{{ {fields.Trim('{', '}')} }}";
Fields = Utf8GraphQLParser.Syntax.ParseSelectionSet(fields);
Fields = FieldSelectionSetType.ParseSelectionSet(fields);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ public static IObjectTypeDescriptor EntityKey(

try
{
fields = $"{{ {fields.Trim('{', '}')} }}";
selectionSet = Utf8GraphQLParser.Syntax.ParseSelectionSet(fields);
selectionSet = FieldSelectionSetType.ParseSelectionSet(fields);
}
catch (SyntaxException ex)
{
Expand Down Expand Up @@ -87,8 +86,7 @@ public static IInterfaceTypeDescriptor EntityKey(

try
{
fields = $"{{ {fields.Trim('{', '}')} }}";
selectionSet = Utf8GraphQLParser.Syntax.ParseSelectionSet(fields);
selectionSet = FieldSelectionSetType.ParseSelectionSet(fields);
}
catch (SyntaxException ex)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ public Provides(SelectionSetNode fields)
public Provides(string fields)
{
ArgumentNullException.ThrowIfNull(fields);
fields = $"{{ {fields.Trim('{', '}')} }}";
Fields = Utf8GraphQLParser.Syntax.ParseSelectionSet(fields);
Fields = FieldSelectionSetType.ParseSelectionSet(fields);
}

[GraphQLType<NonNullType<FieldSelectionSetType>>]
Expand All @@ -43,8 +42,7 @@ public static IObjectFieldDescriptor Provides(

try
{
fields = $"{{ {fields.Trim('{', '}')} }}";
selectionSet = Utf8GraphQLParser.Syntax.ParseSelectionSet(fields);
selectionSet = FieldSelectionSetType.ParseSelectionSet(fields);
}
catch (SyntaxException ex)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,11 @@ protected override StringValueNode OnValueToLiteral(SelectionSetNode runtimeValu
/// </exception>
internal static SelectionSetNode ParseSelectionSet(string s)
{
s = $"{{ {s.Trim('{', '}')} }}";
s = s.Trim();
if (s.Length < 2 || s[0] != '{' || s[^1] != '}')
{
s = $"{{ {s} }}";
}
return Utf8GraphQLParser.Syntax.ParseSelectionSet(s);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,9 @@ private static SourceObjectFieldCollection BuildSourceOutputFieldCollection(
fieldDirective.SourceName ?? fieldDefinition.Name,
context.GetSchemaName(fieldDirective.SchemaKey),
requirements,
CompleteType(fieldDef.Type, fieldDirective.SourceType, context)));
CompleteType(fieldDef.Type, fieldDirective.SourceType, context),
fieldDirective.IsExternal,
fieldDirective.Provides));
}

return new SourceObjectFieldCollection(temp.ToImmutable());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using HotChocolate.Language;
using HotChocolate.Types;

namespace HotChocolate.Fusion.Types.Metadata;
Expand All @@ -6,7 +7,9 @@ public sealed class SourceOutputField(
string name,
string schemaName,
FieldRequirements? requirements,
IType type)
IType type,
bool isExternal,
SelectionSetNode? provides)
: ISourceMember
{
public string Name { get; } = name;
Expand All @@ -17,5 +20,7 @@ public sealed class SourceOutputField(

public IType Type { get; } = type;

public int BaseCost => 1;
public bool IsExternal { get; } = isExternal;

public SelectionSetNode? Provides { get; } = provides;
}
Original file line number Diff line number Diff line change
Expand Up @@ -239,12 +239,78 @@ void CompleteSelection<T>(T original, T? resolvable, T? unresolvable, int index)
}

static SelectionSetNode? GetProvidedSelectionSet(
ITypeDefinition _1,
FusionSchemaDefinition _2,
ITypeDefinition type,
FusionSchemaDefinition schema,
SelectionSetNode? providedSelectionSetNode)
{
// todo match correct inline fragment
return providedSelectionSetNode;
if (providedSelectionSetNode is null)
{
return null;
}

List<ISelectionNode>? flattened = null;
var hasFragment = false;

for (var i = 0; i < providedSelectionSetNode.Selections.Count; i++)
{
var selection = providedSelectionSetNode.Selections[i];

if (selection is InlineFragmentNode fragment)
{
hasFragment = true;

if (fragment.TypeCondition is null)
{
flattened ??= CopyUpTo(providedSelectionSetNode.Selections, i);
flattened.AddRange(fragment.SelectionSet.Selections);
continue;
}

if (!schema.Types.TryGetType(fragment.TypeCondition.Name.Value, out var fragmentType))
{
flattened ??= CopyUpTo(providedSelectionSetNode.Selections, i);
continue;
}

if (fragmentType.IsAssignableFrom(type))
{
flattened ??= CopyUpTo(providedSelectionSetNode.Selections, i);
flattened.AddRange(fragment.SelectionSet.Selections);
}
else if (type.IsAssignableFrom(fragmentType))
{
flattened ??= CopyUpTo(providedSelectionSetNode.Selections, i);
flattened.Add(fragment);
}
else
{
flattened ??= CopyUpTo(providedSelectionSetNode.Selections, i);
}
}
else
{
flattened?.Add(selection);
}
}

if (!hasFragment)
{
return providedSelectionSetNode;
}

return flattened is null
? providedSelectionSetNode
: new SelectionSetNode(flattened);
}

static List<ISelectionNode> CopyUpTo(IReadOnlyList<ISelectionNode> selections, int exclusiveEnd)
{
var copy = new List<ISelectionNode>(selections.Count);
for (var j = 0; j < exclusiveEnd; j++)
{
copy.Add(selections[j]);
}
return copy;
}

static bool IsTypeNameSelection(ISelectionNode selection)
Expand Down Expand Up @@ -385,29 +451,29 @@ private static SelectionSetNode WrapInExtraConditions(
FieldNode? providedFieldNode)
{
var field = complexType.Fields.GetField(fieldNode.Name.Value, allowInaccessibleFields: true);
field.Sources.TryGetMember(context.SchemaName, out var source);

// The field is resolvable from the current schema when either the parent's provides
// scope covers it, or the schema declares a non-external source for it.
var isResolvable = providedFieldNode is not null || source is { IsExternal: false };

if (providedFieldNode is null)
if (!isResolvable)
{
// if the field is not available in the current schema we return null
// which will remove the field from the rewritten selection set.
if (!field.Sources.TryGetMember(context.SchemaName, out var source))
{
return (null, fieldNode);
}
return (null, fieldNode);
}

if (source.Requirements is not null)
{
context.FieldsWithRequirements =
context.FieldsWithRequirements.Push(
new ConditionedFieldSelection(
new FieldSelection(
context.GetId((SelectionSetNode)context.Nodes.Peek()),
fieldNode,
field,
context.BuildPath()),
context.SnapshotConditions()));
return (null, null);
}
if (providedFieldNode is null && source?.Requirements is not null)
{
context.FieldsWithRequirements =
context.FieldsWithRequirements.Push(
new ConditionedFieldSelection(
new FieldSelection(
context.GetId((SelectionSetNode)context.Nodes.Peek()),
fieldNode,
field,
context.BuildPath()),
context.SnapshotConditions()));
return (null, null);
}

var selectionSet = fieldNode.SelectionSet;
Expand All @@ -420,7 +486,7 @@ private static SelectionSetNode WrapInExtraConditions(
context,
field.Type.AsTypeDefinition(),
selectionSet,
providedFieldNode?.SelectionSet);
MergeProvidedSelectionSets(providedFieldNode?.SelectionSet, source?.Provides));

context.Nodes.Pop();

Expand All @@ -437,6 +503,26 @@ private static SelectionSetNode WrapInExtraConditions(
return (fieldNode, null);
}

private static SelectionSetNode? MergeProvidedSelectionSets(
SelectionSetNode? inherited,
SelectionSetNode? fromSource)
{
if (inherited is null)
{
return fromSource;
}

if (fromSource is null)
{
return inherited;
}

var merged = new List<ISelectionNode>(inherited.Selections.Count + fromSource.Selections.Count);
merged.AddRange(inherited.Selections);
merged.AddRange(fromSource.Selections);
return new SelectionSetNode(merged);
}

Comment thread
michaelstaib marked this conversation as resolved.
private (InlineFragmentNode?, InlineFragmentNode?) RewriteFragmentNode(
Context context,
ITypeDefinition type,
Expand Down
Loading
Loading