eslint-plugin-sonarjs 4.0.0 → 4.0.2

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 (413) hide show
  1. package/README.md +269 -268
  2. package/cjs/S100/rule.js +7 -5
  3. package/cjs/S101/rule.js +2 -2
  4. package/cjs/S104/rule.js +2 -2
  5. package/cjs/S105/rule.js +2 -2
  6. package/cjs/S1066/rule.js +5 -4
  7. package/cjs/S1067/rule.js +8 -6
  8. package/cjs/S1110/rule.js +7 -5
  9. package/cjs/S1119/rule.js +85 -7
  10. package/cjs/S1121/rule.js +4 -3
  11. package/cjs/S1125/rule.js +9 -8
  12. package/cjs/S1126/rule.js +2 -2
  13. package/cjs/S1128/rule.js +8 -5
  14. package/cjs/S1134/rule.js +2 -2
  15. package/cjs/S1135/rule.js +2 -2
  16. package/cjs/S1154/rule.js +6 -4
  17. package/cjs/S117/rule.js +6 -5
  18. package/cjs/S1172/rule.js +2 -2
  19. package/cjs/S1192/rule.js +5 -4
  20. package/cjs/S1219/rule.js +4 -3
  21. package/cjs/S1226/rule.js +6 -4
  22. package/cjs/S124/rule.js +2 -2
  23. package/cjs/S125/rule.js +9 -7
  24. package/cjs/S126/rule.js +2 -2
  25. package/cjs/S1264/rule.js +2 -2
  26. package/cjs/S128/rule.js +4 -3
  27. package/cjs/S1291/rule.js +2 -2
  28. package/cjs/S1301/rule.js +2 -2
  29. package/cjs/S1313/rule.js +2 -2
  30. package/cjs/S134/rule.js +7 -5
  31. package/cjs/S135/rule.js +5 -4
  32. package/cjs/S138/rule.js +9 -6
  33. package/cjs/S1439/rule.js +2 -2
  34. package/cjs/S1444/rule.js +2 -2
  35. package/cjs/S1451/rule.js +2 -2
  36. package/cjs/S1472/rule.js +2 -2
  37. package/cjs/S1479/rule.js +2 -2
  38. package/cjs/S1481/rule.js +2 -2
  39. package/cjs/S1488/generated-meta.js +1 -1
  40. package/cjs/S1488/rule.js +11 -7
  41. package/cjs/S1515/rule.js +10 -8
  42. package/cjs/{helpers/aws/index.js → S1523/generated-meta.js} +34 -18
  43. package/cjs/S1523/index.js +21 -0
  44. package/cjs/S1523/meta.js +21 -0
  45. package/cjs/S1523/rule.js +143 -0
  46. package/cjs/S1526/rule.js +5 -4
  47. package/cjs/S1527/rule.js +2 -2
  48. package/cjs/S1528/rule.js +2 -2
  49. package/cjs/S1529/generated-meta.js +1 -1
  50. package/cjs/S1529/rule.js +4 -3
  51. package/cjs/S1530/rule.js +5 -3
  52. package/cjs/S1533/rule.js +2 -2
  53. package/cjs/S1535/rule.js +2 -2
  54. package/cjs/S1541/rule.js +10 -7
  55. package/cjs/S1607/rule.js +22 -20
  56. package/cjs/S1764/rule.js +10 -7
  57. package/cjs/S1821/rule.js +2 -2
  58. package/cjs/S1848/rule.js +10 -7
  59. package/cjs/S1854/rule.js +18 -14
  60. package/cjs/S1862/rule.js +10 -8
  61. package/cjs/S1871/rule.js +21 -16
  62. package/cjs/S1874/rule.js +4 -3
  63. package/cjs/S1940/rule.js +2 -2
  64. package/cjs/S1994/rule.js +10 -7
  65. package/cjs/S2004/rule.js +9 -7
  66. package/cjs/S2068/rule.js +75 -12
  67. package/cjs/S2077/generated-meta.js +1 -1
  68. package/cjs/S2077/rule.js +10 -6
  69. package/cjs/S2092/rule.js +2 -2
  70. package/cjs/S2123/rule.js +2 -2
  71. package/cjs/S2137/rule.js +2 -2
  72. package/cjs/S2138/rule.js +4 -3
  73. package/cjs/S2187/rule.js +2 -2
  74. package/cjs/S2201/rule.js +47 -5
  75. package/cjs/S2208/rule.js +2 -2
  76. package/cjs/S2234/rule.js +58 -11
  77. package/cjs/S2245/rule.js +4 -3
  78. package/cjs/S2251/rule.js +5 -4
  79. package/cjs/S2255/rule.js +6 -5
  80. package/cjs/S2259/rule.js +14 -9
  81. package/cjs/S2301/rule.js +14 -9
  82. package/cjs/S2310/rule.js +80 -9
  83. package/cjs/S2392/rule.js +7 -5
  84. package/cjs/S2424/rule.js +2 -2
  85. package/cjs/S2428/rule.js +8 -6
  86. package/cjs/S2486/rule.js +4 -3
  87. package/cjs/S2589/rule.js +12 -10
  88. package/cjs/S2598/rule.js +17 -14
  89. package/cjs/S2612/generated-meta.js +1 -1
  90. package/cjs/S2612/rule.js +8 -6
  91. package/cjs/S2639/rule.js +2 -2
  92. package/cjs/S2681/rule.js +2 -2
  93. package/cjs/S2692/rule.js +6 -4
  94. package/cjs/S2699/generated-meta.js +1 -1
  95. package/cjs/S2699/rule.js +40 -31
  96. package/cjs/S2703/rule.js +2 -2
  97. package/cjs/S2737/rule.js +6 -4
  98. package/cjs/S2755/rule.js +9 -6
  99. package/cjs/S2757/rule.js +2 -2
  100. package/cjs/S2817/rule.js +10 -7
  101. package/cjs/S2819/rule.js +16 -12
  102. package/cjs/S2870/rule.js +8 -5
  103. package/cjs/S2871/rule.js +12 -9
  104. package/cjs/S2970/rule.js +9 -8
  105. package/cjs/S2990/rule.js +2 -2
  106. package/cjs/S2999/rule.js +10 -7
  107. package/cjs/S3001/rule.js +2 -2
  108. package/cjs/S3003/rule.js +10 -7
  109. package/cjs/S3317/rule.js +4 -3
  110. package/cjs/S3330/rule.js +2 -2
  111. package/cjs/S3358/rule.js +2 -2
  112. package/cjs/S3402/rule.js +14 -10
  113. package/cjs/S3403/rule.js +10 -7
  114. package/cjs/S3415/rule.js +16 -13
  115. package/cjs/S3499/rule.js +5 -4
  116. package/cjs/S3500/rule.js +5 -4
  117. package/cjs/S3513/rule.js +5 -4
  118. package/cjs/S3514/rule.js +10 -7
  119. package/cjs/S3516/rule.js +10 -7
  120. package/cjs/S3524/rule.js +2 -2
  121. package/cjs/S3525/rule.js +6 -4
  122. package/cjs/S3531/rule.js +5 -3
  123. package/cjs/S3533/rule.js +8 -7
  124. package/cjs/S3579/rule.js +6 -4
  125. package/cjs/S3616/rule.js +6 -4
  126. package/cjs/S3626/rule.js +4 -3
  127. package/cjs/S3686/rule.js +7 -5
  128. package/cjs/S3699/rule.js +4 -3
  129. package/cjs/S3735/rule.js +8 -5
  130. package/cjs/S3757/rule.js +8 -6
  131. package/cjs/S3758/rule.js +9 -7
  132. package/cjs/S3760/rule.js +24 -21
  133. package/cjs/S3776/rule.js +26 -22
  134. package/cjs/S3782/rule.js +6 -4
  135. package/cjs/S3785/rule.js +9 -6
  136. package/cjs/S3796/rule.js +12 -8
  137. package/cjs/S3798/rule.js +4 -3
  138. package/cjs/S3800/rule.js +22 -11
  139. package/cjs/S3801/generated-meta.js +1 -1
  140. package/cjs/S3801/rule.js +15 -11
  141. package/cjs/S3827/rule.js +9 -6
  142. package/cjs/S3923/rule.js +9 -6
  143. package/cjs/S3972/rule.js +5 -4
  144. package/cjs/S3973/rule.js +7 -5
  145. package/cjs/S3981/rule.js +4 -3
  146. package/cjs/S3984/rule.js +4 -3
  147. package/cjs/S4030/rule.js +10 -7
  148. package/cjs/S4036/rule.js +7 -5
  149. package/cjs/S4043/rule.js +12 -8
  150. package/cjs/S4139/rule.js +7 -5
  151. package/cjs/S4143/rule.js +12 -9
  152. package/cjs/S4144/rule.js +12 -9
  153. package/cjs/S4158/rule.js +11 -8
  154. package/cjs/S4165/rule.js +14 -12
  155. package/cjs/S4322/rule.js +8 -5
  156. package/cjs/S4323/rule.js +4 -3
  157. package/cjs/S4324/rule.js +7 -5
  158. package/cjs/S4328/rule.js +2 -2
  159. package/cjs/S4335/rule.js +6 -4
  160. package/cjs/S4423/rule.js +4 -3
  161. package/cjs/S4423/rule.lib.js +8 -7
  162. package/cjs/S4426/rule.js +11 -10
  163. package/cjs/S4502/rule.js +16 -13
  164. package/cjs/S4507/rule.js +8 -6
  165. package/cjs/S4524/rule.js +2 -2
  166. package/cjs/S4619/rule.js +6 -4
  167. package/cjs/S4621/rule.js +5 -4
  168. package/cjs/S4622/rule.js +5 -3
  169. package/cjs/S4623/rule.js +8 -5
  170. package/cjs/S4624/rule.js +6 -4
  171. package/cjs/S4634/rule.js +4 -3
  172. package/cjs/S4721/rule.js +7 -5
  173. package/cjs/S4782/rule.js +7 -5
  174. package/cjs/S4784/rule.js +5 -4
  175. package/cjs/S4787/rule.js +9 -7
  176. package/cjs/S4790/rule.js +7 -5
  177. package/cjs/S4798/rule.js +2 -2
  178. package/cjs/S4817/rule.js +10 -8
  179. package/cjs/S4818/rule.js +4 -3
  180. package/cjs/S4822/rule.js +13 -9
  181. package/cjs/S4823/rule.js +4 -3
  182. package/cjs/S4829/rule.js +4 -3
  183. package/cjs/S4830/rule.js +11 -8
  184. package/cjs/S5042/rule.js +9 -7
  185. package/cjs/S5122/rule.js +40 -36
  186. package/cjs/S5148/rule.js +9 -8
  187. package/cjs/S5247/rule.js +22 -18
  188. package/cjs/S5256/rule.js +5 -4
  189. package/cjs/S5257/rule.js +4 -3
  190. package/cjs/S5260/rule.js +4 -3
  191. package/cjs/S5264/rule.js +4 -3
  192. package/cjs/S5332/rule.js +4 -3
  193. package/cjs/S5332/rule.lib.js +19 -17
  194. package/cjs/S5443/rule.js +2 -2
  195. package/cjs/S5527/rule.js +18 -14
  196. package/cjs/S5542/rule.js +6 -4
  197. package/cjs/S5547/rule.js +6 -4
  198. package/cjs/S5604/rule.js +15 -14
  199. package/cjs/S5659/rule.js +15 -12
  200. package/cjs/S5689/rule.js +11 -8
  201. package/cjs/S5691/rule.js +7 -5
  202. package/cjs/S5693/rule.js +14 -12
  203. package/cjs/S5725/rule.js +9 -6
  204. package/cjs/S5728/rule.js +7 -4
  205. package/cjs/S5730/rule.js +9 -6
  206. package/cjs/S5732/rule.js +8 -5
  207. package/cjs/S5734/rule.js +7 -4
  208. package/cjs/S5736/rule.js +8 -5
  209. package/cjs/S5739/rule.js +11 -8
  210. package/cjs/S5742/rule.js +7 -4
  211. package/cjs/S5743/rule.js +8 -6
  212. package/cjs/S5757/rule.js +13 -10
  213. package/cjs/S5759/rule.js +10 -7
  214. package/cjs/S5842/rule.js +2 -2
  215. package/cjs/S5843/rule.js +22 -19
  216. package/cjs/S5850/rule.js +4 -3
  217. package/cjs/S5852/rule.js +2 -2
  218. package/cjs/S5856/rule.js +10 -7
  219. package/cjs/S5860/rule.js +30 -26
  220. package/cjs/S5863/rule.js +15 -11
  221. package/cjs/S5867/rule.js +8 -7
  222. package/cjs/S5868/rule.js +7 -5
  223. package/cjs/S5869/rule.js +6 -5
  224. package/cjs/S5876/rule.js +12 -8
  225. package/cjs/S5958/rule.js +12 -9
  226. package/cjs/S5973/rule.js +10 -7
  227. package/cjs/S6019/rule.js +4 -3
  228. package/cjs/S6035/rule.js +2 -2
  229. package/cjs/S6079/rule.js +9 -6
  230. package/cjs/S6080/rule.js +13 -10
  231. package/cjs/S6092/rule.js +9 -7
  232. package/cjs/S6245/rule.js +14 -9
  233. package/cjs/S6249/rule.js +7 -5
  234. package/cjs/S6252/rule.js +12 -8
  235. package/cjs/S6265/rule.js +27 -20
  236. package/cjs/S6268/rule.js +5 -4
  237. package/cjs/S6270/rule.js +12 -9
  238. package/cjs/S6275/rule.js +2 -2
  239. package/cjs/S6281/rule.js +22 -17
  240. package/cjs/S6299/rule.js +2 -2
  241. package/cjs/S6302/rule.js +6 -5
  242. package/cjs/S6303/rule.js +12 -10
  243. package/cjs/S6304/rule.js +6 -5
  244. package/cjs/S6308/rule.js +7 -5
  245. package/cjs/S6317/rule.js +5 -4
  246. package/cjs/S6319/rule.js +2 -2
  247. package/cjs/S6321/rule.js +25 -23
  248. package/cjs/S6323/rule.js +4 -3
  249. package/cjs/S6324/rule.js +2 -2
  250. package/cjs/S6326/rule.js +2 -2
  251. package/cjs/S6327/rule.js +2 -2
  252. package/cjs/S6328/rule.js +4 -3
  253. package/cjs/S6329/rule.js +7 -5
  254. package/cjs/S6330/rule.js +2 -2
  255. package/cjs/S6332/rule.js +2 -2
  256. package/cjs/S6333/rule.js +8 -6
  257. package/cjs/S6351/rule.js +22 -19
  258. package/cjs/S6353/rule.js +2 -2
  259. package/cjs/S6397/rule.js +2 -2
  260. package/cjs/S6418/config.js +1 -1
  261. package/cjs/S6418/rule.js +9 -24
  262. package/cjs/S6426/rule.js +5 -4
  263. package/cjs/S6437/rule.js +10 -7
  264. package/cjs/S6439/rule.js +9 -7
  265. package/cjs/S6442/rule.js +11 -8
  266. package/cjs/S6443/rule.js +9 -7
  267. package/cjs/S6486/rule.js +5 -4
  268. package/cjs/S6564/rule.js +4 -3
  269. package/cjs/S6594/rule.js +12 -8
  270. package/cjs/S6627/rule.js +6 -4
  271. package/cjs/S6759/rule.js +10 -6
  272. package/cjs/S6958/rule.js +2 -2
  273. package/cjs/S6959/rule.js +9 -6
  274. package/cjs/S7059/generated-meta.js +1 -1
  275. package/cjs/S7059/rule.js +8 -5
  276. package/cjs/S7639/generated-meta.js +1 -1
  277. package/cjs/S7639/rule.js +5 -4
  278. package/cjs/S7790/generated-meta.js +1 -1
  279. package/cjs/S7790/rule.js +7 -5
  280. package/cjs/S8441/generated-meta.js +1 -1
  281. package/cjs/S8441/rule.js +13 -9
  282. package/cjs/S881/rule.js +2 -2
  283. package/cjs/S888/rule.js +4 -3
  284. package/cjs/S930/rule.js +14 -12
  285. package/cjs/helpers/ast.js +11 -8
  286. package/cjs/helpers/aws/s3.js +9 -6
  287. package/cjs/helpers/chai.js +41 -43
  288. package/cjs/helpers/configs.js +92 -0
  289. package/cjs/helpers/cookie-flag-check.js +19 -17
  290. package/cjs/helpers/{decorators/index.js → entropy.js} +16 -17
  291. package/cjs/helpers/express.js +127 -128
  292. package/cjs/helpers/find-up/all-in-parent-dirs.js +0 -16
  293. package/cjs/helpers/mocha.js +50 -54
  294. package/cjs/helpers/regex/ast.js +7 -6
  295. package/cjs/helpers/regex/extract.js +11 -11
  296. package/cjs/helpers/regex/group.js +2 -2
  297. package/cjs/helpers/regex/location.js +2 -2
  298. package/cjs/helpers/regex/range.js +5 -4
  299. package/cjs/helpers/regex/rule-template.js +4 -3
  300. package/cjs/helpers/sinon.js +33 -36
  301. package/cjs/helpers/supertest.js +34 -37
  302. package/cjs/helpers/vitest.js +29 -32
  303. package/cjs/plugin-rules.js +452 -450
  304. package/docs/assertions-in-tests.md +2 -0
  305. package/docs/bitwise-operators.md +2 -0
  306. package/docs/code-eval.md +7 -0
  307. package/docs/file-permissions.md +1 -1
  308. package/docs/no-async-constructor.md +2 -0
  309. package/docs/no-inconsistent-returns.md +2 -0
  310. package/docs/prefer-immediate-return.md +2 -0
  311. package/docs/sql-queries.md +2 -0
  312. package/package.json +39 -1
  313. package/types/S1067/rule.d.ts +1 -1
  314. package/types/S1110/rule.d.ts +1 -1
  315. package/types/S1128/rule.d.ts +1 -1
  316. package/types/S1172/rule.d.ts +1 -1
  317. package/types/S1226/rule.d.ts +1 -1
  318. package/types/S134/rule.d.ts +1 -1
  319. package/types/S1472/rule.d.ts +1 -1
  320. package/types/S1481/rule.d.ts +1 -1
  321. package/types/S1488/generated-meta.d.ts +1 -1
  322. package/types/S1515/rule.d.ts +1 -1
  323. package/types/S1523/generated-meta.d.ts +17 -0
  324. package/types/S1523/index.d.ts +1 -0
  325. package/types/S1523/meta.d.ts +2 -0
  326. package/types/S1523/rule.d.ts +2 -0
  327. package/types/S1527/rule.d.ts +1 -1
  328. package/types/S1529/generated-meta.d.ts +1 -1
  329. package/types/S1541/rule.d.ts +1 -1
  330. package/types/S1862/rule.d.ts +1 -1
  331. package/types/S2077/generated-meta.d.ts +1 -1
  332. package/types/S2123/rule.d.ts +1 -1
  333. package/types/S2259/rule.d.ts +1 -1
  334. package/types/S2428/rule.d.ts +1 -1
  335. package/types/S2589/rule.d.ts +1 -1
  336. package/types/S2598/rule.d.ts +1 -1
  337. package/types/S2699/generated-meta.d.ts +1 -1
  338. package/types/S2699/rule.d.ts +1 -1
  339. package/types/S2737/rule.d.ts +1 -1
  340. package/types/S2757/rule.d.ts +1 -1
  341. package/types/S2819/rule.d.ts +1 -1
  342. package/types/S3001/rule.d.ts +1 -1
  343. package/types/S3317/rule.d.ts +1 -1
  344. package/types/S3500/rule.d.ts +1 -1
  345. package/types/S3513/rule.d.ts +1 -1
  346. package/types/S3686/rule.d.ts +1 -1
  347. package/types/S3801/generated-meta.d.ts +1 -1
  348. package/types/S3972/rule.d.ts +1 -1
  349. package/types/S3973/rule.d.ts +1 -1
  350. package/types/S4030/rule.d.ts +1 -1
  351. package/types/S4143/rule.d.ts +1 -1
  352. package/types/S4158/rule.d.ts +1 -1
  353. package/types/S4621/rule.d.ts +1 -1
  354. package/types/S4782/rule.d.ts +1 -1
  355. package/types/S5693/rule.d.ts +1 -1
  356. package/types/S5725/rule.d.ts +1 -1
  357. package/types/S5860/rule.d.ts +1 -1
  358. package/types/S5868/rule.d.ts +1 -1
  359. package/types/S5869/rule.d.ts +1 -1
  360. package/types/S6079/rule.d.ts +1 -1
  361. package/types/S6326/rule.d.ts +1 -1
  362. package/types/S6351/rule.d.ts +1 -1
  363. package/types/S6418/config.d.ts +1 -1
  364. package/types/S6443/rule.d.ts +1 -1
  365. package/types/S7059/generated-meta.d.ts +1 -1
  366. package/types/S7639/generated-meta.d.ts +1 -1
  367. package/types/S7790/generated-meta.d.ts +1 -1
  368. package/types/S8441/generated-meta.d.ts +1 -1
  369. package/types/S930/rule.d.ts +1 -1
  370. package/types/helpers/ancestor.d.ts +3 -3
  371. package/types/helpers/ast.d.ts +1 -1
  372. package/types/helpers/aws/iam.d.ts +2 -2
  373. package/types/helpers/aws/s3.d.ts +1 -1
  374. package/types/helpers/chai.d.ts +3 -5
  375. package/types/helpers/configs.d.ts +39 -1
  376. package/types/helpers/entropy.d.ts +1 -0
  377. package/types/helpers/equivalence.d.ts +1 -1
  378. package/types/helpers/express.d.ts +38 -43
  379. package/types/helpers/find-up/all-in-parent-dirs.d.ts +1 -1
  380. package/types/helpers/find-up/closest.d.ts +1 -1
  381. package/types/helpers/find-up/find-minimatch.d.ts +1 -1
  382. package/types/helpers/generate-meta.d.ts +1 -1
  383. package/types/helpers/mocha.d.ts +19 -21
  384. package/types/helpers/module.d.ts +1 -1
  385. package/types/helpers/package-jsons/all-in-parent-dirs.d.ts +1 -1
  386. package/types/helpers/package-jsons/dependencies.d.ts +1 -1
  387. package/types/helpers/recognizers/CodeRecognizer.d.ts +1 -1
  388. package/types/helpers/recognizers/JavaScriptFootPrint.d.ts +2 -2
  389. package/types/helpers/recognizers/LanguageFootprint.d.ts +1 -1
  390. package/types/helpers/regex/alternation.d.ts +1 -1
  391. package/types/helpers/regex/ast.d.ts +1 -1
  392. package/types/helpers/regex/location.d.ts +2 -2
  393. package/types/helpers/regex/range.d.ts +2 -2
  394. package/types/helpers/regex/rule-template.d.ts +1 -1
  395. package/types/helpers/result.d.ts +1 -1
  396. package/types/helpers/sinon.d.ts +4 -6
  397. package/types/helpers/sonar-runtime.d.ts +1 -1
  398. package/types/helpers/supertest.d.ts +4 -6
  399. package/types/helpers/type.d.ts +1 -1
  400. package/types/helpers/vitest.d.ts +4 -6
  401. package/types/plugin-rules.d.ts +1 -0
  402. package/cjs/helpers/decorators/interceptor.js +0 -88
  403. package/cjs/helpers/index.js +0 -60
  404. package/cjs/helpers/recognizers/index.js +0 -37
  405. package/cjs/helpers/rule-detect-react.js +0 -29
  406. package/cjs/helpers/validate-version.js +0 -94
  407. package/types/helpers/aws/index.d.ts +0 -3
  408. package/types/helpers/decorators/index.d.ts +0 -2
  409. package/types/helpers/decorators/interceptor.d.ts +0 -16
  410. package/types/helpers/index.d.ts +0 -28
  411. package/types/helpers/recognizers/index.d.ts +0 -2
  412. package/types/helpers/rule-detect-react.d.ts +0 -2
  413. package/types/helpers/validate-version.d.ts +0 -13
package/cjs/S2187/rule.js CHANGED
@@ -51,7 +51,7 @@ var __importStar = (this && this.__importStar) || (function () {
51
51
  })();
52
52
  Object.defineProperty(exports, "__esModule", { value: true });
53
53
  exports.rule = void 0;
54
- const index_js_1 = require("../helpers/index.js");
54
+ const generate_meta_js_1 = require("../helpers/generate-meta.js");
55
55
  const meta = __importStar(require("./generated-meta.js"));
56
56
  const APIs = new Set([
57
57
  // Jasmine
@@ -114,7 +114,7 @@ const APIs = new Set([
114
114
  'ruleTester.run',
115
115
  ]);
116
116
  exports.rule = {
117
- meta: (0, index_js_1.generateMeta)(meta, {
117
+ meta: (0, generate_meta_js_1.generateMeta)(meta, {
118
118
  messages: {
119
119
  missingTest: 'Add some tests to this file or delete it.',
120
120
  },
package/cjs/S2201/rule.js CHANGED
@@ -55,7 +55,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
55
55
  Object.defineProperty(exports, "__esModule", { value: true });
56
56
  exports.rule = void 0;
57
57
  const typescript_1 = __importDefault(require("typescript"));
58
- const index_js_1 = require("../helpers/index.js");
58
+ const ancestor_js_1 = require("../helpers/ancestor.js");
59
+ const generate_meta_js_1 = require("../helpers/generate-meta.js");
60
+ const type_js_1 = require("../helpers/type.js");
61
+ const parser_services_js_1 = require("../helpers/parser-services.js");
59
62
  const meta = __importStar(require("./generated-meta.js"));
60
63
  const METHODS_WITHOUT_SIDE_EFFECTS = {
61
64
  array: new Set([
@@ -68,6 +71,8 @@ const METHODS_WITHOUT_SIDE_EFFECTS = {
68
71
  'entries',
69
72
  'filter',
70
73
  'findIndex',
74
+ 'findLast',
75
+ 'findLastIndex',
71
76
  'keys',
72
77
  'map',
73
78
  'values',
@@ -203,7 +208,7 @@ const METHODS_WITHOUT_SIDE_EFFECTS = {
203
208
  ]),
204
209
  };
205
210
  exports.rule = {
206
- meta: (0, index_js_1.generateMeta)(meta, {
211
+ meta: (0, generate_meta_js_1.generateMeta)(meta, {
207
212
  messages: {
208
213
  useForEach: `Consider using "forEach" instead of "map" as its return value is not being used here.`,
209
214
  returnValueMustBeUsed: 'The return value of "{{methodName}}" must be used.',
@@ -211,7 +216,7 @@ exports.rule = {
211
216
  }),
212
217
  create(context) {
213
218
  const services = context.sourceCode.parserServices;
214
- if (!(0, index_js_1.isRequiredParserServices)(services)) {
219
+ if (!(0, parser_services_js_1.isRequiredParserServices)(services)) {
215
220
  return {};
216
221
  }
217
222
  return {
@@ -226,7 +231,8 @@ exports.rule = {
226
231
  .getTypeChecker()
227
232
  .getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(callee.object));
228
233
  if (!hasSideEffect(methodName, objectType, services) &&
229
- !isReplaceWithCallback(methodName, call.arguments, services)) {
234
+ !isReplaceWithCallback(methodName, call.arguments, services) &&
235
+ !isFindWithAssignmentCallback(methodName, call.arguments, context.sourceCode.visitorKeys)) {
230
236
  context.report(reportDescriptor(methodName, node));
231
237
  }
232
238
  }
@@ -241,12 +247,48 @@ const isFunctionTypeNode = (candidate) => {
241
247
  };
242
248
  function isReplaceWithCallback(methodName, callArguments, services) {
243
249
  if (methodName === 'replace' && callArguments.length > 1) {
244
- const type = (0, index_js_1.getTypeFromTreeNode)(callArguments[1], services);
250
+ const type = (0, type_js_1.getTypeFromTreeNode)(callArguments[1], services);
245
251
  const typeNode = services.program.getTypeChecker().typeToTypeNode(type, undefined, undefined);
246
252
  return typeNode && isFunctionTypeNode(typeNode);
247
253
  }
248
254
  return false;
249
255
  }
256
+ // Early-exit array methods currently in METHODS_WITHOUT_SIDE_EFFECTS['array']
257
+ const EARLY_EXIT_ARRAY_METHODS = new Set(['find', 'findIndex', 'findLast', 'findLastIndex']);
258
+ /**
259
+ * Returns true if the call is an early-exit array method whose first argument is an inline
260
+ * function containing an AssignmentExpression. Such callbacks intentionally assign to outer
261
+ * variables to exploit early-exit behavior, making the return value unused by design.
262
+ */
263
+ function isFindWithAssignmentCallback(methodName, callArguments, visitorKeys) {
264
+ if (!EARLY_EXIT_ARRAY_METHODS.has(methodName) || callArguments.length === 0) {
265
+ return false;
266
+ }
267
+ const callback = callArguments[0];
268
+ if (callback.type !== 'ArrowFunctionExpression' && callback.type !== 'FunctionExpression') {
269
+ return false;
270
+ }
271
+ return containsAssignment(callback.body, visitorKeys);
272
+ }
273
+ const FUNCTION_BOUNDARIES = new Set([
274
+ 'FunctionExpression',
275
+ 'ArrowFunctionExpression',
276
+ 'FunctionDeclaration',
277
+ ]);
278
+ /**
279
+ * Recursively checks if an AST node contains an AssignmentExpression, using childrenOf for
280
+ * complete traversal. Stops at nested function boundaries so assignments in inner closures
281
+ * do not suppress the issue.
282
+ */
283
+ function containsAssignment(node, visitorKeys) {
284
+ if (node.type === 'AssignmentExpression') {
285
+ return true;
286
+ }
287
+ if (FUNCTION_BOUNDARIES.has(node.type)) {
288
+ return false;
289
+ }
290
+ return (0, ancestor_js_1.childrenOf)(node, visitorKeys).some(child => containsAssignment(child, visitorKeys));
291
+ }
250
292
  function reportDescriptor(methodName, node) {
251
293
  if (methodName === 'map') {
252
294
  return {
package/cjs/S2208/rule.js CHANGED
@@ -51,10 +51,10 @@ var __importStar = (this && this.__importStar) || (function () {
51
51
  })();
52
52
  Object.defineProperty(exports, "__esModule", { value: true });
53
53
  exports.rule = void 0;
54
- const index_js_1 = require("../helpers/index.js");
54
+ const generate_meta_js_1 = require("../helpers/generate-meta.js");
55
55
  const meta = __importStar(require("./generated-meta.js"));
56
56
  exports.rule = {
57
- meta: (0, index_js_1.generateMeta)(meta, {
57
+ meta: (0, generate_meta_js_1.generateMeta)(meta, {
58
58
  messages: {
59
59
  wildcardImport: 'Explicitly {{xPort}} the specific member needed.',
60
60
  },
package/cjs/S2234/rule.js CHANGED
@@ -51,13 +51,17 @@ var __importStar = (this && this.__importStar) || (function () {
51
51
  })();
52
52
  Object.defineProperty(exports, "__esModule", { value: true });
53
53
  exports.rule = void 0;
54
- const index_js_1 = require("../helpers/index.js");
54
+ const ast_js_1 = require("../helpers/ast.js");
55
+ const generate_meta_js_1 = require("../helpers/generate-meta.js");
56
+ const type_js_1 = require("../helpers/type.js");
57
+ const parser_services_js_1 = require("../helpers/parser-services.js");
58
+ const location_js_1 = require("../helpers/location.js");
55
59
  const meta = __importStar(require("./generated-meta.js"));
56
60
  exports.rule = {
57
- meta: (0, index_js_1.generateMeta)(meta),
61
+ meta: (0, generate_meta_js_1.generateMeta)(meta),
58
62
  create(context) {
59
63
  const services = context.sourceCode.parserServices;
60
- const canResolveType = (0, index_js_1.isRequiredParserServices)(services);
64
+ const canResolveType = (0, parser_services_js_1.isRequiredParserServices)(services);
61
65
  function checkArguments(functionCall) {
62
66
  // Extract argument names first (cheap operation)
63
67
  const argumentNames = functionCall.arguments.map(arg => {
@@ -77,6 +81,9 @@ exports.rule = {
77
81
  return;
78
82
  }
79
83
  const { params: functionParameters, declaration: functionDeclaration } = resolvedFunction;
84
+ if (isCryptoCyclicRotation(functionCall, functionParameters)) {
85
+ return;
86
+ }
80
87
  for (let argumentIndex = 0; argumentIndex < argumentNames.length; argumentIndex++) {
81
88
  const argumentName = argumentNames[argumentIndex];
82
89
  if (argumentName) {
@@ -138,11 +145,11 @@ exports.rule = {
138
145
  return resolveFromTSSignature(node);
139
146
  }
140
147
  let functionDeclaration = null;
141
- if ((0, index_js_1.isFunctionNode)(node.callee)) {
148
+ if ((0, ast_js_1.isFunctionNode)(node.callee)) {
142
149
  functionDeclaration = node.callee;
143
150
  }
144
151
  else if (node.callee.type === 'Identifier') {
145
- functionDeclaration = (0, index_js_1.resolveFromFunctionReference)(context, node.callee);
152
+ functionDeclaration = (0, ast_js_1.resolveFromFunctionReference)(context, node.callee);
146
153
  }
147
154
  if (!functionDeclaration) {
148
155
  return null;
@@ -153,7 +160,7 @@ exports.rule = {
153
160
  };
154
161
  }
155
162
  function resolveFromTSSignature(node) {
156
- const signature = (0, index_js_1.getSignatureFromCallee)(node, services);
163
+ const signature = (0, type_js_1.getSignatureFromCallee)(node, services);
157
164
  if (signature?.declaration) {
158
165
  return {
159
166
  params: signature.parameters.map(param => param.name),
@@ -176,14 +183,14 @@ exports.rule = {
176
183
  }
177
184
  function haveCompatibleTypes(arg1, arg2) {
178
185
  if (canResolveType) {
179
- const type1 = normalizeType((0, index_js_1.getTypeAsString)(arg1, services));
180
- const type2 = normalizeType((0, index_js_1.getTypeAsString)(arg2, services));
186
+ const type1 = normalizeType((0, type_js_1.getTypeAsString)(arg1, services));
187
+ const type2 = normalizeType((0, type_js_1.getTypeAsString)(arg2, services));
181
188
  return type1 === type2;
182
189
  }
183
190
  return true;
184
191
  }
185
192
  function raiseIssue(arg1, arg2, functionDeclaration, node) {
186
- (0, index_js_1.report)(context, {
193
+ (0, location_js_1.report)(context, {
187
194
  message: `Arguments '${arg1}' and '${arg2}' have the same names but not the same order as the function parameters.`,
188
195
  loc: getParametersClauseLocation(node.arguments),
189
196
  }, getSecondaryLocations(functionDeclaration));
@@ -198,9 +205,49 @@ exports.rule = {
198
205
  };
199
206
  },
200
207
  };
208
+ const CRYPTO_FUNCTION_PATTERN = /^(md[45]_?)?(ff|gg|hh|ii)$/i;
209
+ const CRYPTO_STATE_PARAM_COUNT = 4;
210
+ function isCryptoCyclicRotation(functionCall, functionParameters) {
211
+ const callee = functionCall.callee;
212
+ let calleeName = null;
213
+ if (callee.type === 'Identifier') {
214
+ calleeName = callee.name;
215
+ }
216
+ else if (callee.type === 'MemberExpression' && callee.property.type === 'Identifier') {
217
+ calleeName = callee.property.name;
218
+ }
219
+ if (!calleeName || !CRYPTO_FUNCTION_PATTERN.test(calleeName)) {
220
+ return false;
221
+ }
222
+ if (functionParameters.length < CRYPTO_STATE_PARAM_COUNT ||
223
+ functionCall.arguments.length < CRYPTO_STATE_PARAM_COUNT) {
224
+ return false;
225
+ }
226
+ // First 4 arguments must all be identifiers
227
+ const argNames = [];
228
+ for (let i = 0; i < CRYPTO_STATE_PARAM_COUNT; i++) {
229
+ const arg = functionCall.arguments[i];
230
+ if (arg.type !== 'Identifier') {
231
+ return false;
232
+ }
233
+ argNames.push(arg.name);
234
+ }
235
+ // First 4 parameters must all be defined
236
+ const paramNames = functionParameters.slice(0, CRYPTO_STATE_PARAM_COUNT);
237
+ if (paramNames.includes(undefined)) {
238
+ return false;
239
+ }
240
+ // Check if args[0..3] are a cyclic rotation of params[0..3]
241
+ for (let k = 1; k <= CRYPTO_STATE_PARAM_COUNT - 1; k++) {
242
+ if (argNames.every((arg, i) => arg === paramNames[(i + k) % CRYPTO_STATE_PARAM_COUNT])) {
243
+ return true;
244
+ }
245
+ }
246
+ return false;
247
+ }
201
248
  function extractFunctionParameters(functionDeclaration) {
202
249
  return functionDeclaration.params.map(param => {
203
- const identifiers = (0, index_js_1.resolveIdentifiers)(param);
250
+ const identifiers = (0, ast_js_1.resolveIdentifiers)(param);
204
251
  if (identifiers.length === 1 && identifiers[0]) {
205
252
  return identifiers[0].name;
206
253
  }
@@ -210,7 +257,7 @@ function extractFunctionParameters(functionDeclaration) {
210
257
  function getSecondaryLocations(functionDeclaration) {
211
258
  if (functionDeclaration?.params && functionDeclaration.params.length > 0) {
212
259
  const { start, end } = getParametersClauseLocation(functionDeclaration.params);
213
- return [(0, index_js_1.toSecondaryLocation)({ loc: { start, end } }, 'Formal parameters')];
260
+ return [(0, location_js_1.toSecondaryLocation)({ loc: { start, end } }, 'Formal parameters')];
214
261
  }
215
262
  return [];
216
263
  }
package/cjs/S2245/rule.js CHANGED
@@ -51,10 +51,11 @@ var __importStar = (this && this.__importStar) || (function () {
51
51
  })();
52
52
  Object.defineProperty(exports, "__esModule", { value: true });
53
53
  exports.rule = void 0;
54
- const index_js_1 = require("../helpers/index.js");
54
+ const generate_meta_js_1 = require("../helpers/generate-meta.js");
55
+ const module_js_1 = require("../helpers/module.js");
55
56
  const meta = __importStar(require("./generated-meta.js"));
56
57
  exports.rule = {
57
- meta: (0, index_js_1.generateMeta)(meta, {
58
+ meta: (0, generate_meta_js_1.generateMeta)(meta, {
58
59
  messages: {
59
60
  safeGenerator: 'Make sure that using this pseudorandom number generator is safe here.',
60
61
  },
@@ -62,7 +63,7 @@ exports.rule = {
62
63
  create(context) {
63
64
  return {
64
65
  CallExpression(node) {
65
- const fqn = (0, index_js_1.getFullyQualifiedName)(context, node);
66
+ const fqn = (0, module_js_1.getFullyQualifiedName)(context, node);
66
67
  if (fqn === 'Math.random') {
67
68
  context.report({
68
69
  messageId: 'safeGenerator',
package/cjs/S2251/rule.js CHANGED
@@ -51,10 +51,11 @@ var __importStar = (this && this.__importStar) || (function () {
51
51
  })();
52
52
  Object.defineProperty(exports, "__esModule", { value: true });
53
53
  exports.rule = void 0;
54
- const index_js_1 = require("../helpers/index.js");
54
+ const generate_meta_js_1 = require("../helpers/generate-meta.js");
55
+ const location_js_1 = require("../helpers/location.js");
55
56
  const meta = __importStar(require("./generated-meta.js"));
56
57
  exports.rule = {
57
- meta: (0, index_js_1.generateMeta)(meta),
58
+ meta: (0, generate_meta_js_1.generateMeta)(meta),
58
59
  create(context) {
59
60
  return {
60
61
  ForStatement: (node) => {
@@ -67,10 +68,10 @@ exports.rule = {
67
68
  const wrongDirection = getWrongDirection(test, loopIncrement);
68
69
  if (wrongDirection !== 0 && wrongDirection === loopIncrement.direction) {
69
70
  const movement = wrongDirection > 0 ? 'incremented' : 'decremented';
70
- (0, index_js_1.report)(context, {
71
+ (0, location_js_1.report)(context, {
71
72
  message: `"${loopIncrement.identifier.name}" is ${movement} and will never reach its stop condition.`,
72
73
  node: forStatement.update,
73
- }, [(0, index_js_1.toSecondaryLocation)(test)]);
74
+ }, [(0, location_js_1.toSecondaryLocation)(test)]);
74
75
  }
75
76
  },
76
77
  };
package/cjs/S2255/rule.js CHANGED
@@ -51,10 +51,11 @@ var __importStar = (this && this.__importStar) || (function () {
51
51
  })();
52
52
  Object.defineProperty(exports, "__esModule", { value: true });
53
53
  exports.rule = void 0;
54
- const index_js_1 = require("../helpers/index.js");
54
+ const generate_meta_js_1 = require("../helpers/generate-meta.js");
55
+ const ast_js_1 = require("../helpers/ast.js");
55
56
  const meta = __importStar(require("./generated-meta.js"));
56
57
  exports.rule = {
57
- meta: (0, index_js_1.generateMeta)(meta, {
58
+ meta: (0, generate_meta_js_1.generateMeta)(meta, {
58
59
  messages: {
59
60
  safeCookie: 'Make sure that cookie is written safely here.',
60
61
  },
@@ -75,7 +76,7 @@ exports.rule = {
75
76
  const { left } = node;
76
77
  if (left.type === 'MemberExpression') {
77
78
  const { object, property } = left;
78
- if ((0, index_js_1.isIdentifier)(object, 'document') && (0, index_js_1.isIdentifier)(property, 'cookie')) {
79
+ if ((0, ast_js_1.isIdentifier)(object, 'document') && (0, ast_js_1.isIdentifier)(property, 'cookie')) {
79
80
  context.report({
80
81
  messageId: 'safeCookie',
81
82
  node: left,
@@ -87,14 +88,14 @@ exports.rule = {
87
88
  const { callee, arguments: args } = node;
88
89
  if (callee.type === 'MemberExpression' &&
89
90
  usingExpressFramework &&
90
- (0, index_js_1.isIdentifier)(callee.property, 'cookie', 'cookies')) {
91
+ (0, ast_js_1.isIdentifier)(callee.property, 'cookie', 'cookies')) {
91
92
  context.report({
92
93
  messageId: 'safeCookie',
93
94
  node,
94
95
  });
95
96
  }
96
97
  if (callee.type === 'MemberExpression' &&
97
- (0, index_js_1.isIdentifier)(callee.property, 'setHeader') &&
98
+ (0, ast_js_1.isIdentifier)(callee.property, 'setHeader') &&
98
99
  isLiteral(args[0], 'Set-Cookie')) {
99
100
  context.report({
100
101
  messageId: 'safeCookie',
package/cjs/S2259/rule.js CHANGED
@@ -51,7 +51,12 @@ var __importStar = (this && this.__importStar) || (function () {
51
51
  })();
52
52
  Object.defineProperty(exports, "__esModule", { value: true });
53
53
  exports.rule = void 0;
54
- const index_js_1 = require("../helpers/index.js");
54
+ const equivalence_js_1 = require("../helpers/equivalence.js");
55
+ const ancestor_js_1 = require("../helpers/ancestor.js");
56
+ const ast_js_1 = require("../helpers/ast.js");
57
+ const generate_meta_js_1 = require("../helpers/generate-meta.js");
58
+ const parser_services_js_1 = require("../helpers/parser-services.js");
59
+ const type_js_1 = require("../helpers/type.js");
55
60
  const meta = __importStar(require("./generated-meta.js"));
56
61
  var Null;
57
62
  (function (Null) {
@@ -60,19 +65,19 @@ var Null;
60
65
  Null[Null["unknown"] = 2] = "unknown";
61
66
  })(Null || (Null = {}));
62
67
  function isNull(n) {
63
- return (0, index_js_1.isNullLiteral)(n) || (0, index_js_1.isUndefined)(n);
68
+ return (0, ast_js_1.isNullLiteral)(n) || (0, ast_js_1.isUndefined)(n);
64
69
  }
65
70
  const equalOperators = new Set(['==', '===']);
66
71
  const notEqualOperators = new Set(['!=', '!==']);
67
72
  exports.rule = {
68
- meta: (0, index_js_1.generateMeta)(meta, {
73
+ meta: (0, generate_meta_js_1.generateMeta)(meta, {
69
74
  messages: {
70
75
  nullDereference: 'TypeError can be thrown as "{{symbol}}" might be null or undefined here.',
71
76
  shortCircuitError: 'TypeError can be thrown as expression might be null or undefined here.',
72
77
  },
73
78
  }),
74
79
  create(context) {
75
- if (!(0, index_js_1.isRequiredParserServices)(context.sourceCode.parserServices)) {
80
+ if (!(0, parser_services_js_1.isRequiredParserServices)(context.sourceCode.parserServices)) {
76
81
  return {};
77
82
  }
78
83
  const alreadyRaisedSymbols = new Set();
@@ -104,9 +109,9 @@ exports.rule = {
104
109
  function getNullState(expr, node, context) {
105
110
  const { left, right } = expr;
106
111
  if ((isNull(right) &&
107
- (0, index_js_1.areEquivalent)(left, node, context.sourceCode)) ||
112
+ (0, equivalence_js_1.areEquivalent)(left, node, context.sourceCode)) ||
108
113
  (isNull(left) &&
109
- (0, index_js_1.areEquivalent)(right, node, context.sourceCode))) {
114
+ (0, equivalence_js_1.areEquivalent)(right, node, context.sourceCode))) {
110
115
  if (notEqualOperators.has(expr.operator)) {
111
116
  return Null.discarded;
112
117
  }
@@ -131,7 +136,7 @@ function checkLogicalNullDereference(expr, node, context) {
131
136
  function isWrittenInInnerFunction(symbol, fn) {
132
137
  return symbol.references.some(ref => {
133
138
  if (ref.isWrite() && ref.identifier.hasOwnProperty('parent')) {
134
- const enclosingFn = (0, index_js_1.findFirstMatchingAncestor)(ref.identifier, node => index_js_1.functionLike.has(node.type));
139
+ const enclosingFn = (0, ancestor_js_1.findFirstMatchingAncestor)(ref.identifier, node => ast_js_1.functionLike.has(node.type));
135
140
  return enclosingFn && enclosingFn !== fn;
136
141
  }
137
142
  return false;
@@ -148,10 +153,10 @@ function checkNullDereference(node, context, alreadyRaisedSymbols) {
148
153
  }
149
154
  const enclosingFunction = context.sourceCode
150
155
  .getAncestors(node)
151
- .find(n => index_js_1.functionLike.has(n.type));
156
+ .find(n => ast_js_1.functionLike.has(n.type));
152
157
  if (!alreadyRaisedSymbols.has(symbol) &&
153
158
  !isWrittenInInnerFunction(symbol, enclosingFunction) &&
154
- (0, index_js_1.isUndefinedOrNull)(node, context.sourceCode.parserServices)) {
159
+ (0, type_js_1.isUndefinedOrNull)(node, context.sourceCode.parserServices)) {
155
160
  alreadyRaisedSymbols.add(symbol);
156
161
  context.report({
157
162
  messageId: 'nullDereference',
package/cjs/S2301/rule.js CHANGED
@@ -51,20 +51,25 @@ var __importStar = (this && this.__importStar) || (function () {
51
51
  })();
52
52
  Object.defineProperty(exports, "__esModule", { value: true });
53
53
  exports.rule = void 0;
54
- const index_js_1 = require("../helpers/index.js");
54
+ const generate_meta_js_1 = require("../helpers/generate-meta.js");
55
+ const type_js_1 = require("../helpers/type.js");
56
+ const reaching_definitions_js_1 = require("../helpers/reaching-definitions.js");
57
+ const ast_js_1 = require("../helpers/ast.js");
58
+ const parser_services_js_1 = require("../helpers/parser-services.js");
59
+ const location_js_1 = require("../helpers/location.js");
55
60
  const meta = __importStar(require("./generated-meta.js"));
56
61
  const message = 'Provide multiple methods instead of using "{{parameterName}}" to determine which action to take.';
57
62
  /**
58
63
  * A suspect test node is a test node that is the only child of a function body
59
64
  */
60
65
  exports.rule = {
61
- meta: (0, index_js_1.generateMeta)(meta, {
66
+ meta: (0, generate_meta_js_1.generateMeta)(meta, {
62
67
  messages: {
63
68
  message,
64
69
  },
65
70
  }),
66
71
  create: context => {
67
- if (!(0, index_js_1.isRequiredParserServices)(context.sourceCode.parserServices)) {
72
+ if (!(0, parser_services_js_1.isRequiredParserServices)(context.sourceCode.parserServices)) {
68
73
  return {};
69
74
  }
70
75
  const suspectTestNodes = [];
@@ -77,7 +82,7 @@ exports.rule = {
77
82
  }
78
83
  };
79
84
  const isAChildOf = (identifier, node) => {
80
- if ((0, index_js_1.hasParent)(identifier)) {
85
+ if ((0, ast_js_1.hasParent)(identifier)) {
81
86
  if (identifier.parent === node) {
82
87
  return true;
83
88
  }
@@ -114,21 +119,21 @@ exports.rule = {
114
119
  if (!isSuspect) {
115
120
  return;
116
121
  }
117
- const variable = (0, index_js_1.getVariableFromIdentifier)(node, context.sourceCode.getScope(node));
122
+ const variable = (0, reaching_definitions_js_1.getVariableFromIdentifier)(node, context.sourceCode.getScope(node));
118
123
  if (variable) {
119
124
  const definition = variable.defs.at(-1);
120
125
  if (definition?.type === 'Parameter') {
121
- const type = (0, index_js_1.getTypeFromTreeNode)(definition.name, context.sourceCode.parserServices);
126
+ const type = (0, type_js_1.getTypeFromTreeNode)(definition.name, context.sourceCode.parserServices);
122
127
  const definitionParent = definition.name.parent;
123
- if ((0, index_js_1.isBooleanType)(type) && definitionParent?.type !== 'Property') {
124
- (0, index_js_1.report)(context, {
128
+ if ((0, type_js_1.isBooleanType)(type) && definitionParent?.type !== 'Property') {
129
+ (0, location_js_1.report)(context, {
125
130
  message,
126
131
  loc: node.loc,
127
132
  data: {
128
133
  parameterName: variable.name,
129
134
  },
130
135
  }, [
131
- (0, index_js_1.toSecondaryLocation)(definition.name, `Parameter "${variable.name}" was declared here`),
136
+ (0, location_js_1.toSecondaryLocation)(definition.name, `Parameter "${variable.name}" was declared here`),
132
137
  ]);
133
138
  }
134
139
  }
package/cjs/S2310/rule.js CHANGED
@@ -51,10 +51,13 @@ var __importStar = (this && this.__importStar) || (function () {
51
51
  })();
52
52
  Object.defineProperty(exports, "__esModule", { value: true });
53
53
  exports.rule = void 0;
54
- const index_js_1 = require("../helpers/index.js");
54
+ const generate_meta_js_1 = require("../helpers/generate-meta.js");
55
+ const ancestor_js_1 = require("../helpers/ancestor.js");
56
+ const ast_js_1 = require("../helpers/ast.js");
57
+ const location_js_1 = require("../helpers/location.js");
55
58
  const meta = __importStar(require("./generated-meta.js"));
56
59
  exports.rule = {
57
- meta: (0, index_js_1.generateMeta)(meta),
60
+ meta: (0, generate_meta_js_1.generateMeta)(meta),
58
61
  create(context) {
59
62
  function checkLoop(updateNode, extractCounters, loopBody) {
60
63
  const counters = [];
@@ -64,7 +67,7 @@ exports.rule = {
64
67
  }
65
68
  }
66
69
  function checkCounter(counter, block) {
67
- const variable = (0, index_js_1.getVariableFromName)(context, counter.name, block);
70
+ const variable = (0, ast_js_1.getVariableFromName)(context, counter.name, block);
68
71
  if (!variable) {
69
72
  return;
70
73
  }
@@ -73,16 +76,16 @@ exports.rule = {
73
76
  if (isIntentionalSkipAhead(ref.identifier, block)) {
74
77
  continue;
75
78
  }
76
- (0, index_js_1.report)(context, {
79
+ (0, location_js_1.report)(context, {
77
80
  node: ref.identifier,
78
81
  message: `Remove this assignment of "${counter.name}".`,
79
- }, [(0, index_js_1.toSecondaryLocation)(counter, 'Counter variable update')]);
82
+ }, [(0, location_js_1.toSecondaryLocation)(counter, 'Counter variable update')]);
80
83
  }
81
84
  }
82
85
  }
83
86
  return {
84
87
  'ForStatement > BlockStatement': (node) => {
85
- const forLoop = (0, index_js_1.getParent)(context, node);
88
+ const forLoop = (0, ancestor_js_1.getParent)(context, node);
86
89
  if (forLoop.update) {
87
90
  checkLoop(forLoop.update, collectCountersFor, node);
88
91
  }
@@ -113,28 +116,96 @@ function collectCountersFor(updateExpression, counters) {
113
116
  /**
114
117
  * Checks if a loop counter modification is an intentional skip-ahead pattern
115
118
  * (UpdateExpression or compound assignment) rather than a simple assignment.
119
+ * Simple assignments (=) are allowed when a splice() call using the same
120
+ * counter variable exists in the enclosing block (splice compensation pattern).
116
121
  * Modifications in nested for-loop update clauses are not considered skip-ahead.
117
122
  */
118
123
  function isIntentionalSkipAhead(id, outerLoopBody) {
119
124
  if (isInNestedForLoopUpdate(id, outerLoopBody)) {
120
125
  return false;
121
126
  }
122
- const parent = (0, index_js_1.getNodeParent)(id);
127
+ const parent = (0, ancestor_js_1.getNodeParent)(id);
123
128
  if (parent?.type === 'UpdateExpression') {
124
129
  return true;
125
130
  }
126
131
  if (parent?.type === 'AssignmentExpression' && parent.operator !== '=') {
127
132
  return true;
128
133
  }
134
+ if (parent?.type === 'AssignmentExpression' && parent.operator === '=') {
135
+ const block = findEnclosingBlock(id);
136
+ if (block && blockContainsSpliceWithCounter(block, id.name)) {
137
+ return true;
138
+ }
139
+ }
140
+ return false;
141
+ }
142
+ /**
143
+ * Walks up the AST from the given node to find the nearest enclosing BlockStatement.
144
+ */
145
+ function findEnclosingBlock(node) {
146
+ let current = (0, ancestor_js_1.getNodeParent)(node);
147
+ while (current) {
148
+ if (current.type === 'BlockStatement') {
149
+ return current;
150
+ }
151
+ current = (0, ancestor_js_1.getNodeParent)(current);
152
+ }
153
+ return undefined;
154
+ }
155
+ /**
156
+ * Checks whether a block contains a splice() call whose first argument
157
+ * is an Identifier matching the given counter variable name.
158
+ */
159
+ function blockContainsSpliceWithCounter(block, counterName) {
160
+ return block.body.some(stmt => containsSpliceWithCounter(stmt, counterName));
161
+ }
162
+ /**
163
+ * Checks whether a statement contains a splice() call whose first argument
164
+ * references the given counter variable name. Only checks direct statements
165
+ * in the block — not ones nested inside conditional branches.
166
+ */
167
+ function containsSpliceWithCounter(node, counterName) {
168
+ if (node.type === 'ExpressionStatement') {
169
+ return expressionContainsSplice(node.expression, counterName);
170
+ }
171
+ if (node.type === 'VariableDeclaration' &&
172
+ node.declarations.some(d => d.init?.type === 'CallExpression' && isSpliceCallWithCounter(d.init, counterName))) {
173
+ return true;
174
+ }
129
175
  return false;
130
176
  }
177
+ /**
178
+ * Checks whether an expression is or contains a splice() call whose first argument
179
+ * matches the given counter variable name. Handles both direct splice calls
180
+ * and splice calls on the right side of assignments (e.g., removed = arr.splice(i, 1)).
181
+ */
182
+ function expressionContainsSplice(expr, counterName) {
183
+ if (expr.type === 'CallExpression') {
184
+ return isSpliceCallWithCounter(expr, counterName);
185
+ }
186
+ return (expr.type === 'AssignmentExpression' &&
187
+ expr.right.type === 'CallExpression' &&
188
+ isSpliceCallWithCounter(expr.right, counterName));
189
+ }
190
+ /**
191
+ * Checks if a CallExpression is a .splice() call whose first argument
192
+ * is an Identifier matching the counter variable name.
193
+ */
194
+ function isSpliceCallWithCounter(call, counterName) {
195
+ return (call.callee.type === 'MemberExpression' &&
196
+ call.callee.property.type === 'Identifier' &&
197
+ call.callee.property.name === 'splice' &&
198
+ call.arguments.length >= 1 &&
199
+ call.arguments[0].type === 'Identifier' &&
200
+ call.arguments[0].name === counterName);
201
+ }
131
202
  function isUsedInsideBody(id, loopBody) {
132
203
  const bodyRange = loopBody.range;
133
204
  return id.range && bodyRange && id.range[0] > bodyRange[0] && id.range[1] < bodyRange[1];
134
205
  }
135
206
  function isInNestedForLoopUpdate(id, outerLoopBody) {
136
207
  let node = id;
137
- let parent = (0, index_js_1.getNodeParent)(node);
208
+ let parent = (0, ancestor_js_1.getNodeParent)(node);
138
209
  while (parent) {
139
210
  // Stop if we've reached the outer loop body
140
211
  if (parent === outerLoopBody) {
@@ -151,7 +222,7 @@ function isInNestedForLoopUpdate(id, outerLoopBody) {
151
222
  }
152
223
  }
153
224
  node = parent;
154
- parent = (0, index_js_1.getNodeParent)(node);
225
+ parent = (0, ancestor_js_1.getNodeParent)(node);
155
226
  }
156
227
  return false;
157
228
  }