Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update: Add disallowTemplateShorthand option in no-implicit-coercion #13579

Merged
43 changes: 39 additions & 4 deletions docs/rules/no-implicit-coercion.md
Expand Up @@ -33,10 +33,11 @@ This rule is aimed to flag shorter notations for the type conversion, then sugge

This rule has three main options and one override option to allow some coercions as required.

* `"boolean"` (`true` by default) - When this is `true`, this rule warns shorter type conversions for `boolean` type.
* `"number"` (`true` by default) - When this is `true`, this rule warns shorter type conversions for `number` type.
* `"string"` (`true` by default) - When this is `true`, this rule warns shorter type conversions for `string` type.
* `"allow"` (`empty` by default) - Each entry in this array can be one of `~`, `!!`, `+` or `*` that are to be allowed.
- `"boolean"` (`true` by default) - When this is `true`, this rule warns shorter type conversions for `boolean` type.
- `"number"` (`true` by default) - When this is `true`, this rule warns shorter type conversions for `number` type.
- `"string"` (`true` by default) - When this is `true`, this rule warns shorter type conversions for `string` type.
- `"disallowTemplateString"` (`false` by default) - When this is `true`, this rule warns shorter type conversions using template strings.
- `"allow"` (`empty` by default) - Each entry in this array can be one of `~`, `!!`, `+` or `*` that are to be allowed.

Note that operator `+` in `allow` list would allow `+foo` (number coercion) as well as `"" + foo` (string coercion).

Expand Down Expand Up @@ -106,6 +107,40 @@ var s = String(foo);
foo = String(foo);
```

### disallowTemplateString
remcohaszing marked this conversation as resolved.
Show resolved Hide resolved

This option is **not** affected by the `string` option.

Examples of **incorrect** code for the `{ "disallowTemplateString": true }` option:

```js
/*eslint no-implicit-coercion: ["error", { "disallowTemplateString": true }]*/

var s = `${foo}`;
```

Examples of **correct** code for the `{ "disallowTemplateString": true }` option:

```js
/*eslint no-implicit-coercion: ["error", { "disallowTemplateString": true }]*/

var s = String(foo);

var s = `a${foo}`;

var s = `${foo}b`;

var s = `${foo}${bar}`;
```
remcohaszing marked this conversation as resolved.
Show resolved Hide resolved

remcohaszing marked this conversation as resolved.
Show resolved Hide resolved
Examples of **correct** code for the default `{ "disallowTemplateString": false }` option:

```js
/*eslint no-implicit-coercion: ["error", { "disallowTemplateString": false }]*/

var s = `${foo}`;
```

### allow

Using `allow` list, we can override and allow specific operators.
Expand Down
37 changes: 37 additions & 0 deletions lib/rules/no-implicit-coercion.js
Expand Up @@ -24,6 +24,7 @@ function parseOptions(options) {
boolean: "boolean" in options ? options.boolean : true,
number: "number" in options ? options.number : true,
string: "string" in options ? options.string : true,
disallowTemplateShorthand: "disallowTemplateShorthand" in options ? options.disallowTemplateShorthand : false,
allow: options.allow || []
};
}
Expand Down Expand Up @@ -180,6 +181,10 @@ module.exports = {
type: "boolean",
default: true
},
disallowTemplateShorthand: {
type: "boolean",
default: false
},
allow: {
type: "array",
items: {
Expand Down Expand Up @@ -299,6 +304,38 @@ module.exports = {

report(node, recommendation, true);
}
},

TemplateLiteral(node) {
if (!options.disallowTemplateShorthand) {
return;
}

// tag`${foo}`
if (node.parent.type === "TaggedTemplateExpression") {
return;
}

// `` or `${foo}${bar}`
if (node.expressions.length !== 1) {
return;
}


// `prefix${foo}`
if (node.quasis[0].value.cooked !== "") {
return;
}

// `${foo}postfix`
if (node.quasis[1].value.cooked !== "") {
return;
}

const code = sourceCode.getText(node.expressions[0]);
const recommendation = `String(${code})`;

report(node, recommendation, true);
remcohaszing marked this conversation as resolved.
Show resolved Hide resolved
}
};
}
Expand Down
40 changes: 40 additions & 0 deletions tests/lib/rules/no-implicit-coercion.js
Expand Up @@ -88,6 +88,13 @@ ruleTester.run("no-implicit-coercion", rule, {
{ code: "`${foo}` + ''", parserOptions: { ecmaVersion: 6 } },
"foo += 'bar'",
{ code: "foo += `${bar}`", parserOptions: { ecmaVersion: 6 } },
{ code: "`a${foo}`", options: [{ disallowTemplateShorthand: true }], parserOptions: { ecmaVersion: 6 } },
{ code: "`${foo}b`", options: [{ disallowTemplateShorthand: true }], parserOptions: { ecmaVersion: 6 } },
{ code: "`${foo}${bar}`", options: [{ disallowTemplateShorthand: true }], parserOptions: { ecmaVersion: 6 } },
{ code: "tag`${foo}`", options: [{ disallowTemplateShorthand: true }], parserOptions: { ecmaVersion: 6 } },
{ code: "`${foo}`", parserOptions: { ecmaVersion: 6 } },
{ code: "`${foo}`", options: [{ }], parserOptions: { ecmaVersion: 6 } },
{ code: "`${foo}`", options: [{ disallowTemplateShorthand: false }], parserOptions: { ecmaVersion: 6 } },
"+42"
],
invalid: [
Expand Down Expand Up @@ -248,6 +255,39 @@ ruleTester.run("no-implicit-coercion", rule, {
type: "BinaryExpression"
}]
},
{
code: "`${foo}`",
output: "String(foo)",
options: [{ disallowTemplateShorthand: true }],
parserOptions: { ecmaVersion: 6 },
errors: [{
messageId: "useRecommendation",
data: { recommendation: "String(foo)" },
type: "TemplateLiteral"
}]
},
{
code: "`\\\n${foo}`",
output: "String(foo)",
options: [{ disallowTemplateShorthand: true }],
parserOptions: { ecmaVersion: 6 },
errors: [{
messageId: "useRecommendation",
data: { recommendation: "String(foo)" },
type: "TemplateLiteral"
}]
},
{
code: "`${foo}\\\n`",
output: "String(foo)",
options: [{ disallowTemplateShorthand: true }],
parserOptions: { ecmaVersion: 6 },
errors: [{
messageId: "useRecommendation",
data: { recommendation: "String(foo)" },
type: "TemplateLiteral"
}]
},
remcohaszing marked this conversation as resolved.
Show resolved Hide resolved
{
code: "foo += \"\"",
output: "foo = String(foo)",
Expand Down