@blumintinc/eslint-plugin-blumint 1.7.3 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -61
- package/lib/index.js +85 -1
- package/lib/rules/enforce-assert-throws.js +48 -3
- package/lib/rules/enforce-assertSafe-object-key.d.ts +2 -0
- package/lib/rules/enforce-assertSafe-object-key.js +284 -0
- package/lib/rules/enforce-centralized-mock-firestore.js +192 -14
- package/lib/rules/enforce-css-media-queries.d.ts +5 -0
- package/lib/rules/enforce-css-media-queries.js +87 -0
- package/lib/rules/enforce-dynamic-imports.d.ts +9 -0
- package/lib/rules/enforce-dynamic-imports.js +84 -0
- package/lib/rules/enforce-firestore-facade.js +8 -0
- package/lib/rules/enforce-id-capitalization.d.ts +6 -0
- package/lib/rules/enforce-id-capitalization.js +78 -0
- package/lib/rules/enforce-microdiff.d.ts +3 -0
- package/lib/rules/enforce-microdiff.js +379 -0
- package/lib/rules/enforce-mui-rounded-icons.d.ts +1 -0
- package/lib/rules/enforce-mui-rounded-icons.js +54 -0
- package/lib/rules/enforce-object-literal-as-const.d.ts +4 -0
- package/lib/rules/enforce-object-literal-as-const.js +88 -0
- package/lib/rules/enforce-positive-naming.d.ts +1 -0
- package/lib/rules/enforce-positive-naming.js +387 -0
- package/lib/rules/enforce-props-argument-name.d.ts +8 -0
- package/lib/rules/enforce-props-argument-name.js +182 -0
- package/lib/rules/enforce-react-type-naming.d.ts +3 -0
- package/lib/rules/enforce-react-type-naming.js +191 -0
- package/lib/rules/enforce-render-hits-memoization.js +155 -26
- package/lib/rules/enforce-singular-type-names.d.ts +2 -0
- package/lib/rules/enforce-singular-type-names.js +112 -0
- package/lib/rules/enforce-timestamp-now.d.ts +1 -0
- package/lib/rules/enforce-timestamp-now.js +223 -0
- package/lib/rules/enforce-verb-noun-naming.js +5 -2
- package/lib/rules/ensure-pointer-events-none.d.ts +1 -0
- package/lib/rules/ensure-pointer-events-none.js +211 -0
- package/lib/rules/extract-global-constants.d.ts +1 -1
- package/lib/rules/extract-global-constants.js +109 -1
- package/lib/rules/global-const-style.js +3 -2
- package/lib/rules/key-only-outermost-element.d.ts +3 -0
- package/lib/rules/key-only-outermost-element.js +152 -0
- package/lib/rules/no-always-true-false-conditions.d.ts +3 -0
- package/lib/rules/no-always-true-false-conditions.js +1221 -0
- package/lib/rules/no-circular-references.d.ts +1 -0
- package/lib/rules/no-circular-references.js +523 -0
- package/lib/rules/no-firestore-jest-mock.js +27 -4
- package/lib/rules/no-hungarian.d.ts +5 -0
- package/lib/rules/no-hungarian.js +223 -0
- package/lib/rules/no-mock-firebase-admin.js +20 -7
- package/lib/rules/no-object-values-on-strings.d.ts +2 -0
- package/lib/rules/no-object-values-on-strings.js +294 -0
- package/lib/rules/no-type-assertion-returns.d.ts +9 -0
- package/lib/rules/no-type-assertion-returns.js +299 -0
- package/lib/rules/no-unnecessary-destructuring.d.ts +5 -0
- package/lib/rules/no-unnecessary-destructuring.js +69 -0
- package/lib/rules/no-unnecessary-verb-suffix.d.ts +1 -0
- package/lib/rules/no-unnecessary-verb-suffix.js +203 -0
- package/lib/rules/no-unused-props.js +10 -5
- package/lib/rules/no-unused-usestate.d.ts +8 -0
- package/lib/rules/no-unused-usestate.js +84 -0
- package/lib/rules/omit-index-html.d.ts +7 -0
- package/lib/rules/omit-index-html.js +91 -0
- package/lib/rules/prefer-clone-deep.js +294 -22
- package/lib/rules/prefer-fragment-component.js +265 -34
- package/lib/rules/prefer-global-router-state-key.d.ts +5 -0
- package/lib/rules/prefer-global-router-state-key.js +89 -0
- package/lib/rules/prefer-usememo-over-useeffect-usestate.d.ts +5 -0
- package/lib/rules/prefer-usememo-over-useeffect-usestate.js +129 -0
- package/lib/rules/prefer-utility-function-over-private-static.d.ts +1 -0
- package/lib/rules/prefer-utility-function-over-private-static.js +77 -0
- package/lib/rules/react-usememo-should-be-component.d.ts +1 -0
- package/lib/rules/react-usememo-should-be-component.js +623 -0
- package/package.json +10 -7
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.noTypeAssertionReturns = void 0;
|
|
4
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
5
|
+
const createRule_1 = require("../utils/createRule");
|
|
6
|
+
const defaultOptions = {
|
|
7
|
+
allowAsConst: true,
|
|
8
|
+
allowTypePredicates: true,
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Checks if a type assertion is 'as const'
|
|
12
|
+
*/
|
|
13
|
+
function isAsConstAssertion(node) {
|
|
14
|
+
const typeAnnotation = node.typeAnnotation;
|
|
15
|
+
return (typeAnnotation.type === utils_1.AST_NODE_TYPES.TSTypeReference &&
|
|
16
|
+
typeAnnotation.typeName.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
17
|
+
typeAnnotation.typeName.name === 'const');
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Checks if a node is a type predicate (using 'is' keyword)
|
|
21
|
+
*/
|
|
22
|
+
function isTypePredicate(node) {
|
|
23
|
+
return node.typeAnnotation.type === utils_1.AST_NODE_TYPES.TSTypePredicate;
|
|
24
|
+
}
|
|
25
|
+
exports.noTypeAssertionReturns = (0, createRule_1.createRule)({
|
|
26
|
+
name: 'no-type-assertion-returns',
|
|
27
|
+
meta: {
|
|
28
|
+
type: 'suggestion',
|
|
29
|
+
docs: {
|
|
30
|
+
description: 'Enforce typing variables before returning them, rather than using type assertions or explicit return types',
|
|
31
|
+
recommended: 'error',
|
|
32
|
+
requiresTypeChecking: false,
|
|
33
|
+
},
|
|
34
|
+
fixable: 'code',
|
|
35
|
+
schema: [
|
|
36
|
+
{
|
|
37
|
+
type: 'object',
|
|
38
|
+
properties: {
|
|
39
|
+
allowAsConst: { type: 'boolean' },
|
|
40
|
+
allowTypePredicates: { type: 'boolean' },
|
|
41
|
+
},
|
|
42
|
+
additionalProperties: false,
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
messages: {
|
|
46
|
+
noTypeAssertionReturns: 'Type assertions in return statements are not allowed. Type the variable explicitly before returning it.',
|
|
47
|
+
useExplicitVariable: 'Explicit return type annotations are not allowed. Type the variable explicitly before returning it.',
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
defaultOptions: [defaultOptions],
|
|
51
|
+
create(context, [options]) {
|
|
52
|
+
const mergedOptions = { ...defaultOptions, ...options };
|
|
53
|
+
return {
|
|
54
|
+
// Check for return statements with type assertions
|
|
55
|
+
ReturnStatement(node) {
|
|
56
|
+
if (!node.argument)
|
|
57
|
+
return;
|
|
58
|
+
// Check for type assertions using 'as' keyword
|
|
59
|
+
if (node.argument.type === utils_1.AST_NODE_TYPES.TSAsExpression) {
|
|
60
|
+
// Allow 'as const' assertions if configured
|
|
61
|
+
if (mergedOptions.allowAsConst && isAsConstAssertion(node.argument)) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// For nested type assertions, only report the outermost one
|
|
65
|
+
if (node.argument.expression.type === utils_1.AST_NODE_TYPES.TSAsExpression) {
|
|
66
|
+
context.report({
|
|
67
|
+
node: node.argument,
|
|
68
|
+
messageId: 'noTypeAssertionReturns',
|
|
69
|
+
});
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
context.report({
|
|
73
|
+
node: node.argument,
|
|
74
|
+
messageId: 'noTypeAssertionReturns',
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
// Check for type assertions using angle bracket syntax
|
|
78
|
+
if (node.argument.type === utils_1.AST_NODE_TYPES.TSTypeAssertion) {
|
|
79
|
+
context.report({
|
|
80
|
+
node: node.argument,
|
|
81
|
+
messageId: 'noTypeAssertionReturns',
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
// Check functions with explicit return types
|
|
86
|
+
FunctionDeclaration(node) {
|
|
87
|
+
if (!node.returnType)
|
|
88
|
+
return;
|
|
89
|
+
// Allow type predicates if configured
|
|
90
|
+
if (mergedOptions.allowTypePredicates && isTypePredicate(node.returnType)) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
// If type predicates are not allowed, report them
|
|
94
|
+
if (!mergedOptions.allowTypePredicates && isTypePredicate(node.returnType)) {
|
|
95
|
+
context.report({
|
|
96
|
+
node: node.returnType,
|
|
97
|
+
messageId: 'useExplicitVariable',
|
|
98
|
+
});
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
// Check if the function has a return statement with a direct value (not a variable)
|
|
102
|
+
if (node.body && node.body.type === utils_1.AST_NODE_TYPES.BlockStatement) {
|
|
103
|
+
for (const statement of node.body.body) {
|
|
104
|
+
if (statement.type === utils_1.AST_NODE_TYPES.ReturnStatement && statement.argument) {
|
|
105
|
+
// If returning a variable reference, that's fine
|
|
106
|
+
if (statement.argument.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
// If returning an object literal, array literal, or other complex expression
|
|
110
|
+
// without first assigning it to a typed variable, that's a problem
|
|
111
|
+
if (statement.argument.type === utils_1.AST_NODE_TYPES.ObjectExpression ||
|
|
112
|
+
statement.argument.type === utils_1.AST_NODE_TYPES.ArrayExpression ||
|
|
113
|
+
statement.argument.type === utils_1.AST_NODE_TYPES.CallExpression) {
|
|
114
|
+
context.report({
|
|
115
|
+
node: node.returnType,
|
|
116
|
+
messageId: 'useExplicitVariable',
|
|
117
|
+
});
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
// Check function expressions with explicit return types
|
|
125
|
+
FunctionExpression(node) {
|
|
126
|
+
if (!node.returnType)
|
|
127
|
+
return;
|
|
128
|
+
// Allow type predicates if configured
|
|
129
|
+
if (mergedOptions.allowTypePredicates && isTypePredicate(node.returnType)) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
// If type predicates are not allowed, report them
|
|
133
|
+
if (!mergedOptions.allowTypePredicates && isTypePredicate(node.returnType)) {
|
|
134
|
+
context.report({
|
|
135
|
+
node: node.returnType,
|
|
136
|
+
messageId: 'useExplicitVariable',
|
|
137
|
+
});
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
// Check if the function has a return statement with a direct value (not a variable)
|
|
141
|
+
if (node.body && node.body.type === utils_1.AST_NODE_TYPES.BlockStatement) {
|
|
142
|
+
for (const statement of node.body.body) {
|
|
143
|
+
if (statement.type === utils_1.AST_NODE_TYPES.ReturnStatement && statement.argument) {
|
|
144
|
+
// If returning a variable reference, that's fine
|
|
145
|
+
if (statement.argument.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
// If returning an object literal, array literal, or other complex expression
|
|
149
|
+
// without first assigning it to a typed variable, that's a problem
|
|
150
|
+
if (statement.argument.type === utils_1.AST_NODE_TYPES.ObjectExpression ||
|
|
151
|
+
statement.argument.type === utils_1.AST_NODE_TYPES.ArrayExpression ||
|
|
152
|
+
statement.argument.type === utils_1.AST_NODE_TYPES.CallExpression) {
|
|
153
|
+
context.report({
|
|
154
|
+
node: node.returnType,
|
|
155
|
+
messageId: 'useExplicitVariable',
|
|
156
|
+
});
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
// Check arrow functions
|
|
164
|
+
ArrowFunctionExpression(node) {
|
|
165
|
+
// For arrow functions with expression bodies (no block)
|
|
166
|
+
if (node.body.type !== utils_1.AST_NODE_TYPES.BlockStatement) {
|
|
167
|
+
// Check for explicit return type
|
|
168
|
+
if (node.returnType) {
|
|
169
|
+
// Allow type predicates if configured
|
|
170
|
+
if (mergedOptions.allowTypePredicates && isTypePredicate(node.returnType)) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
// If type predicates are not allowed, report them
|
|
174
|
+
if (!mergedOptions.allowTypePredicates && isTypePredicate(node.returnType)) {
|
|
175
|
+
context.report({
|
|
176
|
+
node: node.returnType,
|
|
177
|
+
messageId: 'useExplicitVariable',
|
|
178
|
+
});
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
// If returning an object literal with explicit return type, report it
|
|
182
|
+
if (node.body.type === utils_1.AST_NODE_TYPES.ObjectExpression ||
|
|
183
|
+
node.body.type === utils_1.AST_NODE_TYPES.ArrayExpression) {
|
|
184
|
+
context.report({
|
|
185
|
+
node: node.returnType,
|
|
186
|
+
messageId: 'useExplicitVariable',
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// Check for type assertions in the body
|
|
191
|
+
if (node.body.type === utils_1.AST_NODE_TYPES.TSAsExpression) {
|
|
192
|
+
// Allow 'as const' assertions if configured
|
|
193
|
+
if (mergedOptions.allowAsConst && isAsConstAssertion(node.body)) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
context.report({
|
|
197
|
+
node: node.body,
|
|
198
|
+
messageId: 'noTypeAssertionReturns',
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
else if (node.body.type === utils_1.AST_NODE_TYPES.TSTypeAssertion) {
|
|
202
|
+
context.report({
|
|
203
|
+
node: node.body,
|
|
204
|
+
messageId: 'noTypeAssertionReturns',
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
else if (node.returnType) {
|
|
209
|
+
// For arrow functions with block bodies
|
|
210
|
+
// Allow type predicates if configured
|
|
211
|
+
if (mergedOptions.allowTypePredicates && isTypePredicate(node.returnType)) {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
// If type predicates are not allowed, report them
|
|
215
|
+
if (!mergedOptions.allowTypePredicates && isTypePredicate(node.returnType)) {
|
|
216
|
+
context.report({
|
|
217
|
+
node: node.returnType,
|
|
218
|
+
messageId: 'useExplicitVariable',
|
|
219
|
+
});
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
// Check if the function has a return statement with a direct value (not a variable)
|
|
223
|
+
if (node.body && node.body.type === utils_1.AST_NODE_TYPES.BlockStatement) {
|
|
224
|
+
for (const statement of node.body.body) {
|
|
225
|
+
if (statement.type === utils_1.AST_NODE_TYPES.ReturnStatement && statement.argument) {
|
|
226
|
+
// If returning a variable reference, that's fine
|
|
227
|
+
if (statement.argument.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
// If returning an object literal, array literal, or other complex expression
|
|
231
|
+
// without first assigning it to a typed variable, that's a problem
|
|
232
|
+
if (statement.argument.type === utils_1.AST_NODE_TYPES.ObjectExpression ||
|
|
233
|
+
statement.argument.type === utils_1.AST_NODE_TYPES.ArrayExpression ||
|
|
234
|
+
statement.argument.type === utils_1.AST_NODE_TYPES.CallExpression) {
|
|
235
|
+
context.report({
|
|
236
|
+
node: node.returnType,
|
|
237
|
+
messageId: 'useExplicitVariable',
|
|
238
|
+
});
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
// Check for array methods with type assertions
|
|
247
|
+
CallExpression() {
|
|
248
|
+
// Skip this check as we'll handle it in the TSAsExpression and TSTypeAssertion handlers
|
|
249
|
+
},
|
|
250
|
+
// Check for type assertions in expressions
|
|
251
|
+
TSAsExpression(node) {
|
|
252
|
+
// Allow 'as const' assertions if configured
|
|
253
|
+
if (mergedOptions.allowAsConst && isAsConstAssertion(node)) {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
// If the parent is a return statement, we already handle it in ReturnStatement
|
|
257
|
+
if (node.parent?.type === utils_1.AST_NODE_TYPES.ReturnStatement) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
// If the parent is an arrow function, we already handle it in ArrowFunctionExpression
|
|
261
|
+
if (node.parent?.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
// If the parent is a variable declarator, this is a variable declaration with type assertion
|
|
265
|
+
// which is a valid pattern and should not be flagged
|
|
266
|
+
if (node.parent?.type === utils_1.AST_NODE_TYPES.VariableDeclarator) {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
// For standalone type assertions in expressions
|
|
270
|
+
context.report({
|
|
271
|
+
node,
|
|
272
|
+
messageId: 'noTypeAssertionReturns',
|
|
273
|
+
});
|
|
274
|
+
},
|
|
275
|
+
// Check for type assertions using angle bracket syntax
|
|
276
|
+
TSTypeAssertion(node) {
|
|
277
|
+
// If the parent is a return statement, we already handle it in ReturnStatement
|
|
278
|
+
if (node.parent?.type === utils_1.AST_NODE_TYPES.ReturnStatement) {
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
// If the parent is an arrow function, we already handle it in ArrowFunctionExpression
|
|
282
|
+
if (node.parent?.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
// If the parent is a variable declarator, this is a variable declaration with type assertion
|
|
286
|
+
// which is a valid pattern and should not be flagged
|
|
287
|
+
if (node.parent?.type === utils_1.AST_NODE_TYPES.VariableDeclarator) {
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
// For standalone type assertions in expressions
|
|
291
|
+
context.report({
|
|
292
|
+
node,
|
|
293
|
+
messageId: 'noTypeAssertionReturns',
|
|
294
|
+
});
|
|
295
|
+
},
|
|
296
|
+
};
|
|
297
|
+
},
|
|
298
|
+
});
|
|
299
|
+
//# sourceMappingURL=no-type-assertion-returns.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { TSESTree } from '@typescript-eslint/utils';
|
|
2
|
+
export declare const noUnnecessaryDestructuring: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"noUnnecessaryDestructuring", never[], {
|
|
3
|
+
VariableDeclarator(node: TSESTree.VariableDeclarator): void;
|
|
4
|
+
AssignmentExpression(node: TSESTree.AssignmentExpression): void;
|
|
5
|
+
}>;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.noUnnecessaryDestructuring = void 0;
|
|
4
|
+
const createRule_1 = require("../utils/createRule");
|
|
5
|
+
exports.noUnnecessaryDestructuring = (0, createRule_1.createRule)({
|
|
6
|
+
name: 'no-unnecessary-destructuring',
|
|
7
|
+
meta: {
|
|
8
|
+
type: 'suggestion',
|
|
9
|
+
docs: {
|
|
10
|
+
description: 'Avoid unnecessary object destructuring when there is only one property inside the destructured object',
|
|
11
|
+
recommended: 'error',
|
|
12
|
+
},
|
|
13
|
+
messages: {
|
|
14
|
+
noUnnecessaryDestructuring: 'Avoid unnecessary object destructuring with a single rest property. Use the object directly instead of `{ ...obj }`.',
|
|
15
|
+
},
|
|
16
|
+
schema: [],
|
|
17
|
+
fixable: 'code',
|
|
18
|
+
},
|
|
19
|
+
defaultOptions: [],
|
|
20
|
+
create(context) {
|
|
21
|
+
return {
|
|
22
|
+
// Handle variable declarations
|
|
23
|
+
VariableDeclarator(node) {
|
|
24
|
+
if (node.id.type === 'ObjectPattern' &&
|
|
25
|
+
node.id.properties.length === 1 &&
|
|
26
|
+
node.id.properties[0].type === 'RestElement') {
|
|
27
|
+
const restElement = node.id.properties[0];
|
|
28
|
+
// Report the issue
|
|
29
|
+
context.report({
|
|
30
|
+
node,
|
|
31
|
+
messageId: 'noUnnecessaryDestructuring',
|
|
32
|
+
fix(fixer) {
|
|
33
|
+
const sourceCode = context.getSourceCode();
|
|
34
|
+
const restName = sourceCode.getText(restElement.argument);
|
|
35
|
+
// Handle the case where init might be null
|
|
36
|
+
if (!node.init) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
const initText = sourceCode.getText(node.init);
|
|
40
|
+
// Replace the destructuring with direct assignment
|
|
41
|
+
return fixer.replaceText(node, `${restName} = ${initText}`);
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
// Handle assignments like { ...obj } = value
|
|
47
|
+
AssignmentExpression(node) {
|
|
48
|
+
if (node.operator === '=' &&
|
|
49
|
+
node.left.type === 'ObjectPattern' &&
|
|
50
|
+
node.left.properties.length === 1 &&
|
|
51
|
+
node.left.properties[0].type === 'RestElement') {
|
|
52
|
+
const restElement = node.left.properties[0];
|
|
53
|
+
context.report({
|
|
54
|
+
node,
|
|
55
|
+
messageId: 'noUnnecessaryDestructuring',
|
|
56
|
+
fix(fixer) {
|
|
57
|
+
const sourceCode = context.getSourceCode();
|
|
58
|
+
const restName = sourceCode.getText(restElement.argument);
|
|
59
|
+
const rightText = sourceCode.getText(node.right);
|
|
60
|
+
// Replace the destructuring with direct assignment
|
|
61
|
+
return fixer.replaceText(node, `${restName} = ${rightText}`);
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
//# sourceMappingURL=no-unnecessary-destructuring.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const noUnnecessaryVerbSuffix: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"unnecessaryVerbSuffix", [], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.noUnnecessaryVerbSuffix = void 0;
|
|
4
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
5
|
+
const createRule_1 = require("../utils/createRule");
|
|
6
|
+
const COMMON_PREPOSITION_SUFFIXES = new Set([
|
|
7
|
+
// Basic prepositions
|
|
8
|
+
'From',
|
|
9
|
+
'For',
|
|
10
|
+
'With',
|
|
11
|
+
'To',
|
|
12
|
+
'By',
|
|
13
|
+
'In',
|
|
14
|
+
'On',
|
|
15
|
+
'At',
|
|
16
|
+
'Of',
|
|
17
|
+
// Directional prepositions
|
|
18
|
+
'Above',
|
|
19
|
+
'Below',
|
|
20
|
+
'Over',
|
|
21
|
+
'Under',
|
|
22
|
+
'Up',
|
|
23
|
+
'Down',
|
|
24
|
+
'Into',
|
|
25
|
+
'Onto',
|
|
26
|
+
'Out',
|
|
27
|
+
'Off',
|
|
28
|
+
'Through',
|
|
29
|
+
'Throughout',
|
|
30
|
+
'Across',
|
|
31
|
+
'Along',
|
|
32
|
+
'Around',
|
|
33
|
+
'Past',
|
|
34
|
+
// Temporal prepositions
|
|
35
|
+
'After',
|
|
36
|
+
'Before',
|
|
37
|
+
'During',
|
|
38
|
+
'Until',
|
|
39
|
+
'Till',
|
|
40
|
+
'Since',
|
|
41
|
+
'Within',
|
|
42
|
+
// Logical/causal prepositions
|
|
43
|
+
'Because',
|
|
44
|
+
'Despite',
|
|
45
|
+
'Instead',
|
|
46
|
+
'Via',
|
|
47
|
+
'Without',
|
|
48
|
+
'Versus',
|
|
49
|
+
'Vs',
|
|
50
|
+
// Comparative prepositions
|
|
51
|
+
'Than',
|
|
52
|
+
'Like',
|
|
53
|
+
'As',
|
|
54
|
+
// Compound prepositions
|
|
55
|
+
'According',
|
|
56
|
+
'Ahead',
|
|
57
|
+
'Apart',
|
|
58
|
+
'Aside',
|
|
59
|
+
'Away',
|
|
60
|
+
'Back',
|
|
61
|
+
'Forward',
|
|
62
|
+
'Backward',
|
|
63
|
+
'Inside',
|
|
64
|
+
'Outside',
|
|
65
|
+
'Together',
|
|
66
|
+
// Phrasal prepositions (common endings)
|
|
67
|
+
'About',
|
|
68
|
+
'Against',
|
|
69
|
+
'Among',
|
|
70
|
+
'Amongst',
|
|
71
|
+
'Beside',
|
|
72
|
+
'Besides',
|
|
73
|
+
'Between',
|
|
74
|
+
'Beyond',
|
|
75
|
+
'Concerning',
|
|
76
|
+
'Considering',
|
|
77
|
+
'Regarding',
|
|
78
|
+
'Respecting',
|
|
79
|
+
'Towards',
|
|
80
|
+
'Toward',
|
|
81
|
+
'Upon',
|
|
82
|
+
// Preposition-like adverbs
|
|
83
|
+
'Again',
|
|
84
|
+
'Already',
|
|
85
|
+
'Always',
|
|
86
|
+
'Ever',
|
|
87
|
+
'Never',
|
|
88
|
+
'Now',
|
|
89
|
+
'Soon',
|
|
90
|
+
'Then',
|
|
91
|
+
'There',
|
|
92
|
+
'Where',
|
|
93
|
+
'When',
|
|
94
|
+
'While',
|
|
95
|
+
// Programming-specific suffixes
|
|
96
|
+
'Async',
|
|
97
|
+
'Sync',
|
|
98
|
+
]);
|
|
99
|
+
exports.noUnnecessaryVerbSuffix = (0, createRule_1.createRule)({
|
|
100
|
+
name: 'no-unnecessary-verb-suffix',
|
|
101
|
+
meta: {
|
|
102
|
+
type: 'suggestion',
|
|
103
|
+
docs: {
|
|
104
|
+
description: 'Prevent unnecessary verb suffixes in function and method names',
|
|
105
|
+
recommended: 'error',
|
|
106
|
+
},
|
|
107
|
+
fixable: 'code',
|
|
108
|
+
schema: [],
|
|
109
|
+
messages: {
|
|
110
|
+
unnecessaryVerbSuffix: 'Unnecessary verb suffix "{{suffix}}" in function name. Consider using "{{suggestion}}" instead.',
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
defaultOptions: [],
|
|
114
|
+
create(context) {
|
|
115
|
+
function checkFunctionName(node, name) {
|
|
116
|
+
if (!name)
|
|
117
|
+
return;
|
|
118
|
+
for (const suffix of COMMON_PREPOSITION_SUFFIXES) {
|
|
119
|
+
// Check if the name ends with the suffix
|
|
120
|
+
if (name.endsWith(suffix)) {
|
|
121
|
+
// Make sure there's a verb before the suffix (camelCase format)
|
|
122
|
+
// This regex checks for a verb pattern before the suffix
|
|
123
|
+
// It looks for a word character followed by lowercase letters before the suffix
|
|
124
|
+
const verbBeforeSuffixPattern = new RegExp(`\\w[a-z]+${suffix}$`);
|
|
125
|
+
if (verbBeforeSuffixPattern.test(name)) {
|
|
126
|
+
const suggestion = name.substring(0, name.length - suffix.length);
|
|
127
|
+
// Skip if the suggestion would be empty or just a single character
|
|
128
|
+
if (suggestion.length <= 1)
|
|
129
|
+
continue;
|
|
130
|
+
context.report({
|
|
131
|
+
node,
|
|
132
|
+
messageId: 'unnecessaryVerbSuffix',
|
|
133
|
+
data: {
|
|
134
|
+
suffix,
|
|
135
|
+
suggestion,
|
|
136
|
+
},
|
|
137
|
+
fix(fixer) {
|
|
138
|
+
if (node.type === utils_1.AST_NODE_TYPES.FunctionDeclaration) {
|
|
139
|
+
return fixer.replaceText(node.id, suggestion);
|
|
140
|
+
}
|
|
141
|
+
else if (node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
|
|
142
|
+
node.type === utils_1.AST_NODE_TYPES.FunctionExpression) {
|
|
143
|
+
const parent = node.parent;
|
|
144
|
+
if (parent &&
|
|
145
|
+
(parent.type === utils_1.AST_NODE_TYPES.VariableDeclarator ||
|
|
146
|
+
parent.type === utils_1.AST_NODE_TYPES.Property ||
|
|
147
|
+
parent.type === utils_1.AST_NODE_TYPES.MethodDefinition)) {
|
|
148
|
+
if ('key' in parent) {
|
|
149
|
+
return fixer.replaceText(parent.key, suggestion);
|
|
150
|
+
}
|
|
151
|
+
else if ('id' in parent && parent.id) {
|
|
152
|
+
return fixer.replaceText(parent.id, suggestion);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return null;
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
FunctionDeclaration(node) {
|
|
165
|
+
if (node.id) {
|
|
166
|
+
checkFunctionName(node, node.id.name);
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
VariableDeclarator(node) {
|
|
170
|
+
if (node.id.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
171
|
+
(node.init?.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
|
|
172
|
+
node.init?.type === utils_1.AST_NODE_TYPES.FunctionExpression)) {
|
|
173
|
+
checkFunctionName(node.init, node.id.name);
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
MethodDefinition(node) {
|
|
177
|
+
if (node.key.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
178
|
+
checkFunctionName(node.value, node.key.name);
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
TSMethodSignature(node) {
|
|
182
|
+
// Handle interface method signatures
|
|
183
|
+
if (node.key.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
184
|
+
checkFunctionName(node, node.key.name);
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
Property(node) {
|
|
188
|
+
if (node.key.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
189
|
+
(node.value.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
|
|
190
|
+
node.value.type === utils_1.AST_NODE_TYPES.FunctionExpression)) {
|
|
191
|
+
checkFunctionName(node.value, node.key.name);
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
FunctionExpression(node) {
|
|
195
|
+
// Handle named function expressions
|
|
196
|
+
if (node.id) {
|
|
197
|
+
checkFunctionName(node, node.id.name);
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
};
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
//# sourceMappingURL=no-unnecessary-verb-suffix.js.map
|
|
@@ -168,11 +168,16 @@ exports.noUnusedProps = (0, createRule_1.createRule)({
|
|
|
168
168
|
if (propsType && used) {
|
|
169
169
|
Object.keys(propsType).forEach((prop) => {
|
|
170
170
|
if (!used.has(prop)) {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
171
|
+
// For imported types (props that start with '...'), only report if there's no rest spread operator
|
|
172
|
+
// This allows imported types to be used without being flagged when properly forwarded
|
|
173
|
+
const hasRestSpread = Array.from(used.values()).some(usedProp => usedProp.startsWith('...'));
|
|
174
|
+
if (!prop.startsWith('...') || !hasRestSpread) {
|
|
175
|
+
context.report({
|
|
176
|
+
node: propsType[prop],
|
|
177
|
+
messageId: 'unusedProp',
|
|
178
|
+
data: { propName: prop },
|
|
179
|
+
});
|
|
180
|
+
}
|
|
176
181
|
}
|
|
177
182
|
});
|
|
178
183
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { TSESTree } from '@typescript-eslint/utils';
|
|
2
|
+
/**
|
|
3
|
+
* Rule to detect and remove unused useState hooks in React components
|
|
4
|
+
* This rule identifies cases where the state variable from useState is ignored (e.g., replaced with _)
|
|
5
|
+
*/
|
|
6
|
+
export declare const noUnusedUseState: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"unusedUseState", never[], {
|
|
7
|
+
VariableDeclarator(node: TSESTree.VariableDeclarator): void;
|
|
8
|
+
}>;
|