@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
@@ -4,25 +4,20 @@
4
4
  * ignore entry or a baseline row. A bound record marks its declaration live before the
5
5
  * sweep, unless its code reports a part or a dependency row, and is in effect when it
6
6
  * withholds a finding its code would have produced there, dormant when the configuration
7
- * withholds every such finding anyway, and stale otherwise.
7
+ * or a hold withholds every such finding anyway, and stale otherwise.
8
8
  */
9
- import { ConfigError } from "./config.js";
9
+ import { KIND_ROWS, REMEDIES, SYMBOL_SUBJECTS, } from "./contract/contract.generated.js";
10
+ import { UsageError } from "./usage.js";
10
11
  import { positionKey } from "./position.js";
11
12
  import { isRef } from "./ref.js";
12
- /** The code a suppression that carries no reason is reported under. */
13
- export const SUPPRESSION_WITHOUT_REASON = "DS1701";
14
- /** The code an ignore entry or a baseline row that names no path is reported under. */
15
- export const UNSCOPED_ENTRY = "DS1702";
16
- /** The code a suppression that withholds nothing is reported under. */
17
- export const STALE_SUPPRESSION = "DS1703";
18
13
  /**
19
14
  * A directive, an entry or a document the grammar refuses before any finding exists: an
20
15
  * instruction the analysis cannot carry out. It is a malformed input, so the command line
21
16
  * answers it with the usage code.
22
17
  */
23
- export class SuppressionError extends ConfigError {
18
+ export class SuppressionError extends UsageError {
24
19
  constructor(mechanism, at, text, want) {
25
- super("malformed", at, `${mechanism} ${at}: ${text}: want ${want}`);
20
+ super(`${mechanism} ${at}: ${text}: want ${want}`);
26
21
  this.name = "SuppressionError";
27
22
  }
28
23
  }
@@ -71,73 +66,54 @@ export function isSymbolRef(value) {
71
66
  export function blankReason(reason) {
72
67
  return reason === undefined || /^[ \t\r\n]*$/u.test(reason);
73
68
  }
74
- /**
75
- * The subject kinds that are a dependency row, each with the code that reports one. An
76
- * ignore entry or a baseline row naming the row's reference and file withholds its finding
77
- * and marks nothing, and an inline directive never binds one.
78
- */
79
- const DEPENDENCY_SUBJECTS = new Map([
80
- ["dependency", ["DS1601"]],
81
- ["module-directive", ["DS1605"]],
82
- ]);
83
- /**
84
- * The subject kinds that are a row of a document rather than a declaration of the program,
85
- * each with the codes that report one. Apart from a dependency row, nothing withholds a
86
- * finding about one.
87
- */
88
- const ROW_SUBJECTS = new Map([
89
- ["file", ["DS1501", "DS1502"]],
90
- ...DEPENDENCY_SUBJECTS,
91
- ["root", ["DS1704"]],
92
- ["configured-declaration", ["DS1706"]],
93
- ["suppression", ["DS1701", "DS1702", "DS1703"]],
94
- ["edge", ["DS1705"]],
95
- ]);
69
+ /** No hold. */
70
+ const NO_HOLDS = { withholds: () => false, holdsRecord: () => false };
71
+ /** The subject of the kind each live code names. */
72
+ const SUBJECT_OF_CODE = new Map(KIND_ROWS.map((row) => [row.code, row.subject]));
73
+ /** The subject a finding about one symbol kind is about. */
74
+ function subjectOf(kind) {
75
+ return Object.hasOwn(SYMBOL_SUBJECTS, kind)
76
+ ? SYMBOL_SUBJECTS[kind]
77
+ : undefined;
78
+ }
79
+ /** Whether a subject is a row of a document rather than a declaration of the program. */
80
+ function rowOf(subject) {
81
+ return subject === "file" || subject === "dependency" || subject === "record";
82
+ }
96
83
  /** Whether a finding's subject is a row of a document rather than a declaration. */
97
84
  export function isRowSubject(kind) {
98
- return ROW_SUBJECTS.has(kind);
85
+ return rowOf(subjectOf(kind));
99
86
  }
100
- /** Whether a code reports a row of a document. */
101
- export function isRowCode(code) {
102
- return [...ROW_SUBJECTS.values()].some((codes) => codes.includes(code));
87
+ /** The subject a code reports, which kinds.json's remedies table answers for. */
88
+ export function subjectOfCode(code) {
89
+ return SUBJECT_OF_CODE.get(code);
103
90
  }
104
- /** Whether a finding's subject is a dependency row. */
105
- export function isDependencySubject(kind) {
106
- return DEPENDENCY_SUBJECTS.has(kind);
107
- }
108
- /** Whether a code reports a dependency row, which only an ignore entry or a baseline row names. */
109
- export function isDependencyCode(code) {
110
- return [...DEPENDENCY_SUBJECTS.values()].some((codes) => codes.includes(code));
91
+ /**
92
+ * Whether a record of `mechanism` can name a finding about `subject`, as kinds.json's
93
+ * remedies table lists the suppressions of each subject. A subject the table does not
94
+ * know is a declaration's.
95
+ */
96
+ export function names(subject, mechanism) {
97
+ return REMEDIES[subject ?? "declaration"].suppressions.includes(mechanism);
111
98
  }
112
- /** Whether a code reports a row of a document that no record of any mechanism can name. */
113
- export function isUnsuppressibleCode(code) {
114
- return isRowCode(code) && !isDependencyCode(code);
99
+ /** Whether a finding about a symbol of `kind` is one a record of `mechanism` can name. */
100
+ export function namesKind(kind, mechanism) {
101
+ return names(subjectOf(kind), mechanism);
115
102
  }
116
103
  /**
117
- * The subject kinds that are a part of a declaration rather than a declaration: a part
104
+ * Whether a finding's subject is a part of the declaration its reference names: a part
118
105
  * has no reference of its own, so a finding about one names the declaration that holds
119
106
  * it, and the part is decided inside that declaration whatever uses it.
120
107
  */
121
- const PART_SUBJECTS = new Set([
122
- "parameter",
123
- "receiver",
124
- "result",
125
- "statement",
126
- "case",
127
- "store",
128
- ]);
129
- /** Whether a finding's subject is a part of the declaration its reference names. */
130
108
  export function isPartSubject(kind) {
131
- return PART_SUBJECTS.has(kind);
109
+ return subjectOf(kind) === "part";
132
110
  }
133
- /** The prefix of the codes of the part kinds, the intra-function range. */
134
- const PART_KIND_PREFIX = "DS18";
135
111
  /**
136
112
  * Whether a code is a part kind, whose record withholds its finding and marks nothing:
137
113
  * the record says the part is wanted, not that the declaration holding it is.
138
114
  */
139
115
  export function isPartKind(code) {
140
- return code.startsWith(PART_KIND_PREFIX);
116
+ return SUBJECT_OF_CODE.get(code) === "part";
141
117
  }
142
118
  /** One finding's identity: its code and the position of the thing it names. */
143
119
  function claimKey(finding) {
@@ -155,14 +131,13 @@ export function pairs(record, finding) {
155
131
  if (record.code !== finding.code) {
156
132
  return false;
157
133
  }
158
- if (DEPENDENCY_SUBJECTS.has(finding.symbol.kind)) {
159
- return (record.mechanism !== "inline" &&
160
- record.symbol === finding.symbol.ref &&
161
- record.path === finding.position.path);
162
- }
163
- if (ROW_SUBJECTS.has(finding.symbol.kind)) {
134
+ const subject = subjectOf(finding.symbol.kind);
135
+ if (!names(subject, record.mechanism)) {
164
136
  return false;
165
137
  }
138
+ if (subject === "dependency") {
139
+ return record.symbol === finding.symbol.ref && record.path === finding.position.path;
140
+ }
166
141
  if (record.bound !== "" && record.bound === positionKey(finding.position)) {
167
142
  return true;
168
143
  }
@@ -174,10 +149,10 @@ export function pairs(record, finding) {
174
149
  * there: swept with no mark for a liveness kind, and as swept otherwise. The first record
175
150
  * in reading order claims a finding, so a second naming it is stale; a part-kind record
176
151
  * claims every finding of its code about a part of its declaration. A record is dormant
177
- * when the dials withhold every finding it claims, read from those findings alone, or when
178
- * it claims none and its code's severity is `allow`.
152
+ * when the dials or `holds` withhold every finding it claims, or when it claims none and
153
+ * its code is at `allow` or a hold keeps its declaration live.
179
154
  */
180
- export function ledgerOf(records, would, dials) {
155
+ export function ledgerOf(records, would, dials, holds = NO_HOLDS) {
181
156
  const taken = new Set();
182
157
  const verdicts = [];
183
158
  for (const record of records) {
@@ -185,13 +160,17 @@ export function ledgerOf(records, would, dials) {
185
160
  const first = would.find(open);
186
161
  const claimed = first === undefined ? [] : isPartKind(record.code) ? would.filter(open) : [first];
187
162
  if (claimed.length === 0) {
188
- verdicts.push(record.bound !== "" && dials.allows(record.code) ? "dormant" : "stale");
163
+ verdicts.push(record.bound !== "" && (dials.allows(record.code) || holds.holdsRecord(record))
164
+ ? "dormant"
165
+ : "stale");
189
166
  continue;
190
167
  }
191
168
  for (const finding of claimed) {
192
169
  taken.add(claimKey(finding));
193
170
  }
194
- verdicts.push(claimed.every((finding) => dials.withholds(finding)) ? "dormant" : "in-effect");
171
+ verdicts.push(claimed.every((finding) => dials.withholds(finding) || holds.withholds(finding))
172
+ ? "dormant"
173
+ : "in-effect");
195
174
  }
196
175
  return {
197
176
  verdicts,
@@ -5,16 +5,12 @@
5
5
  * No name node resolves to such a member: the key's name resolves to the constant. An
6
6
  * iteration reads the member its well-known iteration symbol keys.
7
7
  */
8
- import { isComputedPropertyName, isForOfStatement, isIdentifier, isNoSubstitutionTemplateLiteral, isNumericLiteral, isParenthesizedExpression, isPropertyAccessExpression, isSpreadElement, isStringLiteral, } from "@typescript/native/ast";
9
- import { nodeKey } from "./inventory.js";
10
- import { renderPosition } from "./position.js";
11
- import { isAnswered } from "./query.js";
8
+ import { isComputedPropertyName, isForOfStatement, isIdentifier, isNoSubstitutionTemplateLiteral, isNumericLiteral, isPropertyAccessExpression, isSpreadElement, isStringLiteral, } from "@typescript/native/ast";
9
+ import { parenthesesRemoved } from "./unwrap.js";
10
+ import { isAnswered, UNANSWERED } from "./query.js";
12
11
  /** The identifier an element access's argument names its key by, where it is a name. */
13
12
  export function keyNameOf(argument) {
14
- let at = argument;
15
- while (isParenthesizedExpression(at)) {
16
- at = at.expression;
17
- }
13
+ const at = parenthesesRemoved(argument);
18
14
  if (isIdentifier(at)) {
19
15
  return at;
20
16
  }
@@ -129,87 +125,95 @@ function wellKnownName(name) {
129
125
  : undefined;
130
126
  }
131
127
  /**
132
- * The references the iterations of one project's own files make to the iteration members
133
- * of the values they iterate: a `for…of` statement and a spread element read
134
- * `[Symbol.iterator]`, and a `for await…of` statement reads `[Symbol.asyncIterator]` and,
135
- * which it falls back to, `[Symbol.iterator]`. Each is made by the declaration holding it.
128
+ * The reads the iterations of a side's files make of the iteration members of the values they
129
+ * iterate: a `for…of` statement and a spread element read `[Symbol.iterator]`, and a
130
+ * `for await…of` statement reads `[Symbol.asyncIterator]` and, which it falls back to,
131
+ * `[Symbol.iterator]`. Each is made by the declaration holding it. A value whose type or
132
+ * members the checker leaves unanswered holds the members those names could spell.
136
133
  */
137
- export function iterationReferences(project, held, chains, root, testFiles) {
138
- const queries = project.queries;
139
- const ownPaths = project.ownPaths();
140
- const iterated = [];
141
- for (const file of project.ownSourceFiles()) {
142
- const fileId = held.declarations.get(nodeKey(file, file));
143
- if (fileId === undefined) {
144
- continue;
145
- }
146
- const visit = (node, from) => {
147
- const holder = held.declarations.get(nodeKey(file, node)) ?? from;
148
- if (isForOfStatement(node)) {
149
- const protocols = node.awaitModifier === undefined ? ["iterator"] : ["asyncIterator", "iterator"];
150
- iterated.push({ file, from: holder, operand: node.expression, protocols });
151
- }
152
- else if (isSpreadElement(node)) {
153
- iterated.push({ file, from: holder, operand: node.expression, protocols: ["iterator"] });
154
- }
155
- node.forEachChild((child) => {
156
- visit(child, holder);
157
- });
158
- };
159
- file.forEachChild((child) => {
160
- visit(child, fileId);
161
- });
162
- }
163
- if (iterated.length === 0) {
164
- return [];
165
- }
166
- const types = queries.typesAt(iterated.map((one) => one.operand));
167
- const members = new Map();
168
- const membersOf = (type) => {
169
- const known = members.get(type.id);
170
- if (known !== undefined) {
171
- return known;
172
- }
173
- const keyed = [];
174
- const properties = queries.propertiesOf(type);
175
- for (const property of isAnswered(properties) ? properties : []) {
176
- for (const handle of property.declarations) {
177
- const node = ownPaths.has(handle.path) ? project.declarationAt(handle)?.node : undefined;
178
- const name = wellKnownName(node?.name);
179
- if (name !== undefined) {
180
- keyed.push({ name, ids: chains.declarationsOf(property) });
181
- break;
134
+ export const iteration = {
135
+ start() {
136
+ const iterated = [];
137
+ return {
138
+ visit(node, { file, from }) {
139
+ if (isForOfStatement(node)) {
140
+ const protocols = node.awaitModifier === undefined ? ["iterator"] : ["asyncIterator", "iterator"];
141
+ iterated.push({ file, from, operand: node.expression, protocols });
182
142
  }
183
- }
184
- }
185
- members.set(type.id, keyed);
186
- return keyed;
187
- };
188
- const found = [];
189
- iterated.forEach((one, index) => {
190
- const type = types[index];
191
- if (type === undefined || !isAnswered(type)) {
192
- return;
193
- }
194
- const parts = type.isUnionType() || type.isIntersectionType() ? queries.constituents(type) : [type];
195
- const position = renderPosition(one.file, root, one.operand.getStart());
196
- for (const part of isAnswered(parts) ? parts : []) {
197
- for (const member of membersOf(part)) {
198
- if (!one.protocols.includes(member.name)) {
199
- continue;
143
+ else if (isSpreadElement(node)) {
144
+ iterated.push({ file, from, operand: node.expression, protocols: ["iterator"] });
200
145
  }
201
- for (const to of member.ids) {
202
- found.push({
203
- from: one.from,
204
- to,
205
- position,
206
- use: "read",
207
- resolution: "keyed",
208
- test: testFiles.has(position.path),
209
- });
146
+ },
147
+ reads({ project, chains }) {
148
+ const found = [];
149
+ if (iterated.length === 0) {
150
+ return found;
210
151
  }
211
- }
212
- }
213
- });
214
- return found;
215
- }
152
+ const queries = project.queries;
153
+ const ownPaths = project.ownPaths();
154
+ const types = queries.typesAt(iterated.map((one) => one.operand));
155
+ const members = new Map();
156
+ const membersOf = (type) => {
157
+ const known = members.get(type.id);
158
+ if (known !== undefined) {
159
+ return known;
160
+ }
161
+ const properties = queries.propertiesOf(type);
162
+ const keyed = [];
163
+ for (const property of isAnswered(properties) ? properties : []) {
164
+ for (const handle of property.declarations) {
165
+ const node = ownPaths.has(handle.path)
166
+ ? project.declarationAt(handle)?.node
167
+ : undefined;
168
+ const name = wellKnownName(node?.name);
169
+ if (name !== undefined) {
170
+ keyed.push({ name, ids: chains.declarationsOf(property) });
171
+ break;
172
+ }
173
+ }
174
+ }
175
+ const result = isAnswered(properties) ? keyed : UNANSWERED;
176
+ members.set(type.id, result);
177
+ return result;
178
+ };
179
+ // A member a well-known symbol keys is named by the symbol's computed name.
180
+ const spelled = (protocols) => protocols.map((protocol) => `Symbol.${protocol}`);
181
+ iterated.forEach((one, index) => {
182
+ const type = types[index];
183
+ if (type === UNANSWERED) {
184
+ found.push({ kind: "held", from: one.from, names: spelled(one.protocols) });
185
+ return;
186
+ }
187
+ if (type === undefined) {
188
+ return;
189
+ }
190
+ const parts = type.isUnionType() || type.isIntersectionType() ? queries.constituents(type) : [type];
191
+ for (const part of isAnswered(parts) ? parts : [type]) {
192
+ const keyed = membersOf(part);
193
+ if (keyed === UNANSWERED) {
194
+ found.push({ kind: "held", from: one.from, names: spelled(one.protocols) });
195
+ continue;
196
+ }
197
+ for (const member of keyed) {
198
+ if (!one.protocols.includes(member.name)) {
199
+ continue;
200
+ }
201
+ for (const to of member.ids) {
202
+ found.push({
203
+ kind: "named",
204
+ from: one.from,
205
+ to,
206
+ file: one.file,
207
+ at: one.operand,
208
+ use: "read",
209
+ via: "keyed",
210
+ });
211
+ }
212
+ }
213
+ }
214
+ });
215
+ return found;
216
+ },
217
+ };
218
+ },
219
+ };
@@ -12,10 +12,12 @@
12
12
  * type, because nothing ties the name to a type.
13
13
  */
14
14
  import { readComponent } from "./component-files.js";
15
- import { ConfigError } from "./config.js";
16
15
  import { memberNames } from "./member-names.js";
17
16
  import { extensionOf, isAbsolutePath, joinPath, normalizePath, relativePath } from "./paths.js";
18
17
  import { isComponentFile } from "./position.js";
18
+ import { bytewise } from "./text/compare.js";
19
+ import { filesBelow } from "./fs/tree.js";
20
+ import { UsageError } from "./usage.js";
19
21
  /** The kinds of declaration an action can name. */
20
22
  const READ_BY_A_TEMPLATE = new Set([
21
23
  "method",
@@ -30,13 +32,6 @@ const READ_BY_A_TEMPLATE = new Set([
30
32
  const READ_BY_MARKUP = new Set([...READ_BY_A_TEMPLATE, "enum-member"]);
31
33
  /** One identifier, as the grammar of the analyzed language spells one. */
32
34
  const IDENTIFIER = /[\p{ID_Start}$_][\p{ID_Continue}$\u200C\u200D]*/uy;
33
- /** Two strings ordered bytewise. */
34
- function compare(a, b) {
35
- if (a === b) {
36
- return 0;
37
- }
38
- return a < b ? -1 : 1;
39
- }
40
35
  /**
41
36
  * Every template under the configured directories, read once for the run, in path
42
37
  * order and each file once. A directory is named relative to the target root, and
@@ -48,34 +43,29 @@ function compare(a, b) {
48
43
  export function readTemplates(host, targetRoot, analysis) {
49
44
  const files = new Map();
50
45
  const read = (dir) => {
51
- const entries = [...host.readDirectory(joinPath(targetRoot, dir))].sort((a, b) => compare(a.name, b.name));
52
- for (const entry of entries) {
53
- const path = joinPath(dir, entry.name);
54
- if (entry.directory) {
55
- read(path);
56
- continue;
57
- }
46
+ for (const below of filesBelow(host, joinPath(targetRoot, dir), () => true)) {
47
+ const path = joinPath(dir, below);
58
48
  const absolute = joinPath(targetRoot, path);
59
49
  if (!files.has(path) && host.kindOf(absolute) === "file") {
60
50
  files.set(path, host.readFile(absolute));
61
51
  }
62
52
  }
63
53
  };
64
- for (const configured of analysis.templateDirs) {
54
+ for (const configured of analysis.template_dirs) {
65
55
  const dir = normalizePath(configured);
66
56
  if (isAbsolutePath(dir) ||
67
57
  dir === ".." ||
68
58
  dir.startsWith("../") ||
69
59
  host.kindOf(joinPath(targetRoot, dir)) !== "directory") {
70
- throw new ConfigError("malformed", "analysis.template_dirs", `analysis.template_dirs: ${JSON.stringify(configured)} is not a directory below the target root`);
60
+ throw new UsageError(`analysis.template_dirs: ${JSON.stringify(configured)} is not a directory below the target root`);
71
61
  }
72
62
  read(dir);
73
63
  }
74
64
  return {
75
- delimiters: analysis.templateDelimiters,
65
+ delimiters: analysis.template_delimiters,
76
66
  files: [...files]
77
67
  .map(([path, text]) => ({ path, text }))
78
- .sort((a, b) => compare(a.path, b.path)),
68
+ .sort((a, b) => bytewise(a.path, b.path)),
79
69
  };
80
70
  }
81
71
  /** The end of the quoted string that opens at `from`, past its closing quote. */
@@ -0,0 +1,76 @@
1
+ /**
2
+ * The file classes the run counts references by. A test file is one a `ts.test_files`
3
+ * pattern or a test runner's row names (the test-runner entry source decides which), a test
4
+ * file no project holds, or a consumer's file a pattern names below the consumer's root.
5
+ * A test-support file is test code as well, decided once the references are known
6
+ * (`support.ts`), so a reference carries only whether a test file made it and the counters
7
+ * read the support class beside it.
8
+ */
9
+ import { renderPosition } from "../position.js";
10
+ import { bytewise } from "../text/compare.js";
11
+ import { globExpression } from "../text/glob.js";
12
+ /** The test files of the target: each file the test-runner source names, by its file name. */
13
+ export function targetTestFile(named) {
14
+ return (file) => named.has(file.fileName);
15
+ }
16
+ /** The test files a pattern names, each by its path below `root`: a consumer's, below the consumer's root. */
17
+ export function patternTestFile(patterns, root) {
18
+ const expressions = patterns.map(globExpression);
19
+ return (file) => {
20
+ const path = renderPosition(file, root, 0).path;
21
+ return expressions.some((expression) => expression.test(path));
22
+ };
23
+ }
24
+ /** The own files of a project that are test files, by their path below `root`, ascending. */
25
+ export function testFilePaths(project, root, testFile) {
26
+ return project
27
+ .ownSourceFiles()
28
+ .filter(testFile)
29
+ .map((file) => renderPosition(file, root, 0).path)
30
+ .sort(bytewise);
31
+ }
32
+ /** Whether test code made one reference: a test file, or a test-support file of the target. */
33
+ export function madeByTestCode(reference, support) {
34
+ return (reference.test || (reference.consumer === undefined && support.has(reference.position.path)));
35
+ }
36
+ /** Whether the mode classes a reference test code made as a test one: any but a loaded consumer's it classes as production. */
37
+ export function classedAsTest(test, consumer, mode) {
38
+ return test && !(consumer && mode.consumerTestsProduction === true);
39
+ }
40
+ /** Whether a production mode counts no reference of this one: test code made it, as the mode classes it. */
41
+ export function withheldBy(mode, reference, support) {
42
+ return (mode.production &&
43
+ classedAsTest(madeByTestCode(reference, support), reference.consumer !== undefined, mode));
44
+ }
45
+ /** Whether a production mode follows no edge like this one: {@link withheldBy} for a graph edge. */
46
+ export function edgeWithheldBy(mode, edge) {
47
+ return mode.production && classedAsTest(edge.test, edge.consumer, mode);
48
+ }
49
+ /** The rule a file the analysis classified as test-support code is counted under. */
50
+ const TEST_SUPPORT_RULE = "test-support";
51
+ /**
52
+ * The name one test-file rule takes. A rule's name is a word list the report's own
53
+ * vocabulary spells, which cannot carry a pattern, so a rule is named by the place of
54
+ * its pattern in the configured list.
55
+ */
56
+ function patternRule(index) {
57
+ return `test-file-pattern-${String(index + 1)}`;
58
+ }
59
+ /**
60
+ * The rules over the test files of several projects at once, ordered by rule: a file two
61
+ * projects hold is one file, so each rule counts the distinct paths it matches.
62
+ */
63
+ export function testFileRulesOf(testFiles, paths, supportFiles = []) {
64
+ const distinct = [...new Set(paths)];
65
+ const support = new Set(supportFiles).size;
66
+ return [
67
+ ...testFiles.map((pattern, index) => {
68
+ const expression = globExpression(pattern);
69
+ return {
70
+ rule: patternRule(index),
71
+ matched: distinct.filter((path) => expression.test(path)).length,
72
+ };
73
+ }),
74
+ ...(support === 0 ? [] : [{ rule: TEST_SUPPORT_RULE, matched: support }]),
75
+ ].sort((a, b) => bytewise(a.rule, b.rule));
76
+ }
@@ -7,15 +7,15 @@
7
7
  * it names is not known.
8
8
  */
9
9
  import { isCallExpression, isExportDeclaration, isImportDeclaration, isNamespaceExport, isNamespaceImport, isNoSubstitutionTemplateLiteral, isStringLiteral, SyntaxKind, } from "@typescript/native/ast";
10
- import { RESOLVED_EXTENSIONS } from "./configuration-files.js";
11
- import { emittedFrom } from "./emit-map.js";
12
- import { namesImported } from "./module-declarations.js";
13
- import { dirnamePath, joinPath, normalizePath, queriedModulePath } from "./paths.js";
14
- import { renderPosition } from "./position.js";
15
- import { nameComponent } from "./ref.js";
10
+ import { RESOLVED_EXTENSIONS } from "../entries/configuration-files.js";
11
+ import { emittedFrom } from "../load/emit-map.js";
12
+ import { namesImported } from "../import-bindings.js";
13
+ import { dirnamePath, joinPath, normalizePath, queriedModulePath, startsRelativePath, } from "../paths.js";
14
+ import { renderPosition } from "../position.js";
15
+ import { nameComponent } from "../ref.js";
16
16
  /** The paths below the target root one relative specifier may name, written path first. */
17
17
  function candidates(dir, specifier) {
18
- if (!specifier.startsWith("./") && !specifier.startsWith("../")) {
18
+ if (!startsRelativePath(specifier)) {
19
19
  return [];
20
20
  }
21
21
  const path = normalizePath(dir === "" ? specifier : `${dir}/${specifier}`);
@@ -5,8 +5,8 @@
5
5
  * another such file, so it is judged with the tests: what it references is referenced by
6
6
  * test code.
7
7
  */
8
- import { CONVENTION_ROWS, TEST_LIBRARIES, TEST_LIBRARY_SCOPES } from "./convention-rows.js";
9
- import { packageOfSpecifier } from "./dependencies.js";
8
+ import { CONVENTION_ROWS, TEST_LIBRARIES, TEST_LIBRARY_SCOPES, } from "../entries/convention-rows.js";
9
+ import { packageOfSpecifier } from "../dependencies.js";
10
10
  /** The root kind that never takes a file out of test-support code: the skip only withholds. */
11
11
  const SKIP_ROOT = "type-error";
12
12
  /**
@@ -14,7 +14,9 @@ const SKIP_ROOT = "type-error";
14
14
  * convention row reads test files for, and the convention table's test libraries.
15
15
  */
16
16
  const TEST_PACKAGES = new Set([
17
- ...CONVENTION_ROWS.filter((row) => row.testFiles !== undefined).map((row) => row.package),
17
+ ...CONVENTION_ROWS.filter((row) => row.testFiles !== undefined ||
18
+ row.testDirectories !== undefined ||
19
+ row.testRunner !== undefined).map((row) => row.package),
18
20
  ...TEST_LIBRARIES,
19
21
  ]);
20
22
  /**
@@ -161,12 +163,3 @@ export function testSupportFiles(symbols, references, roots, testFiles, evidence
161
163
  const support = withoutOutsideUsers(new Set([...onlyTests].filter((path) => carries(onlyTests, path))));
162
164
  return { support, testUsed: new Set([...onlyTests].filter((path) => !support.has(path))) };
163
165
  }
164
- /** The references with every one a test-support file makes counted as a test reference. */
165
- export function supportReferences(references, support) {
166
- if (support.size === 0) {
167
- return references;
168
- }
169
- return references.map((reference) => !reference.test && support.has(reference.position.path)
170
- ? { ...reference, test: true }
171
- : reference);
172
- }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Two strings in the order of their UTF-8 bytes, the order every set of a run is read in.
3
+ * That is code point order, which UTF-16 code unit order (`<` on strings) breaks above
4
+ * U+FFFF: a surrogate unit is below U+E000 while the code point it encodes is above U+FFFF.
5
+ */
6
+ export function bytewise(a, b) {
7
+ if (a === b) {
8
+ return 0;
9
+ }
10
+ const length = Math.min(a.length, b.length);
11
+ for (let at = 0; at < length; at += 1) {
12
+ const x = a.charCodeAt(at);
13
+ const y = b.charCodeAt(at);
14
+ if (x !== y) {
15
+ return ranked(x) < ranked(y) ? -1 : 1;
16
+ }
17
+ }
18
+ return a.length < b.length ? -1 : 1;
19
+ }
20
+ /** One UTF-16 unit moved so that a surrogate ranks above every unit of U+E000 to U+FFFF. */
21
+ function ranked(unit) {
22
+ if (unit >= 0xe000) {
23
+ return unit - 0x800;
24
+ }
25
+ return unit >= 0xd800 ? unit + 0x2000 : unit;
26
+ }