1313 DirectiveArgumentCoordinateNode ,
1414 DirectiveCoordinateNode ,
1515 DirectiveDefinitionNode ,
16+ DirectiveExtensionNode ,
1617 DirectiveNode ,
1718 DocumentNode ,
1819 EnumTypeDefinitionNode ,
@@ -88,6 +89,7 @@ def parse(
8889 no_location : bool = False ,
8990 max_tokens : Optional [int ] = None ,
9091 allow_legacy_fragment_variables : bool = False ,
92+ experimental_directives_on_directive_definitions : bool = False ,
9193) -> DocumentNode :
9294 """Given a GraphQL source, parse it into a Document.
9395
@@ -116,12 +118,23 @@ def parse(
116118 fragment A($var: Boolean = false) on T {
117119 ...
118120 }
121+
122+ Experimental feature:
123+
124+ If ``experimental_directives_on_directive_definitions`` is set to ``True``, the
125+ parser will understand and parse directives on directive definitions. This syntax
126+ is not part of the GraphQL specification and may change. For example::
127+
128+ directive @foo @bar on FIELD
119129 """
120130 parser = Parser (
121131 source ,
122132 no_location = no_location ,
123133 max_tokens = max_tokens ,
124134 allow_legacy_fragment_variables = allow_legacy_fragment_variables ,
135+ experimental_directives_on_directive_definitions = (
136+ experimental_directives_on_directive_definitions
137+ ),
125138 )
126139 return parser .parse_document ()
127140
@@ -131,6 +144,7 @@ def parse_value(
131144 no_location : bool = False ,
132145 max_tokens : Optional [int ] = None ,
133146 allow_legacy_fragment_variables : bool = False ,
147+ experimental_directives_on_directive_definitions : bool = False ,
134148) -> ValueNode :
135149 """Parse the AST for a given string containing a GraphQL value.
136150
@@ -147,6 +161,9 @@ def parse_value(
147161 no_location = no_location ,
148162 max_tokens = max_tokens ,
149163 allow_legacy_fragment_variables = allow_legacy_fragment_variables ,
164+ experimental_directives_on_directive_definitions = (
165+ experimental_directives_on_directive_definitions
166+ ),
150167 )
151168 parser .expect_token (TokenKind .SOF )
152169 value = parser .parse_value_literal (False )
@@ -159,6 +176,7 @@ def parse_const_value(
159176 no_location : bool = False ,
160177 max_tokens : Optional [int ] = None ,
161178 allow_legacy_fragment_variables : bool = False ,
179+ experimental_directives_on_directive_definitions : bool = False ,
162180) -> ConstValueNode :
163181 """Parse the AST for a given string containing a GraphQL constant value.
164182
@@ -170,6 +188,9 @@ def parse_const_value(
170188 no_location = no_location ,
171189 max_tokens = max_tokens ,
172190 allow_legacy_fragment_variables = allow_legacy_fragment_variables ,
191+ experimental_directives_on_directive_definitions = (
192+ experimental_directives_on_directive_definitions
193+ ),
173194 )
174195 parser .expect_token (TokenKind .SOF )
175196 value = parser .parse_const_value_literal ()
@@ -182,6 +203,7 @@ def parse_type(
182203 no_location : bool = False ,
183204 max_tokens : Optional [int ] = None ,
184205 allow_legacy_fragment_variables : bool = False ,
206+ experimental_directives_on_directive_definitions : bool = False ,
185207) -> TypeNode :
186208 """Parse the AST for a given string containing a GraphQL Type.
187209
@@ -198,6 +220,9 @@ def parse_type(
198220 no_location = no_location ,
199221 max_tokens = max_tokens ,
200222 allow_legacy_fragment_variables = allow_legacy_fragment_variables ,
223+ experimental_directives_on_directive_definitions = (
224+ experimental_directives_on_directive_definitions
225+ ),
201226 )
202227 parser .expect_token (TokenKind .SOF )
203228 type_ = parser .parse_type_reference ()
@@ -247,6 +272,7 @@ class Parser:
247272 _no_location : bool
248273 _max_tokens : Optional [int ]
249274 _allow_legacy_fragment_variables : bool
275+ _experimental_directives_on_directive_definitions : bool
250276 _token_counter : int
251277
252278 def __init__ (
@@ -255,6 +281,7 @@ def __init__(
255281 no_location : bool = False ,
256282 max_tokens : Optional [int ] = None ,
257283 allow_legacy_fragment_variables : bool = False ,
284+ experimental_directives_on_directive_definitions : bool = False ,
258285 lexer : Optional [Lexer ] = None ,
259286 ):
260287 source = (
@@ -267,6 +294,9 @@ def __init__(
267294 self ._no_location = no_location
268295 self ._max_tokens = max_tokens
269296 self ._allow_legacy_fragment_variables = allow_legacy_fragment_variables
297+ self ._experimental_directives_on_directive_definitions = (
298+ experimental_directives_on_directive_definitions
299+ )
270300 self ._token_counter = 0
271301
272302 def parse_name (self ) -> NameNode :
@@ -710,6 +740,11 @@ def parse_type_system_extension(self) -> TypeSystemExtensionNode:
710740 )
711741 if method_name : # pragma: no cover
712742 return getattr (self , f"parse_{ method_name } " )()
743+ if (
744+ keyword_token .value == "directive"
745+ and self ._experimental_directives_on_directive_definitions
746+ ):
747+ return self .parse_directive_definition_extension ()
713748 raise self .unexpected (keyword_token )
714749
715750 def peek_description (self ) -> bool :
@@ -1057,6 +1092,22 @@ def parse_input_object_type_extension(self) -> InputObjectTypeExtensionNode:
10571092 name = name , directives = directives , fields = fields , loc = self .loc (start )
10581093 )
10591094
1095+ def parse_directive_definition_extension (self ) -> DirectiveExtensionNode :
1096+ """DirectiveDefinitionExtension"""
1097+ start = self ._lexer .token
1098+ self .expect_keyword ("extend" )
1099+ self .expect_keyword ("directive" )
1100+ self .expect_token (TokenKind .AT )
1101+ name = self .parse_name ()
1102+ directives = self .parse_const_directives ()
1103+ if not directives :
1104+ raise self .unexpected ()
1105+ return DirectiveExtensionNode (
1106+ name = name ,
1107+ directives = directives ,
1108+ loc = self .loc (start ),
1109+ )
1110+
10601111 def parse_directive_definition (self ) -> DirectiveDefinitionNode :
10611112 """DirectiveDefinition"""
10621113 start = self ._lexer .token
@@ -1065,13 +1116,19 @@ def parse_directive_definition(self) -> DirectiveDefinitionNode:
10651116 self .expect_token (TokenKind .AT )
10661117 name = self .parse_name ()
10671118 args = self .parse_argument_defs ()
1119+ directives = (
1120+ self .parse_const_directives ()
1121+ if self ._experimental_directives_on_directive_definitions
1122+ else []
1123+ )
10681124 repeatable = self .expect_optional_keyword ("repeatable" )
10691125 self .expect_keyword ("on" )
10701126 locations = self .parse_directive_locations ()
10711127 return DirectiveDefinitionNode (
10721128 description = description ,
10731129 name = name ,
10741130 arguments = args ,
1131+ directives = directives ,
10751132 repeatable = repeatable ,
10761133 locations = locations ,
10771134 loc = self .loc (start ),
0 commit comments