@@ -24,6 +24,7 @@ import type {
2424 FieldDefinitionNode ,
2525 FieldNode ,
2626 FloatValueNode ,
27+ FragmentArgumentDefinitionNode ,
2728 FragmentDefinitionNode ,
2829 FragmentSpreadNode ,
2930 InlineFragmentNode ,
@@ -91,23 +92,6 @@ export interface ParseOptions {
9192 */
9293 maxTokens ?: number | undefined ;
9394
94- /**
95- * @deprecated will be removed in the v17.0.0
96- *
97- * If enabled, the parser will understand and parse variable definitions
98- * contained in a fragment definition. They'll be represented in the
99- * `variableDefinitions` field of the FragmentDefinitionNode.
100- *
101- * The syntax is identical to normal, query-defined variables. For example:
102- *
103- * ```graphql
104- * fragment A($var: Boolean = false) on T {
105- * ...
106- * }
107- * ```
108- */
109- allowLegacyFragmentVariables ?: boolean | undefined ;
110-
11195 /**
11296 * EXPERIMENTAL:
11397 *
@@ -550,7 +534,7 @@ export class Parser {
550534 /**
551535 * Corresponds to both FragmentSpread and InlineFragment in the spec.
552536 *
553- * FragmentSpread : ... FragmentName Directives?
537+ * FragmentSpread : ... FragmentName Arguments? Directives?
554538 *
555539 * InlineFragment : ... TypeCondition? Directives? SelectionSet
556540 */
@@ -560,9 +544,18 @@ export class Parser {
560544
561545 const hasTypeCondition = this . expectOptionalKeyword ( 'on' ) ;
562546 if ( ! hasTypeCondition && this . peek ( TokenKind . NAME ) ) {
547+ const name = this . parseFragmentName ( ) ;
548+ if ( this . peek ( TokenKind . PAREN_L ) ) {
549+ return this . node < FragmentSpreadNode > ( start , {
550+ kind : Kind . FRAGMENT_SPREAD ,
551+ name,
552+ arguments : this . parseArguments ( false ) ,
553+ directives : this . parseDirectives ( false ) ,
554+ } ) ;
555+ }
563556 return this . node < FragmentSpreadNode > ( start , {
564557 kind : Kind . FRAGMENT_SPREAD ,
565- name : this . parseFragmentName ( ) ,
558+ name,
566559 directives : this . parseDirectives ( false ) ,
567560 } ) ;
568561 }
@@ -576,29 +569,17 @@ export class Parser {
576569
577570 /**
578571 * FragmentDefinition :
579- * - fragment FragmentName on TypeCondition Directives? SelectionSet
572+ * - fragment FragmentName FragmentArgumentsDefinition? on TypeCondition Directives? SelectionSet
580573 *
581574 * TypeCondition : NamedType
582575 */
583576 parseFragmentDefinition ( ) : FragmentDefinitionNode {
584577 const start = this . _lexer . token ;
585578 this . expectKeyword ( 'fragment' ) ;
586- // Legacy support for defining variables within fragments changes
587- // the grammar of FragmentDefinition:
588- // - fragment FragmentName VariableDefinitions? on TypeCondition Directives? SelectionSet
589- if ( this . _options . allowLegacyFragmentVariables === true ) {
590- return this . node < FragmentDefinitionNode > ( start , {
591- kind : Kind . FRAGMENT_DEFINITION ,
592- name : this . parseFragmentName ( ) ,
593- variableDefinitions : this . parseVariableDefinitions ( ) ,
594- typeCondition : ( this . expectKeyword ( 'on' ) , this . parseNamedType ( ) ) ,
595- directives : this . parseDirectives ( false ) ,
596- selectionSet : this . parseSelectionSet ( ) ,
597- } ) ;
598- }
599579 return this . node < FragmentDefinitionNode > ( start , {
600580 kind : Kind . FRAGMENT_DEFINITION ,
601581 name : this . parseFragmentName ( ) ,
582+ arguments : this . parseFragmentArgumentDefs ( ) ,
602583 typeCondition : ( this . expectKeyword ( 'on' ) , this . parseNamedType ( ) ) ,
603584 directives : this . parseDirectives ( false ) ,
604585 selectionSet : this . parseSelectionSet ( ) ,
@@ -615,6 +596,48 @@ export class Parser {
615596 return this . parseName ( ) ;
616597 }
617598
599+ /**
600+ * FragmentArgumentsDefinition : ( FragmentArgumentDefinition+ )
601+ */
602+ parseFragmentArgumentDefs ( ) : Array < FragmentArgumentDefinitionNode > {
603+ return this . optionalMany (
604+ TokenKind . PAREN_L ,
605+ this . parseFragmentArgumentDef ,
606+ TokenKind . PAREN_R ,
607+ ) ;
608+ }
609+
610+ /**
611+ * FragmentArgumentDefinition :
612+ * - Description? Variable : Type DefaultValue? Directives[Const]?
613+ *
614+ * Note: identical to InputValueDefinition, EXCEPT Name always begins
615+ * with $, so we need to parse a Variable out instead of a plain Name.
616+ *
617+ * Note: identical to VariableDefinition, EXCEPT we allow Description.
618+ * Fragments are re-used, and their arguments may need documentation.
619+ */
620+ parseFragmentArgumentDef ( ) : FragmentArgumentDefinitionNode {
621+ const start = this . _lexer . token ;
622+ const description = this . parseDescription ( ) ;
623+ const variable = this . parseVariable ( ) ;
624+ this . expectToken ( TokenKind . COLON ) ;
625+ const type = this . parseTypeReference ( ) ;
626+ let defaultValue ;
627+ if ( this . expectOptionalToken ( TokenKind . EQUALS ) ) {
628+ defaultValue = this . parseConstValueLiteral ( ) ;
629+ }
630+ const directives = this . parseConstDirectives ( ) ;
631+ return this . node < FragmentArgumentDefinitionNode > ( start , {
632+ kind : Kind . FRAGMENT_ARGUMENT_DEFINITION ,
633+ description,
634+ variable,
635+ type,
636+ defaultValue,
637+ directives,
638+ } ) ;
639+ }
640+
618641 // Implements the parsing rules in the Values section.
619642
620643 /**
0 commit comments