|
1 | 1 | from ..utils import type_from_ast, is_valid_literal_value
|
2 | 2 | from ..error import GraphQLError
|
3 |
| -from ..type.definition import is_composite_type, is_input_type, is_leaf_type, GraphQLNonNull |
| 3 | +from ..type.definition import is_composite_type, is_input_type, is_leaf_type, GraphQLNonNull, GraphQLObjectType, |
| 4 | + GraphQLInterfaceType, GraphQLUnionType |
4 | 5 | from ..language import ast
|
5 | 6 | from ..language.visitor import Visitor, visit
|
6 | 7 | from ..language.printer import print_ast
|
@@ -234,7 +235,38 @@ def unused_fragment_message(fragment_name):
|
234 | 235 |
|
235 | 236 |
|
236 | 237 | class PossibleFragmentSpreads(ValidationRule):
|
237 |
| - pass |
| 238 | + def enter_InlineFragment(self, node, *args): |
| 239 | + frag_type = self.context.get_type() |
| 240 | + parent_type = self.context.get_parent_type() |
| 241 | + if frag_type and parent_type and not self.do_types_overlap(frag_type, parent_type): |
| 242 | + return GraphQLError( |
| 243 | + self.type_incompatible_anon_spread_message(parent_type, frag_type), |
| 244 | + [node] |
| 245 | + ) |
| 246 | + |
| 247 | + def enter_FragmentSpread(self, node, *args): |
| 248 | + frag_name = node.name.value |
| 249 | + frag_type = self.get_fragment_type(context, frag_name) |
| 250 | + parent_type = self.context.get_parent_type() |
| 251 | + if frag_type and parent_type and not self.do_types_overlap(frag_type, parent_type): |
| 252 | + return GraphQLError( |
| 253 | + self.type_incompatible_spread_message(frag_name, parent_type, frag_type), |
| 254 | + [node] |
| 255 | + ) |
| 256 | + |
| 257 | + @staticmethod |
| 258 | + def get_fragment_type(context, name): |
| 259 | + frag = context.get_fragment(name) |
| 260 | + return frag and type_from_ast(context.get_schema(), frag.type_condition) |
| 261 | + |
| 262 | + |
| 263 | + @staticmethod |
| 264 | + def type_incompatible_spread_message(frag_name, parent_type, frag_type): |
| 265 | + return 'Fragment {} cannot be spread here as objects of type {} can never be of type {}'.format(frag_name, parent_type, frag_type) |
| 266 | + |
| 267 | + @staticmethod |
| 268 | + def type_incompatible_anon_spread_message(parent_type, frag_type): |
| 269 | + return 'Fragment cannot be spread here as objects of type {} can never be of type {}'.format(parent_type, frag_type) |
238 | 270 |
|
239 | 271 |
|
240 | 272 | class NoFragmentCycles(ValidationRule):
|
|
0 commit comments