Ohm-Management - Projektarbeit B-ME
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

no-cond-assign.js 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /**
  2. * @fileoverview Rule to flag assignment in a conditional statement's test expression
  3. * @author Stephen Murray <spmurrayzzz>
  4. */
  5. "use strict";
  6. const astUtils = require("../util/ast-utils");
  7. const NODE_DESCRIPTIONS = {
  8. DoWhileStatement: "a 'do...while' statement",
  9. ForStatement: "a 'for' statement",
  10. IfStatement: "an 'if' statement",
  11. WhileStatement: "a 'while' statement"
  12. };
  13. //------------------------------------------------------------------------------
  14. // Rule Definition
  15. //------------------------------------------------------------------------------
  16. module.exports = {
  17. meta: {
  18. type: "problem",
  19. docs: {
  20. description: "disallow assignment operators in conditional expressions",
  21. category: "Possible Errors",
  22. recommended: true,
  23. url: "https://eslint.org/docs/rules/no-cond-assign"
  24. },
  25. schema: [
  26. {
  27. enum: ["except-parens", "always"]
  28. }
  29. ],
  30. messages: {
  31. unexpected: "Unexpected assignment within {{type}}.",
  32. // must match JSHint's error message
  33. missing: "Expected a conditional expression and instead saw an assignment."
  34. }
  35. },
  36. create(context) {
  37. const prohibitAssign = (context.options[0] || "except-parens");
  38. const sourceCode = context.getSourceCode();
  39. /**
  40. * Check whether an AST node is the test expression for a conditional statement.
  41. * @param {!Object} node The node to test.
  42. * @returns {boolean} `true` if the node is the text expression for a conditional statement; otherwise, `false`.
  43. */
  44. function isConditionalTestExpression(node) {
  45. return node.parent &&
  46. node.parent.test &&
  47. node === node.parent.test;
  48. }
  49. /**
  50. * Given an AST node, perform a bottom-up search for the first ancestor that represents a conditional statement.
  51. * @param {!Object} node The node to use at the start of the search.
  52. * @returns {?Object} The closest ancestor node that represents a conditional statement.
  53. */
  54. function findConditionalAncestor(node) {
  55. let currentAncestor = node;
  56. do {
  57. if (isConditionalTestExpression(currentAncestor)) {
  58. return currentAncestor.parent;
  59. }
  60. } while ((currentAncestor = currentAncestor.parent) && !astUtils.isFunction(currentAncestor));
  61. return null;
  62. }
  63. /**
  64. * Check whether the code represented by an AST node is enclosed in two sets of parentheses.
  65. * @param {!Object} node The node to test.
  66. * @returns {boolean} `true` if the code is enclosed in two sets of parentheses; otherwise, `false`.
  67. */
  68. function isParenthesisedTwice(node) {
  69. const previousToken = sourceCode.getTokenBefore(node, 1),
  70. nextToken = sourceCode.getTokenAfter(node, 1);
  71. return astUtils.isParenthesised(sourceCode, node) &&
  72. astUtils.isOpeningParenToken(previousToken) && previousToken.range[1] <= node.range[0] &&
  73. astUtils.isClosingParenToken(nextToken) && nextToken.range[0] >= node.range[1];
  74. }
  75. /**
  76. * Check a conditional statement's test expression for top-level assignments that are not enclosed in parentheses.
  77. * @param {!Object} node The node for the conditional statement.
  78. * @returns {void}
  79. */
  80. function testForAssign(node) {
  81. if (node.test &&
  82. (node.test.type === "AssignmentExpression") &&
  83. (node.type === "ForStatement"
  84. ? !astUtils.isParenthesised(sourceCode, node.test)
  85. : !isParenthesisedTwice(node.test)
  86. )
  87. ) {
  88. context.report({
  89. node,
  90. loc: node.test.loc.start,
  91. messageId: "missing"
  92. });
  93. }
  94. }
  95. /**
  96. * Check whether an assignment expression is descended from a conditional statement's test expression.
  97. * @param {!Object} node The node for the assignment expression.
  98. * @returns {void}
  99. */
  100. function testForConditionalAncestor(node) {
  101. const ancestor = findConditionalAncestor(node);
  102. if (ancestor) {
  103. context.report({
  104. node: ancestor,
  105. messageId: "unexpected",
  106. data: {
  107. type: NODE_DESCRIPTIONS[ancestor.type] || ancestor.type
  108. }
  109. });
  110. }
  111. }
  112. if (prohibitAssign === "always") {
  113. return {
  114. AssignmentExpression: testForConditionalAncestor
  115. };
  116. }
  117. return {
  118. DoWhileStatement: testForAssign,
  119. ForStatement: testForAssign,
  120. IfStatement: testForAssign,
  121. WhileStatement: testForAssign,
  122. ConditionalExpression: testForAssign
  123. };
  124. }
  125. };