| 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        };    }};
 |