Skip to content

Commit 1143b21

Browse files
[Fusion] Fixed possible lookup selection (#8625)
Co-authored-by: tobias-tengler <[email protected]>
1 parent b5f7da0 commit 1143b21

Some content is hidden

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

43 files changed

+384
-516
lines changed

src/HotChocolate/Fusion-vnext/src/Fusion.Execution.Types/Collections/SourceInterfaceTypeCollection.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Collections.Immutable;
22
using System.Diagnostics.CodeAnalysis;
3+
using HotChocolate.Fusion.Types.Metadata;
34

45
namespace HotChocolate.Fusion.Types.Collections;
56

src/HotChocolate/Fusion-vnext/src/Fusion.Execution.Types/Collections/SourceMemberCollection.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Frozen;
33
using System.Collections.Immutable;
44
using System.Diagnostics.CodeAnalysis;
5+
using HotChocolate.Fusion.Types.Metadata;
56

67
namespace HotChocolate.Fusion.Types.Collections;
78

src/HotChocolate/Fusion-vnext/src/Fusion.Execution.Types/Collections/SourceObjectFieldCollection.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using HotChocolate.Fusion.Types.Metadata;
2+
13
namespace HotChocolate.Fusion.Types.Collections;
24

35
public class SourceObjectFieldCollection(IEnumerable<SourceOutputField> members)

src/HotChocolate/Fusion-vnext/src/Fusion.Execution.Types/Collections/SourceObjectTypeCollection.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Collections.Immutable;
22
using System.Diagnostics.CodeAnalysis;
3+
using HotChocolate.Fusion.Types.Metadata;
34

45
namespace HotChocolate.Fusion.Types.Collections;
56

src/HotChocolate/Fusion-vnext/src/Fusion.Execution.Types/Collections/SourceUnionTypeCollection.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using HotChocolate.Fusion.Types.Metadata;
2+
13
namespace HotChocolate.Fusion.Types.Collections;
24

35
public class SourceUnionTypeCollection(IEnumerable<SourceUnionType> members)

src/HotChocolate/Fusion-vnext/src/Fusion.Execution.Types/Completion/CompletionTools.cs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using HotChocolate.Fusion.Language;
44
using HotChocolate.Fusion.Types.Collections;
55
using HotChocolate.Fusion.Types.Directives;
6+
using HotChocolate.Fusion.Types.Metadata;
67
using HotChocolate.Language;
78
using HotChocolate.Types;
89

@@ -97,22 +98,28 @@ public static SourceObjectTypeCollection CreateSourceObjectTypeCollection(
9798
{
9899
var types = TypeDirectiveParser.Parse(typeDef.Directives);
99100
var lookupDirectives = LookupDirectiveParser.Parse(typeDef.Directives);
100-
var temp = new SourceObjectType[types.Length];
101+
var sourceObjectType = new SourceObjectType[types.Length];
102+
var sourceImplements = ImplementsDirectiveParser.Parse(typeDef.Directives);
103+
var sourceUnionMembersOf = context.GetSourceUnionMembers(typeDef.Name.Value);
101104

102105
for (var i = 0; i < types.Length; i++)
103106
{
104107
var type = types[i];
105108
var schemaName = context.GetSchemaName(type.SchemaKey);
106109
var lookups = GetLookupBySchema(lookupDirectives, schemaName, typeDef.Name.Value, context);
107110
context.RegisterForCompletionRange(lookups);
111+
sourceImplements.TryGetValue(type.SchemaKey, out var implements);
112+
sourceUnionMembersOf.TryGetValue(type.SchemaKey, out var unionTypes);
108113

109-
temp[i] = new SourceObjectType(
114+
sourceObjectType[i] = new SourceObjectType(
110115
typeDef.Name.Value,
111116
schemaName,
112-
lookups);
117+
lookups,
118+
implements ?? ImmutableHashSet<string>.Empty,
119+
unionTypes ?? ImmutableHashSet<string>.Empty);
113120
}
114121

115-
return new SourceObjectTypeCollection(temp);
122+
return new SourceObjectTypeCollection(sourceObjectType);
116123
}
117124

118125
public static SourceInterfaceTypeCollection CreateSourceInterfaceTypeCollection(
@@ -121,22 +128,26 @@ public static SourceInterfaceTypeCollection CreateSourceInterfaceTypeCollection(
121128
{
122129
var types = TypeDirectiveParser.Parse(typeDef.Directives);
123130
var lookupDirectives = LookupDirectiveParser.Parse(typeDef.Directives);
124-
var temp = new SourceInterfaceType[types.Length];
131+
var sourceInterfaceType = new SourceInterfaceType[types.Length];
132+
var sourceImplements = ImplementsDirectiveParser.Parse(
133+
typeDef.Directives);
125134

126135
for (var i = 0; i < types.Length; i++)
127136
{
128137
var type = types[i];
129138
var schemaName = context.GetSchemaName(type.SchemaKey);
130139
var lookups = GetLookupBySchema(lookupDirectives, schemaName, typeDef.Name.Value, context);
131140
context.RegisterForCompletionRange(lookups);
141+
sourceImplements.TryGetValue(type.SchemaKey, out var implements);
132142

133-
temp[i] = new SourceInterfaceType(
143+
sourceInterfaceType[i] = new SourceInterfaceType(
134144
typeDef.Name.Value,
135145
schemaName,
136-
lookups);
146+
lookups,
147+
implements ?? ImmutableHashSet<string>.Empty);
137148
}
138149

139-
return new SourceInterfaceTypeCollection(temp);
150+
return new SourceInterfaceTypeCollection(sourceInterfaceType);
140151
}
141152

142153
public static SourceUnionTypeCollection CreateSourceUnionTypeCollection(

src/HotChocolate/Fusion-vnext/src/Fusion.Execution.Types/Completion/CompositeSchemaBuilder.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using HotChocolate.Fusion.Rewriters;
77
using HotChocolate.Fusion.Types.Collections;
88
using HotChocolate.Fusion.Types.Directives;
9+
using HotChocolate.Fusion.Types.Metadata;
910
using HotChocolate.Language;
1011
using HotChocolate.Types;
1112
using Microsoft.Extensions.DependencyInjection;
@@ -123,6 +124,7 @@ private static CompositeSchemaBuilderContext CreateTypes(
123124
features ??= new FeatureCollection();
124125

125126
return new CompositeSchemaBuilderContext(
127+
schemaDocument,
126128
name,
127129
description,
128130
services,

src/HotChocolate/Fusion-vnext/src/Fusion.Execution.Types/Completion/CompositeSchemaContext.cs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using HotChocolate.Features;
33
using HotChocolate.Fusion.Types.Collections;
44
using HotChocolate.Fusion.Types.Directives;
5+
using HotChocolate.Fusion.Types.Metadata;
56
using HotChocolate.Language;
67
using HotChocolate.Types;
78
using DirectiveLocation = HotChocolate.Types.DirectiveLocation;
@@ -10,14 +11,17 @@ namespace HotChocolate.Fusion.Types.Completion;
1011

1112
internal sealed class CompositeSchemaBuilderContext : ICompositeSchemaBuilderContext
1213
{
14+
private readonly DocumentNode _document;
1315
private readonly Dictionary<ITypeNode, IType> _compositeTypes = new(SyntaxComparer.BySyntax);
1416
private readonly Dictionary<string, ITypeDefinition> _typeDefinitionLookup;
1517
private ImmutableDictionary<string, ITypeDefinitionNode> _typeDefinitionNodeLookup;
1618
private readonly Dictionary<string, FusionDirectiveDefinition> _directiveDefinitionLookup;
1719
private ImmutableDictionary<string, DirectiveDefinitionNode> _directiveDefinitionNodeLookup;
1820
private readonly List<INeedsCompletion> _completions = [];
21+
private readonly ImmutableDictionary<string, ImmutableDictionary<SchemaKey, ImmutableHashSet<string>>> _sourceUnions;
1922

2023
public CompositeSchemaBuilderContext(
24+
DocumentNode document,
2125
string name,
2226
string? description,
2327
IServiceProvider services,
@@ -33,6 +37,9 @@ public CompositeSchemaBuilderContext(
3337
IFeatureCollection features,
3438
CompositeTypeInterceptor interceptor)
3539
{
40+
_document = document;
41+
_sourceUnions = UnionMemberDirectiveParser.Parse(document.Definitions.OfType<UnionTypeDefinitionNode>());
42+
3643
_typeDefinitionLookup = typeDefinitions.ToDictionary(t => t.Name);
3744
_directiveDefinitionLookup = directiveDefinitions.ToDictionary(t => t.Name);
3845
_typeDefinitionNodeLookup = typeDefinitionNodeLookup;
@@ -183,18 +190,21 @@ private static IType CreateType(ITypeNode typeNode, ITypeDefinition compositeNam
183190
}
184191

185192
public FusionDirectiveDefinition GetDirectiveType(string name)
186-
{
187-
if (_directiveDefinitionLookup.TryGetValue(name, out var type))
188-
{
189-
return type;
190-
}
191-
192-
throw new InvalidOperationException();
193-
}
193+
=> _directiveDefinitionLookup.TryGetValue(name, out var type)
194+
? type
195+
: throw new InvalidOperationException();
194196

195197
public string GetSchemaName(SchemaKey schemaKey)
196198
=> SourceSchemaLookup[schemaKey.Value].Name;
197199

200+
public ImmutableDictionary<SchemaKey, ImmutableHashSet<string>> GetSourceUnionMembers(
201+
string objectTypeName)
202+
{
203+
return _sourceUnions.TryGetValue(objectTypeName, out var sourceUnions)
204+
? sourceUnions
205+
: ImmutableDictionary<SchemaKey, ImmutableHashSet<string>>.Empty;
206+
}
207+
198208
private void AddSpecDirectives()
199209
{
200210
var directive = CreateSkipDirective();

src/HotChocolate/Fusion-vnext/src/Fusion.Execution.Types/Contracts/ISourceMember.cs

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using System.Collections.Immutable;
2+
using HotChocolate.Fusion.Types.Completion;
3+
using HotChocolate.Language;
4+
5+
namespace HotChocolate.Fusion.Types.Directives;
6+
7+
/*
8+
directive @fusion__implements(
9+
schema: fusion__Schema!
10+
interface: String!
11+
) repeatable on OBJECT | INTERFACE
12+
*/
13+
internal static class ImplementsDirectiveParser
14+
{
15+
public static ImmutableDictionary<SchemaKey, ImmutableHashSet<string>> Parse(
16+
IReadOnlyList<DirectiveNode> directiveNodes)
17+
{
18+
Dictionary<SchemaKey, ImmutableHashSet<string>.Builder>? temp = null;
19+
20+
foreach (var directive in directiveNodes)
21+
{
22+
if (directive.Name.Value.Equals(FusionBuiltIns.Implements, StringComparison.Ordinal))
23+
{
24+
temp ??= new Dictionary<SchemaKey, ImmutableHashSet<string>.Builder>();
25+
26+
var schemaValue = directive.Arguments.FirstOrDefault(t => t.Name.Value == "schema")?.Value;
27+
var interfaceValue = directive.Arguments.FirstOrDefault(t => t.Name.Value == "interface")?.Value;
28+
29+
if (schemaValue is not EnumValueNode { Value: { Length: > 0 } schemaName })
30+
{
31+
throw new InvalidOperationException(
32+
$"The directive `@fusion__implements` has an invalid value for `schema`.\r\n{directive}");
33+
}
34+
35+
if (interfaceValue is not StringValueNode { Value.Length: > 0 } interfaceName)
36+
{
37+
throw new InvalidOperationException(
38+
$"The directive `@fusion__implements` has an invalid value for `interface`.\r\n{directive}");
39+
}
40+
41+
var schemaKey = new SchemaKey(schemaName);
42+
43+
if(!temp.TryGetValue(schemaKey, out var implements))
44+
{
45+
implements = ImmutableHashSet.CreateBuilder<string>();
46+
temp.Add(schemaKey, implements);
47+
}
48+
49+
implements.Add(interfaceName.Value);
50+
}
51+
}
52+
53+
return temp is null
54+
? ImmutableDictionary<SchemaKey, ImmutableHashSet<string>>.Empty
55+
: temp.ToImmutableDictionary(t => t.Key, t => t.Value.ToImmutable());
56+
}
57+
}

0 commit comments

Comments
 (0)