twada/espower

View on GitHub
lib/rules/to-be-skipped.js

Summary

Maintainability
A
0 mins
Test Coverage
'use strict';

const { Syntax } = require('estraverse');
const supportedNodeTypes = require('./supported-node-types');

const isLeftHandSideOfAssignment = (parentNode, currentKey) => {
  // Do not instrument left due to 'Invalid left-hand side in assignment'
  return parentNode.type === Syntax.AssignmentExpression && currentKey === 'left';
};

const isChildOfObjectLiteral = (parentNode) => {
  return parentNode.type === Syntax.Property && parentNode.kind === 'init';
};

const isObjectLiteralKey = (parentNode, currentKey) => {
  return isChildOfObjectLiteral(parentNode) && currentKey === 'key';
};

const isObjectLiteralValue = (parentNode, currentKey) => {
  return isChildOfObjectLiteral(parentNode) && currentKey === 'value';
};

const isNonComputedObjectLiteralKey = (parentNode, currentKey) => {
  // Do not instrument non-computed Object literal key
  return isObjectLiteralKey(parentNode, currentKey) && !parentNode.computed;
};

const isShorthandedValueOfObjectLiteral = (parentNode, currentKey) => {
  // Do not instrument shorthanded Object literal value
  return isObjectLiteralValue(parentNode, currentKey) && parentNode.shorthand;
};

const isUpdateExpression = (parentNode) => {
  // Just wrap UpdateExpression, not digging in.
  return parentNode.type === Syntax.UpdateExpression;
};

const isCallExpressionWithNonComputedMemberExpression = (currentNode, parentNode, currentKey) => {
  // Do not instrument non-computed property of MemberExpression within CallExpression.
  return currentNode.type === Syntax.Identifier && parentNode.type === Syntax.MemberExpression && !parentNode.computed && currentKey === 'property';
};

const isTypeOfOrDeleteUnaryExpression = (currentNode, parentNode, currentKey) => {
  // 'typeof Identifier' or 'delete Identifier' is not instrumented
  return currentNode.type === Syntax.Identifier && parentNode.type === Syntax.UnaryExpression && (parentNode.operator === 'typeof' || parentNode.operator === 'delete') && currentKey === 'argument';
};

const isSupportedNodeType = (node) => {
  return supportedNodeTypes.indexOf(node.type) !== -1;
};

const toBeSkipped = ({ currentNode, parentNode, currentKey }) => {
  return !isSupportedNodeType(currentNode) ||
        isLeftHandSideOfAssignment(parentNode, currentKey) ||
        isNonComputedObjectLiteralKey(parentNode, currentKey) ||
        isShorthandedValueOfObjectLiteral(parentNode, currentKey) ||
        isUpdateExpression(parentNode) ||
        isCallExpressionWithNonComputedMemberExpression(currentNode, parentNode, currentKey) ||
        isTypeOfOrDeleteUnaryExpression(currentNode, parentNode, currentKey);
};

module.exports = toBeSkipped;