@cplieger/deadset-ts 8.0.0-dev.2 → 8.0.0-dev.21

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 (431) hide show
  1. package/README.md +3 -1
  2. package/THIRD_PARTY_NOTICES.md +27 -0
  3. package/dist/bin/mapper-connection.js +2 -1
  4. package/dist/bin/node-host.js +24 -5
  5. package/dist/src/alias-chain.js +35 -9
  6. package/dist/src/amd.js +81 -0
  7. package/dist/src/analysis.js +274 -496
  8. package/dist/src/augmentations.js +64 -3
  9. package/dist/src/automatic-types.js +10 -29
  10. package/dist/src/bindings.js +382 -0
  11. package/dist/src/commands/held.js +499 -0
  12. package/dist/src/commands/read.js +161 -0
  13. package/dist/src/commands/shell.js +169 -0
  14. package/dist/src/commands/tools.js +1847 -0
  15. package/dist/src/component-files.js +3 -2
  16. package/dist/src/component-layer.js +4 -2
  17. package/dist/src/config.js +6 -82
  18. package/dist/src/conformance-record.js +2 -2
  19. package/dist/src/consumers.js +10 -38
  20. package/dist/src/contextual-uses.js +57 -26
  21. package/dist/src/contract/config.generated.js +561 -0
  22. package/dist/src/contract/contract.generated.js +1370 -0
  23. package/dist/src/contract/report.generated.js +866 -0
  24. package/dist/src/dependencies.js +165 -122
  25. package/dist/src/destructuring.js +1 -19
  26. package/dist/src/edges.js +38 -122
  27. package/dist/src/element-access.js +181 -168
  28. package/dist/src/entries/build-scripts.js +222 -0
  29. package/dist/src/{configuration-files.js → entries/configuration-files.js} +52 -256
  30. package/dist/src/{convention-rows.js → entries/convention-rows.js} +170 -30
  31. package/dist/src/entries/conventions.js +740 -0
  32. package/dist/src/{html-entries.js → entries/html-entries.js} +12 -42
  33. package/dist/src/{mdx-entries.js → entries/mdx-entries.js} +5 -28
  34. package/dist/src/entries/run-directories.js +77 -0
  35. package/dist/src/entries/sources.js +144 -0
  36. package/dist/src/entries/static-module.js +670 -0
  37. package/dist/src/entries/test-runners.js +650 -0
  38. package/dist/src/entries/workflow-steps.js +345 -0
  39. package/dist/src/exemptions/argument-places.js +131 -0
  40. package/dist/src/exemptions/calls.js +338 -0
  41. package/dist/src/exemptions/classes.js +13 -0
  42. package/dist/src/{decorator.js → exemptions/decorator.js} +19 -30
  43. package/dist/src/exemptions/detectors.js +48 -0
  44. package/dist/src/{enum-group.js → exemptions/enum-group.js} +9 -16
  45. package/dist/src/{erased-stores.js → exemptions/erased-stores.js} +7 -11
  46. package/dist/src/{framework-lifecycle.js → exemptions/framework-lifecycle.js} +76 -54
  47. package/dist/src/exemptions/generated-file.js +241 -0
  48. package/dist/src/{injection-container.js → exemptions/injection-container.js} +20 -26
  49. package/dist/src/exemptions/installed-globals.js +173 -0
  50. package/dist/src/{interface-satisfaction.js → exemptions/interface-satisfaction.js} +52 -121
  51. package/dist/src/exemptions/lifecycle.js +150 -0
  52. package/dist/src/{reflective-lookup.js → exemptions/reflective-lookup.js} +3 -3
  53. package/dist/src/exemptions/serialization-contract.js +1276 -0
  54. package/dist/src/exemptions/sites.js +182 -0
  55. package/dist/src/{template-field.js → exemptions/template-field.js} +13 -23
  56. package/dist/src/{value-reach.js → exemptions/value-reach.js} +14 -7
  57. package/dist/src/exposure.js +400 -0
  58. package/dist/src/extensions.js +37 -0
  59. package/dist/src/facts.js +38 -0
  60. package/dist/src/failure.js +36 -0
  61. package/dist/src/file-facts.js +3 -26
  62. package/dist/src/findings/completion.js +109 -56
  63. package/dist/src/findings/dependencies-and-module-machinery.js +4 -5
  64. package/dist/src/findings/emitters.js +27 -41
  65. package/dist/src/{implementations.js → findings/implementations.js} +3 -3
  66. package/dist/src/{in-operands.js → findings/in-operands.js} +3 -2
  67. package/dist/src/findings/interfaces.js +4 -5
  68. package/dist/src/findings/intra-function.js +16 -13
  69. package/dist/src/findings/non-code-artifacts.js +17 -12
  70. package/dist/src/findings/reads-and-writes.js +86 -27
  71. package/dist/src/findings/self-check.js +44 -30
  72. package/dist/src/findings/unused-declarations.js +29 -45
  73. package/dist/src/findings/visibility-narrowing.js +23 -31
  74. package/dist/src/findings-pass.js +13 -21
  75. package/dist/src/fs/document.js +52 -0
  76. package/dist/src/fs/manifest.js +67 -0
  77. package/dist/src/fs/tree.js +88 -0
  78. package/dist/src/git-ignore.js +39 -26
  79. package/dist/src/import-bindings.js +73 -28
  80. package/dist/src/index/sites.js +557 -0
  81. package/dist/src/index/values.js +124 -0
  82. package/dist/src/index.js +2 -2
  83. package/dist/src/indexed-access.js +523 -478
  84. package/dist/src/intra-function-parts.js +63 -43
  85. package/dist/src/inventory/commonjs.js +507 -0
  86. package/dist/src/inventory/enumerate.js +167 -0
  87. package/dist/src/inventory/syntax.js +236 -0
  88. package/dist/src/inventory.js +323 -724
  89. package/dist/src/javascript-file.js +48 -0
  90. package/dist/src/json-document.js +198 -67
  91. package/dist/src/keyof-comparisons.js +126 -107
  92. package/dist/src/kinds.js +3 -366
  93. package/dist/src/{components.js → liveness/components.js} +2 -3
  94. package/dist/src/{graph.js → liveness/graph.js} +52 -28
  95. package/dist/src/liveness/matrix.js +99 -0
  96. package/dist/src/liveness/sweep.js +558 -0
  97. package/dist/src/load/classify.js +289 -0
  98. package/dist/src/load/diagnostics.js +87 -0
  99. package/dist/src/load/discover.js +285 -0
  100. package/dist/src/{emit-map.js → load/emit-map.js} +1 -1
  101. package/dist/src/load/expected-module.js +136 -0
  102. package/dist/src/load/load.js +27 -0
  103. package/dist/src/load/module-lookup.js +37 -0
  104. package/dist/src/load/package-scope.js +56 -0
  105. package/dist/src/load/plan.js +313 -0
  106. package/dist/src/load/specifiers.js +113 -0
  107. package/dist/src/load/synthesize.js +152 -0
  108. package/dist/src/load/test-globals.js +207 -0
  109. package/dist/src/load/test-joins.js +82 -0
  110. package/dist/src/{workspace-manifests.js → load/workspace-manifests.js} +4 -4
  111. package/dist/src/{workspace-programs.js → load/workspace-programs.js} +89 -66
  112. package/dist/src/{workspace-resolution.js → load/workspace-resolution.js} +24 -66
  113. package/dist/src/{workspace-run.js → load/workspace-run.js} +7 -7
  114. package/dist/src/{workspace.js → load/workspace.js} +62 -124
  115. package/dist/src/module-declarations.js +70 -85
  116. package/dist/src/overrides.js +134 -112
  117. package/dist/src/partial.js +2 -1
  118. package/dist/src/paths.js +82 -16
  119. package/dist/src/platform-calls.js +78 -0
  120. package/dist/src/platform-symbols.js +134 -0
  121. package/dist/src/position.js +43 -1
  122. package/dist/src/print.js +11 -79
  123. package/dist/src/product.js +13 -0
  124. package/dist/src/query.js +95 -0
  125. package/dist/src/ref.js +12 -20
  126. package/dist/src/references/read-rule.js +1 -0
  127. package/dist/src/references/read-rules.js +48 -0
  128. package/dist/src/references/sink.js +237 -0
  129. package/dist/src/references/sources.js +450 -0
  130. package/dist/src/references.js +117 -1074
  131. package/dist/src/report-schema.js +51 -0
  132. package/dist/src/report.js +57 -41
  133. package/dist/src/reporters/annotations.js +15 -8
  134. package/dist/src/reporters/sarif.js +16 -10
  135. package/dist/src/reporters/template.js +4 -19
  136. package/dist/src/resolve.js +246 -730
  137. package/dist/src/{configured-declarations.js → roots/configured-declarations.js} +22 -24
  138. package/dist/src/{entry-point-gaps.js → roots/entry-point-gaps.js} +6 -15
  139. package/dist/src/roots/manifest.js +216 -0
  140. package/dist/src/roots/published-reach.js +412 -0
  141. package/dist/src/roots/root-set.js +487 -0
  142. package/dist/src/roots/unseen-loads.js +236 -0
  143. package/dist/src/run.js +66 -77
  144. package/dist/src/schema.js +320 -343
  145. package/dist/src/scope.js +38 -115
  146. package/dist/src/session.js +37 -29
  147. package/dist/src/source-files.js +6 -10
  148. package/dist/src/stores.js +4 -2
  149. package/dist/src/suppress-file.js +25 -28
  150. package/dist/src/suppress-inline.js +36 -83
  151. package/dist/src/suppress.js +50 -71
  152. package/dist/src/symbol-keys.js +92 -88
  153. package/dist/src/tests/file-class.js +76 -0
  154. package/dist/src/{outside-tests.js → tests/outside.js} +7 -7
  155. package/dist/src/{test-support.js → tests/support.js} +5 -12
  156. package/dist/src/text/compare.js +26 -0
  157. package/dist/src/text/glob.js +194 -0
  158. package/dist/src/text/named-files.js +298 -0
  159. package/dist/src/text/yaml.js +684 -0
  160. package/dist/src/type-errors.js +11 -232
  161. package/dist/src/type-parameter-reads.js +178 -139
  162. package/dist/src/unimplemented-callees.js +262 -242
  163. package/dist/src/unwrap.js +23 -0
  164. package/dist/src/usage.js +10 -0
  165. package/dist/src/vendor/unbash/ansi-c.js +132 -0
  166. package/dist/src/vendor/unbash/arithmetic-parts.js +37 -0
  167. package/dist/src/vendor/unbash/arithmetic.js +591 -0
  168. package/dist/src/vendor/unbash/assignment.js +131 -0
  169. package/dist/src/vendor/unbash/chars.js +48 -0
  170. package/dist/src/vendor/unbash/command.js +41 -0
  171. package/dist/src/vendor/unbash/expansion.js +80 -0
  172. package/dist/src/vendor/unbash/glob.js +268 -0
  173. package/dist/src/vendor/unbash/heredoc.js +27 -0
  174. package/dist/src/vendor/unbash/internal-types.js +1 -0
  175. package/dist/src/vendor/unbash/lexer.js +4274 -0
  176. package/dist/src/vendor/unbash/limits.js +3 -0
  177. package/dist/src/vendor/unbash/parser.js +1366 -0
  178. package/dist/src/vendor/unbash/parts.js +57 -0
  179. package/dist/src/vendor/unbash/substitution-context.js +8 -0
  180. package/dist/src/vendor/unbash/traversal.js +212 -0
  181. package/dist/src/vendor/unbash/types.js +1 -0
  182. package/dist/src/vendor/unbash/word-value.js +61 -0
  183. package/dist/src/vendor/unbash/word.js +40 -0
  184. package/dist/src/verbs/analyze.js +194 -127
  185. package/dist/src/verbs/describe.js +13 -18
  186. package/dist/src/verbs/explain.js +85 -139
  187. package/dist/src/verbs/print-config.js +2 -1
  188. package/dist/src/verbs/print-projects.js +6 -4
  189. package/dist/src/verbs/print-retained.js +30 -6
  190. package/dist/src/verbs/print-roots.js +4 -2
  191. package/dist/src/verbs/verb.js +1 -5
  192. package/dist/src/verbs/version.js +14 -3
  193. package/jsr.json +2 -1
  194. package/package.json +14 -8
  195. package/src/alias-chain.ts +40 -11
  196. package/src/amd.ts +130 -0
  197. package/src/analysis.ts +426 -733
  198. package/src/augmentations.ts +93 -4
  199. package/src/automatic-types.ts +12 -30
  200. package/src/bindings.ts +460 -0
  201. package/src/commands/held.ts +632 -0
  202. package/src/commands/read.ts +242 -0
  203. package/src/commands/shell.ts +228 -0
  204. package/src/commands/tools.ts +2382 -0
  205. package/src/component-files.ts +4 -2
  206. package/src/component-layer.ts +4 -2
  207. package/src/config.ts +31 -302
  208. package/src/conformance-record.ts +2 -2
  209. package/src/consumers.ts +16 -66
  210. package/src/contextual-uses.ts +66 -34
  211. package/src/contract/config.generated.ts +821 -0
  212. package/src/contract/contract.generated.ts +1453 -0
  213. package/src/contract/report.generated.ts +1241 -0
  214. package/src/dependencies.ts +223 -128
  215. package/src/destructuring.ts +1 -31
  216. package/src/edges.ts +41 -140
  217. package/src/element-access.ts +190 -187
  218. package/src/entries/build-scripts.ts +292 -0
  219. package/src/{configuration-files.ts → entries/configuration-files.ts} +68 -278
  220. package/src/{convention-rows.ts → entries/convention-rows.ts} +227 -31
  221. package/src/{conventions.ts → entries/conventions.ts} +367 -583
  222. package/src/{html-entries.ts → entries/html-entries.ts} +22 -48
  223. package/src/{mdx-entries.ts → entries/mdx-entries.ts} +7 -30
  224. package/src/entries/run-directories.ts +108 -0
  225. package/src/entries/sources.ts +266 -0
  226. package/src/entries/static-module.ts +858 -0
  227. package/src/entries/test-runners.ts +835 -0
  228. package/src/entries/workflow-steps.ts +432 -0
  229. package/src/exemptions/argument-places.ts +198 -0
  230. package/src/exemptions/calls.ts +483 -0
  231. package/src/exemptions/classes.ts +49 -0
  232. package/src/exemptions/decorator.ts +56 -0
  233. package/src/exemptions/detectors.ts +75 -0
  234. package/src/{enum-group.ts → exemptions/enum-group.ts} +10 -19
  235. package/src/{erased-stores.ts → exemptions/erased-stores.ts} +7 -14
  236. package/src/{framework-lifecycle.ts → exemptions/framework-lifecycle.ts} +85 -66
  237. package/src/exemptions/generated-file.ts +318 -0
  238. package/src/{injection-container.ts → exemptions/injection-container.ts} +29 -34
  239. package/src/exemptions/installed-globals.ts +255 -0
  240. package/src/{interface-satisfaction.ts → exemptions/interface-satisfaction.ts} +69 -160
  241. package/src/exemptions/lifecycle.ts +286 -0
  242. package/src/{reflective-lookup.ts → exemptions/reflective-lookup.ts} +5 -5
  243. package/src/exemptions/serialization-contract.ts +1729 -0
  244. package/src/exemptions/sites.ts +293 -0
  245. package/src/{template-field.ts → exemptions/template-field.ts} +22 -32
  246. package/src/{value-reach.ts → exemptions/value-reach.ts} +16 -8
  247. package/src/exposure.ts +492 -0
  248. package/src/extensions.ts +45 -0
  249. package/src/facts.ts +46 -0
  250. package/src/failure.ts +63 -0
  251. package/src/file-facts.ts +15 -25
  252. package/src/finding.ts +10 -10
  253. package/src/findings/boundary.ts +11 -0
  254. package/src/findings/completion.ts +133 -64
  255. package/src/findings/dependencies-and-module-machinery.ts +4 -7
  256. package/src/findings/emitter.ts +9 -10
  257. package/src/findings/emitters.ts +38 -52
  258. package/src/{implementations.ts → findings/implementations.ts} +4 -4
  259. package/src/{in-operands.ts → findings/in-operands.ts} +4 -3
  260. package/src/findings/interfaces.ts +7 -9
  261. package/src/findings/intra-function.ts +16 -14
  262. package/src/findings/non-code-artifacts.ts +24 -15
  263. package/src/findings/reads-and-writes.ts +118 -41
  264. package/src/findings/self-check.ts +51 -38
  265. package/src/findings/unused-declarations.ts +31 -49
  266. package/src/findings/visibility-narrowing.ts +36 -40
  267. package/src/findings-pass.ts +15 -31
  268. package/src/fs/document.ts +70 -0
  269. package/src/fs/manifest.ts +96 -0
  270. package/src/fs/tree.ts +110 -0
  271. package/src/git-ignore.ts +50 -26
  272. package/src/host.ts +12 -5
  273. package/src/import-bindings.ts +98 -29
  274. package/src/index/sites.ts +781 -0
  275. package/src/index/values.ts +170 -0
  276. package/src/index.ts +2 -2
  277. package/src/indexed-access.ts +570 -527
  278. package/src/intra-function-parts.ts +73 -44
  279. package/src/inventory/commonjs.ts +696 -0
  280. package/src/inventory/enumerate.ts +203 -0
  281. package/src/inventory/syntax.ts +311 -0
  282. package/src/inventory.ts +442 -895
  283. package/src/javascript-file.ts +54 -0
  284. package/src/json-document.ts +241 -76
  285. package/src/keyof-comparisons.ts +133 -122
  286. package/src/kinds.ts +5 -413
  287. package/src/{components.ts → liveness/components.ts} +4 -6
  288. package/src/{graph.ts → liveness/graph.ts} +100 -35
  289. package/src/liveness/matrix.ts +162 -0
  290. package/src/liveness/sweep.ts +855 -0
  291. package/src/load/classify.ts +433 -0
  292. package/src/load/diagnostics.ts +154 -0
  293. package/src/load/discover.ts +471 -0
  294. package/src/{emit-map.ts → load/emit-map.ts} +1 -1
  295. package/src/load/expected-module.ts +194 -0
  296. package/src/load/load.ts +73 -0
  297. package/src/load/module-lookup.ts +50 -0
  298. package/src/load/package-scope.ts +74 -0
  299. package/src/load/plan.ts +513 -0
  300. package/src/load/specifiers.ts +171 -0
  301. package/src/load/synthesize.ts +230 -0
  302. package/src/load/test-globals.ts +251 -0
  303. package/src/load/test-joins.ts +98 -0
  304. package/src/{workspace-manifests.ts → load/workspace-manifests.ts} +5 -5
  305. package/src/{workspace-programs.ts → load/workspace-programs.ts} +128 -85
  306. package/src/{workspace-resolution.ts → load/workspace-resolution.ts} +41 -77
  307. package/src/{workspace-run.ts → load/workspace-run.ts} +18 -16
  308. package/src/{workspace.ts → load/workspace.ts} +90 -134
  309. package/src/module-declarations.ts +74 -98
  310. package/src/overrides.ts +162 -134
  311. package/src/partial.ts +3 -2
  312. package/src/paths.ts +92 -16
  313. package/src/platform-calls.ts +119 -0
  314. package/src/platform-symbols.ts +189 -0
  315. package/src/position.ts +44 -1
  316. package/src/print.ts +12 -92
  317. package/src/product.ts +18 -0
  318. package/src/query.ts +201 -10
  319. package/src/ref.ts +12 -20
  320. package/src/references/read-rule.ts +60 -0
  321. package/src/references/read-rules.ts +55 -0
  322. package/src/references/sink.ts +314 -0
  323. package/src/references/sources.ts +632 -0
  324. package/src/references.ts +187 -1450
  325. package/src/report-schema.ts +68 -0
  326. package/src/report.ts +103 -226
  327. package/src/reporters/annotations.ts +22 -11
  328. package/src/reporters/json.ts +1 -1
  329. package/src/reporters/reporter.ts +2 -4
  330. package/src/reporters/reporters.ts +1 -1
  331. package/src/reporters/sarif.ts +29 -16
  332. package/src/reporters/template.ts +4 -20
  333. package/src/reporters/text.ts +3 -3
  334. package/src/resolve.ts +284 -1115
  335. package/src/{configured-declarations.ts → roots/configured-declarations.ts} +26 -29
  336. package/src/{entry-point-gaps.ts → roots/entry-point-gaps.ts} +7 -16
  337. package/src/roots/manifest.ts +303 -0
  338. package/src/roots/published-reach.ts +486 -0
  339. package/src/{roots.ts → roots/root-set.ts} +286 -469
  340. package/src/roots/unseen-loads.ts +345 -0
  341. package/src/run.ts +75 -91
  342. package/src/schema.ts +391 -388
  343. package/src/scope.ts +46 -138
  344. package/src/session.ts +87 -55
  345. package/src/source-files.ts +6 -11
  346. package/src/stores.ts +15 -3
  347. package/src/suppress-file.ts +24 -33
  348. package/src/suppress-inline.ts +55 -91
  349. package/src/suppress.ts +78 -79
  350. package/src/symbol-keys.ts +104 -107
  351. package/src/tests/file-class.ts +135 -0
  352. package/src/{outside-tests.ts → tests/outside.ts} +16 -10
  353. package/src/{test-support.ts → tests/support.ts} +15 -21
  354. package/src/text/compare.ts +27 -0
  355. package/src/text/glob.ts +210 -0
  356. package/src/text/named-files.ts +388 -0
  357. package/src/text/yaml.ts +747 -0
  358. package/src/type-errors.ts +18 -288
  359. package/src/type-parameter-reads.ts +187 -158
  360. package/src/unimplemented-callees.ts +297 -280
  361. package/src/unwrap.ts +34 -0
  362. package/src/usage.ts +10 -0
  363. package/src/vendor/unbash/LICENSE +15 -0
  364. package/src/vendor/unbash/VENDORED.md +16 -0
  365. package/src/vendor/unbash/ansi-c.ts +132 -0
  366. package/src/vendor/unbash/arithmetic-parts.ts +53 -0
  367. package/src/vendor/unbash/arithmetic.ts +641 -0
  368. package/src/vendor/unbash/assignment.ts +163 -0
  369. package/src/vendor/unbash/chars.ts +48 -0
  370. package/src/vendor/unbash/command.ts +47 -0
  371. package/src/vendor/unbash/expansion.ts +144 -0
  372. package/src/vendor/unbash/glob.ts +284 -0
  373. package/src/vendor/unbash/heredoc.ts +34 -0
  374. package/src/vendor/unbash/internal-types.ts +94 -0
  375. package/src/vendor/unbash/lexer.ts +4352 -0
  376. package/src/vendor/unbash/limits.ts +3 -0
  377. package/src/vendor/unbash/parser.ts +1612 -0
  378. package/src/vendor/unbash/parts.ts +96 -0
  379. package/src/vendor/unbash/substitution-context.ts +20 -0
  380. package/src/vendor/unbash/traversal.ts +182 -0
  381. package/src/vendor/unbash/types.ts +660 -0
  382. package/src/vendor/unbash/word-value.ts +64 -0
  383. package/src/vendor/unbash/word.ts +50 -0
  384. package/src/verbs/analyze.ts +255 -164
  385. package/src/verbs/describe.ts +19 -17
  386. package/src/verbs/explain.ts +93 -169
  387. package/src/verbs/print-config.ts +2 -1
  388. package/src/verbs/print-projects.ts +6 -4
  389. package/src/verbs/print-retained.ts +36 -6
  390. package/src/verbs/print-roots.ts +4 -2
  391. package/src/verbs/verb.ts +2 -8
  392. package/src/verbs/version.ts +15 -3
  393. package/dist/src/base-url.js +0 -18
  394. package/dist/src/calls.js +0 -155
  395. package/dist/src/conventions.js +0 -937
  396. package/dist/src/discover.js +0 -468
  397. package/dist/src/entry-points.js +0 -529
  398. package/dist/src/exempt-classes.js +0 -75
  399. package/dist/src/exempt.js +0 -209
  400. package/dist/src/generated-file.js +0 -95
  401. package/dist/src/glob.js +0 -65
  402. package/dist/src/manifest.js +0 -165
  403. package/dist/src/matrix.js +0 -246
  404. package/dist/src/pnpm-workspace.js +0 -120
  405. package/dist/src/roots.js +0 -672
  406. package/dist/src/serialization-contract.js +0 -611
  407. package/dist/src/setup-failure.js +0 -23
  408. package/dist/src/sweep.js +0 -224
  409. package/dist/src/test-joins.js +0 -101
  410. package/dist/src/value-flow.js +0 -74
  411. package/dist/src/version.js +0 -7
  412. package/dist/src/workflow-steps.js +0 -185
  413. package/src/base-url.ts +0 -24
  414. package/src/calls.ts +0 -225
  415. package/src/decorator.ts +0 -78
  416. package/src/discover.ts +0 -653
  417. package/src/entry-points.ts +0 -687
  418. package/src/exempt-classes.ts +0 -123
  419. package/src/exempt.ts +0 -323
  420. package/src/generated-file.ts +0 -111
  421. package/src/glob.ts +0 -67
  422. package/src/manifest.ts +0 -234
  423. package/src/matrix.ts +0 -423
  424. package/src/pnpm-workspace.ts +0 -135
  425. package/src/serialization-contract.ts +0 -849
  426. package/src/setup-failure.ts +0 -39
  427. package/src/sweep.ts +0 -347
  428. package/src/test-joins.ts +0 -120
  429. package/src/value-flow.ts +0 -104
  430. package/src/version.ts +0 -7
  431. package/src/workflow-steps.ts +0 -216
@@ -0,0 +1,483 @@
1
+ /**
2
+ * The calls and decorators of one project that the configured classes read: what each
3
+ * call invokes, a call through a method of `Function.prototype` included, and which of the
4
+ * target's classes a call passes or a decorator is attached to. A class is passed by each
5
+ * value an argument can carry ({@link carriedValues}), named directly or through
6
+ * variables, and a decorator written as a call is a call.
7
+ */
8
+
9
+ import {
10
+ isArrayLiteralExpression,
11
+ isArrowFunction,
12
+ isBindingElement,
13
+ isCallExpression,
14
+ isDecorator,
15
+ isFunctionDeclaration,
16
+ isFunctionExpression,
17
+ isIdentifier,
18
+ isMethodDeclaration,
19
+ isParameterDeclaration,
20
+ isPropertyAccessExpression,
21
+ isPropertyAssignment,
22
+ isPropertyDeclaration,
23
+ isShorthandPropertyAssignment,
24
+ isSpreadElement,
25
+ isVariableDeclaration,
26
+ type CallExpression,
27
+ type Decorator,
28
+ type Expression,
29
+ type Node,
30
+ type ParameterDeclaration,
31
+ } from "@typescript/native/ast";
32
+ import {
33
+ ObjectFlags,
34
+ SymbolFlags,
35
+ type Symbol as TSSymbol,
36
+ type Type,
37
+ } from "@typescript/native/sync";
38
+ import { resolvedTargets, type AliasChains } from "../alias-chain.ts";
39
+ import { carriedValues, nameOf, type CarriedValue } from "../index/values.ts";
40
+ import type { Inventory } from "../inventory.ts";
41
+ import { must } from "../query.ts";
42
+ import type { ProjectView } from "../session.ts";
43
+ import { parenthesesRemoved, unwrapped } from "../unwrap.ts";
44
+ import type { ProjectSites } from "./sites.ts";
45
+
46
+ /** One class of the target a call passes or a decorator is attached to, and where. */
47
+ interface ClassUse {
48
+ /** The inventory's identifier of the class. */
49
+ readonly id: string;
50
+ readonly site: Node;
51
+ }
52
+
53
+ /** The callee one decorator names: its expression, or the callee of the call it writes. */
54
+ export function decoratorCallee(decorator: Decorator): Node | undefined {
55
+ const expression = decorator.expression;
56
+ return nameOf(isCallExpression(expression) ? expression.expression : expression);
57
+ }
58
+
59
+ /** How one decorator is spelled in a record: its expression, without a call's arguments. */
60
+ export function spelledDecorator(decorator: Decorator): string {
61
+ const expression = decorator.expression;
62
+ const named = isCallExpression(expression) ? expression.expression : expression;
63
+ return `@${named.getText().replace(/\s+/gu, "")}`;
64
+ }
65
+
66
+ /** The decorators written on one declaration. */
67
+ export function decoratorsOf(node: Node): readonly Decorator[] {
68
+ return ((node as { readonly modifiers?: readonly Node[] }).modifiers ?? []).filter(isDecorator);
69
+ }
70
+
71
+ /** The methods of `Function.prototype` that invoke a function with arguments of their own. */
72
+ const FUNCTION_METHODS: ReadonlySet<string> = new Set(["call", "apply", "bind"]);
73
+
74
+ /** The interfaces of the standard library that declare those methods for a function value. */
75
+ const FUNCTION_INTERFACES: ReadonlySet<string> = new Set([
76
+ "Function",
77
+ "CallableFunction",
78
+ "NewableFunction",
79
+ ]);
80
+
81
+ /**
82
+ * One call as the function it invokes sees it: the expression naming that function,
83
+ * and the argument each of its parameters binds, in order.
84
+ */
85
+ export interface Invocation {
86
+ readonly callee: Expression;
87
+ readonly arguments: readonly Expression[];
88
+ /** Whether the call reaches the callee through a method of `Function.prototype`. */
89
+ readonly indirect: boolean;
90
+ /** Whether the last argument is a list the parameters bind the elements of, as `apply` takes. */
91
+ readonly listed: boolean;
92
+ }
93
+
94
+ /** A call through a method of `Function.prototype`: the method's name and the invocation. */
95
+ interface MethodForm {
96
+ readonly method: Node;
97
+ readonly invocation: Invocation;
98
+ }
99
+
100
+ /**
101
+ * The invocation a call writes through a method of `Function.prototype`, read from
102
+ * the syntax alone: `f.call(self, a)`, `f.apply(self, [a])`, `f.bind(self, a)`, which
103
+ * passes `a` though nothing calls the bound function there, because the bound function
104
+ * carries `a` to wherever it is called and that call is not followed, and
105
+ * `f.bind(self, a)(b)`, which passes `b` after it. An `apply` argument
106
+ * that is no array literal is the value of the first parameter, whose elements it
107
+ * carries. Whether the method is the prototype's is resolution's to say.
108
+ */
109
+ function throughMethod(call: CallExpression): MethodForm | undefined {
110
+ const expression = parenthesesRemoved(call.expression);
111
+ if (isPropertyAccessExpression(expression) && FUNCTION_METHODS.has(expression.name.text)) {
112
+ const [, ...rest] = call.arguments;
113
+ let passed: readonly Expression[] = rest;
114
+ let listed = false;
115
+ if (expression.name.text === "apply") {
116
+ const list = rest[0] === undefined ? undefined : parenthesesRemoved(rest[0]);
117
+ listed = list !== undefined && !isArrayLiteralExpression(list);
118
+ passed = list === undefined ? [] : isArrayLiteralExpression(list) ? list.elements : [list];
119
+ }
120
+ return {
121
+ method: expression.name,
122
+ invocation: { callee: expression.expression, arguments: passed, indirect: true, listed },
123
+ };
124
+ }
125
+ if (isCallExpression(expression)) {
126
+ const bound = parenthesesRemoved(expression.expression);
127
+ if (isPropertyAccessExpression(bound) && bound.name.text === "bind") {
128
+ return {
129
+ method: bound.name,
130
+ invocation: {
131
+ callee: bound.expression,
132
+ arguments: [...expression.arguments.slice(1), ...call.arguments],
133
+ indirect: true,
134
+ listed: false,
135
+ },
136
+ };
137
+ }
138
+ }
139
+ return undefined;
140
+ }
141
+
142
+ /** What each call of one project invokes. */
143
+ export interface Invocations {
144
+ /** The function one call invokes and the arguments its parameters bind. */
145
+ readonly of: (call: CallExpression) => Invocation;
146
+ /** The declaration the invoked function's name resolves to, every alias followed. */
147
+ readonly callee: (call: CallExpression) => TSSymbol | undefined;
148
+ }
149
+
150
+ /**
151
+ * What each of a project's calls invokes. A call through `call`, `apply` or `bind`
152
+ * invokes the function the method is read from only where the method is the standard
153
+ * library's: the program's own `call` and `Reflect.apply` pass nothing on.
154
+ */
155
+ export function invocations<Brand>(
156
+ project: ProjectView<Brand>,
157
+ calls: readonly CallExpression[],
158
+ ): Invocations {
159
+ const forms = new Map<CallExpression, MethodForm>();
160
+ for (const call of calls) {
161
+ const form = throughMethod(call);
162
+ if (form !== undefined) {
163
+ forms.set(call, form);
164
+ }
165
+ }
166
+ const callees = resolvedTargets(project, [
167
+ ...calls.flatMap((call) => nameOf(call.expression) ?? []),
168
+ ...[...forms.values()].flatMap((form) => {
169
+ const name = nameOf(form.invocation.callee);
170
+ return name === undefined ? [form.method] : [form.method, name];
171
+ }),
172
+ ]);
173
+ const standard = (method: TSSymbol): boolean =>
174
+ method.declarations.some(
175
+ (handle) => project.program.getSourceFileMetadata(handle.path)?.isDefaultLibrary === true,
176
+ ) && FUNCTION_INTERFACES.has(must(project.queries.parentOf(method))?.name ?? "");
177
+ const of = (call: CallExpression): Invocation => {
178
+ const form = forms.get(call);
179
+ const method = form === undefined ? undefined : callees.get(form.method);
180
+ return form !== undefined && method !== undefined && standard(method)
181
+ ? form.invocation
182
+ : { callee: call.expression, arguments: call.arguments, indirect: false, listed: false };
183
+ };
184
+ return {
185
+ of,
186
+ callee: (call) => {
187
+ const name = nameOf(of(call).callee);
188
+ return name === undefined ? undefined : callees.get(name);
189
+ },
190
+ };
191
+ }
192
+
193
+ /** The declaration a shorthand property's value resolves to, an import followed to what it names. */
194
+ function shorthandTarget<Brand>(project: ProjectView<Brand>, node: Node): TSSymbol | undefined {
195
+ const value = must(project.shorthandValueAt(project.handle(node)));
196
+ if (value === undefined || (value.flags & SymbolFlags.Alias) === 0) {
197
+ return value;
198
+ }
199
+ const aliased = must(project.queries.aliased(value));
200
+ return aliased.declarations.length === 0 ? undefined : aliased;
201
+ }
202
+
203
+ /**
204
+ * What one carried value holds: the declaration its name resolves to, and the classes and
205
+ * functions the checker's type at it holds ({@link constructedAt}). `known` holds names
206
+ * already resolved in a batch.
207
+ */
208
+ function heldBy<Brand>(
209
+ project: ProjectView<Brand>,
210
+ value: CarriedValue,
211
+ known?: ReadonlyMap<Node, TSSymbol>,
212
+ ): { readonly named: TSSymbol | undefined; readonly typed: readonly TSSymbol[] } {
213
+ const { name } = value;
214
+ if (name === undefined) {
215
+ return { named: undefined, typed: constructedAt(project, value.site) };
216
+ }
217
+ if (value.shorthand) {
218
+ return { named: shorthandTarget(project, name), typed: [] };
219
+ }
220
+ return {
221
+ named: known?.get(name) ?? resolvedTargets(project, [name]).get(name),
222
+ typed: constructedAt(project, value.site),
223
+ };
224
+ }
225
+
226
+ /** The classes of the target each call passes, by the call, as {@link classesCarried} reads its invocation's arguments. */
227
+ export function classesPassed<Brand>(
228
+ project: ProjectView<Brand>,
229
+ held: Inventory,
230
+ chains: AliasChains,
231
+ sites: Pick<ProjectSites, "calls" | "invocations">,
232
+ calls: readonly CallExpression[],
233
+ ): ReadonlyMap<CallExpression, readonly ClassUse[]> {
234
+ const carried = classesCarried(
235
+ project,
236
+ held,
237
+ chains,
238
+ sites,
239
+ calls.map((call) => sites.invocations.of(call).arguments),
240
+ );
241
+ return new Map(calls.map((call, at) => [call, carried[at] ?? []]));
242
+ }
243
+
244
+ /**
245
+ * The classes of the target each group of written values carries: each class a value
246
+ * can carry holds as a constructor, as the checker types it. A name whose type erases
247
+ * the class is followed through what its declaration binds ({@link boundTo}) and, for a
248
+ * parameter, through what each call of its function passes at its place, so a class
249
+ * handed to a wrapper is passed. A class is used at each value that carries it. A class
250
+ * of another program is carried by nothing.
251
+ */
252
+ export function classesCarried<Brand>(
253
+ project: ProjectView<Brand>,
254
+ held: Inventory,
255
+ chains: AliasChains,
256
+ sites: Pick<ProjectSites, "calls" | "invocations">,
257
+ groups: readonly (readonly Expression[])[],
258
+ ): readonly (readonly ClassUse[])[] {
259
+ const { invocations: invoked } = sites;
260
+ const passed = groups.map((written) => written.flatMap(carriedValues));
261
+ const targets = resolvedTargets(
262
+ project,
263
+ passed.flat().flatMap((value) => (value.shorthand ? [] : (value.name ?? []))),
264
+ );
265
+ const classes = new Set(
266
+ held.symbols.filter((symbol) => symbol.kind === "class").map((symbol) => symbol.id),
267
+ );
268
+ let calling: CallsOf | undefined;
269
+ const callsOfFunction = (symbol: TSSymbol): readonly CallExpression[] => {
270
+ calling ??= callsByDeclaration(
271
+ project,
272
+ sites.calls.map((one) => one.call),
273
+ invoked,
274
+ );
275
+ return symbol.declarations.flatMap((handle) => calling?.get(keyOf(handle)) ?? []);
276
+ };
277
+ const classesOf = (value: CarriedValue, seen: Set<number>): readonly string[] => {
278
+ const { named, typed } = heldBy(project, value, targets);
279
+ return [
280
+ ...typed.flatMap((symbol) => chains.declarationsOf(symbol).filter((id) => classes.has(id))),
281
+ ...(named === undefined ? [] : reached(named, seen)),
282
+ ];
283
+ };
284
+ const reached = (symbol: TSSymbol, seen: Set<number>): readonly string[] => {
285
+ const ids = chains.declarationsOf(symbol).filter((id) => classes.has(id));
286
+ if (ids.length > 0 || seen.has(symbol.id)) {
287
+ return ids;
288
+ }
289
+ seen.add(symbol.id);
290
+ const through = (written: Expression): readonly string[] =>
291
+ carriedValues(written).flatMap((value) => classesOf(value, seen));
292
+ return symbol.declarations.flatMap((handle) => {
293
+ const node = project.declarationAt(handle)?.node;
294
+ if (node === undefined) {
295
+ return [];
296
+ }
297
+ if (isParameterDeclaration(node)) {
298
+ return argumentsAt(project, node, callsOfFunction, invoked).flatMap(through);
299
+ }
300
+ const bound = boundTo(project, node);
301
+ return [
302
+ ...(bound.written === undefined ? [] : through(bound.written)),
303
+ ...bound.symbols.flatMap((next) => reached(next, seen)),
304
+ ];
305
+ });
306
+ };
307
+ return passed.map((values) => {
308
+ const uses = new Map<string, ClassUse>();
309
+ for (const value of values) {
310
+ for (const id of classesOf(value, new Set())) {
311
+ uses.set(`${id}\u0000${String(value.site.pos)}`, { id, site: value.site });
312
+ }
313
+ }
314
+ return [...uses.values()];
315
+ });
316
+ }
317
+
318
+ /**
319
+ * The symbols of the classes and functions the checker's type at one expression holds as
320
+ * values, each member of a union: the static side of a class or a function is an
321
+ * anonymous type its declaration's symbol names, which an instance's type is not.
322
+ */
323
+ function constructedAt<Brand>(project: ProjectView<Brand>, written: Node): readonly TSSymbol[] {
324
+ return heldIn(project, must(project.queries.typeAt(unwrapped(written))));
325
+ }
326
+
327
+ /** The classes and functions one type holds as values, as {@link constructedAt} reads them. */
328
+ function heldIn<Brand>(project: ProjectView<Brand>, type: Type | undefined): readonly TSSymbol[] {
329
+ const { queries } = project;
330
+ return (type === undefined ? [] : must(queries.constituents(type))).flatMap((part) => {
331
+ if (!part.isObjectType() || (part.objectFlags & ObjectFlags.Anonymous) === 0) {
332
+ return [];
333
+ }
334
+ return must(queries.symbolOfType(part)) ?? [];
335
+ });
336
+ }
337
+
338
+ /** What one declaration binds its name to: the value it writes, or the symbols it copies. */
339
+ interface Bound {
340
+ readonly written?: Expression;
341
+ readonly symbols: readonly TSSymbol[];
342
+ }
343
+
344
+ /**
345
+ * What a variable, a property or a destructured binding binds its name to: a variable's
346
+ * or a property's initializer, the value a shorthand property names, or the property of
347
+ * the destructured value a binding element reads.
348
+ */
349
+ function boundTo<Brand>(project: ProjectView<Brand>, node: Node): Bound {
350
+ if (isShorthandPropertyAssignment(node)) {
351
+ const value = shorthandTarget(project, node);
352
+ return { symbols: value === undefined ? [] : [value] };
353
+ }
354
+ if (isBindingElement(node)) {
355
+ const key = node.propertyName ?? node.name;
356
+ if (key === undefined || !isIdentifier(key)) {
357
+ return { symbols: [] };
358
+ }
359
+ const source = must(project.queries.typeAt(node.parent));
360
+ const property =
361
+ source === undefined
362
+ ? undefined
363
+ : must(project.queries.propertiesOf(source)).find((one) => one.name === key.text);
364
+ return { symbols: property === undefined ? [] : [property] };
365
+ }
366
+ const written = initializerOf(node);
367
+ return written === undefined ? { symbols: [] } : { written, symbols: [] };
368
+ }
369
+
370
+ /** The value a variable or a property declaration binds its name to, where it writes one. */
371
+ function initializerOf(node: Node): Expression | undefined {
372
+ return isVariableDeclaration(node) || isPropertyAssignment(node) || isPropertyDeclaration(node)
373
+ ? node.initializer
374
+ : undefined;
375
+ }
376
+
377
+ /** The project's calls, by each declaration their callee resolves to. */
378
+ type CallsOf = ReadonlyMap<string, readonly CallExpression[]>;
379
+
380
+ /** The key of one declaration a symbol names, the same for each symbol the checker makes of it. */
381
+ function keyOf(handle: { readonly path: string; readonly index: number }): string {
382
+ return `${handle.path}#${String(handle.index)}`;
383
+ }
384
+
385
+ /**
386
+ * Every call of the project by the declarations its invoked function can be: the function
387
+ * or the method it names, or else each function the checker's type at it holds, wherever
388
+ * that value came from. A name is also followed through what its binding copies
389
+ * ({@link boundTo}), which is how a call reaches a function an annotation erases.
390
+ * Only the target's own declarations are keys, as only its own functions are asked for.
391
+ */
392
+ function callsByDeclaration<Brand>(
393
+ project: ProjectView<Brand>,
394
+ calls: readonly CallExpression[],
395
+ invoked: Invocations,
396
+ ): CallsOf {
397
+ const own = project.ownPaths();
398
+ const named = new Map<number, readonly string[]>();
399
+ const keysOf = (symbol: TSSymbol, seen: Set<number>): readonly string[] => {
400
+ const known = named.get(symbol.id);
401
+ if (known !== undefined || seen.has(symbol.id)) {
402
+ return known ?? [];
403
+ }
404
+ seen.add(symbol.id);
405
+ const keys = symbol.declarations
406
+ .filter((handle) => own.has(handle.path))
407
+ .flatMap((handle) => {
408
+ const node = project.declarationAt(handle)?.node;
409
+ const bound = node === undefined ? { symbols: [] } : boundTo(project, node);
410
+ const copied = [
411
+ ...bound.symbols,
412
+ ...(bound.written === undefined ? [] : carriedValues(bound.written)).flatMap((value) => {
413
+ const { named: next, typed } = heldBy(project, value);
414
+ return [...typed, ...(next === undefined ? [] : [next])];
415
+ }),
416
+ ];
417
+ return [keyOf(handle), ...copied.flatMap((next) => keysOf(next, seen))];
418
+ });
419
+ named.set(symbol.id, keys);
420
+ return keys;
421
+ };
422
+ const declared = (call: CallExpression): boolean =>
423
+ ((invoked.callee(call)?.flags ?? 0) & (SymbolFlags.Function | SymbolFlags.Method)) !== 0;
424
+ const typed = calls.filter((call) => !declared(call));
425
+ const types = new Map(
426
+ project.queries
427
+ .typesAt(typed.map((call) => unwrapped(invoked.of(call).callee)))
428
+ .map((type, index) => [typed[index], must(type)]),
429
+ );
430
+ const found = new Map<string, CallExpression[]>();
431
+ for (const call of calls) {
432
+ const callee = invoked.callee(call);
433
+ const held = [
434
+ ...(callee === undefined ? [] : [callee]),
435
+ ...(types.has(call) ? heldIn(project, types.get(call)) : []),
436
+ ];
437
+ for (const key of new Set(held.flatMap((symbol) => keysOf(symbol, new Set())))) {
438
+ found.set(key, [...(found.get(key) ?? []), call]);
439
+ }
440
+ }
441
+ return found;
442
+ }
443
+
444
+ /**
445
+ * What each call of the function a parameter belongs to passes at the parameter's place,
446
+ * every argument from there on for a rest parameter, as the call's invocation binds them.
447
+ * The function is the one the checker's type at its own declaration names, so a function
448
+ * with no name of its own is called too. A `this` parameter takes no place, and an
449
+ * argument at or after a spread argument passes at every place the spread's length can
450
+ * move it to.
451
+ */
452
+ function argumentsAt<Brand>(
453
+ project: ProjectView<Brand>,
454
+ parameter: ParameterDeclaration,
455
+ callsOfFunction: (symbol: TSSymbol) => readonly CallExpression[],
456
+ invoked: Invocations,
457
+ ): readonly Expression[] {
458
+ const owner = parameter.parent;
459
+ if (
460
+ !isFunctionDeclaration(owner) &&
461
+ !isMethodDeclaration(owner) &&
462
+ !isArrowFunction(owner) &&
463
+ !isFunctionExpression(owner)
464
+ ) {
465
+ return [];
466
+ }
467
+ const calls = new Set(constructedAt(project, owner).flatMap(callsOfFunction));
468
+ const [first] = owner.parameters;
469
+ const erased = first !== undefined && isIdentifier(first.name) && first.name.text === "this";
470
+ const place = owner.parameters.indexOf(parameter) - (erased ? 1 : 0);
471
+ const rest = parameter.dotDotDotToken !== undefined;
472
+ return [...calls].flatMap((call) => {
473
+ let spreads = 0;
474
+ return invoked.of(call).arguments.flatMap((argument, index) => {
475
+ const spread = isSpreadElement(argument);
476
+ const earliest = index - spreads;
477
+ spreads += spread ? 1 : 0;
478
+ const open = spread || earliest < index;
479
+ const lands = open ? rest || earliest <= place : rest ? index >= place : index === place;
480
+ return lands ? [spread ? argument.expression : argument] : [];
481
+ });
482
+ });
483
+ }
@@ -0,0 +1,49 @@
1
+ import { EXEMPTION_CLASSES, type Language } from "../contract/contract.generated.ts";
2
+
3
+ /**
4
+ * Whether a class may retain a member declared with the `private` modifier, and one
5
+ * declared with a `#private` name. The modifier is a compile-time constraint only, so
6
+ * such a member stays reachable by its name at run time; a private name cannot be
7
+ * named from outside its class body at all.
8
+ */
9
+ export interface TypeScriptVisibility {
10
+ readonly private: boolean;
11
+ readonly privateName: boolean;
12
+ }
13
+
14
+ type Row = (typeof EXEMPTION_CLASSES)[number];
15
+
16
+ /** The name of a class of the vocabulary. */
17
+ export type ExemptionClass = Row["class"];
18
+
19
+ /** The classes of the rows that list one language. */
20
+ type ClassesOf<R, L extends Language> = R extends {
21
+ readonly class: infer C;
22
+ readonly languages: readonly (infer Listed)[];
23
+ }
24
+ ? L extends Listed
25
+ ? C
26
+ : never
27
+ : never;
28
+
29
+ /** The name of a class that runs on TypeScript, the only classes this analyzer records. */
30
+ export type TSExemptionClass = ClassesOf<Row, "ts">;
31
+
32
+ function runsOnTS(row: Row): row is Extract<Row, { readonly class: TSExemptionClass }> {
33
+ const languages: readonly Language[] = row.languages;
34
+ return languages.includes("ts");
35
+ }
36
+
37
+ const TS_ROWS = EXEMPTION_CLASSES.filter(runsOnTS);
38
+
39
+ /** The classes that run on TypeScript, in the vocabulary's order. */
40
+ export const TS_EXEMPTION_CLASSES: readonly TSExemptionClass[] = TS_ROWS.map((row) => row.class);
41
+
42
+ const VISIBILITY: ReadonlyMap<TSExemptionClass, TypeScriptVisibility> = new Map(
43
+ TS_ROWS.map((row) => [row.class, row.typescriptVisibility]),
44
+ );
45
+
46
+ /** Which private members one class that runs on TypeScript may retain. */
47
+ export function typescriptVisibilityOf(exemptionClass: TSExemptionClass): TypeScriptVisibility {
48
+ return VISIBILITY.get(exemptionClass) ?? { private: false, privateName: false };
49
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * The decorator class: a member a decorator expression is attached to, and every member
3
+ * of a class one is attached to but the member a parameter property declares, is held
4
+ * back, because the decorator may reach the member by its name. The rule is read from
5
+ * the tree alone. The decorator's own use of what it decorates is the reference pass's
6
+ * `decorator` reference; this class records only that the declaration is held back,
7
+ * static members of a decorated class included.
8
+ */
9
+
10
+ import { decoratorsOf, spelledDecorator } from "./calls.ts";
11
+ import type { DetectorInput, Evidence } from "./lifecycle.ts";
12
+ import { isParameterProperty, type InventorySymbol, type SymbolKind } from "../inventory.ts";
13
+ import { renderPosition } from "../position.ts";
14
+
15
+ /** The kinds of declaration a decorator is attached to and holds back. */
16
+ const DECORATED: ReadonlySet<SymbolKind> = new Set(["class", "method", "class-member"]);
17
+
18
+ /**
19
+ * The decorator detector: each decorated member, and each member of a decorated
20
+ * class, recorded at the decorator.
21
+ */
22
+ export function decorator<Brand>(input: DetectorInput<Brand>): readonly Evidence[] {
23
+ const { held, sites, targetRoot } = input;
24
+ const byId = new Map(held.symbols.map((symbol) => [symbol.id, symbol]));
25
+ const membersOf = new Map<string, InventorySymbol[]>();
26
+ for (const symbol of held.symbols) {
27
+ if (symbol.kind === "method" || symbol.kind === "class-member") {
28
+ const members = membersOf.get(symbol.parent);
29
+ if (members === undefined) {
30
+ membersOf.set(symbol.parent, [symbol]);
31
+ } else {
32
+ members.push(symbol);
33
+ }
34
+ }
35
+ }
36
+ // A decorated class's container passes each constructor argument, which keeps the
37
+ // parameter, not the member a parameter property stores it in. A parameter property's
38
+ // decorator is attached to its parameter, and to no member.
39
+ return sites.decorated.flatMap(({ id, node }) => {
40
+ const symbol = byId.get(id);
41
+ if (symbol === undefined || !DECORATED.has(symbol.kind) || isParameterProperty(node)) {
42
+ return [];
43
+ }
44
+ const members =
45
+ symbol.kind === "class"
46
+ ? (membersOf.get(symbol.id) ?? []).filter(
47
+ (member) => !sites.parameterProperties.has(member.id),
48
+ )
49
+ : [symbol];
50
+ return decoratorsOf(node).flatMap((attached) => {
51
+ const detail = `decorated by ${spelledDecorator(attached)}`;
52
+ const site = renderPosition(node.getSourceFile(), targetRoot, attached.getStart());
53
+ return members.map((member) => ({ id: member.id, detail, site }));
54
+ });
55
+ });
56
+ }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * The exemption classes this analyzer detects, each by its detector, and what their
3
+ * detection reads of the run once for every project. A class without a detector here
4
+ * retains nothing.
5
+ */
6
+
7
+ import type { ResolvedConfig } from "../config.ts";
8
+ import type { Host } from "../host.ts";
9
+ import type { Inventory } from "../inventory.ts";
10
+ import type { ProjectView } from "../session.ts";
11
+ import type { TSExemptionClass } from "./classes.ts";
12
+ import { decorator } from "./decorator.ts";
13
+ import { enumGroup } from "./enum-group.ts";
14
+ import { frameworkLifecycle } from "./framework-lifecycle.ts";
15
+ import { generatedFile, type GeneratedFact } from "./generated-file.ts";
16
+ import { injectionContainer } from "./injection-container.ts";
17
+ import { interfaceSatisfaction } from "./interface-satisfaction.ts";
18
+ import { detect, type Detector, type Detectors, type Exemption } from "./lifecycle.ts";
19
+ import { reflectiveLookup } from "./reflective-lookup.ts";
20
+ import { serializationContract } from "./serialization-contract.ts";
21
+ import { readTemplates, templateField } from "./template-field.ts";
22
+
23
+ export const DETECTORS: Detectors = new Map<TSExemptionClass, Detector>([
24
+ ["interface-satisfaction", interfaceSatisfaction],
25
+ ["enum-group", enumGroup],
26
+ ["generated-file", generatedFile],
27
+ ["template-field", templateField],
28
+ ["reflective-lookup", reflectiveLookup],
29
+ ["decorator", decorator],
30
+ ["injection-container", injectionContainer],
31
+ ["framework-lifecycle", frameworkLifecycle],
32
+ ["serialization-contract", serializationContract],
33
+ ]);
34
+
35
+ /** One project, while its view is open, as detection reads it. */
36
+ interface DetectedProject<Brand> {
37
+ readonly project: ProjectView<Brand>;
38
+ readonly held: Inventory;
39
+ /** The project's generated files, by path below the target root, each with what decided it. */
40
+ readonly generated: ReadonlyMap<string, GeneratedFact>;
41
+ }
42
+
43
+ /**
44
+ * The detection of one run: what every project's detectors read of the run, read once,
45
+ * and a function that runs them over one project. A switched-off class reads nothing,
46
+ * its templates included, and generated files are held only where the configuration
47
+ * leaves them out of the analysis.
48
+ */
49
+ export function detection(
50
+ host: Host,
51
+ targetRoot: string,
52
+ config: ResolvedConfig,
53
+ consumers: readonly string[],
54
+ detectors: Detectors,
55
+ ): <Brand>(one: DetectedProject<Brand>) => readonly Exemption[] {
56
+ const disabled = new Set(config.exemptions.disabled);
57
+ const templates = disabled.has("template-field")
58
+ ? { delimiters: config.analysis.template_delimiters, files: [] }
59
+ : readTemplates(host, targetRoot, config.analysis);
60
+ const included = config.analysis.generated_files === "include";
61
+ return ({ project, held, generated }) =>
62
+ detect(
63
+ {
64
+ project,
65
+ held,
66
+ targetRoot,
67
+ templates,
68
+ ts: config.ts,
69
+ consumers,
70
+ ...(included ? {} : { generated }),
71
+ },
72
+ detectors,
73
+ disabled,
74
+ );
75
+ }