Skip to content

Commit

Permalink
Throw if visitor does not implement methods for all declared locations.
Browse files Browse the repository at this point in the history
  • Loading branch information
benjamn committed Mar 14, 2018
1 parent 99fd3b7 commit 7a9139e
Showing 1 changed file with 31 additions and 0 deletions.
31 changes: 31 additions & 0 deletions src/schemaVisitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
GraphQLUnionType,
Kind,
ValueNode,
DirectiveLocationEnum,
} from 'graphql';

import {
Expand Down Expand Up @@ -446,6 +447,29 @@ export class SchemaDirectiveVisitor extends SchemaVisitor {
}
});

each(declaredDirectives, (decl, name) => {
if (! hasOwn.call(directiveVisitors, name)) {
// SchemaDirectiveVisitors.visitSchemaDirectives might be called
// multiple times with partial directiveVisitors maps, so it's not
// necessarily an error for directiveVisitors to be missing an
// implementation of a directive that was declared in the schema.
return;
}
const visitorClass = directiveVisitors[name];
decl.locations.forEach(loc => {
const visitorMethodName = directiveLocationToVisitorMethodName(loc);
if (! visitorClass.implementsVisitorMethod(visitorMethodName)) {
// While visitor subclasses may implement extra visitor methods,
// it's definitely a mistake if the GraphQLDirective declares itself
// applicable to certain schema locations, and the visitor subclass
// does not implement all the corresponding methods.
throw new Error(
`SchemaDirectiveVisitor for @${name} must implement ${visitorMethodName} method`
);
}
});
});

return declaredDirectives;
}

Expand All @@ -467,6 +491,13 @@ export class SchemaDirectiveVisitor extends SchemaVisitor {
}
}

// Convert a string like "FIELD_DEFINITION" to "visitFieldDefinition".
function directiveLocationToVisitorMethodName(loc: DirectiveLocationEnum) {
return 'visit' + loc.replace(/([^_]*)_?/g, (wholeMatch, part) => {
return part.charAt(0).toUpperCase() + part.slice(1).toLowerCase();
});
}

// Helper widely used in the visit function above.
function each<V>(
obj: { [key: string]: V },
Expand Down

0 comments on commit 7a9139e

Please sign in to comment.