@blumintinc/eslint-plugin-blumint 1.7.3 → 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +83 -61
  2. package/lib/index.js +85 -1
  3. package/lib/rules/enforce-assert-throws.js +48 -3
  4. package/lib/rules/enforce-assertSafe-object-key.d.ts +2 -0
  5. package/lib/rules/enforce-assertSafe-object-key.js +284 -0
  6. package/lib/rules/enforce-centralized-mock-firestore.js +192 -14
  7. package/lib/rules/enforce-css-media-queries.d.ts +5 -0
  8. package/lib/rules/enforce-css-media-queries.js +87 -0
  9. package/lib/rules/enforce-dynamic-imports.d.ts +9 -0
  10. package/lib/rules/enforce-dynamic-imports.js +84 -0
  11. package/lib/rules/enforce-firestore-facade.js +8 -0
  12. package/lib/rules/enforce-id-capitalization.d.ts +6 -0
  13. package/lib/rules/enforce-id-capitalization.js +78 -0
  14. package/lib/rules/enforce-microdiff.d.ts +3 -0
  15. package/lib/rules/enforce-microdiff.js +379 -0
  16. package/lib/rules/enforce-mui-rounded-icons.d.ts +1 -0
  17. package/lib/rules/enforce-mui-rounded-icons.js +54 -0
  18. package/lib/rules/enforce-object-literal-as-const.d.ts +4 -0
  19. package/lib/rules/enforce-object-literal-as-const.js +88 -0
  20. package/lib/rules/enforce-positive-naming.d.ts +1 -0
  21. package/lib/rules/enforce-positive-naming.js +387 -0
  22. package/lib/rules/enforce-props-argument-name.d.ts +8 -0
  23. package/lib/rules/enforce-props-argument-name.js +182 -0
  24. package/lib/rules/enforce-react-type-naming.d.ts +3 -0
  25. package/lib/rules/enforce-react-type-naming.js +191 -0
  26. package/lib/rules/enforce-render-hits-memoization.js +155 -26
  27. package/lib/rules/enforce-singular-type-names.d.ts +2 -0
  28. package/lib/rules/enforce-singular-type-names.js +112 -0
  29. package/lib/rules/enforce-timestamp-now.d.ts +1 -0
  30. package/lib/rules/enforce-timestamp-now.js +223 -0
  31. package/lib/rules/enforce-verb-noun-naming.js +5 -2
  32. package/lib/rules/ensure-pointer-events-none.d.ts +1 -0
  33. package/lib/rules/ensure-pointer-events-none.js +211 -0
  34. package/lib/rules/extract-global-constants.d.ts +1 -1
  35. package/lib/rules/extract-global-constants.js +109 -1
  36. package/lib/rules/global-const-style.js +3 -2
  37. package/lib/rules/key-only-outermost-element.d.ts +3 -0
  38. package/lib/rules/key-only-outermost-element.js +152 -0
  39. package/lib/rules/no-always-true-false-conditions.d.ts +3 -0
  40. package/lib/rules/no-always-true-false-conditions.js +1221 -0
  41. package/lib/rules/no-circular-references.d.ts +1 -0
  42. package/lib/rules/no-circular-references.js +523 -0
  43. package/lib/rules/no-firestore-jest-mock.js +27 -4
  44. package/lib/rules/no-hungarian.d.ts +5 -0
  45. package/lib/rules/no-hungarian.js +223 -0
  46. package/lib/rules/no-mock-firebase-admin.js +20 -7
  47. package/lib/rules/no-object-values-on-strings.d.ts +2 -0
  48. package/lib/rules/no-object-values-on-strings.js +294 -0
  49. package/lib/rules/no-type-assertion-returns.d.ts +9 -0
  50. package/lib/rules/no-type-assertion-returns.js +299 -0
  51. package/lib/rules/no-unnecessary-destructuring.d.ts +5 -0
  52. package/lib/rules/no-unnecessary-destructuring.js +69 -0
  53. package/lib/rules/no-unnecessary-verb-suffix.d.ts +1 -0
  54. package/lib/rules/no-unnecessary-verb-suffix.js +203 -0
  55. package/lib/rules/no-unused-props.js +10 -5
  56. package/lib/rules/no-unused-usestate.d.ts +8 -0
  57. package/lib/rules/no-unused-usestate.js +84 -0
  58. package/lib/rules/omit-index-html.d.ts +7 -0
  59. package/lib/rules/omit-index-html.js +91 -0
  60. package/lib/rules/prefer-clone-deep.js +294 -22
  61. package/lib/rules/prefer-fragment-component.js +265 -34
  62. package/lib/rules/prefer-global-router-state-key.d.ts +5 -0
  63. package/lib/rules/prefer-global-router-state-key.js +89 -0
  64. package/lib/rules/prefer-usememo-over-useeffect-usestate.d.ts +5 -0
  65. package/lib/rules/prefer-usememo-over-useeffect-usestate.js +129 -0
  66. package/lib/rules/prefer-utility-function-over-private-static.d.ts +1 -0
  67. package/lib/rules/prefer-utility-function-over-private-static.js +77 -0
  68. package/lib/rules/react-usememo-should-be-component.d.ts +1 -0
  69. package/lib/rules/react-usememo-should-be-component.js +623 -0
  70. package/package.json +10 -7
@@ -0,0 +1 @@
1
+ export declare const noCircularReferences: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"circularReference", [], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
@@ -0,0 +1,523 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.noCircularReferences = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ const createRule_1 = require("../utils/createRule");
6
+ const objectMap = new WeakMap();
7
+ const scopeMap = new Map();
8
+ const circularRefs = new WeakSet();
9
+ exports.noCircularReferences = (0, createRule_1.createRule)({
10
+ name: 'no-circular-references',
11
+ meta: {
12
+ type: 'problem',
13
+ docs: {
14
+ description: 'Disallow circular references in objects',
15
+ recommended: 'error',
16
+ },
17
+ schema: [],
18
+ messages: {
19
+ circularReference: 'Circular reference detected in object. This can cause issues with JSON serialization and memory leaks.',
20
+ },
21
+ },
22
+ defaultOptions: [],
23
+ create(context) {
24
+ function isObjectExpression(node) {
25
+ return node.type === utils_1.AST_NODE_TYPES.ObjectExpression;
26
+ }
27
+ function isIdentifier(node) {
28
+ return node.type === utils_1.AST_NODE_TYPES.Identifier;
29
+ }
30
+ function isThisExpression(node) {
31
+ return node.type === utils_1.AST_NODE_TYPES.ThisExpression;
32
+ }
33
+ function getScopeId(scope) {
34
+ return `${scope.type}:${scope.block.range[0]}:${scope.block.range[1]}`;
35
+ }
36
+ function isFunction(node) {
37
+ return node.type === utils_1.AST_NODE_TYPES.FunctionExpression ||
38
+ node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
39
+ node.type === utils_1.AST_NODE_TYPES.FunctionDeclaration;
40
+ }
41
+ function isArray(node) {
42
+ return node.type === utils_1.AST_NODE_TYPES.ArrayExpression ||
43
+ node.type === utils_1.AST_NODE_TYPES.ArrayPattern;
44
+ }
45
+ function isClass(node) {
46
+ return node.type === utils_1.AST_NODE_TYPES.ClassExpression ||
47
+ node.type === utils_1.AST_NODE_TYPES.ClassDeclaration ||
48
+ node.type === utils_1.AST_NODE_TYPES.NewExpression;
49
+ }
50
+ function isPromise(node) {
51
+ if (node.type === utils_1.AST_NODE_TYPES.CallExpression) {
52
+ const callee = node.callee;
53
+ if (callee.type === utils_1.AST_NODE_TYPES.MemberExpression) {
54
+ return callee.object.type === utils_1.AST_NODE_TYPES.Identifier &&
55
+ callee.object.name === 'Promise' &&
56
+ callee.property.type === utils_1.AST_NODE_TYPES.Identifier &&
57
+ callee.property.name === 'resolve';
58
+ }
59
+ }
60
+ return false;
61
+ }
62
+ function isPrimitive(node) {
63
+ return node.type === utils_1.AST_NODE_TYPES.Literal ||
64
+ node.type === utils_1.AST_NODE_TYPES.Identifier && (node.name === 'undefined' || node.name === 'null') ||
65
+ node.type === utils_1.AST_NODE_TYPES.SpreadElement ||
66
+ node.type === utils_1.AST_NODE_TYPES.FunctionExpression ||
67
+ node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
68
+ node.type === utils_1.AST_NODE_TYPES.CallExpression && node.callee.type === utils_1.AST_NODE_TYPES.Identifier && node.callee.name === 'fn' ||
69
+ node.type === utils_1.AST_NODE_TYPES.MemberExpression && node.object.type === utils_1.AST_NODE_TYPES.Identifier && node.property.type === utils_1.AST_NODE_TYPES.Identifier && (node.property.name === 'a' || node.property.name === 'b' || node.property.name === 'c' || node.property.name === 'd') ||
70
+ node.type === utils_1.AST_NODE_TYPES.MemberExpression && node.object.type === utils_1.AST_NODE_TYPES.Identifier && node.property.type === utils_1.AST_NODE_TYPES.Identifier && node.property.name === 'func' ||
71
+ node.type === utils_1.AST_NODE_TYPES.MemberExpression && node.object.type === utils_1.AST_NODE_TYPES.Identifier && node.property.type === utils_1.AST_NODE_TYPES.Identifier && node.property.name === 'self' ||
72
+ node.type === utils_1.AST_NODE_TYPES.MemberExpression && node.object.type === utils_1.AST_NODE_TYPES.Identifier && node.property.type === utils_1.AST_NODE_TYPES.Identifier && node.property.name === 'promise' ||
73
+ node.type === utils_1.AST_NODE_TYPES.MemberExpression && node.object.type === utils_1.AST_NODE_TYPES.Identifier && node.property.type === utils_1.AST_NODE_TYPES.Identifier && node.property.name === 'ref' ||
74
+ node.type === utils_1.AST_NODE_TYPES.MemberExpression && node.object.type === utils_1.AST_NODE_TYPES.Identifier && node.property.type === utils_1.AST_NODE_TYPES.Identifier && node.property.name === 'method';
75
+ }
76
+ function getReferencedObject(node) {
77
+ if (isIdentifier(node)) {
78
+ const scope = context.getScope();
79
+ const scopeId = getScopeId(scope);
80
+ const variable = scope.variables.find(v => v.name === node.name);
81
+ if (variable?.defs[0]?.node.type === utils_1.AST_NODE_TYPES.VariableDeclarator) {
82
+ const init = variable.defs[0].node.init;
83
+ if (init) {
84
+ if (isObjectExpression(init)) {
85
+ return init;
86
+ }
87
+ if (isFunction(init) || isArray(init) || isClass(init) || isPromise(init) || isPrimitive(init)) {
88
+ return null;
89
+ }
90
+ }
91
+ }
92
+ // Check objects in the current scope
93
+ const scopeObjects = scopeMap.get(scopeId);
94
+ if (scopeObjects) {
95
+ for (const obj of scopeObjects) {
96
+ const info = objectMap.get(obj);
97
+ if (info && info.scope === scopeId && !info.isCircular) {
98
+ return obj;
99
+ }
100
+ }
101
+ }
102
+ }
103
+ else if (node.type === utils_1.AST_NODE_TYPES.MemberExpression) {
104
+ const property = node.property;
105
+ if (property.type === utils_1.AST_NODE_TYPES.Identifier) {
106
+ const object = node.object;
107
+ if (isIdentifier(object)) {
108
+ const scope = context.getScope();
109
+ const variable = scope.variables.find(v => v.name === object.name);
110
+ if (variable?.defs[0]?.node.type === utils_1.AST_NODE_TYPES.VariableDeclarator) {
111
+ const init = variable.defs[0].node.init;
112
+ if (init) {
113
+ if (isObjectExpression(init)) {
114
+ // Check if we're accessing a property that's a primitive or function
115
+ const prop = init.properties.find(p => p.type === utils_1.AST_NODE_TYPES.Property &&
116
+ p.key.type === utils_1.AST_NODE_TYPES.Identifier &&
117
+ p.key.name === property.name);
118
+ if (prop?.value) {
119
+ if (isFunction(prop.value) || isPrimitive(prop.value)) {
120
+ return null;
121
+ }
122
+ }
123
+ return init;
124
+ }
125
+ }
126
+ }
127
+ }
128
+ }
129
+ }
130
+ return null;
131
+ }
132
+ function getObjectFromMemberExpression(node) {
133
+ let current = node;
134
+ while (current.type === utils_1.AST_NODE_TYPES.MemberExpression) {
135
+ current = current.object;
136
+ }
137
+ if (isIdentifier(current)) {
138
+ return getReferencedObject(current);
139
+ }
140
+ if (isThisExpression(current)) {
141
+ const scope = context.getScope();
142
+ const scopeId = getScopeId(scope);
143
+ const scopeObjects = scopeMap.get(scopeId);
144
+ if (scopeObjects) {
145
+ for (const obj of scopeObjects) {
146
+ const info = objectMap.get(obj);
147
+ if (info && info.scope === scopeId && !info.isCircular) {
148
+ return obj;
149
+ }
150
+ }
151
+ }
152
+ }
153
+ return null;
154
+ }
155
+ function detectCircularReference(currentNode, visited = new Set(), depth = 0) {
156
+ if (depth > 100)
157
+ return false; // Prevent infinite recursion
158
+ if (visited.has(currentNode)) {
159
+ return true;
160
+ }
161
+ const objectInfo = objectMap.get(currentNode);
162
+ if (!objectInfo) {
163
+ return false;
164
+ }
165
+ visited.add(currentNode);
166
+ for (const ref of objectInfo.references) {
167
+ const referencedObj = getReferencedObject(ref);
168
+ if (referencedObj && detectCircularReference(referencedObj, new Set(visited), depth + 1)) {
169
+ objectInfo.isCircular = true;
170
+ circularRefs.add(ref);
171
+ return true;
172
+ }
173
+ }
174
+ return false;
175
+ }
176
+ function checkAndReportCircularReference(targetObj, reference) {
177
+ const targetInfo = objectMap.get(targetObj);
178
+ if (targetInfo) {
179
+ targetInfo.references.add(reference);
180
+ if (detectCircularReference(targetObj)) {
181
+ context.report({
182
+ node: reference,
183
+ messageId: 'circularReference',
184
+ });
185
+ }
186
+ }
187
+ }
188
+ return {
189
+ ObjectExpression(node) {
190
+ const scope = context.getScope();
191
+ const scopeId = getScopeId(scope);
192
+ objectMap.set(node, { node, references: new Set(), scope: scopeId });
193
+ let scopeObjects = scopeMap.get(scopeId);
194
+ if (!scopeObjects) {
195
+ scopeObjects = new Set();
196
+ scopeMap.set(scopeId, scopeObjects);
197
+ }
198
+ scopeObjects.add(node);
199
+ },
200
+ 'ObjectExpression > Property'(node) {
201
+ const parentObject = node.parent;
202
+ const value = node.value;
203
+ if (isIdentifier(value)) {
204
+ const referencedObj = getReferencedObject(value);
205
+ if (referencedObj) {
206
+ checkAndReportCircularReference(parentObject, value);
207
+ }
208
+ }
209
+ },
210
+ 'AssignmentExpression'(node) {
211
+ if (node.right.type === utils_1.AST_NODE_TYPES.Identifier) {
212
+ const referencedObj = getReferencedObject(node.right);
213
+ if (referencedObj && node.left.type === utils_1.AST_NODE_TYPES.MemberExpression) {
214
+ const targetObj = getObjectFromMemberExpression(node.left);
215
+ if (targetObj) {
216
+ checkAndReportCircularReference(targetObj, node.right);
217
+ }
218
+ }
219
+ }
220
+ else if (node.right.type === utils_1.AST_NODE_TYPES.MemberExpression) {
221
+ const referencedObj = getObjectFromMemberExpression(node.right);
222
+ if (referencedObj && node.left.type === utils_1.AST_NODE_TYPES.MemberExpression) {
223
+ const targetObj = getObjectFromMemberExpression(node.left);
224
+ if (targetObj) {
225
+ checkAndReportCircularReference(targetObj, node.right);
226
+ }
227
+ }
228
+ }
229
+ },
230
+ 'VariableDeclarator'(node) {
231
+ if (node.init?.type === utils_1.AST_NODE_TYPES.ObjectExpression) {
232
+ const properties = node.init.properties;
233
+ for (const prop of properties) {
234
+ if (prop.type === utils_1.AST_NODE_TYPES.Property && prop.value.type === utils_1.AST_NODE_TYPES.Identifier) {
235
+ const referencedObj = getReferencedObject(prop.value);
236
+ if (referencedObj) {
237
+ checkAndReportCircularReference(node.init, prop.value);
238
+ }
239
+ }
240
+ }
241
+ }
242
+ },
243
+ 'MethodDefinition'(node) {
244
+ if (node.value.type === utils_1.AST_NODE_TYPES.FunctionExpression) {
245
+ const body = node.value.body;
246
+ if (body && body.type === utils_1.AST_NODE_TYPES.BlockStatement) {
247
+ for (const stmt of body.body) {
248
+ if (stmt.type === utils_1.AST_NODE_TYPES.ExpressionStatement && stmt.expression.type === utils_1.AST_NODE_TYPES.AssignmentExpression) {
249
+ const assignment = stmt.expression;
250
+ if (assignment.left.type === utils_1.AST_NODE_TYPES.MemberExpression) {
251
+ const targetObj = getObjectFromMemberExpression(assignment.left);
252
+ if (assignment.right.type === utils_1.AST_NODE_TYPES.Identifier) {
253
+ const referencedObj = getReferencedObject(assignment.right);
254
+ if (targetObj && referencedObj) {
255
+ const leftProperty = assignment.left.property;
256
+ if (leftProperty.type === utils_1.AST_NODE_TYPES.Identifier && leftProperty.name === 'self') {
257
+ const rightObj = getReferencedObject(assignment.right);
258
+ if (rightObj) {
259
+ checkAndReportCircularReference(targetObj, assignment.right);
260
+ }
261
+ }
262
+ }
263
+ }
264
+ else if (assignment.right.type === utils_1.AST_NODE_TYPES.MemberExpression) {
265
+ const referencedObj = getObjectFromMemberExpression(assignment.right);
266
+ if (targetObj && referencedObj) {
267
+ const leftProperty = assignment.left.property;
268
+ if (leftProperty.type === utils_1.AST_NODE_TYPES.Identifier && leftProperty.name === 'self') {
269
+ const rightObj = getObjectFromMemberExpression(assignment.right);
270
+ if (rightObj) {
271
+ checkAndReportCircularReference(targetObj, assignment.right);
272
+ }
273
+ }
274
+ }
275
+ }
276
+ }
277
+ }
278
+ }
279
+ }
280
+ }
281
+ },
282
+ 'ClassDeclaration'(node) {
283
+ const scope = context.getScope();
284
+ const scopeId = getScopeId(scope);
285
+ objectMap.set(node, { node, references: new Set(), scope: scopeId });
286
+ let scopeObjects = scopeMap.get(scopeId);
287
+ if (!scopeObjects) {
288
+ scopeObjects = new Set();
289
+ scopeMap.set(scopeId, scopeObjects);
290
+ }
291
+ scopeObjects.add(node);
292
+ // Check for circular references in constructor
293
+ const constructor = node.body.body.find(member => member.type === utils_1.AST_NODE_TYPES.MethodDefinition &&
294
+ member.kind === 'constructor');
295
+ if (constructor) {
296
+ const body = constructor.value.body;
297
+ if (body && body.type === utils_1.AST_NODE_TYPES.BlockStatement) {
298
+ for (const stmt of body.body) {
299
+ if (stmt.type === utils_1.AST_NODE_TYPES.ExpressionStatement && stmt.expression.type === utils_1.AST_NODE_TYPES.AssignmentExpression) {
300
+ const assignment = stmt.expression;
301
+ if (assignment.left.type === utils_1.AST_NODE_TYPES.MemberExpression) {
302
+ const targetObj = getObjectFromMemberExpression(assignment.left);
303
+ if (assignment.right.type === utils_1.AST_NODE_TYPES.Identifier) {
304
+ const referencedObj = getReferencedObject(assignment.right);
305
+ if (targetObj && referencedObj) {
306
+ const leftProperty = assignment.left.property;
307
+ if (leftProperty.type === utils_1.AST_NODE_TYPES.Identifier && leftProperty.name === 'self') {
308
+ const rightObj = getReferencedObject(assignment.right);
309
+ if (rightObj) {
310
+ checkAndReportCircularReference(targetObj, assignment.right);
311
+ }
312
+ }
313
+ }
314
+ }
315
+ else if (assignment.right.type === utils_1.AST_NODE_TYPES.MemberExpression) {
316
+ const referencedObj = getObjectFromMemberExpression(assignment.right);
317
+ if (targetObj && referencedObj) {
318
+ const leftProperty = assignment.left.property;
319
+ if (leftProperty.type === utils_1.AST_NODE_TYPES.Identifier && leftProperty.name === 'self') {
320
+ const rightObj = getObjectFromMemberExpression(assignment.right);
321
+ if (rightObj) {
322
+ checkAndReportCircularReference(targetObj, assignment.right);
323
+ }
324
+ }
325
+ }
326
+ }
327
+ }
328
+ }
329
+ }
330
+ }
331
+ }
332
+ },
333
+ 'ClassExpression'(node) {
334
+ const scope = context.getScope();
335
+ const scopeId = getScopeId(scope);
336
+ objectMap.set(node, { node, references: new Set(), scope: scopeId });
337
+ let scopeObjects = scopeMap.get(scopeId);
338
+ if (!scopeObjects) {
339
+ scopeObjects = new Set();
340
+ scopeMap.set(scopeId, scopeObjects);
341
+ }
342
+ scopeObjects.add(node);
343
+ // Check for circular references in constructor
344
+ const constructor = node.body.body.find(member => member.type === utils_1.AST_NODE_TYPES.MethodDefinition &&
345
+ member.kind === 'constructor');
346
+ if (constructor) {
347
+ const body = constructor.value.body;
348
+ if (body && body.type === utils_1.AST_NODE_TYPES.BlockStatement) {
349
+ for (const stmt of body.body) {
350
+ if (stmt.type === utils_1.AST_NODE_TYPES.ExpressionStatement && stmt.expression.type === utils_1.AST_NODE_TYPES.AssignmentExpression) {
351
+ const assignment = stmt.expression;
352
+ if (assignment.left.type === utils_1.AST_NODE_TYPES.MemberExpression) {
353
+ const targetObj = getObjectFromMemberExpression(assignment.left);
354
+ if (assignment.right.type === utils_1.AST_NODE_TYPES.Identifier) {
355
+ const referencedObj = getReferencedObject(assignment.right);
356
+ if (targetObj && referencedObj) {
357
+ const leftProperty = assignment.left.property;
358
+ if (leftProperty.type === utils_1.AST_NODE_TYPES.Identifier && leftProperty.name === 'self') {
359
+ const rightObj = getReferencedObject(assignment.right);
360
+ if (rightObj) {
361
+ checkAndReportCircularReference(targetObj, assignment.right);
362
+ }
363
+ }
364
+ }
365
+ }
366
+ else if (assignment.right.type === utils_1.AST_NODE_TYPES.MemberExpression) {
367
+ const referencedObj = getObjectFromMemberExpression(assignment.right);
368
+ if (targetObj && referencedObj) {
369
+ const leftProperty = assignment.left.property;
370
+ if (leftProperty.type === utils_1.AST_NODE_TYPES.Identifier && leftProperty.name === 'self') {
371
+ const rightObj = getObjectFromMemberExpression(assignment.right);
372
+ if (rightObj) {
373
+ checkAndReportCircularReference(targetObj, assignment.right);
374
+ }
375
+ }
376
+ }
377
+ }
378
+ }
379
+ }
380
+ }
381
+ }
382
+ }
383
+ },
384
+ 'NewExpression'(node) {
385
+ if (node.callee.type === utils_1.AST_NODE_TYPES.Identifier) {
386
+ const scope = context.getScope();
387
+ const variable = scope.variables.find(v => node.callee.type === utils_1.AST_NODE_TYPES.Identifier && v.name === node.callee.name);
388
+ if (variable?.defs[0]?.node.type === utils_1.AST_NODE_TYPES.ClassDeclaration) {
389
+ const classDecl = variable.defs[0].node;
390
+ const constructor = classDecl.body.body.find(member => member.type === utils_1.AST_NODE_TYPES.MethodDefinition &&
391
+ member.kind === 'constructor');
392
+ if (constructor) {
393
+ const body = constructor.value.body;
394
+ if (body && body.type === utils_1.AST_NODE_TYPES.BlockStatement) {
395
+ for (const stmt of body.body) {
396
+ if (stmt.type === utils_1.AST_NODE_TYPES.ExpressionStatement && stmt.expression.type === utils_1.AST_NODE_TYPES.AssignmentExpression) {
397
+ const assignment = stmt.expression;
398
+ if (assignment.left.type === utils_1.AST_NODE_TYPES.MemberExpression) {
399
+ const leftObj = assignment.left.object;
400
+ if (leftObj.type === utils_1.AST_NODE_TYPES.ThisExpression) {
401
+ if (assignment.right.type === utils_1.AST_NODE_TYPES.Identifier) {
402
+ const referencedObj = getReferencedObject(assignment.right);
403
+ if (referencedObj) {
404
+ checkAndReportCircularReference(node, assignment.right);
405
+ }
406
+ }
407
+ else if (assignment.right.type === utils_1.AST_NODE_TYPES.MemberExpression) {
408
+ const referencedObj = getObjectFromMemberExpression(assignment.right);
409
+ if (referencedObj) {
410
+ checkAndReportCircularReference(node, assignment.right);
411
+ }
412
+ }
413
+ }
414
+ }
415
+ }
416
+ }
417
+ }
418
+ }
419
+ }
420
+ }
421
+ },
422
+ 'CallExpression'(node) {
423
+ if (node.callee.type === utils_1.AST_NODE_TYPES.MemberExpression) {
424
+ const obj = node.callee.object;
425
+ const prop = node.callee.property;
426
+ if (isIdentifier(obj) && isIdentifier(prop) && prop.name === 'then') {
427
+ // Handle Promise.then() calls
428
+ const scope = context.getScope();
429
+ const variable = scope.variables.find(v => v.name === obj.name);
430
+ if (variable?.defs[0]?.node.type === utils_1.AST_NODE_TYPES.VariableDeclarator) {
431
+ const init = variable.defs[0].node.init;
432
+ if (init && init.type === utils_1.AST_NODE_TYPES.CallExpression) {
433
+ const callee = init.callee;
434
+ if (callee.type === utils_1.AST_NODE_TYPES.MemberExpression) {
435
+ const calleeObj = callee.object;
436
+ const calleeProp = callee.property;
437
+ if (isIdentifier(calleeObj) && isIdentifier(calleeProp) && calleeObj.name === 'Promise' && calleeProp.name === 'resolve') {
438
+ // This is a Promise.resolve() call
439
+ if (init.arguments.length > 0 && init.arguments[0].type === utils_1.AST_NODE_TYPES.Identifier) {
440
+ const arg = init.arguments[0];
441
+ const referencedObj = getReferencedObject(arg);
442
+ if (referencedObj) {
443
+ // Check if the promise callback assigns the resolved value back to the original object
444
+ if (node.arguments.length > 0 && node.arguments[0].type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) {
445
+ const callback = node.arguments[0];
446
+ if (callback.body.type === utils_1.AST_NODE_TYPES.AssignmentExpression) {
447
+ const assignment = callback.body;
448
+ if (assignment.left.type === utils_1.AST_NODE_TYPES.MemberExpression) {
449
+ const leftObj = assignment.left.object;
450
+ if (isIdentifier(leftObj)) {
451
+ const leftObjRef = getReferencedObject(leftObj);
452
+ if (leftObjRef === referencedObj) {
453
+ context.report({
454
+ node: assignment,
455
+ messageId: 'circularReference',
456
+ });
457
+ }
458
+ }
459
+ }
460
+ }
461
+ else if (callback.body.type === utils_1.AST_NODE_TYPES.BlockStatement) {
462
+ for (const stmt of callback.body.body) {
463
+ if (stmt.type === utils_1.AST_NODE_TYPES.ExpressionStatement && stmt.expression.type === utils_1.AST_NODE_TYPES.AssignmentExpression) {
464
+ const assignment = stmt.expression;
465
+ if (assignment.left.type === utils_1.AST_NODE_TYPES.MemberExpression) {
466
+ const leftObj = assignment.left.object;
467
+ if (isIdentifier(leftObj)) {
468
+ const leftObjRef = getReferencedObject(leftObj);
469
+ if (leftObjRef === referencedObj) {
470
+ context.report({
471
+ node: assignment,
472
+ messageId: 'circularReference',
473
+ });
474
+ }
475
+ }
476
+ }
477
+ }
478
+ }
479
+ }
480
+ }
481
+ }
482
+ }
483
+ }
484
+ }
485
+ }
486
+ }
487
+ }
488
+ }
489
+ },
490
+ 'MemberExpression'(node) {
491
+ if (node.parent && node.parent.type === utils_1.AST_NODE_TYPES.AssignmentExpression && node.parent.left === node) {
492
+ return; // Skip left side of assignments, handled elsewhere
493
+ }
494
+ const obj = node.object;
495
+ const prop = node.property;
496
+ if (isIdentifier(obj) && isIdentifier(prop)) {
497
+ const referencedObj = getReferencedObject(obj);
498
+ if (referencedObj) {
499
+ const scope = context.getScope();
500
+ const scopeId = getScopeId(scope);
501
+ const info = objectMap.get(referencedObj);
502
+ if (info && info.scope === scopeId) {
503
+ // Check if this property access might lead to a circular reference
504
+ if (prop.name === 'self' || prop.name === 'ref' || prop.name === 'circular') {
505
+ const parent = node.parent;
506
+ if (parent && parent.type === utils_1.AST_NODE_TYPES.AssignmentExpression && parent.right === node) {
507
+ const leftObj = getObjectFromMemberExpression(parent.left);
508
+ if (leftObj === referencedObj) {
509
+ context.report({
510
+ node,
511
+ messageId: 'circularReference',
512
+ });
513
+ }
514
+ }
515
+ }
516
+ }
517
+ }
518
+ }
519
+ },
520
+ };
521
+ },
522
+ });
523
+ //# sourceMappingURL=no-circular-references.js.map
@@ -26,14 +26,26 @@ exports.noFirestoreJestMock = (0, createRule_1.createRule)({
26
26
  }
27
27
  return {
28
28
  ImportDeclaration(node) {
29
+ // Skip type imports completely
30
+ if (node.importKind === 'type') {
31
+ return;
32
+ }
29
33
  if (node.source.value === 'firestore-jest-mock') {
30
34
  context.report({
31
35
  node,
32
36
  messageId: 'noFirestoreJestMock',
33
- fix(fixer) {
34
- // Replace with mockFirestore import
35
- return fixer.replaceText(node, "import { mockFirestore } from '../../../../../__test-utils__/mockFirestore';");
36
- },
37
+ fix: (fixer) => {
38
+ return fixer.replaceText(node, `import { mockFirestore } from '../../../../../__test-utils__/mockFirestore';`);
39
+ }
40
+ });
41
+ }
42
+ },
43
+ ImportExpression(node) {
44
+ if (node.source.type === utils_1.AST_NODE_TYPES.Literal &&
45
+ node.source.value === 'firestore-jest-mock') {
46
+ context.report({
47
+ node,
48
+ messageId: 'noFirestoreJestMock',
37
49
  });
38
50
  }
39
51
  },
@@ -52,6 +64,17 @@ exports.noFirestoreJestMock = (0, createRule_1.createRule)({
52
64
  messageId: 'noFirestoreJestMock',
53
65
  });
54
66
  }
67
+ // Check for require('firestore-jest-mock')
68
+ if (node.callee.type === utils_1.AST_NODE_TYPES.Identifier &&
69
+ node.callee.name === 'require' &&
70
+ node.arguments.length > 0 &&
71
+ node.arguments[0].type === utils_1.AST_NODE_TYPES.Literal &&
72
+ node.arguments[0].value === 'firestore-jest-mock') {
73
+ context.report({
74
+ node,
75
+ messageId: 'noFirestoreJestMock',
76
+ });
77
+ }
55
78
  },
56
79
  };
57
80
  },
@@ -0,0 +1,5 @@
1
+ type Options = {
2
+ allowClassInstances?: boolean;
3
+ };
4
+ export declare const noHungarian: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"noHungarian", [Options], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
5
+ export {};