Skip to content

Commit bbc3dfa

Browse files
magicmarkbenjie
andauthored
Updates to schema coordinates (#3044) (#4422)
Co-authored-by: Benjie <[email protected]>
1 parent a59ce3f commit bbc3dfa

File tree

11 files changed

+489
-188
lines changed

11 files changed

+489
-188
lines changed

src/language/__tests__/parser-test.ts

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -690,36 +690,31 @@ describe('Parser', () => {
690690
it('parses Name', () => {
691691
const result = parseSchemaCoordinate('MyType');
692692
expectJSON(result).toDeepEqual({
693-
kind: Kind.SCHEMA_COORDINATE,
693+
kind: Kind.TYPE_COORDINATE,
694694
loc: { start: 0, end: 6 },
695-
ofDirective: false,
696695
name: {
697696
kind: Kind.NAME,
698697
loc: { start: 0, end: 6 },
699698
value: 'MyType',
700699
},
701-
memberName: undefined,
702-
argumentName: undefined,
703700
});
704701
});
705702

706703
it('parses Name . Name', () => {
707704
const result = parseSchemaCoordinate('MyType.field');
708705
expectJSON(result).toDeepEqual({
709-
kind: Kind.SCHEMA_COORDINATE,
706+
kind: Kind.FIELD_COORDINATE,
710707
loc: { start: 0, end: 12 },
711-
ofDirective: false,
712708
name: {
713709
kind: Kind.NAME,
714710
loc: { start: 0, end: 6 },
715711
value: 'MyType',
716712
},
717-
memberName: {
713+
fieldName: {
718714
kind: Kind.NAME,
719715
loc: { start: 7, end: 12 },
720716
value: 'field',
721717
},
722-
argumentName: undefined,
723718
});
724719
});
725720

@@ -732,18 +727,35 @@ describe('Parser', () => {
732727
});
733728
});
734729

730+
it('parses Name :: Name', () => {
731+
const result = parseSchemaCoordinate('MyEnum::value');
732+
expectJSON(result).toDeepEqual({
733+
kind: Kind.VALUE_COORDINATE,
734+
loc: { start: 0, end: 13 },
735+
name: {
736+
kind: Kind.NAME,
737+
loc: { start: 0, end: 6 },
738+
value: 'MyEnum',
739+
},
740+
valueName: {
741+
kind: Kind.NAME,
742+
loc: { start: 8, end: 13 },
743+
value: 'value',
744+
},
745+
});
746+
});
747+
735748
it('parses Name . Name ( Name : )', () => {
736749
const result = parseSchemaCoordinate('MyType.field(arg:)');
737750
expectJSON(result).toDeepEqual({
738-
kind: Kind.SCHEMA_COORDINATE,
751+
kind: Kind.ARGUMENT_COORDINATE,
739752
loc: { start: 0, end: 18 },
740-
ofDirective: false,
741753
name: {
742754
kind: Kind.NAME,
743755
loc: { start: 0, end: 6 },
744756
value: 'MyType',
745757
},
746-
memberName: {
758+
fieldName: {
747759
kind: Kind.NAME,
748760
loc: { start: 7, end: 12 },
749761
value: 'field',
@@ -768,31 +780,26 @@ describe('Parser', () => {
768780
it('parses @ Name', () => {
769781
const result = parseSchemaCoordinate('@myDirective');
770782
expectJSON(result).toDeepEqual({
771-
kind: Kind.SCHEMA_COORDINATE,
783+
kind: Kind.DIRECTIVE_COORDINATE,
772784
loc: { start: 0, end: 12 },
773-
ofDirective: true,
774785
name: {
775786
kind: Kind.NAME,
776787
loc: { start: 1, end: 12 },
777788
value: 'myDirective',
778789
},
779-
memberName: undefined,
780-
argumentName: undefined,
781790
});
782791
});
783792

784793
it('parses @ Name ( Name : )', () => {
785794
const result = parseSchemaCoordinate('@myDirective(arg:)');
786795
expectJSON(result).toDeepEqual({
787-
kind: Kind.SCHEMA_COORDINATE,
796+
kind: Kind.DIRECTIVE_ARGUMENT_COORDINATE,
788797
loc: { start: 0, end: 18 },
789-
ofDirective: true,
790798
name: {
791799
kind: Kind.NAME,
792800
loc: { start: 1, end: 12 },
793801
value: 'myDirective',
794802
},
795-
memberName: undefined,
796803
argumentName: {
797804
kind: Kind.NAME,
798805
loc: { start: 13, end: 16 },

src/language/__tests__/predicates-test.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,12 @@ describe('AST node predicates', () => {
145145

146146
it('isSchemaCoordinateNode', () => {
147147
expect(filterNodes(isSchemaCoordinateNode)).to.deep.equal([
148-
'SchemaCoordinate',
148+
'ArgumentCoordinate',
149+
'DirectiveArgumentCoordinate',
150+
'DirectiveCoordinate',
151+
'FieldCoordinate',
152+
'TypeCoordinate',
153+
'ValueCoordinate',
149154
]);
150155
});
151156
});

src/language/ast.ts

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,12 @@ export type ASTNode =
182182
| UnionTypeExtensionNode
183183
| EnumTypeExtensionNode
184184
| InputObjectTypeExtensionNode
185-
| SchemaCoordinateNode;
185+
| TypeCoordinateNode
186+
| FieldCoordinateNode
187+
| ArgumentCoordinateNode
188+
| ValueCoordinateNode
189+
| DirectiveCoordinateNode
190+
| DirectiveArgumentCoordinateNode;
186191

187192
/**
188193
* Utility type listing all nodes indexed by their kind.
@@ -288,7 +293,14 @@ export const QueryDocumentKeys: {
288293
UnionTypeExtension: ['name', 'directives', 'types'],
289294
EnumTypeExtension: ['name', 'directives', 'values'],
290295
InputObjectTypeExtension: ['name', 'directives', 'fields'],
291-
SchemaCoordinate: ['name', 'memberName', 'argumentName'],
296+
297+
// Schema Coordinates
298+
TypeCoordinate: ['name'],
299+
FieldCoordinate: ['name', 'fieldName'],
300+
ArgumentCoordinate: ['name', 'fieldName', 'argumentName'],
301+
ValueCoordinate: ['name', 'valueName'],
302+
DirectiveCoordinate: ['name'],
303+
DirectiveArgumentCoordinate: ['name', 'argumentName'],
292304
};
293305

294306
const kindValues = new Set<string>(Object.keys(QueryDocumentKeys));
@@ -765,13 +777,53 @@ export interface InputObjectTypeExtensionNode {
765777
readonly fields?: ReadonlyArray<InputValueDefinitionNode> | undefined;
766778
}
767779

768-
// Schema Coordinates
780+
/** Schema Coordinates */
781+
782+
export type SchemaCoordinateNode =
783+
| TypeCoordinateNode
784+
| FieldCoordinateNode
785+
| ArgumentCoordinateNode
786+
| ValueCoordinateNode
787+
| DirectiveCoordinateNode
788+
| DirectiveArgumentCoordinateNode;
789+
790+
export interface TypeCoordinateNode {
791+
readonly kind: typeof Kind.TYPE_COORDINATE;
792+
readonly loc?: Location;
793+
readonly name: NameNode;
794+
}
795+
796+
export interface FieldCoordinateNode {
797+
readonly kind: typeof Kind.FIELD_COORDINATE;
798+
readonly loc?: Location;
799+
readonly name: NameNode;
800+
readonly fieldName: NameNode;
801+
}
802+
803+
export interface ArgumentCoordinateNode {
804+
readonly kind: typeof Kind.ARGUMENT_COORDINATE;
805+
readonly loc?: Location;
806+
readonly name: NameNode;
807+
readonly fieldName: NameNode;
808+
readonly argumentName: NameNode;
809+
}
810+
811+
export interface ValueCoordinateNode {
812+
readonly kind: typeof Kind.VALUE_COORDINATE;
813+
readonly loc?: Location;
814+
readonly name: NameNode;
815+
readonly valueName: NameNode;
816+
}
817+
818+
export interface DirectiveCoordinateNode {
819+
readonly kind: typeof Kind.DIRECTIVE_COORDINATE;
820+
readonly loc?: Location;
821+
readonly name: NameNode;
822+
}
769823

770-
export interface SchemaCoordinateNode {
771-
readonly kind: 'SchemaCoordinate';
824+
export interface DirectiveArgumentCoordinateNode {
825+
readonly kind: typeof Kind.DIRECTIVE_ARGUMENT_COORDINATE;
772826
readonly loc?: Location;
773-
readonly ofDirective: boolean;
774827
readonly name: NameNode;
775-
readonly memberName?: NameNode | undefined;
776-
readonly argumentName?: NameNode | undefined;
828+
readonly argumentName: NameNode;
777829
}

src/language/kinds_.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,5 +110,21 @@ export const INPUT_OBJECT_TYPE_EXTENSION = 'InputObjectTypeExtension';
110110
export type INPUT_OBJECT_TYPE_EXTENSION = typeof INPUT_OBJECT_TYPE_EXTENSION;
111111

112112
/** Schema Coordinates */
113-
export const SCHEMA_COORDINATE = 'SchemaCoordinate';
114-
export type SCHEMA_COORDINATE = typeof SCHEMA_COORDINATE;
113+
export const TYPE_COORDINATE = 'TypeCoordinate';
114+
export type TYPE_COORDINATE = typeof TYPE_COORDINATE;
115+
116+
export const FIELD_COORDINATE = 'FieldCoordinate';
117+
export type FIELD_COORDINATE = typeof FIELD_COORDINATE;
118+
119+
export const ARGUMENT_COORDINATE = 'ArgumentCoordinate';
120+
export type ARGUMENT_COORDINATE = typeof ARGUMENT_COORDINATE;
121+
122+
export const VALUE_COORDINATE = 'ValueCoordinate';
123+
export type VALUE_COORDINATE = typeof VALUE_COORDINATE;
124+
125+
export const DIRECTIVE_COORDINATE = 'DirectiveCoordinate';
126+
export type DIRECTIVE_COORDINATE = typeof DIRECTIVE_COORDINATE;
127+
128+
export const DIRECTIVE_ARGUMENT_COORDINATE = 'DirectiveArgumentCoordinate';
129+
export type DIRECTIVE_ARGUMENT_COORDINATE =
130+
typeof DIRECTIVE_ARGUMENT_COORDINATE;

src/language/lexer.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ export function isPunctuatorTokenKind(kind: TokenKind): boolean {
9898
kind === TokenKind.DOT ||
9999
kind === TokenKind.SPREAD ||
100100
kind === TokenKind.COLON ||
101+
kind === TokenKind.TWO_COLON ||
101102
kind === TokenKind.EQUALS ||
102103
kind === TokenKind.AT ||
103104
kind === TokenKind.BRACKET_L ||
@@ -271,6 +272,14 @@ function readNextToken(lexer: Lexer, start: number): Token {
271272
return readDot(lexer, position);
272273
}
273274
case 0x003a: // :
275+
if (body.charCodeAt(position + 1) === 0x003a) {
276+
return createToken(
277+
lexer,
278+
TokenKind.TWO_COLON,
279+
position,
280+
position + 2,
281+
);
282+
}
274283
return createToken(lexer, TokenKind.COLON, position, position + 1);
275284
case 0x003d: // =
276285
return createToken(lexer, TokenKind.EQUALS, position, position + 1);

src/language/parser.ts

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { GraphQLError } from '../error/GraphQLError.js';
44
import { syntaxError } from '../error/syntaxError.js';
55

66
import type {
7+
ArgumentCoordinateNode,
78
ArgumentNode,
89
BooleanValueNode,
910
ConstArgumentNode,
@@ -13,13 +14,16 @@ import type {
1314
ConstObjectValueNode,
1415
ConstValueNode,
1516
DefinitionNode,
17+
DirectiveArgumentCoordinateNode,
18+
DirectiveCoordinateNode,
1619
DirectiveDefinitionNode,
1720
DirectiveNode,
1821
DocumentNode,
1922
EnumTypeDefinitionNode,
2023
EnumTypeExtensionNode,
2124
EnumValueDefinitionNode,
2225
EnumValueNode,
26+
FieldCoordinateNode,
2327
FieldDefinitionNode,
2428
FieldNode,
2529
FloatValueNode,
@@ -54,10 +58,12 @@ import type {
5458
SelectionSetNode,
5559
StringValueNode,
5660
Token,
61+
TypeCoordinateNode,
5762
TypeNode,
5863
TypeSystemExtensionNode,
5964
UnionTypeDefinitionNode,
6065
UnionTypeExtensionNode,
66+
ValueCoordinateNode,
6167
ValueNode,
6268
VariableDefinitionNode,
6369
VariableNode,
@@ -1461,13 +1467,24 @@ export class Parser {
14611467
* - Name
14621468
* - Name . Name
14631469
* - Name . Name ( Name : )
1470+
* - Name :: Name
14641471
* - @ Name
14651472
* - @ Name ( Name : )
14661473
*/
14671474
parseSchemaCoordinate(): SchemaCoordinateNode {
14681475
const start = this._lexer.token;
14691476
const ofDirective = this.expectOptionalToken(TokenKind.AT);
14701477
const name = this.parseName();
1478+
1479+
if (!ofDirective && this.expectOptionalToken(TokenKind.TWO_COLON)) {
1480+
const valueName = this.parseName();
1481+
return this.node<ValueCoordinateNode>(start, {
1482+
kind: Kind.VALUE_COORDINATE,
1483+
name,
1484+
valueName,
1485+
});
1486+
}
1487+
14711488
let memberName: NameNode | undefined;
14721489
if (!ofDirective && this.expectOptionalToken(TokenKind.DOT)) {
14731490
memberName = this.parseName();
@@ -1481,12 +1498,38 @@ export class Parser {
14811498
this.expectToken(TokenKind.COLON);
14821499
this.expectToken(TokenKind.PAREN_R);
14831500
}
1484-
return this.node<SchemaCoordinateNode>(start, {
1485-
kind: Kind.SCHEMA_COORDINATE,
1486-
ofDirective,
1501+
1502+
if (ofDirective) {
1503+
if (argumentName) {
1504+
return this.node<DirectiveArgumentCoordinateNode>(start, {
1505+
kind: Kind.DIRECTIVE_ARGUMENT_COORDINATE,
1506+
name,
1507+
argumentName,
1508+
});
1509+
}
1510+
return this.node<DirectiveCoordinateNode>(start, {
1511+
kind: Kind.DIRECTIVE_COORDINATE,
1512+
name,
1513+
});
1514+
} else if (memberName) {
1515+
if (argumentName) {
1516+
return this.node<ArgumentCoordinateNode>(start, {
1517+
kind: Kind.ARGUMENT_COORDINATE,
1518+
name,
1519+
fieldName: memberName,
1520+
argumentName,
1521+
});
1522+
}
1523+
return this.node<FieldCoordinateNode>(start, {
1524+
kind: Kind.FIELD_COORDINATE,
1525+
name,
1526+
fieldName: memberName,
1527+
});
1528+
}
1529+
1530+
return this.node<TypeCoordinateNode>(start, {
1531+
kind: Kind.TYPE_COORDINATE,
14871532
name,
1488-
memberName,
1489-
argumentName,
14901533
});
14911534
}
14921535

src/language/predicates.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,5 +115,12 @@ export function isTypeExtensionNode(node: ASTNode): node is TypeExtensionNode {
115115
export function isSchemaCoordinateNode(
116116
node: ASTNode,
117117
): node is SchemaCoordinateNode {
118-
return node.kind === Kind.SCHEMA_COORDINATE;
118+
return (
119+
node.kind === Kind.TYPE_COORDINATE ||
120+
node.kind === Kind.FIELD_COORDINATE ||
121+
node.kind === Kind.ARGUMENT_COORDINATE ||
122+
node.kind === Kind.VALUE_COORDINATE ||
123+
node.kind === Kind.DIRECTIVE_COORDINATE ||
124+
node.kind === Kind.DIRECTIVE_ARGUMENT_COORDINATE
125+
);
119126
}

0 commit comments

Comments
 (0)