Skip to content

Add keyed service support to DataLoaders - #10314

Merged
michaelstaib merged 30 commits into
mainfrom
mst/dataloader-keyed-service
Aug 30, 2026
Merged

michaelstaib merged 30 commits into
mainfrom
mst/dataloader-keyed-service

Conversation

@michaelstaib

@michaelstaib michaelstaib commented Aug 30, 2026 •

Copy link
Copy Markdown
Member

Fixes #8513

Copilot AI lite review requested due to automatic review settings August 30, 2026 10:11
@github-actions github-actions Bot added 📚 documentation This issue is about working on our documentation. 🌶️ hot chocolate labels Aug 30, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends HotChocolate’s DataLoader source generator/analyzers to support resolving keyed services (via [Service("key")] and [FromKeyedServices(...)]), adds new diagnostics (HC0130–HC0133) and code fixes for keyed-service misuse, and updates docs plus unit/integration test coverage to validate the new behavior.

Changes:

  • Add keyed service detection/formatting to DataLoader parameter modeling and generation (emitting GetRequiredKeyedService / GetKeyedService where appropriate).
  • Introduce analyzers + code fixes for keyed-service attribute conflicts/invalid usage (HC0130–HC0133), including derived ServiceAttribute key extraction.
  • Add documentation and comprehensive test coverage (unit snapshots + integration tests) for keyed DataLoader services.

Reviewed changes

Copilot reviewed 34 out of 35 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
website/content/docs/hotchocolate/fetching-data/batching/dataloader.md Documents keyed services usage and new diagnostics for DataLoaders.
src/HotChocolate/Primitives/src/Primitives/ErrorCodes.cs Adds analyzer error code constants HC0130–HC0133.
src/HotChocolate/Core/test/Types.Analyzers.Tests/TestHelper.cs Registers new keyed-service analyzers in test harness.
src/HotChocolate/Core/test/Types.Analyzers.Tests/ServiceAttributeInfoTests.cs Adds unit tests for service attribute key extraction (direct/derived/metadata/from-keyed-services).
src/HotChocolate/Core/test/Types.Analyzers.Tests/DataLoaderTests.cs Adds snapshot-based generator test covering keyed service emission.
src/HotChocolate/Core/test/Types.Analyzers.Tests/DataLoaderKeyedServiceOnConstructorParameterAnalyzerTests.cs Adds tests for constructor-parameter keyed [Service] detection.
src/HotChocolate/Core/test/Types.Analyzers.Tests/DataLoaderKeyedServiceKeyNotDeterminableAnalyzerTests.cs Adds tests for undeterminable derived ServiceAttribute keys (HC0133).
src/HotChocolate/Core/test/Types.Analyzers.Tests/DataLoaderKeyedServiceConflictAnalyzerTests.cs Adds tests for conflicting keyed service attributes (HC0130).
src/HotChocolate/Core/test/Types.Analyzers.Tests/DataLoaderKeyedServiceAttributeIgnoredAnalyzerTests.cs Adds tests for keyed-service attributes applied to non-service parameters (HC0131).
src/HotChocolate/Core/test/Types.Analyzers.Tests/DataLoaderCodeFixTests.cs Adds tests for new keyed-service code fixes (remove/replace attribute while preserving trivia).
src/HotChocolate/Core/test/Types.Analyzers.Tests/snapshots/DataLoaderTests.GenerateSource_DataLoaderKeyedServices_MatchesSnapshot.md Adds expected generated source snapshot for keyed service DataLoader emission.
src/HotChocolate/Core/test/Types.Analyzers.Integration.Tests/KeyedDataLoaderIntegrationTests.cs Adds end-to-end integration tests for keyed DataLoader resolution in execution.
src/HotChocolate/Core/test/Types.Analyzers.Integration.Tests/snapshots/IntegrationTests.Schema_Snapshot.snap Updates integration schema snapshot with new keyed DataLoader fields.
src/HotChocolate/Core/test/Types.Analyzers.Integration.Tests/snapshots/IntegrationTests.Schema_Snapshot_Without_ConnectionName_Inference.snap Updates alternate schema snapshot with new keyed DataLoader fields.
src/HotChocolate/Core/test/Execution.Tests/DependencyInjectionTests.cs Adds execution tests validating keyed DataLoader resolution and inspector identity behavior.
src/HotChocolate/Core/src/Types/Fetching/ExecutionDataLoaderScope.cs Makes the DataLoader service provider keyed-aware (IKeyedServiceProvider + keyed inspector passthrough).
src/HotChocolate/Core/src/Types.Analyzers/WellKnownAttributes.cs Adds well-known type name for FromKeyedServicesAttribute.
src/HotChocolate/Core/src/Types.Analyzers/Properties/SourceGenResources.resx Adds localized messages for HC0130–HC0133 diagnostics.
src/HotChocolate/Core/src/Types.Analyzers/Properties/SourceGenResources.Designer.cs Adds strongly-typed accessors for keyed-service diagnostic messages.
src/HotChocolate/Core/src/Types.Analyzers/Models/GenericDataLoaderInfo.cs Threads Compilation into parameter creation for keyed service analysis.
src/HotChocolate/Core/src/Types.Analyzers/Models/DataLoaderParameterInfo.cs Adds keyed-service Key and nullability metadata to parameter model.
src/HotChocolate/Core/src/Types.Analyzers/Models/DataLoaderInfo.cs Adds keyed service key extraction and formatting for service parameters.
src/HotChocolate/Core/src/Types.Analyzers/Inspectors/DataLoaderInspector.cs Passes compilation to DataLoaderInfo for keyed service key computation.
src/HotChocolate/Core/src/Types.Analyzers/Helpers/SymbolExtensions.cs Adds GetServiceAttributeInfo + derived key extraction logic for ServiceAttribute.
src/HotChocolate/Core/src/Types.Analyzers/Helpers/ServiceAttributeInfo.cs Introduces a structured result for service attribute analysis.
src/HotChocolate/Core/src/Types.Analyzers/Helpers/CSharpLiteralFormatter.cs Centralizes formatting of TypedConstants into valid C# literals.
src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/TypeFileBuilderBase.cs Switches attribute instantiation to use the shared C# literal formatter.
src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/DataLoaderFileBuilder.cs Emits keyed service resolution calls when a keyed service key is present.
src/HotChocolate/Core/src/Types.Analyzers/Errors.cs Adds diagnostic descriptors for HC0130–HC0133.
src/HotChocolate/Core/src/Types.Analyzers/DataLoaderKeyedServiceOnConstructorParameterCodeFixProvider.cs Adds code fix to replace keyed [Service] with [FromKeyedServices] for constructors.
src/HotChocolate/Core/src/Types.Analyzers/DataLoaderKeyedServiceOnConstructorParameterAnalyzer.cs Adds analyzer to detect keyed [Service] on hand-written DataLoader constructors (HC0132).
src/HotChocolate/Core/src/Types.Analyzers/DataLoaderKeyedServiceKeyNotDeterminableAnalyzer.cs Adds analyzer to flag undeterminable derived service keys (HC0133).
src/HotChocolate/Core/src/Types.Analyzers/DataLoaderKeyedServiceConflictAnalyzer.cs Adds analyzer to flag conflicting keyed-service attributes (HC0130).
src/HotChocolate/Core/src/Types.Analyzers/DataLoaderKeyedServiceAttributeIgnoredCodeFixProvider.cs Adds code fix to remove keyed-service attributes that have no effect (HC0131).
src/HotChocolate/Core/src/Types.Analyzers/DataLoaderKeyedServiceAttributeIgnoredAnalyzer.cs Adds analyzer to detect keyed-service attributes applied to non-service DataLoader parameters (HC0131).
Files not reviewed (1)
  • src/HotChocolate/Core/src/Types.Analyzers/Properties/SourceGenResources.Designer.cs: Generated file

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +249 to +259
var serviceAttributeInfo = parameter.GetServiceAttributeInfo(compilation);
var key = serviceAttributeInfo.HasServiceAttribute
? serviceAttributeInfo.ServiceKey is { } serviceKey
? CSharpLiteralFormatter.FormatTypedConstant(serviceKey)
: serviceAttributeInfo.SourceDerivedServiceKey is { } sourceDerivedServiceKey
? CSharpLiteralFormatter.FormatPrimitive(sourceDerivedServiceKey)
: null
: serviceAttributeInfo.HasFromKeyedServicesAttribute
&& serviceAttributeInfo.FromKeyedServicesKey is { } fromKeyedServicesKey
? CSharpLiteralFormatter.FormatTypedConstant(fromKeyedServicesKey)
: null;
Comment on lines +98 to +110
if (attributeType.ToDisplayString() == WellKnownAttributes.ServiceAttribute)
{
return attributeConstructor.Parameters.Length == 1;
}

var attributeData = parameter.GetAttributes().FirstOrDefault(t =>
t.ApplicationSyntaxReference is { } syntaxReference
&& syntaxReference.SyntaxTree == attribute.SyntaxTree
&& syntaxReference.Span == attribute.Span);

return attributeData?.GetDerivedServiceKey(compilation, out _)
== SymbolExtensions.ServiceKeyExtractionResult.Key;
}
}
```

For attributes derived from `ServiceAttribute`, the constructor chain must be available in source and the string passed to the `ServiceAttribute` base constructor must be statically determinable. If `HC0133` remains, apply the key directly with `[Service("key")]` or `[FromKeyedServices(key)]`. Keys can be any constant, including strings, enum values, and integers. `KeyedService.AnyKey` is not supported.
@github-actions

github-actions Bot commented Aug 30, 2026 •

Copy link
Copy Markdown
Contributor

Patch coverage

84.6% of changed lines covered (703/831)

File Covered Changed Patch %
…/Expressions/Parameters/ServiceParameterExpressionBuilder.cs 2 7 28.6% 🔴
…/Core/src/Types.Analyzers/Helpers/CSharpLiteralFormatter.cs 48 81 59.3% 🔴
…/Core/src/Types.Analyzers/FileBuilders/TypeFileBuilderBase.cs 2 3 66.7% 🔴
…/Core/src/Types/Fetching/ExecutionDataLoaderScope.cs 21 31 67.7% 🔴
…/Core/src/Types.Analyzers/Helpers/SymbolExtensions.cs 257 319 80.6% 🟡
…/DataLoaderKeyedServiceAttributeIgnoredCodeFixProvider.cs 31 37 83.8% 🟡
src/HotChocolate/Core/src/Abstractions/ServiceAttribute.cs 6 7 85.7% 🟡
…/DataLoaderKeyedServiceOnConstructorParameterCodeFixProvider.cs 36 42 85.7% 🟡
…/DataLoaderKeyedServiceKeyNotDeterminableAnalyzer.cs 47 49 95.9% 🟡
…/DataLoaderKeyedServiceAttributeIgnoredAnalyzer.cs 68 70 97.1% 🟡
…/Types.Analyzers/DataLoaderKeyedServiceConflictAnalyzer.cs 38 38 100.0% 🟢
…/DataLoaderKeyedServiceOnConstructorParameterAnalyzer.cs 58 58 100.0% 🟢
src/HotChocolate/Core/src/Types.Analyzers/Errors.cs 32 32 100.0% 🟢
…/src/Types.Analyzers/FileBuilders/DataLoaderFileBuilder.cs 17 17 100.0% 🟢
…/Core/src/Types.Analyzers/Helpers/ServiceAttributeInfo.cs 9 9 100.0% 🟢
…/Core/src/Types.Analyzers/Inspectors/DataLoaderInspector.cs 2 2 100.0% 🟢
…/Core/src/Types.Analyzers/Models/DataLoaderInfo.cs 18 18 100.0% 🟢
…/Core/src/Types.Analyzers/Models/DataLoaderParameterInfo.cs 6 6 100.0% 🟢
…/Core/src/Types.Analyzers/Models/GenericDataLoaderInfo.cs 5 5 100.0% 🟢
Uncovered changed lines (JSON)
{
  "sha": "3f42145f622f7581753d601692965baa7913d60e",
  "files": [
    { "path": "src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ServiceParameterExpressionBuilder.cs", "ranges": [[56, 56], [60, 60], [71, 71], [74, 75]] },
    { "path": "src/HotChocolate/Core/src/Types.Analyzers/Helpers/CSharpLiteralFormatter.cs", "ranges": [[19, 20], [27, 28], [34, 34], [36, 40], [56, 62], [65, 67], [72, 73], [108, 118]] },
    { "path": "src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/TypeFileBuilderBase.cs", "ranges": [[1819, 1819]] },
    { "path": "src/HotChocolate/Core/src/Types/Fetching/ExecutionDataLoaderScope.cs", "ranges": [[104, 109], [144, 145], [147, 148]] },
    { "path": "src/HotChocolate/Core/src/Types.Analyzers/Helpers/SymbolExtensions.cs", "ranges": [[857, 860], [939, 940], [961, 962], [983, 991], [994, 994], [1013, 1014], [1045, 1046], [1070, 1071], [1083, 1086], [1125, 1127], [1161, 1162], [1171, 1172], [1183, 1184], [1214, 1221], [1223, 1225], [1250, 1252], [1279, 1281], [1304, 1308], [1316, 1318]] },
    { "path": "src/HotChocolate/Core/src/Types.Analyzers/DataLoaderKeyedServiceAttributeIgnoredCodeFixProvider.cs", "ranges": [[27, 28], [37, 38], [57, 58]] },
    { "path": "src/HotChocolate/Core/src/Abstractions/ServiceAttribute.cs", "ranges": [[45, 45]] },
    { "path": "src/HotChocolate/Core/src/Types.Analyzers/DataLoaderKeyedServiceOnConstructorParameterCodeFixProvider.cs", "ranges": [[17, 17], [21, 21], [29, 30], [75, 76]] },
    { "path": "src/HotChocolate/Core/src/Types.Analyzers/DataLoaderKeyedServiceKeyNotDeterminableAnalyzer.cs", "ranges": [[64, 65]] },
    { "path": "src/HotChocolate/Core/src/Types.Analyzers/DataLoaderKeyedServiceAttributeIgnoredAnalyzer.cs", "ranges": [[82, 83]] }
  ]
}

Project coverage: 57.7% (285877/495692 lines)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📚 documentation This issue is about working on our documentation. 🌶️ hot chocolate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Keyed services can't be injected into data loaders

2 participants