Skip to content

Commit

Permalink
Update: no-implicit-coercion checks TemplateLiterals (fixes #7062) (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
kaicataldo authored and nzakas committed Sep 13, 2016
1 parent 8db4f0c commit a876673
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 14 deletions.
5 changes: 4 additions & 1 deletion docs/rules/no-implicit-coercion.md
Expand Up @@ -13,7 +13,7 @@ var b = ~foo.indexOf(".");
var n = +foo;
var n = 1 * foo;
var s = "" + foo;
foo += "";
foo += ``;
```

Those can be replaced with the following code:
Expand Down Expand Up @@ -94,7 +94,9 @@ Examples of **incorrect** code for the default `{ "string": true }` option:
/*eslint no-implicit-coercion: "error"*/

var s = "" + foo;
var s = `` + foo;
foo += "";
foo += ``;
```

Examples of **correct** code for the default `{ "string": true }` option:
Expand All @@ -103,6 +105,7 @@ Examples of **correct** code for the default `{ "string": true }` option:
/*eslint no-implicit-coercion: "error"*/

var s = String(foo);
foo = String(foo);
```

### allow
Expand Down
16 changes: 3 additions & 13 deletions lib/rules/no-implicit-coercion.js
Expand Up @@ -107,24 +107,14 @@ 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 === "";
return astUtils.isStringLiteral(node) && (node.value === "" || (node.type === "TemplateLiteral" && node.quasis.length === 1 && node.quasis[0].value.cooked === ""));
}

/**
Expand All @@ -134,8 +124,8 @@ function isEmptyString(node) {
*/
function isConcatWithEmptyString(node) {
return node.operator === "+" && (
(isEmptyString(node.left) && !isStringLiteral(node.right)) ||
(isEmptyString(node.right) && !isStringLiteral(node.left))
(isEmptyString(node.left) && !astUtils.isStringLiteral(node.right)) ||
(isEmptyString(node.right) && !astUtils.isStringLiteral(node.left))
);
}

Expand Down
48 changes: 48 additions & 0 deletions tests/lib/rules/no-implicit-coercion.js
Expand Up @@ -63,6 +63,8 @@ ruleTester.run("no-implicit-coercion", rule, {
{code: "1234*1*parseInt(foo)*bar"},
{code: "0 + foo"},
{code: "~foo.bar()"},
{code: "foo + 'bar'" },
{code: "foo + `${bar}`", parserOptions: { ecmaVersion: 6 } },

{code: "!!foo", options: [{boolean: false}]},
{code: "~foo.indexOf(1)", options: [{boolean: false}]},
Expand All @@ -79,8 +81,13 @@ ruleTester.run("no-implicit-coercion", rule, {

// https://github.com/eslint/eslint/issues/7057
{code: "'' + 'foo'"},
{code: "`` + 'foo'", parserOptions: { ecmaVersion: 6 } },
{code: "'' + `${foo}`", parserOptions: { ecmaVersion: 6 } },
{code: "'foo' + ''"},
{code: "'foo' + ``", parserOptions: { ecmaVersion: 6 } },
{code: "`${foo}` + ''", parserOptions: { ecmaVersion: 6 } },
{code: "foo += 'bar'"},
{code: "foo += `${bar}`", parserOptions: { ecmaVersion: 6 } },
{code: "+42"}
],
invalid: [
Expand Down Expand Up @@ -134,21 +141,56 @@ ruleTester.run("no-implicit-coercion", rule, {
errors: [{message: "use `String(foo)` instead.", type: "BinaryExpression"}],
output: "String(foo)"
},
{
code: "``+foo",
parserOptions: { ecmaVersion: 6 },
errors: [{message: "use `String(foo)` instead.", type: "BinaryExpression"}],
output: "String(foo)"
},
{
code: "foo+\"\"",
errors: [{message: "use `String(foo)` instead.", type: "BinaryExpression"}],
output: "String(foo)"
},
{
code: "foo+``",
parserOptions: { ecmaVersion: 6 },
errors: [{message: "use `String(foo)` instead.", type: "BinaryExpression"}],
output: "String(foo)"
},
{
code: "\"\"+foo.bar",
errors: [{message: "use `String(foo.bar)` instead.", type: "BinaryExpression"}],
output: "String(foo.bar)"
},
{
code: "``+foo.bar",
parserOptions: { ecmaVersion: 6 },
errors: [{message: "use `String(foo.bar)` instead.", type: "BinaryExpression"}],
output: "String(foo.bar)"
},
{
code: "foo.bar+\"\"",
errors: [{message: "use `String(foo.bar)` instead.", type: "BinaryExpression"}],
output: "String(foo.bar)"
},
{
code: "foo.bar+``",
parserOptions: { ecmaVersion: 6 },
errors: [{message: "use `String(foo.bar)` instead.", type: "BinaryExpression"}],
output: "String(foo.bar)"
},
{
code: "foo += \"\"",
errors: [{message: "use `foo = String(foo)` instead.", type: "AssignmentExpression"}],
output: "foo = String(foo)"
},
{
code: "foo += ``",
parserOptions: { ecmaVersion: 6 },
errors: [{message: "use `foo = String(foo)` instead.", type: "AssignmentExpression"}],
output: "foo = String(foo)"
},
{
code: "var a = !!foo", options: [{boolean: true, allow: ["~"]}],
errors: [{message: "use `Boolean(foo)` instead.", type: "UnaryExpression"}],
Expand All @@ -173,6 +215,12 @@ ruleTester.run("no-implicit-coercion", rule, {
code: "var a = \"\" + foo", options: [{boolean: true, allow: ["*"]}],
errors: [{message: "use `String(foo)` instead.", type: "BinaryExpression"}],
output: "var a = String(foo)"
},
{
code: "var a = `` + foo", options: [{boolean: true, allow: ["*"]}],
parserOptions: { ecmaVersion: 6 },
errors: [{message: "use `String(foo)` instead.", type: "BinaryExpression"}],
output: "var a = String(foo)"
}
]
});

0 comments on commit a876673

Please sign in to comment.