Skip to content

Parse SDL definitions and extensions with optional bodies, per spec#3670

Open
trevor-scheer wants to merge 11 commits intographql:mainfrom
trevor-scheer:patch-2
Open

Parse SDL definitions and extensions with optional bodies, per spec#3670
trevor-scheer wants to merge 11 commits intographql:mainfrom
trevor-scheer:patch-2

Conversation

@trevor-scheer
Copy link
Copy Markdown
Contributor

@trevor-scheer trevor-scheer commented Jul 31, 2024

The online parser required a body ({ ... }, or = ... for union) in several places where the GraphQL spec marks the body as optional, causing otherwise-valid schema documents to fail to tokenize cleanly — especially when a body-less definition or extension was followed by another definition.

This PR aligns the parser with the spec for each construct:

Construct Spec
extend schema (no root operation defs) §Schema Extension
type / extend type (no fields body) §Objects, §Object Extensions
interface / extend interface (no fields body) §Interfaces, §Interface Extensions
union / extend union (no = member list) §Unions, §Union Extensions
enum / extend enum (no values body) §Enums, §Enum Extensions
input / extend input (no fields body) §Input Objects, §Input Object Extensions

Each construct gets its own commit for easy review.

Out of scope

  • The spec also requires extensions to have at least one of { implements, directives, body } (and extend scalar to have at least one directive). The parser is already permissive around such constraints (e.g. zero-or-more Directive lists), so this PR doesn't try to enforce them — that's validator territory, not a syntax-highlighting parser.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jul 31, 2024

🦋 Changeset detected

Latest commit: 0f7148c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
graphql-language-service Patch
codemirror-graphql Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@trevor-scheer trevor-scheer changed the title Add tests for parsing schema extensions Reproduction for extend schema parsing issue Jul 31, 2024
@codecov
Copy link
Copy Markdown

codecov Bot commented Sep 30, 2024

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 65.35%. Comparing base (9f725b8) to head (b0942f9).
⚠️ Report is 149 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #3670      +/-   ##
==========================================
+ Coverage   65.32%   65.35%   +0.02%     
==========================================
  Files         122      122              
  Lines        7003     7003              
  Branches     2260     2265       +5     
==========================================
+ Hits         4575     4577       +2     
+ Misses       2411     2409       -2     
  Partials       17       17              
Files with missing lines Coverage Δ
...kages/graphql-language-service/src/parser/Rules.ts 97.27% <ø> (+1.81%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@trevor-scheer trevor-scheer changed the title Reproduction for extend schema parsing issue Parse extend schema correctly when root operations list is absent Sep 30, 2024
@trevor-scheer
Copy link
Copy Markdown
Contributor Author

@acao @yaacovCR would either of you be the right person to ping to get eyes on this? I've just updated this PR from a reproduction to a fix and would love to get this reviewed. Thanks in advance!

@yaacovCR
Copy link
Copy Markdown
Contributor

yaacovCR commented Oct 2, 2024

Sorry @trevor-scheer — I am not familiar with the code base here. Just have contributed what I could to get incremental delivery moving…

@trevor-scheer
Copy link
Copy Markdown
Contributor Author

Hey @acao, is there anything I can do to help move this along?

Comment thread .changeset/afraid-oranges-clean.md Outdated
Copy link
Copy Markdown
Member

@benjie benjie left a comment

Choose a reason for hiding this comment

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

This looks correct to me, the tests look sensible.

However; it looks like the same issue applies to object, interface, enum and input object extensions?

Actually... for those, it looks like the {...} should be optional in all cases (extension and original definition), though they appear to be required in this parser definition? It's not immediately obvious to me why schema doesn't follow that same pattern, e.g. if you can have

input Foo @oneof
scalar Bar
extend input Foo {
  int: Int
  bar: Bar
}

why could you not also have:

schema @blah
type Query {
  int: Int
}
extend schema {
  query: Query
}

Perhaps this warrants a spec tweak. That's out of scope for this PR though!

I'm unfamiliar with the parser, so I defer to someone more familiar.

@benjie
Copy link
Copy Markdown
Member

benjie commented May 19, 2025

Regarding my above comment, I did raise a spec tweak to allow schema without operation types:

graphql/graphql-spec#1166

However, Lee doesn't see value in this:

https://youtu.be/Lo0OhLoMBII?t=2754

If you have a strong use case for it, please let me know via that pull request!

Copy link
Copy Markdown
Collaborator

@dimaMachina dimaMachina left a comment

Choose a reason for hiding this comment

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

needs rebase

trevor-scheer and others added 11 commits May 6, 2026 12:36
Co-authored-by: Ted Thibodeau Jr <tthibodeau@openlinksw.com>
Per the GraphQL spec, both `ObjectTypeDefinition` and
`ObjectTypeExtension` permit omitting the `{ FieldDefinition+ }` body:

  - https://spec.graphql.org/draft/#sec-Objects
  - https://spec.graphql.org/draft/#sec-Object-Extensions

Previously the parser required the body in `ObjectTypeDef`, which made
forms like `type Foo @directive` fail to parse cleanly when followed by
another definition. Extract the body into a new `FieldDefs` rule and
make it optional. `[Kind.OBJECT_TYPE_EXTENSION]` continues to reuse
`ObjectTypeDef` and inherits the relaxed grammar.
Per the GraphQL spec, both `InterfaceTypeDefinition` and
`InterfaceTypeExtension` permit omitting the `{ FieldDefinition+ }`
body:

  - https://spec.graphql.org/draft/#sec-Interfaces
  - https://spec.graphql.org/draft/#sec-Interface-Extensions

Mark the body as optional in `InterfaceDef` (sharing the new
`FieldDefs` rule with `ObjectTypeDef`).
`[Kind.INTERFACE_TYPE_EXTENSION]` continues to reuse `InterfaceDef`
and inherits the relaxed grammar.
Per the GraphQL spec, both `UnionTypeDefinition` and
`UnionTypeExtension` permit omitting the `= NamedType | …` member list:

  - https://spec.graphql.org/draft/#sec-Unions
  - https://spec.graphql.org/draft/#sec-Union-Extensions

Extract the `=` and member list into a new `UnionMembers` rule and
mark it as optional in `UnionDef`. `[Kind.UNION_TYPE_EXTENSION]`
continues to reuse `UnionDef` and inherits the relaxed grammar.
Per the GraphQL spec, both `EnumTypeDefinition` and
`EnumTypeExtension` permit omitting the `{ EnumValueDefinition+ }`
body:

  - https://spec.graphql.org/draft/#sec-Enums
  - https://spec.graphql.org/draft/#sec-Enum-Extensions

Extract the body into a new `EnumValueDefs` rule and mark it as
optional in `EnumDef`. `[Kind.ENUM_TYPE_EXTENSION]` continues to reuse
`EnumDef` and inherits the relaxed grammar.
Per the GraphQL spec, both `InputObjectTypeDefinition` and
`InputObjectTypeExtension` permit omitting the
`{ InputValueDefinition+ }` body:

  - https://spec.graphql.org/draft/#sec-Input-Objects
  - https://spec.graphql.org/draft/#sec-Input-Object-Extensions

Extract the body into a new `InputValueDefs` rule and mark it as
optional in `InputDef`. `[Kind.INPUT_OBJECT_TYPE_EXTENSION]` continues
to reuse `InputDef` and inherits the relaxed grammar.
@trevor-scheer trevor-scheer changed the title Parse extend schema correctly when root operations list is absent Parse SDL definitions and extensions with optional bodies, per spec May 6, 2026
@trevor-scheer trevor-scheer requested a review from dimaMachina May 6, 2026 20:02
@trevor-scheer trevor-scheer enabled auto-merge (squash) May 6, 2026 20:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants