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