@blumintinc/eslint-plugin-blumint 1.11.1 → 1.12.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/lib/index.js
CHANGED
|
@@ -106,7 +106,7 @@ const enforce_boolean_naming_prefixes_1 = require("./rules/enforce-boolean-namin
|
|
|
106
106
|
module.exports = {
|
|
107
107
|
meta: {
|
|
108
108
|
name: '@blumintinc/eslint-plugin-blumint',
|
|
109
|
-
version: '1.
|
|
109
|
+
version: '1.12.1',
|
|
110
110
|
},
|
|
111
111
|
parseOptions: {
|
|
112
112
|
ecmaVersion: 2020,
|
|
@@ -121,9 +121,45 @@ exports.enforceBooleanNamingPrefixes = (0, createRule_1.createRule)({
|
|
|
121
121
|
}
|
|
122
122
|
// Check for logical expressions (&&, ||)
|
|
123
123
|
if (node.init.type === utils_1.AST_NODE_TYPES.LogicalExpression &&
|
|
124
|
-
|
|
124
|
+
node.init.operator === '&&') {
|
|
125
125
|
return true;
|
|
126
126
|
}
|
|
127
|
+
// Special case for logical OR (||) - only consider it boolean if:
|
|
128
|
+
// 1. It's used with boolean literals or
|
|
129
|
+
// 2. It's not used with array/object literals as fallbacks
|
|
130
|
+
if (node.init.type === utils_1.AST_NODE_TYPES.LogicalExpression &&
|
|
131
|
+
node.init.operator === '||') {
|
|
132
|
+
// Check if right side is a non-boolean literal (array, object, string, number)
|
|
133
|
+
const rightSide = node.init.right;
|
|
134
|
+
if (rightSide.type === utils_1.AST_NODE_TYPES.ArrayExpression ||
|
|
135
|
+
rightSide.type === utils_1.AST_NODE_TYPES.ObjectExpression ||
|
|
136
|
+
(rightSide.type === utils_1.AST_NODE_TYPES.Literal &&
|
|
137
|
+
typeof rightSide.value !== 'boolean')) {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
// If right side is a boolean literal, it's likely a boolean variable
|
|
141
|
+
if (rightSide.type === utils_1.AST_NODE_TYPES.Literal &&
|
|
142
|
+
typeof rightSide.value === 'boolean') {
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
// For other cases, we need to be more careful
|
|
146
|
+
// If we can determine the left side is a boolean, then it's a boolean variable
|
|
147
|
+
const leftSide = node.init.left;
|
|
148
|
+
if ((leftSide.type === utils_1.AST_NODE_TYPES.Literal &&
|
|
149
|
+
typeof leftSide.value === 'boolean') ||
|
|
150
|
+
(leftSide.type === utils_1.AST_NODE_TYPES.UnaryExpression &&
|
|
151
|
+
leftSide.operator === '!')) {
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
// For function calls, check if the function name suggests it returns a boolean
|
|
155
|
+
if (leftSide.type === utils_1.AST_NODE_TYPES.CallExpression &&
|
|
156
|
+
leftSide.callee.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
157
|
+
const calleeName = leftSide.callee.name;
|
|
158
|
+
return approvedPrefixes.some((prefix) => calleeName.toLowerCase().startsWith(prefix.toLowerCase()));
|
|
159
|
+
}
|
|
160
|
+
// Default to false for other cases with || to avoid false positives
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
127
163
|
// Check for unary expressions with ! operator
|
|
128
164
|
if (node.init.type === utils_1.AST_NODE_TYPES.UnaryExpression &&
|
|
129
165
|
node.init.operator === '!') {
|
|
@@ -349,6 +385,17 @@ exports.enforceBooleanNamingPrefixes = (0, createRule_1.createRule)({
|
|
|
349
385
|
});
|
|
350
386
|
}
|
|
351
387
|
}
|
|
388
|
+
/**
|
|
389
|
+
* Check if an identifier is imported from an external module
|
|
390
|
+
*/
|
|
391
|
+
function isImportedIdentifier(name) {
|
|
392
|
+
const scope = context.getScope();
|
|
393
|
+
const variable = scope.variables.find((v) => v.name === name);
|
|
394
|
+
if (!variable)
|
|
395
|
+
return false;
|
|
396
|
+
// Check if it's an import binding
|
|
397
|
+
return variable.defs.some((def) => def.type === 'ImportBinding');
|
|
398
|
+
}
|
|
352
399
|
/**
|
|
353
400
|
* Check property definitions for boolean values
|
|
354
401
|
*/
|
|
@@ -370,16 +417,51 @@ exports.enforceBooleanNamingPrefixes = (0, createRule_1.createRule)({
|
|
|
370
417
|
utils_1.AST_NODE_TYPES.TSBooleanKeyword) {
|
|
371
418
|
isBooleanProperty = true;
|
|
372
419
|
}
|
|
420
|
+
// Skip checking if this property is part of an object literal passed to an external function
|
|
373
421
|
if (isBooleanProperty && !hasApprovedPrefix(propertyName)) {
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
422
|
+
// Special cases for common Node.js API boolean properties
|
|
423
|
+
if ((propertyName === 'recursive' || propertyName === 'keepAlive') &&
|
|
424
|
+
node.parent?.type === utils_1.AST_NODE_TYPES.ObjectExpression &&
|
|
425
|
+
node.parent.parent?.type === utils_1.AST_NODE_TYPES.CallExpression) {
|
|
426
|
+
return; // Skip checking for these properties in object literals passed to functions
|
|
427
|
+
}
|
|
428
|
+
// Check if this property is in an object literal that's an argument to a function call
|
|
429
|
+
let isExternalApiCall = false;
|
|
430
|
+
// Navigate up to find if we're in an object expression that's an argument to a function call
|
|
431
|
+
if (node.parent?.type === utils_1.AST_NODE_TYPES.ObjectExpression &&
|
|
432
|
+
node.parent.parent?.type === utils_1.AST_NODE_TYPES.CallExpression) {
|
|
433
|
+
const callExpression = node.parent.parent;
|
|
434
|
+
// Check if the function being called is an identifier (like mkdirSync, createServer, etc.)
|
|
435
|
+
if (callExpression.callee.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
436
|
+
const calleeName = callExpression.callee.name;
|
|
437
|
+
if (isImportedIdentifier(calleeName)) {
|
|
438
|
+
isExternalApiCall = true;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
// Also check for member expressions like fs.mkdirSync
|
|
442
|
+
if (callExpression.callee.type === utils_1.AST_NODE_TYPES.MemberExpression) {
|
|
443
|
+
// For member expressions, check if the object is imported
|
|
444
|
+
const objectNode = callExpression.callee.object;
|
|
445
|
+
if (objectNode.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
446
|
+
const objectName = objectNode.name;
|
|
447
|
+
if (isImportedIdentifier(objectName)) {
|
|
448
|
+
isExternalApiCall = true;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
// Only report if it's not an external API call
|
|
454
|
+
if (!isExternalApiCall) {
|
|
455
|
+
context.report({
|
|
456
|
+
node: node.key,
|
|
457
|
+
messageId: 'missingBooleanPrefix',
|
|
458
|
+
data: {
|
|
459
|
+
type: 'property',
|
|
460
|
+
name: propertyName,
|
|
461
|
+
prefixes: formatPrefixes(),
|
|
462
|
+
},
|
|
463
|
+
});
|
|
464
|
+
}
|
|
383
465
|
}
|
|
384
466
|
}
|
|
385
467
|
/**
|
|
@@ -394,15 +476,35 @@ exports.enforceBooleanNamingPrefixes = (0, createRule_1.createRule)({
|
|
|
394
476
|
node.typeAnnotation.typeAnnotation.type ===
|
|
395
477
|
utils_1.AST_NODE_TYPES.TSBooleanKeyword &&
|
|
396
478
|
!hasApprovedPrefix(propertyName)) {
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
479
|
+
// Skip if this property is part of a parameter's type annotation
|
|
480
|
+
// Check if this property signature is inside a parameter's type annotation
|
|
481
|
+
let isInParameterType = false;
|
|
482
|
+
let parent = node.parent;
|
|
483
|
+
while (parent) {
|
|
484
|
+
if (parent.type === utils_1.AST_NODE_TYPES.TSTypeLiteral) {
|
|
485
|
+
const grandParent = parent.parent;
|
|
486
|
+
if (grandParent?.type === utils_1.AST_NODE_TYPES.TSTypeAnnotation &&
|
|
487
|
+
grandParent.parent?.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
488
|
+
grandParent.parent.parent?.type ===
|
|
489
|
+
utils_1.AST_NODE_TYPES.FunctionDeclaration) {
|
|
490
|
+
isInParameterType = true;
|
|
491
|
+
break;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
parent = parent.parent;
|
|
495
|
+
}
|
|
496
|
+
// Only report if not in a parameter type annotation
|
|
497
|
+
if (!isInParameterType) {
|
|
498
|
+
context.report({
|
|
499
|
+
node: node.key,
|
|
500
|
+
messageId: 'missingBooleanPrefix',
|
|
501
|
+
data: {
|
|
502
|
+
type: 'property',
|
|
503
|
+
name: propertyName,
|
|
504
|
+
prefixes: formatPrefixes(),
|
|
505
|
+
},
|
|
506
|
+
});
|
|
507
|
+
}
|
|
406
508
|
}
|
|
407
509
|
}
|
|
408
510
|
/**
|
|
@@ -427,6 +529,31 @@ exports.enforceBooleanNamingPrefixes = (0, createRule_1.createRule)({
|
|
|
427
529
|
},
|
|
428
530
|
});
|
|
429
531
|
}
|
|
532
|
+
// Check if the parameter has an object type with boolean properties
|
|
533
|
+
if (node.typeAnnotation?.typeAnnotation &&
|
|
534
|
+
node.typeAnnotation.typeAnnotation.type === utils_1.AST_NODE_TYPES.TSTypeLiteral) {
|
|
535
|
+
const typeLiteral = node.typeAnnotation.typeAnnotation;
|
|
536
|
+
// Check each member of the type literal
|
|
537
|
+
for (const member of typeLiteral.members) {
|
|
538
|
+
if (member.type === utils_1.AST_NODE_TYPES.TSPropertySignature &&
|
|
539
|
+
member.key.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
540
|
+
member.typeAnnotation?.typeAnnotation.type ===
|
|
541
|
+
utils_1.AST_NODE_TYPES.TSBooleanKeyword) {
|
|
542
|
+
const propertyName = member.key.name;
|
|
543
|
+
if (!hasApprovedPrefix(propertyName)) {
|
|
544
|
+
context.report({
|
|
545
|
+
node: member.key,
|
|
546
|
+
messageId: 'missingBooleanPrefix',
|
|
547
|
+
data: {
|
|
548
|
+
type: 'property',
|
|
549
|
+
name: propertyName,
|
|
550
|
+
prefixes: formatPrefixes(),
|
|
551
|
+
},
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
430
557
|
}
|
|
431
558
|
return {
|
|
432
559
|
VariableDeclarator: checkVariableDeclaration,
|
|
@@ -5,11 +5,853 @@ const utils_1 = require("@typescript-eslint/utils");
|
|
|
5
5
|
const createRule_1 = require("../utils/createRule");
|
|
6
6
|
// Common negative prefixes for boolean variables
|
|
7
7
|
const BOOLEAN_NEGATIVE_PREFIXES = ['not', 'no', 'non', 'un', 'in', 'dis'];
|
|
8
|
+
const IN_EXCEPTIONS = [
|
|
9
|
+
'in',
|
|
10
|
+
'inane',
|
|
11
|
+
'inaugural',
|
|
12
|
+
'inaugurated',
|
|
13
|
+
'inauguration',
|
|
14
|
+
'inbound',
|
|
15
|
+
'inbox',
|
|
16
|
+
'incandescent',
|
|
17
|
+
'incarcerated',
|
|
18
|
+
'incarceration',
|
|
19
|
+
'incarnation',
|
|
20
|
+
'incendiary',
|
|
21
|
+
'incense',
|
|
22
|
+
'incentive',
|
|
23
|
+
'incentives',
|
|
24
|
+
'inception',
|
|
25
|
+
'incest',
|
|
26
|
+
'inch',
|
|
27
|
+
'inches',
|
|
28
|
+
'incidence',
|
|
29
|
+
'incident',
|
|
30
|
+
'incidental',
|
|
31
|
+
'incidentally',
|
|
32
|
+
'incidents',
|
|
33
|
+
'incision',
|
|
34
|
+
'incite',
|
|
35
|
+
'inciting',
|
|
36
|
+
'inclination',
|
|
37
|
+
'incline',
|
|
38
|
+
'inclined',
|
|
39
|
+
'include',
|
|
40
|
+
'included',
|
|
41
|
+
'includes',
|
|
42
|
+
'including',
|
|
43
|
+
'inclusion',
|
|
44
|
+
'inclusive',
|
|
45
|
+
'income',
|
|
46
|
+
'incomes',
|
|
47
|
+
'incoming',
|
|
48
|
+
'incorporate',
|
|
49
|
+
'incorporated',
|
|
50
|
+
'incorporates',
|
|
51
|
+
'incorporating',
|
|
52
|
+
'incorporation',
|
|
53
|
+
'increase',
|
|
54
|
+
'increased',
|
|
55
|
+
'increases',
|
|
56
|
+
'increasing',
|
|
57
|
+
'increasingly',
|
|
58
|
+
'incremental',
|
|
59
|
+
'increments',
|
|
60
|
+
'incriminating',
|
|
61
|
+
'incubation',
|
|
62
|
+
'incubator',
|
|
63
|
+
'incumbent',
|
|
64
|
+
'incumbents',
|
|
65
|
+
'incur',
|
|
66
|
+
'incurred',
|
|
67
|
+
'indebted',
|
|
68
|
+
'indeed',
|
|
69
|
+
'index',
|
|
70
|
+
'indexed',
|
|
71
|
+
'indexes',
|
|
72
|
+
'indexing',
|
|
73
|
+
'indicate',
|
|
74
|
+
'indicated',
|
|
75
|
+
'indicates',
|
|
76
|
+
'indicating',
|
|
77
|
+
'indication',
|
|
78
|
+
'indications',
|
|
79
|
+
'indicative',
|
|
80
|
+
'indicator',
|
|
81
|
+
'indicators',
|
|
82
|
+
'indices',
|
|
83
|
+
'indicted',
|
|
84
|
+
'indictment',
|
|
85
|
+
'indictments',
|
|
86
|
+
'indie',
|
|
87
|
+
'indies',
|
|
88
|
+
'indigenous',
|
|
89
|
+
'indignation',
|
|
90
|
+
'indigo',
|
|
91
|
+
'indoor',
|
|
92
|
+
'indoors',
|
|
93
|
+
'induce',
|
|
94
|
+
'induced',
|
|
95
|
+
'induces',
|
|
96
|
+
'inducing',
|
|
97
|
+
'inducted',
|
|
98
|
+
'induction',
|
|
99
|
+
'indulge',
|
|
100
|
+
'indulgence',
|
|
101
|
+
'indulgent',
|
|
102
|
+
'indulging',
|
|
103
|
+
'industrial',
|
|
104
|
+
'industrialized',
|
|
105
|
+
'industries',
|
|
106
|
+
'industry',
|
|
107
|
+
'inexpensive',
|
|
108
|
+
'infancy',
|
|
109
|
+
'infant',
|
|
110
|
+
'infantry',
|
|
111
|
+
'infants',
|
|
112
|
+
'infect',
|
|
113
|
+
'infected',
|
|
114
|
+
'infection',
|
|
115
|
+
'infections',
|
|
116
|
+
'infectious',
|
|
117
|
+
'infer',
|
|
118
|
+
'inference',
|
|
119
|
+
'inferior',
|
|
120
|
+
'inferno',
|
|
121
|
+
'inferred',
|
|
122
|
+
'infertility',
|
|
123
|
+
'infestation',
|
|
124
|
+
'infested',
|
|
125
|
+
'infidelity',
|
|
126
|
+
'infield',
|
|
127
|
+
'infiltrate',
|
|
128
|
+
'infiltrated',
|
|
129
|
+
'infiltration',
|
|
130
|
+
'infinite',
|
|
131
|
+
'infinitely',
|
|
132
|
+
'infinity',
|
|
133
|
+
'infirmary',
|
|
134
|
+
'inflamed',
|
|
135
|
+
'inflammation',
|
|
136
|
+
'inflammatory',
|
|
137
|
+
'inflatable',
|
|
138
|
+
'inflate',
|
|
139
|
+
'inflated',
|
|
140
|
+
'inflation',
|
|
141
|
+
'inflict',
|
|
142
|
+
'inflicted',
|
|
143
|
+
'inflicting',
|
|
144
|
+
'influence',
|
|
145
|
+
'influenced',
|
|
146
|
+
'influencers',
|
|
147
|
+
'influences',
|
|
148
|
+
'influencing',
|
|
149
|
+
'influential',
|
|
150
|
+
'influenza',
|
|
151
|
+
'influx',
|
|
152
|
+
'info',
|
|
153
|
+
'infographic',
|
|
154
|
+
'inform',
|
|
155
|
+
'informant',
|
|
156
|
+
'informants',
|
|
157
|
+
'informatics',
|
|
158
|
+
'information',
|
|
159
|
+
'informational',
|
|
160
|
+
'informative',
|
|
161
|
+
'informed',
|
|
162
|
+
'informing',
|
|
163
|
+
'informs',
|
|
164
|
+
'infrared',
|
|
165
|
+
'infrastructure',
|
|
166
|
+
'infringed',
|
|
167
|
+
'infringement',
|
|
168
|
+
'infringing',
|
|
169
|
+
'infuriating',
|
|
170
|
+
'infused',
|
|
171
|
+
'infusion',
|
|
172
|
+
'ingenious',
|
|
173
|
+
'ingenuity',
|
|
174
|
+
'ingested',
|
|
175
|
+
'ingot',
|
|
176
|
+
'ingrained',
|
|
177
|
+
'ingredient',
|
|
178
|
+
'ingredients',
|
|
179
|
+
'inhabit',
|
|
180
|
+
'inhabitants',
|
|
181
|
+
'inhabited',
|
|
182
|
+
'inhalation',
|
|
183
|
+
'inhale',
|
|
184
|
+
'inhaled',
|
|
185
|
+
'inhaling',
|
|
186
|
+
'inherent',
|
|
187
|
+
'inherently',
|
|
188
|
+
'inheritance',
|
|
189
|
+
'inherited',
|
|
190
|
+
'initial',
|
|
191
|
+
'initially',
|
|
192
|
+
'initials',
|
|
193
|
+
'initiate',
|
|
194
|
+
'initiated',
|
|
195
|
+
'initiates',
|
|
196
|
+
'initiating',
|
|
197
|
+
'initiation',
|
|
198
|
+
'initiative',
|
|
199
|
+
'initiatives',
|
|
200
|
+
'inject',
|
|
201
|
+
'injected',
|
|
202
|
+
'injecting',
|
|
203
|
+
'injection',
|
|
204
|
+
'injections',
|
|
205
|
+
'injunction',
|
|
206
|
+
'injure',
|
|
207
|
+
'injured',
|
|
208
|
+
'injuries',
|
|
209
|
+
'injuring',
|
|
210
|
+
'injury',
|
|
211
|
+
'ink',
|
|
212
|
+
'inked',
|
|
213
|
+
'inks',
|
|
214
|
+
'inland',
|
|
215
|
+
'inlay',
|
|
216
|
+
'inlet',
|
|
217
|
+
'inmate',
|
|
218
|
+
'inmates',
|
|
219
|
+
'inn',
|
|
220
|
+
'innate',
|
|
221
|
+
'inner',
|
|
222
|
+
'inning',
|
|
223
|
+
'innings',
|
|
224
|
+
'innovate',
|
|
225
|
+
'innovation',
|
|
226
|
+
'innovations',
|
|
227
|
+
'innovative',
|
|
228
|
+
'innovator',
|
|
229
|
+
'innovators',
|
|
230
|
+
'inns',
|
|
231
|
+
'inpatient',
|
|
232
|
+
'input',
|
|
233
|
+
'inputs',
|
|
234
|
+
'inquest',
|
|
235
|
+
'inquire',
|
|
236
|
+
'inquiries',
|
|
237
|
+
'inquiry',
|
|
238
|
+
'inquisition',
|
|
239
|
+
'ins',
|
|
240
|
+
'inscribed',
|
|
241
|
+
'inscription',
|
|
242
|
+
'inscriptions',
|
|
243
|
+
'insect',
|
|
244
|
+
'insects',
|
|
245
|
+
'insert',
|
|
246
|
+
'inserted',
|
|
247
|
+
'inserting',
|
|
248
|
+
'insertion',
|
|
249
|
+
'inserts',
|
|
250
|
+
'inside',
|
|
251
|
+
'insider',
|
|
252
|
+
'insiders',
|
|
253
|
+
'insides',
|
|
254
|
+
'insidious',
|
|
255
|
+
'insight',
|
|
256
|
+
'insightful',
|
|
257
|
+
'insights',
|
|
258
|
+
'insignia',
|
|
259
|
+
'insist',
|
|
260
|
+
'insisted',
|
|
261
|
+
'insistence',
|
|
262
|
+
'insistent',
|
|
263
|
+
'insisting',
|
|
264
|
+
'insists',
|
|
265
|
+
'insofar',
|
|
266
|
+
'inspect',
|
|
267
|
+
'inspected',
|
|
268
|
+
'inspecting',
|
|
269
|
+
'inspection',
|
|
270
|
+
'inspections',
|
|
271
|
+
'inspector',
|
|
272
|
+
'inspectors',
|
|
273
|
+
'inspiration',
|
|
274
|
+
'inspirational',
|
|
275
|
+
'inspirations',
|
|
276
|
+
'inspire',
|
|
277
|
+
'inspired',
|
|
278
|
+
'inspires',
|
|
279
|
+
'inspiring',
|
|
280
|
+
'install',
|
|
281
|
+
'installation',
|
|
282
|
+
'installations',
|
|
283
|
+
'installed',
|
|
284
|
+
'installing',
|
|
285
|
+
'installment',
|
|
286
|
+
'installments',
|
|
287
|
+
'instalment',
|
|
288
|
+
'instance',
|
|
289
|
+
'instances',
|
|
290
|
+
'instant',
|
|
291
|
+
'instantaneous',
|
|
292
|
+
'instantly',
|
|
293
|
+
'instead',
|
|
294
|
+
'instigated',
|
|
295
|
+
'instinct',
|
|
296
|
+
'instinctive',
|
|
297
|
+
'instinctively',
|
|
298
|
+
'instincts',
|
|
299
|
+
'institute',
|
|
300
|
+
'instituted',
|
|
301
|
+
'institutes',
|
|
302
|
+
'institution',
|
|
303
|
+
'institutional',
|
|
304
|
+
'institutions',
|
|
305
|
+
'instruct',
|
|
306
|
+
'instructed',
|
|
307
|
+
'instructing',
|
|
308
|
+
'instruction',
|
|
309
|
+
'instructional',
|
|
310
|
+
'instructions',
|
|
311
|
+
'instructor',
|
|
312
|
+
'instructors',
|
|
313
|
+
'instrument',
|
|
314
|
+
'instrumental',
|
|
315
|
+
'instrumentation',
|
|
316
|
+
'instruments',
|
|
317
|
+
'insular',
|
|
318
|
+
'insulated',
|
|
319
|
+
'insulating',
|
|
320
|
+
'insulation',
|
|
321
|
+
'insulin',
|
|
322
|
+
'insult',
|
|
323
|
+
'insulted',
|
|
324
|
+
'insulting',
|
|
325
|
+
'insults',
|
|
326
|
+
'insurance',
|
|
327
|
+
'insure',
|
|
328
|
+
'insured',
|
|
329
|
+
'insurer',
|
|
330
|
+
'insurers',
|
|
331
|
+
'insurgency',
|
|
332
|
+
'insurgent',
|
|
333
|
+
'insurgents',
|
|
334
|
+
'insurrection',
|
|
335
|
+
'intake',
|
|
336
|
+
'integers',
|
|
337
|
+
'intel',
|
|
338
|
+
'intellect',
|
|
339
|
+
'intellectual',
|
|
340
|
+
'intellectually',
|
|
341
|
+
'intellectuals',
|
|
342
|
+
'intelligence',
|
|
343
|
+
'intelligent',
|
|
344
|
+
'intelligently',
|
|
345
|
+
'intend',
|
|
346
|
+
'intended',
|
|
347
|
+
'intending',
|
|
348
|
+
'intends',
|
|
349
|
+
'intense',
|
|
350
|
+
'intensely',
|
|
351
|
+
'intensified',
|
|
352
|
+
'intensifies',
|
|
353
|
+
'intensify',
|
|
354
|
+
'intensity',
|
|
355
|
+
'intensive',
|
|
356
|
+
'intent',
|
|
357
|
+
'intention',
|
|
358
|
+
'intentional',
|
|
359
|
+
'intentionally',
|
|
360
|
+
'intentions',
|
|
361
|
+
'inter',
|
|
362
|
+
'interact',
|
|
363
|
+
'interacted',
|
|
364
|
+
'interacting',
|
|
365
|
+
'interaction',
|
|
366
|
+
'interactions',
|
|
367
|
+
'interactive',
|
|
368
|
+
'interacts',
|
|
369
|
+
'intercept',
|
|
370
|
+
'intercepted',
|
|
371
|
+
'interception',
|
|
372
|
+
'interceptions',
|
|
373
|
+
'interchange',
|
|
374
|
+
'interchangeable',
|
|
375
|
+
'interconnected',
|
|
376
|
+
'intercourse',
|
|
377
|
+
'interest',
|
|
378
|
+
'interested',
|
|
379
|
+
'interesting',
|
|
380
|
+
'interestingly',
|
|
381
|
+
'interests',
|
|
382
|
+
'interface',
|
|
383
|
+
'interfaces',
|
|
384
|
+
'interfere',
|
|
385
|
+
'interfered',
|
|
386
|
+
'interference',
|
|
387
|
+
'interferes',
|
|
388
|
+
'interfering',
|
|
389
|
+
'interim',
|
|
390
|
+
'interior',
|
|
391
|
+
'interiors',
|
|
392
|
+
'interlude',
|
|
393
|
+
'intermediary',
|
|
394
|
+
'intermediate',
|
|
395
|
+
'intermission',
|
|
396
|
+
'intermittent',
|
|
397
|
+
'intermittently',
|
|
398
|
+
'intern',
|
|
399
|
+
'internal',
|
|
400
|
+
'internally',
|
|
401
|
+
'international',
|
|
402
|
+
'internationally',
|
|
403
|
+
'internationals',
|
|
404
|
+
'interns',
|
|
405
|
+
'internship',
|
|
406
|
+
'internships',
|
|
407
|
+
'interpersonal',
|
|
408
|
+
'interplay',
|
|
409
|
+
'interpret',
|
|
410
|
+
'interpretation',
|
|
411
|
+
'interpretations',
|
|
412
|
+
'interpreted',
|
|
413
|
+
'interpreter',
|
|
414
|
+
'interpreters',
|
|
415
|
+
'interpreting',
|
|
416
|
+
'interpretive',
|
|
417
|
+
'interracial',
|
|
418
|
+
'interrogated',
|
|
419
|
+
'interrogation',
|
|
420
|
+
'interrupt',
|
|
421
|
+
'interrupted',
|
|
422
|
+
'interrupting',
|
|
423
|
+
'interruption',
|
|
424
|
+
'interruptions',
|
|
425
|
+
'interrupts',
|
|
426
|
+
'intersect',
|
|
427
|
+
'intersection',
|
|
428
|
+
'intersections',
|
|
429
|
+
'interspersed',
|
|
430
|
+
'interstate',
|
|
431
|
+
'interstellar',
|
|
432
|
+
'intertwined',
|
|
433
|
+
'interval',
|
|
434
|
+
'intervals',
|
|
435
|
+
'intervene',
|
|
436
|
+
'intervened',
|
|
437
|
+
'intervening',
|
|
438
|
+
'intervention',
|
|
439
|
+
'interventions',
|
|
440
|
+
'interview',
|
|
441
|
+
'interviewed',
|
|
442
|
+
'interviewer',
|
|
443
|
+
'interviewing',
|
|
444
|
+
'interviews',
|
|
445
|
+
'intestinal',
|
|
446
|
+
'intestine',
|
|
447
|
+
'intestines',
|
|
448
|
+
'intimacy',
|
|
449
|
+
'intimate',
|
|
450
|
+
'intimately',
|
|
451
|
+
'intimidate',
|
|
452
|
+
'intimidated',
|
|
453
|
+
'intimidating',
|
|
454
|
+
'intimidation',
|
|
455
|
+
'into',
|
|
456
|
+
'intoxicated',
|
|
457
|
+
'intoxication',
|
|
458
|
+
'intracellular',
|
|
459
|
+
'intravenous',
|
|
460
|
+
'intricate',
|
|
461
|
+
'intrigue',
|
|
462
|
+
'intrigued',
|
|
463
|
+
'intriguing',
|
|
464
|
+
'intrinsic',
|
|
465
|
+
'intrinsically',
|
|
466
|
+
'intro',
|
|
467
|
+
'introduce',
|
|
468
|
+
'introduced',
|
|
469
|
+
'introduces',
|
|
470
|
+
'introducing',
|
|
471
|
+
'introduction',
|
|
472
|
+
'introductions',
|
|
473
|
+
'introductory',
|
|
474
|
+
'intruder',
|
|
475
|
+
'intruders',
|
|
476
|
+
'intrusion',
|
|
477
|
+
'intrusive',
|
|
478
|
+
'intuition',
|
|
479
|
+
'intuitive',
|
|
480
|
+
'intuitively',
|
|
481
|
+
'inundated',
|
|
482
|
+
'invade',
|
|
483
|
+
'invaded',
|
|
484
|
+
'invaders',
|
|
485
|
+
'invading',
|
|
486
|
+
'invasion',
|
|
487
|
+
'invasions',
|
|
488
|
+
'invasive',
|
|
489
|
+
'invent',
|
|
490
|
+
'invented',
|
|
491
|
+
'inventing',
|
|
492
|
+
'invention',
|
|
493
|
+
'inventions',
|
|
494
|
+
'inventive',
|
|
495
|
+
'inventor',
|
|
496
|
+
'inventories',
|
|
497
|
+
'inventors',
|
|
498
|
+
'inventory',
|
|
499
|
+
'inverness',
|
|
500
|
+
'inverse',
|
|
501
|
+
'inversion',
|
|
502
|
+
'inverted',
|
|
503
|
+
'invest',
|
|
504
|
+
'invested',
|
|
505
|
+
'investigate',
|
|
506
|
+
'investigated',
|
|
507
|
+
'investigates',
|
|
508
|
+
'investigating',
|
|
509
|
+
'investigation',
|
|
510
|
+
'investigations',
|
|
511
|
+
'investigative',
|
|
512
|
+
'investigator',
|
|
513
|
+
'investigators',
|
|
514
|
+
'investing',
|
|
515
|
+
'investment',
|
|
516
|
+
'investments',
|
|
517
|
+
'investor',
|
|
518
|
+
'investors',
|
|
519
|
+
'invests',
|
|
520
|
+
'invitation',
|
|
521
|
+
'invitational',
|
|
522
|
+
'invitations',
|
|
523
|
+
'invite',
|
|
524
|
+
'invited',
|
|
525
|
+
'invites',
|
|
526
|
+
'inviting',
|
|
527
|
+
'invoice',
|
|
528
|
+
'invoices',
|
|
529
|
+
'invoke',
|
|
530
|
+
'invoked',
|
|
531
|
+
'invoking',
|
|
532
|
+
'involve',
|
|
533
|
+
'involved',
|
|
534
|
+
'involvement',
|
|
535
|
+
'involves',
|
|
536
|
+
'involving',
|
|
537
|
+
'inward',
|
|
538
|
+
'init',
|
|
539
|
+
'initial',
|
|
540
|
+
'initialization',
|
|
541
|
+
'initialize',
|
|
542
|
+
'initialized',
|
|
543
|
+
'initializing',
|
|
544
|
+
'initializes',
|
|
545
|
+
'initializing',
|
|
546
|
+
'initializes',
|
|
547
|
+
];
|
|
548
|
+
const NO_EXCEPTIONS = [
|
|
549
|
+
'nobility',
|
|
550
|
+
'noble',
|
|
551
|
+
'nobleman',
|
|
552
|
+
'nobles',
|
|
553
|
+
'nobly',
|
|
554
|
+
'nocturnal',
|
|
555
|
+
'nod',
|
|
556
|
+
'nodded',
|
|
557
|
+
'nodding',
|
|
558
|
+
'node',
|
|
559
|
+
'nodes',
|
|
560
|
+
'nods',
|
|
561
|
+
'noel',
|
|
562
|
+
'noir',
|
|
563
|
+
'noise',
|
|
564
|
+
'noises',
|
|
565
|
+
'noisy',
|
|
566
|
+
'nomad',
|
|
567
|
+
'nomadic',
|
|
568
|
+
'nomenclature',
|
|
569
|
+
'nominal',
|
|
570
|
+
'nominally',
|
|
571
|
+
'nominate',
|
|
572
|
+
'nominated',
|
|
573
|
+
'nominating',
|
|
574
|
+
'nomination',
|
|
575
|
+
'nominations',
|
|
576
|
+
'nominee',
|
|
577
|
+
'nominees',
|
|
578
|
+
'noodle',
|
|
579
|
+
'noodles',
|
|
580
|
+
'nook',
|
|
581
|
+
'noon',
|
|
582
|
+
'noose',
|
|
583
|
+
'norM',
|
|
584
|
+
'norma',
|
|
585
|
+
'normal',
|
|
586
|
+
'normalized',
|
|
587
|
+
'normally',
|
|
588
|
+
'normative',
|
|
589
|
+
'norms',
|
|
590
|
+
'north',
|
|
591
|
+
'northbound',
|
|
592
|
+
'northeast',
|
|
593
|
+
'northeastern',
|
|
594
|
+
'northern',
|
|
595
|
+
'northward',
|
|
596
|
+
'northwest',
|
|
597
|
+
'northwestern',
|
|
598
|
+
'nose',
|
|
599
|
+
'nosey',
|
|
600
|
+
'nostalgia',
|
|
601
|
+
'nostalgic',
|
|
602
|
+
'nostrils',
|
|
603
|
+
'notable',
|
|
604
|
+
'notably',
|
|
605
|
+
'notary',
|
|
606
|
+
'notation',
|
|
607
|
+
'notch',
|
|
608
|
+
'notched',
|
|
609
|
+
'notebook',
|
|
610
|
+
'notebooks',
|
|
611
|
+
'noted',
|
|
612
|
+
'notes',
|
|
613
|
+
'noteworthy',
|
|
614
|
+
'notice',
|
|
615
|
+
'noticeable',
|
|
616
|
+
'noticeably',
|
|
617
|
+
'noticed',
|
|
618
|
+
'notices',
|
|
619
|
+
'noticing',
|
|
620
|
+
'notification',
|
|
621
|
+
'notifications',
|
|
622
|
+
'notified',
|
|
623
|
+
'notify',
|
|
624
|
+
'notifying',
|
|
625
|
+
'notion',
|
|
626
|
+
'notions',
|
|
627
|
+
'notoriety',
|
|
628
|
+
'notorious',
|
|
629
|
+
'notoriously',
|
|
630
|
+
'noun',
|
|
631
|
+
'nouns',
|
|
632
|
+
'nourishment',
|
|
633
|
+
'nouveau',
|
|
634
|
+
'nova',
|
|
635
|
+
'novel',
|
|
636
|
+
'novelist',
|
|
637
|
+
'novelists',
|
|
638
|
+
'novella',
|
|
639
|
+
'novels',
|
|
640
|
+
'novelty',
|
|
641
|
+
'novice',
|
|
642
|
+
'now',
|
|
643
|
+
'nowadays',
|
|
644
|
+
'nozzle',
|
|
645
|
+
];
|
|
646
|
+
const UN_EXCEPTIONS = [
|
|
647
|
+
'unanimous',
|
|
648
|
+
'unanimously',
|
|
649
|
+
'uncle',
|
|
650
|
+
'uncles',
|
|
651
|
+
'under',
|
|
652
|
+
'underage',
|
|
653
|
+
'undercover',
|
|
654
|
+
'undercut',
|
|
655
|
+
'underdog',
|
|
656
|
+
'underestimate',
|
|
657
|
+
'underestimated',
|
|
658
|
+
'undergo',
|
|
659
|
+
'undergoes',
|
|
660
|
+
'undergoing',
|
|
661
|
+
'undergone',
|
|
662
|
+
'undergraduate',
|
|
663
|
+
'undergraduates',
|
|
664
|
+
'underground',
|
|
665
|
+
'underlined',
|
|
666
|
+
'underlying',
|
|
667
|
+
'undermine',
|
|
668
|
+
'undermined',
|
|
669
|
+
'undermines',
|
|
670
|
+
'undermining',
|
|
671
|
+
'underneath',
|
|
672
|
+
'underrated',
|
|
673
|
+
'underside',
|
|
674
|
+
'understand',
|
|
675
|
+
'understandable',
|
|
676
|
+
'understandably',
|
|
677
|
+
'understanding',
|
|
678
|
+
'understands',
|
|
679
|
+
'understated',
|
|
680
|
+
'understatement',
|
|
681
|
+
'understood',
|
|
682
|
+
'undertake',
|
|
683
|
+
'undertaken',
|
|
684
|
+
'undertaker',
|
|
685
|
+
'undertaking',
|
|
686
|
+
'undertook',
|
|
687
|
+
'underwater',
|
|
688
|
+
'underway',
|
|
689
|
+
'underwear',
|
|
690
|
+
'underwent',
|
|
691
|
+
'underwood',
|
|
692
|
+
'underworld',
|
|
693
|
+
'underwriting',
|
|
694
|
+
'unicorn',
|
|
695
|
+
'unicorns',
|
|
696
|
+
'unification',
|
|
697
|
+
'unified',
|
|
698
|
+
'uniform',
|
|
699
|
+
'uniformed',
|
|
700
|
+
'uniformity',
|
|
701
|
+
'uniformly',
|
|
702
|
+
'uniforms',
|
|
703
|
+
'unify',
|
|
704
|
+
'unifying',
|
|
705
|
+
'unilateral',
|
|
706
|
+
'unilaterally',
|
|
707
|
+
'union',
|
|
708
|
+
'unionist',
|
|
709
|
+
'unionists',
|
|
710
|
+
'unions',
|
|
711
|
+
'unique',
|
|
712
|
+
'uniquely',
|
|
713
|
+
'uniqueness',
|
|
714
|
+
'unison',
|
|
715
|
+
'unit',
|
|
716
|
+
'unitary',
|
|
717
|
+
'unite',
|
|
718
|
+
'united',
|
|
719
|
+
'unites',
|
|
720
|
+
'uniting',
|
|
721
|
+
'units',
|
|
722
|
+
'unity',
|
|
723
|
+
'universal',
|
|
724
|
+
'universally',
|
|
725
|
+
'universe',
|
|
726
|
+
'universes',
|
|
727
|
+
'universities',
|
|
728
|
+
'university',
|
|
729
|
+
'unless',
|
|
730
|
+
'until',
|
|
731
|
+
'unto',
|
|
732
|
+
];
|
|
733
|
+
const DIS_EXCEPTIONS = [
|
|
734
|
+
'disc',
|
|
735
|
+
'disciple',
|
|
736
|
+
'disciples',
|
|
737
|
+
'disciplinary',
|
|
738
|
+
'discipline',
|
|
739
|
+
'disciplined',
|
|
740
|
+
'disciplines',
|
|
741
|
+
'disco',
|
|
742
|
+
'discography',
|
|
743
|
+
'discern',
|
|
744
|
+
'discerning',
|
|
745
|
+
'discourse',
|
|
746
|
+
'discreet',
|
|
747
|
+
'discreetly',
|
|
748
|
+
'discrepancies',
|
|
749
|
+
'discrepancy',
|
|
750
|
+
'discrete',
|
|
751
|
+
'discretion',
|
|
752
|
+
'discretionary',
|
|
753
|
+
'discriminate',
|
|
754
|
+
'discriminated',
|
|
755
|
+
'discriminating',
|
|
756
|
+
'discrimination',
|
|
757
|
+
'discriminatory',
|
|
758
|
+
'discs',
|
|
759
|
+
'discuss',
|
|
760
|
+
'discussed',
|
|
761
|
+
'discusses',
|
|
762
|
+
'discussing',
|
|
763
|
+
'discussion',
|
|
764
|
+
'discussions',
|
|
765
|
+
'disengage',
|
|
766
|
+
'disparate',
|
|
767
|
+
'dispensary',
|
|
768
|
+
'dispense',
|
|
769
|
+
'dispenser',
|
|
770
|
+
'dispensing',
|
|
771
|
+
'disperse',
|
|
772
|
+
'dispersed',
|
|
773
|
+
'dispersion',
|
|
774
|
+
'disposition',
|
|
775
|
+
'disseminate',
|
|
776
|
+
'dissemination',
|
|
777
|
+
'dissertation',
|
|
778
|
+
'dissident',
|
|
779
|
+
'dissidents',
|
|
780
|
+
'dissimilar',
|
|
781
|
+
'dissipated',
|
|
782
|
+
'dissolution',
|
|
783
|
+
'dissolve',
|
|
784
|
+
'dissolved',
|
|
785
|
+
'dissolving',
|
|
786
|
+
'distal',
|
|
787
|
+
'distance',
|
|
788
|
+
'distances',
|
|
789
|
+
'distancing',
|
|
790
|
+
'distant',
|
|
791
|
+
'distillation',
|
|
792
|
+
'distilled',
|
|
793
|
+
'distillery',
|
|
794
|
+
'distinct',
|
|
795
|
+
'distinction',
|
|
796
|
+
'distinctions',
|
|
797
|
+
'distinctive',
|
|
798
|
+
'distinctly',
|
|
799
|
+
'distinguish',
|
|
800
|
+
'distinguished',
|
|
801
|
+
'distinguishes',
|
|
802
|
+
'distinguishing',
|
|
803
|
+
'distort',
|
|
804
|
+
'distorted',
|
|
805
|
+
'distortion',
|
|
806
|
+
'distortions',
|
|
807
|
+
'distract',
|
|
808
|
+
'distracted',
|
|
809
|
+
'distracting',
|
|
810
|
+
'distraction',
|
|
811
|
+
'distractions',
|
|
812
|
+
'distraught',
|
|
813
|
+
'distribute',
|
|
814
|
+
'distributed',
|
|
815
|
+
'distributes',
|
|
816
|
+
'distributing',
|
|
817
|
+
'distribution',
|
|
818
|
+
'distributions',
|
|
819
|
+
'distributor',
|
|
820
|
+
'distributors',
|
|
821
|
+
'district',
|
|
822
|
+
'districts',
|
|
823
|
+
'dismal',
|
|
824
|
+
'disaster',
|
|
825
|
+
'disasters',
|
|
826
|
+
'disastrous',
|
|
827
|
+
];
|
|
8
828
|
// Words that contain negative prefixes but should be treated as valid
|
|
9
|
-
const EXCEPTION_WORDS = [
|
|
829
|
+
const EXCEPTION_WORDS = [
|
|
830
|
+
...IN_EXCEPTIONS,
|
|
831
|
+
...NO_EXCEPTIONS,
|
|
832
|
+
...UN_EXCEPTIONS,
|
|
833
|
+
...DIS_EXCEPTIONS,
|
|
834
|
+
];
|
|
835
|
+
/**
|
|
836
|
+
* Splits a variable name into individual words based on naming conventions:
|
|
837
|
+
* - camelCase or PascalCase: split on uppercase letters
|
|
838
|
+
* - SCREAMING_SNAKE_CASE: split on underscores
|
|
839
|
+
* @param name Variable name to split
|
|
840
|
+
* @returns Array of individual words in lowercase
|
|
841
|
+
*/
|
|
842
|
+
function splitNameIntoWords(name) {
|
|
843
|
+
// Handle SCREAMING_SNAKE_CASE
|
|
844
|
+
if (name.includes('_')) {
|
|
845
|
+
return name.toLowerCase().split('_').filter(Boolean);
|
|
846
|
+
}
|
|
847
|
+
// Handle camelCase and PascalCase
|
|
848
|
+
// Add space before uppercase letters and then split
|
|
849
|
+
const spacedName = name.replace(/([A-Z])/g, ' $1');
|
|
850
|
+
return spacedName.toLowerCase().trim().split(/\s+/).filter(Boolean);
|
|
851
|
+
}
|
|
10
852
|
// Map of negative boolean terms to suggested positive alternatives
|
|
11
853
|
const BOOLEAN_POSITIVE_ALTERNATIVES = {
|
|
12
|
-
// Boolean prefixes
|
|
854
|
+
// Boolean prefixes - These will be removed from suggestions
|
|
13
855
|
isNot: ['is'],
|
|
14
856
|
isUn: ['is'],
|
|
15
857
|
isDis: ['is'],
|
|
@@ -21,6 +863,28 @@ const BOOLEAN_POSITIVE_ALTERNATIVES = {
|
|
|
21
863
|
shouldNot: ['should'],
|
|
22
864
|
willNot: ['will'],
|
|
23
865
|
doesNot: ['does'],
|
|
866
|
+
IsNot: ['Is'],
|
|
867
|
+
IsUn: ['Is'],
|
|
868
|
+
IsDis: ['Is'],
|
|
869
|
+
IsIn: ['Is'],
|
|
870
|
+
IsNon: ['Is'],
|
|
871
|
+
HasNo: ['Has'],
|
|
872
|
+
HasNot: ['Has'],
|
|
873
|
+
CanNot: ['Can'],
|
|
874
|
+
ShouldNot: ['Should'],
|
|
875
|
+
WillNot: ['Will'],
|
|
876
|
+
DoesNot: ['Does'],
|
|
877
|
+
IS_NOT: ['IS'],
|
|
878
|
+
IS_UN: ['IS'],
|
|
879
|
+
IS_DIS: ['IS'],
|
|
880
|
+
IS_IN: ['IS'],
|
|
881
|
+
IS_NON: ['IS'],
|
|
882
|
+
HAS_NO: ['HAS'],
|
|
883
|
+
HAS_NOT: ['HAS'],
|
|
884
|
+
CAN_NOT: ['CAN'],
|
|
885
|
+
SHOULD_NOT: ['SHOULD'],
|
|
886
|
+
WILL_NOT: ['WILL'],
|
|
887
|
+
DOES_NOT: ['DOES'],
|
|
24
888
|
};
|
|
25
889
|
exports.enforcePositiveNaming = (0, createRule_1.createRule)({
|
|
26
890
|
name: 'enforce-positive-naming',
|
|
@@ -63,46 +927,98 @@ exports.enforcePositiveNaming = (0, createRule_1.createRule)({
|
|
|
63
927
|
alternatives: BOOLEAN_POSITIVE_ALTERNATIVES[name],
|
|
64
928
|
};
|
|
65
929
|
}
|
|
930
|
+
// Split the name into words
|
|
931
|
+
const words = splitNameIntoWords(name);
|
|
932
|
+
// Check if this follows the pattern IS_NOT_SOMETHING or HAS_NO_SOMETHING
|
|
933
|
+
const secondWord = words[1].toLowerCase();
|
|
934
|
+
if (EXCEPTION_WORDS.some((exception) => secondWord === exception.toLowerCase())) {
|
|
935
|
+
return { isNegative: false, alternatives: [] };
|
|
936
|
+
}
|
|
937
|
+
const nameLowercase = name.toLowerCase();
|
|
66
938
|
// Check for negative prefixes in boolean-like variables
|
|
67
|
-
if (
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
//
|
|
74
|
-
for (const exceptionWord of EXCEPTION_WORDS) {
|
|
75
|
-
const lowerCaseName = name.toLowerCase();
|
|
76
|
-
if (lowerCaseName.includes(exceptionWord.toLowerCase())) {
|
|
77
|
-
return { isNegative: false, alternatives: [] };
|
|
78
|
-
}
|
|
79
|
-
}
|
|
939
|
+
if (nameLowercase.startsWith('is') ||
|
|
940
|
+
nameLowercase.startsWith('has') ||
|
|
941
|
+
nameLowercase.startsWith('can') ||
|
|
942
|
+
nameLowercase.startsWith('should') ||
|
|
943
|
+
nameLowercase.startsWith('will') ||
|
|
944
|
+
nameLowercase.startsWith('does')) {
|
|
945
|
+
// We already checked exception words above, so no need to check again
|
|
80
946
|
for (const prefix of BOOLEAN_NEGATIVE_PREFIXES) {
|
|
947
|
+
const prefixCapitalized = prefix.charAt(0).toUpperCase() + prefix.slice(1);
|
|
948
|
+
const prefixUppercase = prefix.toUpperCase();
|
|
81
949
|
// Check for patterns like isNot, hasNo, canNot, etc.
|
|
82
950
|
const prefixPatterns = [
|
|
83
951
|
{
|
|
84
|
-
pattern: new RegExp(`^is${
|
|
85
|
-
key: `is${
|
|
952
|
+
pattern: new RegExp(`^is${prefixCapitalized}`, 'i'),
|
|
953
|
+
key: `is${prefixCapitalized}`,
|
|
954
|
+
},
|
|
955
|
+
{
|
|
956
|
+
pattern: new RegExp(`^has${prefixCapitalized}`, 'i'),
|
|
957
|
+
key: `has${prefixCapitalized}`,
|
|
958
|
+
},
|
|
959
|
+
{
|
|
960
|
+
pattern: new RegExp(`^can${prefixCapitalized}`, 'i'),
|
|
961
|
+
key: `can${prefixCapitalized}`,
|
|
962
|
+
},
|
|
963
|
+
{
|
|
964
|
+
pattern: new RegExp(`^should${prefixCapitalized}`, 'i'),
|
|
965
|
+
key: `should${prefixCapitalized}`,
|
|
966
|
+
},
|
|
967
|
+
{
|
|
968
|
+
pattern: new RegExp(`^will${prefixCapitalized}`, 'i'),
|
|
969
|
+
key: `will${prefixCapitalized}`,
|
|
970
|
+
},
|
|
971
|
+
{
|
|
972
|
+
pattern: new RegExp(`^does${prefixCapitalized}`, 'i'),
|
|
973
|
+
key: `does${prefixCapitalized}`,
|
|
974
|
+
},
|
|
975
|
+
{
|
|
976
|
+
pattern: new RegExp(`^Is${prefixCapitalized}`, 'i'),
|
|
977
|
+
key: `Is${prefixCapitalized}`,
|
|
978
|
+
},
|
|
979
|
+
{
|
|
980
|
+
pattern: new RegExp(`^Has${prefixCapitalized}`, 'i'),
|
|
981
|
+
key: `Has${prefixCapitalized}`,
|
|
982
|
+
},
|
|
983
|
+
{
|
|
984
|
+
pattern: new RegExp(`^Can${prefixCapitalized}`, 'i'),
|
|
985
|
+
key: `Can${prefixCapitalized}`,
|
|
986
|
+
},
|
|
987
|
+
{
|
|
988
|
+
pattern: new RegExp(`^Should${prefixCapitalized}`, 'i'),
|
|
989
|
+
key: `Should${prefixCapitalized}`,
|
|
990
|
+
},
|
|
991
|
+
{
|
|
992
|
+
pattern: new RegExp(`^Will${prefixCapitalized}`, 'i'),
|
|
993
|
+
key: `Will${prefixCapitalized}`,
|
|
994
|
+
},
|
|
995
|
+
{
|
|
996
|
+
pattern: new RegExp(`^Does${prefixCapitalized}`, 'i'),
|
|
997
|
+
key: `Does${prefixCapitalized}`,
|
|
998
|
+
},
|
|
999
|
+
{
|
|
1000
|
+
pattern: new RegExp(`^IS_${prefixUppercase}`, 'i'),
|
|
1001
|
+
key: `IS_${prefixUppercase}`,
|
|
86
1002
|
},
|
|
87
1003
|
{
|
|
88
|
-
pattern: new RegExp(`^
|
|
89
|
-
key: `
|
|
1004
|
+
pattern: new RegExp(`^HAS_${prefixUppercase}`, 'i'),
|
|
1005
|
+
key: `HAS_${prefixUppercase}`,
|
|
90
1006
|
},
|
|
91
1007
|
{
|
|
92
|
-
pattern: new RegExp(`^
|
|
93
|
-
key: `
|
|
1008
|
+
pattern: new RegExp(`^CAN_${prefixUppercase}`, 'i'),
|
|
1009
|
+
key: `CAN_${prefixUppercase}`,
|
|
94
1010
|
},
|
|
95
1011
|
{
|
|
96
|
-
pattern: new RegExp(`^
|
|
97
|
-
key: `
|
|
1012
|
+
pattern: new RegExp(`^SHOULD_${prefixUppercase}`, 'i'),
|
|
1013
|
+
key: `SHOULD_${prefixUppercase}`,
|
|
98
1014
|
},
|
|
99
1015
|
{
|
|
100
|
-
pattern: new RegExp(`^
|
|
101
|
-
key: `
|
|
1016
|
+
pattern: new RegExp(`^WILL_${prefixUppercase}`, 'i'),
|
|
1017
|
+
key: `WILL_${prefixUppercase}`,
|
|
102
1018
|
},
|
|
103
1019
|
{
|
|
104
|
-
pattern: new RegExp(`^
|
|
105
|
-
key: `
|
|
1020
|
+
pattern: new RegExp(`^DOES_${prefixUppercase}`, 'i'),
|
|
1021
|
+
key: `DOES_${prefixUppercase}`,
|
|
106
1022
|
},
|
|
107
1023
|
];
|
|
108
1024
|
for (const { pattern, key } of prefixPatterns) {
|
|
@@ -37,7 +37,7 @@ exports.noCompositingLayerProps = (0, createRule_1.createRule)({
|
|
|
37
37
|
meta: {
|
|
38
38
|
type: 'suggestion',
|
|
39
39
|
docs: {
|
|
40
|
-
description: 'Warn when using CSS properties that trigger compositing layers, which can impact performance. Properties like transform, opacity, filter, and will-change create new GPU layers. While sometimes beneficial for animations, excessive layer creation can increase memory usage and hurt performance. Consider alternatives or explicitly document intentional layer promotion.',
|
|
40
|
+
description: 'Warn when using CSS properties that trigger compositing layers, which can impact performance. Properties like transform, opacity, filter, and will-change create new GPU layers. While sometimes beneficial for animations, excessive layer creation can increase memory usage and hurt performance. This rule checks both regular style objects and MUI sx props. Consider alternatives or explicitly document intentional layer promotion.',
|
|
41
41
|
recommended: 'error',
|
|
42
42
|
},
|
|
43
43
|
schema: [],
|
|
@@ -79,7 +79,7 @@ exports.noCompositingLayerProps = (0, createRule_1.createRule)({
|
|
|
79
79
|
// Check for JSX style attribute
|
|
80
80
|
if (current.parent.type === utils_1.AST_NODE_TYPES.JSXAttribute &&
|
|
81
81
|
current.parent.name.type === utils_1.AST_NODE_TYPES.JSXIdentifier &&
|
|
82
|
-
current.parent.name.name === 'style') {
|
|
82
|
+
(current.parent.name.name === 'style' || current.parent.name.name === 'sx')) {
|
|
83
83
|
return true;
|
|
84
84
|
}
|
|
85
85
|
// Check for style-related variable names or properties
|
|
@@ -91,7 +91,7 @@ exports.noCompositingLayerProps = (0, createRule_1.createRule)({
|
|
|
91
91
|
// Check for style-related object property assignments
|
|
92
92
|
if (current.parent.type === utils_1.AST_NODE_TYPES.Property &&
|
|
93
93
|
current.parent.key.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
94
|
-
/style/i.test(current.parent.key.name)) {
|
|
94
|
+
(/style/i.test(current.parent.key.name) || current.parent.key.name === 'sx')) {
|
|
95
95
|
return true;
|
|
96
96
|
}
|
|
97
97
|
// Skip if we're in a TypeScript type definition
|
|
@@ -142,9 +142,9 @@ exports.noCompositingLayerProps = (0, createRule_1.createRule)({
|
|
|
142
142
|
return;
|
|
143
143
|
checkNode(node);
|
|
144
144
|
},
|
|
145
|
-
// Handle JSX style attributes
|
|
145
|
+
// Handle JSX style and sx attributes
|
|
146
146
|
JSXAttribute(node) {
|
|
147
|
-
if (node.name.name !== 'style')
|
|
147
|
+
if (node.name.name !== 'style' && node.name.name !== 'sx')
|
|
148
148
|
return;
|
|
149
149
|
if (node.value?.type === utils_1.AST_NODE_TYPES.JSXExpressionContainer &&
|
|
150
150
|
node.value.expression.type === utils_1.AST_NODE_TYPES.ObjectExpression) {
|