'use strict';

var _lodash = require('lodash.find');

var _lodash2 = _interopRequireDefault(_lodash);

var _minimatch = require('minimatch');

var _minimatch2 = _interopRequireDefault(_minimatch);

var _resolve = require('../core/resolve');

var _resolve2 = _interopRequireDefault(_resolve);

var _importType = require('../core/importType');

var _importType2 = _interopRequireDefault(_importType);

var _staticRequire = require('../core/staticRequire');

var _staticRequire2 = _interopRequireDefault(_staticRequire);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

module.exports = function noReachingInside(context) {
  var options = context.options[0] || {};
  var allowRegexps = (options.allow || []).map(function (p) {
    return _minimatch2.default.makeRe(p);
  });

  // test if reaching to this destination is allowed
  function reachingAllowed(importPath) {
    return !!(0, _lodash2.default)(allowRegexps, function (re) {
      return re.test(importPath);
    });
  }

  // minimatch patterns are expected to use / path separators, like import
  // statements, so normalize paths to use the same
  function normalizeSep(somePath) {
    return somePath.split('\\').join('/');
  }

  // find a directory that is being reached into, but which shouldn't be
  function isReachViolation(importPath) {
    var steps = normalizeSep(importPath).split('/').reduce(function (acc, step) {
      if (!step || step === '.') {
        return acc;
      } else if (step === '..') {
        return acc.slice(0, -1);
      } else {
        return acc.concat(step);
      }
    }, []);

    if (steps.length <= 1) return false;

    // before trying to resolve, see if the raw import (with relative
    // segments resolved) matches an allowed pattern
    var justSteps = steps.join('/');
    if (reachingAllowed(justSteps) || reachingAllowed('/' + justSteps)) return false;

    // if the import statement doesn't match directly, try to match the
    // resolved path if the import is resolvable
    var resolved = (0, _resolve2.default)(importPath, context);
    if (!resolved || reachingAllowed(normalizeSep(resolved))) return false;

    // this import was not allowed by the allowed paths, and reaches
    // so it is a violation
    return true;
  }

  function checkImportForReaching(importPath, node) {
    var potentialViolationTypes = ['parent', 'index', 'sibling', 'external', 'internal'];
    if (potentialViolationTypes.indexOf((0, _importType2.default)(importPath, context)) !== -1 && isReachViolation(importPath)) {
      context.report({
        node: node,
        message: 'Reaching to "' + importPath + '" is not allowed.'
      });
    }
  }

  return {
    ImportDeclaration: function ImportDeclaration(node) {
      checkImportForReaching(node.source.value, node.source);
    },
    CallExpression: function CallExpression(node) {
      if ((0, _staticRequire2.default)(node)) {
        var _node$arguments = node.arguments;
        var firstArgument = _node$arguments[0];

        checkImportForReaching(firstArgument.value, firstArgument);
      }
    }
  };
};

module.exports.schema = [{
  type: 'object',
  properties: {
    allow: {
      type: 'array',
      items: {
        type: 'string'
      }
    }
  },
  additionalProperties: false
}];
//# sourceMappingURL=data:application/json;base64,[encoded data, 7320 characters]