Skip to content

Commit decc621

Browse files
authored
Added Fusion Base (#7363)
1 parent 76f61da commit decc621

File tree

81 files changed

+3864
-16
lines changed

Some content is hidden

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

81 files changed

+3864
-16
lines changed

src/HotChocolate/Core/src/Types/Types/Contracts/IComplexOutputType.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public interface IComplexOutputType
3030
bool IsImplementing(string typeName);
3131

3232
/// <summary>
33-
/// Defines if this type is implementing the
33+
/// Defines if this type is implementing
3434
/// the given <paramref name="interfaceType" />.
3535
/// </summary>
3636
/// <param name="interfaceType">

src/HotChocolate/Core/src/Types/Types/NamedTypeBase.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ public Type RuntimeType
7373
public Type? TypeIdentity { get; private set; }
7474

7575
/// <inheritdoc />
76-
public virtual bool IsAssignableFrom(INamedType type) =>
77-
ReferenceEquals(type, this);
76+
public virtual bool IsAssignableFrom(INamedType type)
77+
=> ReferenceEquals(type, this);
7878

7979
/// <inheritdoc />
8080
protected override void OnRegisterDependencies(
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#nullable enable
2+
namespace HotChocolate.Types.Relay;
3+
4+
public interface INodeIdRuntimeTypeLookup
5+
{
6+
Type? GetNodeIdRuntimeType(string typeName);
7+
}

src/HotChocolate/Core/src/Types/Types/Relay/Serialization/INodeIdSerializer.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,3 @@ public interface INodeIdSerializer
4848
/// </returns>
4949
NodeId Parse(string formattedId, Type runtimeType);
5050
}
51-
52-
public interface INodeIdRuntimeTypeLookup
53-
{
54-
Type? GetNodeIdRuntimeType(string typeName);
55-
}

src/HotChocolate/Fusion/HotChocolate.Fusion.sln

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HotChocolate.Fusion.Tests.S
3131
EndProject
3232
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HotChocolate.Fusion.SourceSchema", "src\SourceSchema\HotChocolate.Fusion.SourceSchema.csproj", "{5A0F102A-6BB7-484E-9898-564B27779233}"
3333
EndProject
34+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HotChocolate.Fusion.Execution", "src\Fusion.Execution\HotChocolate.Fusion.Execution.csproj", "{DB4E5071-7D99-4A7F-8C91-FCDD30CA9189}"
35+
EndProject
36+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HotChocolate.Fusion.Execution.Tests", "test\Fusion.Execution.Tests\HotChocolate.Fusion.Execution.Tests.csproj", "{12BEA757-2D4F-42ED-ACC6-57E2448CD094}"
37+
EndProject
3438
Global
3539
GlobalSection(SolutionConfigurationPlatforms) = preSolution
3640
Debug|Any CPU = Debug|Any CPU
@@ -88,6 +92,14 @@ Global
8892
{5A0F102A-6BB7-484E-9898-564B27779233}.Debug|Any CPU.Build.0 = Debug|Any CPU
8993
{5A0F102A-6BB7-484E-9898-564B27779233}.Release|Any CPU.ActiveCfg = Release|Any CPU
9094
{5A0F102A-6BB7-484E-9898-564B27779233}.Release|Any CPU.Build.0 = Release|Any CPU
95+
{DB4E5071-7D99-4A7F-8C91-FCDD30CA9189}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
96+
{DB4E5071-7D99-4A7F-8C91-FCDD30CA9189}.Debug|Any CPU.Build.0 = Debug|Any CPU
97+
{DB4E5071-7D99-4A7F-8C91-FCDD30CA9189}.Release|Any CPU.ActiveCfg = Release|Any CPU
98+
{DB4E5071-7D99-4A7F-8C91-FCDD30CA9189}.Release|Any CPU.Build.0 = Release|Any CPU
99+
{12BEA757-2D4F-42ED-ACC6-57E2448CD094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
100+
{12BEA757-2D4F-42ED-ACC6-57E2448CD094}.Debug|Any CPU.Build.0 = Debug|Any CPU
101+
{12BEA757-2D4F-42ED-ACC6-57E2448CD094}.Release|Any CPU.ActiveCfg = Release|Any CPU
102+
{12BEA757-2D4F-42ED-ACC6-57E2448CD094}.Release|Any CPU.Build.0 = Release|Any CPU
91103
EndGlobalSection
92104
GlobalSection(NestedProjects) = preSolution
93105
{BFF3B578-BAF7-4197-8DE5-091D53FB74B0} = {C831C01A-D213-4682-B19D-9946A72B0F77}
@@ -102,5 +114,7 @@ Global
102114
{0564D85A-0CC5-4029-8660-7FF15E1034FD} = {9973827C-F78F-412D-BD95-7D589C3FAA53}
103115
{7C2BD6EE-D899-4269-AA5B-5CD3CA433953} = {9973827C-F78F-412D-BD95-7D589C3FAA53}
104116
{5A0F102A-6BB7-484E-9898-564B27779233} = {C831C01A-D213-4682-B19D-9946A72B0F77}
117+
{DB4E5071-7D99-4A7F-8C91-FCDD30CA9189} = {C831C01A-D213-4682-B19D-9946A72B0F77}
118+
{12BEA757-2D4F-42ED-ACC6-57E2448CD094} = {9973827C-F78F-412D-BD95-7D589C3FAA53}
105119
EndGlobalSection
106120
EndGlobal

src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/RequestDocumentFormatter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ protected void TryForwardVariable(
586586
.First(t => t.Variable.Equals(variable, SyntaxComparison.Syntax));
587587

588588
var typeNode = originalVarDef.Type;
589-
var originalTypeName = typeNode.Name();
589+
var originalTypeName = typeNode.NamedType().Name.Value;
590590
var subgraphTypeName = _config.GetSubgraphTypeName(subgraphName, originalTypeName);
591591

592592
if (!subgraphTypeName.EqualsOrdinal(originalTypeName))
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<AssemblyName>HotChocolate.Fusion.Planning</AssemblyName>
5+
<RootNamespace>HotChocolate.Fusion</RootNamespace>
6+
<Nullable>enable</Nullable>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
11+
<PackageReference Include="Microsoft.Extensions.Http" />
12+
<PackageReference Include="System.Reactive" />
13+
</ItemGroup>
14+
15+
<ItemGroup>
16+
<ProjectReference Include="..\..\..\Language\src\Language.SyntaxTree\HotChocolate.Language.SyntaxTree.csproj" />
17+
<ProjectReference Include="..\..\..\Primitives\src\Primitives\HotChocolate.Primitives.csproj" />
18+
</ItemGroup>
19+
20+
</Project>
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
using System.Collections.Immutable;
2+
using HotChocolate.Fusion.Types;
3+
using HotChocolate.Language;
4+
5+
namespace HotChocolate.Fusion.Planning;
6+
7+
public sealed class InlineFragmentOperationRewriter(CompositeSchema schema)
8+
{
9+
public DocumentNode RewriteDocument(DocumentNode document, string? operationName)
10+
{
11+
var operation = document.GetOperation(operationName);
12+
var operationType = schema.GetOperationType(operation.Operation);
13+
var fragmentLookup = CreateFragmentLookup(document);
14+
var context = new Context(operationType, fragmentLookup);
15+
16+
RewriteFields(operation.SelectionSet, context);
17+
18+
var newSelectionSet = new SelectionSetNode(
19+
null,
20+
context.Selections.ToImmutable());
21+
22+
var newOperation = new OperationDefinitionNode(
23+
null,
24+
operation.Name,
25+
operation.Operation,
26+
operation.VariableDefinitions,
27+
RewriteDirectives(operation.Directives),
28+
newSelectionSet);
29+
30+
return new DocumentNode(ImmutableArray<IDefinitionNode>.Empty.Add(newOperation));
31+
}
32+
33+
private void RewriteFields(SelectionSetNode selectionSet, Context context)
34+
{
35+
foreach (var selection in selectionSet.Selections)
36+
{
37+
switch (selection)
38+
{
39+
case FieldNode field:
40+
RewriteField(field, context);
41+
break;
42+
43+
case InlineFragmentNode inlineFragment:
44+
RewriteInlineFragment(inlineFragment, context);
45+
break;
46+
47+
case FragmentSpreadNode fragmentSpread:
48+
InlineFragmentDefinition(fragmentSpread, context);
49+
break;
50+
}
51+
}
52+
}
53+
54+
private void RewriteField(FieldNode fieldNode, Context context)
55+
{
56+
if (fieldNode.SelectionSet is null)
57+
{
58+
context.Selections.Add(fieldNode.WithLocation(null));
59+
}
60+
else
61+
{
62+
var field = ((CompositeComplexType)context.Type).Fields[fieldNode.Name.Value];
63+
var fieldContext = context.Branch(field.Type.NamedType());
64+
65+
RewriteFields(fieldNode.SelectionSet, fieldContext);
66+
67+
var newSelectionSetNode = new SelectionSetNode(
68+
null,
69+
fieldContext.Selections.ToImmutable());
70+
71+
var newFieldNode = new FieldNode(
72+
null,
73+
fieldNode.Name,
74+
fieldNode.Alias,
75+
RewriteDirectives(fieldNode.Directives),
76+
RewriteArguments(fieldNode.Arguments),
77+
newSelectionSetNode);
78+
79+
context.Selections.Add(newFieldNode);
80+
}
81+
}
82+
83+
private void RewriteInlineFragment(InlineFragmentNode inlineFragment, Context context)
84+
{
85+
if ((inlineFragment.TypeCondition is null
86+
|| inlineFragment.TypeCondition.Name.Value.Equals(context.Type.Name, StringComparison.Ordinal))
87+
&& inlineFragment.Directives.Count == 0)
88+
{
89+
RewriteFields(inlineFragment.SelectionSet, context);
90+
return;
91+
}
92+
93+
var typeCondition = inlineFragment.TypeCondition is null
94+
? context.Type
95+
: schema.GetType(inlineFragment.TypeCondition.Name.Value);
96+
97+
var inlineFragmentContext = context.Branch(typeCondition);
98+
99+
RewriteFields(inlineFragment.SelectionSet, inlineFragmentContext);
100+
101+
var newSelectionSetNode = new SelectionSetNode(
102+
null,
103+
inlineFragmentContext.Selections.ToImmutable());
104+
105+
var newInlineFragment = new InlineFragmentNode(
106+
null,
107+
inlineFragment.TypeCondition,
108+
RewriteDirectives(inlineFragment.Directives),
109+
newSelectionSetNode);
110+
111+
context.Selections.Add(newInlineFragment);
112+
}
113+
114+
private void InlineFragmentDefinition(
115+
FragmentSpreadNode fragmentSpread,
116+
Context context)
117+
{
118+
var fragmentDefinition = context.GetFragmentDefinition(fragmentSpread.Name.Value);
119+
var typeCondition = schema.GetType(fragmentDefinition.TypeCondition.Name.Value);
120+
121+
if (fragmentSpread.Directives.Count == 0
122+
&& typeCondition.IsAssignableFrom(context.Type))
123+
{
124+
RewriteFields(fragmentDefinition.SelectionSet, context);
125+
}
126+
else
127+
{
128+
var fragmentContext = context.Branch(typeCondition);
129+
130+
RewriteFields(fragmentDefinition.SelectionSet, context);
131+
132+
var selectionSet = new SelectionSetNode(
133+
null,
134+
fragmentContext.Selections.ToImmutable());
135+
136+
var inlineFragment = new InlineFragmentNode(
137+
null,
138+
new NamedTypeNode(typeCondition.Name),
139+
RewriteDirectives(fragmentSpread.Directives),
140+
selectionSet);
141+
142+
context.Selections.Add(inlineFragment);
143+
}
144+
}
145+
146+
private IReadOnlyList<DirectiveNode> RewriteDirectives(IReadOnlyList<DirectiveNode> directives)
147+
{
148+
if (directives.Count == 0)
149+
{
150+
return directives;
151+
}
152+
153+
if (directives.Count == 1)
154+
{
155+
var directive = directives[0];
156+
var newDirective = new DirectiveNode(directive.Name.Value, RewriteArguments(directive.Arguments));
157+
return ImmutableArray<DirectiveNode>.Empty.Add(newDirective);
158+
}
159+
160+
var buffer = new DirectiveNode[directives.Count];
161+
for (var i = 0; i < buffer.Length; i++)
162+
{
163+
var directive = directives[i];
164+
buffer[i] = new DirectiveNode(directive.Name.Value, RewriteArguments(directive.Arguments));
165+
}
166+
return ImmutableArray.Create(buffer);
167+
}
168+
169+
private IReadOnlyList<ArgumentNode> RewriteArguments(IReadOnlyList<ArgumentNode> arguments)
170+
{
171+
if (arguments.Count == 0)
172+
{
173+
return arguments;
174+
}
175+
176+
if (arguments.Count == 1)
177+
{
178+
return ImmutableArray<ArgumentNode>.Empty.Add(arguments[0].WithLocation(null));
179+
}
180+
181+
var buffer = new ArgumentNode[arguments.Count];
182+
for (var i = 0; i < buffer.Length; i++)
183+
{
184+
buffer[i] = arguments[i].WithLocation(null);
185+
}
186+
return ImmutableArray.Create(buffer);
187+
}
188+
189+
private Dictionary<string, FragmentDefinitionNode> CreateFragmentLookup(DocumentNode document)
190+
{
191+
var lookup = new Dictionary<string, FragmentDefinitionNode>();
192+
193+
foreach (var definition in document.Definitions)
194+
{
195+
if (definition is FragmentDefinitionNode fragmentDef)
196+
{
197+
lookup.Add(fragmentDef.Name.Value, fragmentDef);
198+
}
199+
}
200+
201+
return lookup;
202+
}
203+
204+
public readonly ref struct Context(
205+
ICompositeNamedType type,
206+
Dictionary<string, FragmentDefinitionNode> fragments)
207+
{
208+
public ICompositeNamedType Type { get; } = type;
209+
210+
public ImmutableArray<ISelectionNode>.Builder Selections { get; } =
211+
ImmutableArray.CreateBuilder<ISelectionNode>();
212+
213+
public FragmentDefinitionNode GetFragmentDefinition(string name)
214+
=> fragments[name];
215+
216+
public Context Branch(ICompositeNamedType type)
217+
=> new(type, fragments);
218+
}
219+
}

0 commit comments

Comments
 (0)