no-negated-condition.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /**
  2. * @fileoverview Rule to disallow a negated condition
  3. * @author Alberto Rodríguez
  4. */
  5. "use strict";
  6. //------------------------------------------------------------------------------
  7. // Rule Definition
  8. //------------------------------------------------------------------------------
  9. /** @type {import('../types').Rule.RuleModule} */
  10. module.exports = {
  11. meta: {
  12. type: "suggestion",
  13. docs: {
  14. description: "Disallow negated conditions",
  15. recommended: false,
  16. frozen: true,
  17. url: "https://eslint.org/docs/latest/rules/no-negated-condition",
  18. },
  19. schema: [],
  20. messages: {
  21. unexpectedNegated: "Unexpected negated condition.",
  22. },
  23. },
  24. create(context) {
  25. /**
  26. * Determines if a given node is an if-else without a condition on the else
  27. * @param {ASTNode} node The node to check.
  28. * @returns {boolean} True if the node has an else without an if.
  29. * @private
  30. */
  31. function hasElseWithoutCondition(node) {
  32. return node.alternate && node.alternate.type !== "IfStatement";
  33. }
  34. /**
  35. * Determines if a given node is a negated unary expression
  36. * @param {Object} test The test object to check.
  37. * @returns {boolean} True if the node is a negated unary expression.
  38. * @private
  39. */
  40. function isNegatedUnaryExpression(test) {
  41. return test.type === "UnaryExpression" && test.operator === "!";
  42. }
  43. /**
  44. * Determines if a given node is a negated binary expression
  45. * @param {Test} test The test to check.
  46. * @returns {boolean} True if the node is a negated binary expression.
  47. * @private
  48. */
  49. function isNegatedBinaryExpression(test) {
  50. return (
  51. test.type === "BinaryExpression" &&
  52. (test.operator === "!=" || test.operator === "!==")
  53. );
  54. }
  55. /**
  56. * Determines if a given node has a negated if expression
  57. * @param {ASTNode} node The node to check.
  58. * @returns {boolean} True if the node has a negated if expression.
  59. * @private
  60. */
  61. function isNegatedIf(node) {
  62. return (
  63. isNegatedUnaryExpression(node.test) ||
  64. isNegatedBinaryExpression(node.test)
  65. );
  66. }
  67. return {
  68. IfStatement(node) {
  69. if (!hasElseWithoutCondition(node)) {
  70. return;
  71. }
  72. if (isNegatedIf(node)) {
  73. context.report({
  74. node,
  75. messageId: "unexpectedNegated",
  76. });
  77. }
  78. },
  79. ConditionalExpression(node) {
  80. if (isNegatedIf(node)) {
  81. context.report({
  82. node,
  83. messageId: "unexpectedNegated",
  84. });
  85. }
  86. },
  87. };
  88. },
  89. };