|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- /**
- * @fileoverview Require spaces around infix operators
- * @author Michael Ficarra
- */
- "use strict";
-
- //------------------------------------------------------------------------------
- // Rule Definition
- //------------------------------------------------------------------------------
-
- module.exports = {
- meta: {
- docs: {
- description: "require spacing around infix operators",
- category: "Stylistic Issues",
- recommended: false,
- url: "https://eslint.org/docs/rules/space-infix-ops"
- },
-
- fixable: "whitespace",
-
- schema: [
- {
- type: "object",
- properties: {
- int32Hint: {
- type: "boolean"
- }
- },
- additionalProperties: false
- }
- ]
- },
-
- create(context) {
- const int32Hint = context.options[0] ? context.options[0].int32Hint === true : false;
-
- const OPERATORS = [
- "*", "/", "%", "+", "-", "<<", ">>", ">>>", "<", "<=", ">", ">=", "in",
- "instanceof", "==", "!=", "===", "!==", "&", "^", "|", "&&", "||", "=",
- "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", "&=", "^=", "|=",
- "?", ":", ",", "**"
- ];
-
- const sourceCode = context.getSourceCode();
-
- /**
- * Returns the first token which violates the rule
- * @param {ASTNode} left - The left node of the main node
- * @param {ASTNode} right - The right node of the main node
- * @returns {Object} The violator token or null
- * @private
- */
- function getFirstNonSpacedToken(left, right) {
- const tokens = sourceCode.getTokensBetween(left, right, 1);
-
- for (let i = 1, l = tokens.length - 1; i < l; ++i) {
- const op = tokens[i];
-
- if (
- (op.type === "Punctuator" || op.type === "Keyword") &&
- OPERATORS.indexOf(op.value) >= 0 &&
- (tokens[i - 1].range[1] >= op.range[0] || op.range[1] >= tokens[i + 1].range[0])
- ) {
- return op;
- }
- }
- return null;
- }
-
- /**
- * Reports an AST node as a rule violation
- * @param {ASTNode} mainNode - The node to report
- * @param {Object} culpritToken - The token which has a problem
- * @returns {void}
- * @private
- */
- function report(mainNode, culpritToken) {
- context.report({
- node: mainNode,
- loc: culpritToken.loc.start,
- message: "Infix operators must be spaced.",
- fix(fixer) {
- const previousToken = sourceCode.getTokenBefore(culpritToken);
- const afterToken = sourceCode.getTokenAfter(culpritToken);
- let fixString = "";
-
- if (culpritToken.range[0] - previousToken.range[1] === 0) {
- fixString = " ";
- }
-
- fixString += culpritToken.value;
-
- if (afterToken.range[0] - culpritToken.range[1] === 0) {
- fixString += " ";
- }
-
- return fixer.replaceText(culpritToken, fixString);
- }
- });
- }
-
- /**
- * Check if the node is binary then report
- * @param {ASTNode} node node to evaluate
- * @returns {void}
- * @private
- */
- function checkBinary(node) {
- const leftNode = (node.left.typeAnnotation) ? node.left.typeAnnotation : node.left;
- const rightNode = node.right;
-
- const nonSpacedNode = getFirstNonSpacedToken(leftNode, rightNode);
-
- if (nonSpacedNode) {
- if (!(int32Hint && sourceCode.getText(node).endsWith("|0"))) {
- report(node, nonSpacedNode);
- }
- }
- }
-
- /**
- * Check if the node is conditional
- * @param {ASTNode} node node to evaluate
- * @returns {void}
- * @private
- */
- function checkConditional(node) {
- const nonSpacedConsequesntNode = getFirstNonSpacedToken(node.test, node.consequent);
- const nonSpacedAlternateNode = getFirstNonSpacedToken(node.consequent, node.alternate);
-
- if (nonSpacedConsequesntNode) {
- report(node, nonSpacedConsequesntNode);
- } else if (nonSpacedAlternateNode) {
- report(node, nonSpacedAlternateNode);
- }
- }
-
- /**
- * Check if the node is a variable
- * @param {ASTNode} node node to evaluate
- * @returns {void}
- * @private
- */
- function checkVar(node) {
- const leftNode = (node.id.typeAnnotation) ? node.id.typeAnnotation : node.id;
- const rightNode = node.init;
-
- if (rightNode) {
- const nonSpacedNode = getFirstNonSpacedToken(leftNode, rightNode);
-
- if (nonSpacedNode) {
- report(node, nonSpacedNode);
- }
- }
- }
-
- return {
- AssignmentExpression: checkBinary,
- AssignmentPattern: checkBinary,
- BinaryExpression: checkBinary,
- LogicalExpression: checkBinary,
- ConditionalExpression: checkConditional,
- VariableDeclarator: checkVar
- };
-
- }
- };
|