@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
@@ -1,702 +1,141 @@
1
- import { isArrayBindingPattern, isBindingElement, isClassDeclaration, isComputedPropertyName, isConstructorDeclaration, isEnumDeclaration, isEnumMember, isExportAssignment, isExportDeclaration, isFunctionDeclaration, isGetAccessorDeclaration, isIdentifier, isInterfaceDeclaration, isIntersectionTypeNode, isMethodDeclaration, isMethodSignatureDeclaration, isModuleBlock, isModuleDeclaration, isNamespaceExport, isObjectBindingPattern, isParameterDeclaration, isParenthesizedTypeNode, isPrivateIdentifier, isPropertyDeclaration, isPropertySignatureDeclaration, isSetAccessorDeclaration, isStringLiteral, isTypeAliasDeclaration, isTypeLiteralNode, isUnionTypeNode, isVariableStatement, ModifierFlags, } from "@typescript/native/ast";
2
- import { dirnamePath, joinPath, relativePath } from "./paths.js";
3
- import { byPosition, positionKey, renderPosition, writtenLength, } from "./position.js";
4
- import { computedComponent, nameComponent, renderRef } from "./ref.js";
5
- import { isAnswered, UNANSWERED } from "./query.js";
6
- const MANIFEST = "package.json";
1
+ import { isClassDeclaration, isComputedPropertyName, isConstructorDeclaration, isEnumMember, isFunctionDeclaration, isGetAccessorDeclaration, isIdentifier, isInterfaceDeclaration, isMethodDeclaration, isMethodSignatureDeclaration, isParameterDeclaration, isPrivateIdentifier, isPropertyDeclaration, isPropertySignatureDeclaration, isSetAccessorDeclaration, isTypeAliasDeclaration, ModifierFlags, SyntaxKind, } from "@typescript/native/ast";
2
+ import { byPosition, positionKey, renderPosition, startLine } from "./position.js";
3
+ import { renderRef, spell } from "./ref.js";
4
+ import { signatureOf } from "./signatures.js";
5
+ /** The reader's word for each kind of declaration, as a finding names it. */
6
+ export const WORDS = {
7
+ file: "file",
8
+ function: "function",
9
+ class: "class",
10
+ interface: "interface",
11
+ type: "type alias",
12
+ enum: "enum",
13
+ namespace: "namespace",
14
+ variable: "variable",
15
+ "export-alias": "re-export",
16
+ method: "method",
17
+ "class-member": "class member",
18
+ "interface-method": "interface method",
19
+ "type-member": "type member",
20
+ "enum-member": "enum member",
21
+ "type-parameter": "type parameter",
22
+ };
7
23
  /**
8
- * Resolves each file's package scope: the name of the nearest manifest at or above
9
- * its directory up to the target root, and the file's path below that manifest.
10
- * Where no manifest up to the root carries a name, the package is a single dot and
11
- * the path is read from the root, which cannot collide, because a package name never
12
- * starts with a dot.
13
- *
14
- * One directory is read at most once, because a package holds many files and a
15
- * manifest read is a filesystem call.
16
- */
17
- export function packageScope(host, root) {
18
- const named = new Map();
19
- const manifestName = (dir) => {
20
- let text;
21
- try {
22
- text = host.readFile(joinPath(root, dir, MANIFEST));
23
- }
24
- catch {
25
- return undefined;
26
- }
27
- let value;
28
- try {
29
- value = JSON.parse(text);
30
- }
31
- catch {
32
- // A manifest this program cannot read names no package, which is the same
33
- // answer as an absent one: the file is then scoped by the target root.
34
- return undefined;
35
- }
36
- if (typeof value !== "object" || value === null) {
37
- return undefined;
38
- }
39
- const name = value["name"];
40
- return typeof name === "string" && name !== "" ? name : undefined;
41
- };
42
- const nearest = (dir) => {
43
- if (named.has(dir)) {
44
- return named.get(dir);
45
- }
46
- const name = manifestName(dir);
47
- const found = name !== undefined ? { name, at: dir } : dir === "" ? undefined : nearest(parentOf(dir));
48
- named.set(dir, found);
49
- return found;
50
- };
51
- return (path) => {
52
- const found = nearest(parentOf(path));
53
- if (found === undefined) {
54
- return { package: ".", path };
55
- }
56
- return { package: found.name, path: found.at === "" ? path : path.slice(found.at.length + 1) };
57
- };
58
- }
59
- /** The directory one path below the root sits in, and the root itself as the empty path. */
60
- function parentOf(path) {
61
- const dir = dirnamePath(path);
62
- return dir === "." ? "" : dir;
63
- }
64
- /** The modifier flags one node carries, and zero for a node that carries none. */
65
- function modifiersOf(node) {
66
- return node.modifierFlags ?? 0;
67
- }
68
- /** Whether a declaration is ambient: in a declaration file, or under a `declare` modifier. */
69
- function isAmbient(file, node) {
70
- if (file.isDeclarationFile) {
71
- return true;
72
- }
73
- for (let at = node; at !== undefined; at = at.parent) {
74
- if ((modifiersOf(at) & ModifierFlags.Ambient) !== 0) {
75
- return true;
76
- }
77
- }
78
- return false;
79
- }
80
- /** The type parameters one node declares, and none for a node that declares none. */
81
- function typeParametersOf(node) {
82
- if (isFunctionDeclaration(node) ||
83
- isMethodDeclaration(node) ||
84
- isMethodSignatureDeclaration(node) ||
85
- isClassDeclaration(node) ||
86
- isInterfaceDeclaration(node) ||
87
- isTypeAliasDeclaration(node)) {
88
- return node.typeParameters ?? [];
89
- }
90
- return [];
91
- }
92
- /**
93
- * The reference component one declaration name node spells, and undefined for a
94
- * name the grammar does not represent: a binding pattern, and a computed key whose
95
- * source text carries a closing bracket.
96
- */
97
- function componentOf(name) {
98
- if (name === undefined) {
99
- return undefined;
100
- }
101
- if (isComputedPropertyName(name)) {
102
- const text = name.expression.getText();
103
- return text.includes("]") ? undefined : { text, computed: true };
104
- }
105
- if (isIdentifier(name) || isPrivateIdentifier(name)) {
106
- return { text: name.getText(), computed: false };
107
- }
108
- if (isStringOrNumericName(name)) {
109
- // A string or numeric key's own text carries its quotes and its numeric
110
- // spelling; the reference carries the value, which the component then quotes.
111
- return { text: literalTextOf(name), computed: false };
112
- }
113
- return undefined;
114
- }
115
- function isStringOrNumericName(name) {
116
- const text = name.getText();
117
- return (text.startsWith('"') || text.startsWith("'") || text.startsWith("`") || /^[0-9]/u.test(text));
118
- }
119
- /** One member's identity inside its container: its component, and its side of a class. */
120
- function memberKey(component, isStatic) {
121
- return `${component.computed ? "[" : ""}${component.text}${isStatic ? ":static" : ""}`;
122
- }
123
- /** The type one node is, through however many parentheses are written around it. */
124
- function unparenthesizedType(type) {
125
- let held = type;
126
- while (isParenthesizedTypeNode(held)) {
127
- held = held.type;
128
- }
129
- return held;
130
- }
131
- /**
132
- * The direct constituents of one type. Parentheses are syntax and are not a
133
- * constituent, so a parenthesized type contributes the constituents it holds: the
134
- * constituents of `(A | B) & C` are `A`, `B` and `C`. A union or an intersection
135
- * written without them stays one constituent.
136
- */
137
- function constituentsOf(type) {
138
- const held = unparenthesizedType(type);
139
- if (!isUnionTypeNode(held) && !isIntersectionTypeNode(held)) {
140
- return [held];
141
- }
142
- return held.types.flatMap((member) => isParenthesizedTypeNode(member) ? constituentsOf(member) : [member]);
143
- }
144
- /**
145
- * The members one type alias declares: the members of the object type it writes, and
146
- * of every object type that is a direct constituent of a union or an intersection it
147
- * writes. A constituent naming another type declares nothing here, because that
148
- * declaration carries its own members.
149
- *
150
- * A name two constituents both declare is left out of all of them. The alias stands
151
- * for such a member, because the two declarations are one member of the type and
152
- * neither of them is the one a reference to it would name.
153
- */
154
- function aliasMembers(type) {
155
- const literals = constituentsOf(type).filter(isTypeLiteralNode);
156
- if (literals.length < 2) {
157
- return literals[0]?.members ?? [];
158
- }
159
- const declaring = new Map();
160
- for (const literal of literals) {
161
- for (const key of new Set(literal.members.map(keyOf))) {
162
- if (key !== undefined) {
163
- declaring.set(key, (declaring.get(key) ?? 0) + 1);
164
- }
165
- }
166
- }
167
- return literals.flatMap((literal) => literal.members.filter((member) => {
168
- const key = keyOf(member);
169
- return key !== undefined && declaring.get(key) === 1;
170
- }));
171
- }
172
- /** One type member's identity, and undefined for a member the grammar cannot name. */
173
- function keyOf(member) {
174
- const component = componentOf(nameNodeOf(member));
175
- return component === undefined ? undefined : memberKey(component, false);
176
- }
177
- /** The value one string or numeric key denotes, which is what the reference names. */
178
- function literalTextOf(name) {
179
- const text = name.getText();
180
- if (text.startsWith('"') || text.startsWith("'") || text.startsWith("`")) {
181
- return text.slice(1, -1);
182
- }
183
- return text;
184
- }
185
- /**
186
- * The component one declaration's reference carries, and its declared name where the
187
- * two differ.
188
- *
189
- * A declaration its module exports as the default is named `default`, because that is
190
- * its export name and a module has at most one, so the spelling is unambiguous and it
191
- * holds for an anonymous declaration too. Its declared name is a fact about the source
192
- * rather than about the export, so it travels beside the component as the display name.
193
- */
194
- function exportedAs(node, name) {
195
- const declared = componentOf(name);
196
- if ((modifiersOf(node) & ModifierFlags.Default) === 0) {
197
- return { component: declared, localName: undefined };
198
- }
199
- return { component: { text: "default", computed: false }, localName: declared?.text };
200
- }
201
- /** The visibility one member declaration's modifiers and name give it. */
202
- function visibilityOf(node, name) {
203
- if (name !== undefined && isPrivateIdentifier(name)) {
204
- return "private-name";
205
- }
206
- const flags = modifiersOf(node);
207
- if ((flags & ModifierFlags.Private) !== 0) {
208
- return "private";
209
- }
210
- if ((flags & ModifierFlags.Protected) !== 0) {
211
- return "protected";
212
- }
213
- return "public";
214
- }
215
- /**
216
- * The binding elements of a destructuring declaration that each declare a name of their
217
- * own, at any depth, but one with a default, whose removal skips the default's
218
- * evaluation, and one beside a rest element of its object pattern, whose removal
219
- * changes what the rest holds.
220
- */
221
- function patternElements(name) {
222
- if (!isObjectBindingPattern(name) && !isArrayBindingPattern(name)) {
223
- return [];
224
- }
225
- const rest = isObjectBindingPattern(name) &&
226
- name.elements.some((element) => element.dotDotDotToken !== undefined);
227
- return name.elements.flatMap((element) => {
228
- if (!isBindingElement(element) ||
229
- element.initializer !== undefined ||
230
- (rest && element.dotDotDotToken === undefined)) {
231
- return [];
232
- }
233
- const bound = element.name;
234
- if (bound === undefined) {
235
- return [];
236
- }
237
- return isIdentifier(bound) ? [{ element, name: bound }] : patternElements(bound);
238
- });
239
- }
240
- /** The name node of one declaration, for the kinds that carry one. */
241
- function nameNodeOf(node) {
242
- return node.name;
243
- }
244
- /**
245
- * The fragment component one declaration's name spells in a reference, as the inventory
246
- * spells it, or undefined for a name the grammar does not represent.
247
- */
248
- export function declaredComponent(node) {
249
- const component = componentOf(nameNodeOf(node));
250
- if (component === undefined) {
251
- return undefined;
252
- }
253
- return component.computed ? computedComponent(component.text) : nameComponent(component.text);
254
- }
255
- /**
256
- * One node's identity inside one program, which is how two readings of that program
257
- * name one declaration.
258
- *
259
- * The two mechanisms behind the member set resolve a member separately and meet here;
260
- * so does the reference pass, which starts from a resolved symbol's declaration and
261
- * needs the declaration this enumeration made for it.
24
+ * One node's identity inside one program, which is how two readings of that program name
25
+ * one declaration: the binder's table and the tree meet here, and so does the reference
26
+ * pass, which starts from a resolved symbol's declaration.
262
27
  */
263
28
  export function nodeKey(file, node) {
264
29
  return `${file.fileName}:${String(node.pos)}:${String(node.end)}:${String(node.kind)}`;
265
30
  }
266
- /** Whether `node` is written inside `declaration`, compared by file and range. */
267
- function writtenInside(declaration, node) {
268
- return (node.getSourceFile().fileName === declaration.getSourceFile().fileName &&
269
- declaration.pos <= node.pos &&
270
- node.end <= declaration.end);
271
- }
272
- /** `export default`, up to the keyword that stands where an unnamed default export's name would. */
273
- const DEFAULT_EXPORT = /^export\s+(?=default\b)/u;
274
- /**
275
- * Where an unnamed declaration is placed: at `default` when it is the default export, so it
276
- * never shares the file's own position, else at its first token.
277
- */
278
- function unnamedStart(node) {
279
- const start = node.getStart();
280
- const prefix = DEFAULT_EXPORT.exec(node.getText());
281
- return prefix === null ? start : start + prefix[0].length;
282
- }
283
31
  /**
284
32
  * Whether one node is a parameter property: a constructor parameter carrying an
285
- * accessibility, `readonly` or `override` modifier, which also declares an instance
286
- * member of the class, with the parameter's node as the member's declaration.
33
+ * accessibility, `readonly` or `override` modifier, which also declares an instance member
34
+ * of the class, with the parameter's node as the member's declaration.
287
35
  */
288
36
  export function isParameterProperty(node) {
289
37
  return (isParameterDeclaration(node) &&
290
38
  isConstructorDeclaration(node.parent) &&
291
39
  (modifiersOf(node) & ModifierFlags.ParameterPropertyModifier) !== 0);
292
40
  }
293
- /** The parameter properties every constructor of one class declares. */
294
- function parameterPropertiesOf(node) {
295
- return node.members.flatMap((member) => isConstructorDeclaration(member) ? member.parameters.filter(isParameterProperty) : []);
296
- }
297
- /** The kind a class element takes: a method, or a property or accessor. */
298
- function classMemberKind(node) {
299
- return isMethodDeclaration(node) ? "method" : "class-member";
300
- }
301
- /** The kind a type element takes: a method of an interface, or any other member. */
302
- function typeMemberKind(node, inInterface) {
303
- return inInterface && isMethodSignatureDeclaration(node) ? "interface-method" : "type-member";
41
+ /**
42
+ * The fragment component one declaration's name spells in a reference, as the inventory
43
+ * spells it, or undefined for a name the grammar does not represent.
44
+ */
45
+ export function declaredComponent(node) {
46
+ const component = componentOf(nameNodeOf(node));
47
+ return component === undefined ? undefined : spell(component);
304
48
  }
305
49
  /**
306
- * Every declaration one project's own files hold.
307
- *
308
- * `targetRoot` is the absolute path every position is rendered against; a file the
309
- * program holds that is not below it ends the enumeration rather than being passed
310
- * over. `host` is the filesystem the manifests that name each file's package are
311
- * read through, and nothing else is read from it.
312
- *
313
- * The order is by rendered position, so two enumerations of one project return the
314
- * same list whatever order the program reported its files in.
50
+ * Collects one project's declarations, from every {@link DeclarationSource} and from the
51
+ * binder's tables, and renders them. A member is kept once per container, by its
52
+ * component and its side of a class, whichever mechanism names it first.
315
53
  */
316
- export function inventory(project, host, targetRoot) {
317
- const files = project.ownSourceFiles();
318
- const ownFiles = new Set(files.map((file) => file.fileName));
319
- const moduleOf = packageScope(host, targetRoot);
320
- const building = [];
321
- const byNode = new Map();
322
- const exportScopes = [];
323
- const containers = [];
324
- const modules = [];
325
- const keep = (record) => {
326
- building.push(record);
327
- byNode.set(nodeKey(record.file, record.node), record);
328
- return record;
329
- };
330
- for (const file of files) {
331
- const path = relativePath(targetRoot, file.fileName);
332
- if (path === undefined) {
333
- // renderPosition states the refusal, with the root it was rendered against.
334
- renderPosition(file, targetRoot, 0);
335
- continue;
336
- }
337
- const module = moduleOf(path);
338
- const fileRecord = keep({
339
- file,
340
- node: file,
54
+ export class Builder {
55
+ #targetRoot;
56
+ #records = [];
57
+ #byNode = new Map();
58
+ #exportScopes = [];
59
+ #containers = [];
60
+ #modules = [];
61
+ #unansweredOwners = new Set();
62
+ #openTables = new Set();
63
+ constructor(targetRoot) {
64
+ this.#targetRoot = targetRoot;
65
+ }
66
+ get exportScopes() {
67
+ return this.#exportScopes;
68
+ }
69
+ get containers() {
70
+ return this.#containers;
71
+ }
72
+ /** One file's own record, which is also the export scope of its module. */
73
+ file(file, module, path) {
74
+ const record = this.#keep(file, file, 0, {
341
75
  module,
342
- position: renderPosition(file, targetRoot, 0),
343
- endLine: renderPosition(file, targetRoot, Math.max(file.end - 1, 0)).line,
344
76
  kind: "file",
345
77
  parentChain: [],
346
- // A file's reference names its module, so no component of it is ever spelled;
347
- // the path is what a text line renders for it.
78
+ // A file's reference names its module, so no component of it is ever spelled; the
79
+ // path is what a text line renders for it.
348
80
  component: { text: path, computed: false },
349
81
  localName: path,
350
82
  parent: undefined,
351
- visibility: "public",
352
- static: false,
353
- exported: false,
354
- typeParameter: undefined,
355
83
  });
356
- exportScopes.push({ owner: fileRecord, nameNode: file });
357
- // A statement a component file's module appends is not written in the file.
358
- const written = writtenLength(file);
359
- walkStatements(file.statements.filter((statement) => statement.end <= written), fileRecord);
360
- }
361
- /** One declaration of a module, a namespace or a container body. */
362
- function walkStatements(statements, owner) {
363
- for (const statement of statements) {
364
- walkStatement(statement, owner);
365
- }
84
+ this.#exportScopes.push({ owner: record, nameNode: file });
85
+ return record;
366
86
  }
367
- function declare(node, owner, kind, name, named) {
368
- const record = keep({
369
- file: owner.file,
370
- node,
87
+ /** One declaration written under `owner`, placed at its name, and its type parameters. */
88
+ declare(node, owner, kind, name, named) {
89
+ const record = this.#keep(owner.file, node, name?.getStart() ?? unnamedStart(node), {
371
90
  module: owner.module,
372
- position: renderPosition(owner.file, targetRoot, name?.getStart() ?? unnamedStart(node)),
373
- endLine: renderPosition(owner.file, targetRoot, Math.max(node.end - 1, 0)).line,
374
91
  kind,
375
92
  parentChain: owner.kind === "file" ? [] : chainOf(owner),
376
- component: named.component,
377
- localName: named.localName,
93
+ ...named,
378
94
  parent: owner,
379
95
  visibility: visibilityOf(node, name),
380
96
  static: (modifiersOf(node) & ModifierFlags.Static) !== 0,
381
- exported: false,
382
- typeParameter: undefined,
383
97
  });
384
- declareTypeParameters(node, record);
98
+ this.#declareTypeParameters(node, record);
385
99
  return record;
386
100
  }
387
- function declareTypeParameters(node, owner) {
388
- for (const parameter of typeParametersOf(node)) {
389
- const name = nameNodeOf(parameter);
390
- if (name === undefined) {
391
- continue;
392
- }
393
- keep({
394
- file: owner.file,
395
- node: parameter,
396
- module: owner.module,
397
- position: renderPosition(owner.file, targetRoot, name.getStart()),
398
- endLine: renderPosition(owner.file, targetRoot, Math.max(parameter.end - 1, 0)).line,
399
- kind: "type-parameter",
400
- parentChain: owner.parentChain,
401
- component: owner.component,
402
- localName: undefined,
403
- parent: owner,
404
- visibility: "public",
405
- static: owner.static,
406
- exported: false,
407
- typeParameter: name.getText(),
408
- });
409
- }
410
- }
411
- function walkStatement(node, owner) {
412
- if (isFunctionDeclaration(node)) {
413
- const named = exportedAs(node, node.name);
414
- if (named.component !== undefined) {
415
- declare(node, owner, "function", node.name, { ...named, component: named.component });
416
- }
417
- return;
418
- }
419
- if (isClassDeclaration(node)) {
420
- const named = exportedAs(node, node.name);
421
- if (named.component === undefined) {
422
- return;
423
- }
424
- const record = declare(node, owner, "class", node.name, {
425
- ...named,
426
- component: named.component,
427
- });
428
- containers.push({
429
- owner: record,
430
- declaration: node,
431
- nameNode: node.name,
432
- members: [...node.members, ...parameterPropertiesOf(node)],
433
- memberKind: "class-member",
434
- isClass: true,
435
- membersAreExports: false,
436
- });
101
+ /** A container of members; a class's constructors are where its parts are bound. */
102
+ container(container) {
103
+ this.#containers.push(container);
104
+ if (container.memberKind !== "class-member") {
437
105
  return;
438
106
  }
439
- if (isInterfaceDeclaration(node)) {
440
- const named = exportedAs(node, node.name);
441
- if (named.component === undefined) {
442
- return;
107
+ for (const member of container.members.filter(isConstructorDeclaration)) {
108
+ for (const at of [member, ...member.parameters.filter((one) => !isParameterProperty(one))]) {
109
+ container.owner.partLines.add(startLine(container.owner.file, at.pos));
443
110
  }
444
- const record = declare(node, owner, "interface", node.name, {
445
- ...named,
446
- component: named.component,
447
- });
448
- containers.push({
449
- owner: record,
450
- declaration: node,
451
- nameNode: node.name,
452
- members: node.members,
453
- memberKind: "interface-method",
454
- isClass: false,
455
- membersAreExports: false,
456
- });
457
- return;
458
- }
459
- if (isTypeAliasDeclaration(node)) {
460
- const named = exportedAs(node, node.name);
461
- if (named.component === undefined) {
462
- return;
463
- }
464
- const record = declare(node, owner, "type", node.name, {
465
- ...named,
466
- component: named.component,
467
- });
468
- // A type alias keeps no member table of its own: the members belong to the
469
- // object types its declaration writes, so the declaration is what carries them.
470
- const members = aliasMembers(node.type);
471
- if (members.length > 0) {
472
- containers.push({
473
- owner: record,
474
- declaration: node,
475
- nameNode: undefined,
476
- members,
477
- memberKind: "type-member",
478
- isClass: false,
479
- membersAreExports: false,
480
- });
481
- }
482
- return;
483
- }
484
- if (isEnumDeclaration(node)) {
485
- const named = exportedAs(node, node.name);
486
- if (named.component === undefined) {
487
- return;
488
- }
489
- const record = declare(node, owner, "enum", node.name, {
490
- ...named,
491
- component: named.component,
492
- });
493
- containers.push({
494
- owner: record,
495
- declaration: node,
496
- nameNode: node.name,
497
- members: node.members,
498
- memberKind: "enum-member",
499
- isClass: false,
500
- membersAreExports: true,
501
- });
502
- return;
503
- }
504
- if (isModuleDeclaration(node)) {
505
- const component = componentOf(node.name);
506
- if (component === undefined) {
507
- return;
508
- }
509
- const record = declare(node, owner, "namespace", node.name, {
510
- component,
511
- localName: undefined,
512
- });
513
- exportScopes.push({ owner: record, nameNode: node.name });
514
- if (isStringLiteral(node.name)) {
515
- modules.push([record, node.name.text]);
516
- }
517
- const body = node.body;
518
- if (body === undefined) {
519
- return;
520
- }
521
- if (isModuleBlock(body)) {
522
- walkStatements(body.statements, record);
523
- return;
524
- }
525
- walkStatement(body, record);
526
- return;
527
- }
528
- if (isVariableStatement(node)) {
529
- for (const declaration of node.declarationList.declarations) {
530
- const component = componentOf(declaration.name);
531
- if (component !== undefined) {
532
- declare(declaration, owner, "variable", declaration.name, {
533
- component,
534
- localName: undefined,
535
- });
536
- continue;
537
- }
538
- for (const { element, name } of patternElements(declaration.name)) {
539
- declare(element, owner, "variable", name, {
540
- component: { text: name.text, computed: false },
541
- localName: undefined,
542
- });
543
- }
544
- }
545
- return;
546
- }
547
- if (isExportDeclaration(node)) {
548
- walkExportDeclaration(node, owner);
549
- return;
550
- }
551
- if (isExportAssignment(node) && !node.isExportEquals) {
552
- declare(node, owner, "export-alias", undefined, {
553
- component: { text: "default", computed: false },
554
- localName: undefined,
555
- });
556
111
  }
557
112
  }
558
- function walkExportDeclaration(node, owner) {
559
- const clause = node.exportClause;
560
- // A bare star re-export declares nothing: the names it carries are the named module's.
561
- if (clause === undefined) {
562
- return;
563
- }
564
- if (isNamespaceExport(clause)) {
565
- const component = componentOf(clause.name);
566
- if (component !== undefined) {
567
- declare(clause, owner, "export-alias", clause.name, { component, localName: undefined });
568
- }
569
- return;
570
- }
571
- for (const element of clause.elements ?? []) {
572
- const name = nameNodeOf(element);
573
- const component = componentOf(name);
574
- if (component !== undefined) {
575
- declare(element, owner, "export-alias", name, { component, localName: undefined });
576
- }
577
- }
113
+ /** A namespace whose export table says which of its declarations it exports. */
114
+ exportScope(owner, nameNode) {
115
+ this.#exportScopes.push({ owner, nameNode });
578
116
  }
579
- // One batch for every module and every container the walk found, because a
580
- // checker accessor with an array overload costs one round trip for the batch and
581
- // one per node without it.
582
- const batched = [
583
- ...exportScopes.map((scope) => scope.nameNode),
584
- ...containers.map((container) => container.nameNode).filter((node) => node !== undefined),
585
- ];
586
- const handles = batched.map((node) => project.handle(node));
587
- const resolved = project.symbolsAt(handles);
588
- const symbolOf = new Map();
589
- // A scope or a container whose symbol or table went unanswered keeps what its syntax
590
- // declares, and everything under it is recorded unanswered.
591
- const unansweredOwners = new Set();
592
- batched.forEach((node, index) => {
593
- const symbol = resolved[index];
594
- if (typeof symbol === "object") {
595
- symbolOf.set(node, symbol);
596
- }
597
- });
598
- resolved.slice(0, exportScopes.length).forEach((symbol, index) => {
599
- const scope = exportScopes[index];
600
- if (symbol === UNANSWERED && scope !== undefined) {
601
- unansweredOwners.add(scope.owner);
602
- }
603
- });
604
- containers
605
- .filter((container) => container.nameNode !== undefined)
606
- .forEach((container, index) => {
607
- if (resolved[exportScopes.length + index] === UNANSWERED) {
608
- unansweredOwners.add(container.owner);
609
- }
610
- });
611
- let exportTables = 0;
612
- for (const scope of exportScopes) {
613
- const symbol = symbolOf.get(scope.nameNode);
614
- if (symbol === undefined) {
615
- continue;
616
- }
617
- exportTables += 1;
618
- const table = project.queries.exportsOf(symbol);
619
- if (!isAnswered(table)) {
620
- unansweredOwners.add(scope.owner);
621
- }
622
- for (const [, exported] of isAnswered(table) ? table : []) {
623
- for (const declaration of exported.declarations) {
624
- const held = project.declarationAt(declaration);
625
- if (held === undefined) {
626
- continue;
627
- }
628
- const record = byNode.get(nodeKey(held.node.getSourceFile(), held.node));
629
- if (record === undefined) {
630
- continue;
631
- }
632
- record.exported = true;
633
- }
634
- }
117
+ /** A `declare module` declaration named by a string literal. */
118
+ module(record, name) {
119
+ this.#modules.push([record, name]);
635
120
  }
636
- let memberTables = 0;
637
- for (const container of containers) {
638
- const symbol = container.nameNode === undefined ? undefined : symbolOf.get(container.nameNode);
639
- const seen = new Map();
640
- if (symbol !== undefined) {
641
- if (!container.membersAreExports) {
642
- memberTables += 1;
643
- const table = project.queries.membersOf(symbol);
644
- if (isAnswered(table)) {
645
- readTable(container, table, seen, false);
646
- }
647
- else {
648
- unansweredOwners.add(container.owner);
649
- }
650
- }
651
- if (container.membersAreExports || container.isClass) {
652
- memberTables += 1;
653
- const table = project.queries.exportsOf(symbol);
654
- if (isAnswered(table)) {
655
- readTable(container, table, seen, container.isClass);
656
- }
657
- else {
658
- unansweredOwners.add(container.owner);
659
- }
660
- }
661
- }
662
- completeFromTree(container, seen);
121
+ /** The declaration enumerated at one node, where one is. */
122
+ recordAt(node) {
123
+ return this.#byNode.get(nodeKey(node.getSourceFile(), node));
663
124
  }
664
- /**
665
- * One container's members as its symbol table holds them, each positioned at the
666
- * declaration the table names. A member with no declaration is the language's own
667
- * (a class's `prototype`), and a member declared outside the target's own files
668
- * belongs to another program; neither is a declaration of the target.
669
- */
670
- function readTable(container, table, seen, areStatic) {
671
- for (const [, member] of table) {
672
- const declarations = member.declarations
673
- .map((handle) => project.declarationAt(handle))
674
- .filter((held) => held !== undefined);
675
- if (declarations.length === 0) {
676
- continue;
677
- }
678
- const own = declarations.filter((held) => ownFiles.has(held.node.getSourceFile().fileName));
679
- if (own.length === 0) {
680
- continue;
681
- }
682
- // A merged symbol's table holds the members every one of its declarations writes,
683
- // and each member is kept once, by the declaration that writes it.
684
- for (const held of own.filter((one) => writtenInside(container.declaration, one.node))) {
685
- keepMember(container, held.node, seen, areStatic);
686
- }
687
- }
125
+ /** Records that a table of `owner` is unknown, which leaves everything under it unknown. */
126
+ unanswered(owner) {
127
+ this.#unansweredOwners.add(owner);
128
+ }
129
+ /** Records that one file writes its exports in a form its table does not model. */
130
+ openTable(file) {
131
+ this.#openTables.add(file);
688
132
  }
689
133
  /**
690
- * One container's members as its own declaration writes them, for the members its
691
- * symbol table does not hold: a member whose key is computed is bound to the
692
- * container's type later than the table is built.
134
+ * One member of a container. A getter and a setter of one name are one symbol and one
135
+ * reference, so the second declaration widens the first record rather than making a
136
+ * second, and both nodes name that record.
693
137
  */
694
- function completeFromTree(container, seen) {
695
- for (const member of container.members) {
696
- keepMember(container, member, seen, (modifiersOf(member) & ModifierFlags.Static) !== 0);
697
- }
698
- }
699
- function keepMember(container, node, seen, areStatic) {
138
+ member(container, node, seen, areStatic) {
700
139
  const kind = memberKindOf(container, node);
701
140
  if (kind === undefined) {
702
141
  return;
@@ -709,61 +148,234 @@ export function inventory(project, host, targetRoot) {
709
148
  const file = node.getSourceFile();
710
149
  const key = memberKey(component, areStatic);
711
150
  const held = seen.get(key);
712
- const endLine = renderPosition(file, targetRoot, Math.max(node.end - 1, 0)).line;
151
+ const endLine = this.#endOf(file, node);
713
152
  if (held !== undefined) {
714
- // A getter and a setter of one name are one symbol and one reference, so the
715
- // second declaration widens the first record rather than making a second. Both
716
- // nodes name that record, so a reading that starts from either one finds it.
717
153
  held.endLine = Math.max(held.endLine, endLine);
718
- byNode.set(nodeKey(file, node), held);
154
+ this.#byNode.set(nodeKey(file, node), held);
155
+ placeAt(held, node);
719
156
  return;
720
157
  }
721
- const at = name ?? node;
722
- const record = keep({
723
- file,
724
- node,
158
+ const record = this.#keep(file, node, (name ?? node).getStart(), {
725
159
  module: container.owner.module,
726
- position: renderPosition(file, targetRoot, at.getStart()),
727
- endLine,
728
160
  kind,
729
161
  parentChain: chainOf(container.owner),
730
162
  component,
731
- localName: undefined,
732
163
  parent: container.owner,
733
164
  visibility: visibilityOf(node, name),
734
165
  static: areStatic,
735
- exported: false,
736
- typeParameter: undefined,
166
+ holder: isParameterProperty(node) ? container.owner : undefined,
737
167
  });
738
168
  seen.set(key, record);
739
- declareTypeParameters(node, record);
740
- }
741
- function memberKindOf(container, node) {
742
- if (container.isClass) {
743
- if (isPropertyDeclaration(node) ||
744
- isMethodDeclaration(node) ||
745
- isGetAccessorDeclaration(node) ||
746
- isSetAccessorDeclaration(node) ||
747
- isParameterProperty(node)) {
748
- return classMemberKind(node);
169
+ this.#declareTypeParameters(node, record);
170
+ }
171
+ /** The inventory of everything collected. */
172
+ build(cost) {
173
+ const byId = new Map(this.#records.map((record) => [positionKey(record.position), record]));
174
+ const symbols = this.#records.map(render).sort((a, b) => byPosition(a.position, b.position));
175
+ return {
176
+ symbols,
177
+ declarations: new Map([...this.#byNode].map(([key, record]) => [key, positionKey(record.position)])),
178
+ cost,
179
+ unanswered: symbols
180
+ .filter((symbol) => underUnanswered(byId.get(symbol.id), this.#unansweredOwners))
181
+ .map((symbol) => symbol.id),
182
+ byName: namesOf(this.#records),
183
+ modules: new Map(this.#modules.map(([record, name]) => [positionKey(record.position), name])),
184
+ ambient: new Set(this.#records
185
+ .filter((record) => isAmbient(record.file, record.node))
186
+ .map((record) => positionKey(record.position))),
187
+ dependents: dependentsOf(this.#containers, (node) => this.recordAt(node)),
188
+ placement: placementOf(this.#records),
189
+ openTables: new Set([...this.#openTables].map((file) => positionKey(file.position))),
190
+ };
191
+ }
192
+ #keep(file, node, at, fields) {
193
+ const kept = {
194
+ file,
195
+ node,
196
+ position: renderPosition(file, this.#targetRoot, at),
197
+ endLine: this.#endOf(file, node),
198
+ localName: undefined,
199
+ visibility: "public",
200
+ static: false,
201
+ exported: false,
202
+ typeParameter: undefined,
203
+ holder: undefined,
204
+ ...fields,
205
+ startLines: new Set(),
206
+ partLines: new Set(),
207
+ };
208
+ this.#records.push(kept);
209
+ this.#byNode.set(nodeKey(kept.file, kept.node), kept);
210
+ if (kept.kind !== "file") {
211
+ placeAt(kept, kept.node);
212
+ }
213
+ return kept;
214
+ }
215
+ #declareTypeParameters(node, owner) {
216
+ for (const parameter of typeParametersOf(node)) {
217
+ const name = nameNodeOf(parameter);
218
+ if (name === undefined) {
219
+ continue;
749
220
  }
750
- return undefined;
751
- }
752
- if (container.memberKind === "enum-member") {
753
- return isEnumMember(node) ? "enum-member" : undefined;
221
+ this.#keep(owner.file, parameter, name.getStart(), {
222
+ module: owner.module,
223
+ kind: "type-parameter",
224
+ parentChain: owner.parentChain,
225
+ component: owner.component,
226
+ parent: owner,
227
+ static: owner.static,
228
+ typeParameter: name.getText(),
229
+ });
754
230
  }
755
- if (isPropertySignatureDeclaration(node) || isMethodSignatureDeclaration(node)) {
756
- return typeMemberKind(node, container.memberKind === "interface-method");
231
+ }
232
+ #endOf(file, node) {
233
+ return renderPosition(file, this.#targetRoot, Math.max(node.end - 1, 0)).line;
234
+ }
235
+ }
236
+ /** The lines one declaring node binds its declaration on. */
237
+ function placeAt(record, node) {
238
+ const file = record.file;
239
+ record.startLines.add(startLine(file, node.pos));
240
+ for (const parameter of signatureOf(node)?.parameters ?? []) {
241
+ record.startLines.add(startLine(file, parameter.pos));
242
+ }
243
+ const list = node.parent;
244
+ if (node.kind === SyntaxKind.VariableDeclaration &&
245
+ list?.kind === SyntaxKind.VariableDeclarationList &&
246
+ list.parent.kind === SyntaxKind.VariableStatement) {
247
+ record.startLines.add(startLine(file, list.parent.pos));
248
+ }
249
+ }
250
+ /** The modifier flags one node carries, and zero for a node that carries none. */
251
+ export function modifiersOf(node) {
252
+ return node.modifierFlags ?? 0;
253
+ }
254
+ /** The name node of one declaration, for the kinds that carry one. */
255
+ export function nameNodeOf(node) {
256
+ return node.name;
257
+ }
258
+ /**
259
+ * The reference component one declaration name node spells, and undefined for a name the
260
+ * grammar does not represent: a binding pattern, and a computed key whose source text
261
+ * carries a closing bracket.
262
+ */
263
+ export function componentOf(name) {
264
+ if (name === undefined) {
265
+ return undefined;
266
+ }
267
+ if (isComputedPropertyName(name)) {
268
+ const text = name.expression.getText();
269
+ return text.includes("]") ? undefined : { text, computed: true };
270
+ }
271
+ if (isIdentifier(name) || isPrivateIdentifier(name)) {
272
+ return { text: name.getText(), computed: false };
273
+ }
274
+ const text = name.getText();
275
+ if (text.startsWith('"') || text.startsWith("'") || text.startsWith("`")) {
276
+ // A string key's own text carries its quotes; the reference carries the value.
277
+ return { text: text.slice(1, -1), computed: false };
278
+ }
279
+ return /^[0-9]/u.test(text) ? { text, computed: false } : undefined;
280
+ }
281
+ /**
282
+ * The component one declaration's reference carries, and its declared name where the two
283
+ * differ. A declaration its module exports as the default is named `default`, its export
284
+ * name, which a module has at most one of and an anonymous declaration has too.
285
+ */
286
+ export function exportedAs(node, name) {
287
+ const declared = componentOf(name);
288
+ if ((modifiersOf(node) & ModifierFlags.Default) === 0) {
289
+ return { component: declared, localName: undefined };
290
+ }
291
+ return { component: { text: "default", computed: false }, localName: declared?.text };
292
+ }
293
+ /** One member's identity inside its container: its component, and its side of a class. */
294
+ export function memberKey(component, isStatic) {
295
+ return `${component.computed ? "[" : ""}${component.text}${isStatic ? ":static" : ""}`;
296
+ }
297
+ /** The visibility one member declaration's modifiers and name give it. */
298
+ function visibilityOf(node, name) {
299
+ if (name !== undefined && isPrivateIdentifier(name)) {
300
+ return "private-name";
301
+ }
302
+ const flags = modifiersOf(node);
303
+ if ((flags & ModifierFlags.Private) !== 0) {
304
+ return "private";
305
+ }
306
+ if ((flags & ModifierFlags.Protected) !== 0) {
307
+ return "protected";
308
+ }
309
+ return "public";
310
+ }
311
+ /** Whether a declaration is ambient: in a declaration file, or under a `declare` modifier. */
312
+ export function isAmbient(file, node) {
313
+ if (file.isDeclarationFile) {
314
+ return true;
315
+ }
316
+ for (let at = node; at !== undefined; at = at.parent) {
317
+ if ((modifiersOf(at) & ModifierFlags.Ambient) !== 0) {
318
+ return true;
757
319
  }
758
- if (isGetAccessorDeclaration(node) || isSetAccessorDeclaration(node)) {
759
- return "type-member";
320
+ }
321
+ return false;
322
+ }
323
+ /** The type parameters one node declares, and none for a node that declares none. */
324
+ function typeParametersOf(node) {
325
+ if (isFunctionDeclaration(node) ||
326
+ isMethodDeclaration(node) ||
327
+ isMethodSignatureDeclaration(node) ||
328
+ isClassDeclaration(node) ||
329
+ isInterfaceDeclaration(node) ||
330
+ isTypeAliasDeclaration(node)) {
331
+ return node.typeParameters ?? [];
332
+ }
333
+ return [];
334
+ }
335
+ /** `export default`, up to the keyword that stands where an unnamed default export's name would. */
336
+ const DEFAULT_EXPORT = /^export\s+(?=default\b)/u;
337
+ /**
338
+ * Where an unnamed declaration is placed: at `default` when it is the default export, so it
339
+ * never shares the file's own position, else at its first token.
340
+ */
341
+ function unnamedStart(node) {
342
+ const start = node.getStart();
343
+ const prefix = DEFAULT_EXPORT.exec(node.getText());
344
+ return prefix === null ? start : start + prefix[0].length;
345
+ }
346
+ /** The kind one member of a container takes, and undefined for a node that is no member. */
347
+ function memberKindOf(container, node) {
348
+ if (container.memberKind === "class-member") {
349
+ if (isPropertyDeclaration(node) ||
350
+ isGetAccessorDeclaration(node) ||
351
+ isSetAccessorDeclaration(node) ||
352
+ isParameterProperty(node)) {
353
+ return "class-member";
760
354
  }
761
- return undefined;
355
+ return isMethodDeclaration(node) ? "method" : undefined;
356
+ }
357
+ if (container.memberKind === "enum-member") {
358
+ return isEnumMember(node) ? "enum-member" : undefined;
762
359
  }
360
+ if (isMethodSignatureDeclaration(node)) {
361
+ return container.memberKind === "interface-method" ? "interface-method" : "type-member";
362
+ }
363
+ if (isPropertySignatureDeclaration(node) ||
364
+ isGetAccessorDeclaration(node) ||
365
+ isSetAccessorDeclaration(node)) {
366
+ return "type-member";
367
+ }
368
+ return undefined;
369
+ }
370
+ /**
371
+ * Each enum member's dependents: the later members of its declaration with no initializer,
372
+ * up to the first one with an initializer.
373
+ */
374
+ function dependentsOf(containers, recordAt) {
763
375
  const dependents = new Map();
764
376
  for (const container of containers.filter((one) => one.memberKind === "enum-member")) {
765
377
  const ids = container.members.map((member) => {
766
- const record = byNode.get(nodeKey(member.getSourceFile(), member));
378
+ const record = recordAt(member);
767
379
  return record === undefined ? undefined : positionKey(record.position);
768
380
  });
769
381
  container.members.forEach((_member, index) => {
@@ -784,22 +396,21 @@ export function inventory(project, host, targetRoot) {
784
396
  }
785
397
  });
786
398
  }
787
- const byId = new Map(building.map((record) => [positionKey(record.position), record]));
788
- const symbols = building.map(render).sort((a, b) => byPosition(a.position, b.position));
789
- return {
790
- symbols,
791
- declarations: new Map([...byNode].map(([key, record]) => [key, positionKey(record.position)])),
792
- cost: { batches: 1, exportTables, memberTables },
793
- unanswered: symbols
794
- .filter((symbol) => underUnanswered(byId.get(symbol.id), unansweredOwners))
795
- .map((symbol) => symbol.id),
796
- byName: namesOf(building),
797
- modules: new Map(modules.map(([record, name]) => [positionKey(record.position), name])),
798
- ambient: new Set(building
799
- .filter((record) => isAmbient(record.file, record.node))
800
- .map((record) => positionKey(record.position))),
801
- dependents,
802
- };
399
+ return dependents;
400
+ }
401
+ /** Each declaration but a file to where a directive binds it. */
402
+ function placementOf(records) {
403
+ const ascending = (lines) => [...lines].sort((a, b) => a - b);
404
+ return new Map(records
405
+ .filter((record) => record.kind !== "file")
406
+ .map((record) => [
407
+ positionKey(record.position),
408
+ {
409
+ startLines: ascending(record.startLines),
410
+ holder: positionKey((record.holder ?? record).position),
411
+ partLines: ascending(record.partLines),
412
+ },
413
+ ]));
803
414
  }
804
415
  /** Whether one declaration is, or is declared under, a scope or container left unanswered. */
805
416
  function underUnanswered(record, owners) {
@@ -811,9 +422,9 @@ function underUnanswered(record, owners) {
811
422
  return false;
812
423
  }
813
424
  /** Every declaration but a file, by each name a use may spell it with. */
814
- function namesOf(building) {
425
+ function namesOf(records) {
815
426
  const byName = new Map();
816
- for (const record of building) {
427
+ for (const record of records) {
817
428
  if (record.kind === "file") {
818
429
  continue;
819
430
  }
@@ -842,21 +453,17 @@ function chainOf(record) {
842
453
  }
843
454
  /**
844
455
  * One declaration as the inventory reports it. The display name is the chain in the
845
- * spelling a reference gives it, except where the declaration carries a name of its
846
- * own the reference does not: a file, whose reference names its module, and a default
847
- * export, whose reference carries its export name.
456
+ * spelling a reference gives it, except where the declaration carries a name of its own
457
+ * the reference does not: a file, whose reference names its module, and a default export.
848
458
  */
849
459
  function render(record) {
850
460
  const chain = chainOf(record);
851
- const spelled = chain
852
- .map((component) => component.computed ? computedComponent(component.text) : nameComponent(component.text))
853
- .join(".");
854
- const name = record.localName ??
855
- (record.typeParameter === undefined ? spelled : `${spelled}<${record.typeParameter}>`);
461
+ const spelled = chain.map(spell).join(".");
856
462
  return {
857
463
  id: positionKey(record.position),
858
464
  ref: refOf(record, chain),
859
- name,
465
+ name: record.localName ??
466
+ (record.typeParameter === undefined ? spelled : `${spelled}<${record.typeParameter}>`),
860
467
  kind: record.kind,
861
468
  position: record.position,
862
469
  endLine: record.endLine,
@@ -885,11 +492,3 @@ function refOf(record, chain) {
885
492
  ...(record.typeParameter === undefined ? {} : { typeParameter: record.typeParameter }),
886
493
  });
887
494
  }
888
- /**
889
- * Every declaration of an inventory other than a file, by each name a use may spell it
890
- * with. It is how a reference the checker could not resolve is still counted, as a
891
- * reference to every declaration that bears the name it spells.
892
- */
893
- export function declarationsByName(held) {
894
- return held.byName;
895
- }