• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * Utility functions common to ESLint rules.
3 */
4'use strict';
5
6function isRequireCall(node) {
7  return node.callee.type === 'Identifier' && node.callee.name === 'require';
8}
9module.exports.isRequireCall = isRequireCall;
10
11module.exports.isString = function(node) {
12  return node && node.type === 'Literal' && typeof node.value === 'string';
13};
14
15module.exports.isDefiningError = function(node) {
16  return node.expression &&
17         node.expression.type === 'CallExpression' &&
18         node.expression.callee &&
19         node.expression.callee.name === 'E' &&
20         node.expression.arguments.length !== 0;
21};
22
23/**
24 * Returns true if any of the passed in modules are used in
25 * require calls.
26 */
27module.exports.isRequired = function(node, modules) {
28  return isRequireCall(node) && node.arguments.length !== 0 &&
29    modules.includes(node.arguments[0].value);
30};
31
32/**
33* Return true if common module is required
34* in AST Node under inspection
35*/
36const commonModuleRegExp = new RegExp(/^(\.\.\/)*common(\.js)?$/);
37module.exports.isCommonModule = function(node) {
38  return isRequireCall(node) &&
39         node.arguments.length !== 0 &&
40         commonModuleRegExp.test(node.arguments[0].value);
41};
42
43/**
44 * Returns true if any of the passed in modules are used in
45 * process.binding() or internalBinding() calls.
46 */
47module.exports.isBinding = function(node, modules) {
48  const isProcessBinding = node.callee.object &&
49                           node.callee.object.name === 'process' &&
50                           node.callee.property.name === 'binding';
51
52  return (isProcessBinding || node.callee.name === 'internalBinding') &&
53         modules.includes(node.arguments[0].value);
54};
55
56/**
57 * Returns true is the node accesses any property in the properties
58 * array on the 'common' object.
59 */
60module.exports.usesCommonProperty = function(node, properties) {
61  if (node.name) {
62    return properties.includes(node.name);
63  }
64  if (node.property) {
65    return properties.includes(node.property.name);
66  }
67  return false;
68};
69
70/**
71 * Returns true if the passed in node is inside an if statement block,
72 * and the block also has a call to skip.
73 */
74module.exports.inSkipBlock = function(node) {
75  let hasSkipBlock = false;
76  if (node.test &&
77      node.test.type === 'UnaryExpression' &&
78      node.test.operator === '!') {
79    const consequent = node.consequent;
80    if (consequent.body) {
81      consequent.body.some((expressionStatement) => {
82        if (hasSkip(expressionStatement.expression)) {
83          return hasSkipBlock = true;
84        }
85        return false;
86      });
87    } else if (hasSkip(consequent.expression)) {
88      hasSkipBlock = true;
89    }
90  }
91  return hasSkipBlock;
92};
93
94function hasSkip(expression) {
95  return expression &&
96         expression.callee &&
97         (expression.callee.name === 'skip' ||
98         expression.callee.property &&
99         expression.callee.property.name === 'skip');
100}
101