From 28e7498ad06679bb92343db53bb40a7b5ba2990a Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Mon, 25 Sep 2023 13:12:39 +0800 Subject: [PATCH] Support RegExp `v` flag (#2195) --- rules/better-regex.js | 5 +- rules/prefer-regexp-test.js | 4 + rules/prefer-string-replace-all.js | 5 +- test/better-regex.mjs | 1 + test/prefer-regexp-test.mjs | 39 +++++++ test/prefer-string-replace-all.mjs | 4 + test/prefer-string-starts-ends-with.mjs | 2 + test/snapshots/prefer-regexp-test.mjs.md | 32 ++++++ test/snapshots/prefer-regexp-test.mjs.snap | Bin 3018 -> 3098 bytes .../prefer-string-replace-all.mjs.md | 108 ++++++++++++++---- .../prefer-string-replace-all.mjs.snap | Bin 1888 -> 2018 bytes .../prefer-string-starts-ends-with.mjs.md | 36 +++++- .../prefer-string-starts-ends-with.mjs.snap | Bin 2167 -> 2222 bytes 13 files changed, 207 insertions(+), 29 deletions(-) diff --git a/rules/better-regex.js b/rules/better-regex.js index 680b10b156..26ef86d761 100644 --- a/rules/better-regex.js +++ b/rules/better-regex.js @@ -28,10 +28,9 @@ const create = context => { } const {raw: original, regex} = node; - - // Regular Expressions with `u` flag are not well handled by `regexp-tree` + // Regular Expressions with `u` and `v` flag are not well handled by `regexp-tree` // https://github.com/DmitrySoshnikov/regexp-tree/issues/162 - if (regex.flags.includes('u')) { + if (regex.flags.includes('u') || regex.flags.includes('v')) { return; } diff --git a/rules/prefer-regexp-test.js b/rules/prefer-regexp-test.js index a1161ae324..ecff31099e 100644 --- a/rules/prefer-regexp-test.js +++ b/rules/prefer-regexp-test.js @@ -77,6 +77,10 @@ const cases = [ const isRegExpNode = node => isRegexLiteral(node) || isNewExpression(node, {name: 'RegExp'}); const isRegExpWithoutGlobalFlag = (node, scope) => { + if (isRegexLiteral(node)) { + return !node.regex.flags.includes('g'); + } + const staticResult = getStaticValue(node, scope); // Don't know if there is `g` flag diff --git a/rules/prefer-string-replace-all.js b/rules/prefer-string-replace-all.js index 3d2cbbe80c..cd0d01161b 100644 --- a/rules/prefer-string-replace-all.js +++ b/rules/prefer-string-replace-all.js @@ -17,7 +17,7 @@ function getPatternReplacement(node) { } const {pattern, flags} = node.regex; - if (flags.replace('u', '') !== 'g') { + if (flags.replace('u', '').replace('v', '') !== 'g') { return; } @@ -25,7 +25,8 @@ function getPatternReplacement(node) { try { tree = parseRegExp(pattern, flags, { - unicodePropertyEscape: true, + unicodePropertyEscape: flags.includes('u'), + unicodeSet: flags.includes('v'), namedGroups: true, lookbehind: true, }); diff --git a/test/better-regex.mjs b/test/better-regex.mjs index 1c6cefc18c..5675d04fba 100644 --- a/test/better-regex.mjs +++ b/test/better-regex.mjs @@ -40,6 +40,7 @@ test({ // Should not crash ESLint (#446 and #448) '/\\{\\{verificationUrl\\}\\}/gu', '/^test-(?[a-zA-Z-\\d]+)$/u', + String.raw`/[\p{Script_Extensions=Greek}--π]/v`, // Should not suggest wrong regex (#447) '/(\\s|\\.|@|_|-)/u', diff --git a/test/prefer-regexp-test.mjs b/test/prefer-regexp-test.mjs index 66c73d167e..459e38c781 100644 --- a/test/prefer-regexp-test.mjs +++ b/test/prefer-regexp-test.mjs @@ -150,6 +150,8 @@ test.snapshot({ let re = new RegExp('foo', 'g'); if(str.match(re)); `, + '!/a/u.exec(foo)', + '!/a/v.exec(foo)', ], }); @@ -173,3 +175,40 @@ test.vue({ }, ], }); + +const supportsUnicodeSets = (() => { + try { + // eslint-disable-next-line prefer-regex-literals -- Can't test with regex literal + return new RegExp('.', 'v').unicodeSets; + } catch {} + + return false; +})(); +// These cases can be auto-fixed in environments supports `v` flag (eg, Node.js v20), +// But will use suggestions instead in environments doesn't support `v` flag. +test({ + valid: [], + invalid: [ + { + code: 'const re = /a/v; !re.exec(foo)', + output: 'const re = /a/v; !re.test(foo)', + }, + { + code: 'const re = new RegExp("a", "v"); !re.exec(foo)', + output: 'const re = new RegExp("a", "v"); !re.test(foo)', + }, + ].map(({code, output}) => + supportsUnicodeSets + ? { + code, + output, + errors: 1, + } + : { + code, + errors: [ + {suggestions: [{output}]}, + ], + }, + ), +}); diff --git a/test/prefer-string-replace-all.mjs b/test/prefer-string-replace-all.mjs index e742f84c3b..6fb1158feb 100644 --- a/test/prefer-string-replace-all.mjs +++ b/test/prefer-string-replace-all.mjs @@ -77,11 +77,13 @@ test.snapshot({ 'foo.replace(/\\W/g, bar)', 'foo.replace(/\\u{61}/g, bar)', 'foo.replace(/\\u{61}/gu, bar)', + 'foo.replace(/\\u{61}/gv, bar)', 'foo.replace(/]/g, "bar")', // Extra flag 'foo.replace(/a/gi, bar)', 'foo.replace(/a/gui, bar)', 'foo.replace(/a/uig, bar)', + 'foo.replace(/a/vig, bar)', // Variables 'const pattern = new RegExp("foo", "g"); foo.replace(pattern, bar)', 'foo.replace(new RegExp("foo", "g"), bar)', @@ -99,9 +101,11 @@ test.snapshot({ 'foo.replace(/\\u{1f600}/gu, _)', 'foo.replace(/\\n/g, _)', 'foo.replace(/\\u{20}/gu, _)', + 'foo.replace(/\\u{20}/gv, _)', 'foo.replaceAll(/a]/g, _)', 'foo.replaceAll(/\\r\\n\\u{1f600}/gu, _)', + 'foo.replaceAll(/\\r\\n\\u{1f600}/gv, _)', `foo.replaceAll(/a${' very'.repeat(30)} long string/g, _)`, // Invalid RegExp #2010 diff --git a/test/prefer-string-starts-ends-with.mjs b/test/prefer-string-starts-ends-with.mjs index 9727322061..4af56909e5 100644 --- a/test/prefer-string-starts-ends-with.mjs +++ b/test/prefer-string-starts-ends-with.mjs @@ -219,6 +219,8 @@ test.snapshot({ '/a$/.test(a ??= b)', '/^a/.test(a || b)', '/^a/.test(a && b)', + '/^a/u.test("string")', + '/^a/v.test("string")', // eslint-disable-next-line no-template-curly-in-string '/a$/.test(`${unknown}`)', '/a$/.test(String(unknown))', diff --git a/test/snapshots/prefer-regexp-test.mjs.md b/test/snapshots/prefer-regexp-test.mjs.md index 4838a18635..92399bc611 100644 --- a/test/snapshots/prefer-regexp-test.mjs.md +++ b/test/snapshots/prefer-regexp-test.mjs.md @@ -927,3 +927,35 @@ Generated by [AVA](https://avajs.dev). 1 | let re = new RegExp('foo', 'g');␊ 2 | if(re.test(str));␊ ` + +## Invalid #57 + 1 | !/a/u.exec(foo) + +> Output + + `␊ + 1 | !/a/u.test(foo)␊ + ` + +> Error 1/1 + + `␊ + > 1 | !/a/u.exec(foo)␊ + | ^^^^ Prefer \`.test(…)\` over \`.exec(…)\`.␊ + ` + +## Invalid #58 + 1 | !/a/v.exec(foo) + +> Output + + `␊ + 1 | !/a/v.test(foo)␊ + ` + +> Error 1/1 + + `␊ + > 1 | !/a/v.exec(foo)␊ + | ^^^^ Prefer \`.test(…)\` over \`.exec(…)\`.␊ + ` diff --git a/test/snapshots/prefer-regexp-test.mjs.snap b/test/snapshots/prefer-regexp-test.mjs.snap index dc06b67f28ace0f8d25e2c694322ec7320950ac2..d692343591962e353845cb2a45950241a0159306 100644 GIT binary patch literal 3098 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 literal 3018 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 Output + + `␊ + 1 | foo.replaceAll('a', bar)␊ + ` + +> Error 1/1 + + `␊ + > 1 | foo.replace(/\\u{61}/gv, bar)␊ + | ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊ + ` + +## Invalid #17 1 | foo.replace(/]/g, "bar") > Output @@ -278,7 +294,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊ ` -## Invalid #17 +## Invalid #18 1 | foo.replace(/a/gi, bar) > Output @@ -294,7 +310,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊ ` -## Invalid #18 +## Invalid #19 1 | foo.replace(/a/gui, bar) > Output @@ -310,7 +326,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊ ` -## Invalid #19 +## Invalid #20 1 | foo.replace(/a/uig, bar) > Output @@ -326,7 +342,23 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊ ` -## Invalid #20 +## Invalid #21 + 1 | foo.replace(/a/vig, bar) + +> Output + + `␊ + 1 | foo.replaceAll(/a/vig, bar)␊ + ` + +> Error 1/1 + + `␊ + > 1 | foo.replace(/a/vig, bar)␊ + | ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊ + ` + +## Invalid #22 1 | const pattern = new RegExp("foo", "g"); foo.replace(pattern, bar) > Output @@ -342,7 +374,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊ ` -## Invalid #21 +## Invalid #23 1 | foo.replace(new RegExp("foo", "g"), bar) > Output @@ -358,7 +390,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊ ` -## Invalid #22 +## Invalid #24 1 | foo.replace(/a]/g, _) > Output @@ -374,7 +406,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊ ` -## Invalid #23 +## Invalid #25 1 | foo.replace(/[a]/g, _) > Output @@ -390,7 +422,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊ ` -## Invalid #24 +## Invalid #26 1 | foo.replace(/a{1/g, _) > Output @@ -406,7 +438,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊ ` -## Invalid #25 +## Invalid #27 1 | foo.replace(/a{1}/g, _) > Output @@ -422,7 +454,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊ ` -## Invalid #26 +## Invalid #28 1 | foo.replace(/\u0022/g, _) > Output @@ -438,7 +470,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊ ` -## Invalid #27 +## Invalid #29 1 | foo.replace(/\u0027/g, _) > Output @@ -454,7 +486,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊ ` -## Invalid #28 +## Invalid #30 1 | foo.replace(/\cM\cj/g, _) > Output @@ -470,7 +502,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊ ` -## Invalid #29 +## Invalid #31 1 | foo.replace(/\x22/g, _) > Output @@ -486,7 +518,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊ ` -## Invalid #30 +## Invalid #32 1 | foo.replace(/\x27/g, _) > Output @@ -502,7 +534,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊ ` -## Invalid #31 +## Invalid #33 1 | foo.replace(/\uD83D\ude00/g, _) > Output @@ -518,7 +550,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊ ` -## Invalid #32 +## Invalid #34 1 | foo.replace(/\u{1f600}/gu, _) > Output @@ -534,7 +566,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊ ` -## Invalid #33 +## Invalid #35 1 | foo.replace(/\n/g, _) > Output @@ -550,7 +582,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊ ` -## Invalid #34 +## Invalid #36 1 | foo.replace(/\u{20}/gu, _) > Output @@ -566,7 +598,23 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊ ` -## Invalid #35 +## Invalid #37 + 1 | foo.replace(/\u{20}/gv, _) + +> Output + + `␊ + 1 | foo.replaceAll(' ', _)␊ + ` + +> Error 1/1 + + `␊ + > 1 | foo.replace(/\\u{20}/gv, _)␊ + | ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊ + ` + +## Invalid #38 1 | foo.replaceAll(/a]/g, _) > Output @@ -582,7 +630,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^ This pattern can be replaced with 'a]'.␊ ` -## Invalid #36 +## Invalid #39 1 | foo.replaceAll(/\r\n\u{1f600}/gu, _) > Output @@ -598,7 +646,23 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^^ This pattern can be replaced with '\\r\\n😀'.␊ ` -## Invalid #37 +## Invalid #40 + 1 | foo.replaceAll(/\r\n\u{1f600}/gv, _) + +> Output + + `␊ + 1 | foo.replaceAll('\\r\\n😀', _)␊ + ` + +> Error 1/1 + + `␊ + > 1 | foo.replaceAll(/\\r\\n\\u{1f600}/gv, _)␊ + | ^^^^^^^^^^^^^^^^^ This pattern can be replaced with '\\r\\n😀'.␊ + ` + +## Invalid #41 1 | foo.replaceAll(/a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long string/g, _) > Output @@ -614,7 +678,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This pattern can be replaced with a string literal.␊ ` -## Invalid #38 +## Invalid #42 1 | foo.replace(/(?!a)+/g, "") > Output diff --git a/test/snapshots/prefer-string-replace-all.mjs.snap b/test/snapshots/prefer-string-replace-all.mjs.snap index 8e01a4e09c0b8ccffac7ce78d09f9767b9dfb5fa..baf0750efe1b6a4ee45d2c82681ef87eb7584344 100644 GIT binary patch literal 2018 zcmV<82Oao9RzVF2}_x;T^1))o{xZlKa_-WgzJR7{1^8;?%g&rx@X_013MsA$4RUN zpayQuSH4}4oj2V%`^5az=psLe)v1I-2#>eIn^rUw)=aD$+3QCJgg~tRNzgk1;JM)S zBfBE1HukQ+aOM-;G%dtxDZ$GbfI&TXJfa<^xnFpBjS$#Vt1V`u!)7I)*qC5Y8Nu2z;Jq;1F9nQ;ZCsdWR} z4j+3Ob%0lQ6XZQmk7rk@To2Zz+>>l*JjCiu!l%52Ce2hj=}6@JwHt%CWiy2k ztE~h>PXLAmUu(&oF+ZjD+6zmaRPz{!)hfbpHvk^?^Qgb@O6kR#;88u+5BWJ0VpT(E z;w{#DZrpt-+&Q^rdcDt-Rj)&=_Hehd01?I(`z2m1{UNg7)K!(T0`y*ZwTdw80RU8o zJt~{~MXZrk@7I)7?5u@YeU@+zG5mC&EiMyBOn$F*(!`Pnd&?nK2Y6V?M??e#?nvB` zSmAN~O3C+E2j75LeV3r>1;Ci5z``Z}U zb4x$!4zUV*TggOB9+0{P7G1vD6fPefcp&2##OhYUz&-%XUJs8}UolN?tzOyqee)y; zu^LU-i->=D{uk5CKIcyr|NZ%g`@TePpI3h*BzOX#Tk&@J=DM$*Nt|+GTSfkF=OI=L z2u@xAEI++**p@x(u5H@z=sDN)R5Qe?icodH5Vs#%uIRO37x0E-&+EQ_L=UZ!5 z`&M3uSk(|tA@;BM=$$irTWho2k5?W`-y96F>g8)?IimLK%O&iFSuZ`N-8OdZ*qC1- zR`(GU0|96#YubMOWYdZ^ud}EBbWd0gv6?_=L^P*ts>u3m?|#_eQu^kcQ9cl>5CF-$U^7e*X%TtJzlfO&h^9y-+D>|MKj`w58Eb%Z|t0JNPuw>Y(F zVa$ew-yCk9Ha;3+brhi*;RJf%RaoKzyd(kc45MUnnPj6e)TBw%b4i-9dc9mGRm)@{ zj12t-x_4+W*FDm{ft;1fSnYq-3_5c8A12OvFi)E_$r=-rFx_m@8MFa5j|og*j2X9H zLV9S2r@}nY?k5|>BpFjvH3l?AR3|(-uao@%w3|YvLiHbLIv$>$MHVwzRjFT}e zd-Ga2x-cAH2tj8f@L3{fLgx|udB=#rqqp%bvZHSl$M|5m-C?LY>mJLo+W*}@2_rB> za?t=mt?aC|wDFu9=-!ezy8Oq?e5#&^R6D^4>_4y9ZH?O^qGOI z#T|4)OAMEzq>Q;_>b%HNiaFGV2nABs<@Lp)P=rN@>7!s2sjr$IMRDJ=itZtOQqi2w zqBwoq){b1rWw9vGQuJ79S8AqMKGeio6fgY+yksaNHibT7bHWt!SZ#*mQ(|aPH&UXF zu_#VHbermeo)+OEaI2%ZV|*JFS7q`D1s__AU1)F30__JgW3Dd!W-3bJ3{0YiA@`oc zWa`XwnRb`#x*$;I^Yh)JqXn8eWNob-TOs8r=aH4O3l&nku|wyTlrpdA)o@l=*uBUD z^psC`@m?kTuDi&w7ExUk%J^I?)DeT34wygPh5 z!N%N-Oy@;O3?+&VSaj6Sb|VMb7(2H9r0s7tR1XdJPwgo%q4{(uUI+zqU~VG)MbmSj zjkOqV!h=94lniR0egFOFjRq}~j(bI^gsLS%OXGdudMDlKbnU+Hk1iw^j&zpM>yQzr zcU-m%$pF literal 1888 zcmV-m2cP&sRzVpz83miD$OXfG*SrK`+{UP9*55Xn`y8)RCKi|{0b@?X)?c0PN`VL~YzsL-C)WN=R zxw7nQ^`(jf9%o~IR60YFY3 z^6-lLk054W5+tGVx@!^=bHh#t{&aG+=av-a8;IF81a0g9@a@!N=U3mWkLBzCc8qH_ z2)%`4g9&zX7VJ{j$cMRC1KWlEim;|< zL|N7xV`{{zKCQDuUHe1KwrFX_Y=pHP3S|qnr8M0bGjpR$$?1s@v%3jATLG{>*67$` ze8J@NIcKEC<=H4%ICcWTX@t!_TjsavzG2r6JKM|I!G!=~*0Hr2OAxk%4ZGky72Yjh z=AQ57yLbh}>`{W=PRL?j&qEVjws-#d;Dzx9JwRjO*l2=F2>a7bn@SdxZN9!^>ypLo z^Ik#BI<_$*1L1J;HaEMQ%{$+V^^%o8iOzwT-Amxv7JwuF_6h5|t~j`7E8B|Y%Sx_6 z%)TJl?~L?JD;ivQSije^Vw_|8gS5pEvv&zp?E$#0)gKT)48L5EHfw6`+(!!`X0r&y zE&%-H{eyk*js>rVEle6E8Wh+@* z@_b?bso}wox;F{b#}t=A%+4k#M`#2Z)kNn@hoJaS^Sha(Ul}K6bYikCzH13B9H#cTPq9#g{$V7}bCh81YcZ=6} zL@@DFtKUMrccr(&Oz>7G+l^7j>-8Fg5i#9Zbi)_j5L?K%u<%6|GGyY%nTRcJ_?f%* zz`Rr?Wmxvjy&mXBPkh4*UG>6Ok*Y*=?ay6To)LJq25o_rwNZp|lO_J2Q&rpWSQV>% z=kbZU@PvpWQDJznYS|YkP9|5Gl9`}-lyH4mu8+c$>J!yVE}zb7O}OjZh_PtlRU0!V zT9?EmsEkHUqJdGX3{0ekAonYWTEhmVNi8A2M;js{+3z*<^}E7G_S$HqcL zxJW{m$f|yrNtkFN4uYF((Yy~i2i+3m2hAUBnVCl}}vNfm#_(EM51 zzFwDUymhxKcNNLL{zB$%9TOv-o){q?`-Lb>Q#5k9kXm_X(_n4UQy7HQ$8%ES_5vmy zZ7HOl)GV#*v!+P7t%C%;wrcWFRpQ+Pv98z3rx;&{9fXCkAR;^Qoz3fz-o8SHB%eTr zB9OXBqN3+3aK(Es+XqgdaDL{^?6gRFG}1HM!urFP8~WMGB$o?YaQx^R>3a~`)FxAO z*Vy}mXFmT-3!3{prJbGh=IB@ZF?N!$$HcCDi@Yhdm-)<6-T$#X%amn@`dz0|eJD<+ ze-%je5pX);5x^&rLH$!2-cMY-LCYlJQBl58?iBHTpK1WoYZ*?hAJ7_nv*HV%iVT*C z(;*{OoYnhbldcX`)55v|>_6gaT7CrGgz$a~Vzt!M1>a6d(8C3v&q*P%(&v`e^?K~( a{+_V9f~$ur)G_aQJ^v3wGi4|ZApij5Ag5yh diff --git a/test/snapshots/prefer-string-starts-ends-with.mjs.md b/test/snapshots/prefer-string-starts-ends-with.mjs.md index 1b84db47ba..324dadbb72 100644 --- a/test/snapshots/prefer-string-starts-ends-with.mjs.md +++ b/test/snapshots/prefer-string-starts-ends-with.mjs.md @@ -573,6 +573,38 @@ Generated by [AVA](https://avajs.dev). ` ## Invalid #23 + 1 | /^a/u.test("string") + +> Output + + `␊ + 1 | "string".startsWith('a')␊ + ` + +> Error 1/1 + + `␊ + > 1 | /^a/u.test("string")␊ + | ^^^^^^^^^^^^^^^^^^^^ Prefer \`String#startsWith()\` over a regex with \`^\`.␊ + ` + +## Invalid #24 + 1 | /^a/v.test("string") + +> Output + + `␊ + 1 | "string".startsWith('a')␊ + ` + +> Error 1/1 + + `␊ + > 1 | /^a/v.test("string")␊ + | ^^^^^^^^^^^^^^^^^^^^ Prefer \`String#startsWith()\` over a regex with \`^\`.␊ + ` + +## Invalid #25 1 | /a$/.test(`${unknown}`) > Output @@ -588,7 +620,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^^^^^^^^ Prefer \`String#endsWith()\` over a regex with \`$\`.␊ ` -## Invalid #24 +## Invalid #26 1 | /a$/.test(String(unknown)) > Output @@ -604,7 +636,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer \`String#endsWith()\` over a regex with \`$\`.␊ ` -## Invalid #25 +## Invalid #27 1 | /* 1 */ 2 | ( 3 | /* 2 */ diff --git a/test/snapshots/prefer-string-starts-ends-with.mjs.snap b/test/snapshots/prefer-string-starts-ends-with.mjs.snap index 1f73e419583db9a3260eb11ccc936ebe9241197b..9312b0134561adfe450798d0a37f642200d6689a 100644 GIT binary patch literal 2222 zcmV;f2vPSzRzVF#G@Sz4_k%zW@K< zyd5^Q0H6nG>2z#rbtmk%xwmfjh>jk+hXC-?A4@I$wOe`P*H3T$+4{lyF^>;N8hQ{& zdml@6D*&R_wlqD6YLh$(=*_pI{%K7hZ9SHvHUM-#oB7fCs=E=FqpOE$x{ugQAnjLJ z_C){?^I+rd`4M~4C!St-;eEr3aRky{!IIeyfY>?bCf(oPE_=k4^B-FEM*1#Ly8uhq zNC5hb+&H6WhZ}cm6JBe$)bE`f0%_mGa+((H%|TrXcdT!}bY@}I`SJOG5J(%{(IXQ( z1CToUvh84})|wtOP8WR8c(RT_+ND?`y8tlMYTJHo=e8$Db=~SJR$UuKAZ;3!JKX>n zYjiK${n?O&2|rwn?pJ%PoIu*HQ65=Ji@mxc?abn}AG;pr)vU~_qFX?1EtYA~066B% zkBqpoy5Y#T8!GbOYUd)5b_bTio&c0yxOc2_*yqRBG-NhLov52aAng}e29p5H>S?(5 z>5`brs2W2~T18PQfwYBK>S2rBm+TLIe7foC-kqjLUmm2A zF1BB6oR+?eKw2x78?;oVm#6JtRA)MpAMp*csO_lrNI5MB=RKLe=)IAZ6NVjn zl5=%V1%b4Ov1BFyP_xo(dSh>7ZmY6gQ??y#JA^>m3;jHDGZ}!RTeA1rYZi~_y6{wW zuNCuB38ak~=#lVL0KR#=`S*F%<4#N}9i7`a<4`Ptv=gx`9}K`>3k$oPYN$W+c4_;h zt=GHIK84zoSjx-*Jk0ApvUvG-C%!+hWXIHhyDuh?_5hZt!vJ`c@OOkhV))RXrOzCwltJ9^${o?3hNZK%2@FB-JthrVPX~}Ro3T%13SvQEYkoM`ci6R}= zJZmXgLMutjWQ#65yni!)!ZX}?c{JVvyNxvHlLnE)?Kb+>F4AQuod_5MP(dF;?@7#hS!mwYiIm3Y__5 zww)@nImE|*2%dV!i>BvQo$7DMcXENCQTZL)a4>f`A<78hG>E;3&4Cvi9UP2Akk6lC#N zE2ZLf~*hIE3qFL<5|iWKV6&x4s$yDt3%HobHmv=hRHL- zizufv-Rg2XY|b>#&>8M5q!ruTbHXyQg=nc&HgtexH?)KM8CE11<6rr7)RiI>&nuuD zf;r%}O|{ueY_j`fx8OOA*V%tqHQ~9910j}m21CxCO^Tj#ani&Z(KA7&uN>ge3v@ZB z1!E+$@Tx0R*~kOhHZuh|&~3A~kU!6Db6;k9E{EGnn(5|){BE8rh2h8PEuS$$F9hXX z7mPv3L9DVcy7&$LMtuEg4;VWW(Z+6v9 zP_VOFDZaBx@VBuFJ(A0KEEw7CgR3rDvw%N`P1RHuo2M(@RW-x5D#rI)xEcPg?C;0n zRibf+yS{o)G|a@+5PCki>WVxc?tlW1=_b$Ta%ny{_v4HzxU4EBtCPoySgi5Z9nML) ze5Vr3Wi2FgToX>(o3o-=VrSu_xiX8~!Jb`ku*dEh;4^xlM|w@K((V^orF(JTSo2q; zmr1^gC|{#PGOekrLaVeuE3eN)aTsJEVrM-4CteS~8sRwbB8k3eOB;;XFaUl>mSlJZ zO-a}^5Gjz&#Mlgp*qGuorlLz^#kZqdAr%F$4L&ozslkX;Fj5Rj-jVTb4G0mkc@Yi3 zrh#6Q2~Q&#TOb@{NcGHnphs_nKy*-Hq7|giZ%~y2Rd5DI10F3E_d@t+&%$fQVFnDs z2=T=s-=dpyeBZJy-}ggVzDH>RYWR!5&KJ<`TNJ)Uut@v{o<)OsNz7{Ec~sCKh4HY! zlFIcs-;S1CtfRreSrLKR$XOwnOF3&JXrIJgD}i0ocRo6KNz8A-Vm#ku5|CWbB*jO1 zfsGX-5{qt3^ah2%WZ(yhpoLLt-30s|rgRJoXUkZH- zZ&vZjH+>VOdIorArkVu6d9+Fl7k!ad*_&;|FMeOS4&d3_`w5ZKCjFwd%z;LbWoJ2R zsOu?BY8Hx)qtfswlyinHo6L3FvJoVTe&(CyKyQMPTB?L9aKUF-k*Do4ZrEs;*C%Dh zW4-Xq8n_Hck<2ILV@k$p%p23POA&-2rj%ELkbBOvdA697n-ynT5;4e)8t=bz@uy##V4SDUe>xO8byxxe{%w6JFow%$98`X3`Vx|FsqC0 wT<`(?YOSTvtGiA4uQ1e4irt~dYAHtrBbzZ+b+MR1Eydse0LGwVQpZRD0Ei4kEC2ui literal 2167 zcmV--2#EJVRzVNmV4>&#A(9&NSYRzL?N7To*rL3kJ2H zBH0@aKvLU=-3z1lOqhJ4?rf21#dr*AFCi(60U&wa=_z*`VoF9_I`cMZG}FB>+C@lu z#R8Bra>LBT9@lO+r@zqJGH_fe2DPsuIYEp5#?ZKFJJ)w#I%`_vnTZv@V^Ev$oJS`2 z1R$eZ+=ZgBJO7+(OOB1aQThW0wddkIayt=#T++Vd%C7B?4jX!(-?aM5D;U%!yy%f; z9DuQA_p;q9how*Y=KF+!%}17CP~#gW7r|eUkv7 znl|N~TwMR2>t6Z6RmF{T8;o`wlE=vaIOZ*kjlQ(D_0X3eZK@a*weI#oK18{h2$zJN< z;t{>-jyLsNu^h z^^>D(yJv2@8dr-!Z4DA*E&%t+<40C6|LWM+`##t?{qOk27}SzT67y(0>3>EWqw{mm zrCLv!Z(W>-LG5THKji}u4!Xh^3X1^GhrJYq<0gC#UPe)dV!~l?x(J8MIkD1Jq1O?* z)F}VLSREFX3ricP5=MiIbh`AYUMk%TP8+5QKKOVCSw=c=TY<|_X)o{Z*FmZcr)JP5 z0(X$*WG!ApD{zwz*vC#YxB3K z8aOBo$VaFEJ7j^co+xTFgSya3;?!HrZ=wn>sURxt5IGImDh?T8wLV>}nJiYjyQ-?v zS%H^OL>1{QfnXU2<5nxK(@D6Qb+AYw0VTuqsFIzm!3(Hr63vl(Ev!LEWPStEj1FOH z3!I<@j`Klli|l;#s#wovZ9PF3ABGpF8c2Jo6xnBa$xb9Ava{7xXKiou;>1o424eeR zj24ZB0cM zf3{LO&pjH<@7xh+I@xoFqAK&_s41I=2R8ZAm4awt>&XO0yJA2TB%K@v3}EuEY)mf_ z#x$xYg)#J^RLW677>+DfZABi7T2+vxu(dJ<;z^#VOj4-g6mXbRS!o^Wc+BPd=NLB6 zs5`n8R1wUz$!A8Ln#@qe#HuON+cN6b1Q9`-7tvs38sars&@i%)g@FSNIi7J3 z@#xJA5CfyI&^eyb1_WG;>?J^ zZ05`mlkGWkBPgHAohyM|(sw>Oc}dJK;m3Hs$s!=Rph&il^a7h-j7UtnIl~(i0+Wd! zB!UuVsd*FdS5Sb*XK#rRSq?id6QXYZqlBoPj2L9M4*xHOzKOSLc;?%GlcjkEct)m~ z1i;xICbM_BWfX9iorv;0Zc)*j3sc|gxY z*(WW5J`eRip^+wZ$DhrlaM|RxPq$MwcG-6&ZoxY{US;J+EbVxQ$AK__ofMbDP2yI% z_)x`XxtoPagHu}`bm%1xdDjJF>fj*OSn}XtSCu}}*t*PvAHDC@jMBr=ed6ySIV~s# zXbAFM*^R--c>!u|@tzM~74!T1-z%i6xF1|4em|J5bUPS&B$x46FtXbRS6j691FnkE zNm1T2k5=aVpwc10)uMz(RiC{L4m)ryaM}k~Ta@{caVByP%5*P2+0MhPEw*#P t2lV_+Prx$??fD-QtS80p&||ffqk@sm2&=YO%%Ya!@4q}?_JuV^003q?Cl3Gs