From 4d6d9640e351f12159eafb28fb7c2efb07042044 Mon Sep 17 00:00:00 2001 From: Trevor Scheer Date: Wed, 31 Jul 2024 12:14:52 -0700 Subject: [PATCH 1/5] Add tests for parsing schema extensions --- .../src/parser/__tests__/OnlineParser-test.ts | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/packages/graphql-language-service/src/parser/__tests__/OnlineParser-test.ts b/packages/graphql-language-service/src/parser/__tests__/OnlineParser-test.ts index 5865c78202f..29aefde41ff 100644 --- a/packages/graphql-language-service/src/parser/__tests__/OnlineParser-test.ts +++ b/packages/graphql-language-service/src/parser/__tests__/OnlineParser-test.ts @@ -66,6 +66,49 @@ describe('onlineParser', () => { t.eol(); }); + + it('parses schema extension bare', () => { + const { t } = getUtils(` + extend schema + `); + + t.keyword('extend', { kind: 'ExtendDef' }); + t.keyword('schema', { kind: 'SchemaDef' }); + + t.eol(); + }); + + it('parses schema extension with operation defs', () => { + const { t } = getUtils(` + extend schema { + query: SomeType + } + `); + + t.keyword('extend', { kind: 'ExtendDef' }); + t.keyword('schema', { kind: 'SchemaDef' }); + t.punctuation('{'); + + t.keyword('query', { kind: 'OperationTypeDef' }); + t.punctuation(':'); + t.name('SomeType'); + + t.punctuation('}', { kind: 'Document' }); + + t.eol(); + }); + + it('parses schema extension with directive applications', () => { + const { t } = getUtils(` + extend schema @someDirective + `); + + t.keyword('extend', { kind: 'ExtendDef' }); + t.keyword('schema', { kind: 'SchemaDef' }); + expectDirective({ t }, { name: 'someDirective' }); + + t.eol(); + }); it('parses short query', () => { const { t } = getUtils(` From 3ff337953bc59d8c694af4c5d9997a8594a86b9f Mon Sep 17 00:00:00 2001 From: Trevor Scheer Date: Wed, 31 Jul 2024 13:50:57 -0700 Subject: [PATCH 2/5] Add a failing test --- .../src/parser/__tests__/OnlineParser-test.ts | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/packages/graphql-language-service/src/parser/__tests__/OnlineParser-test.ts b/packages/graphql-language-service/src/parser/__tests__/OnlineParser-test.ts index 29aefde41ff..a05d4cf9c7b 100644 --- a/packages/graphql-language-service/src/parser/__tests__/OnlineParser-test.ts +++ b/packages/graphql-language-service/src/parser/__tests__/OnlineParser-test.ts @@ -66,7 +66,7 @@ describe('onlineParser', () => { t.eol(); }); - + it('parses schema extension bare', () => { const { t } = getUtils(` extend schema @@ -110,6 +110,28 @@ describe('onlineParser', () => { t.eol(); }); + it('parses schema extension with directive applications without root operation definitions, followed by a type definition', () => { + const { t } = getUtils(` + extend schema @someDirective + + type A { field: String } + `); + + t.keyword('extend', { kind: 'ExtendDef' }); + t.keyword('schema', { kind: 'SchemaDef' }); + expectDirective({ t }, { name: 'someDirective' }); + + t.keyword('type', { kind: 'ObjectTypeDef' }); + t.name('A'); + t.punctuation('{'); + t.property('field', { kind: 'FieldDef' }); + t.punctuation(':'); + t.name('String', { kind: 'NamedType' }); + t.punctuation('}'); + + t.eol(); + }); + it('parses short query', () => { const { t } = getUtils(` { From 6938c317c0ee8b406e857dfa65e3ad8882acad58 Mon Sep 17 00:00:00 2001 From: Trevor Scheer Date: Mon, 30 Sep 2024 12:56:59 -0700 Subject: [PATCH 3/5] Fix parser and update tests --- .../graphql-language-service/src/parser/Rules.ts | 16 +++++++--------- .../src/parser/__tests__/OnlineParser-test.ts | 14 +++++++------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/packages/graphql-language-service/src/parser/Rules.ts b/packages/graphql-language-service/src/parser/Rules.ts index af74ca23823..59dcdaddfee 100644 --- a/packages/graphql-language-service/src/parser/Rules.ts +++ b/packages/graphql-language-service/src/parser/Rules.ts @@ -239,14 +239,8 @@ export const ParseRules: { [name: string]: ParseRule } = { Implements: [word('implements'), list('NamedType', p('&'))], DirectiveLocation: [name('string-2')], // GraphQL schema language - SchemaDef: [ - word('schema'), - list('Directive'), - p('{'), - list('OperationTypeDef'), - p('}'), - ], - + SchemaDef: [word('schema'), list('Directive'), 'OperationTypeDefs'], + OperationTypeDefs: [p('{'), list('OperationTypeDef'), p('}')], OperationTypeDef: [name('keyword'), p(':'), name('atom')], ScalarDef: [word('scalar'), name('atom'), list('Directive')], ObjectTypeDef: [ @@ -322,7 +316,11 @@ export const ParseRules: { [name: string]: ParseRule } = { return Kind.INPUT_OBJECT_TYPE_EXTENSION; } }, - [Kind.SCHEMA_EXTENSION]: ['SchemaDef'], + [Kind.SCHEMA_EXTENSION]: [ + word('schema'), + list('Directive'), + opt('OperationTypeDefs'), + ], [Kind.SCALAR_TYPE_EXTENSION]: ['ScalarDef'], [Kind.OBJECT_TYPE_EXTENSION]: ['ObjectTypeDef'], [Kind.INTERFACE_TYPE_EXTENSION]: ['InterfaceDef'], diff --git a/packages/graphql-language-service/src/parser/__tests__/OnlineParser-test.ts b/packages/graphql-language-service/src/parser/__tests__/OnlineParser-test.ts index a05d4cf9c7b..00c490f49cb 100644 --- a/packages/graphql-language-service/src/parser/__tests__/OnlineParser-test.ts +++ b/packages/graphql-language-service/src/parser/__tests__/OnlineParser-test.ts @@ -56,7 +56,7 @@ describe('onlineParser', () => { `); t.keyword('schema', { kind: 'SchemaDef' }); - t.punctuation('{'); + t.punctuation('{', { kind: 'OperationTypeDefs' }); t.keyword('query', { kind: 'OperationTypeDef' }); t.punctuation(':'); @@ -73,7 +73,7 @@ describe('onlineParser', () => { `); t.keyword('extend', { kind: 'ExtendDef' }); - t.keyword('schema', { kind: 'SchemaDef' }); + t.keyword('schema', { kind: 'SchemaExtension' }); t.eol(); }); @@ -86,8 +86,8 @@ describe('onlineParser', () => { `); t.keyword('extend', { kind: 'ExtendDef' }); - t.keyword('schema', { kind: 'SchemaDef' }); - t.punctuation('{'); + t.keyword('schema', { kind: 'SchemaExtension' }); + t.punctuation('{', { kind: 'OperationTypeDefs' }); t.keyword('query', { kind: 'OperationTypeDef' }); t.punctuation(':'); @@ -104,7 +104,7 @@ describe('onlineParser', () => { `); t.keyword('extend', { kind: 'ExtendDef' }); - t.keyword('schema', { kind: 'SchemaDef' }); + t.keyword('schema', { kind: 'SchemaExtension' }); expectDirective({ t }, { name: 'someDirective' }); t.eol(); @@ -118,7 +118,7 @@ describe('onlineParser', () => { `); t.keyword('extend', { kind: 'ExtendDef' }); - t.keyword('schema', { kind: 'SchemaDef' }); + t.keyword('schema', { kind: 'SchemaExtension' }); expectDirective({ t }, { name: 'someDirective' }); t.keyword('type', { kind: 'ObjectTypeDef' }); @@ -127,7 +127,7 @@ describe('onlineParser', () => { t.property('field', { kind: 'FieldDef' }); t.punctuation(':'); t.name('String', { kind: 'NamedType' }); - t.punctuation('}'); + t.punctuation('}', { kind: 'Document' }); t.eol(); }); From e66383c2e420c9a79339ca50bdb995200d80bebd Mon Sep 17 00:00:00 2001 From: Trevor Scheer Date: Mon, 30 Sep 2024 13:03:55 -0700 Subject: [PATCH 4/5] changeset --- .changeset/afraid-oranges-clean.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .changeset/afraid-oranges-clean.md diff --git a/.changeset/afraid-oranges-clean.md b/.changeset/afraid-oranges-clean.md new file mode 100644 index 00000000000..2048c644bfa --- /dev/null +++ b/.changeset/afraid-oranges-clean.md @@ -0,0 +1,9 @@ +--- +'graphql-language-service': patch +--- + +fix: Correctly parse schema extensions with no root operations + +Previously, the parser gave schema extensions the same treatment as schema definitions. The requirements are slightly different, however, since a schema extension does not require a list of root operations according to the spec: https://spec.graphql.org/draft/#sec-Schema-Extension. + +The rule for parsing a schema extension is now distinct from schema definition, allowing the root operations list to be omitted. From b0942f94309d0ba3e391ebd064ebc8f1a0581838 Mon Sep 17 00:00:00 2001 From: Trevor Scheer Date: Mon, 2 Dec 2024 14:55:48 -0800 Subject: [PATCH 5/5] Update .changeset/afraid-oranges-clean.md Co-authored-by: Ted Thibodeau Jr --- .changeset/afraid-oranges-clean.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/afraid-oranges-clean.md b/.changeset/afraid-oranges-clean.md index 2048c644bfa..417922cf249 100644 --- a/.changeset/afraid-oranges-clean.md +++ b/.changeset/afraid-oranges-clean.md @@ -6,4 +6,4 @@ fix: Correctly parse schema extensions with no root operations Previously, the parser gave schema extensions the same treatment as schema definitions. The requirements are slightly different, however, since a schema extension does not require a list of root operations according to the spec: https://spec.graphql.org/draft/#sec-Schema-Extension. -The rule for parsing a schema extension is now distinct from schema definition, allowing the root operations list to be omitted. +The rule for parsing a schema extension is now distinct from that for a schema definition, allowing the root operations list to be omitted.