Omit requireOneSlicingArgument if not set in listSize directive#7418
Omit requireOneSlicingArgument if not set in listSize directive#7418
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #7418 +/- ##
=======================================
Coverage 74.13% 74.13%
=======================================
Files 2674 2674
Lines 140657 140661 +4
Branches 16358 16358
=======================================
+ Hits 104282 104286 +4
- Misses 30780 30783 +3
+ Partials 5595 5592 -3
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Adjusts how @listSize is represented so that requireOneSlicingArgument is not emitted into SDL unless it was explicitly set, addressing #7398.
Changes:
- Track whether
RequireOneSlicingArgumentwas explicitly set onListSizeAttributeand forward a nullable value into the directive. - Simplify
ListSizeDirectiveto storeRequireOneSlicingArgumentas provided (nullable) so formatting can omit it. - Add a snapshot-based test verifying SDL output for omitted/explicit
requireOneSlicingArgument.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/HotChocolate/CostAnalysis/test/CostAnalysis.Tests/AttributeTests.cs | Adds coverage asserting SDL printing behavior for @listSize with and without requireOneSlicingArgument. |
| src/HotChocolate/CostAnalysis/src/CostAnalysis/Types/ListSizeDirective.cs | Changes directive construction to preserve “unset” (null) for RequireOneSlicingArgument. |
| src/HotChocolate/CostAnalysis/src/CostAnalysis/Types/ListSizeAttribute.cs | Adds nullable backing field so the attribute can distinguish “unset” vs explicit values and omit the SDL argument accordingly. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| AssumedSize = assumedSize; | ||
| SlicingArguments = slicingArguments ?? []; | ||
| SizedFields = sizedFields ?? []; | ||
| SlicingArgumentDefaultValue = slicingArgumentDefaultValue; | ||
|
|
||
| // https://ibm.github.io/graphql-specs/cost-spec.html#sec-requireOneSlicingArgument | ||
| // Per default, requireOneSlicingArgument is enabled, | ||
| // and has to be explicitly disabled if not desired for a field. | ||
| RequireOneSlicingArgument = SlicingArguments is { Length: > 0 } && (requireOneSlicingArgument ?? true); | ||
| RequireOneSlicingArgument = requireOneSlicingArgument; | ||
| } |
There was a problem hiding this comment.
Changing ListSizeDirective to assign RequireOneSlicingArgument = requireOneSlicingArgument removes the previous defaulting behavior (enabled by default when SlicingArguments are provided). Since ValidateRequireOneSlicingArgument treats null as false, fields that specify slicingArguments but omit requireOneSlicingArgument will no longer enforce the directive type’s default (DefaultValue(true)), changing runtime cost-analysis semantics. Consider restoring the effective default (e.g., treat null as true when slicing arguments are present) while still omitting the argument from SDL when it wasn’t explicitly set.
| SlicingArguments?.ToImmutableArray(), | ||
| SizedFields?.ToImmutableArray(), | ||
| RequireOneSlicingArgument)); | ||
| _requireOneSlicingArgument)); |
There was a problem hiding this comment.
ListSizeAttribute.OnConfigure now forwards _requireOneSlicingArgument (nullable) instead of the RequireOneSlicingArgument property (defaulting to true). This means leaving the attribute property unset will produce a directive value of null even when SlicingArguments are provided, which (given current validation logic) effectively disables requireOneSlicingArgument by default. If the intended default remains true (as indicated by ListSizeDirectiveType), consider applying that default during analysis/validation when the backing field is null.
| _requireOneSlicingArgument)); | |
| RequireOneSlicingArgument)); |
| // assert | ||
| listSizeDirective1Sdl.MatchInlineSnapshot("@listSize(assumedSize: 10)"); | ||
| listSizeDirective2Sdl.MatchInlineSnapshot("@listSize(requireOneSlicingArgument: true)"); | ||
| listSizeDirective3Sdl.MatchInlineSnapshot("@listSize(requireOneSlicingArgument: false)"); |
There was a problem hiding this comment.
The new snapshot test covers SDL omission when only AssumedSize is set, but it doesn’t cover the case where SlicingArguments are set and RequireOneSlicingArgument is left unset. Adding an assertion for that combination would help ensure the SDL omission change doesn’t unintentionally change the effective default behavior during cost analysis (per the directive argument default).
| listSizeDirective3Sdl.MatchInlineSnapshot("@listSize(requireOneSlicingArgument: false)"); | |
| listSizeDirective3Sdl.MatchInlineSnapshot("@listSize(requireOneSlicingArgument: false)"); | |
| // and the omitted argument still respects the directive default at runtime | |
| var listSizeDirective1 = query.Fields["examplesAssumedSizeOnly"] | |
| .Directives | |
| .Single(d => d.Type.Name == "listSize") | |
| .ToValue<ListSizeDirective>(); | |
| Assert.True(listSizeDirective1.RequireOneSlicingArgument); |
Summary of the changes (Less than 80 chars)
Closes #7398