(code: string, keyword: string, afterKeyword: number)
| 129 | * can't be delimited confidently (unbalanced braces, generator-mangled source) |
| 130 | * — in which case nothing is reported rather than something guessed. */ |
| 131 | const loopBody = (code: string, keyword: string, afterKeyword: number): string | null => { |
| 132 | let index = afterKeyword; |
| 133 | const skipSpace = (): void => { |
| 134 | while (index < code.length && /\s/.test(code[index] ?? "")) index += 1; |
| 135 | }; |
| 136 | |
| 137 | // `for (...)` / `while (...)`: step over the header's parens first. A hook in |
| 138 | // the header itself is not the shape we're after. |
| 139 | if (keyword !== "do") { |
| 140 | skipSpace(); |
| 141 | if (code[index] !== "(") return null; |
| 142 | let depth = 0; |
| 143 | for (; index < code.length; index += 1) { |
| 144 | if (code[index] === "(") depth += 1; |
| 145 | else if (code[index] === ")") { |
| 146 | depth -= 1; |
| 147 | if (depth === 0) { |
| 148 | index += 1; |
| 149 | break; |
| 150 | } |
| 151 | } |
| 152 | } |
| 153 | if (depth !== 0) return null; |
| 154 | } |
| 155 | |
| 156 | skipSpace(); |
| 157 | |
| 158 | // Only a braced body is scanned. A braceless one has no delimiter to trust — |
| 159 | // its end would have to be guessed at the next semicolon, which in JSX prose |
| 160 | // can run far past the statement and reach an unrelated hook. Giving up costs |
| 161 | // only `for (…) useQuery(…)`, which no generator writes. |
| 162 | if (code[index] !== "{") return null; |
| 163 | |
| 164 | const start = index; |
| 165 | let depth = 0; |
| 166 | for (; index < code.length; index += 1) { |
| 167 | if (code[index] === "{") depth += 1; |
| 168 | else if (code[index] === "}") { |
| 169 | depth -= 1; |
| 170 | if (depth === 0) return code.slice(start + 1, index); |
| 171 | } |
| 172 | } |
| 173 | return null; |
| 174 | }; |
| 175 | |
| 176 | /** `do` is also an ordinary English word that can appear in JSX text ahead of an |
| 177 | * expression container ("nothing to do {count}"), where `for`/`while` are |
no test coverage detected