1 | 'use strict';
|
2 | const getDocumentationUrl = require('./utils/get-documentation-url');
|
3 |
|
4 | const doesNotContain = (string, characters) => characters.every(character => !string.includes(character));
|
5 |
|
6 | const isSimpleString = string => doesNotContain(
|
7 | string,
|
8 | ['^', '$', '+', '[', '{', '(', '\\', '.', '?', '*']
|
9 | );
|
10 |
|
11 | const create = context => {
|
12 | return {
|
13 | CallExpression(node) {
|
14 | const {callee} = node;
|
15 | const {property} = callee;
|
16 |
|
17 | if (!(property && callee.type === 'MemberExpression')) {
|
18 | return;
|
19 | }
|
20 |
|
21 | const arguments_ = node.arguments;
|
22 |
|
23 | let regex;
|
24 | if (property.name === 'test' && callee.object.regex) {
|
25 | ({regex} = callee.object);
|
26 | } else if (
|
27 | property.name === 'match' &&
|
28 | arguments_ &&
|
29 | arguments_[0] &&
|
30 | arguments_[0].regex
|
31 | ) {
|
32 | ({regex} = arguments_[0]);
|
33 | } else {
|
34 | return;
|
35 | }
|
36 |
|
37 | if (regex.flags && regex.flags.includes('i')) {
|
38 | return;
|
39 | }
|
40 |
|
41 | const {pattern} = regex;
|
42 | if (pattern.startsWith('^') && isSimpleString(pattern.slice(1))) {
|
43 | context.report({
|
44 | node,
|
45 | message: 'Prefer `String#startsWith()` over a regex with `^`.'
|
46 | });
|
47 | } else if (
|
48 | pattern.endsWith('$') &&
|
49 | isSimpleString(pattern.slice(0, -1))
|
50 | ) {
|
51 | context.report({
|
52 | node,
|
53 | message: 'Prefer `String#endsWith()` over a regex with `$`.'
|
54 | });
|
55 | }
|
56 | }
|
57 | };
|
58 | };
|
59 |
|
60 | module.exports = {
|
61 | create,
|
62 | meta: {
|
63 | type: 'suggestion',
|
64 | docs: {
|
65 | url: getDocumentationUrl(__filename)
|
66 | }
|
67 | }
|
68 | };
|