UNPKG

1.55 kBJavaScriptView Raw
1'use strict';
2const getDocumentationUrl = require('./utils/get-documentation-url');
3const quoteString = require('./utils/quote-string');
4const methodSelector = require('./utils/method-selector');
5
6const selector = methodSelector({
7 name: 'replace',
8 length: 2
9});
10
11const message = 'Prefer `String#replaceAll()` over `String#replace()`.';
12
13function isRegexWithGlobalFlag(node) {
14 const {type, regex} = node;
15 return type === 'Literal' && regex && regex.flags === 'g';
16}
17
18function isLiteralCharactersOnly(node) {
19 const searchPattern = node.regex.pattern;
20 return !/[$()*+.?[\\\]^{}]/.test(searchPattern.replace(/\\[$()*+.?[\\\]^{}]/g, ''));
21}
22
23function removeEscapeCharacters(regexString) {
24 let fixedString = regexString;
25 let index = 0;
26 do {
27 index = fixedString.indexOf('\\', index);
28
29 if (index >= 0) {
30 fixedString = fixedString.slice(0, index) + fixedString.slice(index + 1);
31 index++;
32 }
33 } while (index >= 0);
34
35 return fixedString;
36}
37
38const create = context => {
39 return {
40 [selector]: node => {
41 const {arguments: arguments_} = node;
42 const [search] = arguments_;
43
44 if (!isRegexWithGlobalFlag(search) || !isLiteralCharactersOnly(search)) {
45 return;
46 }
47
48 context.report({
49 node,
50 message,
51 fix: fixer =>
52 [
53 fixer.insertTextAfter(node.callee, 'All'),
54 fixer.replaceText(search, quoteString(removeEscapeCharacters(search.regex.pattern)))
55 ]
56 });
57 }
58 };
59};
60
61module.exports = {
62 create,
63 meta: {
64 type: 'suggestion',
65 docs: {
66 url: getDocumentationUrl(__filename)
67 },
68 fixable: 'code'
69 }
70};