Permalink
Cannot retrieve contributors at this time
| /** | |
| * @fileoverview Require spaces around infix operators | |
| * @author Michael Ficarra | |
| */ | |
| "use strict"; | |
| //------------------------------------------------------------------------------ | |
| // Rule Definition | |
| //------------------------------------------------------------------------------ | |
| module.exports = { | |
| meta: { | |
| type: "layout", | |
| 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", | |
| default: false | |
| } | |
| }, | |
| additionalProperties: false | |
| } | |
| ] | |
| }, | |
| create(context) { | |
| const int32Hint = context.options[0] ? context.options[0].int32Hint === true : false; | |
| 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 | |
| * @param {string} op The operator of the main node | |
| * @returns {Object} The violator token or null | |
| * @private | |
| */ | |
| function getFirstNonSpacedToken(left, right, op) { | |
| const operator = sourceCode.getFirstTokenBetween(left, right, token => token.value === op); | |
| const prev = sourceCode.getTokenBefore(operator); | |
| const next = sourceCode.getTokenAfter(operator); | |
| if (!sourceCode.isSpaceBetweenTokens(prev, operator) || !sourceCode.isSpaceBetweenTokens(operator, next)) { | |
| return operator; | |
| } | |
| 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: "Operator '{{operator}}' must be spaced.", | |
| data: { | |
| operator: culpritToken.value | |
| }, | |
| 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; | |
| // search for = in AssignmentPattern nodes | |
| const operator = node.operator || "="; | |
| const nonSpacedNode = getFirstNonSpacedToken(leftNode, rightNode, operator); | |
| 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 | |
| }; | |
| } | |
| }; |