Skip to content

Reject cyclical SDL directive definitions#4385

Open
andimarek wants to merge 1 commit into
masterfrom
reproduce-4201-cyclical-directives
Open

Reject cyclical SDL directive definitions#4385
andimarek wants to merge 1 commit into
masterfrom
reproduce-4201-cyclical-directives

Conversation

@andimarek
Copy link
Copy Markdown
Member

Summary

  • Detect indirect cycles between SDL directive definitions before schema generation.
  • Preserve the existing direct self-reference error while adding a cycle-aware message for indirect references.
  • Add checker-level and schema-generation regression coverage for Improper handling of cyclical directive defs (spec issue) #4201.

Fixes #4201

Testing

  • ./gradlew test --tests graphql.schema.idl.SchemaTypeDirectivesCheckerTest --tests graphql.schema.idl.SchemaGeneratorTest."Improper handling of cyclical directive defs (spec issue) #4201 indirect cyclical directive definitions are rejected without stack overflow"
  • ./gradlew clean test --tests graphql.archunit.JMHForkArchRuleTest
  • ./gradlew test

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 18, 2026

Test Report

Test Results

Java Version Total Passed Failed Errors Skipped
Java 11 5797 (+4 🟢) 5741 (+4 🟢) 0 (±0) 0 (±0) 56 (±0)
Java 17 5797 (+4 🟢) 5740 (+4 🟢) 0 (±0) 0 (±0) 57 (±0)
Java 21 5797 (+4 🟢) 5740 (+4 🟢) 0 (±0) 0 (±0) 57 (±0)
Java 25 5797 (+4 🟢) 5740 (+4 🟢) 0 (±0) 0 (±0) 57 (±0)
jcstress 32 (±0) 32 (±0) 0 (±0) 0 (±0) 0 (±0)
Total 23220 (+16 🟢) 22993 (+16 🟢) 0 (±0) 0 (±0) 227 (±0)

Code Coverage (Java 25)

Metric Covered Missed Coverage vs Master
Lines 29480 3102 90.5% ±0.0%
Branches 8627 1507 85.1% ±0.0%
Methods 7887 1209 86.7% ±0.0%

No per-class coverage changes detected.

Full HTML report: build artifact jacoco-html-report

Updated: 2026-05-18 23:57:30 UTC

for (DirectiveDefinition directiveDefinition : directiveDefinitions) {
result.putIfAbsent(directiveDefinition.getName(), directiveDefinition);
}
return result;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Use graphql.util.FpKit#getByName(java.util.List<T>, java.util.function.Function<T,java.lang.String>, java.util.function.BinaryOperator<T>)

Less code

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done in c58ab2a. I replaced the hand-written directiveDefinitionsByName(...) map builder with FpKit#getByName(..., mergeFirst()), preserving the existing first-definition-wins behavior while removing the extra helper code.

for (DirectiveDefinition directiveDefinition : directiveDefinitions) {
result.put(directiveDefinition.getName(), directiveReferences(directiveDefinition, directiveDefinitionsByName));
}
return result;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think you can use graphql.util.FpKit#getByName(java.util.List, java.util.function.Function<T,java.lang.String>, java.util.function.BinaryOperator)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done in c58ab2a. directiveReferencesByName(...) now consumes the map produced by FpKit#getByName(..., mergeFirst()) instead of rebuilding the directive-definition map itself, so the cycle checker uses the shared local utility as suggested.

@andimarek andimarek force-pushed the reproduce-4201-cyclical-directives branch 2 times, most recently from 179dacf to b2b2d8f Compare May 18, 2026 23:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improper handling of cyclical directive defs (spec issue)

2 participants