knownDirectivesRule function
Visitor
knownDirectivesRule(
- SDLValidationCtx context
Known directives
A GraphQL document is only valid if all @directives
are known by the
schema and legally positioned.
See https://spec.graphql.org/draft/#sec-Directives-Are-Defined
Implementation
Visitor knownDirectivesRule(
SDLValidationCtx context,
) {
final visitor = TypedVisitor();
final locationsMap = <String, List<DirectiveLocation>>{};
final schema = context.schema;
final definedDirectives =
schema != null ? schema.directives : GraphQLDirective.specifiedDirectives;
for (final directive in definedDirectives) {
locationsMap[directive.name] = directive.locations;
}
final astDefinitions = context.document.definitions;
for (final def in astDefinitions.whereType<DirectiveDefinitionNode>()) {
locationsMap[def.name.value] =
def.locations.map(mapDirectiveLocation).toList();
}
visitor.add<DirectiveNode>((node) {
final name = node.name.value;
final locations = locationsMap[name];
final _errorLocations =
GraphQLErrorLocation.firstFromNodes([node, node.name]);
if (locations == null) {
context.reportError(
GraphQLError(
'Unknown directive "@${name}".',
locations: _errorLocations,
extensions: _knownDirectivesSpec.extensions(),
),
);
return;
}
final candidateLocation = getDirectiveLocationForASTPath(
visitor.ancestors(),
);
if (candidateLocation != null && !locations.contains(candidateLocation)) {
context.reportError(
GraphQLError(
'Directive "@${name}" may not be used on ${candidateLocation.toJson()}.',
locations: _errorLocations,
extensions: _misplacedDirectivesSpec.extensions(),
),
);
}
});
return visitor;
}