Skip to content

Commit 55b9a4c

Browse files
authored
[Fusion] Added support for merging @cost and @listSize directives (#9057)
1 parent 35ed02f commit 55b9a4c

27 files changed

+1559
-45
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using HotChocolate.Types;
2+
using HotChocolate.Types.Mutable;
3+
4+
namespace HotChocolate.Fusion.Definitions;
5+
6+
internal sealed class CostMutableDirectiveDefinition : MutableDirectiveDefinition
7+
{
8+
public CostMutableDirectiveDefinition(MutableScalarTypeDefinition stringType)
9+
: base(DirectiveNames.Cost.Name)
10+
{
11+
Arguments.Add(
12+
new MutableInputFieldDefinition(
13+
DirectiveNames.Cost.Arguments.Weight,
14+
new NonNullType(stringType)));
15+
16+
Locations =
17+
DirectiveLocation.ArgumentDefinition
18+
| DirectiveLocation.Enum
19+
| DirectiveLocation.FieldDefinition
20+
| DirectiveLocation.InputFieldDefinition
21+
| DirectiveLocation.Object
22+
| DirectiveLocation.Scalar;
23+
}
24+
25+
public static CostMutableDirectiveDefinition Create(ISchemaDefinition schema)
26+
{
27+
if (!schema.Types.TryGetType<MutableScalarTypeDefinition>(SpecScalarNames.String.Name, out var stringType))
28+
{
29+
stringType = BuiltIns.String.Create();
30+
}
31+
32+
return new CostMutableDirectiveDefinition(stringType);
33+
}
34+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using HotChocolate.Types;
2+
using HotChocolate.Types.Mutable;
3+
using static HotChocolate.Fusion.Properties.CompositionResources;
4+
using static HotChocolate.Fusion.WellKnownArgumentNames;
5+
using static HotChocolate.Fusion.WellKnownDirectiveNames;
6+
7+
namespace HotChocolate.Fusion.Definitions;
8+
9+
/// <summary>
10+
/// The <c>@fusion__cost</c> directive specifies cost metadata for each source schema.
11+
/// </summary>
12+
internal sealed class FusionCostMutableDirectiveDefinition : MutableDirectiveDefinition
13+
{
14+
public FusionCostMutableDirectiveDefinition(
15+
MutableEnumTypeDefinition schemaMutableEnumType,
16+
MutableScalarTypeDefinition stringType)
17+
: base(FusionCost)
18+
{
19+
Description = FusionCostMutableDirectiveDefinition_Description;
20+
21+
Arguments.Add(
22+
new MutableInputFieldDefinition(Schema, new NonNullType(schemaMutableEnumType))
23+
{
24+
Description = FusionCostMutableDirectiveDefinition_Argument_Schema_Description
25+
});
26+
27+
Arguments.Add(
28+
new MutableInputFieldDefinition(Weight, new NonNullType(stringType))
29+
{
30+
Description = FusionCostMutableDirectiveDefinition_Argument_Weight_Description
31+
});
32+
33+
IsRepeatable = true;
34+
35+
Locations =
36+
DirectiveLocation.ArgumentDefinition
37+
| DirectiveLocation.Enum
38+
| DirectiveLocation.FieldDefinition
39+
| DirectiveLocation.InputFieldDefinition
40+
| DirectiveLocation.Object
41+
| DirectiveLocation.Scalar;
42+
}
43+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using HotChocolate.Types;
2+
using HotChocolate.Types.Mutable;
3+
using static HotChocolate.Fusion.Properties.CompositionResources;
4+
using static HotChocolate.Fusion.WellKnownArgumentNames;
5+
using static HotChocolate.Fusion.WellKnownDirectiveNames;
6+
7+
namespace HotChocolate.Fusion.Definitions;
8+
9+
/// <summary>
10+
/// The <c>@fusion__listSize</c> directive specifies list size metadata for each source schema.
11+
/// </summary>
12+
internal sealed class FusionListSizeMutableDirectiveDefinition : MutableDirectiveDefinition
13+
{
14+
public FusionListSizeMutableDirectiveDefinition(
15+
MutableEnumTypeDefinition schemaMutableEnumType,
16+
MutableScalarTypeDefinition intType,
17+
MutableScalarTypeDefinition stringType,
18+
MutableScalarTypeDefinition booleanType)
19+
: base(FusionListSize)
20+
{
21+
Description = FusionListSizeMutableDirectiveDefinition_Description;
22+
23+
Arguments.Add(
24+
new MutableInputFieldDefinition(Schema, new NonNullType(schemaMutableEnumType))
25+
{
26+
Description = FusionListSizeMutableDirectiveDefinition_Argument_Schema_Description
27+
});
28+
29+
Arguments.Add(
30+
new MutableInputFieldDefinition(AssumedSize, intType)
31+
{
32+
Description = FusionListSizeMutableDirectiveDefinition_Argument_AssumedSize_Description
33+
});
34+
35+
Arguments.Add(
36+
new MutableInputFieldDefinition(SlicingArguments, new ListType(new NonNullType(stringType)))
37+
{
38+
Description = FusionListSizeMutableDirectiveDefinition_Argument_SlicingArguments_Description
39+
});
40+
41+
Arguments.Add(
42+
new MutableInputFieldDefinition(SlicingArgumentDefaultValue, intType)
43+
{
44+
Description = FusionListSizeMutableDirectiveDefinition_Argument_SlicingArgumentDefaultValue_Description
45+
});
46+
47+
Arguments.Add(
48+
new MutableInputFieldDefinition(SizedFields, new ListType(new NonNullType(stringType)))
49+
{
50+
Description = FusionListSizeMutableDirectiveDefinition_Argument_SizedFields_Description
51+
});
52+
53+
Arguments.Add(
54+
new MutableInputFieldDefinition(RequireOneSlicingArgument, booleanType)
55+
{
56+
Description = FusionListSizeMutableDirectiveDefinition_Argument_RequireOneSlicingArgument_Description
57+
});
58+
59+
IsRepeatable = true;
60+
61+
Locations = DirectiveLocation.FieldDefinition;
62+
}
63+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using HotChocolate.Types;
2+
using HotChocolate.Types.Mutable;
3+
4+
namespace HotChocolate.Fusion.Definitions;
5+
6+
internal sealed class ListSizeMutableDirectiveDefinition : MutableDirectiveDefinition
7+
{
8+
public ListSizeMutableDirectiveDefinition(
9+
MutableScalarTypeDefinition intType,
10+
MutableScalarTypeDefinition stringType,
11+
MutableScalarTypeDefinition booleanType)
12+
: base(DirectiveNames.ListSize.Name)
13+
{
14+
Arguments.Add(
15+
new MutableInputFieldDefinition(
16+
DirectiveNames.ListSize.Arguments.AssumedSize,
17+
intType));
18+
19+
Arguments.Add(
20+
new MutableInputFieldDefinition(
21+
DirectiveNames.ListSize.Arguments.SlicingArguments,
22+
new ListType(new NonNullType(stringType))));
23+
24+
Arguments.Add(
25+
new MutableInputFieldDefinition(
26+
DirectiveNames.ListSize.Arguments.SlicingArgumentDefaultValue,
27+
intType));
28+
29+
Arguments.Add(
30+
new MutableInputFieldDefinition(
31+
DirectiveNames.ListSize.Arguments.SizedFields,
32+
new ListType(new NonNullType(stringType))));
33+
34+
Arguments.Add(
35+
new MutableInputFieldDefinition(
36+
DirectiveNames.ListSize.Arguments.RequireOneSlicingArgument,
37+
booleanType));
38+
39+
Locations = DirectiveLocation.FieldDefinition;
40+
}
41+
42+
public static ListSizeMutableDirectiveDefinition Create(ISchemaDefinition schema)
43+
{
44+
if (!schema.Types.TryGetType<MutableScalarTypeDefinition>(SpecScalarNames.Int.Name, out var intType))
45+
{
46+
intType = BuiltIns.Int.Create();
47+
}
48+
49+
if (!schema.Types.TryGetType<MutableScalarTypeDefinition>(SpecScalarNames.String.Name, out var stringType))
50+
{
51+
stringType = BuiltIns.String.Create();
52+
}
53+
54+
if (!schema.Types.TryGetType<MutableScalarTypeDefinition>(SpecScalarNames.Boolean.Name, out var booleanType))
55+
{
56+
booleanType = BuiltIns.Boolean.Create();
57+
}
58+
59+
return new ListSizeMutableDirectiveDefinition(intType, stringType, booleanType);
60+
}
61+
}

src/HotChocolate/Fusion-vnext/src/Fusion.Composition/DirectiveMergers/CacheControlDirectiveMerger.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using HotChocolate.Fusion.Definitions;
33
using HotChocolate.Fusion.Directives;
44
using HotChocolate.Fusion.Extensions;
5+
using HotChocolate.Fusion.Info;
56
using HotChocolate.Fusion.Options;
67
using HotChocolate.Language;
78
using HotChocolate.Types;
@@ -40,7 +41,7 @@ public override void MergeDirectiveDefinition(
4041

4142
public override void MergeDirectives(
4243
IDirectivesProvider mergedMember,
43-
ImmutableArray<IDirectivesProvider> memberDefinitions,
44+
ImmutableArray<DirectivesProviderInfo> memberDefinitions,
4445
MutableSchemaDefinition mergedSchema)
4546
{
4647
if (MergeBehavior is DirectiveMergeBehavior.Ignore)
@@ -57,7 +58,7 @@ public override void MergeDirectives(
5758
var cacheControlDirectives =
5859
memberDefinitions
5960
.SelectMany(
60-
d => d.Directives.Where(dir => dir.Name == DirectiveNames.CacheControl))
61+
d => d.Member.Directives.Where(dir => dir.Name == DirectiveNames.CacheControl))
6162
.Select(CacheControlDirective.From)
6263
.ToArray();
6364

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using System.Collections.Immutable;
2+
using System.Globalization;
3+
using HotChocolate.Fusion.Definitions;
4+
using HotChocolate.Fusion.Directives;
5+
using HotChocolate.Fusion.Extensions;
6+
using HotChocolate.Fusion.Info;
7+
using HotChocolate.Fusion.Options;
8+
using HotChocolate.Types;
9+
using HotChocolate.Types.Mutable;
10+
using ArgumentNames = HotChocolate.Fusion.WellKnownArgumentNames;
11+
using DirectiveNames = HotChocolate.Fusion.WellKnownDirectiveNames;
12+
13+
namespace HotChocolate.Fusion.DirectiveMergers;
14+
15+
internal class CostDirectiveMerger(DirectiveMergeBehavior mergeBehavior)
16+
: DirectiveMergerBase(mergeBehavior)
17+
{
18+
public override string DirectiveName => DirectiveNames.Cost;
19+
20+
public override MutableDirectiveDefinition GetCanonicalDirectiveDefinition(ISchemaDefinition schema)
21+
{
22+
return CostMutableDirectiveDefinition.Create(schema);
23+
}
24+
25+
public override void MergeDirectives(
26+
IDirectivesProvider mergedMember,
27+
ImmutableArray<DirectivesProviderInfo> memberDefinitions,
28+
MutableSchemaDefinition mergedSchema)
29+
{
30+
if (!mergedSchema.DirectiveDefinitions.TryGetDirective(DirectiveName, out var directiveDefinition))
31+
{
32+
// Merged definition not found.
33+
return;
34+
}
35+
36+
var costDirectives =
37+
memberDefinitions
38+
.SelectMany(d => d.Member.Directives.Where(dir => dir.Name == DirectiveNames.Cost))
39+
.Select(CostDirective.From)
40+
.ToArray();
41+
42+
if (costDirectives.Length == 0)
43+
{
44+
return;
45+
}
46+
47+
var maxWeight = costDirectives.Max(d => d.Weight);
48+
var weightArgument =
49+
new ArgumentAssignment(ArgumentNames.Weight, maxWeight.ToString(CultureInfo.InvariantCulture));
50+
var costDirective = new Directive(directiveDefinition, weightArgument);
51+
52+
mergedMember.AddDirective(costDirective);
53+
}
54+
}

src/HotChocolate/Fusion-vnext/src/Fusion.Composition/DirectiveMergers/DirectiveMergerBase.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections.Immutable;
2+
using HotChocolate.Fusion.Info;
23
using HotChocolate.Fusion.Options;
34
using HotChocolate.Types;
45
using HotChocolate.Types.Mutable;
@@ -27,6 +28,6 @@ public virtual void MergeDirectiveDefinition(
2728

2829
public abstract void MergeDirectives(
2930
IDirectivesProvider mergedMember,
30-
ImmutableArray<IDirectivesProvider> memberDefinitions,
31+
ImmutableArray<DirectivesProviderInfo> memberDefinitions,
3132
MutableSchemaDefinition mergedSchema);
3233
}

src/HotChocolate/Fusion-vnext/src/Fusion.Composition/DirectiveMergers/IDirectiveMerger.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections.Immutable;
2+
using HotChocolate.Fusion.Info;
23
using HotChocolate.Fusion.Options;
34
using HotChocolate.Types;
45
using HotChocolate.Types.Mutable;
@@ -19,6 +20,6 @@ void MergeDirectiveDefinition(
1920

2021
void MergeDirectives(
2122
IDirectivesProvider mergedMember,
22-
ImmutableArray<IDirectivesProvider> memberDefinitions,
23+
ImmutableArray<DirectivesProviderInfo> memberDefinitions,
2324
MutableSchemaDefinition mergedSchema);
2425
}

0 commit comments

Comments
 (0)