From 694451c71fefc5c0a1dbf2402e03c4842021a4a8 Mon Sep 17 00:00:00 2001 From: Ville Immonen Date: Sat, 19 Sep 2015 19:16:41 +0300 Subject: [PATCH] Add directives to field definitions This extends the GraphQL IDL syntax to support directives for fields in types. Directives can be used to add custom metadata / annotations to fields. --- .../__tests__/schema-kitchen-sink.graphql | 1 + src/language/__tests__/schema-parser.js | 55 +++++++++++++++++++ src/language/ast.js | 1 + src/language/parser.js | 2 + 4 files changed, 59 insertions(+) diff --git a/src/language/__tests__/schema-kitchen-sink.graphql b/src/language/__tests__/schema-kitchen-sink.graphql index be875685df..ec8fbfadf3 100644 --- a/src/language/__tests__/schema-kitchen-sink.graphql +++ b/src/language/__tests__/schema-kitchen-sink.graphql @@ -11,6 +11,7 @@ type Foo implements Bar { three(argument: InputType, other: String): Int four(argument: String = "string"): String five(argument: [String] = ["string", "string"]): String + @meta(value: 6) six(argument: InputType = {key: "value"}): Type } diff --git a/src/language/__tests__/schema-parser.js b/src/language/__tests__/schema-parser.js index 8b4754ac17..0fedff7c79 100644 --- a/src/language/__tests__/schema-parser.js +++ b/src/language/__tests__/schema-parser.js @@ -47,11 +47,16 @@ function fieldNode(name, type, loc) { } function fieldNodeWithArgs(name, type, args, loc) { + return fieldNodeWithDirectives(name, type, args, [], loc); +} + +function fieldNodeWithDirectives(name, type, args, directives, loc) { return { kind: 'FieldDefinition', name, arguments: args, type, + directives, loc, }; } @@ -445,6 +450,56 @@ type Hello { expect(printJson(doc)).to.equal(printJson(expected)); }); + it('Simple field with a directive', () => { + var body = ` +type Hello { + @relatedField(name: "hellos") + world: World +}`; + var doc = parse(body); + var loc = createLocFn(body); + var expected = { + kind: 'Document', + definitions: [ + { + kind: 'ObjectTypeDefinition', + name: nameNode('Hello', loc(6, 11)), + interfaces: [], + fields: [ + fieldNodeWithDirectives( + nameNode('world', loc(48, 53)), + typeNode('World', loc(55, 60)), + [], + [ + { + kind: 'Directive', + name: nameNode('relatedField', loc(17, 29)), + arguments: [ + { + kind: 'Argument', + name: nameNode('name', loc(30, 34)), + value: { + kind: 'StringValue', + value: 'hellos', + loc: loc(36, 44), + }, + loc: loc(30, 44) + }, + ], + loc: loc(16, 45), + }, + ], + loc(16, 60) + ) + ], + loc: loc(1, 62), + } + ], + loc: loc(1, 62), + }; + expect(printJson(doc)).to.equal(printJson(expected)); + }); + it('Simple union', () => { var body = `union Hello = World`; var doc = parse(body); diff --git a/src/language/ast.js b/src/language/ast.js index 8cc5d83206..b3a4cf1413 100644 --- a/src/language/ast.js +++ b/src/language/ast.js @@ -276,6 +276,7 @@ export type FieldDefinition = { name: Name; arguments: Array; type: Type; + directives?: ?Array; } export type InputValueDefinition = { diff --git a/src/language/parser.js b/src/language/parser.js index dadbaa7433..956d60b0a4 100644 --- a/src/language/parser.js +++ b/src/language/parser.js @@ -719,6 +719,7 @@ function parseImplementsInterfaces(parser): Array { */ function parseFieldDefinition(parser): FieldDefinition { var start = parser.token.start; + var directives = parseDirectives(parser); var name = parseName(parser); var args = parseArgumentDefs(parser); expect(parser, TokenKind.COLON); @@ -728,6 +729,7 @@ function parseFieldDefinition(parser): FieldDefinition { name, arguments: args, type, + directives, loc: loc(parser, start), }; }