@opensip-cli/checks-typescript 0.1.10 → 0.1.12

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 (252) hide show
  1. package/README.md +4 -2
  2. package/dist/__tests__/all-checks-execute.test.d.ts.map +1 -1
  3. package/dist/__tests__/all-checks-execute.test.js +0 -1
  4. package/dist/__tests__/all-checks-execute.test.js.map +1 -1
  5. package/dist/__tests__/behavior-fixtures-2.test.d.ts.map +1 -1
  6. package/dist/__tests__/behavior-fixtures-2.test.js +0 -1
  7. package/dist/__tests__/behavior-fixtures-2.test.js.map +1 -1
  8. package/dist/__tests__/behavior-fixtures-3.test.d.ts.map +1 -1
  9. package/dist/__tests__/behavior-fixtures-3.test.js +0 -1
  10. package/dist/__tests__/behavior-fixtures-3.test.js.map +1 -1
  11. package/dist/__tests__/behavior-fixtures-4.test.d.ts.map +1 -1
  12. package/dist/__tests__/behavior-fixtures-4.test.js +0 -1
  13. package/dist/__tests__/behavior-fixtures-4.test.js.map +1 -1
  14. package/dist/__tests__/behavior-fixtures-5.test.d.ts.map +1 -1
  15. package/dist/__tests__/behavior-fixtures-5.test.js +0 -1
  16. package/dist/__tests__/behavior-fixtures-5.test.js.map +1 -1
  17. package/dist/__tests__/behavior-fixtures-6.test.js +10 -0
  18. package/dist/__tests__/behavior-fixtures-6.test.js.map +1 -1
  19. package/dist/__tests__/behavior-fixtures.test.d.ts.map +1 -1
  20. package/dist/__tests__/behavior-fixtures.test.js +2 -4
  21. package/dist/__tests__/behavior-fixtures.test.js.map +1 -1
  22. package/dist/__tests__/branch-fixtures-2.test.d.ts.map +1 -1
  23. package/dist/__tests__/branch-fixtures-2.test.js +0 -1
  24. package/dist/__tests__/branch-fixtures-2.test.js.map +1 -1
  25. package/dist/__tests__/branch-fixtures-3.test.d.ts.map +1 -1
  26. package/dist/__tests__/branch-fixtures-3.test.js +0 -1
  27. package/dist/__tests__/branch-fixtures-3.test.js.map +1 -1
  28. package/dist/__tests__/branch-fixtures.test.d.ts.map +1 -1
  29. package/dist/__tests__/branch-fixtures.test.js +0 -1
  30. package/dist/__tests__/branch-fixtures.test.js.map +1 -1
  31. package/dist/checks/architecture/__tests__/live-view-through-cli-live.test.d.ts +2 -0
  32. package/dist/checks/architecture/__tests__/live-view-through-cli-live.test.d.ts.map +1 -0
  33. package/dist/checks/architecture/__tests__/live-view-through-cli-live.test.js +13 -0
  34. package/dist/checks/architecture/__tests__/live-view-through-cli-live.test.js.map +1 -0
  35. package/dist/checks/architecture/contracts-schema-consistency.d.ts.map +1 -1
  36. package/dist/checks/architecture/contracts-schema-consistency.js +0 -3
  37. package/dist/checks/architecture/contracts-schema-consistency.js.map +1 -1
  38. package/dist/checks/architecture/drizzle-orm-migration-guardrails.d.ts.map +1 -1
  39. package/dist/checks/architecture/drizzle-orm-migration-guardrails.js +1 -0
  40. package/dist/checks/architecture/drizzle-orm-migration-guardrails.js.map +1 -1
  41. package/dist/checks/architecture/index.d.ts +1 -0
  42. package/dist/checks/architecture/index.d.ts.map +1 -1
  43. package/dist/checks/architecture/index.js +1 -0
  44. package/dist/checks/architecture/index.js.map +1 -1
  45. package/dist/checks/architecture/live-view-through-cli-live.d.ts +8 -0
  46. package/dist/checks/architecture/live-view-through-cli-live.d.ts.map +1 -0
  47. package/dist/checks/architecture/live-view-through-cli-live.js +43 -0
  48. package/dist/checks/architecture/live-view-through-cli-live.js.map +1 -0
  49. package/dist/checks/architecture/missing-type-exports.d.ts.map +1 -1
  50. package/dist/checks/architecture/missing-type-exports.js +1 -1
  51. package/dist/checks/architecture/missing-type-exports.js.map +1 -1
  52. package/dist/checks/architecture/module-coupling-fan-out.d.ts.map +1 -1
  53. package/dist/checks/architecture/module-coupling-fan-out.js +6 -2
  54. package/dist/checks/architecture/module-coupling-fan-out.js.map +1 -1
  55. package/dist/checks/architecture/no-bootstrap-tool-import.d.ts.map +1 -1
  56. package/dist/checks/architecture/no-bootstrap-tool-import.js +1 -0
  57. package/dist/checks/architecture/no-bootstrap-tool-import.js.map +1 -1
  58. package/dist/checks/architecture/no-run-done-result.d.ts.map +1 -1
  59. package/dist/checks/architecture/no-run-done-result.js +1 -0
  60. package/dist/checks/architecture/no-run-done-result.js.map +1 -1
  61. package/dist/checks/architecture/package-json-exports-field.d.ts.map +1 -1
  62. package/dist/checks/architecture/package-json-exports-field.js +1 -1
  63. package/dist/checks/architecture/package-json-exports-field.js.map +1 -1
  64. package/dist/checks/architecture/phantom-dependency-detection.d.ts.map +1 -1
  65. package/dist/checks/architecture/phantom-dependency-detection.js +0 -4
  66. package/dist/checks/architecture/phantom-dependency-detection.js.map +1 -1
  67. package/dist/checks/architecture/tsconfig-extends-validation.d.ts.map +1 -1
  68. package/dist/checks/architecture/tsconfig-extends-validation.js +0 -2
  69. package/dist/checks/architecture/tsconfig-extends-validation.js.map +1 -1
  70. package/dist/checks/quality/api/fastify-schema-coverage.d.ts.map +1 -1
  71. package/dist/checks/quality/api/fastify-schema-coverage.js +21 -10
  72. package/dist/checks/quality/api/fastify-schema-coverage.js.map +1 -1
  73. package/dist/checks/quality/code-structure/__tests__/duplicate-utility-lang-substrate.test.d.ts +5 -0
  74. package/dist/checks/quality/code-structure/__tests__/duplicate-utility-lang-substrate.test.d.ts.map +1 -0
  75. package/dist/checks/quality/code-structure/__tests__/duplicate-utility-lang-substrate.test.js +17 -0
  76. package/dist/checks/quality/code-structure/__tests__/duplicate-utility-lang-substrate.test.js.map +1 -0
  77. package/dist/checks/quality/code-structure/duplicate-utility-functions-config.d.ts +18 -0
  78. package/dist/checks/quality/code-structure/duplicate-utility-functions-config.d.ts.map +1 -0
  79. package/dist/checks/quality/code-structure/duplicate-utility-functions-config.js +36 -0
  80. package/dist/checks/quality/code-structure/duplicate-utility-functions-config.js.map +1 -0
  81. package/dist/checks/quality/code-structure/duplicate-utility-functions-helpers.d.ts +15 -0
  82. package/dist/checks/quality/code-structure/duplicate-utility-functions-helpers.d.ts.map +1 -0
  83. package/dist/checks/quality/code-structure/duplicate-utility-functions-helpers.js +288 -0
  84. package/dist/checks/quality/code-structure/duplicate-utility-functions-helpers.js.map +1 -0
  85. package/dist/checks/quality/code-structure/duplicate-utility-functions.d.ts +1 -26
  86. package/dist/checks/quality/code-structure/duplicate-utility-functions.d.ts.map +1 -1
  87. package/dist/checks/quality/code-structure/duplicate-utility-functions.js +3 -407
  88. package/dist/checks/quality/code-structure/duplicate-utility-functions.js.map +1 -1
  89. package/dist/checks/quality/data-integrity/__tests__/null-safety-fp.test.js +39 -2
  90. package/dist/checks/quality/data-integrity/__tests__/null-safety-fp.test.js.map +1 -1
  91. package/dist/checks/quality/data-integrity/array-validation-detectors.d.ts +17 -0
  92. package/dist/checks/quality/data-integrity/array-validation-detectors.d.ts.map +1 -0
  93. package/dist/checks/quality/data-integrity/array-validation-detectors.js +184 -0
  94. package/dist/checks/quality/data-integrity/array-validation-detectors.js.map +1 -0
  95. package/dist/checks/quality/data-integrity/array-validation.d.ts +0 -2
  96. package/dist/checks/quality/data-integrity/array-validation.d.ts.map +1 -1
  97. package/dist/checks/quality/data-integrity/array-validation.js +2 -360
  98. package/dist/checks/quality/data-integrity/array-validation.js.map +1 -1
  99. package/dist/checks/quality/data-integrity/database-schema-validation.d.ts.map +1 -1
  100. package/dist/checks/quality/data-integrity/database-schema-validation.js +0 -1
  101. package/dist/checks/quality/data-integrity/database-schema-validation.js.map +1 -1
  102. package/dist/checks/quality/data-integrity/null-safety-analyze.d.ts +33 -0
  103. package/dist/checks/quality/data-integrity/null-safety-analyze.d.ts.map +1 -0
  104. package/dist/checks/quality/data-integrity/null-safety-analyze.js +164 -0
  105. package/dist/checks/quality/data-integrity/null-safety-analyze.js.map +1 -0
  106. package/dist/checks/quality/data-integrity/null-safety-config.d.ts +50 -0
  107. package/dist/checks/quality/data-integrity/null-safety-config.d.ts.map +1 -0
  108. package/dist/checks/quality/data-integrity/null-safety-config.js +69 -0
  109. package/dist/checks/quality/data-integrity/null-safety-config.js.map +1 -0
  110. package/dist/checks/quality/data-integrity/null-safety-heuristics.d.ts +76 -0
  111. package/dist/checks/quality/data-integrity/null-safety-heuristics.d.ts.map +1 -0
  112. package/dist/checks/quality/data-integrity/null-safety-heuristics.js +276 -0
  113. package/dist/checks/quality/data-integrity/null-safety-heuristics.js.map +1 -0
  114. package/dist/checks/quality/data-integrity/null-safety-prefixes.d.ts +13 -0
  115. package/dist/checks/quality/data-integrity/null-safety-prefixes.d.ts.map +1 -0
  116. package/dist/checks/quality/data-integrity/null-safety-prefixes.js +333 -0
  117. package/dist/checks/quality/data-integrity/null-safety-prefixes.js.map +1 -0
  118. package/dist/checks/quality/data-integrity/null-safety.d.ts +2 -82
  119. package/dist/checks/quality/data-integrity/null-safety.d.ts.map +1 -1
  120. package/dist/checks/quality/data-integrity/null-safety.js +3 -796
  121. package/dist/checks/quality/data-integrity/null-safety.js.map +1 -1
  122. package/dist/checks/quality/frontend/test-only-frontend-modules.d.ts.map +1 -1
  123. package/dist/checks/quality/frontend/test-only-frontend-modules.js +0 -2
  124. package/dist/checks/quality/frontend/test-only-frontend-modules.js.map +1 -1
  125. package/dist/checks/quality/linting/typescript-frontend.d.ts.map +1 -1
  126. package/dist/checks/quality/linting/typescript-frontend.js +1 -0
  127. package/dist/checks/quality/linting/typescript-frontend.js.map +1 -1
  128. package/dist/checks/quality/observability/logger-event-name-format.d.ts.map +1 -1
  129. package/dist/checks/quality/observability/logger-event-name-format.js +0 -1
  130. package/dist/checks/quality/observability/logger-event-name-format.js.map +1 -1
  131. package/dist/checks/quality/observability/no-hardcoded-correlation-id.d.ts.map +1 -1
  132. package/dist/checks/quality/observability/no-hardcoded-correlation-id.js +2 -3
  133. package/dist/checks/quality/observability/no-hardcoded-correlation-id.js.map +1 -1
  134. package/dist/checks/quality/patterns/__tests__/async-waterfall-sequential.test.d.ts +8 -0
  135. package/dist/checks/quality/patterns/__tests__/async-waterfall-sequential.test.d.ts.map +1 -0
  136. package/dist/checks/quality/patterns/__tests__/async-waterfall-sequential.test.js +87 -0
  137. package/dist/checks/quality/patterns/__tests__/async-waterfall-sequential.test.js.map +1 -0
  138. package/dist/checks/quality/patterns/__tests__/error-handling-probes.test.d.ts +2 -0
  139. package/dist/checks/quality/patterns/__tests__/error-handling-probes.test.d.ts.map +1 -0
  140. package/dist/checks/quality/patterns/__tests__/error-handling-probes.test.js +51 -0
  141. package/dist/checks/quality/patterns/__tests__/error-handling-probes.test.js.map +1 -0
  142. package/dist/checks/quality/patterns/__tests__/result-pattern-registration-guards.test.d.ts +2 -0
  143. package/dist/checks/quality/patterns/__tests__/result-pattern-registration-guards.test.d.ts.map +1 -0
  144. package/dist/checks/quality/patterns/__tests__/result-pattern-registration-guards.test.js +89 -0
  145. package/dist/checks/quality/patterns/__tests__/result-pattern-registration-guards.test.js.map +1 -0
  146. package/dist/checks/quality/patterns/__tests__/throws-documentation-analyze.test.d.ts +5 -0
  147. package/dist/checks/quality/patterns/__tests__/throws-documentation-analyze.test.d.ts.map +1 -0
  148. package/dist/checks/quality/patterns/__tests__/throws-documentation-analyze.test.js +78 -0
  149. package/dist/checks/quality/patterns/__tests__/throws-documentation-analyze.test.js.map +1 -0
  150. package/dist/checks/quality/patterns/__tests__/toctou-fp.test.js +44 -0
  151. package/dist/checks/quality/patterns/__tests__/toctou-fp.test.js.map +1 -1
  152. package/dist/checks/quality/patterns/async-waterfall-analysis.d.ts +17 -0
  153. package/dist/checks/quality/patterns/async-waterfall-analysis.d.ts.map +1 -0
  154. package/dist/checks/quality/patterns/async-waterfall-analysis.js +215 -0
  155. package/dist/checks/quality/patterns/async-waterfall-analysis.js.map +1 -0
  156. package/dist/checks/quality/patterns/async-waterfall-branch-keys.d.ts +6 -0
  157. package/dist/checks/quality/patterns/async-waterfall-branch-keys.d.ts.map +1 -0
  158. package/dist/checks/quality/patterns/async-waterfall-branch-keys.js +54 -0
  159. package/dist/checks/quality/patterns/async-waterfall-branch-keys.js.map +1 -0
  160. package/dist/checks/quality/patterns/async-waterfall-detection.d.ts.map +1 -1
  161. package/dist/checks/quality/patterns/async-waterfall-detection.js +3 -352
  162. package/dist/checks/quality/patterns/async-waterfall-detection.js.map +1 -1
  163. package/dist/checks/quality/patterns/containing-function-name.d.ts +3 -0
  164. package/dist/checks/quality/patterns/containing-function-name.d.ts.map +1 -0
  165. package/dist/checks/quality/patterns/containing-function-name.js +21 -0
  166. package/dist/checks/quality/patterns/containing-function-name.js.map +1 -0
  167. package/dist/checks/quality/patterns/error-handling-quality.d.ts +3 -0
  168. package/dist/checks/quality/patterns/error-handling-quality.d.ts.map +1 -1
  169. package/dist/checks/quality/patterns/error-handling-quality.js +150 -30
  170. package/dist/checks/quality/patterns/error-handling-quality.js.map +1 -1
  171. package/dist/checks/quality/patterns/result-pattern-consistency.d.ts +3 -0
  172. package/dist/checks/quality/patterns/result-pattern-consistency.d.ts.map +1 -1
  173. package/dist/checks/quality/patterns/result-pattern-consistency.js +136 -69
  174. package/dist/checks/quality/patterns/result-pattern-consistency.js.map +1 -1
  175. package/dist/checks/quality/patterns/throws-documentation-analyze.d.ts +14 -0
  176. package/dist/checks/quality/patterns/throws-documentation-analyze.d.ts.map +1 -0
  177. package/dist/checks/quality/patterns/throws-documentation-analyze.js +352 -0
  178. package/dist/checks/quality/patterns/throws-documentation-analyze.js.map +1 -0
  179. package/dist/checks/quality/patterns/throws-documentation-constants.d.ts +15 -0
  180. package/dist/checks/quality/patterns/throws-documentation-constants.d.ts.map +1 -0
  181. package/dist/checks/quality/patterns/throws-documentation-constants.js +94 -0
  182. package/dist/checks/quality/patterns/throws-documentation-constants.js.map +1 -0
  183. package/dist/checks/quality/patterns/throws-documentation.d.ts +1 -11
  184. package/dist/checks/quality/patterns/throws-documentation.d.ts.map +1 -1
  185. package/dist/checks/quality/patterns/throws-documentation.js +4 -472
  186. package/dist/checks/quality/patterns/throws-documentation.js.map +1 -1
  187. package/dist/checks/quality/patterns/toctou-race-condition-classify.d.ts +23 -0
  188. package/dist/checks/quality/patterns/toctou-race-condition-classify.d.ts.map +1 -0
  189. package/dist/checks/quality/patterns/toctou-race-condition-classify.js +125 -0
  190. package/dist/checks/quality/patterns/toctou-race-condition-classify.js.map +1 -0
  191. package/dist/checks/quality/patterns/toctou-race-condition-collection.d.ts +24 -0
  192. package/dist/checks/quality/patterns/toctou-race-condition-collection.d.ts.map +1 -0
  193. package/dist/checks/quality/patterns/toctou-race-condition-collection.js +248 -0
  194. package/dist/checks/quality/patterns/toctou-race-condition-collection.js.map +1 -0
  195. package/dist/checks/quality/patterns/toctou-race-condition-constants.d.ts +32 -0
  196. package/dist/checks/quality/patterns/toctou-race-condition-constants.d.ts.map +1 -0
  197. package/dist/checks/quality/patterns/toctou-race-condition-constants.js +116 -0
  198. package/dist/checks/quality/patterns/toctou-race-condition-constants.js.map +1 -0
  199. package/dist/checks/quality/patterns/toctou-race-condition.d.ts +1 -29
  200. package/dist/checks/quality/patterns/toctou-race-condition.d.ts.map +1 -1
  201. package/dist/checks/quality/patterns/toctou-race-condition.js +11 -536
  202. package/dist/checks/quality/patterns/toctou-race-condition.js.map +1 -1
  203. package/dist/checks/quality/unused-config-options.d.ts.map +1 -1
  204. package/dist/checks/quality/unused-config-options.js +1 -4
  205. package/dist/checks/quality/unused-config-options.js.map +1 -1
  206. package/dist/checks/resilience/__tests__/context-mutation.test.js +8 -0
  207. package/dist/checks/resilience/__tests__/context-mutation.test.js.map +1 -1
  208. package/dist/checks/resilience/__tests__/detached-promises-sync-detection.test.d.ts +2 -0
  209. package/dist/checks/resilience/__tests__/detached-promises-sync-detection.test.d.ts.map +1 -0
  210. package/dist/checks/resilience/__tests__/detached-promises-sync-detection.test.js +98 -0
  211. package/dist/checks/resilience/__tests__/detached-promises-sync-detection.test.js.map +1 -0
  212. package/dist/checks/resilience/callback-invocation-safe.d.ts.map +1 -1
  213. package/dist/checks/resilience/callback-invocation-safe.js +0 -1
  214. package/dist/checks/resilience/callback-invocation-safe.js.map +1 -1
  215. package/dist/checks/resilience/context-leakage.d.ts.map +1 -1
  216. package/dist/checks/resilience/context-leakage.js +1 -0
  217. package/dist/checks/resilience/context-leakage.js.map +1 -1
  218. package/dist/checks/resilience/context-mutation.d.ts.map +1 -1
  219. package/dist/checks/resilience/context-mutation.js +30 -4
  220. package/dist/checks/resilience/context-mutation.js.map +1 -1
  221. package/dist/checks/resilience/detached-promises-detection.d.ts +7 -0
  222. package/dist/checks/resilience/detached-promises-detection.d.ts.map +1 -0
  223. package/dist/checks/resilience/detached-promises-detection.js +228 -0
  224. package/dist/checks/resilience/detached-promises-detection.js.map +1 -0
  225. package/dist/checks/resilience/detached-promises-sync-constants.d.ts +36 -0
  226. package/dist/checks/resilience/detached-promises-sync-constants.d.ts.map +1 -0
  227. package/dist/checks/resilience/detached-promises-sync-constants.js +299 -0
  228. package/dist/checks/resilience/detached-promises-sync-constants.js.map +1 -0
  229. package/dist/checks/resilience/detached-promises-sync-detection.d.ts +14 -0
  230. package/dist/checks/resilience/detached-promises-sync-detection.d.ts.map +1 -0
  231. package/dist/checks/resilience/detached-promises-sync-detection.js +69 -0
  232. package/dist/checks/resilience/detached-promises-sync-detection.js.map +1 -0
  233. package/dist/checks/resilience/detached-promises.d.ts +1 -14
  234. package/dist/checks/resilience/detached-promises.d.ts.map +1 -1
  235. package/dist/checks/resilience/detached-promises.js +2 -598
  236. package/dist/checks/resilience/detached-promises.js.map +1 -1
  237. package/dist/checks/resilience/no-raw-fetch.d.ts.map +1 -1
  238. package/dist/checks/resilience/no-raw-fetch.js +1 -0
  239. package/dist/checks/resilience/no-raw-fetch.js.map +1 -1
  240. package/dist/checks/resilience/no-unbounded-concurrency.d.ts.map +1 -1
  241. package/dist/checks/resilience/no-unbounded-concurrency.js +1 -0
  242. package/dist/checks/resilience/no-unbounded-concurrency.js.map +1 -1
  243. package/dist/checks/security/sql-injection.d.ts.map +1 -1
  244. package/dist/checks/security/sql-injection.js +0 -1
  245. package/dist/checks/security/sql-injection.js.map +1 -1
  246. package/dist/display/architecture.d.ts.map +1 -1
  247. package/dist/display/architecture.js +1 -0
  248. package/dist/display/architecture.js.map +1 -1
  249. package/dist/display/types.d.ts.map +1 -1
  250. package/dist/display/types.js +0 -1
  251. package/dist/display/types.js.map +1 -1
  252. package/package.json +5 -5
@@ -1,478 +1,14 @@
1
1
  // @fitness-ignore-file no-generic-error -- Generic errors appropriate in this context
2
- // @fitness-ignore-file file-length-limit -- JSDoc documentation required for public API
3
2
  // @fitness-ignore-file no-hardcoded-timeouts -- framework default for fitness check execution timeout
4
3
  /**
5
4
  * @fileoverview Missing @throws JSDoc Detection Check
6
5
  *
7
6
  * Detects functions that contain throw statements but lack @throws JSDoc documentation.
8
- *
9
7
  */
10
- import { defineCheck, getCheckConfig, isTestFile } from '@opensip-cli/fitness';
8
+ import { defineCheck, isTestFile } from '@opensip-cli/fitness';
11
9
  import { getSharedSourceFile } from '@opensip-cli/lang-typescript';
12
- import * as ts from 'typescript';
13
- // =============================================================================
14
- // HELPER FUNCTIONS
15
- // =============================================================================
16
- /**
17
- * Check if node is a function-like node (function, method, or arrow function)
18
- * @param n - The TypeScript AST node to check
19
- * @returns True if the node is a function declaration, function expression, arrow function, or method declaration
20
- */
21
- function isFunctionLikeNode(n) {
22
- return (ts.isFunctionDeclaration(n) ||
23
- ts.isFunctionExpression(n) ||
24
- ts.isArrowFunction(n) ||
25
- ts.isMethodDeclaration(n));
26
- }
27
- /**
28
- * Find throw statements in a node (not descending into nested functions)
29
- * @param node - The AST node to search for throw statements
30
- * @returns Array of throw statements found in the node (excluding nested functions)
31
- */
32
- function findThrowStatements(node) {
33
- const throws = [];
34
- const visit = (n) => {
35
- // Don't descend into nested functions
36
- if (isFunctionLikeNode(n) && n !== node) {
37
- return;
38
- }
39
- if (ts.isThrowStatement(n)) {
40
- throws.push(n);
41
- }
42
- ts.forEachChild(n, visit);
43
- };
44
- visit(node);
45
- return throws;
46
- }
47
- /**
48
- * Check if a node has @throws JSDoc
49
- * @param node - The AST node to check for @throws documentation
50
- * @param sourceFile - The source file containing the node
51
- * @returns True if the node has a @throws JSDoc comment
52
- */
53
- function hasThrowsJSDoc(node, sourceFile) {
54
- const fullText = sourceFile.getFullText();
55
- const nodeStart = node.getFullStart();
56
- const comments = ts.getLeadingCommentRanges(fullText, nodeStart);
57
- if (!comments)
58
- return false;
59
- for (const comment of comments) {
60
- const commentText = fullText.slice(comment.pos, comment.end);
61
- if (commentText.includes('@throws')) {
62
- return true;
63
- }
64
- }
65
- return false;
66
- }
67
- const ANONYMOUS_FUNCTION_NAME = '<anonymous>';
68
- /**
69
- * Get function name from a function declaration node
70
- * @param node - The function declaration node
71
- * @returns The function name, or "<anonymous>" if unnamed
72
- */
73
- function getNameFromFunctionDeclaration(node) {
74
- return node.name?.text ?? ANONYMOUS_FUNCTION_NAME;
75
- }
76
- /**
77
- * Get function name from a method declaration node
78
- * @param node - The method declaration node
79
- * @returns The method name, or "<anonymous>" if the name is not an identifier
80
- */
81
- function getNameFromMethodDeclaration(node) {
82
- return ts.isIdentifier(node.name) ? node.name.text : ANONYMOUS_FUNCTION_NAME;
83
- }
84
- /**
85
- * Get function name from an arrow function node
86
- * @param node - The arrow function node
87
- * @returns The variable name if assigned to a variable, or "<anonymous>" otherwise
88
- */
89
- function getNameFromArrowFunction(node) {
90
- const parent = node.parent;
91
- if (ts.isVariableDeclaration(parent) && ts.isIdentifier(parent.name)) {
92
- return parent.name.text;
93
- }
94
- return ANONYMOUS_FUNCTION_NAME;
95
- }
96
- /**
97
- * Get the name of a function-like node
98
- * @param node - The function-like node (function declaration, method, or arrow function)
99
- * @returns The function name, or "<anonymous>" if unnamed
100
- */
101
- // @fitness-ignore-next-line duplicate-utility-functions -- Check-specific helper for FunctionLikeNode; each fitness check defines its own variant for its node type
102
- function getFunctionName(node) {
103
- if (ts.isFunctionDeclaration(node)) {
104
- return getNameFromFunctionDeclaration(node);
105
- }
106
- if (ts.isMethodDeclaration(node)) {
107
- return getNameFromMethodDeclaration(node);
108
- }
109
- return getNameFromArrowFunction(node);
110
- }
111
- /**
112
- * Check if an arrow function is an anonymous callback that should be skipped
113
- * @param node - The arrow function node to check
114
- * @returns True if the arrow function is used as a callback in a call expression
115
- */
116
- function isAnonymousCallback(node) {
117
- const parent = node.parent;
118
- return ts.isCallExpression(parent) || ts.isCallExpression(parent.parent);
119
- }
120
- /**
121
- * Typed error classes (e.g., from a project error module).
122
- * These are self-documenting and don't require @throws JSDoc.
123
- */
124
- const SELF_DOCUMENTING_ERRORS = new Set([
125
- // Domain errors
126
- 'ValidationError',
127
- 'AuthorizationError',
128
- 'NotFoundError',
129
- 'ConflictError',
130
- 'DomainError',
131
- // System errors
132
- 'SystemError',
133
- 'ConfigurationError',
134
- 'InfrastructureError',
135
- 'ExternalServiceError',
136
- 'DatabaseError',
137
- 'CacheError',
138
- 'NetworkError',
139
- // Application errors
140
- 'ApplicationError',
141
- 'OperationError',
142
- 'StateError',
143
- 'IntegrationError',
144
- // HTTP errors
145
- 'BadRequestError',
146
- 'UnauthorizedError',
147
- 'ForbiddenError',
148
- 'MethodNotAllowedError',
149
- 'NotAcceptableError',
150
- 'RequestTimeoutError',
151
- 'GoneError',
152
- 'PayloadTooLargeError',
153
- 'UnsupportedMediaTypeError',
154
- 'UnprocessableEntityError',
155
- 'TooManyRequestsError',
156
- 'InternalServerError',
157
- 'NotImplementedError',
158
- 'BadGatewayError',
159
- 'ServiceUnavailableError',
160
- 'GatewayTimeoutError',
161
- // Common error aliases
162
- 'InputValidationError',
163
- 'BusinessRuleError',
164
- 'AuthenticationError',
165
- 'PermissionError',
166
- 'ResourceNotFoundError',
167
- 'DuplicateResourceError',
168
- 'DataIntegrityError',
169
- ]);
170
- /**
171
- * Suffixes that indicate a self-documenting error type.
172
- * These typed error classes are descriptive enough that @throws JSDoc adds little value.
173
- *
174
- * The list is intentionally broad: any class name ending in a recognizable error
175
- * suffix counts as self-documenting because it carries its semantic meaning in the
176
- * type name itself (callers can read and handle the typed error directly without
177
- * needing prose).
178
- */
179
- const SELF_DOCUMENTING_SUFFIXES = [
180
- 'ValidationError',
181
- 'NotFoundError',
182
- 'AuthorizationError',
183
- 'SystemError',
184
- 'DomainError',
185
- 'ConfigurationError',
186
- 'SecurityError',
187
- 'TimeoutError',
188
- 'LockError',
189
- 'LimitError',
190
- 'InfrastructureError',
191
- 'ApplicationError',
192
- 'OperationError',
193
- 'ErrorBuilder', // Builder pattern for typed errors
194
- // Generic-sounding suffixes any project may use:
195
- 'NetworkError',
196
- 'ExecutionError',
197
- 'LoadError',
198
- 'VerifyError',
199
- 'ApiError',
200
- 'ParseError',
201
- 'EncodingError',
202
- 'DecodingError',
203
- 'StateError',
204
- 'SyncError',
205
- 'CaptureError',
206
- 'IntegrationError',
207
- 'PermissionError',
208
- 'AccessError',
209
- 'AuthenticationError',
210
- 'ResourceNotFoundError',
211
- 'DuplicateResourceError',
212
- 'DataIntegrityError',
213
- 'BusinessRuleError',
214
- 'InputValidationError',
215
- // NOTE: opensip-specific suffixes — `CompositionError`, `CompositeError`,
216
- // `CanonicalizationError`, `TransformError`, `VersioningError`,
217
- // `TransitionError` — are NOT defaults. They live in opensip's recipe
218
- // under `checks.config['throws-documentation'].additionalSelfDocumentingSuffixes`.
219
- ];
220
- /**
221
- * Build the effective self-documenting suffix list by merging built-in
222
- * defaults with the recipe config slice. Called per-file from the analyze entry.
223
- */
224
- function buildEffectiveSuffixes() {
225
- const cfg = getCheckConfig('throws-documentation');
226
- return [...SELF_DOCUMENTING_SUFFIXES, ...(cfg.additionalSelfDocumentingSuffixes ?? [])];
227
- }
228
- function isSelfDocumentingError(errorType, suffixes) {
229
- // Check exact match
230
- if (SELF_DOCUMENTING_ERRORS.has(errorType)) {
231
- return true;
232
- }
233
- // Check if it ends with known self-documenting patterns
234
- return suffixes.some((suffix) => errorType.endsWith(suffix));
235
- }
236
- /**
237
- * Extract thrown error type from a throw statement
238
- * @param throwStmt - The throw statement to analyze
239
- * @param sourceFile - The source file containing the throw statement
240
- * @returns The error class name (e.g., "TypeError"), or "Error" if not determinable
241
- */
242
- function extractThrownType(throwStmt, sourceFile) {
243
- const text = throwStmt.expression.getText(sourceFile);
244
- // @fitness-ignore-next-line sonarjs-backend -- Safe regex with fixed tokens for extracting error class name
245
- const typeMatch = /new\s+(\w+)/.exec(text);
246
- return typeMatch?.[1] ?? 'Error';
247
- }
248
- /**
249
- * Get unique thrown error types from throw statements
250
- * @param throwStatements - Array of throw statements to analyze
251
- * @param sourceFile - The source file containing the throw statements
252
- * @returns Array of unique error type names found in the throw statements
253
- */
254
- function getUniqueThrowTypes(throwStatements, sourceFile) {
255
- if (!Array.isArray(throwStatements)) {
256
- return [];
257
- }
258
- const thrownTypes = throwStatements.map((t) => extractThrownType(t, sourceFile));
259
- return [...new Set(thrownTypes)];
260
- }
261
- /**
262
- * Create a violation for a function missing @throws documentation
263
- * @param node - The function-like node that is missing @throws documentation
264
- * @param funcName - The name of the function
265
- * @param throwStatements - The throw statements found in the function
266
- * @param ctx - The file analysis context
267
- * @returns A violation object describing the missing @throws documentation
268
- * @throws {Error} If throwStatements is not an array
269
- */
270
- function createMissingThrowsViolation(node, funcName, throwStatements, ctx) {
271
- if (!Array.isArray(throwStatements)) {
272
- throw new TypeError('throwStatements must be an array');
273
- }
274
- const { line, character } = ctx.sourceFile.getLineAndCharacterOfPosition(node.getStart());
275
- const lineNum = line + 1;
276
- const uniqueTypes = getUniqueThrowTypes(throwStatements, ctx.sourceFile);
277
- return {
278
- line: lineNum,
279
- column: character + 1,
280
- message: `Function '${funcName}' throws but lacks @throws JSDoc`,
281
- severity: 'warning',
282
- suggestion: `Add @throws JSDoc above the function: /** @throws {${uniqueTypes.join(' | ')}} Description of when this error is thrown */`,
283
- match: funcName,
284
- };
285
- }
286
- /**
287
- * Check if a function-like node should be analyzed
288
- * @param node - The function-like node to check
289
- * @param funcName - The name of the function
290
- * @returns True if the function should be analyzed for @throws documentation
291
- */
292
- function shouldAnalyzeFunction(node, funcName) {
293
- // Skip anonymous arrow function callbacks
294
- if (funcName === '<anonymous>' && ts.isArrowFunction(node)) {
295
- return !isAnonymousCallback(node);
296
- }
297
- return true;
298
- }
299
- /**
300
- * Check if all throw statements in a function use self-documenting errors
301
- * @param throwStatements - Array of throw statements to check
302
- * @param sourceFile - The source file containing the throw statements
303
- * @returns True if all thrown errors are self-documenting
304
- */
305
- function allThrowsSelfDocumenting(throwStatements, sourceFile, suffixes) {
306
- if (!Array.isArray(throwStatements) || throwStatements.length === 0) {
307
- return false;
308
- }
309
- return throwStatements.every((stmt) => {
310
- const errorType = extractThrownType(stmt, sourceFile);
311
- return isSelfDocumentingError(errorType, suffixes);
312
- });
313
- }
314
- /**
315
- * Common error-field name patterns on `this` that indicate a stored-error rethrow.
316
- * Used to recognise patterns like `throw this.error` (Result-pattern Failure rethrow).
317
- */
318
- const ERROR_FIELD_NAME_PATTERN = /^(error|err|cause|innerError|originalError)$/i;
319
- /**
320
- * Generic error-variable name patterns (caught-error identifiers).
321
- * Used as a fallback when we cannot statically determine the enclosing catch clause
322
- * (e.g. when isRethrow is called without a function context).
323
- */
324
- const ERROR_VAR_NAME_PATTERN = /^(error|err|e|ex|exception)$/i;
325
- /**
326
- * Collect identifier names introduced by `catch (X)` clauses anywhere inside the
327
- * given function-like node (excluding nested function bodies). These names are the
328
- * caught-error variables that a subsequent `throw <name>` or `throw <name>.<...>`
329
- * is treated as a re-throw of.
330
- *
331
- * @param fnNode - The enclosing function-like node
332
- * @returns Set of caught-error variable names
333
- */
334
- function collectCaughtErrorNames(fnNode) {
335
- const names = new Set();
336
- const visit = (n) => {
337
- // Don't descend into nested function bodies — their catch variables are
338
- // out of scope at the throw site we care about.
339
- if (isFunctionLikeNode(n) && n !== fnNode) {
340
- return;
341
- }
342
- if (ts.isCatchClause(n) && n.variableDeclaration) {
343
- const decl = n.variableDeclaration;
344
- if (ts.isIdentifier(decl.name)) {
345
- names.add(decl.name.text);
346
- }
347
- }
348
- ts.forEachChild(n, visit);
349
- };
350
- visit(fnNode);
351
- return names;
352
- }
353
- /**
354
- * Check if a throw statement is a re-throw of a caught error.
355
- *
356
- * Recognised re-throw shapes:
357
- * - `throw err` — bare caught-error identifier
358
- * - `throw err.unwrapErr()` — typed Result rethrow
359
- * - `throw this.error` — Result-pattern Failure stored-error rethrow
360
- * - `throw sanitizedError(err)` — single-arg helper wrapping a caught error
361
- *
362
- * @param throwStmt - The throw statement to check
363
- * @param sourceFile - The source file containing the throw statement
364
- * @param caughtNames - Names of caught-error variables in the enclosing function
365
- * @returns True if this throw statement re-throws (rather than freshly creates) an error
366
- */
367
- // eslint-disable-next-line sonarjs/cognitive-complexity -- rethrow heuristic: enumerates the AST shapes that count as rethrowing (caught var, wrapping cause, scoped helpers); flatter shape would obscure the matching logic
368
- function isRethrow(throwStmt, sourceFile, caughtNames) {
369
- const expr = throwStmt.expression;
370
- const text = expr.getText(sourceFile).trim();
371
- // `new X(...)` is never a re-throw.
372
- if (ts.isNewExpression(expr))
373
- return false;
374
- // `throw err` — bare identifier
375
- if (ts.isIdentifier(expr)) {
376
- if (caughtNames?.has(expr.text))
377
- return true;
378
- // Fallback: name matches a generic caught-error pattern (used when no context).
379
- return ERROR_VAR_NAME_PATTERN.test(expr.text);
380
- }
381
- // `throw this.error` / `throw this.cause` — stored-error field rethrow
382
- if (ts.isPropertyAccessExpression(expr) &&
383
- expr.expression.kind === ts.SyntaxKind.ThisKeyword &&
384
- ts.isIdentifier(expr.name) &&
385
- ERROR_FIELD_NAME_PATTERN.test(expr.name.text)) {
386
- return true;
387
- }
388
- // Result-pattern rethrows: `throw X.unwrapErr()` / `throw X.unwrap()` —
389
- // the throw extracts an already-typed error from a Result and propagates it.
390
- // We treat this as a rethrow regardless of whether X is in scope as a caught
391
- // variable, because the wrapped error is itself a typed error from elsewhere.
392
- if (ts.isCallExpression(expr) && ts.isPropertyAccessExpression(expr.expression)) {
393
- const methodName = ts.isIdentifier(expr.expression.name) ? expr.expression.name.text : '';
394
- if (methodName === 'unwrapErr' || methodName === 'unwrap') {
395
- return true;
396
- }
397
- // Method invocation on a caught-error variable — also a rethrow.
398
- const root = expr.expression.expression;
399
- if (ts.isIdentifier(root) && caughtNames?.has(root.text)) {
400
- return true;
401
- }
402
- }
403
- // `throw sanitizedError(err)` — single-arg call wrapping a caught-error variable.
404
- // Heuristic: the call has exactly one argument and that argument is an identifier
405
- // matching a caught-error name (preferred) or the generic err/error pattern.
406
- if (ts.isCallExpression(expr) && expr.arguments.length === 1) {
407
- const arg = expr.arguments[0];
408
- if (arg && ts.isIdentifier(arg)) {
409
- if (caughtNames?.has(arg.text))
410
- return true;
411
- if (!caughtNames && ERROR_VAR_NAME_PATTERN.test(arg.text))
412
- return true;
413
- }
414
- }
415
- // Legacy fallback: bare-identifier-shaped text without 'new'. Kept for backward
416
- // compatibility with call sites that don't pass the AST node.
417
- return !text.includes('new ') && ERROR_VAR_NAME_PATTERN.test(text);
418
- }
419
- /**
420
- * Analyze a function-like node for missing @throws documentation
421
- * @param node - The function-like node to analyze
422
- * @param ctx - The file analysis context
423
- * @returns A violation if the function is missing @throws documentation, or null if compliant
424
- */
425
- function analyzeFunctionNode(node, ctx) {
426
- const funcName = getFunctionName(node);
427
- if (!shouldAnalyzeFunction(node, funcName)) {
428
- return null;
429
- }
430
- const throwStatements = findThrowStatements(node);
431
- if (throwStatements.length === 0) {
432
- return null;
433
- }
434
- // Skip if already has @throws documentation
435
- if (hasThrowsJSDoc(node, ctx.sourceFile)) {
436
- return null;
437
- }
438
- // Skip if all throws are self-documenting typed errors
439
- if (allThrowsSelfDocumenting(throwStatements, ctx.sourceFile, ctx.selfDocumentingSuffixes)) {
440
- return null;
441
- }
442
- // Skip if all throws are re-throws (error propagation). We pass the set of
443
- // caught-error variable names declared in any `catch (X)` clause inside the
444
- // function so that `throw err`, `throw err.unwrapErr()`, and
445
- // `throw sanitizedError(err)` are recognised as rethrows.
446
- const caughtNames = collectCaughtErrorNames(node);
447
- if (throwStatements.every((stmt) => isRethrow(stmt, ctx.sourceFile, caughtNames))) {
448
- return null;
449
- }
450
- return createMissingThrowsViolation(node, funcName, throwStatements, ctx);
451
- }
452
- /**
453
- * Analyze a file for missing @throws documentation
454
- * @param ctx - The file analysis context containing source file and metadata
455
- * @returns Array of violations for functions missing @throws documentation
456
- */
457
- function analyzeFile(ctx) {
458
- const violations = [];
459
- const visit = (node) => {
460
- if (ts.isFunctionDeclaration(node) ||
461
- ts.isMethodDeclaration(node) ||
462
- ts.isArrowFunction(node)) {
463
- const violation = analyzeFunctionNode(node, ctx);
464
- if (violation) {
465
- violations.push(violation);
466
- }
467
- }
468
- ts.forEachChild(node, visit);
469
- };
470
- visit(ctx.sourceFile);
471
- return violations;
472
- }
473
- // =============================================================================
474
- // CHECK DEFINITION
475
- // =============================================================================
10
+ import { analyzeFile } from './throws-documentation-analyze.js';
11
+ import { buildEffectiveSuffixes } from './throws-documentation-constants.js';
476
12
  /**
477
13
  * Check: quality/throws-documentation
478
14
  *
@@ -494,14 +30,10 @@ export const throwsDocumentation = defineCheck({
494
30
  **Scope:** Codebase-specific convention enforcing error handling standards`,
495
31
  tags: ['quality', 'documentation', 'best-practices'],
496
32
  fileTypes: ['ts'],
497
- timeout: 180_000, // 3 minutes - parses TypeScript AST for all backend files
33
+ timeout: 180_000,
498
34
  analyze(content, filePath) {
499
- // Skip test files — assertion failures, anonymous test callbacks, and
500
- // fixture helpers are not public-API surface. Matches the convention in
501
- // `null-safety`. Public-API throws are documented in non-test code.
502
35
  if (isTestFile(filePath))
503
36
  return [];
504
- // Quick filter
505
37
  if (!content.includes('throw ')) {
506
38
  return [];
507
39
  }
@@ -1 +1 @@
1
- {"version":3,"file":"throws-documentation.js","sourceRoot":"","sources":["../../../../src/checks/quality/patterns/throws-documentation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"throws-documentation.js","sourceRoot":"","sources":["../../../../src/checks/quality/patterns/throws-documentation.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,sGAAsG;AACtG;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnE,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAE7E;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,WAAW,CAAC;IAC7C,EAAE,EAAE,sCAAsC;IAC1C,IAAI,EAAE,sBAAsB;IAC5B,KAAK,EAAE,EAAE,SAAS,EAAE,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,CAAC,EAAE;IAC9E,aAAa,EAAE,eAAe;IAE9B,UAAU,EAAE,MAAM;IAClB,WAAW,EAAE,8DAA8D;IAC3E,eAAe,EAAE;;;;;;2EAMwD;IACzE,IAAI,EAAE,CAAC,SAAS,EAAE,eAAe,EAAE,gBAAgB,CAAC;IACpD,SAAS,EAAE,CAAC,IAAI,CAAC;IACjB,OAAO,EAAE,OAAO;IAEhB,OAAO,CAAC,OAAO,EAAE,QAAQ;QACvB,IAAI,UAAU,CAAC,QAAQ,CAAC;YAAE,OAAO,EAAE,CAAC;QAEpC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChC,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,UAAU,GAAG,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC1D,IAAI,CAAC,UAAU;YAAE,OAAO,EAAE,CAAC;QAE3B,OAAO,WAAW,CAAC;YACjB,UAAU;YACV,OAAO;YACP,QAAQ;YACR,uBAAuB,EAAE,sBAAsB,EAAE;SAClD,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Call-site classification for the TOCTOU race-condition check.
3
+ */
4
+ import { type FunctionLikeNode } from './toctou-race-condition-collection.js';
5
+ import { KIND_READ_LOCAL, KIND_READ_SHARED, KIND_UPDATE_LOCAL, KIND_UPDATE_SHARED } from './toctou-race-condition-constants.js';
6
+ /** Classification of a `<receiver>.<method>(...)` call site. */
7
+ export type CallKind = {
8
+ kind: typeof KIND_READ_SHARED;
9
+ } | {
10
+ kind: typeof KIND_UPDATE_SHARED;
11
+ } | {
12
+ kind: typeof KIND_READ_LOCAL;
13
+ } | {
14
+ kind: typeof KIND_UPDATE_LOCAL;
15
+ } | {
16
+ kind: 'atomic-sql-write';
17
+ } | {
18
+ kind: 'unrelated';
19
+ };
20
+ export declare function classifyFunctionCalls(node: FunctionLikeNode, localCollections: Set<string>, classCacheFields: Set<string>, localObjectCollectionKeys: Set<string>): {
21
+ hasSharedReadAndUpdateOnSameReceiver: boolean;
22
+ };
23
+ //# sourceMappingURL=toctou-race-condition-classify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toctou-race-condition-classify.d.ts","sourceRoot":"","sources":["../../../../src/checks/quality/patterns/toctou-race-condition-classify.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAIL,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,sCAAsC,CAAC;AAE9C,gEAAgE;AAChE,MAAM,MAAM,QAAQ,GAChB;IAAE,IAAI,EAAE,OAAO,gBAAgB,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,OAAO,kBAAkB,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,OAAO,eAAe,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,OAAO,iBAAiB,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,kBAAkB,CAAA;CAAE,GAC5B;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC;AAqF1B,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,gBAAgB,EACtB,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,EAC7B,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,EAC7B,yBAAyB,EAAE,GAAG,CAAC,MAAM,CAAC,GACrC;IAAE,oCAAoC,EAAE,OAAO,CAAA;CAAE,CAwCnD"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Call-site classification for the TOCTOU race-condition check.
3
+ */
4
+ import * as ts from 'typescript';
5
+ import { getReceiverChainText, isFunctionLikeNode, isInMemoryCacheReceiverText, } from './toctou-race-condition-collection.js';
6
+ import { isDrizzleAtomicWriteMethod, isReadMethod, isUpdateMethod, KIND_READ_LOCAL, KIND_READ_SHARED, KIND_UPDATE_LOCAL, KIND_UPDATE_SHARED, } from './toctou-race-condition-constants.js';
7
+ function isAtomicSqlExecute(call) {
8
+ if (!ts.isPropertyAccessExpression(call.expression))
9
+ return false;
10
+ if (call.expression.name.text !== 'execute')
11
+ return false;
12
+ const arg = call.arguments[0];
13
+ if (!arg)
14
+ return false;
15
+ if (ts.isTaggedTemplateExpression(arg) && ts.isIdentifier(arg.tag) && arg.tag.text === 'sql')
16
+ return true;
17
+ return false;
18
+ }
19
+ function isDrizzleAtomicWrite(call) {
20
+ if (!ts.isPropertyAccessExpression(call.expression))
21
+ return false;
22
+ const methodName = call.expression.name.text;
23
+ if (!isDrizzleAtomicWriteMethod(methodName))
24
+ return false;
25
+ const receiver = call.expression.expression;
26
+ if (ts.isIdentifier(receiver)) {
27
+ const r = receiver.text;
28
+ if (r === 'db' || r === 'tx' || /Db$|Tx$/.test(r))
29
+ return true;
30
+ }
31
+ return false;
32
+ }
33
+ function getReceiverName(call) {
34
+ if (!ts.isPropertyAccessExpression(call.expression))
35
+ return null;
36
+ const receiver = call.expression.expression;
37
+ if (receiver.kind === ts.SyntaxKind.ThisKeyword) {
38
+ return { name: call.expression.name.text, isThisField: true };
39
+ }
40
+ const chain = getReceiverChainText(receiver);
41
+ if (!chain)
42
+ return null;
43
+ if (chain.startsWith('this.')) {
44
+ return { name: chain.slice('this.'.length), isThisField: true };
45
+ }
46
+ return { name: chain, isThisField: false };
47
+ }
48
+ function isLocalReceiver(receiver, ctx) {
49
+ if (receiver.isThisField) {
50
+ return ctx.classCacheFields.has(receiver.name) || isInMemoryCacheReceiverText(receiver.name);
51
+ }
52
+ return (ctx.localCollections.has(receiver.name) ||
53
+ ctx.localObjectCollectionKeys.has(receiver.name) ||
54
+ isInMemoryCacheReceiverText(receiver.name));
55
+ }
56
+ function classifyCall(call, ctx) {
57
+ if (isAtomicSqlExecute(call))
58
+ return { kind: 'atomic-sql-write' };
59
+ if (isDrizzleAtomicWrite(call))
60
+ return { kind: 'atomic-sql-write' };
61
+ if (!ts.isPropertyAccessExpression(call.expression))
62
+ return { kind: 'unrelated' };
63
+ const methodName = call.expression.name.text;
64
+ const isRead = isReadMethod(methodName);
65
+ const isUpdate = isUpdateMethod(methodName);
66
+ if (!isRead && !isUpdate)
67
+ return { kind: 'unrelated' };
68
+ const receiver = getReceiverName(call);
69
+ if (!receiver) {
70
+ return { kind: isRead ? KIND_READ_SHARED : KIND_UPDATE_SHARED };
71
+ }
72
+ if (isLocalReceiver(receiver, ctx)) {
73
+ return { kind: isRead ? KIND_READ_LOCAL : KIND_UPDATE_LOCAL };
74
+ }
75
+ return { kind: isRead ? KIND_READ_SHARED : KIND_UPDATE_SHARED };
76
+ }
77
+ /* eslint-disable sonarjs/cognitive-complexity -- TOCTOU classifier AST visitor */
78
+ export function classifyFunctionCalls(node, localCollections, classCacheFields, localObjectCollectionKeys) {
79
+ const ctx = { localCollections, classCacheFields, localObjectCollectionKeys };
80
+ const perReceiver = new Map();
81
+ let hasReadOnUnknownReceiver = false;
82
+ let hasUpdateOnUnknownReceiver = false;
83
+ const visit = (n) => {
84
+ if (n !== node && isFunctionLikeNode(n))
85
+ return;
86
+ if (ts.isCallExpression(n)) {
87
+ const cls = classifyCall(n, ctx);
88
+ if (cls.kind === 'read-shared' || cls.kind === 'update-shared') {
89
+ const recv = getReceiverName(n);
90
+ if (recv) {
91
+ const key = recv.isThisField ? `this.${recv.name}` : recv.name;
92
+ let entry = perReceiver.get(key);
93
+ if (!entry) {
94
+ entry = { read: false, update: false };
95
+ perReceiver.set(key, entry);
96
+ }
97
+ if (cls.kind === 'read-shared')
98
+ entry.read = true;
99
+ else
100
+ entry.update = true;
101
+ }
102
+ else {
103
+ if (cls.kind === 'read-shared')
104
+ hasReadOnUnknownReceiver = true;
105
+ else
106
+ hasUpdateOnUnknownReceiver = true;
107
+ }
108
+ }
109
+ }
110
+ ts.forEachChild(n, visit);
111
+ };
112
+ if (node.body)
113
+ visit(node.body);
114
+ for (const entry of perReceiver.values()) {
115
+ if (entry.read && entry.update) {
116
+ return { hasSharedReadAndUpdateOnSameReceiver: true };
117
+ }
118
+ }
119
+ if (hasReadOnUnknownReceiver && hasUpdateOnUnknownReceiver) {
120
+ return { hasSharedReadAndUpdateOnSameReceiver: true };
121
+ }
122
+ return { hasSharedReadAndUpdateOnSameReceiver: false };
123
+ }
124
+ /* eslint-enable sonarjs/cognitive-complexity */
125
+ //# sourceMappingURL=toctou-race-condition-classify.js.map