@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
@@ -1,21 +1,26 @@
1
+ import { CODE } from "../contract/contract.generated.ts";
1
2
  import type { Finding, FindingDetails, FindingPosition } from "../finding.ts";
2
- import type { InventorySymbol } from "../inventory.ts";
3
- import type { MatrixCandidate } from "../matrix.ts";
3
+ import { WORDS, type InventorySymbol } from "../inventory.ts";
4
+ import type { Candidate } from "../liveness/sweep.ts";
4
5
  import { positionKey } from "../position.ts";
5
6
  import { declarationKey } from "../ref.ts";
7
+ import { reachabilityClasses } from "./completion.ts";
6
8
  import type { Emitter, EmitterInput } from "./emitter.ts";
7
9
 
8
- /** The codes of this family. */
9
- type ReadsAndWritesCode = "DS1301" | "DS1302" | "DS1303";
10
+ import { bytewise } from "../text/compare.ts";
10
11
 
11
- /** The containers whose type parameters `DS1303` reports: a function and a class method. */
12
- const SIGNATURES: ReadonlySet<string> = new Set(["function", "method"]);
12
+ /** The codes this emitter reports. */
13
+ type ReadsAndWritesCode =
14
+ typeof CODE.writeOnlySymbol | typeof CODE.unusedEnumMember | typeof CODE.unusedTypeParameter;
13
15
 
14
- /** What the family reads of one run, indexed by declaration. */
16
+ /** The containers whose type parameters `DS1006` reports: a function, a class method and a type alias. */
17
+ const SIGNATURES: ReadonlySet<string> = new Set(["function", "method", "type"]);
18
+
19
+ /** What this emitter reads of one run, indexed by declaration. */
15
20
  interface Run {
16
21
  readonly input: EmitterInput;
17
22
  readonly symbols: ReadonlyMap<string, InventorySymbol>;
18
- readonly candidates: ReadonlyMap<string, MatrixCandidate>;
23
+ readonly candidates: ReadonlyMap<string, Candidate>;
19
24
  }
20
25
 
21
26
  function indexed(input: EmitterInput): Run {
@@ -109,19 +114,16 @@ function parametersOnlyNamedBy(
109
114
  }
110
115
 
111
116
  /** What one write-only finding says, the declarations its deletion takes with it included. */
112
- function writeOnlyMessage(
113
- run: Run,
114
- namedBy: ReadonlyMap<string, ReadonlySet<string>>,
115
- symbol: InventorySymbol,
116
- held: Uses,
117
- ): string {
117
+ function writeOnlyMessage(run: Run, written: Written, subject: Subject): string {
118
+ const { symbol, held } = subject;
118
119
  const writes = held.writes.length === 1 ? "once" : `at ${String(held.writes.length)} positions`;
119
120
  const read = run.input.stores.readInTests.has(symbol.id)
120
121
  ? "read only from test files"
121
122
  : "never read";
122
123
  const cascade = [
123
- ...parametersOnlyNamedBy(run, namedBy, symbol).map((name) => `type parameter ${name}`),
124
- ...[...held.alone].sort().map((name) => `import ${name}`),
124
+ ...parametersOnlyNamedBy(run, written.namedBy, symbol).map((name) => `type parameter ${name}`),
125
+ ...[...held.alone].sort(bytewise).map((name) => `import ${name}`),
126
+ ...(written.named.get(symbol.id) ?? []),
125
127
  ];
126
128
  const word = SUBJECT_WORDS[symbol.kind] ?? "member";
127
129
  const message = `${word} ${symbol.name} is written ${writes} and ${read}`;
@@ -130,17 +132,55 @@ function writeOnlyMessage(
130
132
  : `${message}, and deleting it with its writes deletes ${cascade.join(" and ")} too`;
131
133
  }
132
134
 
135
+ /** One declaration the write-only kind reports, with its uses. */
136
+ interface Subject {
137
+ readonly symbol: InventorySymbol;
138
+ readonly held: Uses;
139
+ }
140
+
133
141
  /**
134
- * `DS1301`: a module-level variable, a type member or a class member the counted
135
- * references store into and never read, named with every position written.
142
+ * What the write-only kind answers of one run: its subjects in site order, and the
143
+ * declarations that fall with them, each named under the innermost subject of every chain
144
+ * of carriers its references hold.
145
+ */
146
+ interface Written {
147
+ readonly subjects: readonly Subject[];
148
+ readonly namedBy: ReadonlyMap<string, ReadonlySet<string>>;
149
+ readonly named: ReadonlyMap<string, readonly string[]>;
150
+ readonly falls: ReadonlySet<string>;
151
+ }
152
+
153
+ /**
154
+ * The kinds of declaration that fall with a write-only subject: a declaration of its own.
155
+ * A member falls with its container, and a type parameter is the type-parameter clause's.
156
+ */
157
+ const FALLING: ReadonlySet<InventorySymbol["kind"]> = new Set([
158
+ "function",
159
+ "class",
160
+ "interface",
161
+ "type",
162
+ "enum",
163
+ "namespace",
164
+ "variable",
165
+ ]);
166
+
167
+ const WRITTEN = new WeakMap<EmitterInput, Written>();
168
+
169
+ /**
170
+ * `DS1301`'s subjects: a module-level variable, a type member or a class member the
171
+ * counted references store into and never read.
136
172
  *
137
173
  * The subject is a live declaration: a store is a reference, so the sweep holds a
138
174
  * written one live and its candidates are never this kind's. Every reference that is
139
175
  * not a store reads, and so does an exemption record naming the declaration.
140
176
  */
141
- function writeOnlySymbols(run: Run): readonly Finding[] {
177
+ function writtenOf(run: Run): Written {
178
+ const known = WRITTEN.get(run.input);
179
+ if (known !== undefined) {
180
+ return known;
181
+ }
142
182
  const { stores } = run.input;
143
- const { matrix } = run.input.swept;
183
+ const { matrix, sweep } = run.input.swept;
144
184
  const uses = new Map<string, Uses>();
145
185
  for (const reference of stores.references) {
146
186
  let held = uses.get(reference.to);
@@ -171,26 +211,54 @@ function writeOnlySymbols(run: Run): readonly Finding[] {
171
211
  }
172
212
  }
173
213
 
174
- const found: Finding[] = [];
175
- for (const symbol of matrix.union.symbols) {
214
+ const subjects = matrix.union.symbols.flatMap((symbol): Subject[] => {
176
215
  const held = uses.get(symbol.id);
177
- if (
178
- held === undefined ||
216
+ return held === undefined ||
179
217
  held.writes.length === 0 ||
180
218
  held.reads > 0 ||
181
219
  !writable(run, symbol) ||
182
220
  stores.exempt.has(symbol.id) ||
183
221
  run.candidates.has(symbol.id)
222
+ ? []
223
+ : [{ symbol, held }];
224
+ });
225
+ const subjectIds = new Set(subjects.map((subject) => subject.symbol.id));
226
+ const classOf = reachabilityClasses(run.input);
227
+ const named = new Map<string, string[]>();
228
+ const falls = new Set<string>();
229
+ for (const symbol of matrix.union.symbols) {
230
+ const chains = sweep.carried.get(symbol.id);
231
+ if (
232
+ chains === undefined ||
233
+ subjectIds.has(symbol.id) ||
234
+ !FALLING.has(symbol.kind) ||
235
+ classOf(symbol.id) !== "certain"
184
236
  ) {
185
237
  continue;
186
238
  }
187
- found.push(
188
- findingAbout(symbol, "DS1301", writeOnlyMessage(run, namedBy, symbol, held), {
189
- writePositions: held.writes,
190
- }),
191
- );
239
+ const innermost = chains.map((chain) => chain.find((id) => subjectIds.has(id)));
240
+ if (innermost.includes(undefined)) {
241
+ continue;
242
+ }
243
+ falls.add(symbol.id);
244
+ for (const subject of new Set(innermost)) {
245
+ const name = `${WORDS[symbol.kind]} ${symbol.name}`;
246
+ named.set(subject ?? "", [...(named.get(subject ?? "") ?? []), name]);
247
+ }
192
248
  }
193
- return found;
249
+ const written = { subjects, namedBy, named, falls };
250
+ WRITTEN.set(run.input, written);
251
+ return written;
252
+ }
253
+
254
+ /** `DS1301`: each subject, named with every position written and what falls with it. */
255
+ function writeOnlySymbols(run: Run): readonly Finding[] {
256
+ const written = writtenOf(run);
257
+ return written.subjects.map((subject) =>
258
+ findingAbout(subject.symbol, CODE.writeOnlySymbol, writeOnlyMessage(run, written, subject), {
259
+ writePositions: subject.held.writes,
260
+ }),
261
+ );
194
262
  }
195
263
 
196
264
  /**
@@ -214,21 +282,22 @@ function unnamed(run: Run, kind: InventorySymbol["kind"]): readonly InventorySym
214
282
  }
215
283
 
216
284
  /**
217
- * `DS1302`: a member of an enum declaration that nothing names. A member an enum-group
285
+ * `DS1005`: a member of an enum declaration that nothing names. A member an enum-group
218
286
  * record holds back is no candidate, so a member a conversion can produce never reaches
219
287
  * this kind.
220
288
  */
221
289
  function unusedEnumMembers(run: Run): readonly Finding[] {
222
290
  return unnamed(run, "enum-member").map((symbol) =>
223
- findingAbout(symbol, "DS1302", `enum member ${symbol.name} is named nowhere`),
291
+ findingAbout(symbol, CODE.unusedEnumMember, `enum member ${symbol.name} is named nowhere`),
224
292
  );
225
293
  }
226
294
 
227
295
  /**
228
- * `DS1303`: a type parameter of a function or a class method that neither the
229
- * declaration's signature nor its body names. A type parameter of a class, an interface,
230
- * a type alias or a method signature belongs to a type declaration and is never
231
- * reported, because a phantom parameter makes two instantiations distinct types.
296
+ * `DS1006`: a type parameter of a function, a class method or a type alias that neither
297
+ * the declaration's signature nor its body names. An alias names no type of its own, so
298
+ * a parameter its type never names makes no two instantiations distinct. One of a class,
299
+ * an interface or a method signature is never reported: a class or an interface merges
300
+ * only with declarations of the same parameters.
232
301
  */
233
302
  function unusedTypeParameters(run: Run): readonly Finding[] {
234
303
  return unnamed(run, "type-parameter")
@@ -236,7 +305,7 @@ function unusedTypeParameters(run: Run): readonly Finding[] {
236
305
  .map((symbol) =>
237
306
  findingAbout(
238
307
  symbol,
239
- "DS1303",
308
+ CODE.unusedTypeParameter,
240
309
  `type parameter ${symbol.name} is named in neither its signature nor its body`,
241
310
  ),
242
311
  );
@@ -249,15 +318,23 @@ function unusedTypeParameters(run: Run): readonly Finding[] {
249
318
  */
250
319
  export function writeOnlyDeclarations(input: EmitterInput): ReadonlySet<string> {
251
320
  return new Set(
252
- writeOnlySymbols(indexed(input)).map((finding) =>
253
- declarationKey(finding.symbol.ref, finding.position.path),
321
+ writtenOf(indexed(input)).subjects.map(({ symbol }) =>
322
+ declarationKey(symbol.ref, symbol.position.path),
254
323
  ),
255
324
  );
256
325
  }
257
326
 
258
327
  /**
259
- * The findings of the reads-and-writes family, `DS1300` to `DS1399`, in code order and
260
- * each code's in site order.
328
+ * The declarations that fall with a write-only subject, whatever the severity: a finding
329
+ * about one would name code its subject's deletion already deletes.
330
+ */
331
+ export function fallingWithWrites(input: EmitterInput): ReadonlySet<string> {
332
+ return writtenOf(indexed(input)).falls;
333
+ }
334
+
335
+ /**
336
+ * The findings of the reads-and-writes kinds, `DS1301`, `DS1005` and `DS1006`, in that
337
+ * order and each code's in site order.
261
338
  */
262
339
  export const readsAndWrites: Emitter = (input) => {
263
340
  const run = indexed(input);
@@ -1,24 +1,18 @@
1
+ import { CODE, REMEDIES, type Subject } from "../contract/contract.generated.ts";
1
2
  import { REPOSITORY_DOCUMENT } from "../config.ts";
2
3
  import type { Finding, FindingDetails, SuppressionEntry } from "../finding.ts";
3
4
  import type { InventorySymbol } from "../inventory.ts";
4
5
  import { FIXED_SEVERITY_CODES } from "../kinds.ts";
5
6
  import type { Position } from "../position.ts";
6
7
  import {
7
- isDependencyCode,
8
- isUnsuppressibleCode,
9
- STALE_SUPPRESSION,
10
- SUPPRESSION_WITHOUT_REASON,
8
+ names,
9
+ subjectOfCode,
11
10
  type Mechanism,
12
11
  type Refusal,
13
12
  type SuppressionRecord,
14
13
  } from "../suppress.ts";
15
14
  import type { Emitter } from "./emitter.ts";
16
-
17
- /** The code a configured root that matches nothing is reported under. */
18
- const UNMATCHED_ROOT = "DS1704";
19
-
20
- /** The code a configured declaration that names nothing is reported under. */
21
- const UNMATCHED_DECLARATION = "DS1706";
15
+ import { bytewise } from "../text/compare.ts";
22
16
 
23
17
  /** The subject kind of a finding about a configured declaration. */
24
18
  const DECLARATION_SUBJECT = "configured-declaration";
@@ -39,7 +33,7 @@ export interface StaleRecord {
39
33
  readonly reports: readonly string[];
40
34
  }
41
35
 
42
- /** What the self-check family reads: the run's refused suppressions and its configured roots. */
36
+ /** What the configuration family reads: the run's refused suppressions and its configured roots. */
43
37
  export interface SelfCheckFacts {
44
38
  /** The suppressions the grammar refused with a finding, in reading order. */
45
39
  readonly refusals: readonly Refusal[];
@@ -78,6 +72,43 @@ export function fileRefsOf(symbols: readonly InventorySymbol[]): FileRefs {
78
72
  return (path) => byPath.get(path);
79
73
  }
80
74
 
75
+ /**
76
+ * Why a record of `mechanism` naming `codes` can match nothing, one clause per subject whose
77
+ * findings kinds.json's remedies table lets no record of that mechanism name, in subject order.
78
+ */
79
+ function unnameable(codes: readonly string[], mechanism: Mechanism): readonly string[] {
80
+ return (Object.keys(REMEDIES) as Subject[]).flatMap((subject) => {
81
+ const named = codes.filter((code) => subjectOfCode(code) === subject);
82
+ if (named.length === 0 || names(subject, mechanism)) {
83
+ return [];
84
+ }
85
+ const { names: what, suppressions } = REMEDIES[subject];
86
+ const reports = `${spelled(named)} ${named.length === 1 ? "reports" : "each report"} ${what}`;
87
+ if (suppressions.length > 0) {
88
+ const records = suppressions.map((one) => articled(WRITTEN[one]));
89
+ return [`${reports}, which only ${spelledOr(records)} can name`];
90
+ }
91
+ const settable = named.filter((code) => !FIXED_SEVERITY_CODES.includes(code));
92
+ const remedy =
93
+ settable.length === 0
94
+ ? "fix what the finding names instead"
95
+ : `fix what the finding names or set the severity of ${spelled(settable)} instead`;
96
+ return [`${reports}, which no suppression can name; ${remedy}`];
97
+ });
98
+ }
99
+
100
+ /** A record's written name with its indefinite article. */
101
+ function articled(name: string): string {
102
+ return `${/^[aeiou]/u.test(name) ? "an" : "a"} ${name}`;
103
+ }
104
+
105
+ /** A list as a sentence names alternatives. */
106
+ function spelledOr(items: readonly string[]): string {
107
+ return items.length < 2
108
+ ? items.join("")
109
+ : `${items.slice(0, -1).join(", ")} or ${items.at(-1) ?? ""}`;
110
+ }
111
+
81
112
  /** A list of codes as a sentence names them. */
82
113
  function spelled(codes: readonly string[]): string {
83
114
  if (codes.length < 2) {
@@ -135,7 +166,7 @@ function refusedSuppressions(refusals: readonly Refusal[], files: FileRefs): rea
135
166
  suppressionRef(refused.symbol, refused.path, files),
136
167
  refused.site,
137
168
  `${WRITTEN[refused.mechanism]} for ${refused.code} ${
138
- refused.reported === SUPPRESSION_WITHOUT_REASON
169
+ refused.reported === CODE.suppressionWithoutReason
139
170
  ? "carries no reason"
140
171
  : "names a symbol and no path"
141
172
  }`,
@@ -146,7 +177,7 @@ function refusedSuppressions(refusals: readonly Refusal[], files: FileRefs): rea
146
177
 
147
178
  /** One stale suppression as the report's stale-suppression record carries it. */
148
179
  export interface StaleSuppression {
149
- readonly code: typeof STALE_SUPPRESSION;
180
+ readonly code: typeof CODE.staleSuppression;
150
181
  readonly mechanism: Mechanism;
151
182
  readonly entry: {
152
183
  readonly code: string;
@@ -178,30 +209,12 @@ export function staleSuppressions(
178
209
  bySite.set(key, held);
179
210
  }
180
211
  return [...bySite.values()].map(({ first, records }) => {
181
- const codes = [...new Set(records.map((one) => one.record.code))].sort();
212
+ const codes = [...new Set(records.map((one) => one.record.code))].sort(bytewise);
182
213
  const reports = [...new Set(records.flatMap((one) => one.reports))]
183
214
  .filter((code) => !codes.includes(code))
184
- .sort();
185
- const rows = codes.filter(isUnsuppressibleCode);
186
- const dependencies = first.mechanism === "inline" ? codes.filter(isDependencyCode) : [];
187
- const settable = rows.filter((code) => !FIXED_SEVERITY_CODES.includes(code));
188
- const remedy =
189
- settable.length === 0
190
- ? "fix what the finding names instead"
191
- : `fix what the finding names or set the severity of ${spelled(settable)} instead`;
215
+ .sort(bytewise);
192
216
  const declared = reports.length === 0 ? "" : `its declaration reports ${spelled(reports)}`;
193
- const because = [
194
- ...(rows.length > 0
195
- ? [
196
- `${spelled(rows)} ${rows.length === 1 ? "reports a row" : "report rows"} of a document, which no suppression can name; ${remedy}`,
197
- ]
198
- : []),
199
- ...(dependencies.length > 0
200
- ? [
201
- `${spelled(dependencies)} ${dependencies.length === 1 ? "reports a dependency row" : "report dependency rows"}, which only an ignore entry or a baseline row can name`,
202
- ]
203
- : []),
204
- ];
217
+ const because = unnameable(codes, first.mechanism);
205
218
  const instead =
206
219
  because.length > 0
207
220
  ? `, because ${because.join("; ")}${declared === "" ? "" : `; ${declared}`}`
@@ -209,7 +222,7 @@ export function staleSuppressions(
209
222
  ? ""
210
223
  : `, and ${declared}`;
211
224
  return {
212
- code: STALE_SUPPRESSION,
225
+ code: CODE.staleSuppression,
213
226
  mechanism: first.mechanism,
214
227
  entry: {
215
228
  code: first.code,
@@ -242,7 +255,7 @@ function unmatchedDeclarationFindings(
242
255
  unmatched: readonly UnmatchedDeclaration[],
243
256
  ): readonly Finding[] {
244
257
  return unmatched.map((one) => ({
245
- code: UNMATCHED_DECLARATION,
258
+ code: CODE.unmatchedConfiguredDeclaration,
246
259
  position: documentPosition(one.document),
247
260
  symbol: { ref: one.ref, kind: DECLARATION_SUBJECT, name: one.ref, sizeLines: 1 },
248
261
  message: `${one.key} entry names no declaration in any project`,
@@ -262,7 +275,7 @@ export function unmatchedRootFindings(
262
275
  ): readonly Finding[] {
263
276
  const position = documentPosition(document);
264
277
  return sources.map((source) => ({
265
- code: UNMATCHED_ROOT,
278
+ code: CODE.unmatchedRoot,
266
279
  position,
267
280
  symbol: { ref: source, kind: ROOT_SUBJECT, name: source, sizeLines: 1 },
268
281
  message:
@@ -273,7 +286,7 @@ export function unmatchedRootFindings(
273
286
  }
274
287
 
275
288
  /**
276
- * The findings of the self-check family, `DS1700` to `DS1799`: a suppression refused for
289
+ * The findings of the configuration family, `DS9000` to `DS9099`: a suppression refused for
277
290
  * carrying no reason or naming no path, and a configured root or declaration that named
278
291
  * nothing. A
279
292
  * suppression that matched nothing is a record of the report's stale suppressions, which
@@ -1,6 +1,7 @@
1
+ import { CODE } from "../contract/contract.generated.ts";
1
2
  import type { Finding } from "../finding.ts";
2
- import type { InventorySymbol, SymbolKind } from "../inventory.ts";
3
- import type { MatrixCandidate } from "../matrix.ts";
3
+ import { WORDS, type InventorySymbol, type SymbolKind } from "../inventory.ts";
4
+ import type { Candidate } from "../liveness/sweep.ts";
4
5
  import type { Emitter, EmitterInput } from "./emitter.ts";
5
6
  import { unreachableExports } from "./visibility-narrowing.ts";
6
7
 
@@ -13,42 +14,23 @@ const MEMBERS: ReadonlySet<SymbolKind> = new Set([
13
14
  ]);
14
15
 
15
16
  /**
16
- * The kinds of declaration no code of this family reports: an interface and a method an
17
+ * The kinds of declaration no code of this emitter reports: an interface and a method an
17
18
  * interface declares are the interface kinds' subjects, and a type parameter is the
18
19
  * subject of the unused-type-parameter kind or of none.
19
20
  */
20
- const NOT_THIS_FAMILY: ReadonlySet<SymbolKind> = new Set([
21
+ const NOT_REPORTED_HERE: ReadonlySet<SymbolKind> = new Set([
21
22
  "file",
22
23
  "interface",
23
24
  "interface-method",
24
25
  "type-parameter",
25
26
  ]);
26
27
 
27
- /** The reader's word for each kind of declaration a finding of the family names. */
28
- const WORDS: Readonly<Record<SymbolKind, string>> = {
29
- file: "file",
30
- function: "function",
31
- class: "class",
32
- interface: "interface",
33
- type: "type alias",
34
- enum: "enum",
35
- namespace: "namespace",
36
- variable: "variable",
37
- "export-alias": "re-export",
38
- method: "method",
39
- "class-member": "class member",
40
- "interface-method": "interface method",
41
- "type-member": "type member",
42
- "enum-member": "enum member",
43
- "type-parameter": "type parameter",
44
- };
45
-
46
28
  /** What the test-of-dead-code kind says, which states the rule it applies. */
47
29
  const TEST_OF_DEAD_CODE = "every target symbol this test references is reported dead";
48
30
 
49
31
  /** What the run holds about one candidate that decides its code. */
50
32
  interface Judged {
51
- readonly candidate: MatrixCandidate;
33
+ readonly candidate: Candidate;
52
34
  readonly symbol: InventorySymbol;
53
35
  /** Whether a test file declares it. */
54
36
  readonly test: boolean;
@@ -68,9 +50,9 @@ interface Judged {
68
50
  function codeOf(judged: Judged): string | undefined {
69
51
  const { candidate, symbol } = judged;
70
52
  if (candidate.testOfDeadCode) {
71
- return "DS1005";
53
+ return CODE.testOfDeadCode;
72
54
  }
73
- if ((judged.test && !candidate.unreferencedTest) || NOT_THIS_FAMILY.has(symbol.kind)) {
55
+ if ((judged.test && !candidate.unreferencedTest) || NOT_REPORTED_HERE.has(symbol.kind)) {
74
56
  return undefined;
75
57
  }
76
58
  const referenced = candidate.productionRefs + candidate.testRefs > 0;
@@ -81,33 +63,33 @@ function codeOf(judged: Judged): string | undefined {
81
63
  return unreferencedCode(symbol);
82
64
  }
83
65
  if (candidate.heldByTests === candidate.id) {
84
- return "DS1004";
66
+ return CODE.testOnlyUse;
85
67
  }
86
68
  if (candidate.productionRefs === 0 && judged.deprecated) {
87
- return "DS1006";
69
+ return CODE.deprecatedUnused;
88
70
  }
89
71
  if (
90
72
  candidate.testRefs > 0 &&
91
73
  (candidate.productionRefs === 0 ||
92
74
  (candidate.relation === "reachability" && candidate.keptByTests))
93
75
  ) {
94
- return "DS1004";
76
+ return CODE.testOnlyUse;
95
77
  }
96
78
  if (MEMBERS.has(symbol.kind)) {
97
- return "DS1003";
79
+ return CODE.unusedMember;
98
80
  }
99
81
  if (!symbol.exported) {
100
- return "DS1002";
82
+ return CODE.unusedUnexported;
101
83
  }
102
- return judged.unreachable ? undefined : "DS1001";
84
+ return judged.unreachable ? undefined : CODE.unusedExported;
103
85
  }
104
86
 
105
87
  /** The code a declaration nothing references carries, by its shape and its visibility. */
106
88
  function unreferencedCode(symbol: InventorySymbol): string {
107
89
  if (MEMBERS.has(symbol.kind)) {
108
- return "DS1003";
90
+ return CODE.unusedMember;
109
91
  }
110
- return symbol.exported ? "DS1001" : "DS1002";
92
+ return symbol.exported ? CODE.unusedExported : CODE.unusedUnexported;
111
93
  }
112
94
 
113
95
  /** The visibility a member's message names, where it narrows the member's reach. */
@@ -132,17 +114,17 @@ function messageOf(code: string, judged: Judged): string {
132
114
  const { candidate, symbol } = judged;
133
115
  const word = WORDS[symbol.kind];
134
116
  switch (code) {
135
- case "DS1005":
117
+ case CODE.testOfDeadCode:
136
118
  return TEST_OF_DEAD_CODE;
137
- case "DS1006":
119
+ case CODE.deprecatedUnused:
138
120
  return `deprecated ${word} has no production reference`;
139
- case "DS1004":
121
+ case CODE.testOnlyUse:
140
122
  return candidate.productionRefs === 0
141
123
  ? `${word} is referenced only from test files and never from production code`
142
124
  : `${word} is referenced only from test files and from declarations that are themselves dead`;
143
125
  }
144
126
  const subject =
145
- code === "DS1003"
127
+ code === CODE.unusedMember
146
128
  ? `${visibilityWord(symbol)}${word}`
147
129
  : symbol.kind === "export-alias"
148
130
  ? word
@@ -150,7 +132,7 @@ function messageOf(code: string, judged: Judged): string {
150
132
  if (candidate.relation === "reachability") {
151
133
  return `${subject} is referenced only from declarations that are themselves dead`;
152
134
  }
153
- if (code === "DS1001") {
135
+ if (code === CODE.unusedExported) {
154
136
  return `${subject} has no reference in the target and none from any loaded consumer`;
155
137
  }
156
138
  return `${subject} has no reference in the target`;
@@ -202,25 +184,25 @@ function brandMembers(input: EmitterInput): ReadonlySet<string> {
202
184
  /** The kinds of member a brand is: a data member of a type or of a class. */
203
185
  const BRANDS: ReadonlySet<SymbolKind> = new Set(["type-member", "class-member"]);
204
186
 
205
- /** The findings of the unused-declarations family, `DS1000` to `DS1099`. */
187
+ /** The findings of the unused-declaration kinds, `DS1001` to `DS1004` and `DS1102` to `DS1104`. */
206
188
  export const unusedDeclarations: Emitter = (input) => [
207
- ...familyFindings(input, false),
189
+ ...emitterFindings(input, false),
208
190
  ...unusedImports(input),
209
191
  ];
210
192
 
211
193
  /**
212
- * The import bindings their file never reads, under the unexported code. A generated
213
- * file's are the generator's to remove unless the run includes generated files.
194
+ * The import bindings their file never reads. A generated file's are the generator's to
195
+ * remove unless the run includes generated files.
214
196
  */
215
197
  function unusedImports(input: EmitterInput): Finding[] {
216
198
  const generated =
217
- input.config.analysis.generatedFiles === "include" ? undefined : input.files.generated;
199
+ input.config.analysis.generated_files === "include" ? undefined : input.files.generated;
218
200
  return input.intraFunction.imports.flatMap((binding) =>
219
201
  binding.used || generated?.has(binding.position.path) === true
220
202
  ? []
221
203
  : [
222
204
  {
223
- code: "DS1002",
205
+ code: CODE.unusedImport,
224
206
  position: binding.position,
225
207
  symbol: { ref: binding.ref, kind: "import", name: binding.name, sizeLines: 1 },
226
208
  message: `import binding ${binding.name} is never read in its file`,
@@ -234,10 +216,10 @@ function unusedImports(input: EmitterInput): Finding[] {
234
216
  * a record on such a member is matched against, since the report carries the container's
235
217
  * finding rather than one of the member's own.
236
218
  */
237
- export const fallenMembers: Emitter = (input) => familyFindings(input, true);
219
+ export const fallenMembers: Emitter = (input) => emitterFindings(input, true);
238
220
 
239
- /** The family's findings, or, where `fallen` is set, its dead containers' members' alone. */
240
- function familyFindings(input: EmitterInput, fallen: boolean): Finding[] {
221
+ /** This emitter's findings, or, where `fallen` is set, its dead containers' members' alone. */
222
+ function emitterFindings(input: EmitterInput, fallen: boolean): Finding[] {
241
223
  const union = input.swept.matrix.union;
242
224
  const dead = new Set(input.swept.sweep.candidates.map((candidate) => candidate.id));
243
225
  const unreachable = unreachableExports(input);
@@ -264,7 +246,7 @@ function familyFindings(input: EmitterInput, fallen: boolean): Finding[] {
264
246
  const code = codeOf(judged);
265
247
  if (
266
248
  code === undefined ||
267
- (code === "DS1003" && (brands ??= brandMembers(input)).has(symbol.id))
249
+ (code === CODE.unusedMember && (brands ??= brandMembers(input)).has(symbol.id))
268
250
  ) {
269
251
  continue;
270
252
  }