@samitouri / QOS-React / commits / 1f7a901d7b

Fix false positive lint error with large number of branches (#24287)

* Switched RulesOfHooks.js to use BigInt. Added test and updated .eslintrc.js to use es2020. * Added BigInt as readonly global in eslintrc.cjs.js and eslintrc.cjs2015.js * Added comment to RulesOfHooks.js that gets rid of BigInt eslint error * Got rid of changes in .eslintrc.js and yarn.lock * Move global down Co-authored-by: stephen cyron <stephen.cyron@fdmgroup.com> Co-authored-by: dan <dan.abramov@gmail.com>

Stephen Cyron committed Apr 7, 2022 at 19:22 UTC 1f7a901d7b2fc073e29a1887553b1bd18080da1b
4 files changed +81 -9
packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js
+69
@@ -325,6 +325,75 @@ const tests = {
325 useHook();
326 }
327 `,
328 + `
329 + // Valid because the neither the conditions before or after the hook affect the hook call
330 + // Failed prior to implementing BigInt because pathsFromStartToEnd and allPathsFromStartToEnd were too big and had rounding errors
331 + const useSomeHook = () => {};
332 +
333 + const SomeName = () => {
334 + const filler = FILLER ?? FILLER ?? FILLER;
335 + const filler2 = FILLER ?? FILLER ?? FILLER;
336 + const filler3 = FILLER ?? FILLER ?? FILLER;
337 + const filler4 = FILLER ?? FILLER ?? FILLER;
338 + const filler5 = FILLER ?? FILLER ?? FILLER;
339 + const filler6 = FILLER ?? FILLER ?? FILLER;
340 + const filler7 = FILLER ?? FILLER ?? FILLER;
341 + const filler8 = FILLER ?? FILLER ?? FILLER;
342 +
343 + useSomeHook();
344 +
345 + if (anyConditionCanEvenBeFalse) {
346 + return null;
347 + }
348 +
349 + return (
350 + <React.Fragment>
351 + {FILLER ? FILLER : FILLER}
352 + {FILLER ? FILLER : FILLER}
353 + {FILLER ? FILLER : FILLER}
354 + {FILLER ? FILLER : FILLER}
355 + {FILLER ? FILLER : FILLER}
356 + {FILLER ? FILLER : FILLER}
357 + {FILLER ? FILLER : FILLER}
358 + {FILLER ? FILLER : FILLER}
359 + {FILLER ? FILLER : FILLER}
360 + {FILLER ? FILLER : FILLER}
361 + {FILLER ? FILLER : FILLER}
362 + {FILLER ? FILLER : FILLER}
363 + {FILLER ? FILLER : FILLER}
364 + {FILLER ? FILLER : FILLER}
365 + {FILLER ? FILLER : FILLER}
366 + {FILLER ? FILLER : FILLER}
367 + {FILLER ? FILLER : FILLER}
368 + {FILLER ? FILLER : FILLER}
369 + {FILLER ? FILLER : FILLER}
370 + {FILLER ? FILLER : FILLER}
371 + {FILLER ? FILLER : FILLER}
372 + {FILLER ? FILLER : FILLER}
373 + {FILLER ? FILLER : FILLER}
374 + {FILLER ? FILLER : FILLER}
375 + {FILLER ? FILLER : FILLER}
376 + {FILLER ? FILLER : FILLER}
377 + {FILLER ? FILLER : FILLER}
378 + {FILLER ? FILLER : FILLER}
379 + {FILLER ? FILLER : FILLER}
380 + {FILLER ? FILLER : FILLER}
381 + {FILLER ? FILLER : FILLER}
382 + {FILLER ? FILLER : FILLER}
383 + {FILLER ? FILLER : FILLER}
384 + {FILLER ? FILLER : FILLER}
385 + {FILLER ? FILLER : FILLER}
386 + {FILLER ? FILLER : FILLER}
387 + {FILLER ? FILLER : FILLER}
388 + {FILLER ? FILLER : FILLER}
389 + {FILLER ? FILLER : FILLER}
390 + {FILLER ? FILLER : FILLER}
391 + {FILLER ? FILLER : FILLER}
392 + {FILLER ? FILLER : FILLER}
393 + </React.Fragment>
394 + );
395 + };
396 + `,
397 `
398 // Valid because the neither the condition nor the loop affect the hook call.
399 function App(props) {
packages/eslint-plugin-react-hooks/src/RulesOfHooks.js
+10 -9
@@ -5,6 +5,7 @@
5 * LICENSE file in the root directory of this source tree.
6 */
7
8 +/* global BigInt */
9 /* eslint-disable no-for-of-loops/no-for-of-loops */
10
11 'use strict';
@@ -175,7 +176,7 @@ export default {
176 cyclic.add(cyclicSegment);
177 }
178
178 - return 0;
179 + return BigInt('0');
180 }
181
182 // add the current segment to pathList
@@ -187,11 +188,11 @@ export default {
188 }
189
190 if (codePath.thrownSegments.includes(segment)) {
190 - paths = 0;
191 + paths = BigInt('0');
192 } else if (segment.prevSegments.length === 0) {
192 - paths = 1;
193 + paths = BigInt('1');
194 } else {
194 - paths = 0;
195 + paths = BigInt('0');
196 for (const prevSegment of segment.prevSegments) {
197 paths += countPathsFromStart(prevSegment, pathList);
198 }
@@ -199,7 +200,7 @@ export default {
200
201 // If our segment is reachable then there should be at least one path
202 // to it from the start of our code path.
202 - if (segment.reachable && paths === 0) {
203 + if (segment.reachable && paths === BigInt('0')) {
204 cache.delete(segment.id);
205 } else {
206 cache.set(segment.id, paths);
@@ -246,7 +247,7 @@ export default {
247 cyclic.add(cyclicSegment);
248 }
249
249 - return 0;
250 + return BigInt('0');
251 }
252
253 // add the current segment to pathList
@@ -258,11 +259,11 @@ export default {
259 }
260
261 if (codePath.thrownSegments.includes(segment)) {
261 - paths = 0;
262 + paths = BigInt('0');
263 } else if (segment.nextSegments.length === 0) {
263 - paths = 1;
264 + paths = BigInt('1');
265 } else {
265 - paths = 0;
266 + paths = BigInt('0');
267 for (const nextSegment of segment.nextSegments) {
268 paths += countPathsToEnd(nextSegment, pathList);
269 }
scripts/rollup/validate/eslintrc.cjs.js
+1
@@ -7,6 +7,7 @@ module.exports = {
7 },
8 globals: {
9 // ES 6
10 + BigInt: 'readonly',
11 Map: 'readonly',
12 Set: 'readonly',
13 Proxy: 'readonly',
scripts/rollup/validate/eslintrc.cjs2015.js
+1
@@ -7,6 +7,7 @@ module.exports = {
7 },
8 globals: {
9 // ES 6
10 + BigInt: 'readonly',
11 Map: 'readonly',
12 Set: 'readonly',
13 Proxy: 'readonly',