Skip to content

Pin how type extensions behave before merging definitions - #948

Merged
oryan-block merged 1 commit into
agent-friendlyfrom
agent-friendly-p7-extension-tests
Nov 4, 2026
Merged

oryan-block merged 1 commit into
agent-friendlyfrom
agent-friendly-p7-extension-tests

Conversation

@oryan-block

Copy link
Copy Markdown
Collaborator

Why

Agents working in graphql-java-tools keep repeating the same mistakes, and the repo should change so a change that looks right from one file is right for the whole repo. With extensions it's always the same one. A type and its extensions travel separately, so every reader of a type's fields, members or interfaces has to remember withExtensions, and a reader that forgets still compiles and passes every test that has no extensions. The next PR merges each type with its extensions once. Before it moves anything, these tests pin what a user sees today, so that PR can show it changed nothing.

Description

Tests only, nothing in src/main changes.

  • one schema with a definition and an extension for every kind of type, plus Query. It checks the built types printed in declaration order, the definition and extensionDefinitions graphql-java gets, and a query through every extension field, member, value and input field, including an input that refers to itself through its extension
  • interfaces, unions, enums and scalars that only have extensions are built from the first one. Object and input extensions without a definition don't define their type: a field or argument using one fails in the scanner, an unused one is dropped without a warning, and a dictionary entry for one isn't found
  • the wrong-kind WARN for all six kind phrases, a union cycle and a union diamond through extensions, an interface used only by a field of an interface extension, a repeat in an extension naming the extension's file, and an enum used by a directive and by a field of an interface extension
  • which error wins when a repeat competes with another one. Scanner errors and the "not a Java enum" error come first, a missing enum constant comes after the repeat
  • three edge cases the next PR could change without a test noticing:
    • a type defined twice is built from its last definition, except when only its interface reaches it. Then it's built from the first one and the last one is reported as unused
    • an ignored extend scalar on an input object still counts the input as a scalar, so a Map argument gets graphql-java's coerced values (enum constants) instead of Jackson's (strings)
    • when a TypeDefinitionFactory reuses one TypeName node, a type error names its first use in a definition before any use in an extension, even when the extension is the one being built

The last two look like bugs to me, and the first one is odd at best. I pinned them instead of fixing them since this PR shouldn't change behaviour, so fixing one later is a deliberate test change.

No release note, nothing changes for library users.

Checklist

  • Pull requests follows the contribution guide
  • New or modified functionality is covered by tests

To check the tests actually catch what they claim, I ran 38 one-line mutations of src/main against the 5 test classes. Each one drops a withExtensions or an extension's directives, reverses the input field order, changes the wrong-kind WARN, reverts the extension merge, or undoes one of the edge cases above. Every new test fails under at least one of them, and every mutation fails at least one test. Six of them only fail existing tests, which already cover those spots: the two sealed-subclass lookups, nested-union discovery, implementors added by object extensions, the union repeat check and the type-error lookup in extensions.

mvn clean verify passes on JDK 17 with 452 tests, 12 more than agent-friendly.

Characterization tests for what a user sees when types have extensions: the built types for every kind, lone and orphan extensions, wrong-kind warnings, error order and source names, union cycles and diamonds through extensions, and three edge cases (a type defined twice, an ignored scalar extension on an input, a reused TypeName in type errors). They pass on the current code, so merging each type with its extensions once can show it changed nothing.
@sonarqubecloud

sonarqubecloud Bot commented Nov 4, 2026

Copy link
Copy Markdown

@oryan-block
oryan-block merged commit d754faa into agent-friendly Nov 4, 2026
5 checks passed
@oryan-block
oryan-block deleted the agent-friendly-p7-extension-tests branch November 4, 2026 20:16
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.

1 participant