...
1 package validator
2
3 import (
4 "github.com/vektah/gqlparser/ast"
5 . "github.com/vektah/gqlparser/validator"
6 )
7
8 func init() {
9 AddRule("PossibleFragmentSpreads", func(observers *Events, addError AddErrFunc) {
10
11 validate := func(walker *Walker, parentDef *ast.Definition, fragmentName string, emitError func()) {
12 if parentDef == nil {
13 return
14 }
15
16 var parentDefs []*ast.Definition
17 switch parentDef.Kind {
18 case ast.Object:
19 parentDefs = []*ast.Definition{parentDef}
20 case ast.Interface, ast.Union:
21 parentDefs = walker.Schema.GetPossibleTypes(parentDef)
22 default:
23 return
24 }
25
26 fragmentDefType := walker.Schema.Types[fragmentName]
27 if fragmentDefType == nil {
28 return
29 }
30 if !fragmentDefType.IsCompositeType() {
31
32 return
33 }
34 fragmentDefs := walker.Schema.GetPossibleTypes(fragmentDefType)
35
36 for _, fragmentDef := range fragmentDefs {
37 for _, parentDef := range parentDefs {
38 if parentDef.Name == fragmentDef.Name {
39 return
40 }
41 }
42 }
43
44 emitError()
45 }
46
47 observers.OnInlineFragment(func(walker *Walker, inlineFragment *ast.InlineFragment) {
48 validate(walker, inlineFragment.ObjectDefinition, inlineFragment.TypeCondition, func() {
49 addError(
50 Message(`Fragment cannot be spread here as objects of type "%s" can never be of type "%s".`, inlineFragment.ObjectDefinition.Name, inlineFragment.TypeCondition),
51 At(inlineFragment.Position),
52 )
53 })
54 })
55
56 observers.OnFragmentSpread(func(walker *Walker, fragmentSpread *ast.FragmentSpread) {
57 if fragmentSpread.Definition == nil {
58 return
59 }
60 validate(walker, fragmentSpread.ObjectDefinition, fragmentSpread.Definition.TypeCondition, func() {
61 addError(
62 Message(`Fragment "%s" cannot be spread here as objects of type "%s" can never be of type "%s".`, fragmentSpread.Name, fragmentSpread.ObjectDefinition.Name, fragmentSpread.Definition.TypeCondition),
63 At(fragmentSpread.Position),
64 )
65 })
66 })
67 })
68 }
69
View as plain text