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

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 (402) 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 +2 -7
  6. package/dist/src/amd.js +81 -0
  7. package/dist/src/analysis.js +269 -432
  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/calls.js +279 -43
  12. package/dist/src/commands/held.js +499 -0
  13. package/dist/src/commands/read.js +161 -0
  14. package/dist/src/commands/shell.js +169 -0
  15. package/dist/src/commands/tools.js +1847 -0
  16. package/dist/src/component-files.js +3 -2
  17. package/dist/src/component-layer.js +4 -2
  18. package/dist/src/config.js +6 -82
  19. package/dist/src/conformance-record.js +1 -1
  20. package/dist/src/consumers.js +10 -38
  21. package/dist/src/contextual-uses.js +57 -26
  22. package/dist/src/contract/config.generated.js +561 -0
  23. package/dist/src/contract/contract.generated.js +1369 -0
  24. package/dist/src/contract/report.generated.js +866 -0
  25. package/dist/src/dependencies.js +164 -121
  26. package/dist/src/destructuring.js +1 -19
  27. package/dist/src/edges.js +38 -122
  28. package/dist/src/element-access.js +181 -168
  29. package/dist/src/entries/build-scripts.js +222 -0
  30. package/dist/src/{configuration-files.js → entries/configuration-files.js} +52 -256
  31. package/dist/src/{convention-rows.js → entries/convention-rows.js} +170 -30
  32. package/dist/src/entries/conventions.js +740 -0
  33. package/dist/src/{html-entries.js → entries/html-entries.js} +12 -42
  34. package/dist/src/{mdx-entries.js → entries/mdx-entries.js} +5 -28
  35. package/dist/src/entries/run-directories.js +77 -0
  36. package/dist/src/entries/sources.js +144 -0
  37. package/dist/src/entries/static-module.js +670 -0
  38. package/dist/src/entries/test-runners.js +650 -0
  39. package/dist/src/entries/workflow-steps.js +345 -0
  40. package/dist/src/enum-group.js +3 -10
  41. package/dist/src/erased-stores.js +4 -6
  42. package/dist/src/exempt-classes.js +1 -63
  43. package/dist/src/exempt.js +21 -66
  44. package/dist/src/exposure.js +400 -0
  45. package/dist/src/extensions.js +37 -0
  46. package/dist/src/facts.js +38 -0
  47. package/dist/src/failure.js +36 -0
  48. package/dist/src/file-facts.js +3 -26
  49. package/dist/src/findings/completion.js +109 -56
  50. package/dist/src/findings/dependencies-and-module-machinery.js +4 -5
  51. package/dist/src/findings/emitters.js +27 -41
  52. package/dist/src/{implementations.js → findings/implementations.js} +3 -3
  53. package/dist/src/{in-operands.js → findings/in-operands.js} +3 -2
  54. package/dist/src/findings/interfaces.js +4 -5
  55. package/dist/src/findings/intra-function.js +16 -13
  56. package/dist/src/findings/non-code-artifacts.js +17 -12
  57. package/dist/src/findings/reads-and-writes.js +86 -27
  58. package/dist/src/findings/self-check.js +44 -30
  59. package/dist/src/findings/unused-declarations.js +29 -45
  60. package/dist/src/findings/visibility-narrowing.js +23 -31
  61. package/dist/src/findings-pass.js +13 -21
  62. package/dist/src/framework-lifecycle.js +46 -19
  63. package/dist/src/fs/document.js +52 -0
  64. package/dist/src/fs/manifest.js +67 -0
  65. package/dist/src/fs/tree.js +88 -0
  66. package/dist/src/generated-file.js +174 -28
  67. package/dist/src/git-ignore.js +39 -26
  68. package/dist/src/import-bindings.js +73 -28
  69. package/dist/src/index/sites.js +557 -0
  70. package/dist/src/index.js +2 -2
  71. package/dist/src/indexed-access.js +523 -478
  72. package/dist/src/injection-container.js +2 -2
  73. package/dist/src/interface-satisfaction.js +1 -1
  74. package/dist/src/intra-function-parts.js +63 -43
  75. package/dist/src/inventory/commonjs.js +507 -0
  76. package/dist/src/inventory/enumerate.js +167 -0
  77. package/dist/src/inventory/syntax.js +236 -0
  78. package/dist/src/inventory.js +323 -724
  79. package/dist/src/javascript-file.js +48 -0
  80. package/dist/src/json-document.js +198 -67
  81. package/dist/src/keyof-comparisons.js +126 -107
  82. package/dist/src/kinds.js +3 -366
  83. package/dist/src/{components.js → liveness/components.js} +2 -3
  84. package/dist/src/{graph.js → liveness/graph.js} +52 -28
  85. package/dist/src/liveness/matrix.js +99 -0
  86. package/dist/src/liveness/sweep.js +558 -0
  87. package/dist/src/load/classify.js +289 -0
  88. package/dist/src/load/diagnostics.js +87 -0
  89. package/dist/src/load/discover.js +285 -0
  90. package/dist/src/{emit-map.js → load/emit-map.js} +1 -1
  91. package/dist/src/load/expected-module.js +136 -0
  92. package/dist/src/load/load.js +27 -0
  93. package/dist/src/load/module-lookup.js +37 -0
  94. package/dist/src/load/package-scope.js +56 -0
  95. package/dist/src/load/plan.js +313 -0
  96. package/dist/src/load/specifiers.js +113 -0
  97. package/dist/src/load/synthesize.js +152 -0
  98. package/dist/src/load/test-globals.js +207 -0
  99. package/dist/src/load/test-joins.js +82 -0
  100. package/dist/src/{workspace-manifests.js → load/workspace-manifests.js} +4 -4
  101. package/dist/src/{workspace-programs.js → load/workspace-programs.js} +89 -66
  102. package/dist/src/{workspace-resolution.js → load/workspace-resolution.js} +24 -66
  103. package/dist/src/{workspace-run.js → load/workspace-run.js} +7 -7
  104. package/dist/src/{workspace.js → load/workspace.js} +62 -124
  105. package/dist/src/module-declarations.js +70 -85
  106. package/dist/src/overrides.js +134 -112
  107. package/dist/src/partial.js +2 -1
  108. package/dist/src/paths.js +82 -16
  109. package/dist/src/platform-calls.js +78 -0
  110. package/dist/src/platform-symbols.js +134 -0
  111. package/dist/src/position.js +43 -1
  112. package/dist/src/print.js +11 -79
  113. package/dist/src/product.js +13 -0
  114. package/dist/src/query.js +47 -0
  115. package/dist/src/ref.js +12 -20
  116. package/dist/src/references/read-rule.js +1 -0
  117. package/dist/src/references/read-rules.js +48 -0
  118. package/dist/src/references/sink.js +237 -0
  119. package/dist/src/references/sources.js +450 -0
  120. package/dist/src/references.js +117 -1074
  121. package/dist/src/report-schema.js +51 -0
  122. package/dist/src/report.js +57 -41
  123. package/dist/src/reporters/annotations.js +15 -8
  124. package/dist/src/reporters/sarif.js +16 -10
  125. package/dist/src/reporters/template.js +4 -19
  126. package/dist/src/resolve.js +246 -730
  127. package/dist/src/{configured-declarations.js → roots/configured-declarations.js} +22 -24
  128. package/dist/src/{entry-point-gaps.js → roots/entry-point-gaps.js} +6 -15
  129. package/dist/src/roots/manifest.js +216 -0
  130. package/dist/src/roots/published-reach.js +412 -0
  131. package/dist/src/roots/root-set.js +487 -0
  132. package/dist/src/roots/unseen-loads.js +236 -0
  133. package/dist/src/run.js +66 -77
  134. package/dist/src/schema.js +320 -343
  135. package/dist/src/scope.js +38 -115
  136. package/dist/src/serialization-contract.js +601 -22
  137. package/dist/src/session.js +37 -29
  138. package/dist/src/source-files.js +6 -10
  139. package/dist/src/stores.js +4 -2
  140. package/dist/src/suppress-file.js +25 -28
  141. package/dist/src/suppress-inline.js +36 -83
  142. package/dist/src/suppress.js +50 -71
  143. package/dist/src/symbol-keys.js +92 -88
  144. package/dist/src/template-field.js +9 -19
  145. package/dist/src/tests/file-class.js +76 -0
  146. package/dist/src/{outside-tests.js → tests/outside.js} +7 -7
  147. package/dist/src/{test-support.js → tests/support.js} +5 -12
  148. package/dist/src/text/compare.js +26 -0
  149. package/dist/src/text/glob.js +194 -0
  150. package/dist/src/text/named-files.js +298 -0
  151. package/dist/src/text/yaml.js +684 -0
  152. package/dist/src/type-errors.js +11 -232
  153. package/dist/src/type-parameter-reads.js +178 -139
  154. package/dist/src/unimplemented-callees.js +262 -242
  155. package/dist/src/unwrap.js +23 -0
  156. package/dist/src/usage.js +10 -0
  157. package/dist/src/vendor/unbash/ansi-c.js +132 -0
  158. package/dist/src/vendor/unbash/arithmetic-parts.js +37 -0
  159. package/dist/src/vendor/unbash/arithmetic.js +591 -0
  160. package/dist/src/vendor/unbash/assignment.js +131 -0
  161. package/dist/src/vendor/unbash/chars.js +48 -0
  162. package/dist/src/vendor/unbash/command.js +41 -0
  163. package/dist/src/vendor/unbash/expansion.js +80 -0
  164. package/dist/src/vendor/unbash/glob.js +268 -0
  165. package/dist/src/vendor/unbash/heredoc.js +27 -0
  166. package/dist/src/vendor/unbash/internal-types.js +1 -0
  167. package/dist/src/vendor/unbash/lexer.js +4274 -0
  168. package/dist/src/vendor/unbash/limits.js +3 -0
  169. package/dist/src/vendor/unbash/parser.js +1366 -0
  170. package/dist/src/vendor/unbash/parts.js +57 -0
  171. package/dist/src/vendor/unbash/substitution-context.js +8 -0
  172. package/dist/src/vendor/unbash/traversal.js +212 -0
  173. package/dist/src/vendor/unbash/types.js +1 -0
  174. package/dist/src/vendor/unbash/word-value.js +61 -0
  175. package/dist/src/vendor/unbash/word.js +40 -0
  176. package/dist/src/verbs/analyze.js +194 -127
  177. package/dist/src/verbs/describe.js +13 -18
  178. package/dist/src/verbs/explain.js +85 -139
  179. package/dist/src/verbs/print-config.js +2 -1
  180. package/dist/src/verbs/print-projects.js +6 -4
  181. package/dist/src/verbs/print-retained.js +7 -5
  182. package/dist/src/verbs/print-roots.js +4 -2
  183. package/dist/src/verbs/verb.js +1 -5
  184. package/dist/src/verbs/version.js +14 -3
  185. package/jsr.json +2 -1
  186. package/package.json +14 -8
  187. package/src/alias-chain.ts +2 -9
  188. package/src/amd.ts +130 -0
  189. package/src/analysis.ts +424 -650
  190. package/src/augmentations.ts +93 -4
  191. package/src/automatic-types.ts +12 -30
  192. package/src/bindings.ts +460 -0
  193. package/src/calls.ts +338 -46
  194. package/src/commands/held.ts +632 -0
  195. package/src/commands/read.ts +242 -0
  196. package/src/commands/shell.ts +228 -0
  197. package/src/commands/tools.ts +2382 -0
  198. package/src/component-files.ts +4 -2
  199. package/src/component-layer.ts +4 -2
  200. package/src/config.ts +31 -302
  201. package/src/conformance-record.ts +1 -1
  202. package/src/consumers.ts +16 -66
  203. package/src/contextual-uses.ts +66 -34
  204. package/src/contract/config.generated.ts +821 -0
  205. package/src/contract/contract.generated.ts +1452 -0
  206. package/src/contract/report.generated.ts +1241 -0
  207. package/src/dependencies.ts +222 -127
  208. package/src/destructuring.ts +1 -31
  209. package/src/edges.ts +41 -140
  210. package/src/element-access.ts +190 -187
  211. package/src/entries/build-scripts.ts +292 -0
  212. package/src/{configuration-files.ts → entries/configuration-files.ts} +68 -278
  213. package/src/{convention-rows.ts → entries/convention-rows.ts} +227 -31
  214. package/src/{conventions.ts → entries/conventions.ts} +367 -583
  215. package/src/{html-entries.ts → entries/html-entries.ts} +22 -48
  216. package/src/{mdx-entries.ts → entries/mdx-entries.ts} +7 -30
  217. package/src/entries/run-directories.ts +108 -0
  218. package/src/entries/sources.ts +266 -0
  219. package/src/entries/static-module.ts +858 -0
  220. package/src/entries/test-runners.ts +835 -0
  221. package/src/entries/workflow-steps.ts +432 -0
  222. package/src/enum-group.ts +2 -11
  223. package/src/erased-stores.ts +3 -7
  224. package/src/exempt-classes.ts +1 -75
  225. package/src/exempt.ts +70 -98
  226. package/src/exposure.ts +492 -0
  227. package/src/extensions.ts +45 -0
  228. package/src/facts.ts +46 -0
  229. package/src/failure.ts +63 -0
  230. package/src/file-facts.ts +15 -25
  231. package/src/finding.ts +10 -10
  232. package/src/findings/boundary.ts +11 -0
  233. package/src/findings/completion.ts +133 -64
  234. package/src/findings/dependencies-and-module-machinery.ts +4 -7
  235. package/src/findings/emitter.ts +9 -10
  236. package/src/findings/emitters.ts +38 -52
  237. package/src/{implementations.ts → findings/implementations.ts} +4 -4
  238. package/src/{in-operands.ts → findings/in-operands.ts} +4 -3
  239. package/src/findings/interfaces.ts +7 -9
  240. package/src/findings/intra-function.ts +16 -14
  241. package/src/findings/non-code-artifacts.ts +24 -15
  242. package/src/findings/reads-and-writes.ts +118 -41
  243. package/src/findings/self-check.ts +51 -38
  244. package/src/findings/unused-declarations.ts +31 -49
  245. package/src/findings/visibility-narrowing.ts +36 -40
  246. package/src/findings-pass.ts +15 -31
  247. package/src/framework-lifecycle.ts +47 -19
  248. package/src/fs/document.ts +70 -0
  249. package/src/fs/manifest.ts +96 -0
  250. package/src/fs/tree.ts +110 -0
  251. package/src/generated-file.ts +242 -35
  252. package/src/git-ignore.ts +50 -26
  253. package/src/host.ts +12 -5
  254. package/src/import-bindings.ts +98 -29
  255. package/src/index/sites.ts +781 -0
  256. package/src/index.ts +2 -2
  257. package/src/indexed-access.ts +570 -527
  258. package/src/injection-container.ts +2 -2
  259. package/src/interface-satisfaction.ts +2 -2
  260. package/src/intra-function-parts.ts +73 -44
  261. package/src/inventory/commonjs.ts +696 -0
  262. package/src/inventory/enumerate.ts +203 -0
  263. package/src/inventory/syntax.ts +311 -0
  264. package/src/inventory.ts +442 -895
  265. package/src/javascript-file.ts +54 -0
  266. package/src/json-document.ts +241 -76
  267. package/src/keyof-comparisons.ts +133 -122
  268. package/src/kinds.ts +5 -413
  269. package/src/{components.ts → liveness/components.ts} +4 -6
  270. package/src/{graph.ts → liveness/graph.ts} +100 -35
  271. package/src/liveness/matrix.ts +162 -0
  272. package/src/liveness/sweep.ts +855 -0
  273. package/src/load/classify.ts +433 -0
  274. package/src/load/diagnostics.ts +154 -0
  275. package/src/load/discover.ts +471 -0
  276. package/src/{emit-map.ts → load/emit-map.ts} +1 -1
  277. package/src/load/expected-module.ts +194 -0
  278. package/src/load/load.ts +73 -0
  279. package/src/load/module-lookup.ts +50 -0
  280. package/src/load/package-scope.ts +74 -0
  281. package/src/load/plan.ts +513 -0
  282. package/src/load/specifiers.ts +171 -0
  283. package/src/load/synthesize.ts +230 -0
  284. package/src/load/test-globals.ts +251 -0
  285. package/src/load/test-joins.ts +98 -0
  286. package/src/{workspace-manifests.ts → load/workspace-manifests.ts} +5 -5
  287. package/src/{workspace-programs.ts → load/workspace-programs.ts} +128 -85
  288. package/src/{workspace-resolution.ts → load/workspace-resolution.ts} +41 -77
  289. package/src/{workspace-run.ts → load/workspace-run.ts} +18 -16
  290. package/src/{workspace.ts → load/workspace.ts} +90 -134
  291. package/src/module-declarations.ts +74 -98
  292. package/src/overrides.ts +162 -134
  293. package/src/partial.ts +3 -2
  294. package/src/paths.ts +92 -16
  295. package/src/platform-calls.ts +119 -0
  296. package/src/platform-symbols.ts +189 -0
  297. package/src/position.ts +44 -1
  298. package/src/print.ts +12 -92
  299. package/src/product.ts +18 -0
  300. package/src/query.ts +92 -0
  301. package/src/ref.ts +12 -20
  302. package/src/references/read-rule.ts +60 -0
  303. package/src/references/read-rules.ts +55 -0
  304. package/src/references/sink.ts +314 -0
  305. package/src/references/sources.ts +632 -0
  306. package/src/references.ts +187 -1450
  307. package/src/report-schema.ts +68 -0
  308. package/src/report.ts +103 -226
  309. package/src/reporters/annotations.ts +22 -11
  310. package/src/reporters/json.ts +1 -1
  311. package/src/reporters/reporter.ts +2 -4
  312. package/src/reporters/reporters.ts +1 -1
  313. package/src/reporters/sarif.ts +29 -16
  314. package/src/reporters/template.ts +4 -20
  315. package/src/reporters/text.ts +3 -3
  316. package/src/resolve.ts +284 -1115
  317. package/src/{configured-declarations.ts → roots/configured-declarations.ts} +27 -29
  318. package/src/{entry-point-gaps.ts → roots/entry-point-gaps.ts} +7 -16
  319. package/src/roots/manifest.ts +303 -0
  320. package/src/roots/published-reach.ts +486 -0
  321. package/src/{roots.ts → roots/root-set.ts} +286 -469
  322. package/src/roots/unseen-loads.ts +345 -0
  323. package/src/run.ts +75 -91
  324. package/src/schema.ts +391 -388
  325. package/src/scope.ts +46 -138
  326. package/src/serialization-contract.ts +769 -23
  327. package/src/session.ts +87 -55
  328. package/src/source-files.ts +6 -11
  329. package/src/stores.ts +15 -3
  330. package/src/suppress-file.ts +24 -33
  331. package/src/suppress-inline.ts +55 -91
  332. package/src/suppress.ts +78 -79
  333. package/src/symbol-keys.ts +104 -107
  334. package/src/template-field.ts +15 -25
  335. package/src/tests/file-class.ts +135 -0
  336. package/src/{outside-tests.ts → tests/outside.ts} +16 -10
  337. package/src/{test-support.ts → tests/support.ts} +15 -21
  338. package/src/text/compare.ts +27 -0
  339. package/src/text/glob.ts +210 -0
  340. package/src/text/named-files.ts +388 -0
  341. package/src/text/yaml.ts +747 -0
  342. package/src/type-errors.ts +18 -288
  343. package/src/type-parameter-reads.ts +187 -158
  344. package/src/unimplemented-callees.ts +297 -280
  345. package/src/unwrap.ts +34 -0
  346. package/src/usage.ts +10 -0
  347. package/src/vendor/unbash/LICENSE +15 -0
  348. package/src/vendor/unbash/VENDORED.md +16 -0
  349. package/src/vendor/unbash/ansi-c.ts +132 -0
  350. package/src/vendor/unbash/arithmetic-parts.ts +53 -0
  351. package/src/vendor/unbash/arithmetic.ts +641 -0
  352. package/src/vendor/unbash/assignment.ts +163 -0
  353. package/src/vendor/unbash/chars.ts +48 -0
  354. package/src/vendor/unbash/command.ts +47 -0
  355. package/src/vendor/unbash/expansion.ts +144 -0
  356. package/src/vendor/unbash/glob.ts +284 -0
  357. package/src/vendor/unbash/heredoc.ts +34 -0
  358. package/src/vendor/unbash/internal-types.ts +94 -0
  359. package/src/vendor/unbash/lexer.ts +4352 -0
  360. package/src/vendor/unbash/limits.ts +3 -0
  361. package/src/vendor/unbash/parser.ts +1612 -0
  362. package/src/vendor/unbash/parts.ts +96 -0
  363. package/src/vendor/unbash/substitution-context.ts +20 -0
  364. package/src/vendor/unbash/traversal.ts +182 -0
  365. package/src/vendor/unbash/types.ts +660 -0
  366. package/src/vendor/unbash/word-value.ts +64 -0
  367. package/src/vendor/unbash/word.ts +50 -0
  368. package/src/verbs/analyze.ts +255 -164
  369. package/src/verbs/describe.ts +19 -17
  370. package/src/verbs/explain.ts +93 -169
  371. package/src/verbs/print-config.ts +2 -1
  372. package/src/verbs/print-projects.ts +6 -4
  373. package/src/verbs/print-retained.ts +7 -5
  374. package/src/verbs/print-roots.ts +4 -2
  375. package/src/verbs/verb.ts +2 -8
  376. package/src/verbs/version.ts +15 -3
  377. package/dist/src/base-url.js +0 -18
  378. package/dist/src/conventions.js +0 -937
  379. package/dist/src/discover.js +0 -468
  380. package/dist/src/entry-points.js +0 -529
  381. package/dist/src/glob.js +0 -65
  382. package/dist/src/manifest.js +0 -165
  383. package/dist/src/matrix.js +0 -246
  384. package/dist/src/pnpm-workspace.js +0 -120
  385. package/dist/src/roots.js +0 -672
  386. package/dist/src/setup-failure.js +0 -23
  387. package/dist/src/sweep.js +0 -224
  388. package/dist/src/test-joins.js +0 -101
  389. package/dist/src/version.js +0 -7
  390. package/dist/src/workflow-steps.js +0 -185
  391. package/src/base-url.ts +0 -24
  392. package/src/discover.ts +0 -653
  393. package/src/entry-points.ts +0 -687
  394. package/src/glob.ts +0 -67
  395. package/src/manifest.ts +0 -234
  396. package/src/matrix.ts +0 -423
  397. package/src/pnpm-workspace.ts +0 -135
  398. package/src/setup-failure.ts +0 -39
  399. package/src/sweep.ts +0 -347
  400. package/src/test-joins.ts +0 -120
  401. package/src/version.ts +0 -7
  402. package/src/workflow-steps.ts +0 -216
@@ -3,29 +3,20 @@
3
3
  * the code's row of the issue-kind vocabulary, and the dials that withhold a finding
4
4
  * together with every finding that falls with a root they withhold.
5
5
  */
6
- import { componentId } from "../components.js";
7
- import { deadComponents } from "../matrix.js";
8
- import { OUTSIDE } from "../graph.js";
6
+ import { CODE, FAMILY_KEY_LENGTH, KIND_ROWS, } from "../contract/contract.generated.js";
7
+ import { componentId } from "../liveness/components.js";
8
+ import { deadComponents } from "../liveness/sweep.js";
9
+ import { OUTSIDE } from "../liveness/graph.js";
9
10
  import { KINDS } from "../kinds.js";
10
11
  import { byPosition, positionKey } from "../position.js";
11
12
  import { declarationKey } from "../ref.js";
12
- import { FAMILY_KEY_LENGTH } from "../resolve.js";
13
13
  import { isPartSubject, isRowSubject } from "../suppress.js";
14
- /** The unused-file code, whose deletion removes every use its file writes. */
15
- const FILE_NEVER_IMPORTED = "DS1502";
16
14
  /**
17
- * The codes whose subject the run that counts test references holds live, as
18
- * finding.schema.json lists them, so a test file's candidate reported under one carries
19
- * none of a dead declaration's sweep facts.
15
+ * The codes whose subject the run that counts test references holds live, so a test
16
+ * file's candidate reported under one carries none of a dead declaration's sweep facts.
20
17
  */
21
- const LIVE_SUBJECT = new Set([
22
- "DS1101",
23
- "DS1102",
24
- "DS1104",
25
- "DS1204",
26
- "DS1301",
27
- ]);
28
- /** The fixability grammar/analysis.md "Fixability" gives a finding about a held declaration. */
18
+ const LIVE_SUBJECT = new Set(KIND_ROWS.filter((row) => row.holdsLive).map((row) => row.code));
19
+ /** The fixability grammar/analysis/fixability.md gives a finding about a held declaration. */
29
20
  const MANUAL = "manual";
30
21
  /** The member kinds an object property can declare, which an `in` expression tests by name. */
31
22
  const IN_TESTED = new Set([
@@ -50,8 +41,9 @@ function everyDeclaredLoaded(boundary) {
50
41
  * naming its family, else the code's default.
51
42
  */
52
43
  function severityOf(input, code, fallback) {
53
- const { config } = input;
54
- return (config.severity.get(code) ?? config.severity.get(code.slice(0, FAMILY_KEY_LENGTH)) ?? fallback);
44
+ const { severity } = input.config;
45
+ const key = [code, code.slice(0, FAMILY_KEY_LENGTH)].find((one) => Object.hasOwn(severity, one));
46
+ return key === undefined ? fallback : (severity[key] ?? fallback);
55
47
  }
56
48
  /**
57
49
  * The declarations the roots name as a library's published API, each public member of a
@@ -87,10 +79,13 @@ function testedByIn(input) {
87
79
  * published API, a public member of a published type included, is `certain` where the
88
80
  * run loaded every consumer the scope declared and declared one, `probable` where one did
89
81
  * not load, and `possible` where it declared none, whatever the configuration says of the
90
- * consumer set. A member an `in` expression tests by name is `possible`.
82
+ * consumer set. A member an `in` expression tests by name, one a function outside the
83
+ * analysis fills, and one {@link possiblyLoaded} names, is `possible`.
91
84
  */
92
- function reachabilityClasses(input) {
85
+ export function reachabilityClasses(input) {
93
86
  const tested = testedByIn(input);
87
+ const filled = input.boundary.filledOutside ?? new Set();
88
+ const possible = possiblyLoaded(input);
94
89
  const published = publishedIds(input.swept.matrix.union);
95
90
  const { declared } = input.boundary.consumers;
96
91
  const outside = declared.length === 0
@@ -99,7 +94,7 @@ function reachabilityClasses(input) {
99
94
  ? "certain"
100
95
  : "probable";
101
96
  return (id) => {
102
- if (tested.has(id)) {
97
+ if (tested.has(id) || filled.has(id) || possible.has(id)) {
103
98
  return "possible";
104
99
  }
105
100
  return published.has(id) ? outside : "certain";
@@ -130,9 +125,38 @@ function testCeilings(input, classOf) {
130
125
  ? testTargets(union, id).reduce((lowest, target) => capped(lowest, classOf(target)), "certain")
131
126
  : "certain";
132
127
  }
128
+ /**
129
+ * What only a bundler's retry of an import Node leaves unresolved names (program.38), and each
130
+ * dead declaration that reaches through dead declarations, as confidence.20 reads what only
131
+ * tests reach: each is dead only while no loader the analysis does not see loads the file.
132
+ */
133
+ function possiblyLoaded(input) {
134
+ const seeds = input.boundary.possiblyLoaded ?? new Set();
135
+ if (seeds.size === 0) {
136
+ return seeds;
137
+ }
138
+ const union = input.swept.matrix.union;
139
+ const dead = new Set(input.swept.sweep.candidates.map((one) => one.id));
140
+ const reached = new Set();
141
+ const pending = union.symbols.flatMap((symbol, at) => (seeds.has(symbol.id) ? [at] : []));
142
+ for (let at = pending.pop(); at !== undefined; at = pending.pop()) {
143
+ const symbol = union.symbols[at];
144
+ if (symbol === undefined || reached.has(symbol.id)) {
145
+ continue;
146
+ }
147
+ reached.add(symbol.id);
148
+ for (const edge of union.out[at] ?? []) {
149
+ const to = union.symbols[edge.to];
150
+ if (to !== undefined && dead.has(to.id)) {
151
+ pending.push(edge.to);
152
+ }
153
+ }
154
+ }
155
+ return reached;
156
+ }
133
157
  /**
134
158
  * The subjects dead only because production code only tests use is: each declaration the
135
- * sweep marks test-used, each `DS1502` file of such code, and each test of dead code every
159
+ * sweep marks test-used, each `DS1602` file of such code, and each test of dead code every
136
160
  * target of which is one. Nothing they hold references a dead declaration outside them, so
137
161
  * the rest of a component they share is reported without them.
138
162
  */
@@ -151,13 +175,16 @@ function testUsedSubjects(input) {
151
175
  }
152
176
  /**
153
177
  * The ceiling the roots the run found put on one dead subject: a subject other declarations
154
- * reference, found dead only because no root reaches them, is `probable` unless
155
- * the configuration declares the roots complete, because a root the analysis cannot see
156
- * would make it live; every other declaration has none below `certain`.
178
+ * reference, found dead only because no root reaches them, is `probable` unless the
179
+ * configuration declares the roots complete and no configuration holding the subject loads
180
+ * a module the analysis cannot resolve, because a root the analysis cannot see would make
181
+ * it live; every other declaration has none below `certain`.
157
182
  */
158
- function rootsCeiling(input, finding, candidate) {
183
+ function rootsCeiling(input, finding, candidate, configurations) {
159
184
  const unreachable = candidate?.relation === "reachability" || finding.unreachableOnly === true;
160
- return unreachable && !input.config.ts.rootsComplete ? "probable" : "certain";
185
+ const unseen = new Set((input.files.unseenLoads ?? []).map((load) => load.configuration));
186
+ const complete = input.config.ts.roots_complete && !configurations.some((one) => unseen.has(one));
187
+ return unreachable && !complete ? "probable" : "certain";
161
188
  }
162
189
  /**
163
190
  * The component each dead declaration of the run falls in, and none for a live one, with
@@ -170,8 +197,24 @@ function findingComponents(swept, components, cascade) {
170
197
  held.set(member, component);
171
198
  }
172
199
  }
200
+ const listed = membersListed(swept);
201
+ return (id) => {
202
+ const component = held.get(id);
203
+ return component === undefined
204
+ ? undefined
205
+ : {
206
+ id: component.id,
207
+ root: component.roots.includes(id),
208
+ symbolCount: component.members.length,
209
+ deletableLines: component.deletableLines,
210
+ ...(cascade === "full" ? { members: listed(component.members) } : {}),
211
+ };
212
+ };
213
+ }
214
+ /** The members of a component as the run lists them, positioned and in the canonical order. */
215
+ function membersListed(swept) {
173
216
  const symbols = new Map(swept.matrix.union.symbols.map((symbol) => [symbol.id, symbol]));
174
- const listed = (component) => component.members
217
+ return (members) => members
175
218
  .flatMap((member) => {
176
219
  const symbol = symbols.get(member);
177
220
  return symbol === undefined
@@ -188,27 +231,15 @@ function findingComponents(swept, components, cascade) {
188
231
  ];
189
232
  })
190
233
  .sort((a, b) => byPosition(a.position, b.position));
191
- return (id) => {
192
- const component = held.get(id);
193
- return component === undefined
194
- ? undefined
195
- : {
196
- id: component.id,
197
- root: component.roots.includes(id),
198
- symbolCount: component.members.length,
199
- deletableLines: component.deletableLines,
200
- ...(cascade === "full" ? { members: listed(component) } : {}),
201
- };
202
- };
203
234
  }
204
235
  /**
205
- * The run's dead components with each file a `DS1502` finding reports dead among them, so
236
+ * The run's dead components with each file a `DS1602` finding reports dead among them, so
206
237
  * the file's declarations fall with it, and with the components each subject that is no
207
238
  * declaration falls with joined into one.
208
239
  */
209
240
  function runComponents(swept, findings) {
210
241
  const union = swept.matrix.union;
211
- const reported = new Set(findings.filter((one) => one.code === FILE_NEVER_IMPORTED).map((one) => one.position.path));
242
+ const reported = new Set(findings.filter((one) => one.code === CODE.fileNeverImported).map((one) => one.position.path));
212
243
  const files = new Map(union.symbols.flatMap((symbol, at) => symbol.kind === "file" && reported.has(symbol.position.path) ? [[at, symbol]] : []));
213
244
  const computed = files.size === 0
214
245
  ? swept.sweep.components
@@ -267,6 +298,7 @@ export function completed(input, findings, kinds = KINDS) {
267
298
  const union = swept.matrix.union;
268
299
  const positions = new Map(union.symbols.map((symbol, at) => [declarationKey(symbol.ref, symbol.position.path), at]));
269
300
  const candidates = new Map(swept.sweep.candidates.map((candidate) => [candidate.id, candidate]));
301
+ const fileIds = new Map(union.symbols.flatMap((one) => (one.kind === "file" ? [[one.position.path, one.id]] : [])));
270
302
  const classOf = reachabilityClasses(input);
271
303
  const ceilingOf = testCeilings(input, classOf);
272
304
  const testUsed = testUsedSubjects(input);
@@ -277,11 +309,12 @@ export function completed(input, findings, kinds = KINDS) {
277
309
  let minted = computed;
278
310
  const dead = new Set(components.map((component) => component.id));
279
311
  const fallingWith = new Map();
280
- for (const { heldByTests } of swept.sweep.candidates) {
312
+ for (const { id, heldByTests } of swept.sweep.candidates) {
281
313
  if (heldByTests !== undefined) {
282
- fallingWith.set(heldByTests, (fallingWith.get(heldByTests) ?? 0) + 1);
314
+ fallingWith.set(heldByTests, [...(fallingWith.get(heldByTests) ?? []), id]);
283
315
  }
284
316
  }
317
+ const listed = membersListed(swept);
285
318
  const done = findings.map((finding) => {
286
319
  const row = kinds.get(finding.code);
287
320
  if (row === undefined) {
@@ -307,7 +340,7 @@ export function completed(input, findings, kinds = KINDS) {
307
340
  : candidates.get(judged.id);
308
341
  const fallsWith = finding.fallsWith?.[0];
309
342
  const joined = fallsWith === undefined ? undefined : componentOf(fallsWith);
310
- const file = finding.code === FILE_NEVER_IMPORTED ? files.get(finding.position.path) : undefined;
343
+ const file = finding.code === CODE.fileNeverImported ? files.get(finding.position.path) : undefined;
311
344
  const found = joined !== undefined
312
345
  ? { ...joined, root: false }
313
346
  : file !== undefined
@@ -326,22 +359,45 @@ export function completed(input, findings, kinds = KINDS) {
326
359
  let component = found;
327
360
  if (component === undefined) {
328
361
  minted += 1;
362
+ const falling = symbol?.kind === "interface" ? fallingWith.get(symbol.id) : undefined;
329
363
  component = {
330
364
  id: componentId(minted),
331
365
  root: true,
332
- symbolCount: symbol?.kind === "interface" ? (fallingWith.get(symbol.id) ?? 1) : 1,
366
+ symbolCount: falling?.length ?? 1,
333
367
  deletableLines: 0,
368
+ ...(input.config.reporters.cascade !== "full"
369
+ ? {}
370
+ : falling === undefined
371
+ ? {
372
+ members: [
373
+ {
374
+ ref: finding.symbol.ref,
375
+ name: finding.symbol.name,
376
+ position: finding.position,
377
+ },
378
+ ],
379
+ }
380
+ : { members: listed(falling) }),
334
381
  };
335
382
  }
336
383
  const counts = candidate === undefined
337
384
  ? union.made[at]
338
385
  : { production: candidate.productionRefs, test: candidate.testRefs };
339
- const ownClass = judged === undefined ? (finding.reachabilityClass ?? "certain") : classOf(judged.id);
386
+ const ownClass = judged !== undefined
387
+ ? classOf(judged.id)
388
+ : (finding.reachabilityClass ??
389
+ (finding.code === CODE.fileNeverImported
390
+ ? classOf(fileIds.get(finding.position.path) ?? "")
391
+ : "certain"));
340
392
  const used = judged !== undefined
341
393
  ? candidate !== undefined && testUsed.declarations.has(judged.id)
342
- : finding.code === FILE_NEVER_IMPORTED && testUsed.files.has(finding.position.path);
394
+ : finding.code === CODE.fileNeverImported && testUsed.files.has(finding.position.path);
343
395
  const reachabilityClass = used && candidate?.testOfDeadCode !== true ? "possible" : ownClass;
344
- const untested = capped(capped(capped(ownClass, row.maxClass), rootsCeiling(input, finding, candidate)), judged === undefined ? "certain" : ceilingOf(judged.id));
396
+ const configurations = candidate?.configurations ??
397
+ (judged === undefined && !part
398
+ ? swept.matrix.configurations
399
+ : (swept.matrix.heldIn[at] ?? swept.matrix.configurations));
400
+ const untested = capped(capped(capped(ownClass, row.maxClass), rootsCeiling(input, finding, candidate, configurations)), judged === undefined ? "certain" : ceilingOf(judged.id));
345
401
  const generated = input.files.generated?.has(finding.position.path) === true;
346
402
  const fixability = generated
347
403
  ? "none"
@@ -355,7 +411,7 @@ export function completed(input, findings, kinds = KINDS) {
355
411
  ? undefined
356
412
  : candidate !== undefined
357
413
  ? input.dependencies.lastUses.get(candidate.id)
358
- : finding.code === FILE_NEVER_IMPORTED
414
+ : finding.code === CODE.fileNeverImported
359
415
  ? input.dependencies.fileLastUses.get(finding.position.path)
360
416
  : undefined;
361
417
  return {
@@ -372,10 +428,7 @@ export function completed(input, findings, kinds = KINDS) {
372
428
  generated,
373
429
  component,
374
430
  retainedBy: [],
375
- configurations: candidate?.configurations ??
376
- (judged === undefined && !part
377
- ? swept.matrix.configurations
378
- : (swept.matrix.heldIn[at] ?? swept.matrix.configurations)),
431
+ configurations,
379
432
  consumersLoaded: input.boundary.consumers.loaded,
380
433
  fixability,
381
434
  severity: severityOf(input, finding.code, row.defaultSeverity),
@@ -431,7 +484,7 @@ function dialed(finding, minConfidence) {
431
484
  * root withholds itself alone.
432
485
  */
433
486
  export function dialsOf(input, findings) {
434
- const minConfidence = input.config.analysis.minConfidence;
487
+ const minConfidence = input.config.analysis.min_confidence;
435
488
  const components = new Set(findings
436
489
  .filter((finding) => finding.component.root &&
437
490
  dialed({ ...finding, confidence: componentConfidenceOf(finding) }, minConfidence))
@@ -1,8 +1,7 @@
1
+ import { CODE } from "../contract/contract.generated.js";
1
2
  import { declarationKey } from "../dependencies.js";
2
3
  import { renderRef } from "../ref.js";
3
4
  import { nonCodeArtifacts } from "./non-code-artifacts.js";
4
- const UNUSED_DEPENDENCY = "DS1601";
5
- const FILE_NEVER_IMPORTED = "DS1502";
6
5
  const MESSAGES = {
7
6
  dependency: "no import in the target needs the declared dependency",
8
7
  "dev-dependency": "no import in the target needs the declared development dependency",
@@ -25,7 +24,7 @@ function deadCode(input) {
25
24
  const reachedOnly = new Set(swept.sweep.candidates.filter((one) => one.relation === "reachability").map((one) => one.id));
26
25
  for (const finding of nonCodeArtifacts(input)) {
27
26
  const id = files.get(finding.position.path);
28
- if (finding.code === FILE_NEVER_IMPORTED && id !== undefined) {
27
+ if (finding.code === CODE.fileNeverImported && id !== undefined) {
29
28
  dead.add(id);
30
29
  if (finding.unreachableOnly === true) {
31
30
  reachedOnly.add(id);
@@ -57,7 +56,7 @@ function unusedDependencies(input, dependencies) {
57
56
  const atPossible = unbuilt || users?.some((id) => published.has(id)) === true;
58
57
  return [
59
58
  {
60
- code: UNUSED_DEPENDENCY,
59
+ code: CODE.unusedDependency,
61
60
  position: dependency.position,
62
61
  symbol: {
63
62
  ref: renderRef(dependency.manifest, {
@@ -80,5 +79,5 @@ function unusedDependencies(input, dependencies) {
80
79
  ];
81
80
  });
82
81
  }
83
- /** The findings of the dependencies-and-module-machinery family, `DS1600` to `DS1699`. */
82
+ /** The findings of the dependencies family, `DS1700` to `DS1799`. */
84
83
  export const dependenciesAndModuleMachinery = (input) => unusedDependencies(input, input.dependencies);
@@ -1,5 +1,4 @@
1
1
  import { evaluateEdges } from "../edges.js";
2
- import { liveFilesAt } from "../matrix.js";
3
2
  import { declarationKey } from "../ref.js";
4
3
  import { ledgerOf } from "../suppress.js";
5
4
  import { insideSkipped } from "../type-errors.js";
@@ -8,11 +7,11 @@ import { dependenciesAndModuleMachinery } from "./dependencies-and-module-machin
8
7
  import { interfaces } from "./interfaces.js";
9
8
  import { intraFunction } from "./intra-function.js";
10
9
  import { nonCodeArtifacts } from "./non-code-artifacts.js";
11
- import { readsAndWrites } from "./reads-and-writes.js";
10
+ import { fallingWithWrites, readsAndWrites } from "./reads-and-writes.js";
12
11
  import { selfCheck } from "./self-check.js";
13
12
  import { fallenMembers, unusedDeclarations } from "./unused-declarations.js";
14
13
  import { visibilityNarrowing } from "./visibility-narrowing.js";
15
- /** Every kind family this analyzer reports, each by its emitter, in code order. */
14
+ /** Every emitter this analyzer runs, by the name its tests select it by. */
16
15
  export const EMITTERS = new Map([
17
16
  ["unused-declarations", unusedDeclarations],
18
17
  ["visibility-narrowing", visibilityNarrowing],
@@ -23,37 +22,25 @@ export const EMITTERS = new Map([
23
22
  ["self-check", selfCheck],
24
23
  ["intra-function", intraFunction],
25
24
  ]);
26
- /**
27
- * The keys of every declaration an unanswered question could have kept live, which the run
28
- * reports nothing about: a finding about one would be computed from the gap.
29
- */
30
- function heldKeys(input) {
31
- const held = new Set(input.swept.heldByUnanswered);
32
- if (held.size === 0) {
33
- return held;
34
- }
25
+ /** The keys of the declarations the identifiers name, as {@link findingKey} keys a finding. */
26
+ function keysOf(input, ids) {
27
+ const named = new Set(ids);
35
28
  return new Set(input.swept.matrix.union.symbols
36
- .filter((symbol) => held.has(symbol.id))
29
+ .filter((symbol) => named.has(symbol.id))
37
30
  .map((symbol) => declarationKey(symbol.ref, symbol.position.path)));
38
31
  }
32
+ /** The key of the declaration a finding is about, or of the one holding the part it is about. */
33
+ function findingKey(finding) {
34
+ return declarationKey(finding.symbol.holder ?? finding.symbol.ref, finding.position.path);
35
+ }
39
36
  /**
40
- * The keys of every top-level declaration of a live component file. The file's
41
- * markup may use each of them, which no analysis of the markup can rule out, so the run
42
- * reports nothing about one while the file is live.
37
+ * Every emitter's findings over one sweep, and those of any further emitter, completed by
38
+ * one step, but none about a declaration that falls with a write-only subject: that
39
+ * subject's finding names it, so no finding about it exists for a record to match.
43
40
  */
44
- function markupKeys(input) {
45
- const { swept } = input;
46
- if (swept.componentFiles.length === 0) {
47
- return new Set();
48
- }
49
- const live = new Set(liveFilesAt(swept.matrix, swept.sweep, new Set(swept.componentFiles)).map((symbol) => symbol.id));
50
- return new Set(swept.matrix.union.symbols
51
- .filter((symbol) => live.has(symbol.parent))
52
- .map((symbol) => declarationKey(symbol.ref, symbol.position.path)));
53
- }
54
- /** Every family's findings over one sweep, and those of any further emitter, completed by one step. */
55
41
  function completedOver(input, ...more) {
56
- return completed(input, [...EMITTERS.values(), ...more].flatMap((emit) => emit(input)));
42
+ const falls = keysOf(input, fallingWithWrites(input));
43
+ return completed(input, [...EMITTERS.values(), ...more].flatMap((emit) => emit(input))).filter((finding) => !falls.has(findingKey(finding)));
57
44
  }
58
45
  /**
59
46
  * The dials over the findings a record could name, each read against the sweep that
@@ -70,8 +57,8 @@ function dialsOver(input, found, suppressed, unmarked) {
70
57
  }
71
58
  /**
72
59
  * Every finding of one run swept under its suppressions' marks, decided in one pass: each
73
- * family's findings completed by one step, so every component number is minted once, the
74
- * finding each record claims withheld, the rest withheld by the dials, so a root one family
60
+ * emitter's findings completed by one step, so every component number is minted once, the
61
+ * finding each record claims withheld, the rest withheld by the dials, so a root one emitter
75
62
  * reports withholds what another reports in its component, and every declared edge
76
63
  * evaluated over what remains, so a pending finding is in its evaluation alone.
77
64
  */
@@ -86,7 +73,7 @@ function atPossible(input) {
86
73
  const { config } = input;
87
74
  return {
88
75
  ...input,
89
- config: { ...config, analysis: { ...config.analysis, minConfidence: "possible" } },
76
+ config: { ...config, analysis: { ...config.analysis, min_confidence: "possible" } },
90
77
  };
91
78
  }
92
79
  /**
@@ -96,16 +83,15 @@ function atPossible(input) {
96
83
  */
97
84
  function dialledOver(input, suppressed, found, unmarked) {
98
85
  const would = [...unmarked, ...found];
99
- const ledger = ledgerOf(suppressed.records, would, dialsOver(input, found, suppressed, unmarked));
100
- const unanswered = heldKeys(input);
101
- const markup = markupKeys(input);
102
- const candidates = found.filter((finding) => {
103
- const key = declarationKey(finding.symbol.holder ?? finding.symbol.ref, finding.position.path);
104
- return (!ledger.withheld(finding) &&
105
- !unanswered.has(key) &&
106
- !markup.has(key) &&
107
- !insideSkipped(input.swept.skipped, finding.position));
108
- });
86
+ const { sweep } = input.swept;
87
+ // A hold is a gap of the analysis, which leaves a record it touches dormant; a live
88
+ // component file's markup is no gap, so a record on one of its bindings stays in effect.
89
+ const unanswered = keysOf(input, sweep.held);
90
+ const markup = keysOf(input, sweep.bindings);
91
+ const heldIds = new Set(sweep.held);
92
+ const held = (finding) => unanswered.has(findingKey(finding)) || insideSkipped(input.swept.skipped, finding.position);
93
+ const ledger = ledgerOf(suppressed.records, would, dialsOver(input, found, suppressed, unmarked), { withholds: held, holdsRecord: (record) => heldIds.has(record.bound) });
94
+ const candidates = found.filter((finding) => !ledger.withheld(finding) && !held(finding) && !markup.has(findingKey(finding)));
109
95
  const kept = reportable(input, candidates);
110
96
  const evaluated = evaluateEdges(kept, input.boundary.edges, input.swept.matrix.union.symbols);
111
97
  return {
@@ -7,9 +7,9 @@
7
7
  */
8
8
  import { isClassDeclaration, isHeritageClause, isInterfaceDeclaration, isMethodDeclaration, SyntaxKind, } from "@typescript/native/ast";
9
9
  import { SymbolFlags } from "@typescript/native/sync";
10
- import { aliasChains } from "./alias-chain.js";
11
- import { nodeKey } from "./inventory.js";
12
- import { must, Unanswerable } from "./query.js";
10
+ import { aliasChains } from "../alias-chain.js";
11
+ import { nodeKey } from "../inventory.js";
12
+ import { must, Unanswerable } from "../query.js";
13
13
  /** The interfaces, the classes and the `implements` entries of one project's own files. */
14
14
  function walk(project, held) {
15
15
  const interfaces = [];
@@ -4,7 +4,8 @@
4
4
  * links the read to a declaration, so only a text match can tell which member it reads.
5
5
  */
6
6
  import { isBinaryExpression, isNoSubstitutionTemplateLiteral, isStringLiteral, SyntaxKind, } from "@typescript/native/ast";
7
- import { sourceFilesOf } from "./source-files.js";
7
+ import { sourceFilesOf } from "../source-files.js";
8
+ import { bytewise } from "../text/compare.js";
8
9
  /**
9
10
  * The text of each string literal, or template literal with no substitution, written as
10
11
  * the left operand of an `in` expression in a file of the project that is no test file.
@@ -26,5 +27,5 @@ export function inOperandNames(project, targetRoot, testFiles) {
26
27
  file.forEachChild(visit);
27
28
  }
28
29
  }
29
- return [...found].sort();
30
+ return [...found].sort(bytewise);
30
31
  }
@@ -1,6 +1,5 @@
1
+ import { CODE } from "../contract/contract.generated.js";
1
2
  import { byPosition } from "../position.js";
2
- const UNUSED_INTERFACE = "DS1201";
3
- const UNCALLED_INTERFACE_METHOD = "DS1203";
4
3
  /** What each finding says, by what the sweep found about the subject's references. */
5
4
  const UNUSED_MESSAGE = "nothing in the target names the interface as a type";
6
5
  const UNUSED_DEAD_MESSAGE = "the interface is named as a type only from declarations that are themselves dead";
@@ -45,7 +44,7 @@ function findingOf(code, symbol, message, implementations) {
45
44
  }
46
45
  /**
47
46
  * The findings of the interfaces family, `DS1200` to `DS1299`: `DS1201`, a dead
48
- * interface, whose members fall with it unreported; and `DS1203`, a method of a live
47
+ * interface, whose members fall with it unreported; and `DS1202`, a method of a live
49
48
  * interface no reference names, unless it is a marker, a method whose every
50
49
  * implementation has an empty body. A test file's declaration is neither kind's subject,
51
50
  * because a production sweep counts none of the references it can have, save an interface
@@ -60,7 +59,7 @@ export const interfaces = (input) => {
60
59
  continue;
61
60
  }
62
61
  if (symbol.kind === "interface") {
63
- found.push(findingOf(UNUSED_INTERFACE, symbol, unusedMessage(candidate), run.implementationsOf(candidate.id)));
62
+ found.push(findingOf(CODE.unusedInterface, symbol, unusedMessage(candidate), run.implementationsOf(candidate.id)));
64
63
  continue;
65
64
  }
66
65
  if (symbol.kind !== "interface-method" ||
@@ -69,7 +68,7 @@ export const interfaces = (input) => {
69
68
  marker(input, candidate.id)) {
70
69
  continue;
71
70
  }
72
- found.push(findingOf(UNCALLED_INTERFACE_METHOD, symbol, UNCALLED_MESSAGE, run.implementationsOf(symbol.parent)));
71
+ found.push(findingOf(CODE.uncalledInterfaceMethod, symbol, UNCALLED_MESSAGE, run.implementationsOf(symbol.parent)));
73
72
  }
74
73
  return found;
75
74
  };
@@ -1,7 +1,8 @@
1
+ import { CODE } from "../contract/contract.generated.js";
1
2
  import { KINDS } from "../kinds.js";
2
3
  import { parameterRef } from "../ref.js";
3
- import { UNUSED_PARAMETER, UNUSED_RESULT } from "../intra-function-parts.js";
4
- import { reachedWithTheTests } from "../sweep.js";
4
+ import {} from "../intra-function-parts.js";
5
+ import { reachedWithTheTests } from "../liveness/sweep.js";
5
6
  /** A list of rules as a sentence names them. */
6
7
  function spelled(rules) {
7
8
  if (rules.length < 2) {
@@ -28,7 +29,8 @@ function overlapClause(overlap, part) {
28
29
  * caller may pass a function used as a value more arguments than it declares, so there one
29
30
  * a read parameter follows is renamed to an underscore name, which the compilers read as
30
31
  * declared unread, and one no read parameter follows is deleted: kept where the call's
31
- * inference may read its annotation, at `probable` where nothing reads the annotation.
32
+ * inference may read its annotation, at `probable` where nothing reads the annotation or
33
+ * where it is a name a contextually typed object pattern binds.
32
34
  */
33
35
  function parameterVerdict(part, free, freeButValued) {
34
36
  const place = part.parameter;
@@ -45,7 +47,8 @@ function parameterVerdict(part, free, freeButValued) {
45
47
  if (place?.annotated === "steers") {
46
48
  return undefined;
47
49
  }
48
- return { fix: "delete", confidence: place?.annotated === "free" ? "probable" : "certain" };
50
+ const unseen = place?.annotated === "free" || place?.contextualPattern === true;
51
+ return { fix: "delete", confidence: unseen ? "probable" : "certain" };
49
52
  }
50
53
  /**
51
54
  * Whether one part is reported. A parameter needs its function's signature free to
@@ -60,9 +63,9 @@ function reported(input, part, callersUnknown) {
60
63
  }
61
64
  const { free, freeButValued, discardedEverywhere } = input.intraFunction;
62
65
  switch (part.code) {
63
- case UNUSED_PARAMETER:
66
+ case CODE.unusedParameter:
64
67
  return parameterVerdict(part, free, freeButValued) !== undefined;
65
- case UNUSED_RESULT:
68
+ case CODE.unusedResult:
66
69
  return (free.has(part.declaration) &&
67
70
  discardedEverywhere.has(part.declaration) &&
68
71
  !callersUnknown.has(part.declaration));
@@ -71,7 +74,7 @@ function reported(input, part, callersUnknown) {
71
74
  }
72
75
  }
73
76
  /**
74
- * The findings of the intra-function family, `DS1800` to `DS1899`, each about a part of
77
+ * The findings of the inside-functions family, `DS1401` to `DS1406`, each about a part of
75
78
  * the declaration its reference names, at the part's own position, whatever the sweep
76
79
  * decided about a production declaration. A part of test code is reported only where the
77
80
  * run that counts test references reaches its declaration and that is no test of dead
@@ -81,8 +84,8 @@ export const intraFunction = (input) => {
81
84
  const union = input.swept.matrix.union;
82
85
  const byId = new Map(union.symbols.map((symbol) => [symbol.id, symbol]));
83
86
  const reached = reachedWithTheTests(union, [
84
- ...input.swept.exempt.map((record) => record.id),
85
- ...input.swept.heldByUnanswered,
87
+ ...input.swept.sweep.exempt.map((record) => record.id),
88
+ ...input.swept.sweep.held,
86
89
  ]);
87
90
  const testsOfDeadCode = new Set(input.swept.sweep.candidates.filter((one) => one.testOfDeadCode).map((one) => one.id));
88
91
  const judged = (id) => {
@@ -95,7 +98,7 @@ export const intraFunction = (input) => {
95
98
  return symbol === undefined ? [] : [symbol.id];
96
99
  }));
97
100
  const { declared, loaded } = input.boundary.consumers;
98
- const closed = input.config.consumersComplete && declared.every((id) => loaded.includes(id));
101
+ const closed = input.config.consumers.complete && declared.every((id) => loaded.includes(id));
99
102
  const published = (id) => {
100
103
  const symbol = byId.get(id);
101
104
  return (symbol !== undefined &&
@@ -112,11 +115,11 @@ export const intraFunction = (input) => {
112
115
  const found = [];
113
116
  for (const part of input.intraFunction.parts) {
114
117
  const declaration = byId.get(part.declaration);
115
- const overlap = KINDS.get(part.code)?.overlap ?? [];
118
+ const overlap = KINDS.get(part.code)?.overlap?.ts ?? [];
116
119
  if (declaration === undefined || !judged(declaration.id) || !reported(input, part, unknown)) {
117
120
  continue;
118
121
  }
119
- const verdict = part.code === UNUSED_PARAMETER
122
+ const verdict = part.code === CODE.unusedParameter
120
123
  ? parameterVerdict(part, input.intraFunction.free, input.intraFunction.freeButValued)
121
124
  : undefined;
122
125
  const message = verdict?.fix === "rename"
@@ -126,7 +129,7 @@ export const intraFunction = (input) => {
126
129
  code: part.code,
127
130
  position: part.position,
128
131
  symbol: {
129
- ...(part.code === UNUSED_PARAMETER
132
+ ...(part.code === CODE.unusedParameter
130
133
  ? { ref: parameterRef(declaration.ref, part.name), holder: declaration.ref }
131
134
  : { ref: declaration.ref }),
132
135
  kind: part.kind,