Skip to content

Commit 6d3b630

Browse files
committed
Add support for directives on directive definitions
1 parent d26810b commit 6d3b630

18 files changed

Lines changed: 114 additions & 5 deletions

src/__testUtils__/kitchenSinkSDL.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,8 @@ extend schema @onSchema
161161
extend schema @onSchema {
162162
subscription: SubscriptionType
163163
}
164+
165+
directive @myDirective @onDirective on OBJECT | FIELD_DEFINITION
166+
167+
extend directive @myDirective @onDirective2
164168
`;

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ export type {
312312
UnionTypeExtensionNode,
313313
EnumTypeExtensionNode,
314314
InputObjectTypeExtensionNode,
315+
DirectiveExtensionNode,
315316
// Schema Coordinates
316317
SchemaCoordinateNode,
317318
TypeCoordinateNode,

src/language/__tests__/predicates-test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ describe('AST node predicates', () => {
3939
'InputObjectTypeDefinition',
4040
'DirectiveDefinition',
4141
'SchemaExtension',
42+
'DirectiveExtension',
4243
'ScalarTypeExtension',
4344
'ObjectTypeExtension',
4445
'InterfaceTypeExtension',
@@ -123,6 +124,7 @@ describe('AST node predicates', () => {
123124
it('isTypeSystemExtensionNode', () => {
124125
expect(filterNodes(isTypeSystemExtensionNode)).to.deep.equal([
125126
'SchemaExtension',
127+
'DirectiveExtension',
126128
'ScalarTypeExtension',
127129
'ObjectTypeExtension',
128130
'InterfaceTypeExtension',

src/language/__tests__/schema-parser-test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,7 @@ input Hello {
10291029
{
10301030
kind: 'DirectiveDefinition',
10311031
description: undefined,
1032+
directives: [],
10321033
name: {
10331034
kind: 'Name',
10341035
value: 'foo',
@@ -1065,6 +1066,7 @@ input Hello {
10651066
{
10661067
kind: 'DirectiveDefinition',
10671068
description: undefined,
1069+
directives: [],
10681070
name: {
10691071
kind: 'Name',
10701072
value: 'foo',

src/language/__tests__/schema-printer-test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,10 @@ describe('Printer: SDL document', () => {
178178
extend schema @onSchema {
179179
subscription: SubscriptionType
180180
}
181+
182+
directive @myDirective @onDirective on OBJECT | FIELD_DEFINITION
183+
184+
extend directive @myDirective @onDirective2
181185
`);
182186
});
183187
});

src/language/ast.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ export type ASTNode =
180180
| UnionTypeExtensionNode
181181
| EnumTypeExtensionNode
182182
| InputObjectTypeExtensionNode
183+
| DirectiveExtensionNode
183184
| TypeCoordinateNode
184185
| MemberCoordinateNode
185186
| ArgumentCoordinateNode
@@ -280,10 +281,18 @@ export const QueryDocumentKeys: {
280281
EnumValueDefinition: ['description', 'name', 'directives'],
281282
InputObjectTypeDefinition: ['description', 'name', 'directives', 'fields'],
282283

283-
DirectiveDefinition: ['description', 'name', 'arguments', 'locations'],
284+
DirectiveDefinition: [
285+
'description',
286+
'name',
287+
'arguments',
288+
'directives',
289+
'locations',
290+
],
284291

285292
SchemaExtension: ['directives', 'operationTypes'],
286293

294+
DirectiveExtension: ['name', 'directives'],
295+
287296
ScalarTypeExtension: ['name', 'directives'],
288297
ObjectTypeExtension: ['name', 'interfaces', 'directives', 'fields'],
289298
InterfaceTypeExtension: ['name', 'interfaces', 'directives', 'fields'],
@@ -686,13 +695,17 @@ export interface DirectiveDefinitionNode {
686695
readonly description?: StringValueNode;
687696
readonly name: NameNode;
688697
readonly arguments?: ReadonlyArray<InputValueDefinitionNode>;
698+
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
689699
readonly repeatable: boolean;
690700
readonly locations: ReadonlyArray<NameNode>;
691701
}
692702

693703
/** Type System Extensions */
694704

695-
export type TypeSystemExtensionNode = SchemaExtensionNode | TypeExtensionNode;
705+
export type TypeSystemExtensionNode =
706+
| SchemaExtensionNode
707+
| TypeExtensionNode
708+
| DirectiveExtensionNode;
696709

697710
export interface SchemaExtensionNode {
698711
readonly kind: Kind.SCHEMA_EXTENSION;
@@ -760,6 +773,13 @@ export interface InputObjectTypeExtensionNode {
760773
readonly fields?: ReadonlyArray<InputValueDefinitionNode>;
761774
}
762775

776+
export interface DirectiveExtensionNode {
777+
readonly kind: Kind.DIRECTIVE_EXTENSION;
778+
readonly loc?: Location;
779+
readonly name: NameNode;
780+
readonly directives?: ReadonlyArray<ConstDirectiveNode>;
781+
}
782+
763783
/** Schema Coordinates */
764784

765785
export type SchemaCoordinateNode =

src/language/directiveLocation.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ enum DirectiveLocation {
2323
ENUM_VALUE = 'ENUM_VALUE',
2424
INPUT_OBJECT = 'INPUT_OBJECT',
2525
INPUT_FIELD_DEFINITION = 'INPUT_FIELD_DEFINITION',
26+
DIRECTIVE_DEFINITION = 'DIRECTIVE_DEFINITION',
2627
}
2728
export { DirectiveLocation };
2829

src/language/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ export type {
9696
UnionTypeExtensionNode,
9797
EnumTypeExtensionNode,
9898
InputObjectTypeExtensionNode,
99+
DirectiveExtensionNode,
99100
// Schema Coordinates
100101
SchemaCoordinateNode,
101102
TypeCoordinateNode,

src/language/kinds.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ enum Kind {
5858

5959
/** Type System Extensions */
6060
SCHEMA_EXTENSION = 'SchemaExtension',
61+
DIRECTIVE_EXTENSION = 'DirectiveExtension',
6162

6263
/** Type Extensions */
6364
SCALAR_TYPE_EXTENSION = 'ScalarTypeExtension',

src/language/parser.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import type {
1717
DirectiveArgumentCoordinateNode,
1818
DirectiveCoordinateNode,
1919
DirectiveDefinitionNode,
20+
DirectiveExtensionNode,
2021
DirectiveNode,
2122
DocumentNode,
2223
EnumTypeDefinitionNode,
@@ -1184,6 +1185,7 @@ export class Parser {
11841185
* - UnionTypeExtension
11851186
* - EnumTypeExtension
11861187
* - InputObjectTypeDefinition
1188+
* - DirectiveDefinitionExtension
11871189
*/
11881190
parseTypeSystemExtension(): TypeSystemExtensionNode {
11891191
const keywordToken = this._lexer.lookahead();
@@ -1204,6 +1206,8 @@ export class Parser {
12041206
return this.parseEnumTypeExtension();
12051207
case 'input':
12061208
return this.parseInputObjectTypeExtension();
1209+
case 'directive':
1210+
return this.parseDirectiveDefinitionExtension();
12071211
}
12081212
}
12091213

@@ -1386,6 +1390,23 @@ export class Parser {
13861390
});
13871391
}
13881392

1393+
parseDirectiveDefinitionExtension(): DirectiveExtensionNode {
1394+
const start = this._lexer.token;
1395+
this.expectKeyword('extend');
1396+
this.expectKeyword('directive');
1397+
this.expectToken(TokenKind.AT);
1398+
const name = this.parseName();
1399+
const directives = this.parseConstDirectives();
1400+
if (directives.length === 0) {
1401+
throw this.unexpected();
1402+
}
1403+
return this.node<DirectiveExtensionNode>(start, {
1404+
kind: Kind.DIRECTIVE_EXTENSION,
1405+
name,
1406+
directives,
1407+
});
1408+
}
1409+
13891410
/**
13901411
* ```
13911412
* DirectiveDefinition :
@@ -1399,6 +1420,7 @@ export class Parser {
13991420
this.expectToken(TokenKind.AT);
14001421
const name = this.parseName();
14011422
const args = this.parseArgumentDefs();
1423+
const directives = this.parseConstDirectives();
14021424
const repeatable = this.expectOptionalKeyword('repeatable');
14031425
this.expectKeyword('on');
14041426
const locations = this.parseDirectiveLocations();
@@ -1407,6 +1429,7 @@ export class Parser {
14071429
description,
14081430
name,
14091431
arguments: args,
1432+
directives,
14101433
repeatable,
14111434
locations,
14121435
});
@@ -1447,6 +1470,7 @@ export class Parser {
14471470
* `ENUM_VALUE`
14481471
* `INPUT_OBJECT`
14491472
* `INPUT_FIELD_DEFINITION`
1473+
* `DIRECTIVE_DEFINITION`
14501474
*/
14511475
parseDirectiveLocation(): NameNode {
14521476
const start = this._lexer.token;

0 commit comments

Comments
 (0)