项目原始demo,不改动
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.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

space-infix-ops.js 5.4 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /**
  2. * @fileoverview Require spaces around infix operators
  3. * @author Michael Ficarra
  4. */
  5. "use strict";
  6. //------------------------------------------------------------------------------
  7. // Rule Definition
  8. //------------------------------------------------------------------------------
  9. module.exports = {
  10. meta: {
  11. docs: {
  12. description: "require spacing around infix operators",
  13. category: "Stylistic Issues",
  14. recommended: false,
  15. url: "https://eslint.org/docs/rules/space-infix-ops"
  16. },
  17. fixable: "whitespace",
  18. schema: [
  19. {
  20. type: "object",
  21. properties: {
  22. int32Hint: {
  23. type: "boolean"
  24. }
  25. },
  26. additionalProperties: false
  27. }
  28. ]
  29. },
  30. create(context) {
  31. const int32Hint = context.options[0] ? context.options[0].int32Hint === true : false;
  32. const OPERATORS = [
  33. "*", "/", "%", "+", "-", "<<", ">>", ">>>", "<", "<=", ">", ">=", "in",
  34. "instanceof", "==", "!=", "===", "!==", "&", "^", "|", "&&", "||", "=",
  35. "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", "&=", "^=", "|=",
  36. "?", ":", ",", "**"
  37. ];
  38. const sourceCode = context.getSourceCode();
  39. /**
  40. * Returns the first token which violates the rule
  41. * @param {ASTNode} left - The left node of the main node
  42. * @param {ASTNode} right - The right node of the main node
  43. * @returns {Object} The violator token or null
  44. * @private
  45. */
  46. function getFirstNonSpacedToken(left, right) {
  47. const tokens = sourceCode.getTokensBetween(left, right, 1);
  48. for (let i = 1, l = tokens.length - 1; i < l; ++i) {
  49. const op = tokens[i];
  50. if (
  51. (op.type === "Punctuator" || op.type === "Keyword") &&
  52. OPERATORS.indexOf(op.value) >= 0 &&
  53. (tokens[i - 1].range[1] >= op.range[0] || op.range[1] >= tokens[i + 1].range[0])
  54. ) {
  55. return op;
  56. }
  57. }
  58. return null;
  59. }
  60. /**
  61. * Reports an AST node as a rule violation
  62. * @param {ASTNode} mainNode - The node to report
  63. * @param {Object} culpritToken - The token which has a problem
  64. * @returns {void}
  65. * @private
  66. */
  67. function report(mainNode, culpritToken) {
  68. context.report({
  69. node: mainNode,
  70. loc: culpritToken.loc.start,
  71. message: "Infix operators must be spaced.",
  72. fix(fixer) {
  73. const previousToken = sourceCode.getTokenBefore(culpritToken);
  74. const afterToken = sourceCode.getTokenAfter(culpritToken);
  75. let fixString = "";
  76. if (culpritToken.range[0] - previousToken.range[1] === 0) {
  77. fixString = " ";
  78. }
  79. fixString += culpritToken.value;
  80. if (afterToken.range[0] - culpritToken.range[1] === 0) {
  81. fixString += " ";
  82. }
  83. return fixer.replaceText(culpritToken, fixString);
  84. }
  85. });
  86. }
  87. /**
  88. * Check if the node is binary then report
  89. * @param {ASTNode} node node to evaluate
  90. * @returns {void}
  91. * @private
  92. */
  93. function checkBinary(node) {
  94. const leftNode = (node.left.typeAnnotation) ? node.left.typeAnnotation : node.left;
  95. const rightNode = node.right;
  96. const nonSpacedNode = getFirstNonSpacedToken(leftNode, rightNode);
  97. if (nonSpacedNode) {
  98. if (!(int32Hint && sourceCode.getText(node).endsWith("|0"))) {
  99. report(node, nonSpacedNode);
  100. }
  101. }
  102. }
  103. /**
  104. * Check if the node is conditional
  105. * @param {ASTNode} node node to evaluate
  106. * @returns {void}
  107. * @private
  108. */
  109. function checkConditional(node) {
  110. const nonSpacedConsequesntNode = getFirstNonSpacedToken(node.test, node.consequent);
  111. const nonSpacedAlternateNode = getFirstNonSpacedToken(node.consequent, node.alternate);
  112. if (nonSpacedConsequesntNode) {
  113. report(node, nonSpacedConsequesntNode);
  114. } else if (nonSpacedAlternateNode) {
  115. report(node, nonSpacedAlternateNode);
  116. }
  117. }
  118. /**
  119. * Check if the node is a variable
  120. * @param {ASTNode} node node to evaluate
  121. * @returns {void}
  122. * @private
  123. */
  124. function checkVar(node) {
  125. const leftNode = (node.id.typeAnnotation) ? node.id.typeAnnotation : node.id;
  126. const rightNode = node.init;
  127. if (rightNode) {
  128. const nonSpacedNode = getFirstNonSpacedToken(leftNode, rightNode);
  129. if (nonSpacedNode) {
  130. report(node, nonSpacedNode);
  131. }
  132. }
  133. }
  134. return {
  135. AssignmentExpression: checkBinary,
  136. AssignmentPattern: checkBinary,
  137. BinaryExpression: checkBinary,
  138. LogicalExpression: checkBinary,
  139. ConditionalExpression: checkConditional,
  140. VariableDeclarator: checkVar
  141. };
  142. }
  143. };