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.
- package/README.md +269 -268
- package/cjs/S100/rule.js +7 -5
- package/cjs/S101/rule.js +2 -2
- package/cjs/S104/rule.js +2 -2
- package/cjs/S105/rule.js +2 -2
- package/cjs/S1066/rule.js +5 -4
- package/cjs/S1067/rule.js +8 -6
- package/cjs/S1110/rule.js +7 -5
- package/cjs/S1119/rule.js +85 -7
- package/cjs/S1121/rule.js +4 -3
- package/cjs/S1125/rule.js +9 -8
- package/cjs/S1126/rule.js +2 -2
- package/cjs/S1128/rule.js +8 -5
- package/cjs/S1134/rule.js +2 -2
- package/cjs/S1135/rule.js +2 -2
- package/cjs/S1154/rule.js +6 -4
- package/cjs/S117/rule.js +6 -5
- package/cjs/S1172/rule.js +2 -2
- package/cjs/S1192/rule.js +5 -4
- package/cjs/S1219/rule.js +4 -3
- package/cjs/S1226/rule.js +6 -4
- package/cjs/S124/rule.js +2 -2
- package/cjs/S125/rule.js +9 -7
- package/cjs/S126/rule.js +2 -2
- package/cjs/S1264/rule.js +2 -2
- package/cjs/S128/rule.js +4 -3
- package/cjs/S1291/rule.js +2 -2
- package/cjs/S1301/rule.js +2 -2
- package/cjs/S1313/rule.js +2 -2
- package/cjs/S134/rule.js +7 -5
- package/cjs/S135/rule.js +5 -4
- package/cjs/S138/rule.js +9 -6
- package/cjs/S1439/rule.js +2 -2
- package/cjs/S1444/rule.js +2 -2
- package/cjs/S1451/rule.js +2 -2
- package/cjs/S1472/rule.js +2 -2
- package/cjs/S1479/rule.js +2 -2
- package/cjs/S1481/rule.js +2 -2
- package/cjs/S1488/generated-meta.js +1 -1
- package/cjs/S1488/rule.js +11 -7
- package/cjs/S1515/rule.js +10 -8
- package/cjs/{helpers/aws/index.js → S1523/generated-meta.js} +34 -18
- package/cjs/S1523/index.js +21 -0
- package/cjs/S1523/meta.js +21 -0
- package/cjs/S1523/rule.js +143 -0
- package/cjs/S1526/rule.js +5 -4
- package/cjs/S1527/rule.js +2 -2
- package/cjs/S1528/rule.js +2 -2
- package/cjs/S1529/generated-meta.js +1 -1
- package/cjs/S1529/rule.js +4 -3
- package/cjs/S1530/rule.js +5 -3
- package/cjs/S1533/rule.js +2 -2
- package/cjs/S1535/rule.js +2 -2
- package/cjs/S1541/rule.js +10 -7
- package/cjs/S1607/rule.js +22 -20
- package/cjs/S1764/rule.js +10 -7
- package/cjs/S1821/rule.js +2 -2
- package/cjs/S1848/rule.js +10 -7
- package/cjs/S1854/rule.js +18 -14
- package/cjs/S1862/rule.js +10 -8
- package/cjs/S1871/rule.js +21 -16
- package/cjs/S1874/rule.js +4 -3
- package/cjs/S1940/rule.js +2 -2
- package/cjs/S1994/rule.js +10 -7
- package/cjs/S2004/rule.js +9 -7
- package/cjs/S2068/rule.js +75 -12
- package/cjs/S2077/generated-meta.js +1 -1
- package/cjs/S2077/rule.js +10 -6
- package/cjs/S2092/rule.js +2 -2
- package/cjs/S2123/rule.js +2 -2
- package/cjs/S2137/rule.js +2 -2
- package/cjs/S2138/rule.js +4 -3
- package/cjs/S2187/rule.js +2 -2
- package/cjs/S2201/rule.js +47 -5
- package/cjs/S2208/rule.js +2 -2
- package/cjs/S2234/rule.js +58 -11
- package/cjs/S2245/rule.js +4 -3
- package/cjs/S2251/rule.js +5 -4
- package/cjs/S2255/rule.js +6 -5
- package/cjs/S2259/rule.js +14 -9
- package/cjs/S2301/rule.js +14 -9
- package/cjs/S2310/rule.js +80 -9
- package/cjs/S2392/rule.js +7 -5
- package/cjs/S2424/rule.js +2 -2
- package/cjs/S2428/rule.js +8 -6
- package/cjs/S2486/rule.js +4 -3
- package/cjs/S2589/rule.js +12 -10
- package/cjs/S2598/rule.js +17 -14
- package/cjs/S2612/generated-meta.js +1 -1
- package/cjs/S2612/rule.js +8 -6
- package/cjs/S2639/rule.js +2 -2
- package/cjs/S2681/rule.js +2 -2
- package/cjs/S2692/rule.js +6 -4
- package/cjs/S2699/generated-meta.js +1 -1
- package/cjs/S2699/rule.js +40 -31
- package/cjs/S2703/rule.js +2 -2
- package/cjs/S2737/rule.js +6 -4
- package/cjs/S2755/rule.js +9 -6
- package/cjs/S2757/rule.js +2 -2
- package/cjs/S2817/rule.js +10 -7
- package/cjs/S2819/rule.js +16 -12
- package/cjs/S2870/rule.js +8 -5
- package/cjs/S2871/rule.js +12 -9
- package/cjs/S2970/rule.js +9 -8
- package/cjs/S2990/rule.js +2 -2
- package/cjs/S2999/rule.js +10 -7
- package/cjs/S3001/rule.js +2 -2
- package/cjs/S3003/rule.js +10 -7
- package/cjs/S3317/rule.js +4 -3
- package/cjs/S3330/rule.js +2 -2
- package/cjs/S3358/rule.js +2 -2
- package/cjs/S3402/rule.js +14 -10
- package/cjs/S3403/rule.js +10 -7
- package/cjs/S3415/rule.js +16 -13
- package/cjs/S3499/rule.js +5 -4
- package/cjs/S3500/rule.js +5 -4
- package/cjs/S3513/rule.js +5 -4
- package/cjs/S3514/rule.js +10 -7
- package/cjs/S3516/rule.js +10 -7
- package/cjs/S3524/rule.js +2 -2
- package/cjs/S3525/rule.js +6 -4
- package/cjs/S3531/rule.js +5 -3
- package/cjs/S3533/rule.js +8 -7
- package/cjs/S3579/rule.js +6 -4
- package/cjs/S3616/rule.js +6 -4
- package/cjs/S3626/rule.js +4 -3
- package/cjs/S3686/rule.js +7 -5
- package/cjs/S3699/rule.js +4 -3
- package/cjs/S3735/rule.js +8 -5
- package/cjs/S3757/rule.js +8 -6
- package/cjs/S3758/rule.js +9 -7
- package/cjs/S3760/rule.js +24 -21
- package/cjs/S3776/rule.js +26 -22
- package/cjs/S3782/rule.js +6 -4
- package/cjs/S3785/rule.js +9 -6
- package/cjs/S3796/rule.js +12 -8
- package/cjs/S3798/rule.js +4 -3
- package/cjs/S3800/rule.js +22 -11
- package/cjs/S3801/generated-meta.js +1 -1
- package/cjs/S3801/rule.js +15 -11
- package/cjs/S3827/rule.js +9 -6
- package/cjs/S3923/rule.js +9 -6
- package/cjs/S3972/rule.js +5 -4
- package/cjs/S3973/rule.js +7 -5
- package/cjs/S3981/rule.js +4 -3
- package/cjs/S3984/rule.js +4 -3
- package/cjs/S4030/rule.js +10 -7
- package/cjs/S4036/rule.js +7 -5
- package/cjs/S4043/rule.js +12 -8
- package/cjs/S4139/rule.js +7 -5
- package/cjs/S4143/rule.js +12 -9
- package/cjs/S4144/rule.js +12 -9
- package/cjs/S4158/rule.js +11 -8
- package/cjs/S4165/rule.js +14 -12
- package/cjs/S4322/rule.js +8 -5
- package/cjs/S4323/rule.js +4 -3
- package/cjs/S4324/rule.js +7 -5
- package/cjs/S4328/rule.js +2 -2
- package/cjs/S4335/rule.js +6 -4
- package/cjs/S4423/rule.js +4 -3
- package/cjs/S4423/rule.lib.js +8 -7
- package/cjs/S4426/rule.js +11 -10
- package/cjs/S4502/rule.js +16 -13
- package/cjs/S4507/rule.js +8 -6
- package/cjs/S4524/rule.js +2 -2
- package/cjs/S4619/rule.js +6 -4
- package/cjs/S4621/rule.js +5 -4
- package/cjs/S4622/rule.js +5 -3
- package/cjs/S4623/rule.js +8 -5
- package/cjs/S4624/rule.js +6 -4
- package/cjs/S4634/rule.js +4 -3
- package/cjs/S4721/rule.js +7 -5
- package/cjs/S4782/rule.js +7 -5
- package/cjs/S4784/rule.js +5 -4
- package/cjs/S4787/rule.js +9 -7
- package/cjs/S4790/rule.js +7 -5
- package/cjs/S4798/rule.js +2 -2
- package/cjs/S4817/rule.js +10 -8
- package/cjs/S4818/rule.js +4 -3
- package/cjs/S4822/rule.js +13 -9
- package/cjs/S4823/rule.js +4 -3
- package/cjs/S4829/rule.js +4 -3
- package/cjs/S4830/rule.js +11 -8
- package/cjs/S5042/rule.js +9 -7
- package/cjs/S5122/rule.js +40 -36
- package/cjs/S5148/rule.js +9 -8
- package/cjs/S5247/rule.js +22 -18
- package/cjs/S5256/rule.js +5 -4
- package/cjs/S5257/rule.js +4 -3
- package/cjs/S5260/rule.js +4 -3
- package/cjs/S5264/rule.js +4 -3
- package/cjs/S5332/rule.js +4 -3
- package/cjs/S5332/rule.lib.js +19 -17
- package/cjs/S5443/rule.js +2 -2
- package/cjs/S5527/rule.js +18 -14
- package/cjs/S5542/rule.js +6 -4
- package/cjs/S5547/rule.js +6 -4
- package/cjs/S5604/rule.js +15 -14
- package/cjs/S5659/rule.js +15 -12
- package/cjs/S5689/rule.js +11 -8
- package/cjs/S5691/rule.js +7 -5
- package/cjs/S5693/rule.js +14 -12
- package/cjs/S5725/rule.js +9 -6
- package/cjs/S5728/rule.js +7 -4
- package/cjs/S5730/rule.js +9 -6
- package/cjs/S5732/rule.js +8 -5
- package/cjs/S5734/rule.js +7 -4
- package/cjs/S5736/rule.js +8 -5
- package/cjs/S5739/rule.js +11 -8
- package/cjs/S5742/rule.js +7 -4
- package/cjs/S5743/rule.js +8 -6
- package/cjs/S5757/rule.js +13 -10
- package/cjs/S5759/rule.js +10 -7
- package/cjs/S5842/rule.js +2 -2
- package/cjs/S5843/rule.js +22 -19
- package/cjs/S5850/rule.js +4 -3
- package/cjs/S5852/rule.js +2 -2
- package/cjs/S5856/rule.js +10 -7
- package/cjs/S5860/rule.js +30 -26
- package/cjs/S5863/rule.js +15 -11
- package/cjs/S5867/rule.js +8 -7
- package/cjs/S5868/rule.js +7 -5
- package/cjs/S5869/rule.js +6 -5
- package/cjs/S5876/rule.js +12 -8
- package/cjs/S5958/rule.js +12 -9
- package/cjs/S5973/rule.js +10 -7
- package/cjs/S6019/rule.js +4 -3
- package/cjs/S6035/rule.js +2 -2
- package/cjs/S6079/rule.js +9 -6
- package/cjs/S6080/rule.js +13 -10
- package/cjs/S6092/rule.js +9 -7
- package/cjs/S6245/rule.js +14 -9
- package/cjs/S6249/rule.js +7 -5
- package/cjs/S6252/rule.js +12 -8
- package/cjs/S6265/rule.js +27 -20
- package/cjs/S6268/rule.js +5 -4
- package/cjs/S6270/rule.js +12 -9
- package/cjs/S6275/rule.js +2 -2
- package/cjs/S6281/rule.js +22 -17
- package/cjs/S6299/rule.js +2 -2
- package/cjs/S6302/rule.js +6 -5
- package/cjs/S6303/rule.js +12 -10
- package/cjs/S6304/rule.js +6 -5
- package/cjs/S6308/rule.js +7 -5
- package/cjs/S6317/rule.js +5 -4
- package/cjs/S6319/rule.js +2 -2
- package/cjs/S6321/rule.js +25 -23
- package/cjs/S6323/rule.js +4 -3
- package/cjs/S6324/rule.js +2 -2
- package/cjs/S6326/rule.js +2 -2
- package/cjs/S6327/rule.js +2 -2
- package/cjs/S6328/rule.js +4 -3
- package/cjs/S6329/rule.js +7 -5
- package/cjs/S6330/rule.js +2 -2
- package/cjs/S6332/rule.js +2 -2
- package/cjs/S6333/rule.js +8 -6
- package/cjs/S6351/rule.js +22 -19
- package/cjs/S6353/rule.js +2 -2
- package/cjs/S6397/rule.js +2 -2
- package/cjs/S6418/config.js +1 -1
- package/cjs/S6418/rule.js +9 -24
- package/cjs/S6426/rule.js +5 -4
- package/cjs/S6437/rule.js +10 -7
- package/cjs/S6439/rule.js +9 -7
- package/cjs/S6442/rule.js +11 -8
- package/cjs/S6443/rule.js +9 -7
- package/cjs/S6486/rule.js +5 -4
- package/cjs/S6564/rule.js +4 -3
- package/cjs/S6594/rule.js +12 -8
- package/cjs/S6627/rule.js +6 -4
- package/cjs/S6759/rule.js +10 -6
- package/cjs/S6958/rule.js +2 -2
- package/cjs/S6959/rule.js +9 -6
- package/cjs/S7059/generated-meta.js +1 -1
- package/cjs/S7059/rule.js +8 -5
- package/cjs/S7639/generated-meta.js +1 -1
- package/cjs/S7639/rule.js +5 -4
- package/cjs/S7790/generated-meta.js +1 -1
- package/cjs/S7790/rule.js +7 -5
- package/cjs/S8441/generated-meta.js +1 -1
- package/cjs/S8441/rule.js +13 -9
- package/cjs/S881/rule.js +2 -2
- package/cjs/S888/rule.js +4 -3
- package/cjs/S930/rule.js +14 -12
- package/cjs/helpers/ast.js +11 -8
- package/cjs/helpers/aws/s3.js +9 -6
- package/cjs/helpers/chai.js +41 -43
- package/cjs/helpers/configs.js +92 -0
- package/cjs/helpers/cookie-flag-check.js +19 -17
- package/cjs/helpers/{decorators/index.js → entropy.js} +16 -17
- package/cjs/helpers/express.js +127 -128
- package/cjs/helpers/find-up/all-in-parent-dirs.js +0 -16
- package/cjs/helpers/mocha.js +50 -54
- package/cjs/helpers/regex/ast.js +7 -6
- package/cjs/helpers/regex/extract.js +11 -11
- package/cjs/helpers/regex/group.js +2 -2
- package/cjs/helpers/regex/location.js +2 -2
- package/cjs/helpers/regex/range.js +5 -4
- package/cjs/helpers/regex/rule-template.js +4 -3
- package/cjs/helpers/sinon.js +33 -36
- package/cjs/helpers/supertest.js +34 -37
- package/cjs/helpers/vitest.js +29 -32
- package/cjs/plugin-rules.js +452 -450
- package/docs/assertions-in-tests.md +2 -0
- package/docs/bitwise-operators.md +2 -0
- package/docs/code-eval.md +7 -0
- package/docs/file-permissions.md +1 -1
- package/docs/no-async-constructor.md +2 -0
- package/docs/no-inconsistent-returns.md +2 -0
- package/docs/prefer-immediate-return.md +2 -0
- package/docs/sql-queries.md +2 -0
- package/package.json +39 -1
- package/types/S1067/rule.d.ts +1 -1
- package/types/S1110/rule.d.ts +1 -1
- package/types/S1128/rule.d.ts +1 -1
- package/types/S1172/rule.d.ts +1 -1
- package/types/S1226/rule.d.ts +1 -1
- package/types/S134/rule.d.ts +1 -1
- package/types/S1472/rule.d.ts +1 -1
- package/types/S1481/rule.d.ts +1 -1
- package/types/S1488/generated-meta.d.ts +1 -1
- package/types/S1515/rule.d.ts +1 -1
- package/types/S1523/generated-meta.d.ts +17 -0
- package/types/S1523/index.d.ts +1 -0
- package/types/S1523/meta.d.ts +2 -0
- package/types/S1523/rule.d.ts +2 -0
- package/types/S1527/rule.d.ts +1 -1
- package/types/S1529/generated-meta.d.ts +1 -1
- package/types/S1541/rule.d.ts +1 -1
- package/types/S1862/rule.d.ts +1 -1
- package/types/S2077/generated-meta.d.ts +1 -1
- package/types/S2123/rule.d.ts +1 -1
- package/types/S2259/rule.d.ts +1 -1
- package/types/S2428/rule.d.ts +1 -1
- package/types/S2589/rule.d.ts +1 -1
- package/types/S2598/rule.d.ts +1 -1
- package/types/S2699/generated-meta.d.ts +1 -1
- package/types/S2699/rule.d.ts +1 -1
- package/types/S2737/rule.d.ts +1 -1
- package/types/S2757/rule.d.ts +1 -1
- package/types/S2819/rule.d.ts +1 -1
- package/types/S3001/rule.d.ts +1 -1
- package/types/S3317/rule.d.ts +1 -1
- package/types/S3500/rule.d.ts +1 -1
- package/types/S3513/rule.d.ts +1 -1
- package/types/S3686/rule.d.ts +1 -1
- package/types/S3801/generated-meta.d.ts +1 -1
- package/types/S3972/rule.d.ts +1 -1
- package/types/S3973/rule.d.ts +1 -1
- package/types/S4030/rule.d.ts +1 -1
- package/types/S4143/rule.d.ts +1 -1
- package/types/S4158/rule.d.ts +1 -1
- package/types/S4621/rule.d.ts +1 -1
- package/types/S4782/rule.d.ts +1 -1
- package/types/S5693/rule.d.ts +1 -1
- package/types/S5725/rule.d.ts +1 -1
- package/types/S5860/rule.d.ts +1 -1
- package/types/S5868/rule.d.ts +1 -1
- package/types/S5869/rule.d.ts +1 -1
- package/types/S6079/rule.d.ts +1 -1
- package/types/S6326/rule.d.ts +1 -1
- package/types/S6351/rule.d.ts +1 -1
- package/types/S6418/config.d.ts +1 -1
- package/types/S6443/rule.d.ts +1 -1
- package/types/S7059/generated-meta.d.ts +1 -1
- package/types/S7639/generated-meta.d.ts +1 -1
- package/types/S7790/generated-meta.d.ts +1 -1
- package/types/S8441/generated-meta.d.ts +1 -1
- package/types/S930/rule.d.ts +1 -1
- package/types/helpers/ancestor.d.ts +3 -3
- package/types/helpers/ast.d.ts +1 -1
- package/types/helpers/aws/iam.d.ts +2 -2
- package/types/helpers/aws/s3.d.ts +1 -1
- package/types/helpers/chai.d.ts +3 -5
- package/types/helpers/configs.d.ts +39 -1
- package/types/helpers/entropy.d.ts +1 -0
- package/types/helpers/equivalence.d.ts +1 -1
- package/types/helpers/express.d.ts +38 -43
- package/types/helpers/find-up/all-in-parent-dirs.d.ts +1 -1
- package/types/helpers/find-up/closest.d.ts +1 -1
- package/types/helpers/find-up/find-minimatch.d.ts +1 -1
- package/types/helpers/generate-meta.d.ts +1 -1
- package/types/helpers/mocha.d.ts +19 -21
- package/types/helpers/module.d.ts +1 -1
- package/types/helpers/package-jsons/all-in-parent-dirs.d.ts +1 -1
- package/types/helpers/package-jsons/dependencies.d.ts +1 -1
- package/types/helpers/recognizers/CodeRecognizer.d.ts +1 -1
- package/types/helpers/recognizers/JavaScriptFootPrint.d.ts +2 -2
- package/types/helpers/recognizers/LanguageFootprint.d.ts +1 -1
- package/types/helpers/regex/alternation.d.ts +1 -1
- package/types/helpers/regex/ast.d.ts +1 -1
- package/types/helpers/regex/location.d.ts +2 -2
- package/types/helpers/regex/range.d.ts +2 -2
- package/types/helpers/regex/rule-template.d.ts +1 -1
- package/types/helpers/result.d.ts +1 -1
- package/types/helpers/sinon.d.ts +4 -6
- package/types/helpers/sonar-runtime.d.ts +1 -1
- package/types/helpers/supertest.d.ts +4 -6
- package/types/helpers/type.d.ts +1 -1
- package/types/helpers/vitest.d.ts +4 -6
- package/types/plugin-rules.d.ts +1 -0
- package/cjs/helpers/decorators/interceptor.js +0 -88
- package/cjs/helpers/index.js +0 -60
- package/cjs/helpers/recognizers/index.js +0 -37
- package/cjs/helpers/rule-detect-react.js +0 -29
- package/cjs/helpers/validate-version.js +0 -94
- package/types/helpers/aws/index.d.ts +0 -3
- package/types/helpers/decorators/index.d.ts +0 -2
- package/types/helpers/decorators/interceptor.d.ts +0 -16
- package/types/helpers/index.d.ts +0 -28
- package/types/helpers/recognizers/index.d.ts +0 -2
- package/types/helpers/rule-detect-react.d.ts +0 -2
- 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
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
61
|
+
meta: (0, generate_meta_js_1.generateMeta)(meta),
|
|
58
62
|
create(context) {
|
|
59
63
|
const services = context.sourceCode.parserServices;
|
|
60
|
-
const canResolveType = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
180
|
-
const type2 = normalizeType((0,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
112
|
+
(0, equivalence_js_1.areEquivalent)(left, node, context.sourceCode)) ||
|
|
108
113
|
(isNull(left) &&
|
|
109
|
-
(0,
|
|
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,
|
|
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 =>
|
|
156
|
+
.find(n => ast_js_1.functionLike.has(n.type));
|
|
152
157
|
if (!alreadyRaisedSymbols.has(symbol) &&
|
|
153
158
|
!isWrittenInInnerFunction(symbol, enclosingFunction) &&
|
|
154
|
-
(0,
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
126
|
+
const type = (0, type_js_1.getTypeFromTreeNode)(definition.name, context.sourceCode.parserServices);
|
|
122
127
|
const definitionParent = definition.name.parent;
|
|
123
|
-
if ((0,
|
|
124
|
-
(0,
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
79
|
+
(0, location_js_1.report)(context, {
|
|
77
80
|
node: ref.identifier,
|
|
78
81
|
message: `Remove this assignment of "${counter.name}".`,
|
|
79
|
-
}, [(0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
225
|
+
parent = (0, ancestor_js_1.getNodeParent)(node);
|
|
155
226
|
}
|
|
156
227
|
return false;
|
|
157
228
|
}
|