diff --git a/docs/rules/prefer-string-slice.md b/docs/rules/prefer-string-slice.md new file mode 100644 index 0000000000..b49eb51ab7 --- /dev/null +++ b/docs/rules/prefer-string-slice.md @@ -0,0 +1,18 @@ +# Prefer the use of `String#slice()` instead of `String#substr()` or `String#substring()` + +Prefer a convention of using [`String#slice()`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/slice) instead of [`String#substr()`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/substr) or [`String#substring()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring). `String#slice()` has clearer behavior and has a counterpart with arrays. It is also better to be consistent. Anything that can be done with `String#substr()` or `String#substring()` can be done with `String#slice()`. + +Read more in [this Stack Overflow question](http://stackoverflow.com/questions/2243824/what-is-the-difference-between-string-slice-and-string-substring) + +## Fail + +```js +const foo = bar.substr(1, 2); +const baz = quux.substring(1, 3); +``` + +## Pass + +```js +const foo = bar.slice(1, 3); +``` diff --git a/index.js b/index.js index 5b6186e9e1..f243f0c02c 100644 --- a/index.js +++ b/index.js @@ -22,7 +22,8 @@ module.exports = { 'unicorn/number-literal-case': 'error', 'unicorn/no-array-instanceof': 'error', 'unicorn/no-new-buffer': 'error', - 'unicorn/no-hex-escape': 'error' + 'unicorn/no-hex-escape': 'error', + 'unicorn/prefer-string-slice': 'error' } } } diff --git a/readme.md b/readme.md index cd3b97c41e..e4c0cb5934 100644 --- a/readme.md +++ b/readme.md @@ -42,7 +42,8 @@ Configure it in `package.json`. "unicorn/number-literal-case": "error", "unicorn/no-array-instanceof": "error", "unicorn/no-new-buffer": "error", - "unicorn/no-hex-escape": "error" + "unicorn/no-hex-escape": "error", + "unicorn/prefer-string-slice": "error" } } } @@ -61,6 +62,7 @@ Configure it in `package.json`. - [no-array-instanceof](docs/rules/no-array-instanceof.md) - Require `Array.isArray()` instead of `instanceof Array`. *(fixable)* - [no-new-buffer](docs/rules/no-new-buffer.md) - Enforce the use of `Buffer.from()` and `Buffer.alloc()` instead of the deprecated `new Buffer()`. *(fixable)* - [no-hex-escape](docs/rules/no-hex-escape.md) - Enforce the use of unicode escapes instead of hexadecimal escapes. *(fixable)* +- [prefer-string-slice](docs/rules/prefer-string-slice) - Prefer the use of `String#slice()` instead of `String#substr()` or `String#substring()` ## Recommended config diff --git a/rules/prefer-string-slice.js b/rules/prefer-string-slice.js new file mode 100644 index 0000000000..d7281ff3d8 --- /dev/null +++ b/rules/prefer-string-slice.js @@ -0,0 +1,18 @@ +'use strict'; + +const create = context => { + return { + Identifier: node => { + if (['substr', 'substring'].indexOf(node.name) !== -1) { + context.report({ + node, + message: `Use \`String#slice\` instead of \`String#${node.name}\`.` + }); + } + } + }; +}; + +module.exports = { + create +}; diff --git a/test/prefer-string-slice.js b/test/prefer-string-slice.js new file mode 100644 index 0000000000..39631f0e96 --- /dev/null +++ b/test/prefer-string-slice.js @@ -0,0 +1,56 @@ +import test from 'ava'; +import avaRuleTester from 'eslint-ava-rule-tester'; +import rule from '../rules/prefer-string-slice'; + +const ruleTester = avaRuleTester(test, { + env: { + es6: true + } +}); + +const error = name => ({ + ruleId: 'prefer-string-slice', + message: `Use \`String#slice\` instead of \`String#${name}\`.` +}); + +ruleTester.run('prefer-string-slice', rule, { + valid: [ + 'const foo = bar.slice(1)', + `const foo = bar.slice(baz, 2);`, + `const foo = bar.slice(baz - 1, 2);` + ], + invalid: [ + { + code: 'const foo = bar.substr(1)', + errors: [error('substr')] + }, + { + code: 'const foo = bar.substr(1,2)', + errors: [error('substr')] + }, + { + code: `const foo = bar.substr(baz, 2);`, + errors: [error('substr')] + }, + { + code: `const foo = bar.substr(baz - 1, 2);`, + errors: [error('substr')] + }, + { + code: 'const foo = bar.substring(1)', + errors: [error('substring')] + }, + { + code: 'const foo = bar.substring(1,2)', + errors: [error('substring')] + }, + { + code: `const foo = bar.substring(baz, 2);`, + errors: [error('substring')] + }, + { + code: `const foo = bar.substring(baz - 1, 2);`, + errors: [error('substring')] + } + ] +});