@agilebot/eslint-plugin 0.3.5 → 0.3.7

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license @agilebot/eslint-plugin v0.3.5
2
+ * @license @agilebot/eslint-plugin v0.3.7
3
3
  *
4
4
  * Copyright (c) Agilebot, Inc. and its affiliates.
5
5
  *
@@ -33,7 +33,7 @@ function _interopNamespaceDefault(e) {
33
33
  var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
34
34
  var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
35
35
 
36
- var enforceIconAlias = {
36
+ var enforceMuiIconAlias = {
37
37
  meta: {
38
38
  type: 'problem',
39
39
  docs: {
@@ -49,10 +49,7 @@ var enforceIconAlias = {
49
49
  create(context) {
50
50
  return {
51
51
  ImportDeclaration(node) {
52
- if (
53
- node.source.value !== '@mui/icons-material' &&
54
- node.source.value !== 'mdi-material-ui'
55
- ) {
52
+ if (node.source.value !== '@mui/icons-material' && node.source.value !== 'mdi-material-ui') {
56
53
  return;
57
54
  }
58
55
  for (const specifier of node.specifiers) {
@@ -66,11 +63,7 @@ var enforceIconAlias = {
66
63
  data: {
67
64
  name: node.source.value
68
65
  },
69
- fix: fixer =>
70
- fixer.replaceText(
71
- specifier,
72
- `${specifier.imported.name} as ${specifier.imported.name}Icon`
73
- )
66
+ fix: fixer => fixer.replaceText(specifier, "".concat(specifier.imported.name, " as ").concat(specifier.imported.name, "Icon"))
74
67
  });
75
68
  }
76
69
  }
@@ -80,11 +73,19 @@ var enforceIconAlias = {
80
73
  };
81
74
 
82
75
  function getSetting(context, name) {
83
- return context.settings[`agilebot/${name}`];
76
+ return context.settings["agilebot/".concat(name)];
84
77
  }
85
78
 
86
- let warnedForMissingPrefix = false;
87
- var monorepo = {
79
+ const warned = new Set();
80
+ function warnOnce(message) {
81
+ if (warned.has(message)) {
82
+ return;
83
+ }
84
+ warned.add(message);
85
+ console.warn("Warning: ".concat(message));
86
+ }
87
+
88
+ var importMonorepo = {
88
89
  meta: {
89
90
  type: 'problem',
90
91
  docs: {
@@ -102,13 +103,10 @@ var monorepo = {
102
103
  ImportDeclaration(node) {
103
104
  let prefix = getSetting(context, 'monorepo-scope');
104
105
  if (!prefix) {
105
- if (!warnedForMissingPrefix) {
106
- console.error('Warning: agilebot/monorepo-scope is not set.');
107
- warnedForMissingPrefix = true;
108
- }
106
+ warnOnce('agilebot/monorepo-scope is not set.');
109
107
  return;
110
108
  }
111
- prefix = `${prefix}/`;
109
+ prefix = "".concat(prefix, "/");
112
110
  if (typeof node.source.value !== 'string') {
113
111
  return;
114
112
  }
@@ -124,10 +122,8 @@ var monorepo = {
124
122
  module: node.source.value
125
123
  },
126
124
  fix: fixer => {
127
- const correctedPath = values
128
- .filter((_, index) => index !== 2)
129
- .join('/');
130
- return fixer.replaceText(node.source, `'${correctedPath}'`);
125
+ const correctedPath = values.filter((_, index) => index !== 2).join('/');
126
+ return fixer.replaceText(node.source, "'".concat(correctedPath, "'"));
131
127
  }
132
128
  });
133
129
  }
@@ -137,74 +133,33 @@ var monorepo = {
137
133
  };
138
134
 
139
135
  function findFormatMessageAttrNode(node, attrName) {
140
- if (
141
- node.type === 'CallExpression' &&
142
- (node.callee.name === 'formatMessage' || node.callee.name === '$t') &&
143
- node.arguments.length > 0 &&
144
- node.arguments[0].properties
145
- ) {
146
- return node.arguments[0].properties.find(
147
- a => a.key && a.key.name === attrName
148
- );
136
+ if (node.type === 'CallExpression' && (node.callee.name === 'formatMessage' || node.callee.name === '$t') && node.arguments.length > 0 && node.arguments[0].properties) {
137
+ return node.arguments[0].properties.find(a => a.key && a.key.name === attrName);
149
138
  }
150
- if (
151
- node.type === 'CallExpression' &&
152
- node.callee.type === 'MemberExpression' &&
153
- (node.callee.object.name === 'intl' ||
154
- (node.callee.object.name && node.callee.object.name.endsWith('Intl'))) &&
155
- (node.callee.property.name === 'formatMessage' ||
156
- node.callee.property.name === '$t')
157
- ) {
158
- return node.arguments[0].properties.find(
159
- a => a.key && a.key.name === attrName
160
- );
139
+ if (node.type === 'CallExpression' && node.callee.type === 'MemberExpression' && (node.callee.object.name === 'intl' || node.callee.object.name && node.callee.object.name.endsWith('Intl')) && (node.callee.property.name === 'formatMessage' || node.callee.property.name === '$t')) {
140
+ return node.arguments[0].properties.find(a => a.key && a.key.name === attrName);
161
141
  }
162
142
  }
163
143
  function findFormattedMessageAttrNode(node, attrName) {
164
- if (
165
- node.type === 'JSXIdentifier' &&
166
- node.name === 'FormattedMessage' &&
167
- node.parent &&
168
- node.parent.type === 'JSXOpeningElement'
169
- ) {
144
+ if (node.type === 'JSXIdentifier' && node.name === 'FormattedMessage' && node.parent && node.parent.type === 'JSXOpeningElement') {
170
145
  return node.parent.attributes.find(a => a.name && a.name.name === attrName);
171
146
  }
172
147
  }
173
148
  function findAttrNodeInDefineMessages(node, attrName) {
174
- if (
175
- node.type === 'Property' &&
176
- node.key.name === attrName &&
177
- node.parent &&
178
- node.parent.parent &&
179
- node.parent.parent.parent &&
180
- node.parent.parent.parent.parent &&
181
- node.parent.parent.parent.parent.type === 'CallExpression' &&
182
- node.parent.parent.parent.parent.callee.name === 'defineMessages'
183
- ) {
149
+ if (node.type === 'Property' && node.key.name === attrName && node.parent && node.parent.parent && node.parent.parent.parent && node.parent.parent.parent.parent && node.parent.parent.parent.parent.type === 'CallExpression' && node.parent.parent.parent.parent.callee.name === 'defineMessages') {
184
150
  return node;
185
151
  }
186
152
  }
187
153
  function findAttrNodeInDefineMessage(node, attrName) {
188
- if (
189
- node.type === 'Property' &&
190
- node.key.name === attrName &&
191
- node.parent &&
192
- node.parent.parent &&
193
- node.parent.parent.type === 'CallExpression' &&
194
- node.parent.parent.callee.name === 'defineMessage'
195
- ) {
154
+ if (node.type === 'Property' && node.key.name === attrName && node.parent && node.parent.parent && node.parent.parent.type === 'CallExpression' && node.parent.parent.callee.name === 'defineMessage') {
196
155
  return node;
197
156
  }
198
157
  }
199
158
  function sortedTemplateElements(node) {
200
- return [...node.quasis, ...node.expressions].sort(
201
- (a, b) => a.range[0] - b.range[0]
202
- );
159
+ return [...node.quasis, ...node.expressions].sort((a, b) => a.range[0] - b.range[0]);
203
160
  }
204
161
  function templateLiteralDisplayStr(node) {
205
- return sortedTemplateElements(node)
206
- .map(e => (!e.value ? '*' : e.value.raw))
207
- .join('');
162
+ return sortedTemplateElements(node).map(e => !e.value ? '*' : e.value.raw).join('');
208
163
  }
209
164
 
210
165
  const localeFilesKeys = {};
@@ -218,22 +173,19 @@ function getIntlIds(context) {
218
173
  localeFiles.forEach(f => {
219
174
  const fullPath = projectRoot ? path__namespace.join(projectRoot, f) : f;
220
175
  const mtime = fs__namespace.lstatSync(fullPath).mtime.getTime();
221
- if (
222
- !localeFilesKeys[fullPath] ||
223
- mtime !== localeFilesKeys[fullPath].mtime
224
- ) {
176
+ if (!localeFilesKeys[fullPath] || mtime !== localeFilesKeys[fullPath].mtime) {
225
177
  let json;
226
178
  if (fullPath.endsWith('.json')) {
227
179
  json = JSON.parse(fs__namespace.readFileSync(fullPath, 'utf8'));
228
180
  } else if (fullPath.endsWith('.ts')) {
229
181
  json = eslintUtils.tsImport(fullPath);
230
- if (typeof json === 'object' && json.default) {
231
- json = json.default;
182
+ if (typeof json === 'object' && json["default"]) {
183
+ json = json["default"];
232
184
  }
233
185
  } else if (fullPath.endsWith('.js')) {
234
186
  json = require(fullPath);
235
- if (typeof json === 'object' && json.default) {
236
- json = json.default;
187
+ if (typeof json === 'object' && json["default"]) {
188
+ json = json["default"];
237
189
  }
238
190
  } else {
239
191
  throw new Error('unsupported file extension');
@@ -248,7 +200,7 @@ function getIntlIds(context) {
248
200
  return results;
249
201
  }
250
202
 
251
- var idMissing = {
203
+ var intlIdMissing = {
252
204
  meta: {
253
205
  docs: {
254
206
  description: 'Validates intl message ids are in locale file',
@@ -275,9 +227,7 @@ var idMissing = {
275
227
  }
276
228
  }
277
229
  function processTemplateLiteral(node) {
278
- const exStr = sortedTemplateElements(node)
279
- .map(e => (!e.value ? '.*' : e.value.raw))
280
- .join('');
230
+ const exStr = sortedTemplateElements(node).map(e => !e.value ? '.*' : e.value.raw).join('');
281
231
  const re = new RegExp(exStr);
282
232
  if (!isTemplateTranslated(re)) {
283
233
  context.report({
@@ -290,10 +240,7 @@ var idMissing = {
290
240
  if (node.value.type === 'Literal') {
291
241
  return processLiteral(node.value);
292
242
  }
293
- if (
294
- node.value.type === 'JSXExpressionContainer' &&
295
- node.value.expression.type === 'TemplateLiteral'
296
- ) {
243
+ if (node.value.type === 'JSXExpressionContainer' && node.value.expression.type === 'TemplateLiteral') {
297
244
  return processTemplateLiteral(node.value.expression);
298
245
  }
299
246
  if (node.value.type === 'TemplateLiteral') {
@@ -318,9 +265,7 @@ var idMissing = {
318
265
  }
319
266
  },
320
267
  Property: function (node) {
321
- const attrNode =
322
- findAttrNodeInDefineMessages(node, 'id') ||
323
- findAttrNodeInDefineMessage(node, 'id');
268
+ const attrNode = findAttrNodeInDefineMessages(node, 'id') || findAttrNodeInDefineMessage(node, 'id');
324
269
  if (attrNode) {
325
270
  return processAttrNode(attrNode);
326
271
  }
@@ -329,33 +274,122 @@ var idMissing = {
329
274
  }
330
275
  };
331
276
 
332
- var idPrefix = {
277
+ var intlIdNaming = {
333
278
  meta: {
334
279
  docs: {
335
- description: 'Validates intl message ids has correct prefixes',
280
+ description: 'Validates intl message ids naming convention',
336
281
  category: 'Intl'
337
282
  },
338
283
  fixable: undefined,
339
- schema: [
340
- {
341
- type: 'array',
342
- items: {
343
- type: 'string'
284
+ schema: [{
285
+ type: 'object',
286
+ properties: {
287
+ format: {
288
+ "enum": ['camelCase', 'PascalCase']
344
289
  }
345
290
  }
346
- ]
291
+ }],
292
+ messages: {
293
+ invalidIdNaming: "Invalid id naming, expected {{format}}"
294
+ }
295
+ },
296
+ create: function (context) {
297
+ if (!context.options[0]) {
298
+ throw new Error('Missing options');
299
+ }
300
+ const format = context.options[0].format;
301
+ function report(node, value) {
302
+ const values = value.split('.');
303
+ let isPass;
304
+ for (const v of values) {
305
+ switch (format) {
306
+ case 'camelCase':
307
+ if (!eslintUtils.isCamelCase(v)) {
308
+ isPass = false;
309
+ }
310
+ break;
311
+ case 'PascalCase':
312
+ if (!eslintUtils.isPascalCase(v)) {
313
+ isPass = false;
314
+ }
315
+ break;
316
+ }
317
+ }
318
+ if (isPass === false) {
319
+ context.report({
320
+ node: node,
321
+ messageId: 'invalidIdNaming',
322
+ data: {
323
+ format
324
+ }
325
+ });
326
+ }
327
+ }
328
+ function processLiteral(node) {
329
+ report(node, node.value);
330
+ }
331
+ function processTemplateLiteral(node) {
332
+ const displayStr = templateLiteralDisplayStr(node);
333
+ report(node, displayStr);
334
+ }
335
+ function processAttrNode(node) {
336
+ if (node.value.type === 'Literal') {
337
+ return processLiteral(node.value);
338
+ }
339
+ if (node.value.type === 'JSXExpressionContainer' && node.value.expression.type === 'TemplateLiteral') {
340
+ return processTemplateLiteral(node.value.expression);
341
+ }
342
+ if (node.value.type === 'TemplateLiteral') {
343
+ return processTemplateLiteral(node.value);
344
+ }
345
+ }
346
+ return {
347
+ JSXIdentifier: function (node) {
348
+ const attrNode = findFormattedMessageAttrNode(node, 'id');
349
+ if (attrNode) {
350
+ return processAttrNode(attrNode);
351
+ }
352
+ },
353
+ CallExpression: function (node) {
354
+ const attrNode = findFormatMessageAttrNode(node, 'id');
355
+ if (attrNode) {
356
+ return processAttrNode(attrNode);
357
+ }
358
+ },
359
+ Property: function (node) {
360
+ const attrNode = findAttrNodeInDefineMessages(node, 'id') || findAttrNodeInDefineMessage(node, 'id');
361
+ if (attrNode) {
362
+ return processAttrNode(attrNode);
363
+ }
364
+ }
365
+ };
366
+ }
367
+ };
368
+
369
+ var intlIdPrefix = {
370
+ meta: {
371
+ docs: {
372
+ description: 'Validates intl message ids has correct prefixes',
373
+ category: 'Intl'
374
+ },
375
+ fixable: undefined,
376
+ schema: [{
377
+ type: 'array',
378
+ items: {
379
+ type: 'string'
380
+ }
381
+ }]
347
382
  },
348
383
  create: function (context) {
349
384
  if (context.options[0].length === 0) {
350
385
  throw new Error('Prefixes are required in settings');
351
386
  }
352
- const hasPrefix = value =>
353
- context.options[0].some(p => value.startsWith(p));
387
+ const hasPrefix = value => context.options[0].some(p => value.startsWith(p));
354
388
  function report(node, value) {
355
389
  if (!hasPrefix(value)) {
356
390
  context.report({
357
391
  node: node,
358
- message: `Invalid id prefix: ${value}`
392
+ message: "Invalid id prefix: ".concat(value)
359
393
  });
360
394
  }
361
395
  }
@@ -370,10 +404,7 @@ var idPrefix = {
370
404
  if (node.value.type === 'Literal') {
371
405
  return processLiteral(node.value);
372
406
  }
373
- if (
374
- node.value.type === 'JSXExpressionContainer' &&
375
- node.value.expression.type === 'TemplateLiteral'
376
- ) {
407
+ if (node.value.type === 'JSXExpressionContainer' && node.value.expression.type === 'TemplateLiteral') {
377
408
  return processTemplateLiteral(node.value.expression);
378
409
  }
379
410
  if (node.value.type === 'TemplateLiteral') {
@@ -394,9 +425,7 @@ var idPrefix = {
394
425
  }
395
426
  },
396
427
  Property: function (node) {
397
- const attrNode =
398
- findAttrNodeInDefineMessages(node, 'id') ||
399
- findAttrNodeInDefineMessage(node, 'id');
428
+ const attrNode = findAttrNodeInDefineMessages(node, 'id') || findAttrNodeInDefineMessage(node, 'id');
400
429
  if (attrNode) {
401
430
  return processAttrNode(attrNode);
402
431
  }
@@ -406,7 +435,7 @@ var idPrefix = {
406
435
  };
407
436
 
408
437
  const usedIds = new Map();
409
- var idUnused = {
438
+ var intlIdUnused = {
410
439
  meta: {
411
440
  docs: {
412
441
  description: 'Finds unused intl message ids in locale file',
@@ -438,9 +467,7 @@ var idUnused = {
438
467
  }
439
468
  }
440
469
  function processTemplateLiteral(node) {
441
- const exStr = sortedTemplateElements(node)
442
- .map(e => (!e.value ? '.*' : e.value.raw))
443
- .join('');
470
+ const exStr = sortedTemplateElements(node).map(e => !e.value ? '.*' : e.value.raw).join('');
444
471
  const re = new RegExp(exStr);
445
472
  if (isTemplateTranslated(re)) ;
446
473
  }
@@ -448,10 +475,7 @@ var idUnused = {
448
475
  if (node.value.type === 'Literal') {
449
476
  return processLiteral(node.value);
450
477
  }
451
- if (
452
- node.value.type === 'JSXExpressionContainer' &&
453
- node.value.expression.type === 'TemplateLiteral'
454
- ) {
478
+ if (node.value.type === 'JSXExpressionContainer' && node.value.expression.type === 'TemplateLiteral') {
455
479
  return processTemplateLiteral(node.value.expression);
456
480
  }
457
481
  if (node.value.type === 'TemplateLiteral') {
@@ -472,9 +496,7 @@ var idUnused = {
472
496
  }
473
497
  },
474
498
  Property: function (node) {
475
- const attrNode =
476
- findAttrNodeInDefineMessages(node, 'id') ||
477
- findAttrNodeInDefineMessage(node, 'id');
499
+ const attrNode = findAttrNodeInDefineMessages(node, 'id') || findAttrNodeInDefineMessage(node, 'id');
478
500
  if (attrNode) {
479
501
  return processAttrNode(attrNode);
480
502
  }
@@ -488,7 +510,7 @@ var idUnused = {
488
510
  }
489
511
  };
490
512
 
491
- var noDefault = {
513
+ var intlNoDefault = {
492
514
  meta: {
493
515
  docs: {
494
516
  description: 'Validates defaultMessage is not used with react-intl',
@@ -518,9 +540,7 @@ var noDefault = {
518
540
  }
519
541
  },
520
542
  Property: function (node) {
521
- const attrNode =
522
- findAttrNodeInDefineMessages(node, 'defaultMessage') ||
523
- findAttrNodeInDefineMessage(node, 'defaultMessage');
543
+ const attrNode = findAttrNodeInDefineMessages(node, 'defaultMessage') || findAttrNodeInDefineMessage(node, 'defaultMessage');
524
544
  if (attrNode) {
525
545
  return processAttrNode(attrNode);
526
546
  }
@@ -529,79 +549,213 @@ var noDefault = {
529
549
  }
530
550
  };
531
551
 
532
- var betterExhaustiveDeps = {
552
+ var noAsyncArrayMethods = {
553
+ meta: {
554
+ docs: {
555
+ description: 'No async callback for Array methods forEach, map, filter, reduce, some, every, etc.',
556
+ category: 'Array',
557
+ recommended: true
558
+ },
559
+ fixable: undefined,
560
+ schema: [],
561
+ messages: {
562
+ noAsyncArrayMethods: "No async function in method '{{ methodName }}'"
563
+ }
564
+ },
565
+ create: function (context) {
566
+ return {
567
+ ExpressionStatement: function (node) {
568
+ const notAllowedArrayMethods = ['forEach', 'filter', 'some', 'every', 'map', 'reduce', 'reduceRight', 'flatMap', 'find', 'findIndex', 'findLast', 'findLastIndex'];
569
+ const {
570
+ callee
571
+ } = node.expression;
572
+ if (!callee || !callee.property || !callee.property.name) {
573
+ return;
574
+ }
575
+ if (notAllowedArrayMethods.includes(callee.property.name)) {
576
+ const functionArguments = node.expression.arguments.find(n => {
577
+ return ['ArrowFunctionExpression', 'FunctionExpression'].includes(n.type);
578
+ });
579
+ if (functionArguments && functionArguments.async) {
580
+ context.report({
581
+ node,
582
+ messageId: 'noAsyncArrayMethods',
583
+ data: {
584
+ methodName: callee.property.name
585
+ }
586
+ });
587
+ }
588
+ }
589
+ }
590
+ };
591
+ }
592
+ };
593
+
594
+ var noImportCss = {
595
+ meta: {
596
+ type: 'problem',
597
+ docs: {
598
+ description: 'Prevent importing CSS',
599
+ recommended: true
600
+ },
601
+ fixable: 'code',
602
+ schema: [],
603
+ messages: {
604
+ noImportCSS: 'Do not import CSS files. Use CSS-in-JS instead.'
605
+ }
606
+ },
607
+ create(context) {
608
+ return {
609
+ ImportDeclaration(node) {
610
+ const ext = path.extname(node.source.value);
611
+ if (ext.startsWith('.css') || ext.startsWith('.scss') || ext.startsWith('.sass') || ext.startsWith('.less') || ext.startsWith('.styl')) {
612
+ context.report({
613
+ node,
614
+ messageId: 'noImportCSS',
615
+ data: {
616
+ path: node.source.value
617
+ }
618
+ });
619
+ }
620
+ }
621
+ };
622
+ }
623
+ };
624
+
625
+ var noThenCatchFinally = {
626
+ meta: {
627
+ type: 'suggestion',
628
+ docs: {
629
+ description: 'Disallow the use of then()/catch()/finally() when invoking specific functions.'
630
+ },
631
+ schema: [{
632
+ type: 'object',
633
+ properties: {
634
+ restrictedFunctions: {
635
+ type: 'array',
636
+ uniqueItems: true,
637
+ items: {
638
+ type: 'string'
639
+ }
640
+ }
641
+ }
642
+ }],
643
+ messages: {
644
+ forbiddenThenCatchFinally: "then()/catch()/finally() is forbidden when invoke {{ name }}()."
645
+ }
646
+ },
647
+ create(context) {
648
+ const configuration = context.options[0] || {};
649
+ const restrictedFunctions = configuration.restrictedFunctions || [];
650
+ function isTopLevelScoped() {
651
+ return context.getScope().block.type === 'Program';
652
+ }
653
+ function isThenCatchFinally(node) {
654
+ return node.property && (node.property.name === 'then' || node.property.name === 'catch' || node.property.name === 'finally');
655
+ }
656
+ return {
657
+ 'CallExpression > MemberExpression.callee'(node) {
658
+ if (isTopLevelScoped()) {
659
+ return;
660
+ }
661
+ if (!isThenCatchFinally(node)) {
662
+ return;
663
+ }
664
+ const callExpression = node.object;
665
+ if (callExpression.type === 'CallExpression' && callExpression.callee.type === 'Identifier' && restrictedFunctions.includes(callExpression.callee.name)) {
666
+ context.report({
667
+ node: node.property,
668
+ messageId: 'forbiddenThenCatchFinally',
669
+ data: {
670
+ name: callExpression.callee.name
671
+ }
672
+ });
673
+ }
674
+ }
675
+ };
676
+ }
677
+ };
678
+
679
+ var noUnnecessaryTemplateLiterals = {
680
+ meta: {
681
+ type: 'problem',
682
+ docs: {
683
+ description: 'Check if a template string contains only one ${}',
684
+ recommended: true
685
+ },
686
+ fixable: 'code',
687
+ schema: [],
688
+ messages: {
689
+ unnecessaryTemplateString: 'Unnecessary template string with only one ${}.'
690
+ }
691
+ },
692
+ create(context) {
693
+ return {
694
+ TemplateLiteral(node) {
695
+ const code = context.sourceCode.getText(node);
696
+ if (code.startsWith('`${') && code.endsWith('}`') && code.split('${').length === 2) {
697
+ context.report({
698
+ node,
699
+ messageId: 'unnecessaryTemplateString',
700
+ fix(fixer) {
701
+ return fixer.replaceText(node, code.substring(3, code.length - 2));
702
+ }
703
+ });
704
+ }
705
+ }
706
+ };
707
+ }
708
+ };
709
+
710
+ var reactBetterExhaustiveDeps = {
533
711
  meta: {
534
712
  type: 'suggestion',
535
713
  docs: {
536
- description:
537
- 'verifies the list of dependencies for Hooks like useEffect and similar',
714
+ description: 'verifies the list of dependencies for Hooks like useEffect and similar',
538
715
  url: 'https://github.com/facebook/react/issues/14920'
539
716
  },
540
717
  fixable: 'code',
541
718
  hasSuggestions: true,
542
- schema: [
543
- {
544
- type: 'object',
545
- additionalProperties: false,
546
- enableDangerousAutofixThisMayCauseInfiniteLoops: false,
547
- properties: {
548
- additionalHooks: {
549
- type: 'string'
550
- },
551
- enableDangerousAutofixThisMayCauseInfiniteLoops: {
552
- type: 'boolean'
553
- },
554
- staticHooks: {
555
- type: 'object',
556
- additionalProperties: {
557
- oneOf: [
558
- {
559
- type: 'boolean'
560
- },
561
- {
562
- type: 'array',
563
- items: {
564
- type: 'boolean'
565
- }
566
- },
567
- {
568
- type: 'object',
569
- additionalProperties: {
570
- type: 'boolean'
571
- }
572
- }
573
- ]
574
- }
575
- },
576
- checkMemoizedVariableIsStatic: {
577
- type: 'boolean'
719
+ schema: [{
720
+ type: 'object',
721
+ additionalProperties: false,
722
+ enableDangerousAutofixThisMayCauseInfiniteLoops: false,
723
+ properties: {
724
+ additionalHooks: {
725
+ type: 'string'
726
+ },
727
+ enableDangerousAutofixThisMayCauseInfiniteLoops: {
728
+ type: 'boolean'
729
+ },
730
+ staticHooks: {
731
+ type: 'object',
732
+ additionalProperties: {
733
+ oneOf: [{
734
+ type: 'boolean'
735
+ }, {
736
+ type: 'array',
737
+ items: {
738
+ type: 'boolean'
739
+ }
740
+ }, {
741
+ type: 'object',
742
+ additionalProperties: {
743
+ type: 'boolean'
744
+ }
745
+ }]
578
746
  }
747
+ },
748
+ checkMemoizedVariableIsStatic: {
749
+ type: 'boolean'
579
750
  }
580
751
  }
581
- ]
752
+ }]
582
753
  },
583
754
  create(context) {
584
- const additionalHooks =
585
- context.options &&
586
- context.options[0] &&
587
- context.options[0].additionalHooks
588
- ? new RegExp(context.options[0].additionalHooks)
589
- : undefined;
590
- const enableDangerousAutofixThisMayCauseInfiniteLoops =
591
- (context.options &&
592
- context.options[0] &&
593
- context.options[0].enableDangerousAutofixThisMayCauseInfiniteLoops) ||
594
- false;
595
- const staticHooks =
596
- (context.options &&
597
- context.options[0] &&
598
- context.options[0].staticHooks) ||
599
- {};
600
- const checkMemoizedVariableIsStatic =
601
- (context.options &&
602
- context.options[0] &&
603
- context.options[0].checkMemoizedVariableIsStatic) ||
604
- false;
755
+ const additionalHooks = context.options && context.options[0] && context.options[0].additionalHooks ? new RegExp(context.options[0].additionalHooks) : undefined;
756
+ const enableDangerousAutofixThisMayCauseInfiniteLoops = context.options && context.options[0] && context.options[0].enableDangerousAutofixThisMayCauseInfiniteLoops || false;
757
+ const staticHooks = context.options && context.options[0] && context.options[0].staticHooks || {};
758
+ const checkMemoizedVariableIsStatic = context.options && context.options[0] && context.options[0].checkMemoizedVariableIsStatic || false;
605
759
  const options = {
606
760
  additionalHooks,
607
761
  enableDangerousAutofixThisMayCauseInfiniteLoops,
@@ -609,11 +763,8 @@ var betterExhaustiveDeps = {
609
763
  checkMemoizedVariableIsStatic
610
764
  };
611
765
  function reportProblem(problem) {
612
- if (
613
- enableDangerousAutofixThisMayCauseInfiniteLoops &&
614
- Array.isArray(problem.suggest) &&
615
- problem.suggest.length > 0
616
- ) {
766
+ if (enableDangerousAutofixThisMayCauseInfiniteLoops &&
767
+ Array.isArray(problem.suggest) && problem.suggest.length > 0) {
617
768
  problem.fix = problem.suggest[0].fix;
618
769
  }
619
770
  context.report(problem);
@@ -633,28 +784,11 @@ var betterExhaustiveDeps = {
633
784
  return result;
634
785
  };
635
786
  }
636
- function visitFunctionWithDependencies(
637
- node,
638
- declaredDependenciesNode,
639
- reactiveHook,
640
- reactiveHookName,
641
- isEffect
642
- ) {
787
+ function visitFunctionWithDependencies(node, declaredDependenciesNode, reactiveHook, reactiveHookName, isEffect) {
643
788
  if (isEffect && node.async) {
644
789
  reportProblem({
645
790
  node: node,
646
- message:
647
- `Effect callbacks are synchronous to prevent race conditions. ` +
648
- `Put the async function inside:\n\n` +
649
- 'useEffect(() => {\n' +
650
- ' async function fetchData() {\n' +
651
- ' // You can await here\n' +
652
- ' const response = await MyAPI.getData(someId);\n' +
653
- ' // ...\n' +
654
- ' }\n' +
655
- ' fetchData();\n' +
656
- `}, [someId]); // Or [] if effect doesn't need props or state\n\n` +
657
- 'Learn more about data fetching with Hooks: https://reactjs.org/link/hooks-data-fetching'
791
+ message: "Effect callbacks are synchronous to prevent race conditions. " + "Put the async function inside:\n\n" + 'useEffect(() => {\n' + ' async function fetchData() {\n' + ' // You can await here\n' + ' const response = await MyAPI.getData(someId);\n' + ' // ...\n' + ' }\n' + ' fetchData();\n' + "}, [someId]); // Or [] if effect doesn't need props or state\n\n" + 'Learn more about data fetching with Hooks: https://reactjs.org/link/hooks-data-fetching'
658
792
  });
659
793
  }
660
794
  const scope = scopeManager.acquire(node);
@@ -675,14 +809,8 @@ var betterExhaustiveDeps = {
675
809
  componentScope = currentScope;
676
810
  }
677
811
  const isArray = Array.isArray;
678
- const memoizedIsStableKnownHookValue = memoizeWithWeakMap(
679
- isStableKnownHookValue,
680
- stableKnownValueCache
681
- );
682
- const memoizedIsFunctionWithoutCapturedValues = memoizeWithWeakMap(
683
- isFunctionWithoutCapturedValues,
684
- functionWithoutCapturedValueCache
685
- );
812
+ const memoizedIsStableKnownHookValue = memoizeWithWeakMap(isStableKnownHookValue, stableKnownValueCache);
813
+ const memoizedIsFunctionWithoutCapturedValues = memoizeWithWeakMap(isFunctionWithoutCapturedValues, functionWithoutCapturedValueCache);
686
814
  function isStableKnownHookValue(resolved) {
687
815
  if (!isArray(resolved.defs)) {
688
816
  return false;
@@ -709,40 +837,27 @@ var betterExhaustiveDeps = {
709
837
  return false;
710
838
  }
711
839
  }
712
- if (
713
- declaration.kind === 'const' &&
714
- init.type === 'Literal' &&
715
- (typeof init.value === 'string' ||
716
- typeof init.value === 'number' ||
717
- init.value == null)
718
- ) {
840
+ if (declaration.kind === 'const' && init.type === 'Literal' && (typeof init.value === 'string' || typeof init.value === 'number' || init.value == null)) {
719
841
  return true;
720
842
  }
721
843
  if (init.type !== 'CallExpression') {
722
844
  return false;
723
845
  }
724
846
  let callee = init.callee;
725
- if (
726
- callee.type === 'MemberExpression' &&
727
- callee.object.name === 'React' &&
728
- callee.property != null &&
729
- !callee.computed
730
- ) {
847
+ if (callee.type === 'MemberExpression' && callee.object.name === 'React' && callee.property != null && !callee.computed) {
731
848
  callee = callee.property;
732
849
  }
733
850
  if (callee.type !== 'Identifier') {
734
851
  return false;
735
852
  }
736
853
  const id = def.node.id;
737
- const { name } = callee;
854
+ const {
855
+ name
856
+ } = callee;
738
857
  if (name === 'useRef' && id.type === 'Identifier') {
739
858
  return true;
740
859
  } else if (name === 'useState' || name === 'useReducer') {
741
- if (
742
- id.type === 'ArrayPattern' &&
743
- id.elements.length === 2 &&
744
- isArray(resolved.identifiers)
745
- ) {
860
+ if (id.type === 'ArrayPattern' && id.elements.length === 2 && isArray(resolved.identifiers)) {
746
861
  if (id.elements[1] === resolved.identifiers[0]) {
747
862
  if (name === 'useState') {
748
863
  const references = resolved.references;
@@ -769,18 +884,11 @@ var betterExhaustiveDeps = {
769
884
  }
770
885
  }
771
886
  } else if (name === 'useTransition') {
772
- if (
773
- id.type === 'ArrayPattern' &&
774
- id.elements.length === 2 &&
775
- Array.isArray(resolved.identifiers) &&
776
- id.elements[1] === resolved.identifiers[0]
777
- ) {
887
+ if (id.type === 'ArrayPattern' && id.elements.length === 2 && Array.isArray(resolved.identifiers) &&
888
+ id.elements[1] === resolved.identifiers[0]) {
778
889
  return true;
779
890
  }
780
- } else if (
781
- options.checkMemoizedVariableIsStatic &&
782
- (name === 'useMemo' || name === 'useCallback')
783
- ) {
891
+ } else if (options.checkMemoizedVariableIsStatic && (name === 'useMemo' || name === 'useCallback')) {
784
892
  const hookArgs = callee.parent.arguments;
785
893
  if (hookArgs.length < 2) {
786
894
  return false;
@@ -790,13 +898,8 @@ var betterExhaustiveDeps = {
790
898
  return true;
791
899
  }
792
900
  for (const dependencyNode of dependencies) {
793
- const dependencyRefernece = resolved.scope.references.find(
794
- reference => reference.identifier === dependencyNode
795
- );
796
- if (
797
- dependencyRefernece !== undefined &&
798
- memoizedIsStableKnownHookValue(dependencyRefernece.resolved)
799
- ) {
901
+ const dependencyRefernece = resolved.scope.references.find(reference => reference.identifier === dependencyNode);
902
+ if (dependencyRefernece !== undefined && memoizedIsStableKnownHookValue(dependencyRefernece.resolved)) {
800
903
  continue;
801
904
  } else {
802
905
  return false;
@@ -805,11 +908,7 @@ var betterExhaustiveDeps = {
805
908
  return true;
806
909
  } else {
807
910
  Object.entries(options.staticHooks).forEach(([key, staticParts]) => {
808
- if (
809
- typeof staticParts === 'object' &&
810
- staticParts.regexp &&
811
- new RegExp(key).test(name)
812
- ) {
911
+ if (typeof staticParts === 'object' && staticParts.regexp && new RegExp(key).test(name)) {
813
912
  options.staticHooks[name] = staticParts.value;
814
913
  }
815
914
  });
@@ -818,23 +917,14 @@ var betterExhaustiveDeps = {
818
917
  if (staticParts === true) {
819
918
  return true;
820
919
  } else if (Array.isArray(staticParts)) {
821
- if (
822
- id.type === 'ArrayPattern' &&
823
- id.elements.length <= staticParts.length &&
824
- Array.isArray(resolved.identifiers)
825
- ) {
920
+ if (id.type === 'ArrayPattern' && id.elements.length <= staticParts.length && Array.isArray(resolved.identifiers)) {
826
921
  const idx = id.elements.indexOf(resolved.identifiers[0]);
827
922
  if (idx >= 0) {
828
923
  return staticParts[idx];
829
924
  }
830
925
  }
831
- } else if (
832
- typeof staticParts === 'object' &&
833
- id.type === 'ObjectPattern'
834
- ) {
835
- const property = id.properties.find(
836
- p => p.key === resolved.identifiers[0]
837
- );
926
+ } else if (typeof staticParts === 'object' && id.type === 'ObjectPattern') {
927
+ const property = id.properties.find(p => p.key === resolved.identifiers[0]);
838
928
  if (property) {
839
929
  return staticParts[property.key.name];
840
930
  }
@@ -862,11 +952,8 @@ var betterExhaustiveDeps = {
862
952
  const childScope = childScopes[i];
863
953
  const childScopeBlock = childScope.block;
864
954
  if (
865
- (fnNode.type === 'FunctionDeclaration' &&
866
- childScopeBlock === fnNode) ||
867
- (fnNode.type === 'VariableDeclarator' &&
868
- childScopeBlock.parent === fnNode)
869
- ) {
955
+ fnNode.type === 'FunctionDeclaration' && childScopeBlock === fnNode ||
956
+ fnNode.type === 'VariableDeclarator' && childScopeBlock.parent === fnNode) {
870
957
  fnScope = childScope;
871
958
  break;
872
959
  }
@@ -879,10 +966,8 @@ var betterExhaustiveDeps = {
879
966
  if (ref.resolved == null) {
880
967
  continue;
881
968
  }
882
- if (
883
- pureScopes.has(ref.resolved.scope) &&
884
- !memoizedIsStableKnownHookValue(ref.resolved)
885
- ) {
969
+ if (pureScopes.has(ref.resolved.scope) &&
970
+ !memoizedIsStableKnownHookValue(ref.resolved)) {
886
971
  return false;
887
972
  }
888
973
  }
@@ -894,9 +979,7 @@ var betterExhaustiveDeps = {
894
979
  let isInReturnedFunction = false;
895
980
  while (curScope.block !== node) {
896
981
  if (curScope.type === 'function') {
897
- isInReturnedFunction =
898
- curScope.block.parent != null &&
899
- curScope.block.parent.type === 'ReturnStatement';
982
+ isInReturnedFunction = curScope.block.parent != null && curScope.block.parent.type === 'ReturnStatement';
900
983
  }
901
984
  curScope = curScope.upper;
902
985
  }
@@ -913,34 +996,19 @@ var betterExhaustiveDeps = {
913
996
  if (!pureScopes.has(reference.resolved.scope)) {
914
997
  continue;
915
998
  }
916
- const referenceNode = fastFindReferenceWithParent(
917
- node,
918
- reference.identifier
919
- );
999
+ const referenceNode = fastFindReferenceWithParent(node, reference.identifier);
920
1000
  const dependencyNode = getDependency(referenceNode);
921
- const dependency = analyzePropertyChain(
922
- dependencyNode,
923
- optionalChains
924
- );
1001
+ const dependency = analyzePropertyChain(dependencyNode, optionalChains);
925
1002
  if (
926
- isEffect &&
927
- dependencyNode.type === 'Identifier' &&
928
- (dependencyNode.parent.type === 'MemberExpression' ||
929
- dependencyNode.parent.type === 'OptionalMemberExpression') &&
930
- !dependencyNode.parent.computed &&
931
- dependencyNode.parent.property.type === 'Identifier' &&
932
- dependencyNode.parent.property.name === 'current' &&
933
- isInsideEffectCleanup(reference)
934
- ) {
1003
+ isEffect &&
1004
+ dependencyNode.type === 'Identifier' && (dependencyNode.parent.type === 'MemberExpression' || dependencyNode.parent.type === 'OptionalMemberExpression') && !dependencyNode.parent.computed && dependencyNode.parent.property.type === 'Identifier' && dependencyNode.parent.property.name === 'current' &&
1005
+ isInsideEffectCleanup(reference)) {
935
1006
  currentRefsInEffectCleanup.set(dependency, {
936
1007
  reference,
937
1008
  dependencyNode
938
1009
  });
939
1010
  }
940
- if (
941
- dependencyNode.parent.type === 'TSTypeQuery' ||
942
- dependencyNode.parent.type === 'TSTypeReference'
943
- ) {
1011
+ if (dependencyNode.parent.type === 'TSTypeQuery' || dependencyNode.parent.type === 'TSTypeReference') {
944
1012
  continue;
945
1013
  }
946
1014
  const def = reference.resolved.defs[0];
@@ -955,9 +1023,7 @@ var betterExhaustiveDeps = {
955
1023
  }
956
1024
  if (!dependencies.has(dependency)) {
957
1025
  const resolved = reference.resolved;
958
- const isStable =
959
- memoizedIsStableKnownHookValue(resolved) ||
960
- memoizedIsFunctionWithoutCapturedValues(resolved);
1026
+ const isStable = memoizedIsStableKnownHookValue(resolved) || memoizedIsFunctionWithoutCapturedValues(resolved);
961
1027
  dependencies.set(dependency, {
962
1028
  isStable,
963
1029
  references: [reference]
@@ -970,39 +1036,33 @@ var betterExhaustiveDeps = {
970
1036
  gatherDependenciesRecursively(childScope);
971
1037
  }
972
1038
  }
973
- currentRefsInEffectCleanup.forEach(
974
- ({ reference, dependencyNode }, dependency) => {
975
- const references = reference.resolved.references;
976
- let foundCurrentAssignment = false;
977
- for (const { identifier } of references) {
978
- const { parent } = identifier;
979
- if (
980
- parent != null &&
981
- parent.type === 'MemberExpression' &&
982
- !parent.computed &&
983
- parent.property.type === 'Identifier' &&
984
- parent.property.name === 'current' &&
985
- parent.parent.type === 'AssignmentExpression' &&
986
- parent.parent.left === parent
987
- ) {
988
- foundCurrentAssignment = true;
989
- break;
990
- }
991
- }
992
- if (foundCurrentAssignment) {
993
- return;
1039
+ currentRefsInEffectCleanup.forEach(({
1040
+ reference,
1041
+ dependencyNode
1042
+ }, dependency) => {
1043
+ const references = reference.resolved.references;
1044
+ let foundCurrentAssignment = false;
1045
+ for (const {
1046
+ identifier
1047
+ } of references) {
1048
+ const {
1049
+ parent
1050
+ } = identifier;
1051
+ if (parent != null &&
1052
+ parent.type === 'MemberExpression' && !parent.computed && parent.property.type === 'Identifier' && parent.property.name === 'current' &&
1053
+ parent.parent.type === 'AssignmentExpression' && parent.parent.left === parent) {
1054
+ foundCurrentAssignment = true;
1055
+ break;
994
1056
  }
995
- reportProblem({
996
- node: dependencyNode.parent.property,
997
- message:
998
- `The ref value '${dependency}.current' will likely have ` +
999
- `changed by the time this effect cleanup function runs. If ` +
1000
- `this ref points to a node rendered by React, copy ` +
1001
- `'${dependency}.current' to a variable inside the effect, and ` +
1002
- `use that variable in the cleanup function.`
1003
- });
1004
1057
  }
1005
- );
1058
+ if (foundCurrentAssignment) {
1059
+ return;
1060
+ }
1061
+ reportProblem({
1062
+ node: dependencyNode.parent.property,
1063
+ message: "The ref value '".concat(dependency, ".current' will likely have ") + "changed by the time this effect cleanup function runs. If " + "this ref points to a node rendered by React, copy " + "'".concat(dependency, ".current' to a variable inside the effect, and ") + "use that variable in the cleanup function."
1064
+ });
1065
+ });
1006
1066
  const staleAssignments = new Set();
1007
1067
  function reportStaleAssignment(writeExpr, key) {
1008
1068
  if (staleAssignments.has(key)) {
@@ -1011,17 +1071,14 @@ var betterExhaustiveDeps = {
1011
1071
  staleAssignments.add(key);
1012
1072
  reportProblem({
1013
1073
  node: writeExpr,
1014
- message:
1015
- `Assignments to the '${key}' variable from inside React Hook ` +
1016
- `${context.getSource(reactiveHook)} will be lost after each ` +
1017
- `render. To preserve the value over time, store it in a useRef ` +
1018
- `Hook and keep the mutable value in the '.current' property. ` +
1019
- `Otherwise, you can move this variable directly inside ` +
1020
- `${context.getSource(reactiveHook)}.`
1074
+ message: "Assignments to the '".concat(key, "' variable from inside React Hook ") + "".concat(context.getSource(reactiveHook), " will be lost after each ") + "render. To preserve the value over time, store it in a useRef " + "Hook and keep the mutable value in the '.current' property. " + "Otherwise, you can move this variable directly inside " + "".concat(context.getSource(reactiveHook), ".")
1021
1075
  });
1022
1076
  }
1023
1077
  const stableDependencies = new Set();
1024
- dependencies.forEach(({ isStable, references }, key) => {
1078
+ dependencies.forEach(({
1079
+ isStable,
1080
+ references
1081
+ }, key) => {
1025
1082
  if (isStable) {
1026
1083
  stableDependencies.add(key);
1027
1084
  }
@@ -1036,7 +1093,9 @@ var betterExhaustiveDeps = {
1036
1093
  }
1037
1094
  if (!declaredDependenciesNode) {
1038
1095
  let setStateInsideEffectWithoutDeps = null;
1039
- dependencies.forEach(({ references }, key) => {
1096
+ dependencies.forEach(({
1097
+ references
1098
+ }, key) => {
1040
1099
  if (setStateInsideEffectWithoutDeps) {
1041
1100
  return;
1042
1101
  }
@@ -1060,7 +1119,9 @@ var betterExhaustiveDeps = {
1060
1119
  });
1061
1120
  });
1062
1121
  if (setStateInsideEffectWithoutDeps) {
1063
- const { suggestedDependencies } = collectRecommendations({
1122
+ const {
1123
+ suggestedDependencies
1124
+ } = collectRecommendations({
1064
1125
  dependencies,
1065
1126
  declaredDependencies: [],
1066
1127
  stableDependencies,
@@ -1069,25 +1130,13 @@ var betterExhaustiveDeps = {
1069
1130
  });
1070
1131
  reportProblem({
1071
1132
  node: reactiveHook,
1072
- message:
1073
- `React Hook ${reactiveHookName} contains a call to '${setStateInsideEffectWithoutDeps}'. ` +
1074
- `Without a list of dependencies, this can lead to an infinite chain of updates. ` +
1075
- `To fix this, pass [` +
1076
- suggestedDependencies.join(', ') +
1077
- `] as a second argument to the ${reactiveHookName} Hook.`,
1078
- suggest: [
1079
- {
1080
- desc: `Add dependencies array: [${suggestedDependencies.join(
1081
- ', '
1082
- )}]`,
1083
- fix(fixer) {
1084
- return fixer.insertTextAfter(
1085
- node,
1086
- `, [${suggestedDependencies.join(', ')}]`
1087
- );
1088
- }
1133
+ message: "React Hook ".concat(reactiveHookName, " contains a call to '").concat(setStateInsideEffectWithoutDeps, "'. ") + "Without a list of dependencies, this can lead to an infinite chain of updates. " + "To fix this, pass [" + suggestedDependencies.join(', ') + "] as a second argument to the ".concat(reactiveHookName, " Hook."),
1134
+ suggest: [{
1135
+ desc: "Add dependencies array: [".concat(suggestedDependencies.join(', '), "]"),
1136
+ fix(fixer) {
1137
+ return fixer.insertTextAfter(node, ", [".concat(suggestedDependencies.join(', '), "]"));
1089
1138
  }
1090
- ]
1139
+ }]
1091
1140
  });
1092
1141
  }
1093
1142
  return;
@@ -1097,11 +1146,7 @@ var betterExhaustiveDeps = {
1097
1146
  if (declaredDependenciesNode.type !== 'ArrayExpression') {
1098
1147
  reportProblem({
1099
1148
  node: declaredDependenciesNode,
1100
- message:
1101
- `React Hook ${context.getSource(reactiveHook)} was passed a ` +
1102
- 'dependency list that is not an array literal. This means we ' +
1103
- "can't statically verify whether you've passed the correct " +
1104
- 'dependencies.'
1149
+ message: "React Hook ".concat(context.getSource(reactiveHook), " was passed a ") + 'dependency list that is not an array literal. This means we ' + "can't statically verify whether you've passed the correct " + 'dependencies.'
1105
1150
  });
1106
1151
  } else {
1107
1152
  declaredDependenciesNode.elements.forEach(declaredDependencyNode => {
@@ -1111,46 +1156,31 @@ var betterExhaustiveDeps = {
1111
1156
  if (declaredDependencyNode.type === 'SpreadElement') {
1112
1157
  reportProblem({
1113
1158
  node: declaredDependencyNode,
1114
- message:
1115
- `React Hook ${context.getSource(reactiveHook)} has a spread ` +
1116
- "element in its dependency array. This means we can't " +
1117
- "statically verify whether you've passed the " +
1118
- 'correct dependencies.'
1159
+ message: "React Hook ".concat(context.getSource(reactiveHook), " has a spread ") + "element in its dependency array. This means we can't " + "statically verify whether you've passed the " + 'correct dependencies.'
1119
1160
  });
1120
1161
  return;
1121
1162
  }
1122
1163
  let declaredDependency;
1123
1164
  try {
1124
- declaredDependency = analyzePropertyChain(
1125
- declaredDependencyNode,
1126
- null
1127
- );
1165
+ declaredDependency = analyzePropertyChain(declaredDependencyNode, null);
1128
1166
  } catch (err) {
1129
1167
  if (/Unsupported node type/.test(err.message)) {
1130
1168
  if (declaredDependencyNode.type === 'Literal') {
1131
1169
  if (dependencies.has(declaredDependencyNode.value)) {
1132
1170
  reportProblem({
1133
1171
  node: declaredDependencyNode,
1134
- message:
1135
- `The ${declaredDependencyNode.raw} literal is not a valid dependency ` +
1136
- `because it never changes. ` +
1137
- `Did you mean to include ${declaredDependencyNode.value} in the array instead?`
1172
+ message: "The ".concat(declaredDependencyNode.raw, " literal is not a valid dependency ") + "because it never changes. " + "Did you mean to include ".concat(declaredDependencyNode.value, " in the array instead?")
1138
1173
  });
1139
1174
  } else {
1140
1175
  reportProblem({
1141
1176
  node: declaredDependencyNode,
1142
- message:
1143
- `The ${declaredDependencyNode.raw} literal is not a valid dependency ` +
1144
- 'because it never changes. You can safely remove it.'
1177
+ message: "The ".concat(declaredDependencyNode.raw, " literal is not a valid dependency ") + 'because it never changes. You can safely remove it.'
1145
1178
  });
1146
1179
  }
1147
1180
  } else {
1148
1181
  reportProblem({
1149
1182
  node: declaredDependencyNode,
1150
- message:
1151
- `React Hook ${context.getSource(reactiveHook)} has a ` +
1152
- `complex expression in the dependency array. ` +
1153
- 'Extract it to a separate variable so it can be statically checked.'
1183
+ message: "React Hook ".concat(context.getSource(reactiveHook), " has a ") + "complex expression in the dependency array. " + 'Extract it to a separate variable so it can be statically checked.'
1154
1184
  });
1155
1185
  }
1156
1186
  return;
@@ -1158,16 +1188,10 @@ var betterExhaustiveDeps = {
1158
1188
  throw err;
1159
1189
  }
1160
1190
  let maybeID = declaredDependencyNode;
1161
- while (
1162
- maybeID.type === 'MemberExpression' ||
1163
- maybeID.type === 'OptionalMemberExpression' ||
1164
- maybeID.type === 'ChainExpression'
1165
- ) {
1191
+ while (maybeID.type === 'MemberExpression' || maybeID.type === 'OptionalMemberExpression' || maybeID.type === 'ChainExpression') {
1166
1192
  maybeID = maybeID.object || maybeID.expression.object;
1167
1193
  }
1168
- const isDeclaredInComponent = !componentScope.through.some(
1169
- ref => ref.identifier === maybeID
1170
- );
1194
+ const isDeclaredInComponent = !componentScope.through.some(ref => ref.identifier === maybeID);
1171
1195
  declaredDependencies.push({
1172
1196
  key: declaredDependency,
1173
1197
  node: declaredDependencyNode
@@ -1190,10 +1214,7 @@ var betterExhaustiveDeps = {
1190
1214
  isEffect
1191
1215
  });
1192
1216
  let suggestedDeps = suggestedDependencies;
1193
- const problemCount =
1194
- duplicateDependencies.size +
1195
- missingDependencies.size +
1196
- unnecessaryDependencies.size;
1217
+ const problemCount = duplicateDependencies.size + missingDependencies.size + unnecessaryDependencies.size;
1197
1218
  if (problemCount === 0) {
1198
1219
  const constructions = scanForConstructions({
1199
1220
  declaredDependencies,
@@ -1201,53 +1222,36 @@ var betterExhaustiveDeps = {
1201
1222
  componentScope,
1202
1223
  scope
1203
1224
  });
1204
- constructions.forEach(
1205
- ({ construction, isUsedOutsideOfHook, depType }) => {
1206
- const wrapperHook =
1207
- depType === 'function' ? 'useCallback' : 'useMemo';
1208
- const constructionType =
1209
- depType === 'function' ? 'definition' : 'initialization';
1210
- const defaultAdvice = `wrap the ${constructionType} of '${construction.name.name}' in its own ${wrapperHook}() Hook.`;
1211
- const advice = isUsedOutsideOfHook
1212
- ? `To fix this, ${defaultAdvice}`
1213
- : `Move it inside the ${reactiveHookName} callback. Alternatively, ${defaultAdvice}`;
1214
- const causation =
1215
- depType === 'conditional' || depType === 'logical expression'
1216
- ? 'could make'
1217
- : 'makes';
1218
- const message =
1219
- `The '${construction.name.name}' ${depType} ${causation} the dependencies of ` +
1220
- `${reactiveHookName} Hook (at line ${declaredDependenciesNode.loc.start.line}) ` +
1221
- `change on every render. ${advice}`;
1222
- let suggest;
1223
- if (
1224
- isUsedOutsideOfHook &&
1225
- construction.type === 'Variable' &&
1226
- depType === 'function'
1227
- ) {
1228
- suggest = [
1229
- {
1230
- desc: `Wrap the ${constructionType} of '${construction.name.name}' in its own ${wrapperHook}() Hook.`,
1231
- fix(fixer) {
1232
- const [before, after] =
1233
- wrapperHook === 'useMemo'
1234
- ? [`useMemo(() => { return `, '; })']
1235
- : ['useCallback(', ')'];
1236
- return [
1237
- fixer.insertTextBefore(construction.node.init, before),
1238
- fixer.insertTextAfter(construction.node.init, after)
1239
- ];
1240
- }
1241
- }
1242
- ];
1243
- }
1244
- reportProblem({
1245
- node: construction.node,
1246
- message,
1247
- suggest
1248
- });
1225
+ constructions.forEach(({
1226
+ construction,
1227
+ isUsedOutsideOfHook,
1228
+ depType
1229
+ }) => {
1230
+ const wrapperHook = depType === 'function' ? 'useCallback' : 'useMemo';
1231
+ const constructionType = depType === 'function' ? 'definition' : 'initialization';
1232
+ const defaultAdvice = "wrap the ".concat(constructionType, " of '").concat(construction.name.name, "' in its own ").concat(wrapperHook, "() Hook.");
1233
+ const advice = isUsedOutsideOfHook ? "To fix this, ".concat(defaultAdvice) : "Move it inside the ".concat(reactiveHookName, " callback. Alternatively, ").concat(defaultAdvice);
1234
+ const causation = depType === 'conditional' || depType === 'logical expression' ? 'could make' : 'makes';
1235
+ const message = "The '".concat(construction.name.name, "' ").concat(depType, " ").concat(causation, " the dependencies of ") + "".concat(reactiveHookName, " Hook (at line ").concat(declaredDependenciesNode.loc.start.line, ") ") + "change on every render. ".concat(advice);
1236
+ let suggest;
1237
+ if (isUsedOutsideOfHook && construction.type === 'Variable' &&
1238
+ depType === 'function') {
1239
+ suggest = [{
1240
+ desc: "Wrap the ".concat(constructionType, " of '").concat(construction.name.name, "' in its own ").concat(wrapperHook, "() Hook."),
1241
+ fix(fixer) {
1242
+ const [before, after] = wrapperHook === 'useMemo' ? ["useMemo(() => { return ", '; })'] : ['useCallback(', ')'];
1243
+ return [
1244
+ fixer.insertTextBefore(construction.node.init, before),
1245
+ fixer.insertTextAfter(construction.node.init, after)];
1246
+ }
1247
+ }];
1249
1248
  }
1250
- );
1249
+ reportProblem({
1250
+ node: construction.node,
1251
+ message,
1252
+ suggest
1253
+ });
1254
+ });
1251
1255
  return;
1252
1256
  }
1253
1257
  if (!isEffect && missingDependencies.size > 0) {
@@ -1287,19 +1291,7 @@ var betterExhaustiveDeps = {
1287
1291
  if (deps.size === 0) {
1288
1292
  return null;
1289
1293
  }
1290
- return (
1291
- (deps.size > 1 ? '' : singlePrefix + ' ') +
1292
- label +
1293
- ' ' +
1294
- (deps.size > 1 ? 'dependencies' : 'dependency') +
1295
- ': ' +
1296
- joinEnglish(
1297
- [...deps].sort().map(name => "'" + formatDependency(name) + "'")
1298
- ) +
1299
- `. Either ${fixVerb} ${
1300
- deps.size > 1 ? 'them' : 'it'
1301
- } or remove the dependency array.`
1302
- );
1294
+ return (deps.size > 1 ? '' : singlePrefix + ' ') + label + ' ' + (deps.size > 1 ? 'dependencies' : 'dependency') + ': ' + joinEnglish([...deps].sort().map(name => "'" + formatDependency(name) + "'")) + ". Either ".concat(fixVerb, " ").concat(deps.size > 1 ? 'them' : 'it', " or remove the dependency array.");
1303
1295
  }
1304
1296
  let extraWarning = '';
1305
1297
  if (unnecessaryDependencies.size > 0) {
@@ -1313,15 +1305,11 @@ var betterExhaustiveDeps = {
1313
1305
  }
1314
1306
  });
1315
1307
  if (badRef != null) {
1316
- extraWarning =
1317
- ` Mutable values like '${badRef}' aren't valid dependencies ` +
1318
- "because mutating them doesn't re-render the component.";
1308
+ extraWarning = " Mutable values like '".concat(badRef, "' aren't valid dependencies ") + "because mutating them doesn't re-render the component.";
1319
1309
  } else if (externalDependencies.size > 0) {
1320
1310
  const dep = [...externalDependencies][0];
1321
1311
  if (!scope.set.has(dep)) {
1322
- extraWarning =
1323
- ` Outer scope values like '${dep}' aren't valid dependencies ` +
1324
- `because mutating them doesn't re-render the component.`;
1312
+ extraWarning = " Outer scope values like '".concat(dep, "' aren't valid dependencies ") + "because mutating them doesn't re-render the component.";
1325
1313
  }
1326
1314
  }
1327
1315
  }
@@ -1336,10 +1324,7 @@ var betterExhaustiveDeps = {
1336
1324
  }
1337
1325
  let isPropsOnlyUsedInMembers = true;
1338
1326
  for (const ref of refs) {
1339
- const id = fastFindReferenceWithParent(
1340
- componentScope.block,
1341
- ref.identifier
1342
- );
1327
+ const id = fastFindReferenceWithParent(componentScope.block, ref.identifier);
1343
1328
  if (!id) {
1344
1329
  isPropsOnlyUsedInMembers = false;
1345
1330
  break;
@@ -1349,20 +1334,13 @@ var betterExhaustiveDeps = {
1349
1334
  isPropsOnlyUsedInMembers = false;
1350
1335
  break;
1351
1336
  }
1352
- if (
1353
- parent.type !== 'MemberExpression' &&
1354
- parent.type !== 'OptionalMemberExpression'
1355
- ) {
1337
+ if (parent.type !== 'MemberExpression' && parent.type !== 'OptionalMemberExpression') {
1356
1338
  isPropsOnlyUsedInMembers = false;
1357
1339
  break;
1358
1340
  }
1359
1341
  }
1360
1342
  if (isPropsOnlyUsedInMembers) {
1361
- extraWarning =
1362
- ` However, 'props' will change when *any* prop changes, so the ` +
1363
- `preferred fix is to destructure the 'props' object outside of ` +
1364
- `the ${reactiveHookName} call and refer to those specific props ` +
1365
- `inside ${context.getSource(reactiveHook)}.`;
1343
+ extraWarning = " However, 'props' will change when *any* prop changes, so the " + "preferred fix is to destructure the 'props' object outside of " + "the ".concat(reactiveHookName, " call and refer to those specific props ") + "inside ".concat(context.getSource(reactiveHook), ".");
1366
1344
  }
1367
1345
  }
1368
1346
  if (!extraWarning && missingDependencies.size > 0) {
@@ -1384,13 +1362,7 @@ var betterExhaustiveDeps = {
1384
1362
  let id;
1385
1363
  for (let i = 0; i < usedDep.references.length; i++) {
1386
1364
  id = usedDep.references[i].identifier;
1387
- if (
1388
- id != null &&
1389
- id.parent != null &&
1390
- (id.parent.type === 'CallExpression' ||
1391
- id.parent.type === 'OptionalCallExpression') &&
1392
- id.parent.callee === id
1393
- ) {
1365
+ if (id != null && id.parent != null && (id.parent.type === 'CallExpression' || id.parent.type === 'OptionalCallExpression') && id.parent.callee === id) {
1394
1366
  isFunctionCall = true;
1395
1367
  break;
1396
1368
  }
@@ -1401,10 +1373,7 @@ var betterExhaustiveDeps = {
1401
1373
  missingCallbackDep = missingDep;
1402
1374
  });
1403
1375
  if (missingCallbackDep != null) {
1404
- extraWarning =
1405
- ` If '${missingCallbackDep}' changes too often, ` +
1406
- `find the parent component that defines it ` +
1407
- `and wrap that definition in useCallback.`;
1376
+ extraWarning = " If '".concat(missingCallbackDep, "' changes too often, ") + "find the parent component that defines it " + "and wrap that definition in useCallback.";
1408
1377
  }
1409
1378
  }
1410
1379
  if (!extraWarning && missingDependencies.size > 0) {
@@ -1422,9 +1391,7 @@ var betterExhaustiveDeps = {
1422
1391
  maybeCall = id.parent;
1423
1392
  while (maybeCall != null && maybeCall !== componentScope.block) {
1424
1393
  if (maybeCall.type === 'CallExpression') {
1425
- const correspondingStateVariable = setStateCallSites.get(
1426
- maybeCall.callee
1427
- );
1394
+ const correspondingStateVariable = setStateCallSites.get(maybeCall.callee);
1428
1395
  if (correspondingStateVariable != null) {
1429
1396
  if (correspondingStateVariable.name === missingDep) {
1430
1397
  setStateRecommendation = {
@@ -1464,27 +1431,13 @@ var betterExhaustiveDeps = {
1464
1431
  if (setStateRecommendation != null) {
1465
1432
  switch (setStateRecommendation.form) {
1466
1433
  case 'reducer':
1467
- extraWarning =
1468
- ` You can also replace multiple useState variables with useReducer ` +
1469
- `if '${setStateRecommendation.setter}' needs the ` +
1470
- `current value of '${setStateRecommendation.missingDep}'.`;
1434
+ extraWarning = " You can also replace multiple useState variables with useReducer " + "if '".concat(setStateRecommendation.setter, "' needs the ") + "current value of '".concat(setStateRecommendation.missingDep, "'.");
1471
1435
  break;
1472
1436
  case 'inlineReducer':
1473
- extraWarning =
1474
- ` If '${setStateRecommendation.setter}' needs the ` +
1475
- `current value of '${setStateRecommendation.missingDep}', ` +
1476
- `you can also switch to useReducer instead of useState and ` +
1477
- `read '${setStateRecommendation.missingDep}' in the reducer.`;
1437
+ extraWarning = " If '".concat(setStateRecommendation.setter, "' needs the ") + "current value of '".concat(setStateRecommendation.missingDep, "', ") + "you can also switch to useReducer instead of useState and " + "read '".concat(setStateRecommendation.missingDep, "' in the reducer.");
1478
1438
  break;
1479
1439
  case 'updater':
1480
- extraWarning = ` You can also do a functional update '${
1481
- setStateRecommendation.setter
1482
- }(${setStateRecommendation.missingDep.slice(
1483
- 0,
1484
- 1
1485
- )} => ...)' if you only need '${
1486
- setStateRecommendation.missingDep
1487
- }' in the '${setStateRecommendation.setter}' call.`;
1440
+ extraWarning = " You can also do a functional update '".concat(setStateRecommendation.setter, "(").concat(setStateRecommendation.missingDep.slice(0, 1), " => ...)' if you only need '").concat(setStateRecommendation.missingDep, "' in the '").concat(setStateRecommendation.setter, "' call.");
1488
1441
  break;
1489
1442
  default:
1490
1443
  throw new Error('Unknown case.');
@@ -1493,35 +1446,14 @@ var betterExhaustiveDeps = {
1493
1446
  }
1494
1447
  reportProblem({
1495
1448
  node: declaredDependenciesNode,
1496
- message:
1497
- `React Hook ${context.getSource(reactiveHook)} has ` +
1498
- (getWarningMessage(missingDependencies, 'a', 'missing', 'include') ||
1499
- getWarningMessage(
1500
- unnecessaryDependencies,
1501
- 'an',
1502
- 'unnecessary',
1503
- 'exclude'
1504
- ) ||
1505
- getWarningMessage(
1506
- duplicateDependencies,
1507
- 'a',
1508
- 'duplicate',
1509
- 'omit'
1510
- )) +
1511
- extraWarning,
1512
- suggest: [
1513
- {
1514
- desc: `Update the dependencies array to be: [${suggestedDeps
1515
- .map(element => formatDependency(element))
1516
- .join(', ')}]`,
1517
- fix(fixer) {
1518
- return fixer.replaceText(
1519
- declaredDependenciesNode,
1520
- `[${suggestedDeps.map(element => formatDependency(element)).join(', ')}]`
1521
- );
1522
- }
1523
- }
1524
- ]
1449
+ message: "React Hook ".concat(context.getSource(reactiveHook), " has ") + (
1450
+ getWarningMessage(missingDependencies, 'a', 'missing', 'include') || getWarningMessage(unnecessaryDependencies, 'an', 'unnecessary', 'exclude') || getWarningMessage(duplicateDependencies, 'a', 'duplicate', 'omit')) + extraWarning,
1451
+ suggest: [{
1452
+ desc: "Update the dependencies array to be: [".concat(suggestedDeps.map(element => formatDependency(element)).join(', '), "]"),
1453
+ fix(fixer) {
1454
+ return fixer.replaceText(declaredDependenciesNode, "[".concat(suggestedDeps.map(element => formatDependency(element)).join(', '), "]"));
1455
+ }
1456
+ }]
1525
1457
  });
1526
1458
  }
1527
1459
  function visitCallExpression(node) {
@@ -1537,23 +1469,15 @@ var betterExhaustiveDeps = {
1537
1469
  if (!callback) {
1538
1470
  reportProblem({
1539
1471
  node: reactiveHook,
1540
- message:
1541
- `React Hook ${reactiveHookName} requires an effect callback. ` +
1542
- `Did you forget to pass a callback to the hook?`
1472
+ message: "React Hook ".concat(reactiveHookName, " requires an effect callback. ") + "Did you forget to pass a callback to the hook?"
1543
1473
  });
1544
1474
  return;
1545
1475
  }
1546
1476
  if (!declaredDependenciesNode && !isEffect) {
1547
- if (
1548
- reactiveHookName === 'useMemo' ||
1549
- reactiveHookName === 'useCallback'
1550
- ) {
1477
+ if (reactiveHookName === 'useMemo' || reactiveHookName === 'useCallback') {
1551
1478
  reportProblem({
1552
1479
  node: reactiveHook,
1553
- message:
1554
- `React Hook ${reactiveHookName} does nothing when called with ` +
1555
- `only one argument. Did you forget to pass an array of ` +
1556
- `dependencies?`
1480
+ message: "React Hook ".concat(reactiveHookName, " does nothing when called with ") + "only one argument. Did you forget to pass an array of " + "dependencies?"
1557
1481
  });
1558
1482
  }
1559
1483
  return;
@@ -1561,24 +1485,13 @@ var betterExhaustiveDeps = {
1561
1485
  switch (callback.type) {
1562
1486
  case 'FunctionExpression':
1563
1487
  case 'ArrowFunctionExpression':
1564
- visitFunctionWithDependencies(
1565
- callback,
1566
- declaredDependenciesNode,
1567
- reactiveHook,
1568
- reactiveHookName,
1569
- isEffect
1570
- );
1488
+ visitFunctionWithDependencies(callback, declaredDependenciesNode, reactiveHook, reactiveHookName, isEffect);
1571
1489
  return;
1572
1490
  case 'Identifier':
1573
1491
  if (!declaredDependenciesNode) {
1574
1492
  return;
1575
1493
  }
1576
- if (
1577
- declaredDependenciesNode.elements &&
1578
- declaredDependenciesNode.elements.some(
1579
- el => el && el.type === 'Identifier' && el.name === callback.name
1580
- )
1581
- ) {
1494
+ if (declaredDependenciesNode.elements && declaredDependenciesNode.elements.some(el => el && el.type === 'Identifier' && el.name === callback.name)) {
1582
1495
  return;
1583
1496
  }
1584
1497
  const variable = context.getScope().set.get(callback.name);
@@ -1594,13 +1507,7 @@ var betterExhaustiveDeps = {
1594
1507
  }
1595
1508
  switch (def.node.type) {
1596
1509
  case 'FunctionDeclaration':
1597
- visitFunctionWithDependencies(
1598
- def.node,
1599
- declaredDependenciesNode,
1600
- reactiveHook,
1601
- reactiveHookName,
1602
- isEffect
1603
- );
1510
+ visitFunctionWithDependencies(def.node, declaredDependenciesNode, reactiveHook, reactiveHookName, isEffect);
1604
1511
  return;
1605
1512
  case 'VariableDeclarator':
1606
1513
  const init = def.node.init;
@@ -1610,13 +1517,7 @@ var betterExhaustiveDeps = {
1610
1517
  switch (init.type) {
1611
1518
  case 'ArrowFunctionExpression':
1612
1519
  case 'FunctionExpression':
1613
- visitFunctionWithDependencies(
1614
- init,
1615
- declaredDependenciesNode,
1616
- reactiveHook,
1617
- reactiveHookName,
1618
- isEffect
1619
- );
1520
+ visitFunctionWithDependencies(init, declaredDependenciesNode, reactiveHook, reactiveHookName, isEffect);
1620
1521
  return;
1621
1522
  }
1622
1523
  break;
@@ -1625,28 +1526,19 @@ var betterExhaustiveDeps = {
1625
1526
  default:
1626
1527
  reportProblem({
1627
1528
  node: reactiveHook,
1628
- message:
1629
- `React Hook ${reactiveHookName} received a function whose dependencies ` +
1630
- `are unknown. Pass an inline function instead.`
1529
+ message: "React Hook ".concat(reactiveHookName, " received a function whose dependencies ") + "are unknown. Pass an inline function instead."
1631
1530
  });
1632
1531
  return;
1633
1532
  }
1634
1533
  reportProblem({
1635
1534
  node: reactiveHook,
1636
- message:
1637
- `React Hook ${reactiveHookName} has a missing dependency: '${callback.name}'. ` +
1638
- `Either include it or remove the dependency array.`,
1639
- suggest: [
1640
- {
1641
- desc: `Update the dependencies array to be: [${callback.name}]`,
1642
- fix(fixer) {
1643
- return fixer.replaceText(
1644
- declaredDependenciesNode,
1645
- `[${callback.name}]`
1646
- );
1647
- }
1535
+ message: "React Hook ".concat(reactiveHookName, " has a missing dependency: '").concat(callback.name, "'. ") + "Either include it or remove the dependency array.",
1536
+ suggest: [{
1537
+ desc: "Update the dependencies array to be: [".concat(callback.name, "]"),
1538
+ fix(fixer) {
1539
+ return fixer.replaceText(declaredDependenciesNode, "[".concat(callback.name, "]"));
1648
1540
  }
1649
- ]
1541
+ }]
1650
1542
  });
1651
1543
  }
1652
1544
  return {
@@ -1677,7 +1569,9 @@ function collectRecommendations({
1677
1569
  parent.isSubtreeUsed = true;
1678
1570
  });
1679
1571
  });
1680
- declaredDependencies.forEach(({ key }) => {
1572
+ declaredDependencies.forEach(({
1573
+ key
1574
+ }) => {
1681
1575
  const node = getOrCreateNodeByPath(depTree, key);
1682
1576
  node.isSatisfiedRecursively = true;
1683
1577
  });
@@ -1712,12 +1606,7 @@ function collectRecommendations({
1712
1606
  }
1713
1607
  const missingDependencies = new Set();
1714
1608
  const satisfyingDependencies = new Set();
1715
- scanTreeRecursively(
1716
- depTree,
1717
- missingDependencies,
1718
- satisfyingDependencies,
1719
- key => key
1720
- );
1609
+ scanTreeRecursively(depTree, missingDependencies, satisfyingDependencies, key => key);
1721
1610
  function scanTreeRecursively(node, missingPaths, satisfyingPaths, keyToPath) {
1722
1611
  node.children.forEach((child, key) => {
1723
1612
  const path = keyToPath(key);
@@ -1731,29 +1620,22 @@ function collectRecommendations({
1731
1620
  missingPaths.add(path);
1732
1621
  return;
1733
1622
  }
1734
- scanTreeRecursively(
1735
- child,
1736
- missingPaths,
1737
- satisfyingPaths,
1738
- childKey => path + '.' + childKey
1739
- );
1623
+ scanTreeRecursively(child, missingPaths, satisfyingPaths, childKey => path + '.' + childKey);
1740
1624
  });
1741
1625
  }
1742
1626
  const suggestedDependencies = [];
1743
1627
  const unnecessaryDependencies = new Set();
1744
1628
  const duplicateDependencies = new Set();
1745
- declaredDependencies.forEach(({ key }) => {
1629
+ declaredDependencies.forEach(({
1630
+ key
1631
+ }) => {
1746
1632
  if (satisfyingDependencies.has(key)) {
1747
1633
  if (!suggestedDependencies.includes(key)) {
1748
1634
  suggestedDependencies.push(key);
1749
1635
  } else {
1750
1636
  duplicateDependencies.add(key);
1751
1637
  }
1752
- } else if (
1753
- isEffect &&
1754
- !key.endsWith('.current') &&
1755
- !externalDependencies.has(key)
1756
- ) {
1638
+ } else if (isEffect && !key.endsWith('.current') && !externalDependencies.has(key)) {
1757
1639
  if (!suggestedDependencies.includes(key)) {
1758
1640
  suggestedDependencies.push(key);
1759
1641
  }
@@ -1783,18 +1665,12 @@ function getConstructionExpressionType(node) {
1783
1665
  case 'ClassExpression':
1784
1666
  return 'class';
1785
1667
  case 'ConditionalExpression':
1786
- if (
1787
- getConstructionExpressionType(node.consequent) != null ||
1788
- getConstructionExpressionType(node.alternate) != null
1789
- ) {
1668
+ if (getConstructionExpressionType(node.consequent) != null || getConstructionExpressionType(node.alternate) != null) {
1790
1669
  return 'conditional';
1791
1670
  }
1792
1671
  return null;
1793
1672
  case 'LogicalExpression':
1794
- if (
1795
- getConstructionExpressionType(node.left) != null ||
1796
- getConstructionExpressionType(node.right) != null
1797
- ) {
1673
+ if (getConstructionExpressionType(node.left) != null || getConstructionExpressionType(node.right) != null) {
1798
1674
  return 'logical expression';
1799
1675
  }
1800
1676
  return null;
@@ -1827,41 +1703,32 @@ function scanForConstructions({
1827
1703
  componentScope,
1828
1704
  scope
1829
1705
  }) {
1830
- const constructions = declaredDependencies
1831
- .map(({ key }) => {
1832
- const ref = componentScope.variables.find(v => v.name === key);
1833
- if (ref == null) {
1834
- return null;
1835
- }
1836
- const node = ref.defs[0];
1837
- if (node == null) {
1838
- return null;
1839
- }
1840
- if (
1841
- node.type === 'Variable' &&
1842
- node.node.type === 'VariableDeclarator' &&
1843
- node.node.id.type === 'Identifier' &&
1844
- node.node.init != null
1845
- ) {
1846
- const constantExpressionType = getConstructionExpressionType(
1847
- node.node.init
1848
- );
1849
- if (constantExpressionType != null) {
1850
- return [ref, constantExpressionType];
1851
- }
1852
- }
1853
- if (
1854
- node.type === 'FunctionName' &&
1855
- node.node.type === 'FunctionDeclaration'
1856
- ) {
1857
- return [ref, 'function'];
1858
- }
1859
- if (node.type === 'ClassName' && node.node.type === 'ClassDeclaration') {
1860
- return [ref, 'class'];
1861
- }
1706
+ const constructions = declaredDependencies.map(({
1707
+ key
1708
+ }) => {
1709
+ const ref = componentScope.variables.find(v => v.name === key);
1710
+ if (ref == null) {
1862
1711
  return null;
1863
- })
1864
- .filter(Boolean);
1712
+ }
1713
+ const node = ref.defs[0];
1714
+ if (node == null) {
1715
+ return null;
1716
+ }
1717
+ if (node.type === 'Variable' && node.node.type === 'VariableDeclarator' && node.node.id.type === 'Identifier' &&
1718
+ node.node.init != null) {
1719
+ const constantExpressionType = getConstructionExpressionType(node.node.init);
1720
+ if (constantExpressionType != null) {
1721
+ return [ref, constantExpressionType];
1722
+ }
1723
+ }
1724
+ if (node.type === 'FunctionName' && node.node.type === 'FunctionDeclaration') {
1725
+ return [ref, 'function'];
1726
+ }
1727
+ if (node.type === 'ClassName' && node.node.type === 'ClassDeclaration') {
1728
+ return [ref, 'class'];
1729
+ }
1730
+ return null;
1731
+ }).filter(Boolean);
1865
1732
  function isUsedOutsideOfHook(ref) {
1866
1733
  let foundWriteExpr = false;
1867
1734
  for (let i = 0; i < ref.references.length; i++) {
@@ -1877,10 +1744,8 @@ function scanForConstructions({
1877
1744
  while (currentScope !== scope && currentScope != null) {
1878
1745
  currentScope = currentScope.upper;
1879
1746
  }
1880
- if (
1881
- currentScope !== scope &&
1882
- !isAncestorNodeOf(declaredDependenciesNode, reference.identifier)
1883
- ) {
1747
+ if (currentScope !== scope &&
1748
+ !isAncestorNodeOf(declaredDependenciesNode, reference.identifier)) {
1884
1749
  return true;
1885
1750
  }
1886
1751
  }
@@ -1893,26 +1758,10 @@ function scanForConstructions({
1893
1758
  }));
1894
1759
  }
1895
1760
  function getDependency(node) {
1896
- if (
1897
- (node.parent.type === 'MemberExpression' ||
1898
- node.parent.type === 'OptionalMemberExpression') &&
1899
- node.parent.object === node &&
1900
- node.parent.property.name !== 'current' &&
1901
- !node.parent.computed &&
1902
- !(
1903
- node.parent.parent != null &&
1904
- (node.parent.parent.type === 'CallExpression' ||
1905
- node.parent.parent.type === 'OptionalCallExpression') &&
1906
- node.parent.parent.callee === node.parent
1907
- )
1908
- ) {
1761
+ if ((node.parent.type === 'MemberExpression' || node.parent.type === 'OptionalMemberExpression') && node.parent.object === node && node.parent.property.name !== 'current' && !node.parent.computed && !(node.parent.parent != null && (node.parent.parent.type === 'CallExpression' || node.parent.parent.type === 'OptionalCallExpression') && node.parent.parent.callee === node.parent)) {
1909
1762
  return getDependency(node.parent);
1910
1763
  } else if (
1911
- node.type === 'MemberExpression' &&
1912
- node.parent &&
1913
- node.parent.type === 'AssignmentExpression' &&
1914
- node.parent.left === node
1915
- ) {
1764
+ node.type === 'MemberExpression' && node.parent && node.parent.type === 'AssignmentExpression' && node.parent.left === node) {
1916
1765
  return node.object;
1917
1766
  }
1918
1767
  return node;
@@ -1938,36 +1787,30 @@ function analyzePropertyChain(node, optionalChains) {
1938
1787
  } else if (node.type === 'MemberExpression' && !node.computed) {
1939
1788
  const object = analyzePropertyChain(node.object, optionalChains);
1940
1789
  const property = analyzePropertyChain(node.property, null);
1941
- const result = `${object}.${property}`;
1790
+ const result = "".concat(object, ".").concat(property);
1942
1791
  markNode(node, optionalChains, result);
1943
1792
  return result;
1944
1793
  } else if (node.type === 'OptionalMemberExpression' && !node.computed) {
1945
1794
  const object = analyzePropertyChain(node.object, optionalChains);
1946
1795
  const property = analyzePropertyChain(node.property, null);
1947
- const result = `${object}.${property}`;
1796
+ const result = "".concat(object, ".").concat(property);
1948
1797
  markNode(node, optionalChains, result);
1949
1798
  return result;
1950
1799
  } else if (node.type === 'ChainExpression' && !node.computed) {
1951
1800
  const expression = node.expression;
1952
1801
  if (expression.type === 'CallExpression') {
1953
- throw new Error(`Unsupported node type: ${expression.type}`);
1802
+ throw new Error("Unsupported node type: ".concat(expression.type));
1954
1803
  }
1955
1804
  const object = analyzePropertyChain(expression.object, optionalChains);
1956
1805
  const property = analyzePropertyChain(expression.property, null);
1957
- const result = `${object}.${property}`;
1806
+ const result = "".concat(object, ".").concat(property);
1958
1807
  markNode(expression, optionalChains, result);
1959
1808
  return result;
1960
1809
  }
1961
- throw new Error(`Unsupported node type: ${node.type}`);
1810
+ throw new Error("Unsupported node type: ".concat(node.type));
1962
1811
  }
1963
1812
  function getNodeWithoutReactNamespace(node) {
1964
- if (
1965
- node.type === 'MemberExpression' &&
1966
- node.object.type === 'Identifier' &&
1967
- node.object.name === 'React' &&
1968
- node.property.type === 'Identifier' &&
1969
- !node.computed
1970
- ) {
1813
+ if (node.type === 'MemberExpression' && node.object.type === 'Identifier' && node.object.name === 'React' && node.property.type === 'Identifier' && !node.computed) {
1971
1814
  return node.property;
1972
1815
  }
1973
1816
  return node;
@@ -2046,28 +1889,17 @@ function joinEnglish(arr) {
2046
1889
  return s;
2047
1890
  }
2048
1891
  function isNodeLike(val) {
2049
- return (
2050
- typeof val === 'object' &&
2051
- val != null &&
2052
- !Array.isArray(val) &&
2053
- typeof val.type === 'string'
2054
- );
1892
+ return typeof val === 'object' && val != null && !Array.isArray(val) && typeof val.type === 'string';
2055
1893
  }
2056
1894
  function isSameIdentifier(a, b) {
2057
- return (
2058
- (a.type === 'Identifier' || a.type === 'JSXIdentifier') &&
2059
- a.type === b.type &&
2060
- a.name === b.name &&
2061
- a.range[0] === b.range[0] &&
2062
- a.range[1] === b.range[1]
2063
- );
1895
+ return (a.type === 'Identifier' || a.type === 'JSXIdentifier') && a.type === b.type && a.name === b.name && a.range[0] === b.range[0] && a.range[1] === b.range[1];
2064
1896
  }
2065
1897
  function isAncestorNodeOf(a, b) {
2066
1898
  return a.range[0] <= b.range[0] && a.range[1] >= b.range[1];
2067
1899
  }
2068
1900
 
2069
1901
  const Components = require('eslint-plugin-react/lib/util/Components');
2070
- var hookUseRef = {
1902
+ var reactHookUseRef = {
2071
1903
  meta: {
2072
1904
  docs: {
2073
1905
  description: 'Ensure naming of useRef hook value.',
@@ -2075,12 +1907,14 @@ var hookUseRef = {
2075
1907
  },
2076
1908
  schema: [],
2077
1909
  type: 'suggestion',
2078
- hasSuggestions: true
1910
+ hasSuggestions: true,
1911
+ messages: {
1912
+ useRefName: 'useRef call is not end with "Ref"'
1913
+ }
2079
1914
  },
2080
1915
  create: Components.detect((context, component, util) => ({
2081
1916
  CallExpression(node) {
2082
- const isImmediateReturn =
2083
- node.parent && node.parent.type === 'ReturnStatement';
1917
+ const isImmediateReturn = node.parent && node.parent.type === 'ReturnStatement';
2084
1918
  if (isImmediateReturn || !util.isReactHookCall(node, ['useRef'])) {
2085
1919
  return;
2086
1920
  }
@@ -2091,7 +1925,7 @@ var hookUseRef = {
2091
1925
  if (!variable.endsWith('Ref')) {
2092
1926
  context.report({
2093
1927
  node: node,
2094
- message: 'useRef call is not end with "Ref"'
1928
+ messageId: 'useRefName'
2095
1929
  });
2096
1930
  }
2097
1931
  }
@@ -2100,54 +1934,39 @@ var hookUseRef = {
2100
1934
 
2101
1935
  function* updateImportStatement(context, fixer, key) {
2102
1936
  const sourceCode = context.sourceCode;
2103
- const importNode = sourceCode.ast.body.find(
2104
- node => node.type === 'ImportDeclaration' && node.source.value === 'react'
2105
- );
1937
+ const importNode = sourceCode.ast.body.find(node => node.type === 'ImportDeclaration' && node.source.value === 'react');
2106
1938
  if (!importNode) {
2107
- yield fixer.insertTextBefore(
2108
- sourceCode.ast.body[0],
2109
- `import { ${key} } from 'react';\n`
2110
- );
1939
+ yield fixer.insertTextBefore(sourceCode.ast.body[0], "import { ".concat(key, " } from 'react';\n"));
2111
1940
  return;
2112
1941
  }
2113
- if (
2114
- importNode.specifiers.length === 1 &&
2115
- importNode.specifiers[0].type === 'ImportDefaultSpecifier'
2116
- ) {
2117
- yield fixer.insertTextAfter(importNode.specifiers[0], `, { ${key} }`);
1942
+ if (importNode.specifiers.length === 1 && importNode.specifiers[0].type === 'ImportDefaultSpecifier') {
1943
+ yield fixer.insertTextAfter(importNode.specifiers[0], ", { ".concat(key, " }"));
2118
1944
  return;
2119
1945
  }
2120
- const alreadyImportedKeys = importNode.specifiers
2121
- .filter(specifier => specifier.type === 'ImportSpecifier')
2122
- .map(specifier => specifier.imported.name);
1946
+ const alreadyImportedKeys = importNode.specifiers.filter(specifier => specifier.type === 'ImportSpecifier').map(specifier => specifier.imported.name);
2123
1947
  if (alreadyImportedKeys.includes(key)) {
2124
1948
  return;
2125
1949
  }
2126
- yield fixer.insertTextAfter([...importNode.specifiers].pop(), `, ${key}`);
1950
+ yield fixer.insertTextAfter([...importNode.specifiers].pop(), ", ".concat(key));
2127
1951
  }
2128
- var preferNamedPropertyAccess = utils.ESLintUtils.RuleCreator.withoutDocs({
1952
+ var reactPreferNamedPropertyAccess = utils.ESLintUtils.RuleCreator.withoutDocs({
2129
1953
  defaultOptions: [],
2130
1954
  meta: {
2131
1955
  type: 'layout',
2132
1956
  fixable: 'code',
2133
1957
  docs: {
2134
- description:
2135
- 'Enforce importing each member of React namespace separately instead of accessing them through React namespace',
1958
+ description: 'Enforce importing each member of React namespace separately instead of accessing them through React namespace',
2136
1959
  recommended: 'recommended'
2137
1960
  },
2138
1961
  messages: {
2139
- illegalReactPropertyAccess:
2140
- 'Illegal React property access: {{name}}. Use named import instead.'
1962
+ illegalReactPropertyAccess: 'Illegal React property access: {{name}}. Use named import instead.'
2141
1963
  },
2142
1964
  schema: []
2143
1965
  },
2144
1966
  create(context) {
2145
1967
  return {
2146
1968
  TSQualifiedName(node) {
2147
- if (
2148
- ('name' in node.left && node.left.name !== 'React') ||
2149
- ('name' in node.right && node.right.name.endsWith('Event'))
2150
- ) {
1969
+ if ('name' in node.left && node.left.name !== 'React' || 'name' in node.right && node.right.name.endsWith('Event')) {
2151
1970
  return;
2152
1971
  }
2153
1972
  context.report({
@@ -2182,7 +2001,7 @@ var preferNamedPropertyAccess = utils.ESLintUtils.RuleCreator.withoutDocs({
2182
2001
  }
2183
2002
  });
2184
2003
 
2185
- var preferSxProp = {
2004
+ var reactPreferSxProp = {
2186
2005
  meta: {
2187
2006
  docs: {
2188
2007
  description: 'Prefer using sx prop instead of inline styles',
@@ -2190,36 +2009,29 @@ var preferSxProp = {
2190
2009
  recommended: true
2191
2010
  },
2192
2011
  messages: {
2193
- preferSxProp:
2194
- 'Avoid using inline styles, use sx prop or tss-react or styled-component instead'
2012
+ preferSxProp: 'Avoid using inline styles, use sx prop or tss-react or styled-component instead'
2195
2013
  },
2196
- schema: [
2197
- {
2198
- type: 'object',
2199
- properties: {
2200
- allowedFor: {
2201
- type: 'array',
2202
- uniqueItems: true,
2203
- items: { type: 'string' }
2014
+ schema: [{
2015
+ type: 'object',
2016
+ properties: {
2017
+ allowedFor: {
2018
+ type: 'array',
2019
+ uniqueItems: true,
2020
+ items: {
2021
+ type: 'string'
2204
2022
  }
2205
2023
  }
2206
2024
  }
2207
- ]
2025
+ }]
2208
2026
  },
2209
2027
  create(context) {
2210
2028
  const configuration = context.options[0] || {};
2211
2029
  const allowedFor = configuration.allowedFor || [];
2212
2030
  function checkComponent(node) {
2213
2031
  const parentName = node.parent.name;
2214
- const tag =
2215
- parentName.name ||
2216
- `${parentName.object.name}.${parentName.property.name}`;
2032
+ const tag = parentName.name || "".concat(parentName.object.name, ".").concat(parentName.property.name);
2217
2033
  const componentName = parentName.name || parentName.property.name;
2218
- if (
2219
- componentName &&
2220
- typeof componentName[0] === 'string' &&
2221
- componentName[0] !== componentName[0].toUpperCase()
2222
- ) {
2034
+ if (componentName && typeof componentName[0] === 'string' && componentName[0] !== componentName[0].toUpperCase()) {
2223
2035
  return;
2224
2036
  }
2225
2037
  if (allowedFor.includes(tag)) {
@@ -2235,9 +2047,7 @@ var preferSxProp = {
2235
2047
  }
2236
2048
  function checkDOMNodes(node) {
2237
2049
  const tag = node.parent.name.name;
2238
- if (
2239
- !(tag && typeof tag === 'string' && tag[0] !== tag[0].toUpperCase())
2240
- ) {
2050
+ if (!(tag && typeof tag === 'string' && tag[0] !== tag[0].toUpperCase())) {
2241
2051
  return;
2242
2052
  }
2243
2053
  if (allowedFor.includes(tag)) {
@@ -2277,25 +2087,24 @@ function getBasicIdentifier(node) {
2277
2087
  }
2278
2088
  function getBaseIdentifier(node) {
2279
2089
  switch (node.type) {
2280
- case 'Identifier': {
2281
- return node;
2282
- }
2283
- case 'CallExpression': {
2284
- return getBaseIdentifier(node.callee);
2285
- }
2286
- case 'MemberExpression': {
2287
- return getBaseIdentifier(node.object);
2288
- }
2090
+ case 'Identifier':
2091
+ {
2092
+ return node;
2093
+ }
2094
+ case 'CallExpression':
2095
+ {
2096
+ return getBaseIdentifier(node.callee);
2097
+ }
2098
+ case 'MemberExpression':
2099
+ {
2100
+ return getBaseIdentifier(node.object);
2101
+ }
2289
2102
  }
2290
2103
  return null;
2291
2104
  }
2292
2105
  function getStyesObj(node) {
2293
2106
  const isMakeStyles = node.callee.name === 'makeStyles';
2294
- const isModernApi =
2295
- node.callee.type === 'MemberExpression' &&
2296
- node.callee.property.name === 'create' &&
2297
- getBaseIdentifier(node.callee.object) &&
2298
- getBaseIdentifier(node.callee.object).name === 'tss';
2107
+ const isModernApi = node.callee.type === 'MemberExpression' && node.callee.property.name === 'create' && getBaseIdentifier(node.callee.object) && getBaseIdentifier(node.callee.object).name === 'tss';
2299
2108
  if (!isMakeStyles && !isModernApi) {
2300
2109
  return;
2301
2110
  }
@@ -2315,35 +2124,51 @@ function getStyesObj(node) {
2315
2124
  return styles;
2316
2125
  case 'ArrowFunctionExpression':
2317
2126
  {
2318
- const { body } = styles;
2127
+ const {
2128
+ body
2129
+ } = styles;
2319
2130
  switch (body.type) {
2320
2131
  case 'ObjectExpression':
2321
2132
  return body;
2322
- case 'BlockStatement': {
2323
- let stylesObj;
2324
- body.body.forEach(bodyNode => {
2325
- if (
2326
- bodyNode.type === 'ReturnStatement' &&
2327
- bodyNode.argument.type === 'ObjectExpression'
2328
- ) {
2329
- stylesObj = bodyNode.argument;
2330
- }
2331
- });
2332
- return stylesObj;
2333
- }
2133
+ case 'BlockStatement':
2134
+ {
2135
+ let stylesObj;
2136
+ body.body.forEach(bodyNode => {
2137
+ if (bodyNode.type === 'ReturnStatement' && bodyNode.argument.type === 'ObjectExpression') {
2138
+ stylesObj = bodyNode.argument;
2139
+ }
2140
+ });
2141
+ return stylesObj;
2142
+ }
2334
2143
  }
2335
2144
  }
2336
2145
  break;
2337
2146
  }
2338
2147
  }
2148
+ function loopStylesObj(node, callback) {
2149
+ if (node && node.type === 'ObjectExpression') {
2150
+ node.properties.forEach(property => {
2151
+ if (property.type === 'Property' && property.value) {
2152
+ if (property.value.type === 'ObjectExpression') {
2153
+ loopStylesObj(property.value, callback);
2154
+ } else {
2155
+ callback(property.value);
2156
+ }
2157
+ }
2158
+ });
2159
+ }
2160
+ }
2339
2161
 
2340
- var classNaming = {
2162
+ var tssClassNaming = {
2341
2163
  meta: {
2342
2164
  type: 'problem',
2343
2165
  docs: {
2344
2166
  description: 'Enforce camelCase class names in TSS',
2345
2167
  category: 'Best Practices',
2346
2168
  recommended: true
2169
+ },
2170
+ messages: {
2171
+ camelCase: 'Class `{{ className }}` must be camelCase in TSS.'
2347
2172
  }
2348
2173
  },
2349
2174
  create: function rule(context) {
@@ -2357,17 +2182,17 @@ var classNaming = {
2357
2182
  if (property.computed) {
2358
2183
  return;
2359
2184
  }
2360
- if (
2361
- property.type === 'ExperimentalSpreadProperty' ||
2362
- property.type === 'SpreadElement'
2363
- ) {
2185
+ if (property.type === 'ExperimentalSpreadProperty' || property.type === 'SpreadElement') {
2364
2186
  return;
2365
2187
  }
2366
2188
  const className = property.key.value || property.key.name;
2367
2189
  if (!eslintUtils.isCamelCase(className)) {
2368
2190
  context.report({
2369
2191
  node: property,
2370
- message: `Class \`${className}\` must be camelCase in TSS.`
2192
+ messageId: 'camelCase',
2193
+ data: {
2194
+ className
2195
+ }
2371
2196
  });
2372
2197
  }
2373
2198
  });
@@ -2376,20 +2201,201 @@ var classNaming = {
2376
2201
  }
2377
2202
  };
2378
2203
 
2379
- var noColorValue = {
2204
+ var colors = {
2205
+ aliceblue: [240, 248, 255],
2206
+ antiquewhite: [250, 235, 215],
2207
+ aqua: [0, 255, 255],
2208
+ aquamarine: [127, 255, 212],
2209
+ azure: [240, 255, 255],
2210
+ beige: [245, 245, 220],
2211
+ bisque: [255, 228, 196],
2212
+ black: [0, 0, 0],
2213
+ blanchedalmond: [255, 235, 205],
2214
+ blue: [0, 0, 255],
2215
+ blueviolet: [138, 43, 226],
2216
+ brown: [165, 42, 42],
2217
+ burlywood: [222, 184, 135],
2218
+ cadetblue: [95, 158, 160],
2219
+ chartreuse: [127, 255, 0],
2220
+ chocolate: [210, 105, 30],
2221
+ coral: [255, 127, 80],
2222
+ cornflowerblue: [100, 149, 237],
2223
+ cornsilk: [255, 248, 220],
2224
+ crimson: [220, 20, 60],
2225
+ cyan: [0, 255, 255],
2226
+ darkblue: [0, 0, 139],
2227
+ darkcyan: [0, 139, 139],
2228
+ darkgoldenrod: [184, 134, 11],
2229
+ darkgray: [169, 169, 169],
2230
+ darkgreen: [0, 100, 0],
2231
+ darkgrey: [169, 169, 169],
2232
+ darkkhaki: [189, 183, 107],
2233
+ darkmagenta: [139, 0, 139],
2234
+ darkolivegreen: [85, 107, 47],
2235
+ darkorange: [255, 140, 0],
2236
+ darkorchid: [153, 50, 204],
2237
+ darkred: [139, 0, 0],
2238
+ darksalmon: [233, 150, 122],
2239
+ darkseagreen: [143, 188, 143],
2240
+ darkslateblue: [72, 61, 139],
2241
+ darkslategray: [47, 79, 79],
2242
+ darkslategrey: [47, 79, 79],
2243
+ darkturquoise: [0, 206, 209],
2244
+ darkviolet: [148, 0, 211],
2245
+ deeppink: [255, 20, 147],
2246
+ deepskyblue: [0, 191, 255],
2247
+ dimgray: [105, 105, 105],
2248
+ dimgrey: [105, 105, 105],
2249
+ dodgerblue: [30, 144, 255],
2250
+ firebrick: [178, 34, 34],
2251
+ floralwhite: [255, 250, 240],
2252
+ forestgreen: [34, 139, 34],
2253
+ fuchsia: [255, 0, 255],
2254
+ gainsboro: [220, 220, 220],
2255
+ ghostwhite: [248, 248, 255],
2256
+ gold: [255, 215, 0],
2257
+ goldenrod: [218, 165, 32],
2258
+ gray: [128, 128, 128],
2259
+ green: [0, 128, 0],
2260
+ greenyellow: [173, 255, 47],
2261
+ grey: [128, 128, 128],
2262
+ honeydew: [240, 255, 240],
2263
+ hotpink: [255, 105, 180],
2264
+ indianred: [205, 92, 92],
2265
+ indigo: [75, 0, 130],
2266
+ ivory: [255, 255, 240],
2267
+ khaki: [240, 230, 140],
2268
+ lavender: [230, 230, 250],
2269
+ lavenderblush: [255, 240, 245],
2270
+ lawngreen: [124, 252, 0],
2271
+ lemonchiffon: [255, 250, 205],
2272
+ lightblue: [173, 216, 230],
2273
+ lightcoral: [240, 128, 128],
2274
+ lightcyan: [224, 255, 255],
2275
+ lightgoldenrodyellow: [250, 250, 210],
2276
+ lightgray: [211, 211, 211],
2277
+ lightgreen: [144, 238, 144],
2278
+ lightgrey: [211, 211, 211],
2279
+ lightpink: [255, 182, 193],
2280
+ lightsalmon: [255, 160, 122],
2281
+ lightseagreen: [32, 178, 170],
2282
+ lightskyblue: [135, 206, 250],
2283
+ lightslategray: [119, 136, 153],
2284
+ lightslategrey: [119, 136, 153],
2285
+ lightsteelblue: [176, 196, 222],
2286
+ lightyellow: [255, 255, 224],
2287
+ lime: [0, 255, 0],
2288
+ limegreen: [50, 205, 50],
2289
+ linen: [250, 240, 230],
2290
+ magenta: [255, 0, 255],
2291
+ maroon: [128, 0, 0],
2292
+ mediumaquamarine: [102, 205, 170],
2293
+ mediumblue: [0, 0, 205],
2294
+ mediumorchid: [186, 85, 211],
2295
+ mediumpurple: [147, 112, 219],
2296
+ mediumseagreen: [60, 179, 113],
2297
+ mediumslateblue: [123, 104, 238],
2298
+ mediumspringgreen: [0, 250, 154],
2299
+ mediumturquoise: [72, 209, 204],
2300
+ mediumvioletred: [199, 21, 133],
2301
+ midnightblue: [25, 25, 112],
2302
+ mintcream: [245, 255, 250],
2303
+ mistyrose: [255, 228, 225],
2304
+ moccasin: [255, 228, 181],
2305
+ navajowhite: [255, 222, 173],
2306
+ navy: [0, 0, 128],
2307
+ oldlace: [253, 245, 230],
2308
+ olive: [128, 128, 0],
2309
+ olivedrab: [107, 142, 35],
2310
+ orange: [255, 165, 0],
2311
+ orangered: [255, 69, 0],
2312
+ orchid: [218, 112, 214],
2313
+ palegoldenrod: [238, 232, 170],
2314
+ palegreen: [152, 251, 152],
2315
+ paleturquoise: [175, 238, 238],
2316
+ palevioletred: [219, 112, 147],
2317
+ papayawhip: [255, 239, 213],
2318
+ peachpuff: [255, 218, 185],
2319
+ peru: [205, 133, 63],
2320
+ pink: [255, 192, 203],
2321
+ plum: [221, 160, 221],
2322
+ powderblue: [176, 224, 230],
2323
+ purple: [128, 0, 128],
2324
+ rebeccapurple: [102, 51, 153],
2325
+ red: [255, 0, 0],
2326
+ rosybrown: [188, 143, 143],
2327
+ royalblue: [65, 105, 225],
2328
+ saddlebrown: [139, 69, 19],
2329
+ salmon: [250, 128, 114],
2330
+ sandybrown: [244, 164, 96],
2331
+ seagreen: [46, 139, 87],
2332
+ seashell: [255, 245, 238],
2333
+ sienna: [160, 82, 45],
2334
+ silver: [192, 192, 192],
2335
+ skyblue: [135, 206, 235],
2336
+ slateblue: [106, 90, 205],
2337
+ slategray: [112, 128, 144],
2338
+ slategrey: [112, 128, 144],
2339
+ snow: [255, 250, 250],
2340
+ springgreen: [0, 255, 127],
2341
+ steelblue: [70, 130, 180],
2342
+ tan: [210, 180, 140],
2343
+ teal: [0, 128, 128],
2344
+ thistle: [216, 191, 216],
2345
+ tomato: [255, 99, 71],
2346
+ turquoise: [64, 224, 208],
2347
+ violet: [238, 130, 238],
2348
+ wheat: [245, 222, 179],
2349
+ white: [255, 255, 255],
2350
+ whitesmoke: [245, 245, 245],
2351
+ yellow: [255, 255, 0],
2352
+ yellowgreen: [154, 205, 50]
2353
+ };
2354
+
2355
+ var tssNoColorName = {
2380
2356
  meta: {
2381
- type: 'problem',
2357
+ type: 'suggestion',
2382
2358
  docs: {
2383
- description:
2384
- 'Enforce the use of color variables instead of color codes within TSS',
2359
+ description: 'Enforce the use of color variables instead of color name within TSS',
2385
2360
  recommended: true
2361
+ },
2362
+ messages: {
2363
+ disallowColorName: 'Disallowed color name. Use color from `@mui/material/colors` or `theme.palette`.'
2386
2364
  }
2387
2365
  },
2388
2366
  create: function (context) {
2389
- const parserOptions = context.parserOptions;
2390
- if (!parserOptions || !parserOptions.project) {
2391
- return {};
2367
+ return {
2368
+ CallExpression(node) {
2369
+ const stylesObj = getStyesObj(node);
2370
+ if (!stylesObj) {
2371
+ return;
2372
+ }
2373
+ function checkColorLiteral(value) {
2374
+ if (value.type === 'Literal' && typeof value.value === 'string' && Object.keys(colors).includes(value.value.toLowerCase())) {
2375
+ context.report({
2376
+ node: value,
2377
+ messageId: 'disallowColorName'
2378
+ });
2379
+ }
2380
+ }
2381
+ loopStylesObj(stylesObj, checkColorLiteral);
2382
+ }
2383
+ };
2384
+ }
2385
+ };
2386
+
2387
+ var tssNoColorValue = {
2388
+ meta: {
2389
+ type: 'problem',
2390
+ docs: {
2391
+ description: 'Enforce the use of color variables instead of color codes within TSS',
2392
+ recommended: true
2393
+ },
2394
+ messages: {
2395
+ preferMuiColor: 'Prefer use color from `@mui/material/colors` or `theme.palette`.'
2392
2396
  }
2397
+ },
2398
+ create: function (context) {
2393
2399
  return {
2394
2400
  CallExpression(node) {
2395
2401
  const stylesObj = getStyesObj(node);
@@ -2398,43 +2404,31 @@ var noColorValue = {
2398
2404
  }
2399
2405
  function checkColorLiteral(value) {
2400
2406
  if (value.type === 'Literal' && typeof value.value === 'string') {
2401
- const colorCodePattern =
2402
- /#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})|rgb\?\(\s*(\d{1,3}\s*,\s*){2}\d{1,3}(?:\s*,\s*\d*(?:\.\d+)?)?\s*\)/g;
2403
- const isColorCode = colorCodePattern.test(value.value);
2404
- if (isColorCode) {
2407
+ const colorCodePattern = /#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})|rgb\?\(\s*(\d{1,3}\s*,\s*){2}\d{1,3}(?:\s*,\s*\d*(?:\.\d+)?)?\s*\)/g;
2408
+ if (colorCodePattern.test(value.value)) {
2405
2409
  context.report({
2406
2410
  node: value,
2407
- message: 'Use color variables instead of color codes in TSS.'
2411
+ messageId: 'preferMuiColor'
2408
2412
  });
2409
2413
  }
2410
2414
  }
2411
2415
  }
2412
- function loopStylesObj(obj) {
2413
- if (obj && obj.type === 'ObjectExpression') {
2414
- obj.properties.forEach(property => {
2415
- if (property.type === 'Property' && property.value) {
2416
- if (property.value.type === 'ObjectExpression') {
2417
- loopStylesObj(property.value);
2418
- } else {
2419
- checkColorLiteral(property.value);
2420
- }
2421
- }
2422
- });
2423
- }
2424
- }
2425
- loopStylesObj(stylesObj);
2416
+ loopStylesObj(stylesObj, checkColorLiteral);
2426
2417
  }
2427
2418
  };
2428
2419
  }
2429
2420
  };
2430
2421
 
2431
- var unusedClasses = {
2422
+ var tssUnusedClasses = {
2432
2423
  meta: {
2433
2424
  type: 'suggestion',
2434
2425
  docs: {
2435
2426
  description: 'Disallow unused classes in tss',
2436
2427
  category: 'Best Practices',
2437
2428
  recommended: true
2429
+ },
2430
+ messages: {
2431
+ unusedClass: 'Class `{{ className }}` is unused in JSX'
2438
2432
  }
2439
2433
  },
2440
2434
  create: function rule(context) {
@@ -2450,20 +2444,14 @@ var unusedClasses = {
2450
2444
  if (property.computed) {
2451
2445
  return;
2452
2446
  }
2453
- if (
2454
- property.type === 'ExperimentalSpreadProperty' ||
2455
- property.type === 'SpreadElement'
2456
- ) {
2447
+ if (property.type === 'ExperimentalSpreadProperty' || property.type === 'SpreadElement') {
2457
2448
  return;
2458
2449
  }
2459
2450
  definedClasses[property.key.value || property.key.name] = property;
2460
2451
  });
2461
2452
  },
2462
2453
  MemberExpression(node) {
2463
- if (
2464
- node.object.type === 'Identifier' &&
2465
- node.object.name === 'classes'
2466
- ) {
2454
+ if (node.object.type === 'Identifier' && node.object.name === 'classes') {
2467
2455
  const whichClass = getBasicIdentifier(node.property);
2468
2456
  if (whichClass) {
2469
2457
  usedClasses[whichClass] = true;
@@ -2477,14 +2465,15 @@ var unusedClasses = {
2477
2465
  if (classIdentifier !== 'classes') {
2478
2466
  return;
2479
2467
  }
2480
- const { parent } = node;
2468
+ const {
2469
+ parent
2470
+ } = node;
2481
2471
  if (parent.type !== 'MemberExpression') {
2482
2472
  return;
2483
2473
  }
2484
2474
  if (
2485
- node.object.object &&
2486
- node.object.object.type !== 'ThisExpression'
2487
- ) {
2475
+ node.object.object &&
2476
+ node.object.object.type !== 'ThisExpression') {
2488
2477
  return;
2489
2478
  }
2490
2479
  const propsIdentifier = getBasicIdentifier(parent.object);
@@ -2507,7 +2496,10 @@ var unusedClasses = {
2507
2496
  if (!usedClasses[definedClassKey]) {
2508
2497
  context.report({
2509
2498
  node: definedClasses[definedClassKey],
2510
- message: `Class \`${definedClassKey}\` is unused`
2499
+ messageId: 'unusedClass',
2500
+ data: {
2501
+ className: definedClassKey
2502
+ }
2511
2503
  });
2512
2504
  }
2513
2505
  });
@@ -2516,177 +2508,27 @@ var unusedClasses = {
2516
2508
  }
2517
2509
  };
2518
2510
 
2519
- var noAsyncArrayMethods = {
2520
- meta: {
2521
- docs: {
2522
- description:
2523
- 'No async callback for Array methods forEach, map, filter, reduce, some, every, etc.',
2524
- category: 'Array',
2525
- recommended: true
2526
- },
2527
- fixable: undefined,
2528
- schema: []
2529
- },
2530
- create: function (context) {
2531
- return {
2532
- ExpressionStatement: function (node) {
2533
- const notAllowedArrayMethods = [
2534
- 'forEach',
2535
- 'filter',
2536
- 'some',
2537
- 'every',
2538
- 'map',
2539
- 'reduce',
2540
- 'reduceRight',
2541
- 'flatMap',
2542
- 'find',
2543
- 'findIndex',
2544
- 'findLast',
2545
- 'findLastIndex'
2546
- ];
2547
- const { callee } = node.expression;
2548
- if (!callee || !callee.property || !callee.property.name) {
2549
- return;
2550
- }
2551
- if (notAllowedArrayMethods.includes(callee.property.name)) {
2552
- const functionArguments = node.expression.arguments.find(n => {
2553
- return ['ArrowFunctionExpression', 'FunctionExpression'].includes(
2554
- n.type
2555
- );
2556
- });
2557
- if (functionArguments && functionArguments.async) {
2558
- context.report({
2559
- node,
2560
- message: `No async function in method '${callee.property.name}'`
2561
- });
2562
- }
2563
- }
2564
- }
2565
- };
2566
- }
2567
- };
2568
-
2569
- var noThenCatchFinally = {
2570
- meta: {
2571
- type: 'suggestion',
2572
- docs: {
2573
- description:
2574
- 'Disallow the use of then()/catch()/finally() when invoking specific functions.'
2575
- },
2576
- schema: [
2577
- {
2578
- type: 'object',
2579
- properties: {
2580
- restrictedFunctions: {
2581
- type: 'array',
2582
- uniqueItems: true,
2583
- items: { type: 'string' }
2584
- }
2585
- }
2586
- }
2587
- ],
2588
- messages: {
2589
- forbiddenThenCatchFinally: `then()/catch()/finally() is forbidden when invoke {{ name }}().`
2590
- }
2591
- },
2592
- create(context) {
2593
- const configuration = context.options[0] || {};
2594
- const restrictedFunctions = configuration.restrictedFunctions || [];
2595
- function isTopLevelScoped() {
2596
- return context.getScope().block.type === 'Program';
2597
- }
2598
- function isThenCatchFinally(node) {
2599
- return (
2600
- node.property &&
2601
- (node.property.name === 'then' ||
2602
- node.property.name === 'catch' ||
2603
- node.property.name === 'finally')
2604
- );
2605
- }
2606
- return {
2607
- 'CallExpression > MemberExpression.callee'(node) {
2608
- if (isTopLevelScoped()) {
2609
- return;
2610
- }
2611
- if (!isThenCatchFinally(node)) {
2612
- return;
2613
- }
2614
- const callExpression = node.object;
2615
- if (
2616
- callExpression.type === 'CallExpression' &&
2617
- callExpression.callee.type === 'Identifier' &&
2618
- restrictedFunctions.includes(callExpression.callee.name)
2619
- ) {
2620
- context.report({
2621
- node: node.property,
2622
- messageId: 'forbiddenThenCatchFinally',
2623
- data: {
2624
- name: callExpression.callee.name
2625
- }
2626
- });
2627
- }
2628
- }
2629
- };
2630
- }
2631
- };
2632
-
2633
- var noUnnecessaryTemplateLiterals = {
2634
- meta: {
2635
- type: 'problem',
2636
- docs: {
2637
- description: 'Check if a template string contains only one ${}',
2638
- recommended: true
2639
- },
2640
- fixable: 'code',
2641
- schema: [],
2642
- messages: {
2643
- unnecessaryTemplateString:
2644
- 'Unnecessary template string with only one ${}.'
2645
- }
2646
- },
2647
- create(context) {
2648
- return {
2649
- TemplateLiteral(node) {
2650
- const code = context.sourceCode.getText(node);
2651
- if (
2652
- code.startsWith('`${') &&
2653
- code.endsWith('}`') &&
2654
- code.split('${').length === 2
2655
- ) {
2656
- context.report({
2657
- node,
2658
- messageId: 'unnecessaryTemplateString',
2659
- fix(fixer) {
2660
- return fixer.replaceText(
2661
- node,
2662
- code.substring(3, code.length - 2)
2663
- );
2664
- }
2665
- });
2666
- }
2667
- }
2668
- };
2669
- }
2670
- };
2671
-
2672
2511
  var ruleFiles = /*#__PURE__*/Object.freeze({
2673
2512
  __proto__: null,
2674
- rules_import_enforce_icon_alias: enforceIconAlias,
2675
- rules_import_monorepo: monorepo,
2676
- rules_intl_id_missing: idMissing,
2677
- rules_intl_id_prefix: idPrefix,
2678
- rules_intl_id_unused: idUnused,
2679
- rules_intl_no_default: noDefault,
2680
- rules_react_better_exhaustive_deps: betterExhaustiveDeps,
2681
- rules_react_hook_use_ref: hookUseRef,
2682
- rules_react_prefer_named_property_access: preferNamedPropertyAccess,
2683
- rules_react_prefer_sx_prop: preferSxProp,
2684
- rules_tss_class_naming: classNaming,
2685
- rules_tss_no_color_value: noColorValue,
2686
- rules_tss_unused_classes: unusedClasses,
2687
- rules_unprefixed_no_async_array_methods: noAsyncArrayMethods,
2688
- rules_unprefixed_no_then_catch_finally: noThenCatchFinally,
2689
- rules_unprefixed_no_unnecessary_template_literals: noUnnecessaryTemplateLiterals
2513
+ rules_enforce_mui_icon_alias: enforceMuiIconAlias,
2514
+ rules_import_monorepo: importMonorepo,
2515
+ rules_intl_id_missing: intlIdMissing,
2516
+ rules_intl_id_naming: intlIdNaming,
2517
+ rules_intl_id_prefix: intlIdPrefix,
2518
+ rules_intl_id_unused: intlIdUnused,
2519
+ rules_intl_no_default: intlNoDefault,
2520
+ rules_no_async_array_methods: noAsyncArrayMethods,
2521
+ rules_no_import_css: noImportCss,
2522
+ rules_no_then_catch_finally: noThenCatchFinally,
2523
+ rules_no_unnecessary_template_literals: noUnnecessaryTemplateLiterals,
2524
+ rules_react_better_exhaustive_deps: reactBetterExhaustiveDeps,
2525
+ rules_react_hook_use_ref: reactHookUseRef,
2526
+ rules_react_prefer_named_property_access: reactPreferNamedPropertyAccess,
2527
+ rules_react_prefer_sx_prop: reactPreferSxProp,
2528
+ rules_tss_class_naming: tssClassNaming,
2529
+ rules_tss_no_color_name: tssNoColorName,
2530
+ rules_tss_no_color_value: tssNoColorValue,
2531
+ rules_tss_unused_classes: tssUnusedClasses
2690
2532
  });
2691
2533
 
2692
2534
  const plugin = {
@@ -2704,13 +2546,12 @@ const plugin = {
2704
2546
  }
2705
2547
  };
2706
2548
  Object.keys(ruleFiles).forEach(key => {
2707
- const ruleKey = key.replace(/^rules_/, '').replace(/^unprefixed_/, '');
2549
+ const ruleKey = key.replace(/^rules_/, '');
2708
2550
  const finalKey = ruleKey.replace(/_/g, '-');
2709
2551
  const rule = ruleFiles[key];
2710
2552
  plugin.rules[finalKey] = rule;
2711
2553
  if (rule.meta && rule.meta.docs && rule.meta.docs.recommended) {
2712
- plugin.configs.recommended.rules[`@agilebot/${finalKey}`] =
2713
- rule.meta.type === 'suggestion' ? 'warn' : 'error';
2554
+ plugin.configs.recommended.rules["@agilebot/".concat(finalKey)] = rule.meta.type === 'suggestion' ? 'warn' : 'error';
2714
2555
  }
2715
2556
  });
2716
2557