@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.
Files changed (70) hide show
  1. package/README.md +83 -61
  2. package/lib/index.js +85 -1
  3. package/lib/rules/enforce-assert-throws.js +48 -3
  4. package/lib/rules/enforce-assertSafe-object-key.d.ts +2 -0
  5. package/lib/rules/enforce-assertSafe-object-key.js +284 -0
  6. package/lib/rules/enforce-centralized-mock-firestore.js +192 -14
  7. package/lib/rules/enforce-css-media-queries.d.ts +5 -0
  8. package/lib/rules/enforce-css-media-queries.js +87 -0
  9. package/lib/rules/enforce-dynamic-imports.d.ts +9 -0
  10. package/lib/rules/enforce-dynamic-imports.js +84 -0
  11. package/lib/rules/enforce-firestore-facade.js +8 -0
  12. package/lib/rules/enforce-id-capitalization.d.ts +6 -0
  13. package/lib/rules/enforce-id-capitalization.js +78 -0
  14. package/lib/rules/enforce-microdiff.d.ts +3 -0
  15. package/lib/rules/enforce-microdiff.js +379 -0
  16. package/lib/rules/enforce-mui-rounded-icons.d.ts +1 -0
  17. package/lib/rules/enforce-mui-rounded-icons.js +54 -0
  18. package/lib/rules/enforce-object-literal-as-const.d.ts +4 -0
  19. package/lib/rules/enforce-object-literal-as-const.js +88 -0
  20. package/lib/rules/enforce-positive-naming.d.ts +1 -0
  21. package/lib/rules/enforce-positive-naming.js +387 -0
  22. package/lib/rules/enforce-props-argument-name.d.ts +8 -0
  23. package/lib/rules/enforce-props-argument-name.js +182 -0
  24. package/lib/rules/enforce-react-type-naming.d.ts +3 -0
  25. package/lib/rules/enforce-react-type-naming.js +191 -0
  26. package/lib/rules/enforce-render-hits-memoization.js +155 -26
  27. package/lib/rules/enforce-singular-type-names.d.ts +2 -0
  28. package/lib/rules/enforce-singular-type-names.js +112 -0
  29. package/lib/rules/enforce-timestamp-now.d.ts +1 -0
  30. package/lib/rules/enforce-timestamp-now.js +223 -0
  31. package/lib/rules/enforce-verb-noun-naming.js +5 -2
  32. package/lib/rules/ensure-pointer-events-none.d.ts +1 -0
  33. package/lib/rules/ensure-pointer-events-none.js +211 -0
  34. package/lib/rules/extract-global-constants.d.ts +1 -1
  35. package/lib/rules/extract-global-constants.js +109 -1
  36. package/lib/rules/global-const-style.js +3 -2
  37. package/lib/rules/key-only-outermost-element.d.ts +3 -0
  38. package/lib/rules/key-only-outermost-element.js +152 -0
  39. package/lib/rules/no-always-true-false-conditions.d.ts +3 -0
  40. package/lib/rules/no-always-true-false-conditions.js +1221 -0
  41. package/lib/rules/no-circular-references.d.ts +1 -0
  42. package/lib/rules/no-circular-references.js +523 -0
  43. package/lib/rules/no-firestore-jest-mock.js +27 -4
  44. package/lib/rules/no-hungarian.d.ts +5 -0
  45. package/lib/rules/no-hungarian.js +223 -0
  46. package/lib/rules/no-mock-firebase-admin.js +20 -7
  47. package/lib/rules/no-object-values-on-strings.d.ts +2 -0
  48. package/lib/rules/no-object-values-on-strings.js +294 -0
  49. package/lib/rules/no-type-assertion-returns.d.ts +9 -0
  50. package/lib/rules/no-type-assertion-returns.js +299 -0
  51. package/lib/rules/no-unnecessary-destructuring.d.ts +5 -0
  52. package/lib/rules/no-unnecessary-destructuring.js +69 -0
  53. package/lib/rules/no-unnecessary-verb-suffix.d.ts +1 -0
  54. package/lib/rules/no-unnecessary-verb-suffix.js +203 -0
  55. package/lib/rules/no-unused-props.js +10 -5
  56. package/lib/rules/no-unused-usestate.d.ts +8 -0
  57. package/lib/rules/no-unused-usestate.js +84 -0
  58. package/lib/rules/omit-index-html.d.ts +7 -0
  59. package/lib/rules/omit-index-html.js +91 -0
  60. package/lib/rules/prefer-clone-deep.js +294 -22
  61. package/lib/rules/prefer-fragment-component.js +265 -34
  62. package/lib/rules/prefer-global-router-state-key.d.ts +5 -0
  63. package/lib/rules/prefer-global-router-state-key.js +89 -0
  64. package/lib/rules/prefer-usememo-over-useeffect-usestate.d.ts +5 -0
  65. package/lib/rules/prefer-usememo-over-useeffect-usestate.js +129 -0
  66. package/lib/rules/prefer-utility-function-over-private-static.d.ts +1 -0
  67. package/lib/rules/prefer-utility-function-over-private-static.js +77 -0
  68. package/lib/rules/react-usememo-should-be-component.d.ts +1 -0
  69. package/lib/rules/react-usememo-should-be-component.js +623 -0
  70. 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
- context.report({
172
- node: propsType[prop],
173
- messageId: 'unusedProp',
174
- data: { propName: prop },
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
+ }>;