text: "use strict";
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.unknownDirectiveMessage = unknownDirectiveMessage;
  exports.misplacedDirectiveMessage = misplacedDirectiveMessage;
  exports.KnownDirectives = KnownDirectives;
  
  var _GraphQLError = require("../../error/GraphQLError");
  
  var _kinds = require("../../language/kinds");
  
  var _directiveLocation = require("../../language/directiveLocation");
  
  var _directives = require("../../type/directives");
  
  /**
   * Copyright (c) Facebook, Inc. and its affiliates.
   *
   * This source code is licensed under the MIT license found in the
   * LICENSE file in the root directory of this source tree.
   *
   * 
   */
  function unknownDirectiveMessage(directiveName) {
    return "Unknown directive \"".concat(directiveName, "\".");
  }
  
  function misplacedDirectiveMessage(directiveName, location) {
    return "Directive \"".concat(directiveName, "\" may not be used on ").concat(location, ".");
  }
  /**
   * Known directives
   *
   * A GraphQL document is only valid if all `@directives` are known by the
   * schema and legally positioned.
   */
  
  
  function KnownDirectives(context) {
    var locationsMap = Object.create(null);
    var schema = context.getSchema();
    var definedDirectives = schema ? schema.getDirectives() : _directives.specifiedDirectives;
    var _iteratorNormalCompletion = true;
    var _didIteratorError = false;
    var _iteratorError = undefined;
  
    try {
      for (var _iterator = definedDirectives[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
        var directive = _step.value;
        locationsMap[directive.name] = directive.locations;
      }
    } catch (err) {
      _didIteratorError = true;
      _iteratorError = err;
    } finally {
      try {
        if (!_iteratorNormalCompletion && _iterator.return != null) {
          _iterator.return();
        }
      } finally {
        if (_didIteratorError) {
          throw _iteratorError;
        }
      }
    }
  
    var astDefinitions = context.getDocument().definitions;
    var _iteratorNormalCompletion2 = true;
    var _didIteratorError2 = false;
    var _iteratorError2 = undefined;
  
    try {
      for (var _iterator2 = astDefinitions[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
        var def = _step2.value;
  
        if (def.kind === _kinds.Kind.DIRECTIVE_DEFINITION) {
          locationsMap[def.name.value] = def.locations.map(function (name) {
            return name.value;
          });
        }
      }
    } catch (err) {
      _didIteratorError2 = true;
      _iteratorError2 = err;
    } finally {
      try {
        if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
          _iterator2.return();
        }
      } finally {
        if (_didIteratorError2) {
          throw _iteratorError2;
        }
      }
    }
  
    return {
      Directive: function Directive(node, key, parent, path, ancestors) {
        var name = node.name.value;
        var locations = locationsMap[name];
  
        if (!locations) {
          context.reportError(new _GraphQLError.GraphQLError(unknownDirectiveMessage(name), node));
          return;
        }
  
        var candidateLocation = getDirectiveLocationForASTPath(ancestors);
  
        if (candidateLocation && locations.indexOf(candidateLocation) === -1) {
          context.reportError(new _GraphQLError.GraphQLError(misplacedDirectiveMessage(name, candidateLocation), node));
        }
      }
    };
  }
  
  function getDirectiveLocationForASTPath(ancestors) {
    var appliedTo = ancestors[ancestors.length - 1];
  
    if (!Array.isArray(appliedTo)) {
      switch (appliedTo.kind) {
        case _kinds.Kind.OPERATION_DEFINITION:
          switch (appliedTo.operation) {
            case 'query':
              return _directiveLocation.DirectiveLocation.QUERY;
  
            case 'mutation':
              return _directiveLocation.DirectiveLocation.MUTATION;
  
            case 'subscription':
              return _directiveLocation.DirectiveLocation.SUBSCRIPTION;
          }
  
          break;
  
        case _kinds.Kind.FIELD:
          return _directiveLocation.DirectiveLocation.FIELD;
  
        case _kinds.Kind.FRAGMENT_SPREAD:
          return _directiveLocation.DirectiveLocation.FRAGMENT_SPREAD;
  
        case _kinds.Kind.INLINE_FRAGMENT:
          return _directiveLocation.DirectiveLocation.INLINE_FRAGMENT;
  
        case _kinds.Kind.FRAGMENT_DEFINITION:
          return _directiveLocation.DirectiveLocation.FRAGMENT_DEFINITION;
  
        case _kinds.Kind.VARIABLE_DEFINITION:
          return _directiveLocation.DirectiveLocation.VARIABLE_DEFINITION;
  
        case _kinds.Kind.SCHEMA_DEFINITION:
        case _kinds.Kind.SCHEMA_EXTENSION:
          return _directiveLocation.DirectiveLocation.SCHEMA;
  
        case _kinds.Kind.SCALAR_TYPE_DEFINITION:
        case _kinds.Kind.SCALAR_TYPE_EXTENSION:
          return _directiveLocation.DirectiveLocation.SCALAR;
  
        case _kinds.Kind.OBJECT_TYPE_DEFINITION:
        case _kinds.Kind.OBJECT_TYPE_EXTENSION:
          return _directiveLocation.DirectiveLocation.OBJECT;
  
        case _kinds.Kind.FIELD_DEFINITION:
          return _directiveLocation.DirectiveLocation.FIELD_DEFINITION;
  
        case _kinds.Kind.INTERFACE_TYPE_DEFINITION:
        case _kinds.Kind.INTERFACE_TYPE_EXTENSION:
          return _directiveLocation.DirectiveLocation.INTERFACE;
  
        case _kinds.Kind.UNION_TYPE_DEFINITION:
        case _kinds.Kind.UNION_TYPE_EXTENSION:
          return _directiveLocation.DirectiveLocation.UNION;
  
        case _kinds.Kind.ENUM_TYPE_DEFINITION:
        case _kinds.Kind.ENUM_TYPE_EXTENSION:
          return _directiveLocation.DirectiveLocation.ENUM;
  
        case _kinds.Kind.ENUM_VALUE_DEFINITION:
          return _directiveLocation.DirectiveLocation.ENUM_VALUE;
  
        case _kinds.Kind.INPUT_OBJECT_TYPE_DEFINITION:
        case _kinds.Kind.INPUT_OBJECT_TYPE_EXTENSION:
          return _directiveLocation.DirectiveLocation.INPUT_OBJECT;
  
        case _kinds.Kind.INPUT_VALUE_DEFINITION:
          {
            var parentNode = ancestors[ancestors.length - 3];
            return parentNode.kind === _kinds.Kind.INPUT_OBJECT_TYPE_DEFINITION ? _directiveLocation.DirectiveLocation.INPUT_FIELD_DEFINITION : _directiveLocation.DirectiveLocation.ARGUMENT_DEFINITION;
          }
      }
    }
  }
  