| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 | /** * @fileoverview disallow unncessary concatenation of template strings * @author Henry Zhu */"use strict";//------------------------------------------------------------------------------// Requirements//------------------------------------------------------------------------------const astUtils = require("../ast-utils");//------------------------------------------------------------------------------// Helpers//------------------------------------------------------------------------------/** * Checks whether or not a given node is a concatenation. * @param {ASTNode} node - A node to check. * @returns {boolean} `true` if the node is a concatenation. */function isConcatenation(node) {    return node.type === "BinaryExpression" && node.operator === "+";}/** * Checks if the given token is a `+` token or not. * @param {Token} token - The token to check. * @returns {boolean} `true` if the token is a `+` token. */function isConcatOperatorToken(token) {    return token.value === "+" && token.type === "Punctuator";}/** * Get's the right most node on the left side of a BinaryExpression with + operator. * @param {ASTNode} node - A BinaryExpression node to check. * @returns {ASTNode} node */function getLeft(node) {    let left = node.left;    while (isConcatenation(left)) {        left = left.right;    }    return left;}/** * Get's the left most node on the right side of a BinaryExpression with + operator. * @param {ASTNode} node - A BinaryExpression node to check. * @returns {ASTNode} node */function getRight(node) {    let right = node.right;    while (isConcatenation(right)) {        right = right.left;    }    return right;}//------------------------------------------------------------------------------// Rule Definition//------------------------------------------------------------------------------module.exports = {    meta: {        docs: {            description: "disallow unnecessary concatenation of literals or template literals",            category: "Best Practices",            recommended: false,            url: "https://eslint.org/docs/rules/no-useless-concat"        },        schema: []    },    create(context) {        const sourceCode = context.getSourceCode();        return {            BinaryExpression(node) {                // check if not concatenation                if (node.operator !== "+") {                    return;                }                // account for the `foo + "a" + "b"` case                const left = getLeft(node);                const right = getRight(node);                if (astUtils.isStringLiteral(left) &&                    astUtils.isStringLiteral(right) &&                    astUtils.isTokenOnSameLine(left, right)                ) {                    const operatorToken = sourceCode.getFirstTokenBetween(left, right, isConcatOperatorToken);                    context.report({                        node,                        loc: operatorToken.loc.start,                        message: "Unexpected string concatenation of literals."                    });                }            }        };    }};
 |