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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (431) hide show
  1. package/README.md +3 -1
  2. package/THIRD_PARTY_NOTICES.md +27 -0
  3. package/dist/bin/mapper-connection.js +2 -1
  4. package/dist/bin/node-host.js +24 -5
  5. package/dist/src/alias-chain.js +35 -9
  6. package/dist/src/amd.js +81 -0
  7. package/dist/src/analysis.js +274 -496
  8. package/dist/src/augmentations.js +64 -3
  9. package/dist/src/automatic-types.js +10 -29
  10. package/dist/src/bindings.js +382 -0
  11. package/dist/src/commands/held.js +499 -0
  12. package/dist/src/commands/read.js +161 -0
  13. package/dist/src/commands/shell.js +169 -0
  14. package/dist/src/commands/tools.js +1847 -0
  15. package/dist/src/component-files.js +3 -2
  16. package/dist/src/component-layer.js +4 -2
  17. package/dist/src/config.js +6 -82
  18. package/dist/src/conformance-record.js +2 -2
  19. package/dist/src/consumers.js +10 -38
  20. package/dist/src/contextual-uses.js +57 -26
  21. package/dist/src/contract/config.generated.js +561 -0
  22. package/dist/src/contract/contract.generated.js +1370 -0
  23. package/dist/src/contract/report.generated.js +866 -0
  24. package/dist/src/dependencies.js +165 -122
  25. package/dist/src/destructuring.js +1 -19
  26. package/dist/src/edges.js +38 -122
  27. package/dist/src/element-access.js +181 -168
  28. package/dist/src/entries/build-scripts.js +222 -0
  29. package/dist/src/{configuration-files.js → entries/configuration-files.js} +52 -256
  30. package/dist/src/{convention-rows.js → entries/convention-rows.js} +170 -30
  31. package/dist/src/entries/conventions.js +740 -0
  32. package/dist/src/{html-entries.js → entries/html-entries.js} +12 -42
  33. package/dist/src/{mdx-entries.js → entries/mdx-entries.js} +5 -28
  34. package/dist/src/entries/run-directories.js +77 -0
  35. package/dist/src/entries/sources.js +144 -0
  36. package/dist/src/entries/static-module.js +670 -0
  37. package/dist/src/entries/test-runners.js +650 -0
  38. package/dist/src/entries/workflow-steps.js +345 -0
  39. package/dist/src/exemptions/argument-places.js +131 -0
  40. package/dist/src/exemptions/calls.js +338 -0
  41. package/dist/src/exemptions/classes.js +13 -0
  42. package/dist/src/{decorator.js → exemptions/decorator.js} +19 -30
  43. package/dist/src/exemptions/detectors.js +48 -0
  44. package/dist/src/{enum-group.js → exemptions/enum-group.js} +9 -16
  45. package/dist/src/{erased-stores.js → exemptions/erased-stores.js} +7 -11
  46. package/dist/src/{framework-lifecycle.js → exemptions/framework-lifecycle.js} +76 -54
  47. package/dist/src/exemptions/generated-file.js +241 -0
  48. package/dist/src/{injection-container.js → exemptions/injection-container.js} +20 -26
  49. package/dist/src/exemptions/installed-globals.js +173 -0
  50. package/dist/src/{interface-satisfaction.js → exemptions/interface-satisfaction.js} +52 -121
  51. package/dist/src/exemptions/lifecycle.js +150 -0
  52. package/dist/src/{reflective-lookup.js → exemptions/reflective-lookup.js} +3 -3
  53. package/dist/src/exemptions/serialization-contract.js +1276 -0
  54. package/dist/src/exemptions/sites.js +182 -0
  55. package/dist/src/{template-field.js → exemptions/template-field.js} +13 -23
  56. package/dist/src/{value-reach.js → exemptions/value-reach.js} +14 -7
  57. package/dist/src/exposure.js +400 -0
  58. package/dist/src/extensions.js +37 -0
  59. package/dist/src/facts.js +38 -0
  60. package/dist/src/failure.js +36 -0
  61. package/dist/src/file-facts.js +3 -26
  62. package/dist/src/findings/completion.js +109 -56
  63. package/dist/src/findings/dependencies-and-module-machinery.js +4 -5
  64. package/dist/src/findings/emitters.js +27 -41
  65. package/dist/src/{implementations.js → findings/implementations.js} +3 -3
  66. package/dist/src/{in-operands.js → findings/in-operands.js} +3 -2
  67. package/dist/src/findings/interfaces.js +4 -5
  68. package/dist/src/findings/intra-function.js +16 -13
  69. package/dist/src/findings/non-code-artifacts.js +17 -12
  70. package/dist/src/findings/reads-and-writes.js +86 -27
  71. package/dist/src/findings/self-check.js +44 -30
  72. package/dist/src/findings/unused-declarations.js +29 -45
  73. package/dist/src/findings/visibility-narrowing.js +23 -31
  74. package/dist/src/findings-pass.js +13 -21
  75. package/dist/src/fs/document.js +52 -0
  76. package/dist/src/fs/manifest.js +67 -0
  77. package/dist/src/fs/tree.js +88 -0
  78. package/dist/src/git-ignore.js +39 -26
  79. package/dist/src/import-bindings.js +73 -28
  80. package/dist/src/index/sites.js +557 -0
  81. package/dist/src/index/values.js +124 -0
  82. package/dist/src/index.js +2 -2
  83. package/dist/src/indexed-access.js +523 -478
  84. package/dist/src/intra-function-parts.js +63 -43
  85. package/dist/src/inventory/commonjs.js +507 -0
  86. package/dist/src/inventory/enumerate.js +167 -0
  87. package/dist/src/inventory/syntax.js +236 -0
  88. package/dist/src/inventory.js +323 -724
  89. package/dist/src/javascript-file.js +48 -0
  90. package/dist/src/json-document.js +198 -67
  91. package/dist/src/keyof-comparisons.js +126 -107
  92. package/dist/src/kinds.js +3 -366
  93. package/dist/src/{components.js → liveness/components.js} +2 -3
  94. package/dist/src/{graph.js → liveness/graph.js} +52 -28
  95. package/dist/src/liveness/matrix.js +99 -0
  96. package/dist/src/liveness/sweep.js +558 -0
  97. package/dist/src/load/classify.js +289 -0
  98. package/dist/src/load/diagnostics.js +87 -0
  99. package/dist/src/load/discover.js +285 -0
  100. package/dist/src/{emit-map.js → load/emit-map.js} +1 -1
  101. package/dist/src/load/expected-module.js +136 -0
  102. package/dist/src/load/load.js +27 -0
  103. package/dist/src/load/module-lookup.js +37 -0
  104. package/dist/src/load/package-scope.js +56 -0
  105. package/dist/src/load/plan.js +313 -0
  106. package/dist/src/load/specifiers.js +113 -0
  107. package/dist/src/load/synthesize.js +152 -0
  108. package/dist/src/load/test-globals.js +207 -0
  109. package/dist/src/load/test-joins.js +82 -0
  110. package/dist/src/{workspace-manifests.js → load/workspace-manifests.js} +4 -4
  111. package/dist/src/{workspace-programs.js → load/workspace-programs.js} +89 -66
  112. package/dist/src/{workspace-resolution.js → load/workspace-resolution.js} +24 -66
  113. package/dist/src/{workspace-run.js → load/workspace-run.js} +7 -7
  114. package/dist/src/{workspace.js → load/workspace.js} +62 -124
  115. package/dist/src/module-declarations.js +70 -85
  116. package/dist/src/overrides.js +134 -112
  117. package/dist/src/partial.js +2 -1
  118. package/dist/src/paths.js +82 -16
  119. package/dist/src/platform-calls.js +78 -0
  120. package/dist/src/platform-symbols.js +134 -0
  121. package/dist/src/position.js +43 -1
  122. package/dist/src/print.js +11 -79
  123. package/dist/src/product.js +13 -0
  124. package/dist/src/query.js +95 -0
  125. package/dist/src/ref.js +12 -20
  126. package/dist/src/references/read-rule.js +1 -0
  127. package/dist/src/references/read-rules.js +48 -0
  128. package/dist/src/references/sink.js +237 -0
  129. package/dist/src/references/sources.js +450 -0
  130. package/dist/src/references.js +117 -1074
  131. package/dist/src/report-schema.js +51 -0
  132. package/dist/src/report.js +57 -41
  133. package/dist/src/reporters/annotations.js +15 -8
  134. package/dist/src/reporters/sarif.js +16 -10
  135. package/dist/src/reporters/template.js +4 -19
  136. package/dist/src/resolve.js +246 -730
  137. package/dist/src/{configured-declarations.js → roots/configured-declarations.js} +22 -24
  138. package/dist/src/{entry-point-gaps.js → roots/entry-point-gaps.js} +6 -15
  139. package/dist/src/roots/manifest.js +216 -0
  140. package/dist/src/roots/published-reach.js +412 -0
  141. package/dist/src/roots/root-set.js +487 -0
  142. package/dist/src/roots/unseen-loads.js +236 -0
  143. package/dist/src/run.js +66 -77
  144. package/dist/src/schema.js +320 -343
  145. package/dist/src/scope.js +38 -115
  146. package/dist/src/session.js +37 -29
  147. package/dist/src/source-files.js +6 -10
  148. package/dist/src/stores.js +4 -2
  149. package/dist/src/suppress-file.js +25 -28
  150. package/dist/src/suppress-inline.js +36 -83
  151. package/dist/src/suppress.js +50 -71
  152. package/dist/src/symbol-keys.js +92 -88
  153. package/dist/src/tests/file-class.js +76 -0
  154. package/dist/src/{outside-tests.js → tests/outside.js} +7 -7
  155. package/dist/src/{test-support.js → tests/support.js} +5 -12
  156. package/dist/src/text/compare.js +26 -0
  157. package/dist/src/text/glob.js +194 -0
  158. package/dist/src/text/named-files.js +298 -0
  159. package/dist/src/text/yaml.js +684 -0
  160. package/dist/src/type-errors.js +11 -232
  161. package/dist/src/type-parameter-reads.js +178 -139
  162. package/dist/src/unimplemented-callees.js +262 -242
  163. package/dist/src/unwrap.js +23 -0
  164. package/dist/src/usage.js +10 -0
  165. package/dist/src/vendor/unbash/ansi-c.js +132 -0
  166. package/dist/src/vendor/unbash/arithmetic-parts.js +37 -0
  167. package/dist/src/vendor/unbash/arithmetic.js +591 -0
  168. package/dist/src/vendor/unbash/assignment.js +131 -0
  169. package/dist/src/vendor/unbash/chars.js +48 -0
  170. package/dist/src/vendor/unbash/command.js +41 -0
  171. package/dist/src/vendor/unbash/expansion.js +80 -0
  172. package/dist/src/vendor/unbash/glob.js +268 -0
  173. package/dist/src/vendor/unbash/heredoc.js +27 -0
  174. package/dist/src/vendor/unbash/internal-types.js +1 -0
  175. package/dist/src/vendor/unbash/lexer.js +4274 -0
  176. package/dist/src/vendor/unbash/limits.js +3 -0
  177. package/dist/src/vendor/unbash/parser.js +1366 -0
  178. package/dist/src/vendor/unbash/parts.js +57 -0
  179. package/dist/src/vendor/unbash/substitution-context.js +8 -0
  180. package/dist/src/vendor/unbash/traversal.js +212 -0
  181. package/dist/src/vendor/unbash/types.js +1 -0
  182. package/dist/src/vendor/unbash/word-value.js +61 -0
  183. package/dist/src/vendor/unbash/word.js +40 -0
  184. package/dist/src/verbs/analyze.js +194 -127
  185. package/dist/src/verbs/describe.js +13 -18
  186. package/dist/src/verbs/explain.js +85 -139
  187. package/dist/src/verbs/print-config.js +2 -1
  188. package/dist/src/verbs/print-projects.js +6 -4
  189. package/dist/src/verbs/print-retained.js +30 -6
  190. package/dist/src/verbs/print-roots.js +4 -2
  191. package/dist/src/verbs/verb.js +1 -5
  192. package/dist/src/verbs/version.js +14 -3
  193. package/jsr.json +2 -1
  194. package/package.json +14 -8
  195. package/src/alias-chain.ts +40 -11
  196. package/src/amd.ts +130 -0
  197. package/src/analysis.ts +426 -733
  198. package/src/augmentations.ts +93 -4
  199. package/src/automatic-types.ts +12 -30
  200. package/src/bindings.ts +460 -0
  201. package/src/commands/held.ts +632 -0
  202. package/src/commands/read.ts +242 -0
  203. package/src/commands/shell.ts +228 -0
  204. package/src/commands/tools.ts +2382 -0
  205. package/src/component-files.ts +4 -2
  206. package/src/component-layer.ts +4 -2
  207. package/src/config.ts +31 -302
  208. package/src/conformance-record.ts +2 -2
  209. package/src/consumers.ts +16 -66
  210. package/src/contextual-uses.ts +66 -34
  211. package/src/contract/config.generated.ts +821 -0
  212. package/src/contract/contract.generated.ts +1453 -0
  213. package/src/contract/report.generated.ts +1241 -0
  214. package/src/dependencies.ts +223 -128
  215. package/src/destructuring.ts +1 -31
  216. package/src/edges.ts +41 -140
  217. package/src/element-access.ts +190 -187
  218. package/src/entries/build-scripts.ts +292 -0
  219. package/src/{configuration-files.ts → entries/configuration-files.ts} +68 -278
  220. package/src/{convention-rows.ts → entries/convention-rows.ts} +227 -31
  221. package/src/{conventions.ts → entries/conventions.ts} +367 -583
  222. package/src/{html-entries.ts → entries/html-entries.ts} +22 -48
  223. package/src/{mdx-entries.ts → entries/mdx-entries.ts} +7 -30
  224. package/src/entries/run-directories.ts +108 -0
  225. package/src/entries/sources.ts +266 -0
  226. package/src/entries/static-module.ts +858 -0
  227. package/src/entries/test-runners.ts +835 -0
  228. package/src/entries/workflow-steps.ts +432 -0
  229. package/src/exemptions/argument-places.ts +198 -0
  230. package/src/exemptions/calls.ts +483 -0
  231. package/src/exemptions/classes.ts +49 -0
  232. package/src/exemptions/decorator.ts +56 -0
  233. package/src/exemptions/detectors.ts +75 -0
  234. package/src/{enum-group.ts → exemptions/enum-group.ts} +10 -19
  235. package/src/{erased-stores.ts → exemptions/erased-stores.ts} +7 -14
  236. package/src/{framework-lifecycle.ts → exemptions/framework-lifecycle.ts} +85 -66
  237. package/src/exemptions/generated-file.ts +318 -0
  238. package/src/{injection-container.ts → exemptions/injection-container.ts} +29 -34
  239. package/src/exemptions/installed-globals.ts +255 -0
  240. package/src/{interface-satisfaction.ts → exemptions/interface-satisfaction.ts} +69 -160
  241. package/src/exemptions/lifecycle.ts +286 -0
  242. package/src/{reflective-lookup.ts → exemptions/reflective-lookup.ts} +5 -5
  243. package/src/exemptions/serialization-contract.ts +1729 -0
  244. package/src/exemptions/sites.ts +293 -0
  245. package/src/{template-field.ts → exemptions/template-field.ts} +22 -32
  246. package/src/{value-reach.ts → exemptions/value-reach.ts} +16 -8
  247. package/src/exposure.ts +492 -0
  248. package/src/extensions.ts +45 -0
  249. package/src/facts.ts +46 -0
  250. package/src/failure.ts +63 -0
  251. package/src/file-facts.ts +15 -25
  252. package/src/finding.ts +10 -10
  253. package/src/findings/boundary.ts +11 -0
  254. package/src/findings/completion.ts +133 -64
  255. package/src/findings/dependencies-and-module-machinery.ts +4 -7
  256. package/src/findings/emitter.ts +9 -10
  257. package/src/findings/emitters.ts +38 -52
  258. package/src/{implementations.ts → findings/implementations.ts} +4 -4
  259. package/src/{in-operands.ts → findings/in-operands.ts} +4 -3
  260. package/src/findings/interfaces.ts +7 -9
  261. package/src/findings/intra-function.ts +16 -14
  262. package/src/findings/non-code-artifacts.ts +24 -15
  263. package/src/findings/reads-and-writes.ts +118 -41
  264. package/src/findings/self-check.ts +51 -38
  265. package/src/findings/unused-declarations.ts +31 -49
  266. package/src/findings/visibility-narrowing.ts +36 -40
  267. package/src/findings-pass.ts +15 -31
  268. package/src/fs/document.ts +70 -0
  269. package/src/fs/manifest.ts +96 -0
  270. package/src/fs/tree.ts +110 -0
  271. package/src/git-ignore.ts +50 -26
  272. package/src/host.ts +12 -5
  273. package/src/import-bindings.ts +98 -29
  274. package/src/index/sites.ts +781 -0
  275. package/src/index/values.ts +170 -0
  276. package/src/index.ts +2 -2
  277. package/src/indexed-access.ts +570 -527
  278. package/src/intra-function-parts.ts +73 -44
  279. package/src/inventory/commonjs.ts +696 -0
  280. package/src/inventory/enumerate.ts +203 -0
  281. package/src/inventory/syntax.ts +311 -0
  282. package/src/inventory.ts +442 -895
  283. package/src/javascript-file.ts +54 -0
  284. package/src/json-document.ts +241 -76
  285. package/src/keyof-comparisons.ts +133 -122
  286. package/src/kinds.ts +5 -413
  287. package/src/{components.ts → liveness/components.ts} +4 -6
  288. package/src/{graph.ts → liveness/graph.ts} +100 -35
  289. package/src/liveness/matrix.ts +162 -0
  290. package/src/liveness/sweep.ts +855 -0
  291. package/src/load/classify.ts +433 -0
  292. package/src/load/diagnostics.ts +154 -0
  293. package/src/load/discover.ts +471 -0
  294. package/src/{emit-map.ts → load/emit-map.ts} +1 -1
  295. package/src/load/expected-module.ts +194 -0
  296. package/src/load/load.ts +73 -0
  297. package/src/load/module-lookup.ts +50 -0
  298. package/src/load/package-scope.ts +74 -0
  299. package/src/load/plan.ts +513 -0
  300. package/src/load/specifiers.ts +171 -0
  301. package/src/load/synthesize.ts +230 -0
  302. package/src/load/test-globals.ts +251 -0
  303. package/src/load/test-joins.ts +98 -0
  304. package/src/{workspace-manifests.ts → load/workspace-manifests.ts} +5 -5
  305. package/src/{workspace-programs.ts → load/workspace-programs.ts} +128 -85
  306. package/src/{workspace-resolution.ts → load/workspace-resolution.ts} +41 -77
  307. package/src/{workspace-run.ts → load/workspace-run.ts} +18 -16
  308. package/src/{workspace.ts → load/workspace.ts} +90 -134
  309. package/src/module-declarations.ts +74 -98
  310. package/src/overrides.ts +162 -134
  311. package/src/partial.ts +3 -2
  312. package/src/paths.ts +92 -16
  313. package/src/platform-calls.ts +119 -0
  314. package/src/platform-symbols.ts +189 -0
  315. package/src/position.ts +44 -1
  316. package/src/print.ts +12 -92
  317. package/src/product.ts +18 -0
  318. package/src/query.ts +201 -10
  319. package/src/ref.ts +12 -20
  320. package/src/references/read-rule.ts +60 -0
  321. package/src/references/read-rules.ts +55 -0
  322. package/src/references/sink.ts +314 -0
  323. package/src/references/sources.ts +632 -0
  324. package/src/references.ts +187 -1450
  325. package/src/report-schema.ts +68 -0
  326. package/src/report.ts +103 -226
  327. package/src/reporters/annotations.ts +22 -11
  328. package/src/reporters/json.ts +1 -1
  329. package/src/reporters/reporter.ts +2 -4
  330. package/src/reporters/reporters.ts +1 -1
  331. package/src/reporters/sarif.ts +29 -16
  332. package/src/reporters/template.ts +4 -20
  333. package/src/reporters/text.ts +3 -3
  334. package/src/resolve.ts +284 -1115
  335. package/src/{configured-declarations.ts → roots/configured-declarations.ts} +26 -29
  336. package/src/{entry-point-gaps.ts → roots/entry-point-gaps.ts} +7 -16
  337. package/src/roots/manifest.ts +303 -0
  338. package/src/roots/published-reach.ts +486 -0
  339. package/src/{roots.ts → roots/root-set.ts} +286 -469
  340. package/src/roots/unseen-loads.ts +345 -0
  341. package/src/run.ts +75 -91
  342. package/src/schema.ts +391 -388
  343. package/src/scope.ts +46 -138
  344. package/src/session.ts +87 -55
  345. package/src/source-files.ts +6 -11
  346. package/src/stores.ts +15 -3
  347. package/src/suppress-file.ts +24 -33
  348. package/src/suppress-inline.ts +55 -91
  349. package/src/suppress.ts +78 -79
  350. package/src/symbol-keys.ts +104 -107
  351. package/src/tests/file-class.ts +135 -0
  352. package/src/{outside-tests.ts → tests/outside.ts} +16 -10
  353. package/src/{test-support.ts → tests/support.ts} +15 -21
  354. package/src/text/compare.ts +27 -0
  355. package/src/text/glob.ts +210 -0
  356. package/src/text/named-files.ts +388 -0
  357. package/src/text/yaml.ts +747 -0
  358. package/src/type-errors.ts +18 -288
  359. package/src/type-parameter-reads.ts +187 -158
  360. package/src/unimplemented-callees.ts +297 -280
  361. package/src/unwrap.ts +34 -0
  362. package/src/usage.ts +10 -0
  363. package/src/vendor/unbash/LICENSE +15 -0
  364. package/src/vendor/unbash/VENDORED.md +16 -0
  365. package/src/vendor/unbash/ansi-c.ts +132 -0
  366. package/src/vendor/unbash/arithmetic-parts.ts +53 -0
  367. package/src/vendor/unbash/arithmetic.ts +641 -0
  368. package/src/vendor/unbash/assignment.ts +163 -0
  369. package/src/vendor/unbash/chars.ts +48 -0
  370. package/src/vendor/unbash/command.ts +47 -0
  371. package/src/vendor/unbash/expansion.ts +144 -0
  372. package/src/vendor/unbash/glob.ts +284 -0
  373. package/src/vendor/unbash/heredoc.ts +34 -0
  374. package/src/vendor/unbash/internal-types.ts +94 -0
  375. package/src/vendor/unbash/lexer.ts +4352 -0
  376. package/src/vendor/unbash/limits.ts +3 -0
  377. package/src/vendor/unbash/parser.ts +1612 -0
  378. package/src/vendor/unbash/parts.ts +96 -0
  379. package/src/vendor/unbash/substitution-context.ts +20 -0
  380. package/src/vendor/unbash/traversal.ts +182 -0
  381. package/src/vendor/unbash/types.ts +660 -0
  382. package/src/vendor/unbash/word-value.ts +64 -0
  383. package/src/vendor/unbash/word.ts +50 -0
  384. package/src/verbs/analyze.ts +255 -164
  385. package/src/verbs/describe.ts +19 -17
  386. package/src/verbs/explain.ts +93 -169
  387. package/src/verbs/print-config.ts +2 -1
  388. package/src/verbs/print-projects.ts +6 -4
  389. package/src/verbs/print-retained.ts +36 -6
  390. package/src/verbs/print-roots.ts +4 -2
  391. package/src/verbs/verb.ts +2 -8
  392. package/src/verbs/version.ts +15 -3
  393. package/dist/src/base-url.js +0 -18
  394. package/dist/src/calls.js +0 -155
  395. package/dist/src/conventions.js +0 -937
  396. package/dist/src/discover.js +0 -468
  397. package/dist/src/entry-points.js +0 -529
  398. package/dist/src/exempt-classes.js +0 -75
  399. package/dist/src/exempt.js +0 -209
  400. package/dist/src/generated-file.js +0 -95
  401. package/dist/src/glob.js +0 -65
  402. package/dist/src/manifest.js +0 -165
  403. package/dist/src/matrix.js +0 -246
  404. package/dist/src/pnpm-workspace.js +0 -120
  405. package/dist/src/roots.js +0 -672
  406. package/dist/src/serialization-contract.js +0 -611
  407. package/dist/src/setup-failure.js +0 -23
  408. package/dist/src/sweep.js +0 -224
  409. package/dist/src/test-joins.js +0 -101
  410. package/dist/src/value-flow.js +0 -74
  411. package/dist/src/version.js +0 -7
  412. package/dist/src/workflow-steps.js +0 -185
  413. package/src/base-url.ts +0 -24
  414. package/src/calls.ts +0 -225
  415. package/src/decorator.ts +0 -78
  416. package/src/discover.ts +0 -653
  417. package/src/entry-points.ts +0 -687
  418. package/src/exempt-classes.ts +0 -123
  419. package/src/exempt.ts +0 -323
  420. package/src/generated-file.ts +0 -111
  421. package/src/glob.ts +0 -67
  422. package/src/manifest.ts +0 -234
  423. package/src/matrix.ts +0 -423
  424. package/src/pnpm-workspace.ts +0 -135
  425. package/src/serialization-contract.ts +0 -849
  426. package/src/setup-failure.ts +0 -39
  427. package/src/sweep.ts +0 -347
  428. package/src/test-joins.ts +0 -120
  429. package/src/value-flow.ts +0 -104
  430. package/src/version.ts +0 -7
  431. package/src/workflow-steps.ts +0 -216
package/src/scope.ts CHANGED
@@ -1,11 +1,12 @@
1
- import { ConfigError } from "./config.ts";
1
+ import { SCOPE_SCHEMA } from "./contract/config.generated.ts";
2
2
  import type { Host } from "./host.ts";
3
+ import { dotted, locatedFault, placeIn, readStrict, StrictJSONError } from "./json-document.ts";
3
4
  import { dirnamePath, isAbsolutePath, joinPath, resolvePath } from "./paths.ts";
4
- import { checkDocument, type KeyNode } from "./schema.ts";
5
-
6
- /** The roles a scope document declares for a module. */
7
- const ROLE_TARGET = "target";
8
- const ROLE_CONSUMER = "consumer";
5
+ import { MARKERS } from "./load/discover.ts";
6
+ import { failureExit } from "./failure.ts";
7
+ import { message } from "./product.ts";
8
+ import { firstRefusal } from "./schema.ts";
9
+ import { UsageError } from "./usage.ts";
9
10
 
10
11
  /**
11
12
  * A scope document above this length is refused rather than decoded. It names one
@@ -14,23 +15,14 @@ const ROLE_CONSUMER = "consumer";
14
15
  const MAX_DOCUMENT_LENGTH = 1 << 20;
15
16
 
16
17
  /**
17
- * A scope document that cannot be read as one. It ends the run with the failure
18
- * code: the run could not learn what to analyze, so it produced no answer.
18
+ * The bytes read of a scope document. A UTF-16 unit decodes from at most three bytes,
19
+ * so a document past the bound is past it within these.
19
20
  */
20
- export class ScopeError extends Error {
21
- constructor(message: string) {
22
- super(message);
23
- this.name = "ScopeError";
24
- }
25
- }
21
+ const MAX_DOCUMENT_BYTES = 3 * (MAX_DOCUMENT_LENGTH + 1);
26
22
 
27
23
  /**
28
- * One module the run reads: the target or a declared consumer.
29
- *
30
- * The role a document declares is not carried here, because the resolved scope
31
- * holds exactly one target and a list of consumers, so a module's role is where it
32
- * sits. What a document declares is read and refused where it contradicts that
33
- * position, which is the only place the declaration can be wrong.
24
+ * One module the run reads: the target or a declared consumer. The role a document
25
+ * declares is not carried, because a module's role is where the scope holds it.
34
26
  */
35
27
  export interface Module {
36
28
  /** The package name. A document may state it; otherwise it is empty. */
@@ -45,150 +37,66 @@ export interface Scope {
45
37
  readonly consumers: readonly Module[];
46
38
  }
47
39
 
48
- const MODULE: KeyNode = {
49
- kind: "section",
50
- members: { id: { kind: "leaf" }, role: { kind: "leaf" }, path: { kind: "leaf" } },
51
- };
52
-
53
- /** The closed key list of the scope document, compared as bytes. */
54
- const SCOPE_ROOT: KeyNode = {
55
- kind: "section",
56
- members: {
57
- target: MODULE,
58
- workspace: { kind: "leaf" },
59
- consumers: { kind: "list", members: MODULE.members ?? {} },
60
- },
61
- };
62
-
63
- function isRecord(value: unknown): value is Record<string, unknown> {
64
- return typeof value === "object" && value !== null && !Array.isArray(value);
65
- }
66
-
67
- /**
68
- * One string member, or undefined where the document omits it. A member the
69
- * document writes is a string holding at least one character, so `null` and `""`
70
- * are refused rather than read as absent.
71
- */
72
- function stringMember(
73
- parent: Record<string, unknown>,
74
- name: string,
75
- at: string,
76
- ): string | undefined {
77
- if (!Object.hasOwn(parent, name)) {
78
- return undefined;
79
- }
80
- const value = parent[name];
81
- if (typeof value !== "string") {
82
- throw new ScopeError(`scope: ${at === "" ? name : `${at}.${name}`} is not a string`);
83
- }
84
- if (value === "") {
85
- throw new ScopeError(`scope: ${at === "" ? name : `${at}.${name}`} names nothing`);
86
- }
87
- return value;
88
- }
89
-
90
- function readModule(value: unknown, at: string, role: string, documentDir: string): Module {
91
- if (!isRecord(value)) {
92
- throw new ScopeError(`scope: ${at} is not an object`);
93
- }
94
- const declared = stringMember(value, "role", at);
95
- if (declared !== undefined && declared !== role) {
96
- throw new ScopeError(
97
- `scope: ${at}.role is ${JSON.stringify(declared)}, want ${JSON.stringify(role)}`,
98
- );
99
- }
100
- const path = stringMember(value, "path", at);
101
- if (path === undefined) {
102
- throw new ScopeError(`scope: ${at}.path names nothing`);
103
- }
104
- return {
105
- id: stringMember(value, "id", at) ?? "",
106
- path: isAbsolutePath(path) ? path : joinPath(documentDir, path),
107
- };
40
+ interface DeclaredModule {
41
+ readonly id?: string;
42
+ readonly path: string;
108
43
  }
109
44
 
110
- /**
111
- * Walks the document's text against the closed key list, refusing a key the list
112
- * does not declare, compared as bytes, and a key one object writes twice, which a
113
- * parse cannot report because it keeps the last value.
114
- */
115
- function checkKeys(text: string, file: string): void {
116
- try {
117
- checkDocument(text, SCOPE_ROOT, `scope: ${file}`);
118
- } catch (error: unknown) {
119
- if (error instanceof ConfigError) {
120
- // The configuration's refusal names the nearest configuration key, which a
121
- // scope document does not have.
122
- throw new ScopeError(
123
- error.kind === "unimplemented-key"
124
- ? `scope: ${file}: ${error.key} is not a declared key`
125
- : error.message,
126
- );
127
- }
128
- throw error;
129
- }
45
+ function refusal(file: string, place: string, reason: string): UsageError {
46
+ return new UsageError(`scope: ${file}: ${place === "" ? "" : `${place}: `}${reason}`);
130
47
  }
131
48
 
132
49
  /**
133
- * Decodes the scope document at `file`. Decoding is strict: an undeclared key, a
134
- * key written twice in one object, and a value of a type the document does not
135
- * admit, `null` included, are errors, and a relative path inside the document
136
- * resolves against the document's own directory.
137
- *
138
- * The `workspace` key the format declares is checked and carries nothing here: it
139
- * names the file a Go consumer resolves the target through, and a TypeScript
140
- * project resolves one through its own compiler configuration.
50
+ * Decodes the scope document at `file`, held to the Contract's scope schema, a relative
51
+ * path resolved against the document's own directory. A document that cannot be read or is
52
+ * refused is a usage error, as any document the invocation names. `workspace` is read by Go consumers
53
+ * alone: a TypeScript project resolves the target through its own compiler configuration.
141
54
  */
142
55
  export function readScope(host: Host, file: string): Scope {
143
56
  const absolute = resolvePath(host.workingDirectory(), file);
144
57
  let text: string;
145
58
  try {
146
- text = host.readFile(absolute);
59
+ text = host.readFile(absolute, MAX_DOCUMENT_BYTES);
147
60
  } catch (error: unknown) {
148
- throw new ScopeError(
149
- `scope: ${file}: ${error instanceof Error ? error.message : String(error)}`,
150
- );
61
+ throw new UsageError(`scope: ${file}: ${message(error)}`);
151
62
  }
152
63
  if (text.length > MAX_DOCUMENT_LENGTH) {
153
- throw new ScopeError(`scope: ${file} is longer than ${String(MAX_DOCUMENT_LENGTH)} characters`);
64
+ throw new UsageError(`scope: ${file} is longer than ${String(MAX_DOCUMENT_LENGTH)} characters`);
154
65
  }
155
66
  let value: unknown;
156
67
  try {
157
- value = JSON.parse(text);
68
+ value = readStrict(text).value;
158
69
  } catch (error: unknown) {
159
- throw new ScopeError(
160
- `scope: ${file}: ${error instanceof Error ? error.message : String(error)}`,
161
- );
70
+ if (!(error instanceof StrictJSONError)) {
71
+ throw error;
72
+ }
73
+ throw refusal(file, dotted(error.place), locatedFault(text, error));
162
74
  }
163
- if (!isRecord(value)) {
164
- throw new ScopeError(`scope: ${file} is not one JSON object`);
75
+ const refused = firstRefusal(SCOPE_SCHEMA, value);
76
+ if (refused !== undefined) {
77
+ throw refusal(file, dotted(placeIn(value, refused.pointer, refused.member)), refused.reason);
165
78
  }
166
- checkKeys(text, file);
167
- stringMember(value, "workspace", "");
79
+ const declared = value as { target: DeclaredModule; consumers?: readonly DeclaredModule[] };
168
80
  const documentDir = dirnamePath(absolute);
169
- if (!Object.hasOwn(value, "target")) {
170
- throw new ScopeError(`scope: ${file} names no target`);
171
- }
172
- const target = readModule(value["target"], "target", ROLE_TARGET, documentDir);
173
- const listed = Object.hasOwn(value, "consumers") ? value["consumers"] : [];
174
- if (!Array.isArray(listed)) {
175
- throw new ScopeError(`scope: ${file}: consumers is not an array`);
176
- }
177
- const consumers = (listed as unknown[]).map((entry, index) =>
178
- readModule(entry, `consumers[${String(index)}]`, ROLE_CONSUMER, documentDir),
179
- );
180
- return { target, consumers };
81
+ const moduleOf = (module: DeclaredModule): Module => ({
82
+ id: module.id ?? "",
83
+ path: isAbsolutePath(module.path) ? module.path : joinPath(documentDir, module.path),
84
+ });
85
+ return { target: moduleOf(declared.target), consumers: (declared.consumers ?? []).map(moduleOf) };
181
86
  }
182
87
 
183
- /** The single-package scope one directory is, when no scope document is given. */
88
+ /**
89
+ * The single-package scope one directory is, when no scope document is given. A target that is
90
+ * no directory holds no program.
91
+ */
184
92
  export function scopeForDir(host: Host, dir: string): Scope {
185
93
  const path = resolvePath(host.workingDirectory(), dir);
186
94
  const kind = host.kindOf(path);
187
- if (kind === "absent") {
188
- throw new ScopeError(`scope: ${path} does not exist`);
189
- }
190
95
  if (kind !== "directory") {
191
- throw new ScopeError(`scope: ${path} is not a directory`);
96
+ throw failureExit(
97
+ "no-program",
98
+ `the target ${path} ${kind === "absent" ? "does not exist" : "is not a directory"}, so it holds no compiler configuration, no file named ${MARKERS.join(", ")}: name the directory that holds one`,
99
+ );
192
100
  }
193
101
  return { target: { id: "", path }, consumers: [] };
194
102
  }
package/src/session.ts CHANGED
@@ -13,11 +13,9 @@ import type {
13
13
  Symbol as TSSymbol,
14
14
  TimingInfo,
15
15
  } from "@typescript/native/sync";
16
- import type { Node, SourceFile } from "@typescript/native/ast";
16
+ import type { Node, SourceFile, StringLiteralLikeNode } from "@typescript/native/ast";
17
17
  import { componentLayer, mapperManifest } from "./component-layer.ts";
18
- import { DiscoveryError } from "./discover.ts";
19
18
  import type { Host, TemporaryDirectory } from "./host.ts";
20
- import type { WorkspaceProgram } from "./workspace-programs.ts";
21
19
  import { joinPath } from "./paths.ts";
22
20
  import {
23
21
  queriesOf,
@@ -26,6 +24,7 @@ import {
26
24
  type Queries,
27
25
  type UnansweredQuestion,
28
26
  } from "./query.ts";
27
+ import { MANIFEST } from "./fs/manifest.ts";
29
28
 
30
29
  /**
31
30
  * The compiler the analysis reads through: a client over a protocol to a separate
@@ -36,8 +35,8 @@ import {
36
35
  export interface Engine {
37
36
  /**
38
37
  * Resolves one compiler configuration file, or throws with the reason it cannot
39
- * be read. The result is spelled through the client's own signature: the type
40
- * the compiler package returns here is not one of its exported names.
38
+ * be read. The result is spelled through the client's own signature: the type the
39
+ * compiler package returns here is not one of its exported names.
41
40
  */
42
41
  parseConfigFile(file: DocumentIdentifier): ReturnType<API["parseConfigFile"]>;
43
42
  /** Resolves one configuration's JSON as if `configFile` held it, which no file need. */
@@ -82,6 +81,22 @@ export interface Engine {
82
81
  close(): void;
83
82
  }
84
83
 
84
+ /** The most questions one round trip carries. */
85
+ const BATCH = 2048;
86
+
87
+ /** Asks one question of every item, in round trips of at most {@link BATCH}, answers in order. */
88
+ export function batched<T, A>(
89
+ engine: Engine,
90
+ items: readonly T[],
91
+ question: (item: T) => APIRequestGenerator<A>,
92
+ ): A[] {
93
+ const answers: A[] = [];
94
+ for (let at = 0; at < items.length; at += BATCH) {
95
+ answers.push(...engine.batch(items.slice(at, at + BATCH).map(question)));
96
+ }
97
+ return answers;
98
+ }
99
+
85
100
  /** How a run opens its compiler client. */
86
101
  export interface EngineOptions {
87
102
  /** Collect per-request timing, which the calibration record reads. */
@@ -115,7 +130,7 @@ export function openEngine(options: EngineOptions): Engine {
115
130
  if (components !== undefined && components.extensions.length > 0) {
116
131
  const made = components.host.temporaryDirectory();
117
132
  try {
118
- components.host.writeDocument(joinPath(made.path, "package.json"), [
133
+ components.host.writeDocument(joinPath(made.path, MANIFEST), [
119
134
  mapperManifest(components.host.componentMapperCommand()),
120
135
  ]);
121
136
  } catch (error: unknown) {
@@ -227,6 +242,11 @@ export interface ProjectView<Brand> {
227
242
  * file it is in.
228
243
  */
229
244
  ownPaths(): ReadonlySet<string>;
245
+ /**
246
+ * The file the compiler's module resolution names for each module specifier of this
247
+ * project's files, in order, or `undefined` where it names none.
248
+ */
249
+ resolvedFileNames(specifiers: readonly StringLiteralLikeNode[]): (string | undefined)[];
230
250
  /** A handle to one node of this project's program. */
231
251
  handle(node: Node): Handle<Brand>;
232
252
  /**
@@ -271,13 +291,6 @@ export interface ProjectView<Brand> {
271
291
  */
272
292
  export type ProjectVisitor<Result> = <Brand>(project: ProjectView<Brand>) => Result;
273
293
 
274
- /** One project a session opened: its configuration and the files of its own program. */
275
- export interface OpenedFiles {
276
- readonly configFile: string;
277
- /** The program's source files no default library and no external library holds. */
278
- readonly fileNames: () => readonly string[];
279
- }
280
-
281
294
  /**
282
295
  * The source files of one program that `own` admits, in the program's order, none of
283
296
  * them one of the compiler's default libraries.
@@ -339,6 +352,17 @@ function viewOf<Brand>(
339
352
  ownKeys ??= new Set(ownSourceFiles().map((file) => file.path));
340
353
  return ownKeys;
341
354
  },
355
+ resolvedFileNames: (specifiers) =>
356
+ batched(engine, specifiers, (node) =>
357
+ project.program.getResolvedModuleFromModuleSpecifier.gen(
358
+ node,
359
+ node.getSourceFile().fileName,
360
+ ),
361
+ ).map((resolved) =>
362
+ resolved === undefined || resolved.resolvedFileName === ""
363
+ ? undefined
364
+ : resolved.resolvedFileName,
365
+ ),
342
366
  handle: (node) => ({ node }),
343
367
  symbolsAt: (handles, cap) =>
344
368
  queries.symbolsAt(
@@ -471,19 +495,30 @@ export function diagnosticsOf<Brand>(project: ProjectView<Brand>): ProjectDiagno
471
495
  };
472
496
  }
473
497
 
498
+ /** How a snapshot builds one configuration other than by opening the project it names. */
499
+ export type ProgramBuild =
500
+ | { readonly kind: "program"; readonly params: CreateSnapshotProgramParams }
501
+ /** A configuration only the snapshot holds, at a path no file has. */
502
+ | { readonly kind: "configuration"; readonly file: string; readonly text: string };
503
+
474
504
  /** One run's result: what the visitor answered for each project, and what it cost. */
475
505
  export interface SessionResult<Result> {
476
- /** One answer per configuration the snapshot opened a project for, in the order named. */
506
+ /** One answer per configuration, in the order named. */
477
507
  readonly projects: readonly Result[];
478
- /** The configurations the snapshot opened no project for, in the order named. */
479
- readonly unopened: readonly string[];
480
508
  readonly timing: TimingInfo;
481
- /** Every question the checker could not answer, each once, in the order first asked. */
482
- readonly unanswered: readonly UnansweredQuestion[];
483
509
  }
484
510
 
485
- /** What a run does about a configuration the snapshot opened no project for. */
486
- type Unopened = "refuse" | "record";
511
+ /** One open snapshot's projects, valid only while the session that handed it out runs. */
512
+ export interface OpenedSession {
513
+ /** One view per configuration the snapshot opened a project for, in the order named. */
514
+ readonly views: readonly ProjectView<unknown>[];
515
+ }
516
+
517
+ /** How one session opens its configurations. */
518
+ export interface SessionOptions {
519
+ /** How the snapshot builds each configuration it does not open as its project. */
520
+ readonly programs?: ReadonlyMap<string, ProgramBuild> | undefined;
521
+ }
487
522
 
488
523
  /**
489
524
  * The projects one snapshot holds for the configurations named, by configuration file. A
@@ -512,22 +547,18 @@ function projectsOf(
512
547
  }
513
548
 
514
549
  /**
515
- * Runs `visit` over every project the compiler configurations name, inside one never updated
516
- * snapshot of one client, and answers in their order. A configuration `programs` describes is
517
- * built as that program, or opened from the configuration it writes. One the snapshot holds
518
- * nothing for ends the run under `"refuse"` and is named in the result under `"record"`.
519
- * `first` runs over every opened project before the first visit and `last` after the last,
520
- * both while the client answers; the snapshot and the client are then released.
550
+ * Opens every project the compiler configurations name in one never updated snapshot of one
551
+ * client, and hands them to `use` while the client answers; the snapshot and the client are
552
+ * then released. A configuration `options.programs` describes is built as that program, or
553
+ * opened from the configuration it writes. One the snapshot holds nothing for has no view.
521
554
  */
522
- export function runSession<Result>(
555
+ export function openSession<Result>(
523
556
  engine: Engine,
524
557
  configFiles: readonly string[],
525
- visit: ProjectVisitor<Result>,
526
- unopened: Unopened = "refuse",
527
- programs: ReadonlyMap<string, WorkspaceProgram> = new Map(),
528
- last: () => void = () => undefined,
529
- first: (opened: readonly OpenedFiles[]) => void = () => undefined,
530
- ): SessionResult<Result> {
558
+ options: SessionOptions,
559
+ use: (opened: OpenedSession, unanswered: () => readonly UnansweredQuestion[]) => Result,
560
+ ): Result {
561
+ const programs = options.programs ?? new Map<string, ProgramBuild>();
531
562
  try {
532
563
  const built: string[] = [];
533
564
  const params: CreateSnapshotProgramParams[] = [];
@@ -552,32 +583,13 @@ export function runSession<Result>(
552
583
  const opened = projectsOf(snapshot, built, written);
553
584
  const log = new UnansweredLog();
554
585
  const views: ProjectView<unknown>[] = [];
555
- const missing: string[] = [];
556
586
  for (const configFile of configFiles) {
557
587
  const project = opened.get(configFile);
558
- if (project === undefined) {
559
- if (unopened === "refuse") {
560
- throw new DiscoveryError(`${configFile} opened no project`, []);
561
- }
562
- missing.push(configFile);
563
- continue;
588
+ if (project !== undefined) {
589
+ views.push(viewOf(project, configFile, engine, log));
564
590
  }
565
- views.push(viewOf(project, configFile, engine, log));
566
591
  }
567
- first(
568
- views.map((view) => ({
569
- configFile: view.configFile,
570
- fileNames: () => view.ownSourceFiles().map((file) => file.fileName),
571
- })),
572
- );
573
- const projects = views.map((view) => visit(view));
574
- last();
575
- return {
576
- projects,
577
- unopened: missing,
578
- timing: engine.getTimingInfo(),
579
- unanswered: log.questions,
580
- };
592
+ return use({ views }, () => log.questions);
581
593
  } finally {
582
594
  snapshot.dispose();
583
595
  }
@@ -585,3 +597,23 @@ export function runSession<Result>(
585
597
  engine.close();
586
598
  }
587
599
  }
600
+
601
+ /**
602
+ * Runs `visit` over the project {@link openSession} opens for each configuration, and answers
603
+ * in their order; a configuration the snapshot opens nothing for throws before any visit.
604
+ */
605
+ export function runSession<Result>(
606
+ engine: Engine,
607
+ configFiles: readonly string[],
608
+ visit: ProjectVisitor<Result>,
609
+ ): SessionResult<Result> {
610
+ return openSession(engine, configFiles, {}, (opened) => {
611
+ const unopened = configFiles.find(
612
+ (configFile) => !opened.views.some((view) => view.configFile === configFile),
613
+ );
614
+ if (unopened !== undefined) {
615
+ throw new Error(`${unopened} opened no project`);
616
+ }
617
+ return { projects: opened.views.map((view) => visit(view)), timing: engine.getTimingInfo() };
618
+ });
619
+ }
@@ -5,9 +5,10 @@
5
5
  */
6
6
 
7
7
  import type { SourceFile } from "@typescript/native/ast";
8
- import { commonDirectory, emittedFrom } from "./emit-map.ts";
8
+ import { commonDirectory, emittedFrom } from "./load/emit-map.ts";
9
9
  import { dirnamePath, joinPath, relativePath, resolvePath } from "./paths.ts";
10
10
  import type { ProjectView } from "./session.ts";
11
+ import { OUTPUT_EXTENSIONS } from "./extensions.ts";
11
12
 
12
13
  /** The one character a subpath pattern of a manifest's `exports` holds. */
13
14
  const SUBPATH_WILDCARD = "*";
@@ -15,9 +16,6 @@ const SUBPATH_WILDCARD = "*";
15
16
  /** The extension a source file's name drops when the project writes it out. */
16
17
  const SOURCE_EXTENSION = /\.[cm]?[jt]sx?$/u;
17
18
 
18
- /** The extensions the project may write a source file's output under. */
19
- const OUTPUT_EXTENSIONS = [".js", ".mjs", ".cjs", ".jsx", ".d.ts", ".d.mts", ".d.cts"] as const;
20
-
21
19
  /**
22
20
  * Whether one path is what a subpath pattern stands for: the text before the
23
21
  * wildcard, any run of characters including the solidus, then the text after it.
@@ -90,13 +88,10 @@ function layoutOf<Brand>(
90
88
  }
91
89
 
92
90
  /**
93
- * The lookups over one project's own files.
94
- *
95
- * A path that names an emitted file is read back to the source the project would
96
- * emit it from through the project's own emit mapping and nothing else: the
97
- * extension is one the compiler emits from a source extension, and a path below the
98
- * output directory is read below the directory the compiler emits from, which the
99
- * configuration declares or which is the directory every input file shares.
91
+ * The lookups over one project's own files. A path naming an emitted file is read back to its
92
+ * source through the project's own emit mapping alone: the extension is one the compiler emits
93
+ * from a source extension, and a path below the output directory is read below the directory
94
+ * the compiler emits from, which the configuration declares or every input file shares.
100
95
  */
101
96
  export function sourceFilesOf<Brand>(project: ProjectView<Brand>, targetRoot: string): SourceFiles {
102
97
  const byName = new Map<string, SourceFile>();
package/src/stores.ts CHANGED
@@ -12,7 +12,9 @@ import {
12
12
  import { nodeKey, type Inventory } from "./inventory.ts";
13
13
  import type { Reference } from "./references.ts";
14
14
  import type { ProjectView } from "./session.ts";
15
- import type { Exemption, Mode } from "./sweep.ts";
15
+ import type { Exemption } from "./exemptions/lifecycle.ts";
16
+ import type { Mode } from "./tests/file-class.ts";
17
+ import { classedAsTest, madeByTestCode, withheldBy } from "./tests/file-class.ts";
16
18
 
17
19
  /** One run's stores and reads, over every configuration. */
18
20
  export interface Stores {
@@ -39,6 +41,8 @@ export interface Stores {
39
41
  /** What one configuration contributes to the run's stores. */
40
42
  interface ConfigurationStores {
41
43
  readonly references: readonly Reference[];
44
+ /** The configuration's test-support files, whose references are test code's. */
45
+ readonly support: ReadonlySet<string>;
42
46
  readonly accessors: readonly string[];
43
47
  }
44
48
 
@@ -71,12 +75,20 @@ export function storesOf(
71
75
  ): Stores {
72
76
  return {
73
77
  references: per.flatMap((one) =>
74
- one.references.filter((reference) => !mode.production || !reference.test),
78
+ one.references.filter((reference) => !withheldBy(mode, reference, one.support)),
75
79
  ),
76
80
  readInTests: new Set(
77
81
  per.flatMap((one) =>
78
82
  one.references
79
- .filter((reference) => reference.test && reference.use !== "write")
83
+ .filter(
84
+ (reference) =>
85
+ reference.use !== "write" &&
86
+ classedAsTest(
87
+ madeByTestCode(reference, one.support),
88
+ reference.consumer !== undefined,
89
+ mode,
90
+ ),
91
+ )
80
92
  .map((reference) => reference.to),
81
93
  ),
82
94
  ),