Repository: facebook/react
File: packages/eslint-plugin-react-hooks/src/RulesOfHooks.js (JavaScript)

Code before:
            const pathArray = Array.from(pathList);
            const cyclicSegments = pathArray.slice(
              pathArray.indexOf(segment.id) - 1,
            );
            for (const cyclicSegment of cyclicSegments) {
              cyclic.add(cyclicSegment);
            }

            return BigInt('0');
          }

          // add the current segment to pathList
          pathList.add(segment.id);

          // We have a cached `paths`. Return it.
          if (paths !== undefined) {
            return paths;
          }

          if (codePath.thrownSegments.includes(segment)) {
            paths = BigInt('0');
          } else if (segment.nextSegments.length === 0) {
            paths = BigInt('1');
          } else {
            paths = BigInt('0');
            for (const nextSegment of segment.nextSegments) {
              paths += countPathsToEnd(nextSegment, pathList);
            }
          }

          // If our segment is reachable then there should be at least one path
          // to it to the end of our code path.
          if (segment.reachable && paths === BigInt('0')) {
            cache.delete(segment.id);
          } else {
            cache.set(segment.id, paths);
          }

          return paths;
        }

        /**
         * Gets the shortest path length to the start of a code path.
         * For example:
         *
         * ```js
         * function MyComponent() {
         *   if (condition) {
         *     // Segment 1
         *   }
         *   // Segment 2

Review comment (bug):
Question here: `slice(pathArray.indexOf(segment.id))` makes sense -- we want to include the cyclic segment itself when adding to `cyclic`. What's the logic for also including the previous segment in pathsHistory?

I do see that this test case (incorrectly) doesn't error if I remove the `- 1`, just trying to understand why. Could we also add this to ESLintRulesOfHooks-test to be complete?
```js
function ComponentWithHookInsideLoop() {
  do {
	  foo();
  } while (useHookInsideLoop());
}
```

Code after:
         *   if (condition) {
         *     // Segment 2
         *   } else {
         *     // Segment 3
         *   }
         * }
         * ```
         *
         * Segments 2 and 3 have one path to the end of `MyComponent` and
         * segment 1 has two paths to the end of `MyComponent` since we could
         * either take the path of segment 1 or segment 2.
         *
         * Populates `cyclic` with cyclic segments.
         */

        function countPathsToEnd(segment, pathHistory) {
          const {cache} = countPathsToEnd;
          let paths = cache.get(segment.id);
          const pathList = new Set(pathHistory);

          // If `pathList` includes the current segment then we've found a cycle!
          // We need to fill `cyclic` with all segments inside cycle
          if (pathList.has(segment.id)) {
            const pathArray = Array.from(pathList);
            const cyclicSegments = pathArray.slice(
              pathArray.indexOf(segment.id) - 1,
            );
            for (const cyclicSegment of cyclicSegments) {
              cyclic.add(cyclicSegment);
            }

            return BigInt('0');
          }

          // add the current segment to pathList
          pathList.add(segment.id);

          // We have a cached `paths`. Return it.
          if (paths !== undefined) {
            return paths;
          }

          if (codePath.thrownSegments.includes(segment)) {
            paths = BigInt('0');
          } else if (segment.nextSegments.length === 0) {
            paths = BigInt('1');
          } else {
            paths = BigInt('0');
            for (const nextSegment of segment.nextSegments) {
              paths += countPathsToEnd(nextSegment, pathList);
            }