diff --git a/docs/rules/prefer-regexp-test.md b/docs/rules/prefer-regexp-test.md index 06096169b8..ca857ab78a 100644 --- a/docs/rules/prefer-regexp-test.md +++ b/docs/rules/prefer-regexp-test.md @@ -2,7 +2,7 @@ ✅ This rule is enabled in the `recommended` [config](https://github.com/sindresorhus/eslint-plugin-unicorn#preset-configs). -🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix). +🔧💡 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) and manually fixable by [editor suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions). diff --git a/readme.md b/readme.md index faa635af74..247137dc0a 100644 --- a/readme.md +++ b/readme.md @@ -137,7 +137,7 @@ Use a [preset config](#preset-configs) or configure each rules in `package.json` | [prefer-prototype-methods](docs/rules/prefer-prototype-methods.md) | Prefer borrowing methods from the prototype instead of the instance. | ✅ | 🔧 | | | [prefer-query-selector](docs/rules/prefer-query-selector.md) | Prefer `.querySelector()` over `.getElementById()`, `.querySelectorAll()` over `.getElementsByClassName()` and `.getElementsByTagName()`. | ✅ | 🔧 | | | [prefer-reflect-apply](docs/rules/prefer-reflect-apply.md) | Prefer `Reflect.apply()` over `Function#apply()`. | ✅ | 🔧 | | -| [prefer-regexp-test](docs/rules/prefer-regexp-test.md) | Prefer `RegExp#test()` over `String#match()` and `RegExp#exec()`. | ✅ | 🔧 | | +| [prefer-regexp-test](docs/rules/prefer-regexp-test.md) | Prefer `RegExp#test()` over `String#match()` and `RegExp#exec()`. | ✅ | 🔧 | 💡 | | [prefer-set-has](docs/rules/prefer-set-has.md) | Prefer `Set#has()` over `Array#includes()` when checking for existence or non-existence. | ✅ | 🔧 | 💡 | | [prefer-spread](docs/rules/prefer-spread.md) | Prefer the spread operator over `Array.from(…)`, `Array#concat(…)`, `Array#slice()` and `String#split('')`. | ✅ | 🔧 | 💡 | | [prefer-string-replace-all](docs/rules/prefer-string-replace-all.md) | Prefer `String#replaceAll()` over regex searches with the global flag. | | 🔧 | | diff --git a/rules/prefer-regexp-test.js b/rules/prefer-regexp-test.js index 68164485df..5a2e1ebd00 100644 --- a/rules/prefer-regexp-test.js +++ b/rules/prefer-regexp-test.js @@ -8,9 +8,11 @@ const shouldAddParenthesesToMemberExpressionObject = require('./utils/should-add const REGEXP_EXEC = 'regexp-exec'; const STRING_MATCH = 'string-match'; +const SUGGESTION = 'suggestion'; const messages = { [REGEXP_EXEC]: 'Prefer `.test(…)` over `.exec(…)`.', [STRING_MATCH]: 'Prefer `RegExp#test(…)` over `String#match(…)`.', + [SUGGESTION]: 'Switch to `RegExp#test(…)`.', }; const cases = [ @@ -75,6 +77,21 @@ const isRegExpNode = node => && node.callee.name === 'RegExp' ); +const isRegExpWithoutGFlag = (node, scope) => { + const staticResult = getStaticValue(node, scope); + + // Don't know if there is `g` flag + if (!staticResult) { + return false; + } + + const {value} = staticResult; + return ( + Object.prototype.toString.call(value) === '[object RegExp]' + && !value.flags.includes('g') + ); +}; + /** @param {import('eslint').Rule.RuleContext} context */ const create = context => Object.fromEntries( cases.map(checkCase => [ @@ -97,20 +114,22 @@ const create = context => Object.fromEntries( messageId: type, }; - if (!isRegExpNode(regexpNode)) { - const staticResult = getStaticValue(regexpNode, context.getScope()); - if (staticResult) { - const {value} = staticResult; - if ( - Object.prototype.toString.call(value) !== '[object RegExp]' - || value.flags.includes('g') - ) { - return problem; - } - } + const fixFunction = fixer => fix(fixer, nodes, context.getSourceCode()); + + if ( + isRegExpNode(regexpNode) + || isRegExpWithoutGFlag(regexpNode, context.getScope()) + ) { + problem.fix = fixFunction; + } else { + problem.suggest = [ + { + messageId: SUGGESTION, + fix: fixFunction, + }, + ]; } - problem.fix = fixer => fix(fixer, nodes, context.getSourceCode()); return problem; }, ]), @@ -125,6 +144,7 @@ module.exports = { description: 'Prefer `RegExp#test()` over `String#match()` and `RegExp#exec()`.', }, fixable: 'code', + hasSuggestions: true, messages, }, }; diff --git a/test/prefer-regexp-test.mjs b/test/prefer-regexp-test.mjs index c6a53fab6a..66c73d167e 100644 --- a/test/prefer-regexp-test.mjs +++ b/test/prefer-regexp-test.mjs @@ -3,7 +3,7 @@ import {getTester} from './utils/test.mjs'; const {test} = getTester(import.meta); -test({ +test.snapshot({ valid: [ 'const bar = !re.test(foo)', // Not `boolean` @@ -41,38 +41,33 @@ test({ 'if (foo.match(1n)) {}', 'if (foo.match(true)) {}', ], - invalid: [], -}); - -test.snapshot({ - valid: [], invalid: [ // `String#match()` - 'const bar = !foo.match(re)', - 'const bar = Boolean(foo.match(re))', - 'if (foo.match(re)) {}', - 'const bar = foo.match(re) ? 1 : 2', - 'while (foo.match(re)) foo = foo.slice(1);', - 'do {foo = foo.slice(1)} while (foo.match(re));', - 'for (; foo.match(re); ) foo = foo.slice(1);', + 'const re = /a/; const bar = !foo.match(re)', + 'const re = /a/; const bar = Boolean(foo.match(re))', + 'const re = /a/; if (foo.match(re)) {}', + 'const re = /a/; const bar = foo.match(re) ? 1 : 2', + 'const re = /a/; while (foo.match(re)) foo = foo.slice(1);', + 'const re = /a/; do {foo = foo.slice(1)} while (foo.match(re));', + 'const re = /a/; for (; foo.match(re); ) foo = foo.slice(1);', // `RegExp#exec()` - 'const bar = !re.exec(foo)', - 'const bar = Boolean(re.exec(foo))', - 'if (re.exec(foo)) {}', - 'const bar = re.exec(foo) ? 1 : 2', - 'while (re.exec(foo)) foo = foo.slice(1);', - 'do {foo = foo.slice(1)} while (re.exec(foo));', - 'for (; re.exec(foo); ) foo = foo.slice(1);', + 'const re = /a/; const bar = !re.exec(foo)', + 'const re = /a/; const bar = Boolean(re.exec(foo))', + 'const re = /a/; if (re.exec(foo)) {}', + 'const re = /a/; const bar = re.exec(foo) ? 1 : 2', + 'const re = /a/; while (re.exec(foo)) foo = foo.slice(1);', + 'const re = /a/; do {foo = foo.slice(1)} while (re.exec(foo));', + 'const re = /a/; for (; re.exec(foo); ) foo = foo.slice(1);', // Parentheses - 'if ((0, foo).match(re)) {}', - 'if ((0, foo).match((re))) {}', - 'if ((foo).match(re)) {}', - 'if ((foo).match((re))) {}', + 'const re = /a/; if ((0, foo).match(re)) {}', + 'const re = /a/; if ((0, foo).match((re))) {}', + 'const re = /a/; if ((foo).match(re)) {}', + 'const re = /a/; if ((foo).match((re))) {}', 'if (foo.match(/re/)) {}', - 'if (foo.match(bar)) {}', - 'if (foo.match(bar.baz)) {}', + 'const re = /a/; if (foo.match(re)) {}', + 'const bar = {bar: /a/}; if (foo.match(bar.baz)) {}', 'if (foo.match(bar.baz())) {}', 'if (foo.match(new RegExp("re", "g"))) {}', 'if (foo.match(new SomeRegExp())) {}', @@ -89,14 +84,14 @@ test.snapshot({ 'if ((foo).match(new SomeRegExp)) {}', 'if ((foo).match(bar?.baz)) {}', 'if ((foo).match(bar?.baz())) {}', - 'if ((foo).match(bar || baz)) {}', + 'const bar = false; const baz = /a/; if ((foo).match(bar || baz)) {}', outdent` async function a() { if ((foo).match(await bar())) {} } `, // Should not need handle ASI problem - 'if (foo.match([re][0])) {}', + 'const re = [/a/]; if (foo.match([re][0])) {}', // Comments outdent` @@ -151,6 +146,10 @@ test.snapshot({ const regex = /weird/gyi; if (regex.exec(foo)); `, + outdent` + let re = new RegExp('foo', 'g'); + if(str.match(re)); + `, ], }); diff --git a/test/snapshots/prefer-regexp-test.mjs.md b/test/snapshots/prefer-regexp-test.mjs.md index 48766edb47..4838a18635 100644 --- a/test/snapshots/prefer-regexp-test.mjs.md +++ b/test/snapshots/prefer-regexp-test.mjs.md @@ -5,291 +5,291 @@ The actual snapshot is saved in `prefer-regexp-test.mjs.snap`. Generated by [AVA](https://avajs.dev). ## Invalid #1 - 1 | const bar = !foo.match(re) + 1 | const re = /a/; const bar = !foo.match(re) > Output `␊ - 1 | const bar = !re.test(foo)␊ + 1 | const re = /a/; const bar = !re.test(foo)␊ ` > Error 1/1 `␊ - > 1 | const bar = !foo.match(re)␊ - | ^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + > 1 | const re = /a/; const bar = !foo.match(re)␊ + | ^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ ` ## Invalid #2 - 1 | const bar = Boolean(foo.match(re)) + 1 | const re = /a/; const bar = Boolean(foo.match(re)) > Output `␊ - 1 | const bar = Boolean(re.test(foo))␊ + 1 | const re = /a/; const bar = Boolean(re.test(foo))␊ ` > Error 1/1 `␊ - > 1 | const bar = Boolean(foo.match(re))␊ - | ^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + > 1 | const re = /a/; const bar = Boolean(foo.match(re))␊ + | ^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ ` ## Invalid #3 - 1 | if (foo.match(re)) {} + 1 | const re = /a/; if (foo.match(re)) {} > Output `␊ - 1 | if (re.test(foo)) {}␊ + 1 | const re = /a/; if (re.test(foo)) {}␊ ` > Error 1/1 `␊ - > 1 | if (foo.match(re)) {}␊ - | ^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + > 1 | const re = /a/; if (foo.match(re)) {}␊ + | ^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ ` ## Invalid #4 - 1 | const bar = foo.match(re) ? 1 : 2 + 1 | const re = /a/; const bar = foo.match(re) ? 1 : 2 > Output `␊ - 1 | const bar = re.test(foo) ? 1 : 2␊ + 1 | const re = /a/; const bar = re.test(foo) ? 1 : 2␊ ` > Error 1/1 `␊ - > 1 | const bar = foo.match(re) ? 1 : 2␊ - | ^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + > 1 | const re = /a/; const bar = foo.match(re) ? 1 : 2␊ + | ^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ ` ## Invalid #5 - 1 | while (foo.match(re)) foo = foo.slice(1); + 1 | const re = /a/; while (foo.match(re)) foo = foo.slice(1); > Output `␊ - 1 | while (re.test(foo)) foo = foo.slice(1);␊ + 1 | const re = /a/; while (re.test(foo)) foo = foo.slice(1);␊ ` > Error 1/1 `␊ - > 1 | while (foo.match(re)) foo = foo.slice(1);␊ - | ^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + > 1 | const re = /a/; while (foo.match(re)) foo = foo.slice(1);␊ + | ^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ ` ## Invalid #6 - 1 | do {foo = foo.slice(1)} while (foo.match(re)); + 1 | const re = /a/; do {foo = foo.slice(1)} while (foo.match(re)); > Output `␊ - 1 | do {foo = foo.slice(1)} while (re.test(foo));␊ + 1 | const re = /a/; do {foo = foo.slice(1)} while (re.test(foo));␊ ` > Error 1/1 `␊ - > 1 | do {foo = foo.slice(1)} while (foo.match(re));␊ - | ^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + > 1 | const re = /a/; do {foo = foo.slice(1)} while (foo.match(re));␊ + | ^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ ` ## Invalid #7 - 1 | for (; foo.match(re); ) foo = foo.slice(1); + 1 | const re = /a/; for (; foo.match(re); ) foo = foo.slice(1); > Output `␊ - 1 | for (; re.test(foo); ) foo = foo.slice(1);␊ + 1 | const re = /a/; for (; re.test(foo); ) foo = foo.slice(1);␊ ` > Error 1/1 `␊ - > 1 | for (; foo.match(re); ) foo = foo.slice(1);␊ - | ^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + > 1 | const re = /a/; for (; foo.match(re); ) foo = foo.slice(1);␊ + | ^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ ` ## Invalid #8 - 1 | const bar = !re.exec(foo) + 1 | const re = /a/; const bar = !re.exec(foo) > Output `␊ - 1 | const bar = !re.test(foo)␊ + 1 | const re = /a/; const bar = !re.test(foo)␊ ` > Error 1/1 `␊ - > 1 | const bar = !re.exec(foo)␊ - | ^^^^ Prefer \`.test(…)\` over \`.exec(…)\`.␊ + > 1 | const re = /a/; const bar = !re.exec(foo)␊ + | ^^^^ Prefer \`.test(…)\` over \`.exec(…)\`.␊ ` ## Invalid #9 - 1 | const bar = Boolean(re.exec(foo)) + 1 | const re = /a/; const bar = Boolean(re.exec(foo)) > Output `␊ - 1 | const bar = Boolean(re.test(foo))␊ + 1 | const re = /a/; const bar = Boolean(re.test(foo))␊ ` > Error 1/1 `␊ - > 1 | const bar = Boolean(re.exec(foo))␊ - | ^^^^ Prefer \`.test(…)\` over \`.exec(…)\`.␊ + > 1 | const re = /a/; const bar = Boolean(re.exec(foo))␊ + | ^^^^ Prefer \`.test(…)\` over \`.exec(…)\`.␊ ` ## Invalid #10 - 1 | if (re.exec(foo)) {} + 1 | const re = /a/; if (re.exec(foo)) {} > Output `␊ - 1 | if (re.test(foo)) {}␊ + 1 | const re = /a/; if (re.test(foo)) {}␊ ` > Error 1/1 `␊ - > 1 | if (re.exec(foo)) {}␊ - | ^^^^ Prefer \`.test(…)\` over \`.exec(…)\`.␊ + > 1 | const re = /a/; if (re.exec(foo)) {}␊ + | ^^^^ Prefer \`.test(…)\` over \`.exec(…)\`.␊ ` ## Invalid #11 - 1 | const bar = re.exec(foo) ? 1 : 2 + 1 | const re = /a/; const bar = re.exec(foo) ? 1 : 2 > Output `␊ - 1 | const bar = re.test(foo) ? 1 : 2␊ + 1 | const re = /a/; const bar = re.test(foo) ? 1 : 2␊ ` > Error 1/1 `␊ - > 1 | const bar = re.exec(foo) ? 1 : 2␊ - | ^^^^ Prefer \`.test(…)\` over \`.exec(…)\`.␊ + > 1 | const re = /a/; const bar = re.exec(foo) ? 1 : 2␊ + | ^^^^ Prefer \`.test(…)\` over \`.exec(…)\`.␊ ` ## Invalid #12 - 1 | while (re.exec(foo)) foo = foo.slice(1); + 1 | const re = /a/; while (re.exec(foo)) foo = foo.slice(1); > Output `␊ - 1 | while (re.test(foo)) foo = foo.slice(1);␊ + 1 | const re = /a/; while (re.test(foo)) foo = foo.slice(1);␊ ` > Error 1/1 `␊ - > 1 | while (re.exec(foo)) foo = foo.slice(1);␊ - | ^^^^ Prefer \`.test(…)\` over \`.exec(…)\`.␊ + > 1 | const re = /a/; while (re.exec(foo)) foo = foo.slice(1);␊ + | ^^^^ Prefer \`.test(…)\` over \`.exec(…)\`.␊ ` ## Invalid #13 - 1 | do {foo = foo.slice(1)} while (re.exec(foo)); + 1 | const re = /a/; do {foo = foo.slice(1)} while (re.exec(foo)); > Output `␊ - 1 | do {foo = foo.slice(1)} while (re.test(foo));␊ + 1 | const re = /a/; do {foo = foo.slice(1)} while (re.test(foo));␊ ` > Error 1/1 `␊ - > 1 | do {foo = foo.slice(1)} while (re.exec(foo));␊ - | ^^^^ Prefer \`.test(…)\` over \`.exec(…)\`.␊ + > 1 | const re = /a/; do {foo = foo.slice(1)} while (re.exec(foo));␊ + | ^^^^ Prefer \`.test(…)\` over \`.exec(…)\`.␊ ` ## Invalid #14 - 1 | for (; re.exec(foo); ) foo = foo.slice(1); + 1 | const re = /a/; for (; re.exec(foo); ) foo = foo.slice(1); > Output `␊ - 1 | for (; re.test(foo); ) foo = foo.slice(1);␊ + 1 | const re = /a/; for (; re.test(foo); ) foo = foo.slice(1);␊ ` > Error 1/1 `␊ - > 1 | for (; re.exec(foo); ) foo = foo.slice(1);␊ - | ^^^^ Prefer \`.test(…)\` over \`.exec(…)\`.␊ + > 1 | const re = /a/; for (; re.exec(foo); ) foo = foo.slice(1);␊ + | ^^^^ Prefer \`.test(…)\` over \`.exec(…)\`.␊ ` ## Invalid #15 - 1 | if ((0, foo).match(re)) {} + 1 | const re = /a/; if ((0, foo).match(re)) {} > Output `␊ - 1 | if ((re).test((0, foo))) {}␊ + 1 | const re = /a/; if ((re).test((0, foo))) {}␊ ` > Error 1/1 `␊ - > 1 | if ((0, foo).match(re)) {}␊ - | ^^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + > 1 | const re = /a/; if ((0, foo).match(re)) {}␊ + | ^^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ ` ## Invalid #16 - 1 | if ((0, foo).match((re))) {} + 1 | const re = /a/; if ((0, foo).match((re))) {} > Output `␊ - 1 | if ((re).test((0, foo))) {}␊ + 1 | const re = /a/; if ((re).test((0, foo))) {}␊ ` > Error 1/1 `␊ - > 1 | if ((0, foo).match((re))) {}␊ - | ^^^^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + > 1 | const re = /a/; if ((0, foo).match((re))) {}␊ + | ^^^^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ ` ## Invalid #17 - 1 | if ((foo).match(re)) {} + 1 | const re = /a/; if ((foo).match(re)) {} > Output `␊ - 1 | if ((re).test(foo)) {}␊ + 1 | const re = /a/; if ((re).test(foo)) {}␊ ` > Error 1/1 `␊ - > 1 | if ((foo).match(re)) {}␊ - | ^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + > 1 | const re = /a/; if ((foo).match(re)) {}␊ + | ^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ ` ## Invalid #18 - 1 | if ((foo).match((re))) {} + 1 | const re = /a/; if ((foo).match((re))) {} > Output `␊ - 1 | if ((re).test((foo))) {}␊ + 1 | const re = /a/; if ((re).test((foo))) {}␊ ` > Error 1/1 `␊ - > 1 | if ((foo).match((re))) {}␊ - | ^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + > 1 | const re = /a/; if ((foo).match((re))) {}␊ + | ^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ ` ## Invalid #19 @@ -309,51 +309,47 @@ Generated by [AVA](https://avajs.dev). ` ## Invalid #20 - 1 | if (foo.match(bar)) {} + 1 | const re = /a/; if (foo.match(re)) {} > Output `␊ - 1 | if (bar.test(foo)) {}␊ + 1 | const re = /a/; if (re.test(foo)) {}␊ ` > Error 1/1 `␊ - > 1 | if (foo.match(bar)) {}␊ - | ^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + > 1 | const re = /a/; if (foo.match(re)) {}␊ + | ^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ ` ## Invalid #21 - 1 | if (foo.match(bar.baz)) {} - -> Output - - `␊ - 1 | if (bar.baz.test(foo)) {}␊ - ` + 1 | const bar = {bar: /a/}; if (foo.match(bar.baz)) {} > Error 1/1 `␊ - > 1 | if (foo.match(bar.baz)) {}␊ - | ^^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + > 1 | const bar = {bar: /a/}; if (foo.match(bar.baz)) {}␊ + | ^^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`RegExp#test(…)\`.␊ + 1 | const bar = {bar: /a/}; if (bar.baz.test(foo)) {}␊ ` ## Invalid #22 1 | if (foo.match(bar.baz())) {} -> Output - - `␊ - 1 | if (bar.baz().test(foo)) {}␊ - ` - > Error 1/1 `␊ > 1 | if (foo.match(bar.baz())) {}␊ | ^^^^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`RegExp#test(…)\`.␊ + 1 | if (bar.baz().test(foo)) {}␊ ` ## Invalid #23 @@ -375,81 +371,71 @@ Generated by [AVA](https://avajs.dev). ## Invalid #24 1 | if (foo.match(new SomeRegExp())) {} -> Output - - `␊ - 1 | if (new SomeRegExp().test(foo)) {}␊ - ` - > Error 1/1 `␊ > 1 | if (foo.match(new SomeRegExp())) {}␊ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`RegExp#test(…)\`.␊ + 1 | if (new SomeRegExp().test(foo)) {}␊ ` ## Invalid #25 1 | if (foo.match(new SomeRegExp)) {} -> Output - - `␊ - 1 | if ((new SomeRegExp).test(foo)) {}␊ - ` - > Error 1/1 `␊ > 1 | if (foo.match(new SomeRegExp)) {}␊ | ^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`RegExp#test(…)\`.␊ + 1 | if ((new SomeRegExp).test(foo)) {}␊ ` ## Invalid #26 1 | if (foo.match(bar?.baz)) {} -> Output - - `␊ - 1 | if (bar?.baz.test(foo)) {}␊ - ` - > Error 1/1 `␊ > 1 | if (foo.match(bar?.baz)) {}␊ | ^^^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`RegExp#test(…)\`.␊ + 1 | if (bar?.baz.test(foo)) {}␊ ` ## Invalid #27 1 | if (foo.match(bar?.baz())) {} -> Output - - `␊ - 1 | if (bar?.baz().test(foo)) {}␊ - ` - > Error 1/1 `␊ > 1 | if (foo.match(bar?.baz())) {}␊ | ^^^^^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`RegExp#test(…)\`.␊ + 1 | if (bar?.baz().test(foo)) {}␊ ` ## Invalid #28 1 | if (foo.match(bar || baz)) {} -> Output - - `␊ - 1 | if ((bar || baz).test(foo)) {}␊ - ` - > Error 1/1 `␊ > 1 | if (foo.match(bar || baz)) {}␊ | ^^^^^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`RegExp#test(…)\`.␊ + 1 | if ((bar || baz).test(foo)) {}␊ ` ## Invalid #29 @@ -457,14 +443,6 @@ Generated by [AVA](https://avajs.dev). 2 | if (foo.match(await bar())) {} 3 | } -> Output - - `␊ - 1 | async function a() {␊ - 2 | if ((await bar()).test(foo)) {}␊ - 3 | }␊ - ` - > Error 1/1 `␊ @@ -472,6 +450,12 @@ Generated by [AVA](https://avajs.dev). > 2 | if (foo.match(await bar())) {}␊ | ^^^^^^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ 3 | }␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`RegExp#test(…)\`.␊ + 1 | async function a() {␊ + 2 | if ((await bar()).test(foo)) {}␊ + 3 | }␊ ` ## Invalid #30 @@ -493,65 +477,59 @@ Generated by [AVA](https://avajs.dev). ## Invalid #31 1 | if ((foo).match(new SomeRegExp)) {} -> Output - - `␊ - 1 | if ((new SomeRegExp).test(foo)) {}␊ - ` - > Error 1/1 `␊ > 1 | if ((foo).match(new SomeRegExp)) {}␊ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`RegExp#test(…)\`.␊ + 1 | if ((new SomeRegExp).test(foo)) {}␊ ` ## Invalid #32 1 | if ((foo).match(bar?.baz)) {} -> Output - - `␊ - 1 | if ((bar?.baz).test(foo)) {}␊ - ` - > Error 1/1 `␊ > 1 | if ((foo).match(bar?.baz)) {}␊ | ^^^^^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`RegExp#test(…)\`.␊ + 1 | if ((bar?.baz).test(foo)) {}␊ ` ## Invalid #33 1 | if ((foo).match(bar?.baz())) {} -> Output - - `␊ - 1 | if ((bar?.baz()).test(foo)) {}␊ - ` - > Error 1/1 `␊ > 1 | if ((foo).match(bar?.baz())) {}␊ | ^^^^^^^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`RegExp#test(…)\`.␊ + 1 | if ((bar?.baz()).test(foo)) {}␊ ` ## Invalid #34 - 1 | if ((foo).match(bar || baz)) {} + 1 | const bar = false; const baz = /a/; if ((foo).match(bar || baz)) {} > Output `␊ - 1 | if ((bar || baz).test(foo)) {}␊ + 1 | const bar = false; const baz = /a/; if ((bar || baz).test(foo)) {}␊ ` > Error 1/1 `␊ - > 1 | if ((foo).match(bar || baz)) {}␊ - | ^^^^^^^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + > 1 | const bar = false; const baz = /a/; if ((foo).match(bar || baz)) {}␊ + | ^^^^^^^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ ` ## Invalid #35 @@ -559,14 +537,6 @@ Generated by [AVA](https://avajs.dev). 2 | if ((foo).match(await bar())) {} 3 | } -> Output - - `␊ - 1 | async function a() {␊ - 2 | if ((await bar()).test(foo)) {}␊ - 3 | }␊ - ` - > Error 1/1 `␊ @@ -574,22 +544,26 @@ Generated by [AVA](https://avajs.dev). > 2 | if ((foo).match(await bar())) {}␊ | ^^^^^^^^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ 3 | }␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`RegExp#test(…)\`.␊ + 1 | async function a() {␊ + 2 | if ((await bar()).test(foo)) {}␊ + 3 | }␊ ` ## Invalid #36 - 1 | if (foo.match([re][0])) {} - -> Output - - `␊ - 1 | if ([re][0].test(foo)) {}␊ - ` + 1 | const re = [/a/]; if (foo.match([re][0])) {} > Error 1/1 `␊ - > 1 | if (foo.match([re][0])) {}␊ - | ^^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + > 1 | const re = [/a/]; if (foo.match([re][0])) {}␊ + | ^^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`RegExp#test(…)\`.␊ + 1 | const re = [/a/]; if ([re][0].test(foo)) {}␊ ` ## Invalid #37 @@ -604,21 +578,6 @@ Generated by [AVA](https://avajs.dev). 9 | ) {} 10 | } -> Output - - `␊ - 1 | async function a() {␊ - 2 | if (␊ - 3 | /* 1 */ (await /* 6 */ bar()) /* 2 */␊ - 4 | ./* 3 */ test /* 4 */ (␊ - 5 | /* 5 */ foo() /* 7 */␊ - 6 | ,␊ - 7 | /* 8 */␊ - 8 | )␊ - 9 | ) {}␊ - 10 | }␊ - ` - > Error 1/1 `␊ @@ -638,6 +597,19 @@ Generated by [AVA](https://avajs.dev). | ^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ 9 | ) {}␊ 10 | }␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`RegExp#test(…)\`.␊ + 1 | async function a() {␊ + 2 | if (␊ + 3 | /* 1 */ (await /* 6 */ bar()) /* 2 */␊ + 4 | ./* 3 */ test /* 4 */ (␊ + 5 | /* 5 */ foo() /* 7 */␊ + 6 | ,␊ + 7 | /* 8 */␊ + 8 | )␊ + 9 | ) {}␊ + 10 | }␊ ` ## Invalid #38 @@ -652,6 +624,12 @@ Generated by [AVA](https://avajs.dev). > 2 | if (foo.match(string)) {␊ | ^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ 3 | }␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`RegExp#test(…)\`.␊ + 1 | const string = '[.!?]\\s*$';␊ + 2 | if (string.test(foo)) {␊ + 3 | }␊ ` ## Invalid #39 @@ -676,17 +654,15 @@ Generated by [AVA](https://avajs.dev). ## Invalid #40 1 | if (foo.match(unknown)) {} -> Output - - `␊ - 1 | if (unknown.test(foo)) {}␊ - ` - > Error 1/1 `␊ > 1 | if (foo.match(unknown)) {}␊ | ^^^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`RegExp#test(…)\`.␊ + 1 | if (unknown.test(foo)) {}␊ ` ## Invalid #41 @@ -875,6 +851,11 @@ Generated by [AVA](https://avajs.dev). 1 | const regex = /weird/g;␊ > 2 | if (foo.match(regex));␊ | ^^^^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`RegExp#test(…)\`.␊ + 1 | const regex = /weird/g;␊ + 2 | if (regex.test(foo));␊ ` ## Invalid #53 @@ -887,6 +868,11 @@ Generated by [AVA](https://avajs.dev). 1 | const regex = /weird/g;␊ > 2 | if (regex.exec(foo));␊ | ^^^^ Prefer \`.test(…)\` over \`.exec(…)\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`RegExp#test(…)\`.␊ + 1 | const regex = /weird/g;␊ + 2 | if (regex.test(foo));␊ ` ## Invalid #54 @@ -918,4 +904,26 @@ Generated by [AVA](https://avajs.dev). 1 | const regex = /weird/gyi;␊ > 2 | if (regex.exec(foo));␊ | ^^^^ Prefer \`.test(…)\` over \`.exec(…)\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`RegExp#test(…)\`.␊ + 1 | const regex = /weird/gyi;␊ + 2 | if (regex.test(foo));␊ + ` + +## Invalid #56 + 1 | let re = new RegExp('foo', 'g'); + 2 | if(str.match(re)); + +> Error 1/1 + + `␊ + 1 | let re = new RegExp('foo', 'g');␊ + > 2 | if(str.match(re));␊ + | ^^^^^^^^^^^^^ Prefer \`RegExp#test(…)\` over \`String#match(…)\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`RegExp#test(…)\`.␊ + 1 | let re = new RegExp('foo', 'g');␊ + 2 | if(re.test(str));␊ ` diff --git a/test/snapshots/prefer-regexp-test.mjs.snap b/test/snapshots/prefer-regexp-test.mjs.snap index b29c719abe..dc06b67f28 100644 Binary files a/test/snapshots/prefer-regexp-test.mjs.snap and b/test/snapshots/prefer-regexp-test.mjs.snap differ