Skip to content

Commit 2611aa4

Browse files
committed
Add star syntax proposal
1 parent 855e4d7 commit 2611aa4

15 files changed

+92
-217
lines changed

src/language/__tests__/parser-test.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -661,20 +661,19 @@ describe('Parser', () => {
661661
describe('parseDocumentDirective', () => {
662662
it("doesn't throw on document-level directive", () => {
663663
parse(dedent`
664-
@SemanticNullability
665664
type Query {
666-
hello: String
667-
world: String?
665+
hello: String*
666+
world: String
668667
foo: String!
669668
}
670669
`);
671670
});
672671

673672
it('parses semantic-non-null types', () => {
674-
const result = parseType('MyType', { allowSemanticNullability: true });
673+
const result = parseType('MyType*');
675674
expectJSON(result).toDeepEqual({
676675
kind: Kind.SEMANTIC_NON_NULL_TYPE,
677-
loc: { start: 0, end: 6 },
676+
loc: { start: 0, end: 7 },
678677
type: {
679678
kind: Kind.NAMED_TYPE,
680679
loc: { start: 0, end: 6 },
@@ -688,7 +687,7 @@ describe('Parser', () => {
688687
});
689688

690689
it('parses nullable types', () => {
691-
const result = parseType('MyType?', { allowSemanticNullability: true });
690+
const result = parseType('MyType');
692691
expectJSON(result).toDeepEqual({
693692
kind: Kind.NAMED_TYPE,
694693
loc: { start: 0, end: 6 },
@@ -701,7 +700,7 @@ describe('Parser', () => {
701700
});
702701

703702
it('parses non-nullable types', () => {
704-
const result = parseType('MyType!', { allowSemanticNullability: true });
703+
const result = parseType('MyType!');
705704
expectJSON(result).toDeepEqual({
706705
kind: Kind.NON_NULL_TYPE,
707706
loc: { start: 0, end: 7 },

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

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -182,39 +182,18 @@ describe('Printer: SDL document', () => {
182182
});
183183

184184
it('prints NamedType', () => {
185-
expect(
186-
print(parseType('MyType', { allowSemanticNullability: false }), {
187-
useSemanticNullability: false,
188-
}),
189-
).to.equal(dedent`MyType`);
185+
expect(print(parseType('MyType'))).to.equal(dedent`MyType`);
190186
});
191187

192-
it('prints SemanticNullableType', () => {
193-
expect(
194-
print(parseType('MyType?', { allowSemanticNullability: true }), {
195-
useSemanticNullability: true,
196-
}),
197-
).to.equal(dedent`MyType?`);
188+
it('prints nullable types', () => {
189+
expect(print(parseType('MyType'))).to.equal(dedent`MyType`);
198190
});
199191

200192
it('prints SemanticNonNullType', () => {
201-
expect(
202-
print(parseType('MyType', { allowSemanticNullability: true }), {
203-
useSemanticNullability: true,
204-
}),
205-
).to.equal(dedent`MyType`);
193+
expect(print(parseType('MyType*'))).to.equal(dedent`MyType*`);
206194
});
207195

208196
it('prints NonNullType', () => {
209-
expect(
210-
print(parseType('MyType!', { allowSemanticNullability: true }), {
211-
useSemanticNullability: true,
212-
}),
213-
).to.equal(dedent`MyType!`);
214-
expect(
215-
print(parseType('MyType!', { allowSemanticNullability: false }), {
216-
useSemanticNullability: true,
217-
}),
218-
).to.equal(dedent`MyType!`);
197+
expect(print(parseType('MyType!'))).to.equal(dedent`MyType!`);
219198
});
220199
});

src/language/lexer.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export class Lexer {
9191
export function isPunctuatorTokenKind(kind: TokenKind): boolean {
9292
return (
9393
kind === TokenKind.BANG ||
94-
kind === TokenKind.QUESTION_MARK ||
94+
kind === TokenKind.STAR ||
9595
kind === TokenKind.DOLLAR ||
9696
kind === TokenKind.AMP ||
9797
kind === TokenKind.PAREN_L ||
@@ -247,16 +247,11 @@ function readNextToken(lexer: Lexer, start: number): Token {
247247
// - FloatValue
248248
// - StringValue
249249
//
250-
// Punctuator :: one of ! ? $ & ( ) ... : = @ [ ] { | }
250+
// Punctuator :: one of ! * $ & ( ) ... : = @ [ ] { | }
251251
case 0x0021: // !
252252
return createToken(lexer, TokenKind.BANG, position, position + 1);
253-
case 0x003f: // ?
254-
return createToken(
255-
lexer,
256-
TokenKind.QUESTION_MARK,
257-
position,
258-
position + 1,
259-
);
253+
case 0x002a: // *
254+
return createToken(lexer, TokenKind.STAR, position, position + 1);
260255
case 0x0024: // $
261256
return createToken(lexer, TokenKind.DOLLAR, position, position + 1);
262257
case 0x0026: // &

src/language/parser.ts

Lines changed: 5 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -104,18 +104,6 @@ export interface ParseOptions {
104104
* ```
105105
*/
106106
allowLegacyFragmentVariables?: boolean;
107-
108-
/**
109-
* When enabled, the parser will understand and parse semantic nullability
110-
* annotations. This means that every type suffixed with `!` will remain
111-
* non-nullable, every type suffixed with `?` will be the classic nullable, and
112-
* types without a suffix will be semantically nullable. Semantic nullability
113-
* will be the new default when this is enabled. A semantically nullable type
114-
* can only be null when there's an error associated with the field.
115-
*
116-
* @experimental
117-
*/
118-
allowSemanticNullability?: boolean;
119107
}
120108

121109
/**
@@ -271,16 +259,6 @@ export class Parser {
271259
* - InputObjectTypeDefinition
272260
*/
273261
parseDefinition(): DefinitionNode {
274-
const directives = this.parseDirectives(false);
275-
// If a document-level SemanticNullability directive exists as
276-
// the first element in a document, then all parsing will
277-
// happen in SemanticNullability mode.
278-
for (const directive of directives) {
279-
if (directive.name.value === 'SemanticNullability') {
280-
this._options.allowSemanticNullability = true;
281-
}
282-
}
283-
284262
if (this.peek(TokenKind.BRACE_L)) {
285263
return this.parseOperationDefinition();
286264
}
@@ -788,27 +766,16 @@ export class Parser {
788766
type = this.parseNamedType();
789767
}
790768

791-
if (this._options.allowSemanticNullability) {
792-
if (this.expectOptionalToken(TokenKind.BANG)) {
793-
return this.node<NonNullTypeNode>(start, {
794-
kind: Kind.NON_NULL_TYPE,
795-
type,
796-
});
797-
} else if (this.expectOptionalToken(TokenKind.QUESTION_MARK)) {
798-
return type;
799-
}
800-
801-
return this.node<SemanticNonNullTypeNode>(start, {
802-
kind: Kind.SEMANTIC_NON_NULL_TYPE,
803-
type,
804-
});
805-
}
806-
807769
if (this.expectOptionalToken(TokenKind.BANG)) {
808770
return this.node<NonNullTypeNode>(start, {
809771
kind: Kind.NON_NULL_TYPE,
810772
type,
811773
});
774+
} else if (this.expectOptionalToken(TokenKind.STAR)) {
775+
return this.node<SemanticNonNullTypeNode>(start, {
776+
kind: Kind.SEMANTIC_NON_NULL_TYPE,
777+
type,
778+
});
812779
}
813780

814781
return type;

src/language/printer.ts

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,14 @@ import type { Maybe } from '../jsutils/Maybe';
22

33
import type { ASTNode } from './ast';
44
import { printBlockString } from './blockString';
5-
import { Kind } from './kinds';
65
import { printString } from './printString';
76
import { visit } from './visitor';
87

9-
/**
10-
* Configuration options to control parser behavior
11-
*/
12-
export interface PrintOptions {
13-
useSemanticNullability?: boolean;
14-
}
15-
168
/**
179
* Converts an AST into a string, using one set of reasonable
1810
* formatting rules.
1911
*/
20-
export function print(ast: ASTNode, options: PrintOptions = {}): string {
12+
export function print(ast: ASTNode): string {
2113
return visit<string>(ast, {
2214
Name: { leave: (node) => node.value },
2315
Variable: { leave: (node) => '$' + node.name },
@@ -131,19 +123,11 @@ export function print(ast: ASTNode, options: PrintOptions = {}): string {
131123
// Type
132124

133125
NamedType: {
134-
leave: ({ name }, _, parent) =>
135-
parent &&
136-
!Array.isArray(parent) &&
137-
((parent as ASTNode).kind === Kind.SEMANTIC_NON_NULL_TYPE ||
138-
(parent as ASTNode).kind === Kind.NON_NULL_TYPE)
139-
? name
140-
: options?.useSemanticNullability
141-
? `${name}?`
142-
: name,
126+
leave: ({ name }) => name,
143127
},
144128
ListType: { leave: ({ type }) => '[' + type + ']' },
145129
NonNullType: { leave: ({ type }) => type + '!' },
146-
SemanticNonNullType: { leave: ({ type }) => type },
130+
SemanticNonNullType: { leave: ({ type }) => type + '*' },
147131

148132
// Type System Definitions
149133

src/language/tokenKind.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ enum TokenKind {
66
SOF = '<SOF>',
77
EOF = '<EOF>',
88
BANG = '!',
9-
QUESTION_MARK = '?',
9+
STAR = '*',
1010
DOLLAR = '$',
1111
AMP = '&',
1212
PAREN_L = '(',

src/type/__tests__/introspection-test.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1798,11 +1798,10 @@ describe('Introspection', () => {
17981798
describe('semantic nullability', () => {
17991799
it('casts semantic-non-null types to nullable types in traditional mode', () => {
18001800
const schema = buildSchema(`
1801-
@SemanticNullability
18021801
type Query {
18031802
someField: String!
1804-
someField2: String
1805-
someField3: String?
1803+
someField2: String*
1804+
someField3: String
18061805
}
18071806
`);
18081807

@@ -1847,11 +1846,10 @@ describe('Introspection', () => {
18471846

18481847
it('returns semantic-non-null types in full mode', () => {
18491848
const schema = buildSchema(`
1850-
@SemanticNullability
18511849
type Query {
18521850
someField: String!
1853-
someField2: String
1854-
someField3: String?
1851+
someField2: String*
1852+
someField3: String
18551853
}
18561854
`);
18571855

src/type/definition.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ export class GraphQLSemanticNonNull<T extends GraphQLNullableType> {
502502
}
503503

504504
toString(): string {
505-
return String(this.ofType);
505+
return String(this.ofType) + '*';
506506
}
507507

508508
toJSON(): string {

src/utilities/__tests__/TypeInfo-test.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -460,11 +460,10 @@ describe('visitWithTypeInfo', () => {
460460

461461
it('supports traversals of semantic non-null types', () => {
462462
const schema = buildSchema(`
463-
@SemanticNullability
464463
type Query {
465464
id: String!
466-
name: String
467-
something: String?
465+
name: String*
466+
something: String
468467
}
469468
`);
470469

@@ -506,10 +505,10 @@ describe('visitWithTypeInfo', () => {
506505
['enter', 'Name', 'id', 'String!'],
507506
['leave', 'Name', 'id', 'String!'],
508507
['leave', 'Field', null, 'String!'],
509-
['enter', 'Field', null, 'String'],
510-
['enter', 'Name', 'name', 'String'],
511-
['leave', 'Name', 'name', 'String'],
512-
['leave', 'Field', null, 'String'],
508+
['enter', 'Field', null, 'String*'],
509+
['enter', 'Name', 'name', 'String*'],
510+
['leave', 'Name', 'name', 'String*'],
511+
['leave', 'Field', null, 'String*'],
513512
['enter', 'Field', null, 'String'],
514513
['enter', 'Name', 'something', 'String'],
515514
['leave', 'Name', 'something', 'String'],

src/utilities/__tests__/buildClientSchema-test.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -988,11 +988,9 @@ describe('Type System: build schema from introspection', () => {
988988
describe('SemanticNullability', () => {
989989
it('should build a client schema with semantic-non-null types', () => {
990990
const sdl = dedent`
991-
@SemanticNullability
992-
993991
type Query {
994-
foo: String
995-
bar: String?
992+
foo: String*
993+
bar: String
996994
}
997995
`;
998996
const schema = buildSchema(sdl, { assumeValid: true });
@@ -1027,10 +1025,8 @@ describe('Type System: build schema from introspection', () => {
10271025

10281026
it('should throw when semantic-non-null types are too deep', () => {
10291027
const sdl = dedent`
1030-
@SemanticNullability
1031-
10321028
type Query {
1033-
bar: [[[[[[String?]]]]]]?
1029+
bar: [[[[[[String]*]*]*]*]*]
10341030
}
10351031
`;
10361032
const schema = buildSchema(sdl, { assumeValid: true });

0 commit comments

Comments
 (0)