Repository navigation
Support @tag on directive definitions - #10043
Conversation
There was a problem hiding this comment.
Pull request overview
Adds support for applying @tag to directive definitions (DIRECTIVE_DEFINITION) across HotChocolate Core and Fusion composition, while keeping Apollo Federation behavior aligned with Apollo’s canonical @tag (i.e., excluding DIRECTIVE_DEFINITION in federation mode). It also extends Fusion’s exclude-by-tag preprocessing to remove tagged directive definitions and cascade the removal to all applications, and relaxes directive-definition matching during merge to allow source schemas that declare a subset of canonical locations.
Changes:
- Extend the canonical
@tagdirective (Core + Fusion) to includeDIRECTIVE_DEFINITION, and enable tagging directive definitions via schema-first, code-first (IDirectiveTypeDescriptor.Tag(...)), and implementation-first ([Tag]on directive classes). - In Fusion preprocessing, support exclude-by-tag removal of tagged directive definitions and remove all applications of removed directives across the schema.
- In Fusion merging, treat source directive definitions as compatible with canonical definitions when their declared locations are a subset of canonical (arguments/repeatability must still match).
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/HotChocolate/Fusion/test/Fusion.Composition.Tests/SourceSchemaPreprocessorTests.cs | Adds coverage for excluding tagged directive definitions and cascading removal to all directive application sites. |
| src/HotChocolate/Fusion/test/Fusion.Composition.Tests/SourceSchemaMerger.TagDirective.Tests.cs | Updates merge tests to cover DIRECTIVE_DEFINITION and location-subset compatibility, plus a custom directive tagging scenario. |
| src/HotChocolate/Fusion/test/Fusion.Composition.Tests/snapshots/SourceSchemaPreprocessorTests.Preprocess_ExcludeByTag_RemovesTaggedDirectiveDefinitionAndCascadesToAllApplicationSites.graphql | New snapshot validating exclude-by-tag cascade results. |
| src/HotChocolate/Fusion/src/Fusion.Composition/SourceSchemaPreprocessor.cs | Implements removal of tagged directive definitions and cascaded removal of their applications. |
| src/HotChocolate/Fusion/src/Fusion.Composition/SourceSchemaMerger.cs | Switches directive-definition merge gating to compatibility (subset-of-locations) instead of strict equality. |
| src/HotChocolate/Fusion/src/Fusion.Composition/DirectiveDefinitionNodeComparer.cs | Removes the old strict structural comparer (no longer used). |
| src/HotChocolate/Fusion/src/Fusion.Composition/DirectiveDefinitionCompatibility.cs | Adds compatibility check allowing source location subsets of canonical directive definitions. |
| src/HotChocolate/Fusion/src/Fusion.Composition/Definitions/TagMutableDirectiveDefinition.cs | Updates Fusion’s canonical @tag locations to include DIRECTIVE_DEFINITION. |
| src/HotChocolate/Core/test/Types.Tests/Types/Directives/TagDirectiveTests.cs | Expands tests to cover schema-first, code-first, and implementation-first tagging including directive definitions. |
| src/HotChocolate/Core/test/Types.Tests/Types/Directives/snapshots/TagDirectiveTests.SchemaFirst_Tag.graphql | Updates snapshot to include tagging across all supported locations including directive definitions. |
| src/HotChocolate/Core/test/Types.Tests/Types/Directives/snapshots/TagDirectiveTests.CodeFirst_Tag.graphql | Updates snapshot for code-first tagging, including directive-definition tagging. |
| src/HotChocolate/Core/test/Types.Tests/Types/Directives/snapshots/TagDirectiveTests.ImplementationFirst_Tag.graphql | Adds snapshot for implementation-first tagging, including directive-definition tagging. |
| src/HotChocolate/Core/src/Types/Types/Directives/TagDirectiveExtensions.cs | Adds Tag(this IDirectiveTypeDescriptor, string) to support tagging directive definitions in code-first. |
| src/HotChocolate/Core/src/Types/Types/Directives/TagAttribute.cs | Enables [Tag] to configure IDirectiveTypeDescriptor (directive definition tagging in implementation-first). |
| src/HotChocolate/Core/src/Types/Types/Directives/Tag.cs | Extends @tag directive locations to include DIRECTIVE_DEFINITION (non-federation mode). |
| src/HotChocolate/Caching/test/Caching.Tests/SchemaTests.cs | Updates expected @tag SDL locations to include DIRECTIVE_DEFINITION. |
| src/HotChocolate/ApolloFederation/test/ApolloFederation.Tests/Directives/TagDirectiveTests.cs | Adds a federation-mode guard test asserting DIRECTIVE_DEFINITION is excluded. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Patch coverage98.6% of changed lines covered (141/143)
Uncovered changed lines (JSON){
"sha": "dfe30243209cd6df676a74b1089765ebc4802652",
"files": [
{ "path": "src/HotChocolate/Fusion/src/Fusion.Composition/DirectiveDefinitionCompatibility.cs", "ranges": [[24, 25]] }
]
}Project coverage: 52.6% (217218/413313 lines) |
Summary
DIRECTIVE_DEFINITIONas a valid location for the@tagdirective, so directive definitions can carry@tagmetadata via schema-first SDL, code-first (.Tag()onIDirectiveTypeDescriptor), and implementation-first ([Tag]on the directive class). Gated out in Apollo Federation mode to stay consistent with Apollo's@tagdefinition.@tagdefinition includesDIRECTIVE_DEFINITION; tag-based exclusion (--exclude-by-tag) removes a tagged directive definition and cascades to every application of it across the schema; and source directive definitions are matched against the canonical by location subset, so schemas declaring@tag(or any merger-backed directive) at a subset of the canonical's locations still compose, keeping existing subgraphs backward compatible.Test plan
@tagat every supported location including directive definitions; an Apollo Federation guard assertsDIRECTIVE_DEFINITIONis excluded there.@taglocation, the exclude-by-tag cascade across all application sites (schema, types, fields, arguments, enum values, input fields, directive definitions), and location-subset backward compatibility.