Skip to content

Commit 3fdf240

Browse files
authored
VariableDefinition Directives: hide behind experimental flag (#1454)
1 parent 1d7efa9 commit 3fdf240

File tree

4 files changed

+70
-6
lines changed

4 files changed

+70
-6
lines changed

src/language/__tests__/parser-test.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,9 @@ describe('Parser', () => {
108108

109109
it('parses variable definition directives', () => {
110110
expect(() =>
111-
parse('query Foo($x: Boolean = false @bar) { field }'),
111+
parse('query Foo($x: Boolean = false @bar) { field }', {
112+
experimentalVariableDefinitionDirectives: true,
113+
}),
112114
).to.not.throw();
113115
});
114116

src/language/__tests__/printer-test.js

+2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ describe('Printer: Query document', () => {
5656

5757
const queryAstWithArtifacts = parse(
5858
'query ($foo: TestType) @testDirective { id, name }',
59+
{ experimentalVariableDefinitionDirectives: true },
5960
);
6061
expect(print(queryAstWithArtifacts)).to.equal(dedent`
6162
query ($foo: TestType) @testDirective {
@@ -66,6 +67,7 @@ describe('Printer: Query document', () => {
6667

6768
const queryAstWithVariableDirective = parse(
6869
'query ($foo: TestType = {a: 123} @testDirective(if: true) @test) { id }',
70+
{ experimentalVariableDefinitionDirectives: true },
6971
);
7072
expect(print(queryAstWithVariableDirective)).to.equal(dedent`
7173
query ($foo: TestType = {a: 123} @testDirective(if: true) @test) {

src/language/parser.js

+24-1
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,17 @@ export type ParseOptions = {
115115
* future.
116116
*/
117117
experimentalFragmentVariables?: boolean,
118+
119+
/**
120+
* EXPERIMENTAL:
121+
*
122+
* If enabled, the parser understands directives on variable definitions:
123+
*
124+
* query Foo($var: String = "abc" @variable_definition_directive) {
125+
* ...
126+
* }
127+
*/
128+
experimentalVariableDefinitionDirectives?: boolean,
118129
};
119130

120131
/**
@@ -336,14 +347,26 @@ function parseVariableDefinitions(
336347
*/
337348
function parseVariableDefinition(lexer: Lexer<*>): VariableDefinitionNode {
338349
const start = lexer.token;
350+
if (lexer.options.experimentalVariableDefinitionDirectives) {
351+
return {
352+
kind: Kind.VARIABLE_DEFINITION,
353+
variable: parseVariable(lexer),
354+
type: (expect(lexer, TokenKind.COLON), parseTypeReference(lexer)),
355+
defaultValue: skip(lexer, TokenKind.EQUALS)
356+
? parseValueLiteral(lexer, true)
357+
: undefined,
358+
directives: parseDirectives(lexer, true),
359+
loc: loc(lexer, start),
360+
};
361+
}
362+
339363
return {
340364
kind: Kind.VARIABLE_DEFINITION,
341365
variable: parseVariable(lexer),
342366
type: (expect(lexer, TokenKind.COLON), parseTypeReference(lexer)),
343367
defaultValue: skip(lexer, TokenKind.EQUALS)
344368
? parseValueLiteral(lexer, true)
345369
: undefined,
346-
directives: parseDirectives(lexer, true),
347370
loc: loc(lexer, start),
348371
};
349372
}

src/validation/__tests__/KnownDirectives-test.js

+41-4
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,16 @@
55
* LICENSE file in the root directory of this source tree.
66
*/
77

8+
import { expect } from 'chai';
89
import { describe, it } from 'mocha';
10+
import { parse } from '../../language';
911
import { buildSchema } from '../../utilities';
12+
import { validate } from '../validate';
1013
import {
1114
expectPassesRule,
1215
expectFailsRule,
1316
expectSDLErrorsFromRule,
17+
testSchema,
1418
} from './harness';
1519

1620
import {
@@ -127,7 +131,7 @@ describe('Validate: Known directives', () => {
127131
expectPassesRule(
128132
KnownDirectives,
129133
`
130-
query Foo($var: Boolean @onVariableDefinition) @onQuery {
134+
query Foo($var: Boolean) @onQuery {
131135
name @include(if: $var)
132136
...Frag @include(if: true)
133137
skippedField @skip(if: true)
@@ -141,11 +145,26 @@ describe('Validate: Known directives', () => {
141145
);
142146
});
143147

148+
it('with well placed variable definition directive', () => {
149+
// Need to parse with experimental flag
150+
const queryString = `
151+
query Foo($var: Boolean @onVariableDefinition) {
152+
name
153+
}
154+
`;
155+
const errors = validate(
156+
testSchema,
157+
parse(queryString, { experimentalVariableDefinitionDirectives: true }),
158+
[KnownDirectives],
159+
);
160+
expect(errors).to.deep.equal([], 'Should validate');
161+
});
162+
144163
it('with misplaced directives', () => {
145164
expectFailsRule(
146165
KnownDirectives,
147166
`
148-
query Foo($var: Boolean @onField) @include(if: true) {
167+
query Foo($var: Boolean) @include(if: true) {
149168
name @onQuery @include(if: $var)
150169
...Frag @onQuery
151170
}
@@ -155,15 +174,33 @@ describe('Validate: Known directives', () => {
155174
}
156175
`,
157176
[
158-
misplacedDirective('onField', 'VARIABLE_DEFINITION', 2, 31),
159-
misplacedDirective('include', 'QUERY', 2, 41),
177+
misplacedDirective('include', 'QUERY', 2, 32),
160178
misplacedDirective('onQuery', 'FIELD', 3, 14),
161179
misplacedDirective('onQuery', 'FRAGMENT_SPREAD', 4, 17),
162180
misplacedDirective('onQuery', 'MUTATION', 7, 20),
163181
],
164182
);
165183
});
166184

185+
it('with misplaced variable definition directive', () => {
186+
// Need to parse with experimental flag
187+
const queryString = `
188+
query Foo($var: Boolean @onField) {
189+
name
190+
}
191+
`;
192+
const errors = validate(
193+
testSchema,
194+
parse(queryString, { experimentalVariableDefinitionDirectives: true }),
195+
[KnownDirectives],
196+
);
197+
const expectedErrors = [
198+
misplacedDirective('onField', 'VARIABLE_DEFINITION', 2, 31),
199+
];
200+
expect(errors).to.have.length.of.at.least(1, 'Should not validate');
201+
expect(errors).to.deep.equal(expectedErrors);
202+
});
203+
167204
describe('within SDL', () => {
168205
it('with directive defined inside SDL', () => {
169206
expectSDLErrors(`

0 commit comments

Comments
 (0)