Skip to content

Commit

Permalink
Update: Add disallowTemplateShorthand option in no-implicit-coercion (#…
Browse files Browse the repository at this point in the history
…13579)

* Update: Add templateString option in no-implicit-coercion (fixes #12866)

This adds the `templateString` option to `no-implicit-coercion`. This makes the
rule report the following code:

```js
`${foo}`
```

For backwards compatibility, this was added as a separate option instead of as
default behaviour.

* Fix no-implicit-coercion templateString examples

* Skip tagged template strings in no-implicit-coercion

* Add missing tests for no-implicit-coercion

* Used cooked template string values

* Add missing documentation for no-implicit-coercion

Note that the `templateString` option isn’t affected by the `string` option.

* Add missing tests for no-implicit-coercion templateString

* Rename templateString to disallowTemplateString

* Fix typo in no-implicit-coercion docs

* Add tagged template string example for no-implicit-coercion

* Update docs/rules/no-implicit-coercion.md

Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com>

Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com>
  • Loading branch information
remcohaszing and mdjermanovic committed Apr 9, 2021
1 parent 71a80e3 commit f06ecdf
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 4 deletions.
45 changes: 41 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.
- `"disallowTemplateShorthand"` (`false` by default) - When this is `true`, this rule warns `string` type conversions using `${expression}` form.
- `"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,42 @@ var s = String(foo);
foo = String(foo);
```

### disallowTemplateShorthand

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

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

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

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

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

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

var s = String(foo);

var s = `a${foo}`;

var s = `${foo}b`;

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

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

Examples of **correct** code for the default `{ "disallowTemplateShorthand": false }` option:

```js
/*eslint no-implicit-coercion: ["error", { "disallowTemplateShorthand": 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);
}
};
}
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"
}]
},
{
code: "foo += \"\"",
output: "foo = String(foo)",
Expand Down

0 comments on commit f06ecdf

Please sign in to comment.