@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
@@ -0,0 +1,189 @@
1
+ /**
2
+ * The platform's names read through a program's checker: its `require` and `URL`, as
3
+ * `platform-calls.ts` decides them, its worker constructors and `navigator`, and Node's
4
+ * `Worker`.
5
+ */
6
+
7
+ import {
8
+ isArrowFunction,
9
+ isClassDeclaration,
10
+ isClassExpression,
11
+ isFunctionDeclaration,
12
+ isFunctionExpression,
13
+ isMethodDeclaration,
14
+ isModuleDeclaration,
15
+ isPropertyAssignment,
16
+ isPropertyDeclaration,
17
+ isSourceFile,
18
+ isStringLiteralLikeNode,
19
+ isVariableDeclaration,
20
+ type Identifier,
21
+ type Node,
22
+ } from "@typescript/native/ast";
23
+ import { SymbolFlags, type Symbol as TSSymbol } from "@typescript/native/sync";
24
+ import { UNANSWERED, type Answer } from "./query.ts";
25
+ import type { ProjectView } from "./session.ts";
26
+ import { boundExports, NAMESPACE } from "./entries/static-module.ts";
27
+ import { isAmbient } from "./inventory.ts";
28
+ import { callsPlatformBy, carriedNames, type BindingOf, type Bound } from "./platform-calls.ts";
29
+ import { unwrapped } from "./unwrap.ts";
30
+
31
+ /** The symbol one symbol names through its aliases, or the symbol itself where it is none. */
32
+ function dealiased<Brand>(project: ProjectView<Brand>, symbol: TSSymbol): Answer<TSSymbol> {
33
+ if ((symbol.flags & SymbolFlags.Alias) === 0) {
34
+ return symbol;
35
+ }
36
+ return project.queries.aliased(symbol);
37
+ }
38
+
39
+ /** Each declaration of `symbol` in a file of the target, read in this project's program. */
40
+ function ownDeclarations<Brand>(project: ProjectView<Brand>, symbol: TSSymbol): readonly Node[] {
41
+ const own = project.ownPaths();
42
+ return symbol.declarations.flatMap((handle) => {
43
+ const node = own.has(handle.path) ? project.declarationAt(handle)?.node : undefined;
44
+ return node === undefined ? [] : [node];
45
+ });
46
+ }
47
+
48
+ /**
49
+ * Whether one declaration writes a function or a class with a body (roots.23): a function
50
+ * or method declaration with a body, a class declaration, or a variable, a property or a
51
+ * class field whose initializer is a function, an arrow function or a class expression,
52
+ * under no `declare` modifier and in no declaration file.
53
+ */
54
+ function writesBody(node: Node): boolean {
55
+ const value =
56
+ (isVariableDeclaration(node) || isPropertyAssignment(node) || isPropertyDeclaration(node)) &&
57
+ node.initializer !== undefined
58
+ ? unwrapped(node.initializer)
59
+ : node;
60
+ return (
61
+ (isFunctionDeclaration(value) || isMethodDeclaration(value)
62
+ ? value.body !== undefined
63
+ : isFunctionExpression(value) ||
64
+ isArrowFunction(value) ||
65
+ isClassDeclaration(value) ||
66
+ isClassExpression(value)) && !isAmbient(value.getSourceFile(), value)
67
+ );
68
+ }
69
+
70
+ /**
71
+ * What the checker binds `symbol` to, one alias step at a time: every name a step of the
72
+ * chain carries it by, and the declarations of the target its last step reaches, which
73
+ * prove it the target's own where one {@link writesBody}. A chain that ends at no
74
+ * declaration, or that the checker leaves unanswered, reaches none.
75
+ */
76
+ function boundBy<Brand>(
77
+ project: ProjectView<Brand>,
78
+ symbol: Answer<TSSymbol> | undefined,
79
+ ): Bound | undefined {
80
+ if (typeof symbol !== "object") {
81
+ return undefined;
82
+ }
83
+ const names = new Set<string>();
84
+ const stepped = new Set<number>();
85
+ for (let at: TSSymbol | undefined = symbol; at !== undefined && !stepped.has(at.id);) {
86
+ stepped.add(at.id);
87
+ names.add(at.name);
88
+ const own = ownDeclarations(project, at);
89
+ for (const node of own) {
90
+ carriedNames(node).forEach((one) => names.add(one));
91
+ }
92
+ if ((at.flags & SymbolFlags.Alias) === 0) {
93
+ return { names, own, provenOwn: own.some(writesBody) };
94
+ }
95
+ const next = project.aliasStepOf(at);
96
+ at = typeof next === "object" ? next : undefined;
97
+ }
98
+ return { names, own: [], provenOwn: false };
99
+ }
100
+
101
+ /** Each written name's binding, as this project's checker answers it. */
102
+ function checkerBinding<Brand>(project: ProjectView<Brand>): BindingOf {
103
+ return (written) => boundBy(project, project.symbolsAt([project.handle(written)])[0]);
104
+ }
105
+
106
+ /**
107
+ * Whether a call or construction through `callee`, the batch's answer for which is `symbol`,
108
+ * is one of the platform's `require`, AMD's `define` or `URL` (roots.23, references-ts.37,
109
+ * references-ts.1), as {@link callsPlatformBy} decides it over this project's checker.
110
+ */
111
+ export function callsPlatform<Brand>(
112
+ project: ProjectView<Brand>,
113
+ name: "require" | "define" | "URL",
114
+ callee: Identifier,
115
+ symbol: Answer<TSSymbol> | undefined,
116
+ ): boolean {
117
+ const others = checkerBinding(project);
118
+ return callsPlatformBy(name, callee, (written) =>
119
+ written === callee ? boundBy(project, symbol) : others(written),
120
+ );
121
+ }
122
+
123
+ /**
124
+ * Whether a worker's constructor or `navigator`, the batch's answer for which is `symbol`, is
125
+ * the platform's (references-ts.2): a name the checker leaves unanswered, or one whose symbol
126
+ * is no alias and has a declaration outside the target's files.
127
+ */
128
+ export function isPlatformGlobal<Brand>(
129
+ project: ProjectView<Brand>,
130
+ symbol: Answer<TSSymbol> | undefined,
131
+ ): boolean {
132
+ if (symbol === UNANSWERED) {
133
+ return true;
134
+ }
135
+ const own = project.ownPaths();
136
+ return (
137
+ symbol !== undefined &&
138
+ (symbol.flags & SymbolFlags.Alias) === 0 &&
139
+ symbol.declarations.some((handle) => !own.has(handle.path))
140
+ );
141
+ }
142
+
143
+ /** The module names Node's worker threads are imported by. */
144
+ const THREADS: ReadonlySet<string> = new Set(["worker_threads", "node:worker_threads"]);
145
+
146
+ function namesThreads(node: Node | undefined): boolean {
147
+ return node !== undefined && isStringLiteralLikeNode(node) && THREADS.has(node.text);
148
+ }
149
+
150
+ /** Whether one declaration is written in the body of `declare module "worker_threads"`. */
151
+ function inThreadsModule(node: Node): boolean {
152
+ for (let at = node; !isSourceFile(at); at = at.parent) {
153
+ if (isModuleDeclaration(at) && namesThreads(at.name)) {
154
+ return true;
155
+ }
156
+ }
157
+ return false;
158
+ }
159
+
160
+ /**
161
+ * Whether a `Worker` constructor, the batch's answer for which is `symbol`, is Node's
162
+ * (references-ts.2): its symbol resolves to a declaration of `worker_threads`, or one of its
163
+ * own declarations binds the module's `Worker`, or `holder`, the namespace it is read
164
+ * through, binds the module, each binding read as {@link boundExports} reads one, which
165
+ * decides where the module has no declaration.
166
+ */
167
+ export function startsThread<Brand>(
168
+ project: ProjectView<Brand>,
169
+ symbol: Answer<TSSymbol> | undefined,
170
+ holder: Answer<TSSymbol> | undefined,
171
+ ): boolean {
172
+ const bindingOf = checkerBinding(project);
173
+ const declared = (one: Answer<TSSymbol> | undefined, member: string): boolean =>
174
+ typeof one === "object" &&
175
+ ownDeclarations(project, one).some((node) =>
176
+ boundExports(node, (specifier) => THREADS.has(specifier), bindingOf).includes(member),
177
+ );
178
+ if (declared(symbol, "Worker") || declared(holder, NAMESPACE)) {
179
+ return true;
180
+ }
181
+ const named = typeof symbol === "object" ? dealiased(project, symbol) : undefined;
182
+ return (
183
+ typeof named === "object" &&
184
+ named.declarations.some((handle) => {
185
+ const node = project.declarationAt(handle)?.node;
186
+ return node !== undefined && inThreadsModule(node);
187
+ })
188
+ );
189
+ }
package/src/position.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { SourceFile } from "@typescript/native/ast";
2
2
  import { relativePath } from "./paths.ts";
3
+ import { bytewise } from "./text/compare.ts";
3
4
 
4
5
  /**
5
6
  * Where one declaration is written, as every report renders it.
@@ -47,6 +48,48 @@ export function writtenLength(file: SourceFile): number {
47
48
  return isComponentFile(file) ? file.originalText.length : file.text.length;
48
49
  }
49
50
 
51
+ /** Whether one character ends a line, under the language's line terminators. */
52
+ function endsLine(char: string | undefined): boolean {
53
+ return char === "\n" || char === "\r" || char === "\u2028" || char === "\u2029";
54
+ }
55
+
56
+ /** The offset where the line holding `from` ends. */
57
+ export function lineEnd(text: string, from: number): number {
58
+ let at = from;
59
+ while (at < text.length && !endsLine(text[at])) {
60
+ at += 1;
61
+ }
62
+ return at;
63
+ }
64
+
65
+ /**
66
+ * The offset of the first token at or after `from`: whitespace, comments and a leading
67
+ * hashbang are trivia.
68
+ */
69
+ export function tokenStart(text: string, from: number): number {
70
+ let at = from;
71
+ if (at === 0 && text.startsWith("#!")) {
72
+ at = lineEnd(text, 0);
73
+ }
74
+ for (;;) {
75
+ if (/\s/u.test(text[at] ?? "")) {
76
+ at += 1;
77
+ } else if (text.startsWith("//", at)) {
78
+ at = lineEnd(text, at);
79
+ } else if (text.startsWith("/*", at)) {
80
+ const close = text.indexOf("*/", at + 2);
81
+ at = close < 0 ? text.length : close + 2;
82
+ } else {
83
+ return at;
84
+ }
85
+ }
86
+ }
87
+
88
+ /** The line, counted from one, of the first token at or after one offset of one file. */
89
+ export function startLine(file: SourceFile, offset: number): number {
90
+ return file.getLineAndCharacterOfPosition(tokenStart(file.text, offset)).line + 1;
91
+ }
92
+
50
93
  /**
51
94
  * The position of one offset of one file, rendered against the target root.
52
95
  *
@@ -87,7 +130,7 @@ export function positionKey(position: Position): string {
87
130
  */
88
131
  export function byPosition(a: Position, b: Position): number {
89
132
  if (a.path !== b.path) {
90
- return a.path < b.path ? -1 : 1;
133
+ return bytewise(a.path, b.path);
91
134
  }
92
135
  if (a.line !== b.line) {
93
136
  return a.line - b.line;
package/src/print.ts CHANGED
@@ -1,96 +1,16 @@
1
- import {
2
- renderOrigin,
3
- type Config,
4
- type DeclarationEntry,
5
- type Provenance,
6
- type Provider,
7
- } from "./config.ts";
8
-
9
- /** One declaration entry as a document writes it: the members of its shape alone. */
10
- function declarationOf(entry: DeclarationEntry): Record<string, string> {
11
- switch (entry.shape) {
12
- case "symbol":
13
- return { symbol: entry.symbol };
14
- case "module":
15
- return { module: entry.module, name: entry.name };
16
- case "global":
17
- return { global: entry.global };
18
- }
19
- }
20
-
21
- /** One provider entry as a document writes it: the members of its shape alone. */
22
- function providerOf(entry: Provider): Record<string, unknown> {
23
- const installed = { name: entry.name, languages: entry.languages, command: entry.command };
24
- if (entry.shape === "installed") {
25
- return installed;
26
- }
27
- return { ...installed, source: entry.source, version: entry.version, digest: entry.digest };
28
- }
1
+ import { renderOrigin, type Provenance, type ResolvedConfig } from "./config.ts";
2
+ import { bytewise } from "./text/compare.ts";
29
3
 
30
4
  /**
31
- * The resolved configuration and its provenance as one JSON object, indented,
32
- * ending in a newline.
33
- *
34
- * The output is an instance of the closed key list, so reading it back as a
35
- * repository configuration resolves to the same configuration: the provenance
36
- * object is a declared key resolution ignores. Keys are written in the schema's
37
- * order and the severity and provenance objects in ascending key order, so one
38
- * configuration renders to one string whatever order a source named its settings
39
- * in.
5
+ * The resolved configuration and its provenance as one JSON object, indented, ending
6
+ * in a newline: the configuration in the order resolution gives it, then the provenance
7
+ * object in ascending key order. Read back as a repository configuration it resolves to
8
+ * the same configuration, because resolution checks the provenance object and then
9
+ * ignores it.
40
10
  */
41
- export function printConfig(config: Config, provenance: Provenance): string {
42
- const document = {
43
- contract_version: config.contractVersion,
44
- target: { kind: config.targetKind },
45
- analysis: {
46
- languages: config.analysis.languages,
47
- min_confidence: config.analysis.minConfidence,
48
- generated_files: config.analysis.generatedFiles,
49
- consumer_tests: config.analysis.consumerTests,
50
- configurations: config.analysis.configurations.map((entry) =>
51
- entry.shape === "project"
52
- ? { id: entry.id, project: entry.project }
53
- : { id: entry.id, os: entry.os, arch: entry.arch, tags: entry.tags },
54
- ),
55
- matrix: { complete: config.analysis.matrixComplete },
56
- template_dirs: config.analysis.templateDirs,
57
- template_delimiters: {
58
- left: config.analysis.templateDelimiters.left,
59
- right: config.analysis.templateDelimiters.right,
60
- },
61
- },
62
- consumers: { complete: config.consumersComplete },
63
- roots: { patterns: config.rootPatterns },
64
- severity: Object.fromEntries([...config.severity].sort(([a], [b]) => (a < b ? -1 : 1))),
65
- exemptions: { disabled: config.exemptionsDisabled },
66
- reporters: {
67
- formats: config.reporters.formats,
68
- sort: config.reporters.sort,
69
- cascade: config.reporters.cascade,
70
- max_findings: config.reporters.maxFindings,
71
- fail_on: config.reporters.failOn,
72
- },
73
- providers: { analyzers: config.providers.analyzers.map(providerOf) },
74
- go: {},
75
- ts: {
76
- test_files: config.ts.testFiles,
77
- entry_files: config.ts.entryFiles,
78
- component_extensions: config.ts.componentExtensions,
79
- disabled_conventions: config.ts.disabledConventions,
80
- injection_registrations: config.ts.injectionRegistrations.map(declarationOf),
81
- lifecycle_contracts: config.ts.lifecycleContracts.map((entry) => ({
82
- components: entry.components.map(declarationOf),
83
- bases: entry.bases.map(declarationOf),
84
- members: entry.members,
85
- })),
86
- serializers: config.ts.serializers.map(declarationOf),
87
- roots_complete: config.ts.rootsComplete,
88
- },
89
- provenance: Object.fromEntries(
90
- [...provenance]
91
- .sort(([a], [b]) => (a < b ? -1 : 1))
92
- .map(([path, origin]) => [path, renderOrigin(origin)]),
93
- ),
94
- };
95
- return `${JSON.stringify(document, undefined, 2)}\n`;
11
+ export function printConfig(config: ResolvedConfig, provenance: Provenance): string {
12
+ const origins = [...provenance]
13
+ .sort(([a], [b]) => bytewise(a, b))
14
+ .map(([path, origin]): [string, string] => [path, renderOrigin(origin)]);
15
+ return `${JSON.stringify({ ...config, provenance: Object.fromEntries(origins) }, undefined, 2)}\n`;
96
16
  }
package/src/product.ts ADDED
@@ -0,0 +1,18 @@
1
+ import { LANGUAGE_ROWS } from "./contract/contract.generated.ts";
2
+ import type { Writer } from "./run.ts";
3
+
4
+ /** The language this analyzer reads. */
5
+ export const LANGUAGE = "ts";
6
+
7
+ /** The analyzer's name: the one its language's row names, which every output spells it with. */
8
+ export const PRODUCT = LANGUAGE_ROWS[LANGUAGE].analyzer;
9
+
10
+ /** Writes one diagnostic line to the error stream, named for the analyzer. */
11
+ export function diagnose(err: Writer, text: string): void {
12
+ err.write(`${PRODUCT}: ${text}\n`);
13
+ }
14
+
15
+ /** The text one thrown value carries. */
16
+ export function message(error: unknown): string {
17
+ return error instanceof Error ? error.message : String(error);
18
+ }
package/src/query.ts CHANGED
@@ -207,10 +207,26 @@ export interface Queries {
207
207
  constraintOf(type: Type): Answer<Type | undefined>;
208
208
  /** The object and the index of an indexed-access type; none for another type. */
209
209
  indexedAccessOf(type: Type): Answer<{ readonly object: Type; readonly index: Type } | undefined>;
210
+ /**
211
+ * The types one type is spelled from besides its constituents, type arguments and members:
212
+ * a type parameter's constraint and default, a conditional's check, extends, true
213
+ * and false types, a mapped type's constraint, name and template, an indexed access's
214
+ * object and index, the operand of `keyof` or of a string mapping, a template literal's
215
+ * spans and a substitution's base and constraint. None for another type.
216
+ */
217
+ partsOf(type: Type): Answer<readonly Type[]>;
218
+ /** The type parameters of a signature, its `this` parameter's type and its predicate's type. */
219
+ signaturePartsOf(signature: Signature): Answer<readonly Type[]>;
210
220
  /** The symbol a type is declared by. */
211
221
  symbolOfType(type: Type): Answer<TSSymbol | undefined>;
222
+ /** The type alias a type was instantiated from, where it was. */
223
+ aliasSymbolOf(type: Type): Answer<TSSymbol | undefined>;
224
+ /** The type arguments the alias a type was instantiated from was given. */
225
+ aliasArgumentsOf(type: Type): Answer<readonly Type[]>;
212
226
  signaturesOf(type: Type, kind: SignatureKind): Answer<readonly Signature[]>;
213
227
  resolvedSignature(node: Node): Answer<Signature | undefined>;
228
+ /** The signature each call-like node resolves to. */
229
+ resolvedSignatures(nodes: readonly Node[], cap?: number): Answer<Signature | undefined>[];
214
230
  parameterType(signature: Signature, index: number): Answer<Type | undefined>;
215
231
  /** The generic signature an instantiated one instantiates; none for another signature. */
216
232
  genericOf(signature: Signature): Answer<Signature | undefined>;
@@ -221,6 +237,37 @@ export interface Queries {
221
237
  typeToString(type: Type): Answer<string>;
222
238
  }
223
239
 
240
+ /** How to read the types one type is spelled from, as {@link Queries.partsOf} names them. */
241
+ function partQuestion(type: Type): (() => readonly (Type | undefined)[]) | undefined {
242
+ if (type.isTypeParameter()) {
243
+ return () => [type.getConstraint(), type.getDefault()];
244
+ }
245
+ if (type.isConditionalType()) {
246
+ return () => [
247
+ type.getCheckType(),
248
+ type.getExtendsType(),
249
+ type.getTrueType(),
250
+ type.getFalseType(),
251
+ ];
252
+ }
253
+ if (type.isMappedType()) {
254
+ return () => [type.getConstraintType(), type.getNameType(), type.getTemplateType()];
255
+ }
256
+ if (type.isIndexedAccessType()) {
257
+ return () => [type.getObjectType(), type.getIndexType()];
258
+ }
259
+ if (type.isIndexType() || type.isStringMappingType()) {
260
+ return () => [type.getTarget()];
261
+ }
262
+ if (type.isTemplateLiteralType()) {
263
+ return () => type.getTypes();
264
+ }
265
+ if (type.isSubstitutionType()) {
266
+ return () => [type.getBaseType(), type.getConstraint()];
267
+ }
268
+ return undefined;
269
+ }
270
+
224
271
  /**
225
272
  * The guarded questions over one project's checker. `configFile` names the project
226
273
  * in the log, `batch` sends many questions in one round trip, `log` is the run's,
@@ -526,12 +573,48 @@ export function queriesOf(
526
573
  () => ({ object: type.getObjectType(), index: type.getIndexType() }),
527
574
  )
528
575
  : undefined,
576
+ partsOf: (type) => {
577
+ const parts = partQuestion(type);
578
+ return parts === undefined
579
+ ? []
580
+ : one(
581
+ "getParts",
582
+ () => typeLocation(type),
583
+ () => parts().filter((part) => part !== undefined),
584
+ );
585
+ },
586
+ signaturePartsOf: (signature) =>
587
+ one(
588
+ "getSignatureParts",
589
+ () => `signature ${String(signature.id)}`,
590
+ () => {
591
+ const self =
592
+ signature.thisParameter === undefined ? undefined : signature.getThisParameter();
593
+ return [
594
+ ...((signature.typeParameters ?? []).length === 0 ? [] : signature.getTypeParameters()),
595
+ self === undefined ? undefined : checker.getTypeOfSymbol(self),
596
+ checker.getTypePredicateOfSignature(signature)?.type,
597
+ ].filter((part) => part !== undefined);
598
+ },
599
+ ),
529
600
  symbolOfType: (type) =>
530
601
  one(
531
602
  "getSymbol",
532
603
  () => typeLocation(type),
533
604
  () => type.getSymbol(),
534
605
  ),
606
+ aliasSymbolOf: (type) =>
607
+ one(
608
+ "getAliasSymbol",
609
+ () => typeLocation(type),
610
+ () => type.getAliasSymbol(),
611
+ ),
612
+ aliasArgumentsOf: (type) =>
613
+ one(
614
+ "getAliasTypeArguments",
615
+ () => typeLocation(type),
616
+ () => type.getAliasTypeArguments(),
617
+ ),
535
618
  signaturesOf: (type, kind) =>
536
619
  one(
537
620
  "getSignaturesOfType",
@@ -544,6 +627,15 @@ export function queriesOf(
544
627
  () => nodeLocation(node),
545
628
  () => checker.getResolvedSignature(node),
546
629
  ),
630
+ resolvedSignatures: (nodes, cap = DEFAULT_BATCH_CAP) =>
631
+ each(
632
+ "getResolvedSignature",
633
+ nodes,
634
+ cap,
635
+ nodeLocation,
636
+ (node) => checker.getResolvedSignature.gen(node),
637
+ (node) => checker.getResolvedSignature(node),
638
+ ),
547
639
  parameterType: (signature, index) =>
548
640
  one(
549
641
  "getParameterType",
package/src/ref.ts CHANGED
@@ -1,13 +1,9 @@
1
1
  /**
2
- * The stable symbol reference: the identifier that names one declaration across
3
- * runs, across reports, in an ignore entry, in a configured root and in a
4
- * cross-language edge. It is built from names and containers only, so an edit above
5
- * a declaration leaves it unchanged, and it is compared as bytes, so there is one
6
- * canonical spelling per declaration and this module is where that spelling is
7
- * written.
8
- *
9
- * The position key of {@link ./position.ts} is the other identifier and has the
10
- * other job: it locates a finding inside one run, and the two never mix.
2
+ * The stable symbol reference: the identifier that names one declaration across runs,
3
+ * reports, ignore entries, configured roots and cross-language edges. It is built from
4
+ * names and containers only, so an edit above a declaration leaves it unchanged, and it
5
+ * is compared as bytes, so this module writes the one canonical spelling. The position
6
+ * key of {@link ./position.ts} locates a finding inside one run; the two never mix.
11
7
  */
12
8
 
13
9
  /** The language prefix, which namespaces every reference this analyzer emits. */
@@ -34,16 +30,10 @@ const SCOPE = `${PREFIX}${TS_PACKAGE}/${TS_FILE}`;
34
30
  const MANIFEST_SCOPE = `${PREFIX}${TS_PACKAGE}/${TS_DIRS}package\\.json`;
35
31
 
36
32
  /**
37
- * One expression per form the grammar defines, each anchored and each the whole of
38
- * a reference. Several forms share one expression because they differ in what the
39
- * symbol is rather than in how the reference is spelled, so the list is the set of
40
- * spellings and not the set of subjects. A reference is valid when it matches one.
41
- *
42
- * They are written here rather than read from the Contract at run time: the Contract
43
- * is data a reader outside this program consults, and a product that read it while
44
- * running would need it installed beside itself. A test compares this list against
45
- * the release this analyzer is written against, so a grammar that grows a form
46
- * arrives here as a failing test.
33
+ * One anchored expression per spelling the grammar defines; a reference is valid when it
34
+ * matches one. They are written here rather than read from the Contract at run time, so
35
+ * the product needs no Contract installed beside it; a test compares this list against
36
+ * the release this analyzer implements, so a grammar that grows a form fails it.
47
37
  */
48
38
  export const REF_EXPRESSIONS: readonly string[] = [
49
39
  `^${SCOPE}#$`,
@@ -52,6 +42,7 @@ export const REF_EXPRESSIONS: readonly string[] = [
52
42
  `^${SCOPE}#${TS_HEAD}:import$`,
53
43
  `^${SCOPE}#${TS_HEAD}(?:\\.${TS_MEMBER})+$`,
54
44
  `^${SCOPE}#${TS_HEAD}(?:\\.${TS_MEMBER})+:static$`,
45
+ `^${SCOPE}#${TS_HEAD}(?:\\.${TS_MEMBER})+\\.${TS_QUOTED}:case$`,
55
46
  `^${SCOPE}#${TS_HEAD}(?:\\.${TS_MEMBER})*(?::static)?<${TS_IDENT}>$`,
56
47
  `^${SCOPE}#(?:${TS_HEAD}(?:\\.${TS_MEMBER})*(?::static)?)?\\(${TS_IDENT}\\)$`,
57
48
  `^${MANIFEST_SCOPE}#${TS_PACKAGE}:(?:dependency|dev-dependency|peer-dependency)$`,
@@ -169,7 +160,8 @@ export function aliasFragment(name: string, block?: string): string {
169
160
  return `${head}${nameComponent(name)}:alias`;
170
161
  }
171
162
 
172
- function spell(component: Component): string {
163
+ /** The canonical spelling of one component: a name, or a computed key. */
164
+ export function spell(component: Component): string {
173
165
  return component.computed ? computedComponent(component.text) : nameComponent(component.text);
174
166
  }
175
167
 
@@ -0,0 +1,60 @@
1
+ import type { Node, SourceFile } from "@typescript/native/ast";
2
+ import type { Type } from "@typescript/native/sync";
3
+ import type { AliasChains } from "../alias-chain.ts";
4
+ import type { Inventory } from "../inventory.ts";
5
+ import type { Position } from "../position.ts";
6
+ import type { Resolution } from "../references.ts";
7
+ import type { ProjectView } from "../session.ts";
8
+
9
+ /** Where the walk offered a read rule one node: the file, and the declaration enclosing the node. */
10
+ interface ReadSite {
11
+ readonly file: SourceFile;
12
+ readonly from: string;
13
+ }
14
+
15
+ /** What a read rule reads its answers through, after the walk of every file of the side. */
16
+ export interface ReadContext<Brand> {
17
+ readonly project: ProjectView<Brand>;
18
+ readonly held: Inventory;
19
+ readonly chains: AliasChains;
20
+ }
21
+
22
+ /**
23
+ * One read a rule makes: a use of the declaration `to` by `from` at a node of a walked file,
24
+ * or, where a question the read needed went unanswered, a hold. A hold names what the answer
25
+ * could have made live (program.33): the declarations `ids`, each declaration bearing one of
26
+ * `names`, each member of one of `types`, or with `members` every member the inventory holds;
27
+ * the declaration making the read is held as well. A named read sits at a node of `file`, or
28
+ * at a declaration's own position in it.
29
+ */
30
+ export type Read =
31
+ | {
32
+ readonly kind: "named";
33
+ readonly from: string;
34
+ readonly to: string;
35
+ readonly file: SourceFile;
36
+ readonly at: Node | Position;
37
+ readonly use: "read" | "write";
38
+ readonly via: Resolution;
39
+ /** A read a rule counts as production code's whoever writes it. */
40
+ readonly production?: true;
41
+ }
42
+ | {
43
+ readonly kind: "held";
44
+ readonly from: string;
45
+ readonly ids?: readonly string[];
46
+ readonly names?: readonly string[];
47
+ readonly types?: readonly Type[];
48
+ readonly members?: true;
49
+ };
50
+
51
+ /** One pass of one read rule over the files of one side: it collects while the walk offers nodes, then reads. */
52
+ interface ReadRuleRun {
53
+ visit(node: Node, site: ReadSite): void;
54
+ reads<Brand>(context: ReadContext<Brand>): readonly Read[];
55
+ }
56
+
57
+ /** One rule of the references pages that reads declarations no name node names. */
58
+ export interface ReadRule {
59
+ start(): ReadRuleRun;
60
+ }