Skip to content

Commit 3685f3f

Browse files
Validate against a case gqlparser doesn't catch (#197)
While writing tests at some point I came across an invalid query that gqlparser doesn't catch, and which causes a panic for us. Now we validate for it and return a nice error instead of panicing. Fixes #176. Test plan: make check
1 parent d4ec64f commit 3685f3f

7 files changed

+34
-4
lines changed

generate/generate.go

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,16 +224,40 @@ func (g *generator) preprocessQueryDocument(doc *ast.QueryDocument) {
224224
validator.Walk(g.schema, doc, &observers)
225225
}
226226

227+
// validateOperation checks for a few classes of operations that gqlparser
228+
// considers valid but we don't allow, and returns an error if this operation
229+
// is invalid for genqlient's purposes.
230+
func (g *generator) validateOperation(op *ast.OperationDefinition) error {
231+
opType, err := g.baseTypeForOperation(op.Operation)
232+
switch {
233+
case err != nil:
234+
// (e.g. operation has subscriptions, which we don't support)
235+
return err
236+
case opType == nil:
237+
// gqlparser should err here, but doesn't [1], so we err to prevent
238+
// panics later.
239+
// TODO(benkraft): Remove once gqlparser is fixed.
240+
// [1] https://github.com/vektah/gqlparser/issues/221
241+
return errorf(op.Position, "schema has no %v type", op.Operation)
242+
}
243+
244+
if op.Name == "" {
245+
return errorf(op.Position, "operations must have operation-names")
246+
} else if goKeywords[op.Name] {
247+
return errorf(op.Position, "operation name must not be a go keyword")
248+
}
249+
250+
return nil
251+
}
252+
227253
// addOperation adds to g.Operations the information needed to generate a
228254
// genqlient entrypoint function for the given operation. It also adds to
229255
// g.typeMap any types referenced by the operation, except for types belonging
230256
// to named fragments, which are added separately by Generate via
231257
// convertFragment.
232258
func (g *generator) addOperation(op *ast.OperationDefinition) error {
233-
if op.Name == "" {
234-
return errorf(op.Position, "operations must have operation-names")
235-
} else if goKeywords[op.Name] {
236-
return errorf(op.Position, "operation name must not be a go keyword")
259+
if err := g.validateOperation(op); err != nil {
260+
return err
237261
}
238262

239263
queryDoc := &ast.QueryDocument{
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
mutation M { g }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
type Query { f: String }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
query Q { f }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
type T { f: String }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
testdata/errors/NoMutationType.graphql:1: schema has no mutation type
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
testdata/errors/NoQueryType.graphql:1: schema has no query type

0 commit comments

Comments
 (0)