Skip to content

RFC: Descriptions as strings. #927

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 30, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/language/__tests__/schema-kitchen-sink.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ schema {
mutation: MutationType
}

"""
This is a description
of the `Foo` type.
"""
type Foo implements Bar {
one: Type
two(argument: InputType!): Type
Expand Down
58 changes: 58 additions & 0 deletions src/language/__tests__/schema-parser-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,55 @@ type Hello {
expect(printJson(doc)).to.equal(printJson(expected));
});

it('parses type with description string', () => {
const doc = parse(`
"Description"
type Hello {
world: String
}`);
expect(doc).to.containSubset({
kind: 'Document',
definitions: [
{
kind: 'ObjectTypeDefinition',
name: nameNode('Hello', { start: 20, end: 25 }),
description: {
kind: 'StringValue',
value: 'Description',
loc: { start: 1, end: 14 },
}
}
],
loc: { start: 0, end: 45 },
});
});

it('parses type with description multi-line string', () => {
const doc = parse(`
"""
Description
"""
# Even with comments between them
type Hello {
world: String
}`);
expect(doc).to.containSubset({
kind: 'Document',
definitions: [
{
kind: 'ObjectTypeDefinition',
name: nameNode('Hello', { start: 60, end: 65 }),
description: {
kind: 'StringValue',
value: 'Description',
loc: { start: 1, end: 20 },
}
}
],
loc: { start: 0, end: 85 },
});
});

it('Simple extension', () => {
const body = `
extend type Hello {
Expand Down Expand Up @@ -128,6 +177,15 @@ extend type Hello {
expect(printJson(doc)).to.equal(printJson(expected));
});

it('Extension do not include descriptions', () => {
expect(() => parse(`
"Description"
extend type Hello {
world: String
}
`)).to.throw('Syntax Error GraphQL request (2:7)');
});

it('Simple non-null type', () => {
const body = `
type Hello {
Expand Down
4 changes: 4 additions & 0 deletions src/language/__tests__/schema-printer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ describe('Printer', () => {
mutation: MutationType
}

"""
This is a description
of the \`Foo\` type.
"""
type Foo implements Bar {
one: Type
two(argument: InputType!): Type
Expand Down
10 changes: 10 additions & 0 deletions src/language/ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -396,13 +396,15 @@ export type TypeDefinitionNode =
export type ScalarTypeDefinitionNode = {
kind: 'ScalarTypeDefinition';
loc?: Location;
description?: ?StringValueNode;
name: NameNode;
directives?: ?Array<DirectiveNode>;
};

export type ObjectTypeDefinitionNode = {
kind: 'ObjectTypeDefinition';
loc?: Location;
description?: ?StringValueNode;
name: NameNode;
interfaces?: ?Array<NamedTypeNode>;
directives?: ?Array<DirectiveNode>;
Expand All @@ -412,6 +414,7 @@ export type ObjectTypeDefinitionNode = {
export type FieldDefinitionNode = {
kind: 'FieldDefinition';
loc?: Location;
description?: ?StringValueNode;
name: NameNode;
arguments: Array<InputValueDefinitionNode>;
type: TypeNode;
Expand All @@ -421,6 +424,7 @@ export type FieldDefinitionNode = {
export type InputValueDefinitionNode = {
kind: 'InputValueDefinition';
loc?: Location;
description?: ?StringValueNode;
name: NameNode;
type: TypeNode;
defaultValue?: ?ValueNode;
Expand All @@ -430,6 +434,7 @@ export type InputValueDefinitionNode = {
export type InterfaceTypeDefinitionNode = {
kind: 'InterfaceTypeDefinition';
loc?: Location;
description?: ?StringValueNode;
name: NameNode;
directives?: ?Array<DirectiveNode>;
fields: Array<FieldDefinitionNode>;
Expand All @@ -438,6 +443,7 @@ export type InterfaceTypeDefinitionNode = {
export type UnionTypeDefinitionNode = {
kind: 'UnionTypeDefinition';
loc?: Location;
description?: ?StringValueNode;
name: NameNode;
directives?: ?Array<DirectiveNode>;
types: Array<NamedTypeNode>;
Expand All @@ -446,6 +452,7 @@ export type UnionTypeDefinitionNode = {
export type EnumTypeDefinitionNode = {
kind: 'EnumTypeDefinition';
loc?: Location;
description?: ?StringValueNode;
name: NameNode;
directives?: ?Array<DirectiveNode>;
values: Array<EnumValueDefinitionNode>;
Expand All @@ -454,13 +461,15 @@ export type EnumTypeDefinitionNode = {
export type EnumValueDefinitionNode = {
kind: 'EnumValueDefinition';
loc?: Location;
description?: ?StringValueNode;
name: NameNode;
directives?: ?Array<DirectiveNode>;
};

export type InputObjectTypeDefinitionNode = {
kind: 'InputObjectTypeDefinition';
loc?: Location;
description?: ?StringValueNode;
name: NameNode;
directives?: ?Array<DirectiveNode>;
fields: Array<InputValueDefinitionNode>;
Expand All @@ -475,6 +484,7 @@ export type TypeExtensionDefinitionNode = {
export type DirectiveDefinitionNode = {
kind: 'DirectiveDefinition';
loc?: Location;
description?: ?StringValueNode;
name: NameNode;
arguments?: ?Array<InputValueDefinitionNode>;
locations: Array<NameNode>;
Expand Down
20 changes: 16 additions & 4 deletions src/language/lexer.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,24 @@ export function createLexer<TOptions>(
token: startOfFileToken,
line: 1,
lineStart: 0,
advance: advanceLexer
advance: advanceLexer,
lookahead
};
return lexer;
}

function advanceLexer() {
let token = this.lastToken = this.token;
this.lastToken = this.token;
const token = this.token = this.lookahead();
return token;
}

function lookahead() {
let token = this.token;
if (token.kind !== EOF) {
do {
token = token.next = readToken(this, token);
token = token.next || (token.next = readToken(this, token));
} while (token.kind === COMMENT);
this.token = token;
}
return token;
}
Expand Down Expand Up @@ -79,6 +85,12 @@ export type Lexer<TOptions> = {
* Advances the token stream to the next non-ignored token.
*/
advance(): Token;

/**
* Looks ahead and returns the next non-ignored token, but does not change
* the Lexer's state.
*/
lookahead(): Token;
};

// Each kind of token.
Expand Down
Loading