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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (431) hide show
  1. package/README.md +3 -1
  2. package/THIRD_PARTY_NOTICES.md +27 -0
  3. package/dist/bin/mapper-connection.js +2 -1
  4. package/dist/bin/node-host.js +24 -5
  5. package/dist/src/alias-chain.js +35 -9
  6. package/dist/src/amd.js +81 -0
  7. package/dist/src/analysis.js +274 -496
  8. package/dist/src/augmentations.js +64 -3
  9. package/dist/src/automatic-types.js +10 -29
  10. package/dist/src/bindings.js +382 -0
  11. package/dist/src/commands/held.js +499 -0
  12. package/dist/src/commands/read.js +161 -0
  13. package/dist/src/commands/shell.js +169 -0
  14. package/dist/src/commands/tools.js +1847 -0
  15. package/dist/src/component-files.js +3 -2
  16. package/dist/src/component-layer.js +4 -2
  17. package/dist/src/config.js +6 -82
  18. package/dist/src/conformance-record.js +2 -2
  19. package/dist/src/consumers.js +10 -38
  20. package/dist/src/contextual-uses.js +57 -26
  21. package/dist/src/contract/config.generated.js +561 -0
  22. package/dist/src/contract/contract.generated.js +1370 -0
  23. package/dist/src/contract/report.generated.js +866 -0
  24. package/dist/src/dependencies.js +165 -122
  25. package/dist/src/destructuring.js +1 -19
  26. package/dist/src/edges.js +38 -122
  27. package/dist/src/element-access.js +181 -168
  28. package/dist/src/entries/build-scripts.js +222 -0
  29. package/dist/src/{configuration-files.js → entries/configuration-files.js} +52 -256
  30. package/dist/src/{convention-rows.js → entries/convention-rows.js} +170 -30
  31. package/dist/src/entries/conventions.js +740 -0
  32. package/dist/src/{html-entries.js → entries/html-entries.js} +12 -42
  33. package/dist/src/{mdx-entries.js → entries/mdx-entries.js} +5 -28
  34. package/dist/src/entries/run-directories.js +77 -0
  35. package/dist/src/entries/sources.js +144 -0
  36. package/dist/src/entries/static-module.js +670 -0
  37. package/dist/src/entries/test-runners.js +650 -0
  38. package/dist/src/entries/workflow-steps.js +345 -0
  39. package/dist/src/exemptions/argument-places.js +131 -0
  40. package/dist/src/exemptions/calls.js +338 -0
  41. package/dist/src/exemptions/classes.js +13 -0
  42. package/dist/src/{decorator.js → exemptions/decorator.js} +19 -30
  43. package/dist/src/exemptions/detectors.js +48 -0
  44. package/dist/src/{enum-group.js → exemptions/enum-group.js} +9 -16
  45. package/dist/src/{erased-stores.js → exemptions/erased-stores.js} +7 -11
  46. package/dist/src/{framework-lifecycle.js → exemptions/framework-lifecycle.js} +76 -54
  47. package/dist/src/exemptions/generated-file.js +241 -0
  48. package/dist/src/{injection-container.js → exemptions/injection-container.js} +20 -26
  49. package/dist/src/exemptions/installed-globals.js +173 -0
  50. package/dist/src/{interface-satisfaction.js → exemptions/interface-satisfaction.js} +52 -121
  51. package/dist/src/exemptions/lifecycle.js +150 -0
  52. package/dist/src/{reflective-lookup.js → exemptions/reflective-lookup.js} +3 -3
  53. package/dist/src/exemptions/serialization-contract.js +1276 -0
  54. package/dist/src/exemptions/sites.js +182 -0
  55. package/dist/src/{template-field.js → exemptions/template-field.js} +13 -23
  56. package/dist/src/{value-reach.js → exemptions/value-reach.js} +14 -7
  57. package/dist/src/exposure.js +400 -0
  58. package/dist/src/extensions.js +37 -0
  59. package/dist/src/facts.js +38 -0
  60. package/dist/src/failure.js +36 -0
  61. package/dist/src/file-facts.js +3 -26
  62. package/dist/src/findings/completion.js +109 -56
  63. package/dist/src/findings/dependencies-and-module-machinery.js +4 -5
  64. package/dist/src/findings/emitters.js +27 -41
  65. package/dist/src/{implementations.js → findings/implementations.js} +3 -3
  66. package/dist/src/{in-operands.js → findings/in-operands.js} +3 -2
  67. package/dist/src/findings/interfaces.js +4 -5
  68. package/dist/src/findings/intra-function.js +16 -13
  69. package/dist/src/findings/non-code-artifacts.js +17 -12
  70. package/dist/src/findings/reads-and-writes.js +86 -27
  71. package/dist/src/findings/self-check.js +44 -30
  72. package/dist/src/findings/unused-declarations.js +29 -45
  73. package/dist/src/findings/visibility-narrowing.js +23 -31
  74. package/dist/src/findings-pass.js +13 -21
  75. package/dist/src/fs/document.js +52 -0
  76. package/dist/src/fs/manifest.js +67 -0
  77. package/dist/src/fs/tree.js +88 -0
  78. package/dist/src/git-ignore.js +39 -26
  79. package/dist/src/import-bindings.js +73 -28
  80. package/dist/src/index/sites.js +557 -0
  81. package/dist/src/index/values.js +124 -0
  82. package/dist/src/index.js +2 -2
  83. package/dist/src/indexed-access.js +523 -478
  84. package/dist/src/intra-function-parts.js +63 -43
  85. package/dist/src/inventory/commonjs.js +507 -0
  86. package/dist/src/inventory/enumerate.js +167 -0
  87. package/dist/src/inventory/syntax.js +236 -0
  88. package/dist/src/inventory.js +323 -724
  89. package/dist/src/javascript-file.js +48 -0
  90. package/dist/src/json-document.js +198 -67
  91. package/dist/src/keyof-comparisons.js +126 -107
  92. package/dist/src/kinds.js +3 -366
  93. package/dist/src/{components.js → liveness/components.js} +2 -3
  94. package/dist/src/{graph.js → liveness/graph.js} +52 -28
  95. package/dist/src/liveness/matrix.js +99 -0
  96. package/dist/src/liveness/sweep.js +558 -0
  97. package/dist/src/load/classify.js +289 -0
  98. package/dist/src/load/diagnostics.js +87 -0
  99. package/dist/src/load/discover.js +285 -0
  100. package/dist/src/{emit-map.js → load/emit-map.js} +1 -1
  101. package/dist/src/load/expected-module.js +136 -0
  102. package/dist/src/load/load.js +27 -0
  103. package/dist/src/load/module-lookup.js +37 -0
  104. package/dist/src/load/package-scope.js +56 -0
  105. package/dist/src/load/plan.js +313 -0
  106. package/dist/src/load/specifiers.js +113 -0
  107. package/dist/src/load/synthesize.js +152 -0
  108. package/dist/src/load/test-globals.js +207 -0
  109. package/dist/src/load/test-joins.js +82 -0
  110. package/dist/src/{workspace-manifests.js → load/workspace-manifests.js} +4 -4
  111. package/dist/src/{workspace-programs.js → load/workspace-programs.js} +89 -66
  112. package/dist/src/{workspace-resolution.js → load/workspace-resolution.js} +24 -66
  113. package/dist/src/{workspace-run.js → load/workspace-run.js} +7 -7
  114. package/dist/src/{workspace.js → load/workspace.js} +62 -124
  115. package/dist/src/module-declarations.js +70 -85
  116. package/dist/src/overrides.js +134 -112
  117. package/dist/src/partial.js +2 -1
  118. package/dist/src/paths.js +82 -16
  119. package/dist/src/platform-calls.js +78 -0
  120. package/dist/src/platform-symbols.js +134 -0
  121. package/dist/src/position.js +43 -1
  122. package/dist/src/print.js +11 -79
  123. package/dist/src/product.js +13 -0
  124. package/dist/src/query.js +95 -0
  125. package/dist/src/ref.js +12 -20
  126. package/dist/src/references/read-rule.js +1 -0
  127. package/dist/src/references/read-rules.js +48 -0
  128. package/dist/src/references/sink.js +237 -0
  129. package/dist/src/references/sources.js +450 -0
  130. package/dist/src/references.js +117 -1074
  131. package/dist/src/report-schema.js +51 -0
  132. package/dist/src/report.js +57 -41
  133. package/dist/src/reporters/annotations.js +15 -8
  134. package/dist/src/reporters/sarif.js +16 -10
  135. package/dist/src/reporters/template.js +4 -19
  136. package/dist/src/resolve.js +246 -730
  137. package/dist/src/{configured-declarations.js → roots/configured-declarations.js} +22 -24
  138. package/dist/src/{entry-point-gaps.js → roots/entry-point-gaps.js} +6 -15
  139. package/dist/src/roots/manifest.js +216 -0
  140. package/dist/src/roots/published-reach.js +412 -0
  141. package/dist/src/roots/root-set.js +487 -0
  142. package/dist/src/roots/unseen-loads.js +236 -0
  143. package/dist/src/run.js +66 -77
  144. package/dist/src/schema.js +320 -343
  145. package/dist/src/scope.js +38 -115
  146. package/dist/src/session.js +37 -29
  147. package/dist/src/source-files.js +6 -10
  148. package/dist/src/stores.js +4 -2
  149. package/dist/src/suppress-file.js +25 -28
  150. package/dist/src/suppress-inline.js +36 -83
  151. package/dist/src/suppress.js +50 -71
  152. package/dist/src/symbol-keys.js +92 -88
  153. package/dist/src/tests/file-class.js +76 -0
  154. package/dist/src/{outside-tests.js → tests/outside.js} +7 -7
  155. package/dist/src/{test-support.js → tests/support.js} +5 -12
  156. package/dist/src/text/compare.js +26 -0
  157. package/dist/src/text/glob.js +194 -0
  158. package/dist/src/text/named-files.js +298 -0
  159. package/dist/src/text/yaml.js +684 -0
  160. package/dist/src/type-errors.js +11 -232
  161. package/dist/src/type-parameter-reads.js +178 -139
  162. package/dist/src/unimplemented-callees.js +262 -242
  163. package/dist/src/unwrap.js +23 -0
  164. package/dist/src/usage.js +10 -0
  165. package/dist/src/vendor/unbash/ansi-c.js +132 -0
  166. package/dist/src/vendor/unbash/arithmetic-parts.js +37 -0
  167. package/dist/src/vendor/unbash/arithmetic.js +591 -0
  168. package/dist/src/vendor/unbash/assignment.js +131 -0
  169. package/dist/src/vendor/unbash/chars.js +48 -0
  170. package/dist/src/vendor/unbash/command.js +41 -0
  171. package/dist/src/vendor/unbash/expansion.js +80 -0
  172. package/dist/src/vendor/unbash/glob.js +268 -0
  173. package/dist/src/vendor/unbash/heredoc.js +27 -0
  174. package/dist/src/vendor/unbash/internal-types.js +1 -0
  175. package/dist/src/vendor/unbash/lexer.js +4274 -0
  176. package/dist/src/vendor/unbash/limits.js +3 -0
  177. package/dist/src/vendor/unbash/parser.js +1366 -0
  178. package/dist/src/vendor/unbash/parts.js +57 -0
  179. package/dist/src/vendor/unbash/substitution-context.js +8 -0
  180. package/dist/src/vendor/unbash/traversal.js +212 -0
  181. package/dist/src/vendor/unbash/types.js +1 -0
  182. package/dist/src/vendor/unbash/word-value.js +61 -0
  183. package/dist/src/vendor/unbash/word.js +40 -0
  184. package/dist/src/verbs/analyze.js +194 -127
  185. package/dist/src/verbs/describe.js +13 -18
  186. package/dist/src/verbs/explain.js +85 -139
  187. package/dist/src/verbs/print-config.js +2 -1
  188. package/dist/src/verbs/print-projects.js +6 -4
  189. package/dist/src/verbs/print-retained.js +30 -6
  190. package/dist/src/verbs/print-roots.js +4 -2
  191. package/dist/src/verbs/verb.js +1 -5
  192. package/dist/src/verbs/version.js +14 -3
  193. package/jsr.json +2 -1
  194. package/package.json +14 -8
  195. package/src/alias-chain.ts +40 -11
  196. package/src/amd.ts +130 -0
  197. package/src/analysis.ts +426 -733
  198. package/src/augmentations.ts +93 -4
  199. package/src/automatic-types.ts +12 -30
  200. package/src/bindings.ts +460 -0
  201. package/src/commands/held.ts +632 -0
  202. package/src/commands/read.ts +242 -0
  203. package/src/commands/shell.ts +228 -0
  204. package/src/commands/tools.ts +2382 -0
  205. package/src/component-files.ts +4 -2
  206. package/src/component-layer.ts +4 -2
  207. package/src/config.ts +31 -302
  208. package/src/conformance-record.ts +2 -2
  209. package/src/consumers.ts +16 -66
  210. package/src/contextual-uses.ts +66 -34
  211. package/src/contract/config.generated.ts +821 -0
  212. package/src/contract/contract.generated.ts +1453 -0
  213. package/src/contract/report.generated.ts +1241 -0
  214. package/src/dependencies.ts +223 -128
  215. package/src/destructuring.ts +1 -31
  216. package/src/edges.ts +41 -140
  217. package/src/element-access.ts +190 -187
  218. package/src/entries/build-scripts.ts +292 -0
  219. package/src/{configuration-files.ts → entries/configuration-files.ts} +68 -278
  220. package/src/{convention-rows.ts → entries/convention-rows.ts} +227 -31
  221. package/src/{conventions.ts → entries/conventions.ts} +367 -583
  222. package/src/{html-entries.ts → entries/html-entries.ts} +22 -48
  223. package/src/{mdx-entries.ts → entries/mdx-entries.ts} +7 -30
  224. package/src/entries/run-directories.ts +108 -0
  225. package/src/entries/sources.ts +266 -0
  226. package/src/entries/static-module.ts +858 -0
  227. package/src/entries/test-runners.ts +835 -0
  228. package/src/entries/workflow-steps.ts +432 -0
  229. package/src/exemptions/argument-places.ts +198 -0
  230. package/src/exemptions/calls.ts +483 -0
  231. package/src/exemptions/classes.ts +49 -0
  232. package/src/exemptions/decorator.ts +56 -0
  233. package/src/exemptions/detectors.ts +75 -0
  234. package/src/{enum-group.ts → exemptions/enum-group.ts} +10 -19
  235. package/src/{erased-stores.ts → exemptions/erased-stores.ts} +7 -14
  236. package/src/{framework-lifecycle.ts → exemptions/framework-lifecycle.ts} +85 -66
  237. package/src/exemptions/generated-file.ts +318 -0
  238. package/src/{injection-container.ts → exemptions/injection-container.ts} +29 -34
  239. package/src/exemptions/installed-globals.ts +255 -0
  240. package/src/{interface-satisfaction.ts → exemptions/interface-satisfaction.ts} +69 -160
  241. package/src/exemptions/lifecycle.ts +286 -0
  242. package/src/{reflective-lookup.ts → exemptions/reflective-lookup.ts} +5 -5
  243. package/src/exemptions/serialization-contract.ts +1729 -0
  244. package/src/exemptions/sites.ts +293 -0
  245. package/src/{template-field.ts → exemptions/template-field.ts} +22 -32
  246. package/src/{value-reach.ts → exemptions/value-reach.ts} +16 -8
  247. package/src/exposure.ts +492 -0
  248. package/src/extensions.ts +45 -0
  249. package/src/facts.ts +46 -0
  250. package/src/failure.ts +63 -0
  251. package/src/file-facts.ts +15 -25
  252. package/src/finding.ts +10 -10
  253. package/src/findings/boundary.ts +11 -0
  254. package/src/findings/completion.ts +133 -64
  255. package/src/findings/dependencies-and-module-machinery.ts +4 -7
  256. package/src/findings/emitter.ts +9 -10
  257. package/src/findings/emitters.ts +38 -52
  258. package/src/{implementations.ts → findings/implementations.ts} +4 -4
  259. package/src/{in-operands.ts → findings/in-operands.ts} +4 -3
  260. package/src/findings/interfaces.ts +7 -9
  261. package/src/findings/intra-function.ts +16 -14
  262. package/src/findings/non-code-artifacts.ts +24 -15
  263. package/src/findings/reads-and-writes.ts +118 -41
  264. package/src/findings/self-check.ts +51 -38
  265. package/src/findings/unused-declarations.ts +31 -49
  266. package/src/findings/visibility-narrowing.ts +36 -40
  267. package/src/findings-pass.ts +15 -31
  268. package/src/fs/document.ts +70 -0
  269. package/src/fs/manifest.ts +96 -0
  270. package/src/fs/tree.ts +110 -0
  271. package/src/git-ignore.ts +50 -26
  272. package/src/host.ts +12 -5
  273. package/src/import-bindings.ts +98 -29
  274. package/src/index/sites.ts +781 -0
  275. package/src/index/values.ts +170 -0
  276. package/src/index.ts +2 -2
  277. package/src/indexed-access.ts +570 -527
  278. package/src/intra-function-parts.ts +73 -44
  279. package/src/inventory/commonjs.ts +696 -0
  280. package/src/inventory/enumerate.ts +203 -0
  281. package/src/inventory/syntax.ts +311 -0
  282. package/src/inventory.ts +442 -895
  283. package/src/javascript-file.ts +54 -0
  284. package/src/json-document.ts +241 -76
  285. package/src/keyof-comparisons.ts +133 -122
  286. package/src/kinds.ts +5 -413
  287. package/src/{components.ts → liveness/components.ts} +4 -6
  288. package/src/{graph.ts → liveness/graph.ts} +100 -35
  289. package/src/liveness/matrix.ts +162 -0
  290. package/src/liveness/sweep.ts +855 -0
  291. package/src/load/classify.ts +433 -0
  292. package/src/load/diagnostics.ts +154 -0
  293. package/src/load/discover.ts +471 -0
  294. package/src/{emit-map.ts → load/emit-map.ts} +1 -1
  295. package/src/load/expected-module.ts +194 -0
  296. package/src/load/load.ts +73 -0
  297. package/src/load/module-lookup.ts +50 -0
  298. package/src/load/package-scope.ts +74 -0
  299. package/src/load/plan.ts +513 -0
  300. package/src/load/specifiers.ts +171 -0
  301. package/src/load/synthesize.ts +230 -0
  302. package/src/load/test-globals.ts +251 -0
  303. package/src/load/test-joins.ts +98 -0
  304. package/src/{workspace-manifests.ts → load/workspace-manifests.ts} +5 -5
  305. package/src/{workspace-programs.ts → load/workspace-programs.ts} +128 -85
  306. package/src/{workspace-resolution.ts → load/workspace-resolution.ts} +41 -77
  307. package/src/{workspace-run.ts → load/workspace-run.ts} +18 -16
  308. package/src/{workspace.ts → load/workspace.ts} +90 -134
  309. package/src/module-declarations.ts +74 -98
  310. package/src/overrides.ts +162 -134
  311. package/src/partial.ts +3 -2
  312. package/src/paths.ts +92 -16
  313. package/src/platform-calls.ts +119 -0
  314. package/src/platform-symbols.ts +189 -0
  315. package/src/position.ts +44 -1
  316. package/src/print.ts +12 -92
  317. package/src/product.ts +18 -0
  318. package/src/query.ts +201 -10
  319. package/src/ref.ts +12 -20
  320. package/src/references/read-rule.ts +60 -0
  321. package/src/references/read-rules.ts +55 -0
  322. package/src/references/sink.ts +314 -0
  323. package/src/references/sources.ts +632 -0
  324. package/src/references.ts +187 -1450
  325. package/src/report-schema.ts +68 -0
  326. package/src/report.ts +103 -226
  327. package/src/reporters/annotations.ts +22 -11
  328. package/src/reporters/json.ts +1 -1
  329. package/src/reporters/reporter.ts +2 -4
  330. package/src/reporters/reporters.ts +1 -1
  331. package/src/reporters/sarif.ts +29 -16
  332. package/src/reporters/template.ts +4 -20
  333. package/src/reporters/text.ts +3 -3
  334. package/src/resolve.ts +284 -1115
  335. package/src/{configured-declarations.ts → roots/configured-declarations.ts} +26 -29
  336. package/src/{entry-point-gaps.ts → roots/entry-point-gaps.ts} +7 -16
  337. package/src/roots/manifest.ts +303 -0
  338. package/src/roots/published-reach.ts +486 -0
  339. package/src/{roots.ts → roots/root-set.ts} +286 -469
  340. package/src/roots/unseen-loads.ts +345 -0
  341. package/src/run.ts +75 -91
  342. package/src/schema.ts +391 -388
  343. package/src/scope.ts +46 -138
  344. package/src/session.ts +87 -55
  345. package/src/source-files.ts +6 -11
  346. package/src/stores.ts +15 -3
  347. package/src/suppress-file.ts +24 -33
  348. package/src/suppress-inline.ts +55 -91
  349. package/src/suppress.ts +78 -79
  350. package/src/symbol-keys.ts +104 -107
  351. package/src/tests/file-class.ts +135 -0
  352. package/src/{outside-tests.ts → tests/outside.ts} +16 -10
  353. package/src/{test-support.ts → tests/support.ts} +15 -21
  354. package/src/text/compare.ts +27 -0
  355. package/src/text/glob.ts +210 -0
  356. package/src/text/named-files.ts +388 -0
  357. package/src/text/yaml.ts +747 -0
  358. package/src/type-errors.ts +18 -288
  359. package/src/type-parameter-reads.ts +187 -158
  360. package/src/unimplemented-callees.ts +297 -280
  361. package/src/unwrap.ts +34 -0
  362. package/src/usage.ts +10 -0
  363. package/src/vendor/unbash/LICENSE +15 -0
  364. package/src/vendor/unbash/VENDORED.md +16 -0
  365. package/src/vendor/unbash/ansi-c.ts +132 -0
  366. package/src/vendor/unbash/arithmetic-parts.ts +53 -0
  367. package/src/vendor/unbash/arithmetic.ts +641 -0
  368. package/src/vendor/unbash/assignment.ts +163 -0
  369. package/src/vendor/unbash/chars.ts +48 -0
  370. package/src/vendor/unbash/command.ts +47 -0
  371. package/src/vendor/unbash/expansion.ts +144 -0
  372. package/src/vendor/unbash/glob.ts +284 -0
  373. package/src/vendor/unbash/heredoc.ts +34 -0
  374. package/src/vendor/unbash/internal-types.ts +94 -0
  375. package/src/vendor/unbash/lexer.ts +4352 -0
  376. package/src/vendor/unbash/limits.ts +3 -0
  377. package/src/vendor/unbash/parser.ts +1612 -0
  378. package/src/vendor/unbash/parts.ts +96 -0
  379. package/src/vendor/unbash/substitution-context.ts +20 -0
  380. package/src/vendor/unbash/traversal.ts +182 -0
  381. package/src/vendor/unbash/types.ts +660 -0
  382. package/src/vendor/unbash/word-value.ts +64 -0
  383. package/src/vendor/unbash/word.ts +50 -0
  384. package/src/verbs/analyze.ts +255 -164
  385. package/src/verbs/describe.ts +19 -17
  386. package/src/verbs/explain.ts +93 -169
  387. package/src/verbs/print-config.ts +2 -1
  388. package/src/verbs/print-projects.ts +6 -4
  389. package/src/verbs/print-retained.ts +36 -6
  390. package/src/verbs/print-roots.ts +4 -2
  391. package/src/verbs/verb.ts +2 -8
  392. package/src/verbs/version.ts +15 -3
  393. package/dist/src/base-url.js +0 -18
  394. package/dist/src/calls.js +0 -155
  395. package/dist/src/conventions.js +0 -937
  396. package/dist/src/discover.js +0 -468
  397. package/dist/src/entry-points.js +0 -529
  398. package/dist/src/exempt-classes.js +0 -75
  399. package/dist/src/exempt.js +0 -209
  400. package/dist/src/generated-file.js +0 -95
  401. package/dist/src/glob.js +0 -65
  402. package/dist/src/manifest.js +0 -165
  403. package/dist/src/matrix.js +0 -246
  404. package/dist/src/pnpm-workspace.js +0 -120
  405. package/dist/src/roots.js +0 -672
  406. package/dist/src/serialization-contract.js +0 -611
  407. package/dist/src/setup-failure.js +0 -23
  408. package/dist/src/sweep.js +0 -224
  409. package/dist/src/test-joins.js +0 -101
  410. package/dist/src/value-flow.js +0 -74
  411. package/dist/src/version.js +0 -7
  412. package/dist/src/workflow-steps.js +0 -185
  413. package/src/base-url.ts +0 -24
  414. package/src/calls.ts +0 -225
  415. package/src/decorator.ts +0 -78
  416. package/src/discover.ts +0 -653
  417. package/src/entry-points.ts +0 -687
  418. package/src/exempt-classes.ts +0 -123
  419. package/src/exempt.ts +0 -323
  420. package/src/generated-file.ts +0 -111
  421. package/src/glob.ts +0 -67
  422. package/src/manifest.ts +0 -234
  423. package/src/matrix.ts +0 -423
  424. package/src/pnpm-workspace.ts +0 -135
  425. package/src/serialization-contract.ts +0 -849
  426. package/src/setup-failure.ts +0 -39
  427. package/src/sweep.ts +0 -347
  428. package/src/test-joins.ts +0 -120
  429. package/src/value-flow.ts +0 -104
  430. package/src/version.ts +0 -7
  431. package/src/workflow-steps.ts +0 -216
@@ -0,0 +1,173 @@
1
+ /**
2
+ * The classes a program installs as globals: a class value written into a property of
3
+ * the global object, which code outside the analysis that names the global constructs.
4
+ * The checker finds each write: the receiver's type is the global object's, the callee is
5
+ * the standard library's `Object.defineProperty` or a test runner's stub, and the
6
+ * property is the one of the key's name that `typeof globalThis` declares.
7
+ */
8
+ import { isIdentifier, isNoSubstitutionTemplateLiteral, isObjectLiteralExpression, isPropertyAssignment, isShorthandPropertyAssignment, isStringLiteral, } from "@typescript/native/ast";
9
+ import { SignatureKind, SymbolFlags, } from "@typescript/native/sync";
10
+ import { typesAt } from "../class-members.js";
11
+ import { packageOfPath } from "../dependencies.js";
12
+ import { must } from "../query.js";
13
+ import { parenthesesRemoved, unwrapped } from "../unwrap.js";
14
+ import { spansOf } from "./argument-places.js";
15
+ import { classesCarried } from "./calls.js";
16
+ /**
17
+ * The test runners' stubs of a global, by method name and the packages that declare it:
18
+ * `vi.stubGlobal` of vitest, and `jest.replaceProperty`, which `@jest/environment` types
19
+ * for `@jest/globals` and `@types/jest` declares for the `jest` global.
20
+ */
21
+ const STUBS = new Map([
22
+ [
23
+ "stubGlobal",
24
+ { packages: new Set(["vitest"]), object: undefined, key: 0, value: 1, described: false },
25
+ ],
26
+ [
27
+ "replaceProperty",
28
+ {
29
+ packages: new Set(["@jest/environment", "@jest/globals", "@types/jest"]),
30
+ object: 0,
31
+ key: 1,
32
+ value: 2,
33
+ described: false,
34
+ },
35
+ ],
36
+ ]);
37
+ /** `Object.defineProperty(object, key, descriptor)`. */
38
+ const DEFINE = { object: 0, key: 1, value: 2, described: true };
39
+ /** The text of a key written as a string literal. */
40
+ function keyText(node) {
41
+ const key = node === undefined ? undefined : parenthesesRemoved(node);
42
+ return key !== undefined && (isStringLiteral(key) || isNoSubstitutionTemplateLiteral(key))
43
+ ? key.text
44
+ : undefined;
45
+ }
46
+ /** Whether a property's name is `value`. */
47
+ function named(name) {
48
+ return (isIdentifier(name) || isStringLiteral(name)) && name.text === "value";
49
+ }
50
+ /** The value a property descriptor written as an object literal gives. */
51
+ function describedValue(node) {
52
+ const descriptor = node === undefined ? undefined : parenthesesRemoved(node);
53
+ if (descriptor === undefined || !isObjectLiteralExpression(descriptor)) {
54
+ return undefined;
55
+ }
56
+ for (const property of descriptor.properties) {
57
+ if (isPropertyAssignment(property) && named(property.name)) {
58
+ return property.initializer;
59
+ }
60
+ if (isShorthandPropertyAssignment(property) &&
61
+ isIdentifier(property.name) &&
62
+ named(property.name)) {
63
+ return property.name;
64
+ }
65
+ }
66
+ return undefined;
67
+ }
68
+ /** How a call's callee writes a property: the standard library's `Object.defineProperty` or a runner's stub. */
69
+ function writerOf(project, method) {
70
+ if (method.name === "defineProperty") {
71
+ const standard = method.declarations.some((handle) => project.program.getSourceFileMetadata(handle.path)?.isDefaultLibrary === true);
72
+ return standard && must(project.queries.parentOf(method))?.name === "ObjectConstructor"
73
+ ? DEFINE
74
+ : undefined;
75
+ }
76
+ const stub = STUBS.get(method.name);
77
+ return stub !== undefined &&
78
+ method.declarations.some((handle) => stub.packages.has(packageOfPath(handle.path) ?? ""))
79
+ ? stub
80
+ : undefined;
81
+ }
82
+ /** Each write of one project's own files that may install a value as a global, read from syntax and the callee. */
83
+ function writesOf(project, sites) {
84
+ const found = sites.stores.map((store) => ({
85
+ site: store.store,
86
+ receiver: store.receiver,
87
+ key: store.key,
88
+ value: store.value,
89
+ }));
90
+ for (const { call } of sites.calls) {
91
+ const method = sites.invocations.callee(call);
92
+ const writer = method === undefined ? undefined : writerOf(project, method);
93
+ if (writer === undefined) {
94
+ continue;
95
+ }
96
+ const invoked = sites.invocations.of(call);
97
+ // With no types asked, a spread has no known length, so only a place no spread
98
+ // comes at or before is read.
99
+ const spans = spansOf(project, invoked.arguments, invoked.listed, []);
100
+ const at = (place) => {
101
+ const span = spans.find((one) => !one.open && one.first === place);
102
+ return span === undefined ? undefined : invoked.arguments[span.argument];
103
+ };
104
+ const key = keyText(at(writer.key));
105
+ const receiver = writer.object === undefined ? undefined : at(writer.object);
106
+ const value = writer.described ? describedValue(at(writer.value)) : at(writer.value);
107
+ if (key !== undefined &&
108
+ value !== undefined &&
109
+ (writer.object === undefined || receiver !== undefined)) {
110
+ found.push({ site: call, receiver, key, value });
111
+ }
112
+ }
113
+ return found;
114
+ }
115
+ /**
116
+ * The classes one project installs as globals. A write installs one where its object is
117
+ * the global object, as the checker types it (`window` and `self` are intersections that
118
+ * hold `typeof globalThis`, and an object asserted to `any` is read inside the
119
+ * assertion), and where the global object declares a property of the key's name with a
120
+ * construct signature, whose instances code outside the analysis makes.
121
+ */
122
+ export function installedGlobals(project, held, chains, sites) {
123
+ const { queries } = project;
124
+ const writes = writesOf(project, sites);
125
+ if (writes.length === 0) {
126
+ return [];
127
+ }
128
+ const global = must(queries.resolveName("globalThis", SymbolFlags.Value, undefined, false));
129
+ const globalType = global === undefined ? undefined : must(queries.typeOfSymbol(global));
130
+ if (global === undefined || globalType === undefined) {
131
+ return [];
132
+ }
133
+ const properties = new Map(must(queries.propertiesOf(globalType)).map((property) => [property.name, property]));
134
+ const keyed = writes.filter((write) => properties.has(write.key));
135
+ const objects = keyed.flatMap((write) => write.receiver === undefined ? [] : [unwrapped(write.receiver)]);
136
+ const objectTypes = new Map(typesAt(project, objects).map((type, at) => [objects[at], type]));
137
+ const globals = new Map();
138
+ const isGlobal = (type) => {
139
+ if (type === undefined) {
140
+ return false;
141
+ }
142
+ let known = globals.get(type.id);
143
+ if (known === undefined) {
144
+ const parts = type.isUnionType() || type.isIntersectionType() ? must(queries.constituents(type)) : [type];
145
+ known = parts.some((part) => must(queries.symbolOfType(part))?.id === global.id);
146
+ globals.set(type.id, known);
147
+ }
148
+ return known;
149
+ };
150
+ const installs = keyed.filter((write) => write.receiver === undefined || isGlobal(objectTypes.get(unwrapped(write.receiver))));
151
+ if (installs.length === 0) {
152
+ return [];
153
+ }
154
+ const instances = new Map();
155
+ const instancesOf = (key) => {
156
+ let made = instances.get(key);
157
+ if (made === undefined) {
158
+ const property = properties.get(key);
159
+ const type = property === undefined ? undefined : must(queries.typeOfSymbol(property));
160
+ made = (type === undefined ? [] : must(queries.signaturesOf(type, SignatureKind.Construct))).flatMap((signature) => must(queries.returnTypeOf(signature)) ?? []);
161
+ instances.set(key, made);
162
+ }
163
+ return made;
164
+ };
165
+ const carried = classesCarried(project, held, chains, sites, installs.map((write) => [write.value]));
166
+ return installs.flatMap((write, at) => {
167
+ const uses = carried[at] ?? [];
168
+ const made = uses.length === 0 ? [] : instancesOf(write.key);
169
+ return made.length === 0
170
+ ? []
171
+ : uses.map((use) => ({ id: use.id, site: write.site, global: write.key, instances: made }));
172
+ });
173
+ }
@@ -3,85 +3,41 @@
3
3
  * reaches a position typed as an interface, or an object type a type alias names, that
4
4
  * requires the member: an `implements` entry, a typed initializer, an assignment, an
5
5
  * argument, a return, an array element, an object property or an `as` or `satisfies`
6
- * operand. `this` is a value of its class; a type parameter reaches its constraint. The
6
+ * operand. `this` is a value of its class; a type parameter reaches its constraint. A
7
+ * class installed as a global reaches the instance type the global constructs, whether
8
+ * or not it is assignable to it, because a stub answers only what its caller uses. The
7
9
  * contextual lookup has no batch form, so it is asked only of a value of a target class.
8
10
  */
9
- import { isCallExpression, isClassDeclaration, isClassExpression, isClassStaticBlockDeclaration, isFunctionDeclaration, isFunctionExpression, isGetAccessorDeclaration, isHeritageClause, isMethodDeclaration, isNewExpression, isObjectLiteralExpression, isSetAccessorDeclaration, isTypeLiteralNode, ModifierFlags, SyntaxKind, } from "@typescript/native/ast";
11
+ import { isCallExpression, isHeritageClause, isNewExpression, isTypeLiteralNode, SyntaxKind, } from "@typescript/native/ast";
10
12
  import { SymbolFlags } from "@typescript/native/sync";
11
- import { aliasChains } from "./alias-chain.js";
12
- import { emptyImplementation } from "./implementations.js";
13
- import { nodeKey } from "./inventory.js";
14
- import { renderPosition } from "./position.js";
15
- import { must } from "./query.js";
16
- import { handedOn, valuesOf } from "./value-flow.js";
13
+ import { aliasChains } from "../alias-chain.js";
14
+ import { emptyImplementation } from "../findings/implementations.js";
15
+ import { installedGlobals } from "./installed-globals.js";
16
+ import { renderPosition } from "../position.js";
17
+ import { must } from "../query.js";
17
18
  /** Whether a type alias names one type: the client's type object carries the alias it was written through. */
18
19
  function aliased(type) {
19
20
  return type.aliasSymbol !== undefined;
20
21
  }
21
- /** Whether one node declares a static member, whose `this` is the class itself. */
22
- function isStatic(node) {
23
- const flags = node.modifierFlags ?? 0;
24
- return (flags & ModifierFlags.Static) !== 0;
25
- }
26
- /** Whether one node is a method or an accessor of an object literal, whose `this` is the literal. */
27
- function isObjectLiteralMethod(node) {
28
- return ((isMethodDeclaration(node) ||
29
- isGetAccessorDeclaration(node) ||
30
- isSetAccessorDeclaration(node)) &&
31
- isObjectLiteralExpression(node.parent));
32
- }
33
22
  /**
34
- * The classes, the `implements` entries and the flowing values of one project's own
35
- * files. `this` is the class an instance member belongs to, so a function that is not
36
- * an arrow, a static member and a static block each stop it.
23
+ * The named classes, the `implements` entries and the flowing values of one project's own
24
+ * files, a value `this` standing for the class it is an instance of.
37
25
  */
38
- function walk(files, declarations) {
39
- const classes = [];
40
- const clauses = [];
41
- const flows = [];
42
- for (const file of files) {
43
- const visit = (node, self) => {
44
- let inner = self;
45
- if (isClassDeclaration(node) || isClassExpression(node)) {
46
- const id = declarations.get(nodeKey(file, node));
47
- const name = node.name;
48
- const owner = id === undefined || name === undefined
49
- ? undefined
50
- : { id, name, generic: node.typeParameters !== undefined };
51
- if (owner !== undefined) {
52
- classes.push(owner);
53
- for (const clause of node.heritageClauses ?? []) {
54
- if (isHeritageClause(clause) && clause.token === SyntaxKind.ImplementsKeyword) {
55
- clauses.push(...clause.types.map((entry) => ({ owner, entry })));
56
- }
57
- }
58
- }
59
- inner = owner;
60
- }
61
- else if (isFunctionDeclaration(node) ||
62
- isFunctionExpression(node) ||
63
- isClassStaticBlockDeclaration(node) ||
64
- isStatic(node) ||
65
- isObjectLiteralMethod(node)) {
66
- inner = undefined;
67
- }
68
- for (const written of handedOn(node)) {
69
- for (const value of valuesOf(written)) {
70
- flows.push({
71
- value,
72
- self: value.kind === SyntaxKind.ThisKeyword ? inner : undefined,
73
- });
74
- }
75
- }
76
- node.forEachChild((child) => {
77
- visit(child, inner);
78
- });
79
- };
80
- file.forEachChild((child) => {
81
- visit(child, undefined);
82
- });
83
- }
84
- return { classes, clauses, flows };
26
+ function walked(sites) {
27
+ const classes = sites.classes.flatMap(({ id, node }) => node.name === undefined
28
+ ? []
29
+ : [{ id, name: node.name, generic: node.typeParameters !== undefined, node }]);
30
+ const byId = new Map(classes.map((owner) => [owner.id, owner]));
31
+ return {
32
+ classes,
33
+ clauses: classes.flatMap((owner) => (owner.node.heritageClauses ?? []).flatMap((clause) => isHeritageClause(clause) && clause.token === SyntaxKind.ImplementsKeyword
34
+ ? clause.types.map((entry) => ({ owner, entry }))
35
+ : [])),
36
+ flows: sites.flows.map((flow) => ({
37
+ value: flow.value,
38
+ self: flow.self === undefined ? undefined : byId.get(flow.self),
39
+ })),
40
+ };
85
41
  }
86
42
  /**
87
43
  * The interface-satisfaction detector: for each class type that reaches an interface
@@ -91,8 +47,8 @@ function walk(files, declarations) {
91
47
  export function interfaceSatisfaction(input) {
92
48
  const { project, held, targetRoot } = input;
93
49
  const queries = project.queries;
94
- const files = project.ownSourceFiles();
95
- const { classes, clauses, flows } = walk(files, held.declarations);
50
+ const chains = aliasChains(project, held);
51
+ const { classes, clauses, flows } = walked(input.sites);
96
52
  if (classes.length === 0) {
97
53
  return [];
98
54
  }
@@ -197,13 +153,15 @@ export function interfaceSatisfaction(input) {
197
153
  const pairs = new Map();
198
154
  const reach = (owner, source, target, name, site) => {
199
155
  const key = `${String(source.id)}:${String(target.id)}`;
200
- const pair = pairs.get(key);
156
+ let pair = pairs.get(key);
201
157
  if (pair === undefined) {
202
- pairs.set(key, { owner, source, target, name, sites: [site] });
158
+ pair = { owner, source, target, name, sites: [site] };
159
+ pairs.set(key, pair);
203
160
  }
204
161
  else {
205
162
  pair.sites.push(site);
206
163
  }
164
+ return pair;
207
165
  };
208
166
  for (const clause of clauses) {
209
167
  const source = instanceOf.get(clause.owner.id);
@@ -237,14 +195,26 @@ export function interfaceSatisfaction(input) {
237
195
  }
238
196
  }
239
197
  });
240
- const chains = aliasChains(project, held);
198
+ const byId = new Map(classes.map((owner) => [owner.id, owner]));
199
+ for (const one of installedGlobals(project, held, chains, input.sites)) {
200
+ const owner = byId.get(one.id);
201
+ const source = instanceOf.get(one.id);
202
+ if (owner === undefined || source === undefined) {
203
+ continue;
204
+ }
205
+ for (const instance of one.instances) {
206
+ reach(owner, source, instance, one.global, one.site).installed = one.global;
207
+ }
208
+ }
241
209
  const required = new Map();
242
210
  const members = new Map();
243
211
  const found = [];
244
- const asking = [...pairs.values()];
245
- const assignable = queries.assignableEach(asking);
246
- for (const [index, pair] of asking.entries()) {
247
- if (!must(assignable[index] ?? false)) {
212
+ const asking = [...pairs.values()].filter((pair) => pair.installed === undefined);
213
+ const assignable = new Set(queries
214
+ .assignableEach(asking)
215
+ .flatMap((answer, index) => (must(answer) ? [asking[index]] : [])));
216
+ for (const pair of pairs.values()) {
217
+ if (pair.installed === undefined && !assignable.has(pair)) {
248
218
  continue;
249
219
  }
250
220
  let names = required.get(pair.target.id);
@@ -267,7 +237,9 @@ export function interfaceSatisfaction(input) {
267
237
  ]));
268
238
  members.set(pair.owner.id, answering);
269
239
  }
270
- const detail = `satisfies ${pair.name}`;
240
+ const detail = pair.installed === undefined
241
+ ? `satisfies ${pair.name}`
242
+ : `installed as the global ${pair.installed}`;
271
243
  for (const [name, methods] of names) {
272
244
  const member = answering.get(name);
273
245
  for (const id of member?.ids ?? []) {
@@ -284,44 +256,3 @@ export function interfaceSatisfaction(input) {
284
256
  }
285
257
  return found;
286
258
  }
287
- /**
288
- * Each project's records with every record dropped whose member implements only interface
289
- * methods nothing calls, unless every implementation of such a method is empty, and a
290
- * reference from each such method to the member, which then falls with the method.
291
- * `references` is every reference of the run, a consumer's included.
292
- */
293
- export function settledSatisfaction(projects, references) {
294
- const methods = new Set(projects.flatMap((one) => one.held.symbols.filter((symbol) => symbol.kind === "interface-method").map((one) => one.id)));
295
- const called = new Set(references.map((reference) => reference.to));
296
- const bodies = new Map();
297
- for (const record of projects.flatMap((one) => one.evidence)) {
298
- for (const method of record.implementing?.methods ?? []) {
299
- bodies.set(method, (bodies.get(method) ?? true) && record.implementing?.empty === true);
300
- }
301
- }
302
- const uncalled = (method) => methods.has(method) && !called.has(method) && bodies.get(method) !== true;
303
- return projects.map(({ evidence }) => {
304
- const kept = [];
305
- const added = [];
306
- for (const record of evidence) {
307
- const implemented = record.implementing?.methods ?? [];
308
- if (record.class !== "interface-satisfaction" ||
309
- implemented.length === 0 ||
310
- !implemented.every(uncalled)) {
311
- kept.push(record);
312
- continue;
313
- }
314
- for (const method of implemented) {
315
- added.push({
316
- from: method,
317
- to: record.id,
318
- position: record.site,
319
- use: "read",
320
- resolution: "override",
321
- test: false,
322
- });
323
- }
324
- }
325
- return { evidence: kept, references: added };
326
- });
327
- }
@@ -0,0 +1,150 @@
1
+ /**
2
+ * The exemption lifecycle: the classes of reason for which a declaration the reference
3
+ * graph alone would report is live all the same. A class is policy over what one
4
+ * project's checker answers, and its detector names the declarations it holds back. This
5
+ * module runs the detectors over one project, then settles every project's records
6
+ * against the run: the writes they wait for, the interface methods they wait to be
7
+ * called, and the mode and test files that decide which of them hold. It names no class:
8
+ * the composition hands it the table of the classes it has.
9
+ */
10
+ import { EXEMPTION_CLASSES } from "../contract/contract.generated.js";
11
+ import { byPosition } from "../position.js";
12
+ import { Unanswerable } from "../query.js";
13
+ import { bytewise } from "../text/compare.js";
14
+ import { TS_EXEMPTION_CLASSES, typescriptVisibilityOf, } from "./classes.js";
15
+ import { projectSites } from "./sites.js";
16
+ /**
17
+ * Whether a class whose row states `allowed` may retain a member of one visibility. A
18
+ * declaration the inventory does not hold has no visibility to refuse it by.
19
+ */
20
+ function retainable(allowed, visibility) {
21
+ if (visibility === "private") {
22
+ return allowed.private;
23
+ }
24
+ if (visibility === "private-name") {
25
+ return allowed.privateName;
26
+ }
27
+ return true;
28
+ }
29
+ /** The kinds of declaration each class can hold back, which a detector that stops holds back whole. */
30
+ const RETAINABLE = new Map(EXEMPTION_CLASSES.flatMap((row) => "ts" in row.retainsKinds ? [[row.class, new Set(row.retainsKinds.ts)]] : []));
31
+ /**
32
+ * What one detector holds back over one project. A detector that stops because the
33
+ * checker left a question it needs unanswered holds back every declaration of the
34
+ * project its class could hold back, each recorded at its own position, so the gap
35
+ * never yields a finding.
36
+ */
37
+ function detected(exemptionClass, detect, input) {
38
+ try {
39
+ return detect(input);
40
+ }
41
+ catch (error) {
42
+ if (!(error instanceof Unanswerable)) {
43
+ throw error;
44
+ }
45
+ const kinds = RETAINABLE.get(exemptionClass);
46
+ return input.held.symbols
47
+ .filter((symbol) => kinds?.has(symbol.kind) === true)
48
+ .map((symbol) => ({
49
+ id: symbol.id,
50
+ detail: "kept live by a question the checker did not answer",
51
+ site: symbol.position,
52
+ unanswered: true,
53
+ }));
54
+ }
55
+ }
56
+ /**
57
+ * Every record one project's detectors found, one per piece of evidence, before the run
58
+ * settles which of them hold. Classes run in the vocabulary's order and a switched-off
59
+ * class runs not at all; evidence on a private member the class's row says it cannot
60
+ * retain is dropped, whatever the detector found.
61
+ */
62
+ export function detect(input, detectors, disabled) {
63
+ const visibility = new Map(input.held.symbols.map((symbol) => [symbol.id, symbol.visibility]));
64
+ const sited = { ...input, sites: projectSites(input.project, input.held) };
65
+ return TS_EXEMPTION_CLASSES.flatMap((exemptionClass) => {
66
+ const run = detectors.get(exemptionClass);
67
+ if (run === undefined || disabled.has(exemptionClass)) {
68
+ return [];
69
+ }
70
+ const allowed = typescriptVisibilityOf(exemptionClass);
71
+ return detected(exemptionClass, run, sited).flatMap((evidence) => retainable(allowed, visibility.get(evidence.id))
72
+ ? [{ ...evidence, class: exemptionClass }]
73
+ : []);
74
+ });
75
+ }
76
+ /**
77
+ * Every project's records settled against the run, in three steps. A record that holds
78
+ * only while written holds where a write the mode counts stores into its declaration.
79
+ * A record whose member implements only interface methods nothing calls is dropped,
80
+ * unless every implementation of such a method is empty. Under a production mode a
81
+ * record whose evidence a test file writes holds nothing, and is a test reference to its
82
+ * declaration, as a reference the test file wrote would be.
83
+ */
84
+ export function settle(projects, run) {
85
+ const written = projects.map((one) => one.records.flatMap(({ whileWritten, ...record }) => whileWritten === undefined || run.written.has(record.id) ? [record] : []));
86
+ const methods = new Set(projects.flatMap((one) => one.held.symbols.filter((symbol) => symbol.kind === "interface-method").map((one) => one.id)));
87
+ const called = new Set(run.references.map((reference) => reference.to));
88
+ const bodies = new Map();
89
+ for (const record of written.flat()) {
90
+ for (const method of record.implementing?.methods ?? []) {
91
+ bodies.set(method, (bodies.get(method) ?? true) && record.implementing?.empty === true);
92
+ }
93
+ }
94
+ const uncalled = (method) => methods.has(method) && !called.has(method) && bodies.get(method) !== true;
95
+ return projects.map((project, index) => {
96
+ const files = new Map(project.held.symbols
97
+ .filter((symbol) => symbol.kind === "file")
98
+ .map((symbol) => [symbol.position.path, symbol.id]));
99
+ const kept = [];
100
+ const references = [];
101
+ const tested = [];
102
+ for (const record of written[index] ?? []) {
103
+ const implemented = record.implementing?.methods ?? [];
104
+ if (implemented.length > 0 && implemented.every(uncalled)) {
105
+ references.push(...implemented.map((method) => ({
106
+ from: method,
107
+ to: record.id,
108
+ position: record.site,
109
+ use: "read",
110
+ resolution: "override",
111
+ test: false,
112
+ })));
113
+ }
114
+ else if (run.mode.production && project.testFiles.has(record.site.path)) {
115
+ const from = files.get(record.site.path);
116
+ if (from !== undefined) {
117
+ tested.push({
118
+ from,
119
+ to: record.id,
120
+ position: record.site,
121
+ use: "read",
122
+ resolution: "syntax",
123
+ test: true,
124
+ });
125
+ }
126
+ }
127
+ else {
128
+ kept.push(record);
129
+ }
130
+ }
131
+ return { records: exemptionsOf(kept), references: [...references, ...tested] };
132
+ });
133
+ }
134
+ /**
135
+ * Records as a run holds them: ordered by site, then class, then declaration, and one
136
+ * per declaration, class, detail and file it holds while live, the one at the first
137
+ * site. A fact found at many sites, or by several projects, is one record.
138
+ */
139
+ export function exemptionsOf(found) {
140
+ const ordered = [...found].sort((a, b) => byPosition(a.site, b.site) || bytewise(a.class, b.class) || bytewise(a.id, b.id));
141
+ const seen = new Set();
142
+ return ordered.filter((record) => {
143
+ const fact = [record.id, record.class, record.detail, record.whileLive ?? ""].join("\u0000");
144
+ if (seen.has(fact)) {
145
+ return false;
146
+ }
147
+ seen.add(fact);
148
+ return true;
149
+ });
150
+ }
@@ -14,9 +14,9 @@
14
14
  */
15
15
  import { isCallExpression, isElementAccessExpression, isIdentifier, isNoSubstitutionTemplateLiteral, isPropertyAccessExpression, isStringLiteral, } from "@typescript/native/ast";
16
16
  import { TypeFlags } from "@typescript/native/sync";
17
- import { memberNames } from "./member-names.js";
18
- import { renderPosition } from "./position.js";
19
- import { isAnswered, UNANSWERED } from "./query.js";
17
+ import { memberNames } from "../member-names.js";
18
+ import { renderPosition } from "../position.js";
19
+ import { isAnswered, UNANSWERED } from "../query.js";
20
20
  /** The `Reflect` methods whose second argument is a property key. */
21
21
  const REFLECT_KEYED = new Set(["get", "set", "has"]);
22
22
  /** The text one key denotes, where it is literal text. */