forked from testing-library/eslint-plugin-testing-library
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathno-global-regexp-flag-in-query.ts
109 lines (98 loc) · 2.93 KB
/
no-global-regexp-flag-in-query.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import { ASTUtils, TSESTree } from '@typescript-eslint/utils';
import { createTestingLibraryRule } from '../create-testing-library-rule';
import {
isMemberExpression,
isCallExpression,
isProperty,
isObjectExpression,
getDeepestIdentifierNode,
isLiteral,
} from '../node-utils';
export const RULE_NAME = 'no-global-regexp-flag-in-query';
export type MessageIds = 'noGlobalRegExpFlagInQuery';
type Options = [];
export default createTestingLibraryRule<Options, MessageIds>({
name: RULE_NAME,
meta: {
type: 'suggestion',
docs: {
description: 'Disallow the use of the global RegExp flag (/g) in queries',
recommendedConfig: {
dom: false,
angular: false,
react: false,
vue: false,
marko: false
},
},
messages: {
noGlobalRegExpFlagInQuery:
'Avoid using the global RegExp flag (/g) in queries',
},
fixable: 'code',
schema: [],
},
defaultOptions: [],
create(context, _, helpers) {
function report(literalNode: TSESTree.Node) {
if (
isLiteral(literalNode) &&
'regex' in literalNode &&
literalNode.regex.flags.includes('g')
) {
context.report({
node: literalNode,
messageId: 'noGlobalRegExpFlagInQuery',
fix(fixer) {
const splitter = literalNode.raw.lastIndexOf('/');
const raw = literalNode.raw.substring(0, splitter);
const flags = literalNode.raw.substring(splitter + 1);
const flagsWithoutGlobal = flags.replace('g', '');
return fixer.replaceText(
literalNode,
`${raw}/${flagsWithoutGlobal}`
);
},
});
return true;
}
return false;
}
function getArguments(identifierNode: TSESTree.Identifier) {
if (isCallExpression(identifierNode.parent)) {
return identifierNode.parent.arguments;
} else if (
isMemberExpression(identifierNode.parent) &&
isCallExpression(identifierNode.parent.parent)
) {
return identifierNode.parent.parent.arguments;
}
return [];
}
return {
CallExpression(node) {
const identifierNode = getDeepestIdentifierNode(node);
if (!identifierNode || !helpers.isQuery(identifierNode)) {
return;
}
const [firstArg, secondArg] = getArguments(identifierNode);
const firstArgumentHasError = report(firstArg);
if (firstArgumentHasError) {
return;
}
if (isObjectExpression(secondArg)) {
const namePropertyNode = secondArg.properties.find(
(p) =>
isProperty(p) &&
ASTUtils.isIdentifier(p.key) &&
p.key.name === 'name' &&
isLiteral(p.value)
) as TSESTree.Property | undefined;
if (namePropertyNode) {
report(namePropertyNode.value);
}
}
},
};
},
});