Skip to content

Commit

Permalink
Fix: no-implicit-coercion string concat false positive (fixes #7057) (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
kaicataldo authored and ilyavolodin committed Sep 7, 2016
1 parent 6718749 commit 1f995c3
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 15 deletions.
46 changes: 32 additions & 14 deletions lib/rules/no-implicit-coercion.js
Expand Up @@ -5,6 +5,8 @@

"use strict";

const astUtils = require("../ast-utils");

//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
Expand Down Expand Up @@ -105,15 +107,35 @@ function getNonNumericOperand(node) {
return null;
}

/**
* Checks whether a node is a string literal or not.
* @param {ASTNode} node The node to check.
* @returns {boolean} Whether or not the passed in node is a
* string literal or not.
*/
function isStringLiteral(node) {
return astUtils.isStringLiteral(node) && node.type !== "TemplateLiteral";
}

/**
* Checks whether a node is an empty string literal or not.
* @param {ASTNode} node The node to check.
* @returns {boolean} Whether or not the passed in node is an
* empty string literal or not.
*/
function isEmptyString(node) {
return isStringLiteral(node) && node.value === "";
}

/**
* Checks whether or not a node is a concatenating with an empty string.
* @param {ASTNode} node - A BinaryExpression node to check.
* @returns {boolean} Whether or not the node is a concatenating with an empty string.
*/
function isConcatWithEmptyString(node) {
return node.operator === "+" && (
(node.left.type === "Literal" && node.left.value === "") ||
(node.right.type === "Literal" && node.right.value === "")
(isEmptyString(node.left) && !isStringLiteral(node.right)) ||
(isEmptyString(node.right) && !isStringLiteral(node.left))
);
}

Expand All @@ -123,20 +145,16 @@ function isConcatWithEmptyString(node) {
* @returns {boolean} Whether or not the node is appended with an empty string.
*/
function isAppendEmptyString(node) {
return node.operator === "+=" && node.right.type === "Literal" && node.right.value === "";
return node.operator === "+=" && isEmptyString(node.right);
}

/**
* Gets a node that is the left or right operand of a node, is not the specified literal.
* @param {ASTNode} node - A BinaryExpression node to get.
* @param {any} value - A literal value to check.
* @returns {ASTNode} A node that is the left or right operand of the node, is not the specified literal.
* Returns the operand that is not an empty string from a flagged BinaryExpression.
* @param {ASTNode} node - The flagged BinaryExpression node to check.
* @returns {ASTNode} The operand that is not an empty string from a flagged BinaryExpression.
*/
function getOtherOperand(node, value) {
if (node.left.type === "Literal" && node.left.value === value) {
return node.right;
}
return node.left;
function getNonEmptyOperand(node) {
return isEmptyString(node.left) ? node.right : node.left;
}

//------------------------------------------------------------------------------
Expand Down Expand Up @@ -236,7 +254,7 @@ module.exports = {
context.report(
node,
"use `String({{code}})` instead.", {
code: sourceCode.getText(getOtherOperand(node, ""))
code: sourceCode.getText(getNonEmptyOperand(node))
});
}
},
Expand All @@ -250,7 +268,7 @@ module.exports = {
context.report(
node,
"use `{{code}} = String({{code}})` instead.", {
code: sourceCode.getText(getOtherOperand(node, ""))
code: sourceCode.getText(getNonEmptyOperand(node))
});
}
}
Expand Down
8 changes: 7 additions & 1 deletion tests/lib/rules/no-implicit-coercion.js
Expand Up @@ -75,7 +75,13 @@ ruleTester.run("no-implicit-coercion", rule, {
{code: "var a = ~foo", options: [{boolean: true}]},
{code: "var a = 1 * foo", options: [{boolean: true, allow: ["*"]}]},
{code: "var a = +foo", options: [{boolean: true, allow: ["+"]}]},
{code: "var a = \"\" + foo", options: [{boolean: true, string: true, allow: ["+"]}]}
{code: "var a = \"\" + foo", options: [{boolean: true, string: true, allow: ["+"]}]},

// https://github.com/eslint/eslint/issues/7057
{code: "'' + 'foo'"},
{code: "'foo' + ''"},
{code: "foo += 'bar'"},
{code: "+42"}
],
invalid: [
{code: "!!foo", errors: [{message: "use `Boolean(foo)` instead.", type: "UnaryExpression"}]},
Expand Down

0 comments on commit 1f995c3

Please sign in to comment.