From 7b74b400041411768a8def03f125db97a20f0fb6 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 8 Jan 2021 18:30:47 +0800 Subject: [PATCH] Add `prefer-regexp-test` rule (#970) Co-authored-by: Sindre Sorhus --- docs/rules/prefer-regexp-test.md | 21 + index.js | 1 + readme.md | 2 + rules/prefer-regexp-test.js | 98 ++++ test/prefer-regexp-test.js | 110 ++++ test/snapshots/prefer-regexp-test.js.md | 641 ++++++++++++++++++++++ test/snapshots/prefer-regexp-test.js.snap | Bin 0 -> 2074 bytes 7 files changed, 873 insertions(+) create mode 100644 docs/rules/prefer-regexp-test.md create mode 100644 rules/prefer-regexp-test.js create mode 100644 test/prefer-regexp-test.js create mode 100644 test/snapshots/prefer-regexp-test.js.md create mode 100644 test/snapshots/prefer-regexp-test.js.snap diff --git a/docs/rules/prefer-regexp-test.md b/docs/rules/prefer-regexp-test.md new file mode 100644 index 0000000000..2b30edb94c --- /dev/null +++ b/docs/rules/prefer-regexp-test.md @@ -0,0 +1,21 @@ +# Prefer `RegExp#test()` over `String#match()` and `RegExp#exec()` + +When you want to know whether a pattern is found in a string, use [`RegExp#test()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test) instead of [`String#match()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match) and [`RegExp#exec()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec). + +This rule is fixable. + +## Fail + +```js +if (string.match(/unicorn/)) {} +``` + +```js +if (/unicorn/.exec(string)) {} +``` + +## Pass + +```js +if (/unicorn/.test(string)) {} +``` diff --git a/index.js b/index.js index cd36141653..07d1bd4de4 100644 --- a/index.js +++ b/index.js @@ -97,6 +97,7 @@ module.exports = { 'unicorn/prefer-optional-catch-binding': 'error', 'unicorn/prefer-query-selector': 'error', 'unicorn/prefer-reflect-apply': 'error', + 'unicorn/prefer-regexp-test': 'error', 'unicorn/prefer-set-has': 'error', 'unicorn/prefer-spread': 'error', // TODO: Enable this by default when targeting Node.js 16. diff --git a/readme.md b/readme.md index 06eb5d2573..931277df0b 100644 --- a/readme.md +++ b/readme.md @@ -89,6 +89,7 @@ Configure it in `package.json`. "unicorn/prefer-optional-catch-binding": "error", "unicorn/prefer-query-selector": "error", "unicorn/prefer-reflect-apply": "error", + "unicorn/prefer-regexp-test": "error", "unicorn/prefer-set-has": "error", "unicorn/prefer-spread": "error", "unicorn/prefer-string-replace-all": "off", @@ -162,6 +163,7 @@ Configure it in `package.json`. - [prefer-optional-catch-binding](docs/rules/prefer-optional-catch-binding.md) - Prefer omitting the `catch` binding parameter. *(fixable)* - [prefer-query-selector](docs/rules/prefer-query-selector.md) - Prefer `.querySelector()` over `.getElementById()`, `.querySelectorAll()` over `.getElementsByClassName()` and `.getElementsByTagName()`. *(partly fixable)* - [prefer-reflect-apply](docs/rules/prefer-reflect-apply.md) - Prefer `Reflect.apply()` over `Function#apply()`. *(fixable)* +- [prefer-regexp-test](docs/rules/prefer-regexp-test.md) - Prefer `RegExp#test()` over `String#match()` and `RegExp#exec()`. *(fixable)* - [prefer-set-has](docs/rules/prefer-set-has.md) - Prefer `Set#has()` over `Array#includes()` when checking for existence or non-existence. *(fixable)* - [prefer-spread](docs/rules/prefer-spread.md) - Prefer the spread operator over `Array.from()`. *(fixable)* - [prefer-string-replace-all](docs/rules/prefer-string-replace-all.md) - Prefer `String#replaceAll()` over regex searches with the global flag. *(fixable)* diff --git a/rules/prefer-regexp-test.js b/rules/prefer-regexp-test.js new file mode 100644 index 0000000000..7c2aab615f --- /dev/null +++ b/rules/prefer-regexp-test.js @@ -0,0 +1,98 @@ +'use strict'; +const {isParenthesized} = require('eslint-utils'); +const getDocumentationUrl = require('./utils/get-documentation-url'); +const methodSelector = require('./utils/method-selector'); +const {isBooleanNode} = require('./utils/boolean'); +const shouldAddParenthesesToMemberExpressionObject = require('./utils/should-add-parentheses-to-member-expression-object'); + +const MESSAGE_ID_REGEXP_EXEC = 'regexp-exec'; +const MESSAGE_ID_STRING_MATCH = 'string-match'; +const messages = { + [MESSAGE_ID_REGEXP_EXEC]: 'Prefer `.test(…)` over `.exec(…)`.', + [MESSAGE_ID_STRING_MATCH]: 'Prefer `RegExp#test(…)` over `String#match(…)`.' +}; + +const regExpExecCallSelector = methodSelector({ + name: 'exec', + length: 1 +}); + +const stringMatchCallSelector = methodSelector({ + name: 'match', + length: 1 +}); + +const create = context => { + const sourceCode = context.getSourceCode(); + + return { + [regExpExecCallSelector](node) { + if (!isBooleanNode(node)) { + return; + } + + node = node.callee.property; + context.report({ + node, + messageId: MESSAGE_ID_REGEXP_EXEC, + fix: fixer => fixer.replaceText(node, 'test') + }); + }, + [stringMatchCallSelector](node) { + if (!isBooleanNode(node)) { + return; + } + + const regexpNode = node.arguments[0]; + + if (regexpNode.type === 'Literal' && !regexpNode.regex) { + return; + } + + const stringNode = node.callee.object; + + context.report({ + node, + messageId: MESSAGE_ID_STRING_MATCH, + * fix(fixer) { + yield fixer.replaceText(node.callee.property, 'test'); + + let stringText = sourceCode.getText(stringNode); + if ( + !isParenthesized(regexpNode, sourceCode) && + // Only `SequenceExpression` need add parentheses + stringNode.type === 'SequenceExpression' + ) { + stringText = `(${stringText})`; + } + + yield fixer.replaceText(regexpNode, stringText); + + let regexpText = sourceCode.getText(regexpNode); + if ( + !isParenthesized(stringNode, sourceCode) && + shouldAddParenthesesToMemberExpressionObject(regexpNode, sourceCode) + ) { + regexpText = `(${regexpText})`; + } + + // The nodes that pass `isBooleanNode` cannot have an ASI problem. + + yield fixer.replaceText(stringNode, regexpText); + } + }); + } + }; +}; + +module.exports = { + create, + meta: { + type: 'suggestion', + docs: { + url: getDocumentationUrl(__filename) + }, + fixable: 'code', + messages + } +}; diff --git a/test/prefer-regexp-test.js b/test/prefer-regexp-test.js new file mode 100644 index 0000000000..21f70724fd --- /dev/null +++ b/test/prefer-regexp-test.js @@ -0,0 +1,110 @@ +import {outdent} from 'outdent'; +import {test} from './utils/test'; + +test({ + valid: [ + 'const bar = !re.test(foo)', + // Not `boolean` + 'const matches = foo.match(re) || []', + 'const matches = foo.match(re)', + 'const matches = re.exec(foo)', + 'while (foo = re.exec(bar)) {}', + 'while ((foo = re.exec(bar))) {}', + + // Method not match + 'if (foo.notMatch(re)) {}', + 'if (re.notExec(foo)) {}', + // Not `CallExpression` + 'if (foo.match) {}', + 'if (re.exec) {}', + // Computed + 'if (foo[match](re)) {}', + 'if (re[exec](foo)) {}', + 'if (foo["match"](re)) {}', + 'if (re["exec"](foo)) {}', + // Not `MemberExpression` + 'if (match(re)) {}', + 'if (exec(foo)) {}', + // More/Less arguments + 'if (foo.match()) {}', + 'if (re.exec()) {}', + 'if (foo.match(re, another)) {}', + 'if (re.exec(foo, another)) {}', + 'if (foo.match(...[regexp])) {}', + 'if (re.exec(...[string])) {}', + // Not regex + 'if (foo.match(1)) {}', + 'if (foo.match("1")) {}', + 'if (foo.match(null)) {}', + 'if (foo.match(1n)) {}', + 'if (foo.match(true)) {}' + ], + invalid: [] +}); + +test.visualize([ + // `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);', + + // `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);', + + // Parentheses + 'if ((0, foo).match(re)) {}', + 'if ((0, foo).match((re))) {}', + 'if ((foo).match(re)) {}', + 'if ((foo).match((re))) {}', + 'if (foo.match(/re/)) {}', + 'if (foo.match(bar)) {}', + 'if (foo.match(bar.baz)) {}', + 'if (foo.match(bar.baz())) {}', + 'if (foo.match(new RegExp("re", "g"))) {}', + 'if (foo.match(new SomeRegExp())) {}', + 'if (foo.match(new SomeRegExp)) {}', + 'if (foo.match(bar?.baz)) {}', + 'if (foo.match(bar?.baz())) {}', + 'if (foo.match(bar || baz)) {}', + outdent` + async function a() { + if (foo.match(await bar())) {} + } + `, + 'if ((foo).match(/re/)) {}', + 'if ((foo).match(new SomeRegExp)) {}', + 'if ((foo).match(bar?.baz)) {}', + 'if ((foo).match(bar?.baz())) {}', + '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])) {}', + + // Comments + outdent` + async function a() { + if ( + /* 1 */ foo() /* 2 */ + ./* 3 */ match /* 4 */ ( + /* 5 */ await /* 6 */ bar() /* 7 */ + , + /* 8 */ + ) + ) {} + } + ` +]); diff --git a/test/snapshots/prefer-regexp-test.js.md b/test/snapshots/prefer-regexp-test.js.md new file mode 100644 index 0000000000..5418359265 --- /dev/null +++ b/test/snapshots/prefer-regexp-test.js.md @@ -0,0 +1,641 @@ +# Snapshot report for `test/prefer-regexp-test.js` + +The actual snapshot is saved in `prefer-regexp-test.js.snap`. + +Generated by [AVA](https://avajs.dev). + +## prefer-regexp-test - #1 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | const bar = !foo.match(re)␊ + ␊ + Output:␊ + 1 | const bar = !re.test(foo)␊ + ␊ + Error 1/1:␊ + > 1 | const bar = !foo.match(re)␊ + | ^^^^^^^^^^^^^ Prefer `RegExp#test(…)` over `String#match(…)`.␊ + ` + +## prefer-regexp-test - #2 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | const bar = Boolean(foo.match(re))␊ + ␊ + Output:␊ + 1 | const bar = Boolean(re.test(foo))␊ + ␊ + Error 1/1:␊ + > 1 | const bar = Boolean(foo.match(re))␊ + | ^^^^^^^^^^^^^ Prefer `RegExp#test(…)` over `String#match(…)`.␊ + ` + +## prefer-regexp-test - #3 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | if (foo.match(re)) {}␊ + ␊ + Output:␊ + 1 | if (re.test(foo)) {}␊ + ␊ + Error 1/1:␊ + > 1 | if (foo.match(re)) {}␊ + | ^^^^^^^^^^^^^ Prefer `RegExp#test(…)` over `String#match(…)`.␊ + ` + +## prefer-regexp-test - #4 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | const bar = foo.match(re) ? 1 : 2␊ + ␊ + Output:␊ + 1 | const bar = re.test(foo) ? 1 : 2␊ + ␊ + Error 1/1:␊ + > 1 | const bar = foo.match(re) ? 1 : 2␊ + | ^^^^^^^^^^^^^ Prefer `RegExp#test(…)` over `String#match(…)`.␊ + ` + +## prefer-regexp-test - #5 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | while (foo.match(re)) foo = foo.slice(1);␊ + ␊ + Output:␊ + 1 | 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(…)`.␊ + ` + +## prefer-regexp-test - #6 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | do {foo = foo.slice(1)} while (foo.match(re));␊ + ␊ + Output:␊ + 1 | 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(…)`.␊ + ` + +## prefer-regexp-test - #7 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | for (; foo.match(re); ) foo = foo.slice(1);␊ + ␊ + Output:␊ + 1 | 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(…)`.␊ + ` + +## prefer-regexp-test - #8 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | const bar = !re.exec(foo)␊ + ␊ + Output:␊ + 1 | const bar = !re.test(foo)␊ + ␊ + Error 1/1:␊ + > 1 | const bar = !re.exec(foo)␊ + | ^^^^ Prefer `.test(…)` over `.exec(…)`.␊ + ` + +## prefer-regexp-test - #9 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | const bar = Boolean(re.exec(foo))␊ + ␊ + Output:␊ + 1 | const bar = Boolean(re.test(foo))␊ + ␊ + Error 1/1:␊ + > 1 | const bar = Boolean(re.exec(foo))␊ + | ^^^^ Prefer `.test(…)` over `.exec(…)`.␊ + ` + +## prefer-regexp-test - #10 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | if (re.exec(foo)) {}␊ + ␊ + Output:␊ + 1 | if (re.test(foo)) {}␊ + ␊ + Error 1/1:␊ + > 1 | if (re.exec(foo)) {}␊ + | ^^^^ Prefer `.test(…)` over `.exec(…)`.␊ + ` + +## prefer-regexp-test - #11 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | const bar = re.exec(foo) ? 1 : 2␊ + ␊ + Output:␊ + 1 | const bar = re.test(foo) ? 1 : 2␊ + ␊ + Error 1/1:␊ + > 1 | const bar = re.exec(foo) ? 1 : 2␊ + | ^^^^ Prefer `.test(…)` over `.exec(…)`.␊ + ` + +## prefer-regexp-test - #12 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | while (re.exec(foo)) foo = foo.slice(1);␊ + ␊ + Output:␊ + 1 | while (re.test(foo)) foo = foo.slice(1);␊ + ␊ + Error 1/1:␊ + > 1 | while (re.exec(foo)) foo = foo.slice(1);␊ + | ^^^^ Prefer `.test(…)` over `.exec(…)`.␊ + ` + +## prefer-regexp-test - #13 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | do {foo = foo.slice(1)} while (re.exec(foo));␊ + ␊ + Output:␊ + 1 | 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(…)`.␊ + ` + +## prefer-regexp-test - #14 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | for (; re.exec(foo); ) foo = foo.slice(1);␊ + ␊ + Output:␊ + 1 | for (; re.test(foo); ) foo = foo.slice(1);␊ + ␊ + Error 1/1:␊ + > 1 | for (; re.exec(foo); ) foo = foo.slice(1);␊ + | ^^^^ Prefer `.test(…)` over `.exec(…)`.␊ + ` + +## prefer-regexp-test - #15 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | if ((0, foo).match(re)) {}␊ + ␊ + Output:␊ + 1 | if ((re).test((0, foo))) {}␊ + ␊ + Error 1/1:␊ + > 1 | if ((0, foo).match(re)) {}␊ + | ^^^^^^^^^^^^^^^^^^ Prefer `RegExp#test(…)` over `String#match(…)`.␊ + ` + +## prefer-regexp-test - #16 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | if ((0, foo).match((re))) {}␊ + ␊ + Output:␊ + 1 | if ((re).test((0, foo))) {}␊ + ␊ + Error 1/1:␊ + > 1 | if ((0, foo).match((re))) {}␊ + | ^^^^^^^^^^^^^^^^^^^^ Prefer `RegExp#test(…)` over `String#match(…)`.␊ + ` + +## prefer-regexp-test - #17 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | if ((foo).match(re)) {}␊ + ␊ + Output:␊ + 1 | if ((re).test(foo)) {}␊ + ␊ + Error 1/1:␊ + > 1 | if ((foo).match(re)) {}␊ + | ^^^^^^^^^^^^^^^ Prefer `RegExp#test(…)` over `String#match(…)`.␊ + ` + +## prefer-regexp-test - #18 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | if ((foo).match((re))) {}␊ + ␊ + Output:␊ + 1 | if ((re).test((foo))) {}␊ + ␊ + Error 1/1:␊ + > 1 | if ((foo).match((re))) {}␊ + | ^^^^^^^^^^^^^^^^^ Prefer `RegExp#test(…)` over `String#match(…)`.␊ + ` + +## prefer-regexp-test - #19 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | if (foo.match(/re/)) {}␊ + ␊ + Output:␊ + 1 | if (/re/.test(foo)) {}␊ + ␊ + Error 1/1:␊ + > 1 | if (foo.match(/re/)) {}␊ + | ^^^^^^^^^^^^^^^ Prefer `RegExp#test(…)` over `String#match(…)`.␊ + ` + +## prefer-regexp-test - #20 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | if (foo.match(bar)) {}␊ + ␊ + Output:␊ + 1 | if (bar.test(foo)) {}␊ + ␊ + Error 1/1:␊ + > 1 | if (foo.match(bar)) {}␊ + | ^^^^^^^^^^^^^^ Prefer `RegExp#test(…)` over `String#match(…)`.␊ + ` + +## prefer-regexp-test - #21 + +> Snapshot 1 + + `␊ + Input:␊ + 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(…)`.␊ + ` + +## prefer-regexp-test - #22 + +> Snapshot 1 + + `␊ + Input:␊ + 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(…)`.␊ + ` + +## prefer-regexp-test - #23 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | if (foo.match(new RegExp("re", "g"))) {}␊ + ␊ + Output:␊ + 1 | if (new RegExp("re", "g").test(foo)) {}␊ + ␊ + Error 1/1:␊ + > 1 | if (foo.match(new RegExp("re", "g"))) {}␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `RegExp#test(…)` over `String#match(…)`.␊ + ` + +## prefer-regexp-test - #24 + +> Snapshot 1 + + `␊ + Input:␊ + 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(…)`.␊ + ` + +## prefer-regexp-test - #25 + +> Snapshot 1 + + `␊ + Input:␊ + 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(…)`.␊ + ` + +## prefer-regexp-test - #26 + +> Snapshot 1 + + `␊ + Input:␊ + 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(…)`.␊ + ` + +## prefer-regexp-test - #27 + +> Snapshot 1 + + `␊ + Input:␊ + 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(…)`.␊ + ` + +## prefer-regexp-test - #28 + +> Snapshot 1 + + `␊ + Input:␊ + 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(…)`.␊ + ` + +## prefer-regexp-test - #29 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | async function a() {␊ + 2 | if (foo.match(await bar())) {}␊ + 3 | }␊ + ␊ + Output:␊ + 1 | async function a() {␊ + 2 | if ((await bar()).test(foo)) {}␊ + 3 | }␊ + ␊ + Error 1/1:␊ + 1 | async function a() {␊ + > 2 | if (foo.match(await bar())) {}␊ + | ^^^^^^^^^^^^^^^^^^^^^^ Prefer `RegExp#test(…)` over `String#match(…)`.␊ + 3 | }␊ + ` + +## prefer-regexp-test - #30 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | if ((foo).match(/re/)) {}␊ + ␊ + Output:␊ + 1 | if ((/re/).test(foo)) {}␊ + ␊ + Error 1/1:␊ + > 1 | if ((foo).match(/re/)) {}␊ + | ^^^^^^^^^^^^^^^^^ Prefer `RegExp#test(…)` over `String#match(…)`.␊ + ` + +## prefer-regexp-test - #31 + +> Snapshot 1 + + `␊ + Input:␊ + 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(…)`.␊ + ` + +## prefer-regexp-test - #32 + +> Snapshot 1 + + `␊ + Input:␊ + 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(…)`.␊ + ` + +## prefer-regexp-test - #33 + +> Snapshot 1 + + `␊ + Input:␊ + 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(…)`.␊ + ` + +## prefer-regexp-test - #34 + +> Snapshot 1 + + `␊ + Input:␊ + 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(…)`.␊ + ` + +## prefer-regexp-test - #35 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | async function a() {␊ + 2 | if ((foo).match(await bar())) {}␊ + 3 | }␊ + ␊ + Output:␊ + 1 | async function a() {␊ + 2 | if ((await bar()).test(foo)) {}␊ + 3 | }␊ + ␊ + Error 1/1:␊ + 1 | async function a() {␊ + > 2 | if ((foo).match(await bar())) {}␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `RegExp#test(…)` over `String#match(…)`.␊ + 3 | }␊ + ` + +## prefer-regexp-test - #36 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | if (foo.match([re][0])) {}␊ + ␊ + Output:␊ + 1 | if ([re][0].test(foo)) {}␊ + ␊ + Error 1/1:␊ + > 1 | if (foo.match([re][0])) {}␊ + | ^^^^^^^^^^^^^^^^^^ Prefer `RegExp#test(…)` over `String#match(…)`.␊ + ` + +## prefer-regexp-test - #37 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | async function a() {␊ + 2 | if (␊ + 3 | /* 1 */ foo() /* 2 */␊ + 4 | ./* 3 */ match /* 4 */ (␊ + 5 | /* 5 */ await /* 6 */ bar() /* 7 */␊ + 6 | ,␊ + 7 | /* 8 */␊ + 8 | )␊ + 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:␊ + 1 | async function a() {␊ + 2 | if (␊ + > 3 | /* 1 */ foo() /* 2 */␊ + | ^^^^^^^^^^^^^␊ + > 4 | ./* 3 */ match /* 4 */ (␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^␊ + > 5 | /* 5 */ await /* 6 */ bar() /* 7 */␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^␊ + > 6 | ,␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^␊ + > 7 | /* 8 */␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^␊ + > 8 | )␊ + | ^^^^^ Prefer `RegExp#test(…)` over `String#match(…)`.␊ + 9 | ) {}␊ + 10 | }␊ + ` diff --git a/test/snapshots/prefer-regexp-test.js.snap b/test/snapshots/prefer-regexp-test.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..afe366171d077e2cc119b50c28efe0417e95ab6d GIT binary patch literal 2074 zcmV+#2<7)dRzV&Fn=w$tJw-{qO(Z|G)ou2PZuM zg21!c!Y#As)g&FfG9z~MvH?dCu-`uB*E(Q9!W@;)n20Iz3zw#~d4w>!har&P?j7^A z)c?Sf!1AEnUD2@!qx+fwbXCt$#(KWIF)Mw|{Mw1n$03YvU?g?BsTvwqS`}FYv8vq6 zJv|UcJ(~dpKSACeqdFAy&*|J{{l6n~5Ju_u092`^ozLECxjp{u#qF_=)0!fT#(Oe7 zSF-#|CVD*_bnAI}i->c92%{Oz0m4@-Ia+h`kH`X_{4#}nX&J)k*D`>poy#AbQDmQ0 zFZSP>2`~m>G|~%T(2rwod?E{6J!np5g5U76@d%@SEdYi$f9)A`yiDBBCqRl}gYf8deJUd+wjxd_o7T|~6X4*KP@=b|%H??1RqgstHI;0)IBGs=U zF>CKU^9yg;yEg9i3xv^;?E#h#_Fq(LoG>DACeN!r9J07dy9r^m zzaPNfR_oGs?z-V!lX`W{wYK*MAdCjQ4^VQXzyI$CBDSsHxiByK#4%>IS=84b;FR%t z&!N||N;>D?IkfrQ`V$DF%FayBs)J?yyQ$NL9Dnwc|AaY=4Op~k7sjg9k*nUMEVxH! z?7Tg0rT+$m(euo&;&SDio|7M3Dp@jZ+3IbDGZ99QegJUc%e_BWsjq+7r?6#wzp>x^ zjWAjq08lga<?(bRA*zT@Zi=c;c8v&7e(_ z&EPd$H#OZD=|xeYR5q2IL@5k(Fr7hb6-j!%Qb}da^zu@t8?9-KbehqECdOdU8>rBb z&`7U=wpmfkmra?z1m>e+4RjK1pc3o&-TtmXnMmos#RwjXkzg;*tRD-^nh_D4sxfLO zD|Ga9YOFq$9z#!x$(U+W1wNf5g~(FO+9lZf8uYCj*VRhvu|`9(Zc^7eAwtT(utRx; z(x&=+LZ{TPmm|Rdt}sD0&jeb%F3m_y&={xz)DXQsh1Te}uE#fkjR9s82fBdIV_xLSs(nVuM}!ZNI*)x}xLo99#$^;8x!71M;$Qj)c_B2+n(nm#!>h33`D zD832A2b+B+O28iW2`6SUS0uGcfg+|*^`a~?0=rnYi#O9*C$D}KschNgOs-eXyFj^+ zniew&G0-8lb;P}r>as9Tf_BcURzci`#2M)EajNk)bu;zbx#{3=C9R$F>LFh6CNc9; zL~&C|6s4rBW6COYO+zh1)aFPl1K1DaE6q7@) zI4(26U7iVq%Dfc!7TR7&bZ*HaUFO>7#5Wae<#)%HqMomNi_&po>=HKZ>bM6*|6I#TVi7v4O&|$dz{8=)9V8`%ds&|7+|cJYTx-mRTU|U1%`= z#jMrpQQ6s)SP0b9*zX%0?rskP{!W^6df}{w%g#hxt^zCUVioU5OlgErx1@16tx0}g za9-u+NbGsV^yDEo(DGiCe3G2}#$rY7z(b1-iIUC|E;5VQO_tQ#I?;W#z4vs^t5z(Q zw1{QQ?j%Ll$UWN->w`GCI7d5Lo$ZNM=T&_!;T@1$7Txs_$dh8b_BMWkc6rGq@o$6# zeVFLqgaf|B|5>o+WkV_VoaZgAE9thvj@1&qrEp%QH6CV_NDrUpH%hj_J{rnoAw8H8 zJwn*+Eknh$!k8A@-3NEef*GhcOMu0*1bx^R=Fqo}gyqqf1?%2BnN~R4!tb7JE5gJv z+(h1sZA6&I_A~YOtAlVPf5iT6vRkN%;yvy=wIJ)